[cfe] Promote matched expression in relational pattern Closes #52123 Change-Id: I702524479d1abe83eb67e801454f03a88febe434 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/298600 Reviewed-by: Chloe Stefantsova <cstefantsova@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart index dbe5fda..39644ff 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/matching_expressions.dart
@@ -566,6 +566,8 @@ @override DelayedExpression visitRelationalPattern( RelationalPattern node, CacheableExpression matchedExpression) { + matchedExpression = matchedExpression.promote(node.matchedValueType!); + CacheableExpression constant = matchingCache.createConstantExpression( node.expressionValue!, node.expressionType!, fileOffset: node.expression.fileOffset); @@ -675,8 +677,7 @@ @override DelayedExpression visitVariablePattern( VariablePattern node, CacheableExpression matchedExpression) { - DartType matchedType = node.matchedValueType!; - matchedExpression = matchedExpression.promote(matchedType); + matchedExpression = matchedExpression.promote(node.matchedValueType!); DelayedExpression? matchingExpression; if (node.type != null) { matchingExpression = new DelayedIsExpression(
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect index 5a33af6..ac6ec72 100644 --- a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect +++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.expect
@@ -39,14 +39,14 @@ hoisted core::int a1; final synthesized dynamic #0#0 = x1; final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) { return a1; } else { hoisted core::int a1; final synthesized dynamic #1#0 = x1; final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression."; - if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { return a1; } else { @@ -86,7 +86,7 @@ { lowered hoisted core::int a3#case#0; lowered hoisted core::String a3#case#1; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { { return 1; } @@ -110,7 +110,7 @@ { lowered hoisted core::int a4#case#0; lowered hoisted core::String a4#case#1; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { { return 1; } @@ -134,7 +134,7 @@ { { hoisted core::int a5; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { #t11 = 1; break #L4; }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect index fd24527..2858ff3 100644 --- a/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.strong.transformed.expect
@@ -2,18 +2,199 @@ // // Problems in library: // -// pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression. -// list8.addAll(const [x8]); -// ^^ +// pkg/front_end/testcases/patterns/issue51971_2.dart:6:27: Error: Read of a non-const variable is not a constant expression. +// if (x1 case int a1 && < a1 || int a1) { // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:8:44: Error: Read of a non-const variable is not a constant expression. +// } else if (x1 case int a1 || int a1 && < a1) { // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:27:22: Error: Read of a non-const variable is not a constant expression. +// case int a3 && < a3: // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:28:26: Error: Read of a non-const variable is not a constant expression. +// case String a3 && == a3: // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:37:22: Error: Read of a non-const variable is not a constant expression. +// case int a4 && < a4 when a4 > 0: // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:38:26: Error: Read of a non-const variable is not a constant expression. +// case String a4 && == a4 when a4.startsWith("f"): // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:47:17: Error: Read of a non-const variable is not a constant expression. +// int a5 && < a5 => 1, // Error. +// ^ // import self as self; import "dart:core" as core; +import "dart:collection" as col; -static method test8() → dynamic { - core::int x8 = 0; - core::List<core::int> list8 = core::_GrowableList::•<core::int>(0); - list8.{core::List::addAll}(invalid-expression "pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression. - list8.addAll(const [x8]); - ^^"){(core::Iterable<core::int>) → void}; - return list8; +static method test1(dynamic x1) → dynamic { + { + hoisted core::int a1; + final synthesized dynamic #0#0 = x1; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t2 = a1 = #0#0{core::int} in true)) { + return a1; + } + else { + hoisted core::int a1; + final synthesized dynamic #1#0 = x1; + final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + if(#1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + return a1; + } + else { + return null; + } + } + } +} +static method test2(dynamic x2) → dynamic { + #L1: + { + final synthesized dynamic #0#0 = x2; + { + lowered hoisted core::int a2#case#0; + lowered hoisted core::String a2#case#1; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t5 = a2#case#0 = #0#0{core::int} in true) || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t6 = a2#case#1 = #0#0{core::String} in true)) { + { + return 1; + } + } + } + { + { + { + return 0; + } + } + } + } +} +static method test3(dynamic x3) → dynamic { + #L2: + { + final synthesized dynamic #0#0 = x3; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression."; + { + lowered hoisted core::int a3#case#0; + lowered hoisted core::String a3#case#1; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { + { + return 1; + } + } + } + { + { + { + return 0; + } + } + } + } +} +static method test4(dynamic x4) → dynamic { + #L3: + { + final synthesized dynamic #0#0 = x4; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression."; + { + lowered hoisted core::int a4#case#0; + lowered hoisted core::String a4#case#1; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { + { + return 1; + } + } + } + { + { + { + return 0; + } + } + } + } +} +static method test5(dynamic x5) → dynamic { + return block { + core::int #t11; + final synthesized dynamic #0#0 = x5; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + #L4: + { + { + hoisted core::int a5; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + #t11 = 1; + break #L4; + } + } + { + if(true) { + #t11 = 0; + break #L4; + } + } + } + } =>#t11; +} +static method test6(dynamic x6) → dynamic { + return block { + final core::Set<core::int> #t13 = new col::_Set::•<core::int>(); + hoisted core::int i6; + hoisted core::int n6; + { + final synthesized dynamic #0#0 = x6 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>; + function ##0#6#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic}; + late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic}; + function ##0#7#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic}; + late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic}; + if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t14 = i6 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t15 = n6 = #0#7{core::int} in true)))) + throw new core::StateError::•("Pattern matching error"); + } + final core::int #t16 = i6; + final core::int #t17 = n6; + for (core::int i6 = #t16, core::int n6 = #t17; i6.{core::num::<}(n6){(core::num) → core::bool}; i6 = i6.{core::num::+}(1){(core::num) → core::int}) + #t13.{core::Set::add}{Invariant}(i6){(core::int) → core::bool}; + } =>#t13; +} +static method test7(dynamic x7) → dynamic { + { + hoisted core::int i7; + hoisted core::int n7; + { + final synthesized dynamic #0#0 = x7 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>; + function ##0#6#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic}; + late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic}; + function ##0#7#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic}; + late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic}; + if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t18 = i7 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t19 = n7 = #0#7{core::int} in true)))) + throw new core::StateError::•("Pattern matching error"); + } + final core::int #t20 = i7; + final core::int #t21 = n7; + for (core::int i7 = #t20, core::int n7 = #t21; i7.{core::num::<}(n7){(core::num) → core::bool}; i7 = i7.{core::num::+}(1){(core::num) → core::int}) { + if(i7.{core::num::%}(3){(core::num) → core::int} =={core::num::==}{(core::Object) → core::bool} 0) + return i7; + } + } + return null; +} + +constants { + #C1 = 2 }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect index 6a64fa0..e25b041 100644 --- a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect +++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.expect
@@ -40,14 +40,14 @@ hoisted core::int a1; final synthesized dynamic #0#0 = x1; final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) { return a1; } else { hoisted core::int a1; final synthesized dynamic #1#0 = x1; final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression."; - if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { return a1; } else { @@ -87,7 +87,7 @@ { lowered hoisted core::int a3#case#0; lowered hoisted core::String a3#case#1; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { { return 1; } @@ -111,7 +111,7 @@ { lowered hoisted core::int a4#case#0; lowered hoisted core::String a4#case#1; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { { return 1; } @@ -135,7 +135,7 @@ { { hoisted core::int a5; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { #t11 = 1; break #L4; }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect index 6a64fa0..e25b041 100644 --- a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect +++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.modular.expect
@@ -40,14 +40,14 @@ hoisted core::int a1; final synthesized dynamic #0#0 = x1; final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t2 = a1 = #0#0{core::int} in true)) { return a1; } else { hoisted core::int a1; final synthesized dynamic #1#0 = x1; final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression."; - if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + if(#1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { return a1; } else { @@ -87,7 +87,7 @@ { lowered hoisted core::int a3#case#0; lowered hoisted core::String a3#case#1; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { { return 1; } @@ -111,7 +111,7 @@ { lowered hoisted core::int a4#case#0; lowered hoisted core::String a4#case#1; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0 =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final dynamic #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { { return 1; } @@ -135,7 +135,7 @@ { { hoisted core::int a5; - if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + if(#0#0 is{ForNonNullableByDefault} core::int && (let final dynamic #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { #t11 = 1; break #L4; }
diff --git a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect index fd24527..20b89de 100644 --- a/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect +++ b/pkg/front_end/testcases/patterns/issue51971_2.dart.weak.transformed.expect
@@ -2,18 +2,201 @@ // // Problems in library: // -// pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression. -// list8.addAll(const [x8]); -// ^^ +// pkg/front_end/testcases/patterns/issue51971_2.dart:6:27: Error: Read of a non-const variable is not a constant expression. +// if (x1 case int a1 && < a1 || int a1) { // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:8:44: Error: Read of a non-const variable is not a constant expression. +// } else if (x1 case int a1 || int a1 && < a1) { // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:27:22: Error: Read of a non-const variable is not a constant expression. +// case int a3 && < a3: // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:28:26: Error: Read of a non-const variable is not a constant expression. +// case String a3 && == a3: // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:37:22: Error: Read of a non-const variable is not a constant expression. +// case int a4 && < a4 when a4 > 0: // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:38:26: Error: Read of a non-const variable is not a constant expression. +// case String a4 && == a4 when a4.startsWith("f"): // Error. +// ^ +// +// pkg/front_end/testcases/patterns/issue51971_2.dart:47:17: Error: Read of a non-const variable is not a constant expression. +// int a5 && < a5 => 1, // Error. +// ^ // import self as self; import "dart:core" as core; +import "dart:_internal" as _in; +import "dart:collection" as col; -static method test8() → dynamic { - core::int x8 = 0; - core::List<core::int> list8 = core::_GrowableList::•<core::int>(0); - list8.{core::List::addAll}(invalid-expression "pkg/front_end/testcases/patterns/issue51971_2.dart:66:23: Error: Not a constant expression. - list8.addAll(const [x8]); - ^^"){(core::Iterable<core::int>) → void}; - return list8; +static method test1(dynamic x1) → dynamic { + { + hoisted core::int a1; + final synthesized dynamic #0#0 = x1; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t1 = a1 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t2 = a1 = #0#0{core::int} in true)) { + return a1; + } + else { + hoisted core::int a1; + final synthesized dynamic #1#0 = x1; + final const synthesized core::int #1#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + if(#1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t3 = a1 = #1#0{core::int} in true) || #1#0 is{ForNonNullableByDefault} core::int && (let final core::int #t4 = a1 = #1#0{core::int} in true) && #1#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + return a1; + } + else { + return null; + } + } + } +} +static method test2(dynamic x2) → dynamic { + #L1: + { + final synthesized dynamic #0#0 = x2; + { + lowered hoisted core::int a2#case#0; + lowered hoisted core::String a2#case#1; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t5 = a2#case#0 = #0#0{core::int} in true) || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t6 = a2#case#1 = #0#0{core::String} in true)) { + { + return 1; + } + } + } + { + { + { + return 0; + } + } + } + } +} +static method test3(dynamic x3) → dynamic { + #L2: + { + final synthesized dynamic #0#0 = x3; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression."; + { + lowered hoisted core::int a3#case#0; + lowered hoisted core::String a3#case#1; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t7 = a3#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t8 = a3#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression.") { + { + return 1; + } + } + } + { + { + { + return 0; + } + } + } + } +} +static method test4(dynamic x4) → dynamic { + #L3: + { + final synthesized dynamic #0#0 = x4; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + final const synthesized core::String #0#3 = invalid-expression "Read of a non-const variable is not a constant expression."; + { + lowered hoisted core::int a4#case#0; + lowered hoisted core::String a4#case#1; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t9 = a4#case#0 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool} && a4#case#0.{core::num::>}(0){(core::num) → core::bool} || #0#0 is{ForNonNullableByDefault} core::String && (let final core::String #t10 = a4#case#1 = #0#0{core::String} in true) && #0#0{core::String} =={core::String::==}{(core::Object) → core::bool} invalid-expression "Read of a non-const variable is not a constant expression." && a4#case#1.{core::String::startsWith}("f"){(core::Pattern, [core::int]) → core::bool}) { + { + return 1; + } + } + } + { + { + { + return 0; + } + } + } + } +} +static method test5(dynamic x5) → dynamic { + return block { + core::int #t11; + final synthesized dynamic #0#0 = x5; + final const synthesized core::int #0#1 = invalid-expression "Read of a non-const variable is not a constant expression."; + #L4: + { + { + hoisted core::int a5; + if(#0#0 is{ForNonNullableByDefault} core::int && (let final core::int #t12 = a5 = #0#0{core::int} in true) && #0#0{core::int}.{core::num::<}(invalid-expression "Read of a non-const variable is not a constant expression."){(core::num) → core::bool}) { + #t11 = 1; + break #L4; + } + } + { + if(true) { + #t11 = 0; + break #L4; + } + } + throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable type."); + } + } =>#t11; +} +static method test6(dynamic x6) → dynamic { + return block { + final core::Set<core::int> #t13 = new col::_Set::•<core::int>(); + hoisted core::int i6; + hoisted core::int n6; + { + final synthesized dynamic #0#0 = x6 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>; + function ##0#6#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic}; + late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic}; + function ##0#7#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic}; + late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic}; + if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t14 = i6 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t15 = n6 = #0#7{core::int} in true)))) + throw new core::StateError::•("Pattern matching error"); + } + final core::int #t16 = i6; + final core::int #t17 = n6; + for (core::int i6 = #t16, core::int n6 = #t17; i6.{core::num::<}(n6){(core::num) → core::bool}; i6 = i6.{core::num::+}(1){(core::num) → core::int}) + #t13.{core::Set::add}{Invariant}(i6){(core::int) → core::bool}; + } =>#t13; +} +static method test7(dynamic x7) → dynamic { + { + hoisted core::int i7; + hoisted core::int n7; + { + final synthesized dynamic #0#0 = x7 as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<core::int>; + function ##0#6#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(0){(core::int) → dynamic}; + late final synthesized dynamic #0#6 = ##0#6#initializer(){() → dynamic}; + function ##0#7#initializer() → dynamic + return #0#0{core::List<dynamic>}.{core::List::[]}(1){(core::int) → dynamic}; + late final synthesized dynamic #0#7 = ##0#7#initializer(){() → dynamic}; + if(!(#0#0 is{ForNonNullableByDefault} core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (#0#6 is{ForNonNullableByDefault} core::int && (let final core::int #t18 = i7 = #0#6{core::int} in true)) && (#0#7 is{ForNonNullableByDefault} core::int && (let final core::int #t19 = n7 = #0#7{core::int} in true)))) + throw new core::StateError::•("Pattern matching error"); + } + final core::int #t20 = i7; + final core::int #t21 = n7; + for (core::int i7 = #t20, core::int n7 = #t21; i7.{core::num::<}(n7){(core::num) → core::bool}; i7 = i7.{core::num::+}(1){(core::num) → core::int}) { + if(i7.{core::num::%}(3){(core::num) → core::int} =={core::num::==}{(core::Object) → core::bool} 0) + return i7; + } + } + return null; +} + +constants { + #C1 = 2 }