Bug Report
Cairo version: 6a3c423
Current behavior:
Felt252DictDefault<T> (corelib/src/dict.cairo:208) is declared impl Felt252DictDefault<T> of Default<Felt252Dict<T>> with no trait bounds on T, and its body calls the unbounded extern felt252_dict_new<T>(). As a result, a function returning Felt252Dict<NonDictValue> via Default::default() passes the semantic layer even when the value type has no Felt252DictValue impl. The resulting dict is unusable — every other method requires +Felt252DictValue<T> (insert/get at lines 103–148, Destruct at line 224 which also requires +Drop<T>, and Index), so any actual use fires E2311 at the use site, but the construction itself type-checks.
Worse, cairo-compile panics (ICE) at crates/cairo-lang-sierra-generator/src/db.rs:370 when lowering the phantom function:
thread 'main' (837) panicked at crates/cairo-lang-sierra-generator/src/db.rs:370:9:
Got failure while specializing type `Felt252Dict<core::integer::u256>`:
Could not specialize type
This is a bound-asymmetry on the same type (Default = no bounds, insert/get = +Felt252DictValue, Destruct = +Drop +Felt252DictValue, Index = +DictTrait +Copy +Destruct<Entry>) combined with a sierra-gen panic on user-reachable code.
Expected behavior:
Felt252DictDefault<T> should carry the same +Felt252DictValue<T> bound that the rest of the Felt252Dict API enforces, so that Default::default() for Felt252Dict<T> is rejected at the construction site for value types that do not implement Felt252DictValue. The compiler should never ICE at sierra-gen on such code — it should report a normal type error instead of panicking with "Could not specialize type".
Steps to reproduce:
- Place the code below in a file (e.g.
repro.cairo).
- Run
cairo-test on it — it passes green: the phantom functions are dead code, so sierra-gen never lowers them and the semantic layer accepts the unbounded Default::default().
- Run
cairo-compile --single-file repro.cairo /dev/null — it compiles everything in the file, reaches the unspecializable Felt252Dict<u256> type, and panics at db.rs:370.
Related code:
use core::dict::Felt252Dict;
fn make_phantom_dict_u256() -> Felt252Dict<u256> {
Default::default() // OK — Felt252DictDefault has no bounds
}
#[derive(Drop)]
struct NotDictValue { pub x: felt252 }
fn make_phantom_dict_user() -> Felt252Dict<NotDictValue> {
Default::default() // OK — same reason
}
#[test]
fn test_E93fe73() { assert!(1_u32 + 1_u32 == 2_u32); }
Other information:
- Source of the missing bound:
corelib/src/dict.cairo:208 (impl Felt252DictDefault<T> of Default<Felt252Dict<T>>, no bounds on T), whose body calls the unbounded extern felt252_dict_new<T>() at line 68. By contrast, Destruct at corelib/src/dict.cairo:224 is impl Felt252DictDestruct<T, +Drop<T>, +Felt252DictValue<T>>, and insert/get at lines 103–148 require +Felt252DictValue<T>.
- Panic site:
crates/cairo-lang-sierra-generator/src/db.rs:370.
- The Cairo Book (ch03-02, https://www.starknet.io/cairo-book/ch03-02-dictionaries.html) states that
Felt252Dict<T> only accepts the 8 Felt252DictValue types (u8/u16/u32/u64/u128/bool/felt252/Nullable), but does not note that Default::default() imposes no such bound at the construction site — the restriction is enforced only by Destruct and insert/get.
- Suggested fix: add
+Felt252DictValue<T> to Felt252DictDefault<T> so the bound is consistent across the dict API.
Bug Report
Cairo version: 6a3c423
Current behavior:
Felt252DictDefault<T>(corelib/src/dict.cairo:208) is declaredimpl Felt252DictDefault<T> of Default<Felt252Dict<T>>with no trait bounds on T, and its body calls the unbounded externfelt252_dict_new<T>(). As a result, a function returningFelt252Dict<NonDictValue>viaDefault::default()passes the semantic layer even when the value type has noFelt252DictValueimpl. The resulting dict is unusable — every other method requires+Felt252DictValue<T>(insert/get at lines 103–148,Destructat line 224 which also requires+Drop<T>, andIndex), so any actual use fires E2311 at the use site, but the construction itself type-checks.Worse,
cairo-compilepanics (ICE) atcrates/cairo-lang-sierra-generator/src/db.rs:370when lowering the phantom function:This is a bound-asymmetry on the same type (Default = no bounds, insert/get =
+Felt252DictValue, Destruct =+Drop +Felt252DictValue, Index =+DictTrait +Copy +Destruct<Entry>) combined with a sierra-gen panic on user-reachable code.Expected behavior:
Felt252DictDefault<T>should carry the same+Felt252DictValue<T>bound that the rest of theFelt252DictAPI enforces, so thatDefault::default()forFelt252Dict<T>is rejected at the construction site for value types that do not implementFelt252DictValue. The compiler should never ICE at sierra-gen on such code — it should report a normal type error instead of panicking with "Could not specialize type".Steps to reproduce:
repro.cairo).cairo-teston it — it passes green: the phantom functions are dead code, so sierra-gen never lowers them and the semantic layer accepts the unboundedDefault::default().cairo-compile --single-file repro.cairo /dev/null— it compiles everything in the file, reaches the unspecializableFelt252Dict<u256>type, and panics atdb.rs:370.Related code:
Other information:
corelib/src/dict.cairo:208(impl Felt252DictDefault<T> of Default<Felt252Dict<T>>, no bounds onT), whose body calls the unbounded externfelt252_dict_new<T>()at line 68. By contrast,Destructatcorelib/src/dict.cairo:224isimpl Felt252DictDestruct<T, +Drop<T>, +Felt252DictValue<T>>, and insert/get at lines 103–148 require+Felt252DictValue<T>.crates/cairo-lang-sierra-generator/src/db.rs:370.Felt252Dict<T>only accepts the 8Felt252DictValuetypes (u8/u16/u32/u64/u128/bool/felt252/Nullable), but does not note thatDefault::default()imposes no such bound at the construction site — the restriction is enforced only byDestructand insert/get.+Felt252DictValue<T>toFelt252DictDefault<T>so the bound is consistent across the dict API.