Sitelet https://github.com/starkware-libs/cairo/commit/50510419a2ed0333ce3fa49d76d1b270541f7a01
Skip to content

Commit 5051041

Browse files
authored
fix(semantic): validate inferred numeric literal values against their type (#10040)
1 parent 45f931d commit 5051041

9 files changed

Lines changed: 133 additions & 125 deletions

File tree

‎crates/cairo-lang-lowering/src/diagnostic.rs‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use cairo_lang_diagnostics::{
44
};
55
use cairo_lang_filesystem::ids::SpanInFile;
66
use cairo_lang_semantic as semantic;
7-
use cairo_lang_semantic::corelib::LiteralError;
87
use cairo_lang_semantic::expr::inference::InferenceError;
98
use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
109
use salsa::Database;
@@ -43,7 +42,7 @@ pub struct LoweringDiagnostic<'db> {
4342
}
4443

4544
impl<'db> DiagnosticEntry<'db> for LoweringDiagnostic<'db> {
46-
fn format(&self, db: &'db dyn Database) -> String {
45+
fn format(&self, _db: &'db dyn Database) -> String {
4746
match &self.kind {
4847
LoweringDiagnosticKind::Unreachable { .. } => "Unreachable code".into(),
4948
LoweringDiagnosticKind::VariableMoved { .. } => "Variable was previously moved.".into(),
@@ -67,7 +66,6 @@ impl<'db> DiagnosticEntry<'db> for LoweringDiagnostic<'db> {
6766
LoweringDiagnosticKind::NoPanicFunctionCycle => {
6867
"Call cycle of `nopanic` functions is not allowed.".into()
6968
}
70-
LoweringDiagnosticKind::LiteralError(literal_error) => literal_error.format(db),
7169
LoweringDiagnosticKind::RefutablePattern => "Refutable pattern in irrefutable \
7270
binding. Refutable patterns are only \
7371
supported in `match`, `if let`, \
@@ -118,7 +116,6 @@ impl<'db> DiagnosticEntry<'db> for LoweringDiagnostic<'db> {
118116
LoweringDiagnosticKind::MemberPathLoop => error_code!(E3006),
119117
LoweringDiagnosticKind::UnexpectedError => error_code!(E3007),
120118
LoweringDiagnosticKind::NoPanicFunctionCycle => error_code!(E3008),
121-
LoweringDiagnosticKind::LiteralError(_) => error_code!(E3009),
122119
LoweringDiagnosticKind::RefutablePattern => error_code!(E3010),
123120
LoweringDiagnosticKind::Unsupported => error_code!(E3011),
124121
LoweringDiagnosticKind::FixedSizeArrayNonCopyableType => error_code!(E3012),
@@ -217,7 +214,6 @@ pub enum LoweringDiagnosticKind<'db> {
217214
CannotInlineFunctionThatMightCallItself,
218215
MemberPathLoop,
219216
NoPanicFunctionCycle,
220-
LiteralError(LiteralError<'db>),
221217
FixedSizeArrayNonCopyableType,
222218
EmptyRepeatedElementFixedSizeArray,
223219
RefutablePattern,

‎crates/cairo-lang-lowering/src/lower/flow_control/create_graph/patterns.rs‎

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use cairo_lang_debug::DebugWithDb;
22
use cairo_lang_defs::ids::NamedLanguageElementId;
3-
use cairo_lang_diagnostics::{DiagnosticNote, Maybe};
3+
use cairo_lang_diagnostics::DiagnosticNote;
44
use cairo_lang_filesystem::flag::FlagsGroup;
5-
use cairo_lang_semantic::corelib::{CorelibSemantic, validate_literal};
5+
use cairo_lang_semantic::corelib::CorelibSemantic;
66
use cairo_lang_semantic::expr::compute::unwrap_pattern_type;
77
use cairo_lang_semantic::items::enm::SemanticEnumEx;
88
use cairo_lang_semantic::items::structure::StructSemantic;
@@ -647,10 +647,10 @@ fn create_node_for_tuple_inner<'db>(
647647
let current_member = struct_members.map(|members| members[item_idx]);
648648

649649
// Collect the patterns on the current item.
650-
let mut patterns_on_current_item = Vec::<Option<semantic::Pattern<'db>>>::default();
651-
let mut live_filter = FilteredPatterns::default();
652-
for (idx, pattern) in patterns.iter().enumerate() {
653-
let item_pattern = match pattern {
650+
let mut patterns_on_current_item =
651+
Vec::<Option<semantic::Pattern<'db>>>::with_capacity(patterns.len());
652+
for pattern in patterns {
653+
patterns_on_current_item.push(match pattern {
654654
Some(semantic::Pattern::Tuple(PatternTuple { field_patterns, .. }))
655655
if current_member.is_none() =>
656656
{
@@ -671,11 +671,7 @@ fn create_node_for_tuple_inner<'db>(
671671
Some(semantic::Pattern::Literal(pattern_literal))
672672
if pattern_literal.literal.ty == ctx.db.core_info().u256 =>
673673
{
674-
match handle_u256_literal(ctx, graph, pattern_literal, item_idx) {
675-
Ok(inner_pattern) => Some(inner_pattern),
676-
// Out-of-range `u256` literal, drop the arm.
677-
Err(_) => continue,
678-
}
674+
Some(handle_u256_literal(ctx, pattern_literal, item_idx))
679675
}
680676
Some(semantic::Pattern::FixedSizeArray(semantic::PatternFixedSizeArray {
681677
elements_patterns,
@@ -698,9 +694,7 @@ fn create_node_for_tuple_inner<'db>(
698694
LoweringDiagnosticKind::UnexpectedError,
699695
);
700696
}
701-
};
702-
live_filter.add(idx);
703-
patterns_on_current_item.push(item_pattern);
697+
});
704698
}
705699

706700
// Create a node to handle the current item. The callback will handle the rest of the tuple.
@@ -711,9 +705,6 @@ fn create_node_for_tuple_inner<'db>(
711705
graph,
712706
patterns: &patterns_ref,
713707
build_node_callback: &mut |graph, pattern_indices, path_head| {
714-
// Lift the survivors from the compacted (dropped-arm) indexing back to this level's
715-
// arm indexing. When no arm was dropped this is the identity.
716-
let pattern_indices = pattern_indices.lift(&live_filter);
717708
// Call `create_node_for_tuple_inner` recursively to handle the rest of the tuple.
718709
create_node_for_tuple_inner(
719710
CreateNodeParams {
@@ -775,18 +766,13 @@ fn add_item_to_path<'db>(
775766
/// pattern.
776767
fn handle_u256_literal<'db>(
777768
ctx: &LoweringContext<'db, '_>,
778-
graph: &mut FlowControlGraphBuilder<'db>,
779769
pattern_literal: &semantic::PatternLiteral<'db>,
780770
item_idx: usize,
781-
) -> Maybe<semantic::Pattern<'db>> {
771+
) -> semantic::Pattern<'db> {
782772
let PatternLiteral {
783-
literal: ExprNumericLiteral { value, ty, stable_ptr: expr_stable_ptr },
773+
literal: ExprNumericLiteral { value, ty: _, stable_ptr: expr_stable_ptr },
784774
stable_ptr,
785775
} = pattern_literal;
786-
if let Err(err) = validate_literal(ctx.db, *ty, value) {
787-
return Err(graph.report(*stable_ptr, LoweringDiagnosticKind::LiteralError(err)));
788-
}
789-
790776
let inner_value = if item_idx == 0 {
791777
value.clone() & ((BigInt::from(1) << 128) - 1)
792778
} else if item_idx == 1 {
@@ -795,14 +781,14 @@ fn handle_u256_literal<'db>(
795781
unreachable!("Unexpected number of members for u256.")
796782
};
797783

798-
Ok(semantic::Pattern::Literal(semantic::PatternLiteral {
784+
semantic::Pattern::Literal(semantic::PatternLiteral {
799785
literal: semantic::ExprNumericLiteral {
800786
value: inner_value,
801787
ty: ctx.db.core_info().u128,
802788
stable_ptr: *expr_stable_ptr,
803789
},
804790
stable_ptr: *stable_ptr,
805-
}))
791+
})
806792
}
807793

808794
/// Creates a node for matching over numeric values, using a combination of [EnumMatch] and
@@ -825,10 +811,6 @@ fn create_node_for_value<'db>(
825811
for (pattern_index, pattern) in patterns.iter().enumerate() {
826812
match pattern {
827813
Some(semantic::Pattern::Literal(semantic::PatternLiteral { literal, .. })) => {
828-
if let Err(err) = validate_literal(ctx.db, var_ty, &literal.value) {
829-
graph.report(literal.stable_ptr, LoweringDiagnosticKind::LiteralError(err));
830-
continue;
831-
}
832814
literals_map
833815
.entry(literal.value.clone())
834816
.or_insert((otherwise_filter.clone(), literal.stable_ptr))

‎crates/cairo-lang-lowering/src/lower/flow_control/graph.rs‎

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -479,15 +479,6 @@ impl<'db> FlowControlGraphBuilder<'db> {
479479
self.graph.var_locations[input_var.0]
480480
}
481481

482-
/// Reports a diagnostic.
483-
pub fn report(
484-
&mut self,
485-
stable_ptr: impl Into<SyntaxStablePtrId<'db>>,
486-
kind: LoweringDiagnosticKind<'db>,
487-
) -> DiagnosticAdded {
488-
self.diagnostics.report(stable_ptr, kind)
489-
}
490-
491482
/// Reports a diagnostic, and returns a new [FlowControlNode::Missing] node.
492483
pub fn report_with_missing_node(
493484
&mut self,

‎crates/cairo-lang-lowering/src/lower/flow_control/test_data/match‎

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,26 +1498,28 @@ fn foo(a: u8) -> bool {
14981498
}
14991499

15001500
//! > graph
1501-
Root: 4
1502-
4 EvaluateExpr { expr: ExprId(0), var_id: v0, next: NodeId(3) }
1503-
3 Upcast { input: v0, output: v1, next: NodeId(2) }
1504-
2 EqualsLiteral { input: v1, literal: 255, true_branch: NodeId(0), false_branch: NodeId(1) }
1501+
Root: 6
1502+
6 EvaluateExpr { expr: ExprId(0), var_id: v0, next: NodeId(5) }
1503+
5 Upcast { input: v0, output: v1, next: NodeId(4) }
1504+
4 EqualsLiteral { input: v1, literal: 255, true_branch: NodeId(0), false_branch: NodeId(3) }
1505+
3 EqualsLiteral { input: v1, literal: 256, true_branch: NodeId(0), false_branch: NodeId(2) }
1506+
2 EqualsLiteral { input: v1, literal: 257, true_branch: NodeId(0), false_branch: NodeId(1) }
15051507
1 ArmExpr { expr: ExprId(4) }
15061508
0 ArmExpr { expr: ExprId(2) }
15071509

15081510
//! > semantic_diagnostics
1509-
1510-
//! > lowering_diagnostics
1511-
error[E3009]: The value does not fit within the range of type core::integer::u8.
1511+
error[E2008]: The value does not fit within the range of type core::integer::u8.
15121512
--> lib.cairo:3:15
15131513
255 | 256 | 257 => false,
15141514
^^^
15151515

1516-
error[E3009]: The value does not fit within the range of type core::integer::u8.
1516+
error[E2008]: The value does not fit within the range of type core::integer::u8.
15171517
--> lib.cairo:3:21
15181518
255 | 256 | 257 => false,
15191519
^^^
15201520

1521+
//! > lowering_diagnostics
1522+
15211523
//! > lowered
15221524

15231525
//! > ==========================================================================
@@ -2032,13 +2034,13 @@ Root: 19
20322034
0 ArmExpr { expr: ExprId(1) }
20332035

20342036
//! > semantic_diagnostics
2035-
2036-
//! > lowering_diagnostics
2037-
error[E3009]: The value does not fit within the range of type core::integer::u256.
2037+
error[E2008]: The value does not fit within the range of type core::integer::u256.
20382038
--> lib.cairo:10:9
20392039
0x10000000000000000000000000000000000000000000000000000000000000000 => 7,
20402040
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20412041

2042+
//! > lowering_diagnostics
2043+
20422044
//! > lowered
20432045

20442046
//! > ==========================================================================
@@ -2058,20 +2060,24 @@ fn foo(x: u256) -> felt252 {
20582060
}
20592061

20602062
//! > graph
2061-
Root: 3
2062-
3 EvaluateExpr { expr: ExprId(0), var_id: v0, next: NodeId(2) }
2063-
2 Deconstruct { input: v0, outputs: [v1, v2], next: NodeId(1) }
2063+
Root: 7
2064+
7 EvaluateExpr { expr: ExprId(0), var_id: v0, next: NodeId(6) }
2065+
6 Deconstruct { input: v0, outputs: [v1, v2], next: NodeId(5) }
2066+
5 Upcast { input: v1, output: v3, next: NodeId(4) }
2067+
4 EqualsLiteral { input: v3, literal: 0, true_branch: NodeId(3), false_branch: NodeId(1) }
2068+
3 Upcast { input: v2, output: v4, next: NodeId(2) }
2069+
2 EqualsLiteral { input: v4, literal: 340282366920938463463374607431768211456, true_branch: NodeId(0), false_branch: NodeId(1) }
20642070
1 ArmExpr { expr: ExprId(2) }
20652071
0 ArmExpr { expr: ExprId(1) }
20662072

20672073
//! > semantic_diagnostics
2068-
2069-
//! > lowering_diagnostics
2070-
error[E3009]: The value does not fit within the range of type core::integer::u256.
2074+
error[E2008]: The value does not fit within the range of type core::integer::u256.
20712075
--> lib.cairo:4:9
20722076
0x10000000000000000000000000000000000000000000000000000000000000000 => 1,
20732077
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20742078

2079+
//! > lowering_diagnostics
2080+
20752081
//! > lowered
20762082

20772083
//! > ==========================================================================
@@ -2090,20 +2096,23 @@ fn foo(x: u256) -> felt252 {
20902096
}
20912097

20922098
//! > graph
2093-
Root: 3
2094-
3 EvaluateExpr { expr: ExprId(0), var_id: v0, next: NodeId(2) }
2095-
2 Deconstruct { input: v0, outputs: [v1, v2], next: NodeId(1) }
2099+
Root: 7
2100+
7 EvaluateExpr { expr: ExprId(0), var_id: v0, next: NodeId(6) }
2101+
6 Deconstruct { input: v0, outputs: [v1, v2], next: NodeId(5) }
2102+
5 Upcast { input: v1, output: v3, next: NodeId(4) }
2103+
4 EqualsLiteral { input: v3, literal: 0, true_branch: NodeId(3), false_branch: NodeId(1) }
2104+
3 Upcast { input: v2, output: v4, next: NodeId(2) }
2105+
2 EqualsLiteral { input: v4, literal: 340282366920938463463374607431768211456, true_branch: NodeId(0), false_branch: NodeId(1) }
20962106
1 Missing
20972107
0 ArmExpr { expr: ExprId(1) }
20982108

20992109
//! > semantic_diagnostics
2100-
2101-
//! > lowering_diagnostics
2102-
error[E3009]: The value does not fit within the range of type core::integer::u256.
2110+
error[E2008]: The value does not fit within the range of type core::integer::u256.
21032111
--> lib.cairo:4:9
21042112
0x10000000000000000000000000000000000000000000000000000000000000000 => 1,
21052113
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21062114

2115+
//! > lowering_diagnostics
21072116
error[E3004]: Match is non-exhaustive: `u256{low: _, high: _}` not covered.
21082117
--> lib.cairo:2:5-5:5
21092118
match x {

‎crates/cairo-lang-lowering/src/lower/mod.rs‎

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use cairo_lang_filesystem::ids::SmolStrId;
66
use cairo_lang_semantic as semantic;
77
use cairo_lang_semantic::corelib::{
88
CorelibSemantic, ErrorPropagationType, bounded_int_ty, get_enum_concrete_variant,
9-
try_get_ty_by_name, unwrap_error_propagation_type, validate_literal,
9+
try_get_ty_by_name, unwrap_error_propagation_type,
1010
};
1111
use cairo_lang_semantic::expr::compute::unwrap_pattern_type;
1212
use cairo_lang_semantic::items::constant::ConstValueId;
@@ -55,7 +55,7 @@ use self::context::{
5555
use self::external::{extern_facade_expr, extern_facade_return_tys};
5656
use self::logical_op::lower_logical_op;
5757
use crate::blocks::Blocks;
58-
use crate::diagnostic::LoweringDiagnosticKind::{self, *};
58+
use crate::diagnostic::LoweringDiagnosticKind::*;
5959
use crate::diagnostic::LoweringDiagnosticsBuilder;
6060
use crate::ids::{
6161
EnrichedSemanticSignature, FunctionLongId, FunctionWithBodyId, FunctionWithBodyLongId,
@@ -960,14 +960,7 @@ fn lower_expr_literal_to_var_usage<'db>(
960960
value: &BigInt,
961961
builder: &mut BlockBuilder<'db>,
962962
) -> VarUsage<'db> {
963-
let value = if let Err(err) = validate_literal(ctx.db, ty, value) {
964-
ConstValue::Missing(
965-
ctx.diagnostics.report(stable_ptr, LoweringDiagnosticKind::LiteralError(err)),
966-
)
967-
.intern(ctx.db)
968-
} else {
969-
ConstValueId::from_int(ctx.db, ty, value)
970-
};
963+
let value = ConstValueId::from_int(ctx.db, ty, value);
971964
let location = ctx.get_location(stable_ptr);
972965
generators::Const { value, ty, location }.add(ctx, &mut builder.statements)
973966
}

0 commit comments

Comments
 (0)