@@ -24,8 +24,10 @@ namespace executorch {
2424namespace extension {
2525namespace pytree {
2626
27- inline void pytree_assert (bool must_be_true) {
28- assert (must_be_true);
27+ inline void pytree_check (bool must_be_true) {
28+ if (!must_be_true) {
29+ throw std::runtime_error (" pytree assertion failed" );
30+ }
2931}
3032
3133#ifdef _MSC_VER
@@ -36,18 +38,6 @@ inline void pytree_assert(bool must_be_true) {
3638#define EXECUTORCH_ALWAYS_INLINE inline
3739#endif
3840
39- [[noreturn]] EXECUTORCH_ALWAYS_INLINE void pytree_unreachable () {
40- assert (false );
41- #if defined(__GNUC__)
42- __builtin_unreachable ();
43- #elif defined(_MSC_VER)
44- __assume (0 );
45- #else
46- while (!0 )
47- ;
48- #endif
49- }
50-
5141enum class Kind : uint8_t { List, Tuple, NamedTuple, Dict, Leaf, Custom, None };
5242
5343using KeyStr = std::string;
@@ -143,45 +133,45 @@ struct ContainerHandle {
143133 : handle(std::move(c)) {}
144134
145135 void set_leaf (leaf_type* leaf) {
146- pytree_assert (handle->kind == Kind::Leaf);
136+ pytree_check (handle->kind == Kind::Leaf);
147137 handle->leaf = leaf;
148138 }
149139
150140 operator leaf_type () const {
151- pytree_assert (handle->kind == Kind::Leaf);
141+ pytree_check (handle->kind == Kind::Leaf);
152142 return *handle->leaf ;
153143 }
154144
155145 const leaf_type& leaf () const {
156- pytree_assert (handle->kind == Kind::Leaf);
146+ pytree_check (handle->kind == Kind::Leaf);
157147 return *handle->leaf ;
158148 }
159149 leaf_type& leaf () {
160- pytree_assert (handle->kind == Kind::Leaf);
150+ pytree_check (handle->kind == Kind::Leaf);
161151 return *handle->leaf ;
162152 }
163153
164154 const leaf_type* leaf_ptr () const {
165- pytree_assert (handle->kind == Kind::Leaf);
155+ pytree_check (handle->kind == Kind::Leaf);
166156 return handle->leaf ;
167157 }
168158 leaf_type* leaf_ptr () {
169- pytree_assert (handle->kind == Kind::Leaf);
159+ pytree_check (handle->kind == Kind::Leaf);
170160 return handle->leaf ;
171161 }
172162
173163 const ContainerHandle& operator [](size_t idx) const {
174- pytree_assert (idx < handle->size );
164+ pytree_check (idx < handle->size );
175165 return handle->items [idx];
176166 }
177167
178168 ContainerHandle& operator [](size_t idx) {
179- pytree_assert (idx < handle->size );
169+ pytree_check (idx < handle->size );
180170 return handle->items [idx];
181171 }
182172
183173 bool contains (const KeyStr& lookup_key) const {
184- pytree_assert (isDict ());
174+ pytree_check (isDict ());
185175 for (size_t i = 0 ; i < handle->size ; ++i) {
186176 if (handle->keys [i] == lookup_key) {
187177 return true ;
@@ -191,13 +181,13 @@ struct ContainerHandle {
191181 }
192182
193183 const ContainerHandle& at (const Key& lookup_key) const {
194- pytree_assert (isDict ());
184+ pytree_check (isDict ());
195185 for (size_t i = 0 ; i < handle->size ; ++i) {
196186 if (handle->keys [i] == lookup_key) {
197187 return handle->items [i];
198188 }
199189 }
200- pytree_unreachable ( );
190+ throw std::runtime_error ( " Dict::at lookup failed " );
201191 }
202192
203193 const ContainerHandle& at (const KeyInt& lookup_key) const {
@@ -209,11 +199,11 @@ struct ContainerHandle {
209199 }
210200
211201 const Key& key (size_t idx) const {
212- pytree_assert (isDict ());
202+ pytree_check (isDict ());
213203 return handle->keys [idx];
214204 }
215205 Key& key (size_t idx) {
216- pytree_assert (isDict ());
206+ pytree_check (isDict ());
217207 return handle->keys [idx];
218208 }
219209
@@ -398,7 +388,8 @@ StrTreeSpec to_str_internal(const TreeSpec<Aux>& spec) {
398388 s.append (key.as_str ());
399389 s.push_back (Config::kDictStrKeyQuote );
400390 } else {
401- pytree_unreachable ();
391+ throw std::runtime_error (
392+ " invalid key in pytree dict; must be int or string" );
402393 }
403394 s.push_back (Config::kDictKeyValueSep );
404395 s.append (to_str_internal (spec[i]));
@@ -474,6 +465,11 @@ struct arr {
474465
475466inline size_t read_number (const StrTreeSpec& spec, size_t & read_idx) {
476467 size_t num = 0 ;
468+ if (!isdigit (spec.at (read_idx))) {
469+ throw std::runtime_error (
470+ std::string (" expected a digit while decoding pytree, not " ) +
471+ spec[read_idx]);
472+ }
477473 while (isdigit (spec.at (read_idx))) {
478474 num = 10 * num + (spec[read_idx] - ' 0' );
479475 read_idx++;
@@ -582,7 +578,6 @@ TreeSpec<Aux> from_str_internal(
582578 c->keys [child_idx] = spec.substr (read_idx, key_len);
583579 read_idx = key_delim_idx + 2 ;
584580 } else {
585- pytree_assert (isdigit (spec[read_idx]));
586581 size_t key = read_number (spec, read_idx);
587582 c->keys [child_idx] = KeyInt (key);
588583 read_idx += 1 ;
@@ -603,7 +598,6 @@ TreeSpec<Aux> from_str_internal(
603598 case Config::kLeaf :
604599 return new TreeSpecContainer<Aux>(nullptr );
605600 }
606- pytree_unreachable ();
607601 return new TreeSpecContainer<Aux>(Kind::None);
608602}
609603
@@ -615,17 +609,17 @@ struct stack final {
615609 T data[SIZE];
616610
617611 void push (T&& item) {
618- pytree_assert (size_ < SIZE);
612+ pytree_check (size_ < SIZE);
619613 data[size_++] = std::move (item);
620614 }
621615
622616 T pop () {
623- pytree_assert (size_ > 0 );
617+ pytree_check (size_ > 0 );
624618 return data[--size_];
625619 }
626620
627621 T& top () {
628- pytree_assert (size_ > 0 );
622+ pytree_check (size_ > 0 );
629623 return data[size_ - 1 ];
630624 }
631625
0 commit comments