diff --git a/crates/cairo-lang-semantic/src/diagnostic_test_data/neg_impl b/crates/cairo-lang-semantic/src/diagnostic_test_data/neg_impl index e58ab79405d..e5a27596119 100644 --- a/crates/cairo-lang-semantic/src/diagnostic_test_data/neg_impl +++ b/crates/cairo-lang-semantic/src/diagnostic_test_data/neg_impl @@ -71,6 +71,6 @@ impl BadImpl<-NegImpl> of NegImpl { //! > expected_diagnostics error: Inference cycle detected - --> lib.cairo:8:16 -fn test_func() { { - ^**^ + --> lib.cairo:10:14 + NegImpl::bar() + ^*^ diff --git a/crates/cairo-lang-semantic/src/expr/compute.rs b/crates/cairo-lang-semantic/src/expr/compute.rs index 20ac55ad92f..b4861f8c110 100644 --- a/crates/cairo-lang-semantic/src/expr/compute.rs +++ b/crates/cairo-lang-semantic/src/expr/compute.rs @@ -1795,6 +1795,11 @@ fn compute_expr_indexed_semantic( ) -> Maybe { let syntax_db = ctx.db.upcast(); let expr = compute_expr_semantic(ctx, &syntax.expr(syntax_db)); + let index_expr_syntax = &syntax.index_expr(syntax_db); + let index_expr = compute_expr_semantic(ctx, index_expr_syntax); + // Make sure the maximal amount of types is known when trying to access. Ignoring the returned + // value, as any errors will be reported later. + ctx.resolver.inference().solve().ok(); let candidate_traits: Vec<_> = ["Index", "IndexView"] .iter() .map(|trait_name| get_core_trait(ctx.db, CoreTraitContext::Ops, (*trait_name).into())) @@ -1810,8 +1815,6 @@ fn compute_expr_indexed_semantic( |ty, _, _| Some(MultipleImplementationOfIndexOperator(ty)), )?; - let index_expr_syntax = &syntax.index_expr(syntax_db); - let index_expr = compute_expr_semantic(ctx, index_expr_syntax); expr_function_call( ctx, function_id, diff --git a/crates/cairo-lang-semantic/src/expr/inference.rs b/crates/cairo-lang-semantic/src/expr/inference.rs index 80d237baaec..50a75f26725 100644 --- a/crates/cairo-lang-semantic/src/expr/inference.rs +++ b/crates/cairo-lang-semantic/src/expr/inference.rs @@ -602,11 +602,18 @@ impl<'db> Inference<'db> { /// Returns whether the inference was successful. If not, the error may be found by /// `.error_state()`. pub fn solve(&mut self) -> InferenceResult<()> { + self.solve_ex().map_err(|(err_set, _)| err_set) + } + + /// Same as `solve`, but returns the error stable pointer if an error occurred. + fn solve_ex(&mut self) -> Result<(), (ErrorSet, Option)> { let mut ambiguous = std::mem::take(&mut self.ambiguous); self.pending.extend(ambiguous.drain(..).map(|(var, _)| var)); while let Some(var) = self.pending.pop_front() { // First inference error stops inference. - self.solve_single_pending(var)?; + self.solve_single_pending(var).map_err(|err_set| { + (err_set, self.stable_ptrs.get(&InferenceVar::Impl(var)).copied()) + })?; } Ok(()) } @@ -668,7 +675,7 @@ impl<'db> Inference<'db> { // Conform all uninferred numeric literals to felt252. loop { let mut changed = false; - self.solve().map_err(|err_set| (err_set, None))?; + self.solve_ex()?; for (var, _) in self.ambiguous.clone() { let impl_var = self.impl_var(var).clone(); if impl_var.concrete_trait_id.trait_id(self.db) != numeric_trait_id { diff --git a/crates/cairo-lang-semantic/src/expr/test_data/closure b/crates/cairo-lang-semantic/src/expr/test_data/closure index 3ad1312e8c6..d12707cee1a 100644 --- a/crates/cairo-lang-semantic/src/expr/test_data/closure +++ b/crates/cairo-lang-semantic/src/expr/test_data/closure @@ -236,9 +236,9 @@ fn bar>(c: T) -> core::ops::FnOnce:: //! > expected_diagnostics error: Type mismatch: `core::integer::u32` and `core::integer::u64`. - --> lib.cairo:4:10 -fn foo() { - ^ + --> lib.cairo:10:23 + let _k: felt252 = bar(c); + ^*^ //! > ========================================================================== @@ -267,9 +267,9 @@ fn bar>(c: T) -> core::ops::FnOnce:: //! > expected_diagnostics error: Type mismatch: `core::felt252` and `core::integer::u128`. - --> lib.cairo:4:10 -fn foo() { - ^ + --> lib.cairo:10:23 + let _k: felt252 = bar(c); + ^*^ //! > ========================================================================== @@ -410,9 +410,9 @@ fn bar(a: felt252) -> u32 { //! > expected_diagnostics error: Type mismatch: `(?6,)` and `(?0, ?1, ?2)`. - --> lib.cairo:4:10 -fn foo() { - ^ + --> lib.cairo:8:19 + let _f: u32 = bar(2); + ^****^ //! > ========================================================================== diff --git a/crates/cairo-lang-semantic/src/expr/test_data/inference b/crates/cairo-lang-semantic/src/expr/test_data/inference index 85365a9e8ea..b7a7fe27bc6 100644 --- a/crates/cairo-lang-semantic/src/expr/test_data/inference +++ b/crates/cairo-lang-semantic/src/expr/test_data/inference @@ -64,9 +64,9 @@ impl MyImpl<+MyTrait> of MyTrait { //! > expected_diagnostics error: Inference cycle detected - --> lib.cairo:8:10 -fn foo() { - ^ + --> lib.cairo:9:14 + MyTrait::foo(); + ^*^ //! > ========================================================================== diff --git a/crates/cairo-lang-semantic/src/expr/test_data/operators b/crates/cairo-lang-semantic/src/expr/test_data/operators index 8922fe75118..c96dab46b3f 100644 --- a/crates/cairo-lang-semantic/src/expr/test_data/operators +++ b/crates/cairo-lang-semantic/src/expr/test_data/operators @@ -123,8 +123,8 @@ impl Struct2Index of Index { //! > expected_diagnostics error: Type `test::Struct1` could not be indexed. -Candidate `Index::index` inference failed with: Trait has no implementation in context: core::ops::index::Index::. -Candidate `IndexView::index` inference failed with: Trait has no implementation in context: core::ops::index::IndexView::. +Candidate `Index::index` inference failed with: Trait has no implementation in context: core::ops::index::Index::. +Candidate `IndexView::index` inference failed with: Trait has no implementation in context: core::ops::index::IndexView::. --> lib.cairo:21:15 let _y1 = x1[0]; ^***^ diff --git a/crates/cairo-lang-semantic/src/items/constant.rs b/crates/cairo-lang-semantic/src/items/constant.rs index 1596c72122c..82d581424a4 100644 --- a/crates/cairo-lang-semantic/src/items/constant.rs +++ b/crates/cairo-lang-semantic/src/items/constant.rs @@ -454,11 +454,29 @@ pub fn evaluate_constant_expr( .collect(), expr.ty, ), - Expr::StructCtor(ExprStructCtor { members, base_struct: None, ty, .. }) => { + Expr::StructCtor(ExprStructCtor { + members, + base_struct: None, + ty, + concrete_struct_id, + .. + }) => { + let member_order = match db.concrete_struct_members(*concrete_struct_id) { + Ok(member_order) => member_order, + Err(diag_add) => return ConstValue::Missing(diag_add), + }; ConstValue::Struct( - members - .iter() - .map(|(_, expr_id)| evaluate_constant_expr(db, exprs, *expr_id, diagnostics)) + member_order + .values() + .map(|m| { + members + .iter() + .find(|(member_id, _)| m.id == *member_id) + .map(|(_, expr_id)| { + evaluate_constant_expr(db, exprs, *expr_id, diagnostics) + }) + .unwrap_or_else(|| ConstValue::Missing(skip_diagnostic())) + }) .collect(), *ty, ) diff --git a/crates/cairo-lang-semantic/src/items/tests/early_conform b/crates/cairo-lang-semantic/src/items/tests/early_conform index 61249bb1f1b..047a5aba8c8 100644 --- a/crates/cairo-lang-semantic/src/items/tests/early_conform +++ b/crates/cairo-lang-semantic/src/items/tests/early_conform @@ -981,13 +981,13 @@ impl MyIndexView of IndexView { //! > expected_diagnostics error[E0002]: Method `my_into` could not be called on type `core::integer::u16`. -Candidate `MyInto::my_into` inference failed with: Trait has no implementation in context: test::MyInto::. +Candidate `MyInto::my_into` inference failed with: Trait has no implementation in context: test::MyInto::. --> lib.cairo:15:13 x[3_u16.my_into()]; ^*****^ error[E0002]: Method `my_into` could not be called on type `core::integer::u16`. -Candidate `MyInto::my_into` inference failed with: Trait has no implementation in context: test::MyInto::. +Candidate `MyInto::my_into` inference failed with: Trait has no implementation in context: test::MyInto::. --> lib.cairo:16:17 3_u64[3_u16.my_into()]; ^*****^ diff --git a/crates/cairo-lang-semantic/src/items/tests/trait_type b/crates/cairo-lang-semantic/src/items/tests/trait_type index a3dc008f7f6..4ac1945f690 100644 --- a/crates/cairo-lang-semantic/src/items/tests/trait_type +++ b/crates/cairo-lang-semantic/src/items/tests/trait_type @@ -904,8 +904,8 @@ impl MyImpl of MyTrait { //! > expected_diagnostics error: Type `core::integer::u32` could not be indexed. -Candidate `Index::index` inference failed with: Trait has no implementation in context: core::ops::index::Index::. -Candidate `IndexView::index` inference failed with: Trait has no implementation in context: core::ops::index::IndexView::. +Candidate `Index::index` inference failed with: Trait has no implementation in context: core::ops::index::Index::. +Candidate `IndexView::index` inference failed with: Trait has no implementation in context: core::ops::index::IndexView::. --> lib.cairo:8:9 x[0]; ^**^ @@ -1150,9 +1150,9 @@ error: Unexpected argument type. Expected: "core::integer::u32", found: "core::i ^ error: Type mismatch: `core::integer::u32` and `core::integer::u16`. - --> lib.cairo:25:11 -fn bar3() { - ^ + --> lib.cairo:26:21 + let _: MyTrait::MyType = 3_u32; + ^****^ //! > ========================================================================== @@ -1525,9 +1525,9 @@ fn ret_expr(x: MyTrait::MyType1) -> MyTrait::MyType2 { ^ error: Type mismatch: `core::integer::u32` and `core::integer::u16`. - --> lib.cairo:15:39 -fn let_statement(x: MyTrait::MyType2) { - ^ + --> lib.cairo:16:21 + let _: MyTrait::MyType1 = x; + ^*****^ error: Loop has incompatible return types: "core::integer::u16" and "core::integer::u32" --> lib.cairo:23:19 diff --git a/tests/bug_samples/issue6580.cairo b/tests/bug_samples/issue6580.cairo new file mode 100644 index 00000000000..69aeef5c16d --- /dev/null +++ b/tests/bug_samples/issue6580.cairo @@ -0,0 +1,22 @@ +#[derive(Drop, Debug)] +struct SomeStruct { + num: felt252 +} + +#[test] +fn inner_index_access() { + let arr_of_bytearrays: Array = array!["str1", "str2", "str3"]; + let arr_of_arrays_of_nums: Array> = array![array![9], array![2], array![19, 20, 21]]; + let arr_of_arrays_of_structs: Array> = array![ + array![SomeStruct { num: 8 }], + array![SomeStruct { num: 2 }], + array![SomeStruct { num: 9 }, SomeStruct { num: 10 }, SomeStruct { num: 11 }] + ]; + + let index_1 = 2_usize; + let index_2 = 2_usize; + + let _nested_item = arr_of_arrays_of_nums[index_1][index_2]; + let _char = arr_of_bytearrays[index_1][index_2]; + let _some_struct = arr_of_arrays_of_structs[index_1][index_2]; +} diff --git a/tests/bug_samples/issue6623.cairo b/tests/bug_samples/issue6623.cairo new file mode 100644 index 00000000000..270cd9860ee --- /dev/null +++ b/tests/bug_samples/issue6623.cairo @@ -0,0 +1,12 @@ +struct S { + a: u64, + b: u64, +} + +const X: S = S { b: 31, a: 252 }; + +#[test] +fn test_const() { + assert_eq!(X.a, 252); + assert_eq!(X.b, 31); +} diff --git a/tests/bug_samples/lib.cairo b/tests/bug_samples/lib.cairo index 27cf287bf10..8de18c08bb7 100644 --- a/tests/bug_samples/lib.cairo +++ b/tests/bug_samples/lib.cairo @@ -48,6 +48,8 @@ mod issue5629; mod issue5680; mod issue5764; mod issue5967; +mod issue6580; +mod issue6623; mod loop_break_in_match; mod loop_only_change; mod partial_param_local;