Files
sdk/pkg/front_end/testcases/patterns/shared_errors.dart.strong.modular.expect
Jens Johansen 3175e427d8 [CFE] Keep const locals by default; expression evaluation can evaluate const locals
Note: Const locals are still off for VM aot and dart2js for the entry
points I've found in an attempt to retain the old behaviour there.
It might be better if those targets could remove such locals in a
whole-world analysis instead.

 * Keep const locals by default (except as noted above). Update the
   verifier to accept that. For the platforms this has increased the
   size by at most 6584 bytes. With this the VM will pass in any const
   locals as it does normal locals, but as the variable is never
   captured it will never pass a const local defined in a method when
   inside a local function in that method.
 * Change the dart scope calculation(s) to return the found variables
   instead of just the types of the found variables.
 * When the incremental compilers expression compilation - via the dart
   scope calculation - finds a const local that it wasn't told about, it
   will pass it on as an extra variable that it knows about, allowing
   for evaluating const locals in the case not covered by the first
   bullet.

With luck this can in future CLs be extended to know about other
variables that we're not told about, allowing to give a message saying
something like
"yes, we know what 'foo' is, but you can't currently use it" as wanted
in for instance https://github.com/dart-lang/sdk/issues/60316 and
https://github.com/dart-lang/sdk/issues/53996.

Tested: Existing tests for existing functionality; new tests for the new
Change-Id: I1ec24350273e6f81574bb2888f6bf46e3b8b1b47
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/445461
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Daco Harkes <dacoharkes@google.com>
2025-08-19 04:30:41 -07:00

293 lines
13 KiB
Plaintext

library;
//
// Problems in library:
//
// pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
// - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
// case >= 0: // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:20:10: Error: A value of type 'Class' can't be assigned to a variable of type 'bool'.
// - 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
// case > 0: // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:26:12: Error: The matched value of type 'List<String>' isn't assignable to the required type 'List<int>'.
// - 'List' is from 'dart:core'.
// Try changing the required type of the pattern, or the matched value type.
// var <int>[a] = list; // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
// Try renaming the variable.
// [a, a] = list; // Error
// ^
// pkg/front_end/testcases/patterns/shared_errors.dart:31:4: Context: The first assigned variable pattern.
// [a, a] = list; // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
// Try removing the duplicate field.
// case (field: 1, field: 2): // Error
// ^
// pkg/front_end/testcases/patterns/shared_errors.dart:36:18: Context: The first field.
// case (field: 1, field: 2): // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
// Try removing the duplicate field.
// case Class(field: 1, field: 2): // Error
// ^
// pkg/front_end/testcases/patterns/shared_errors.dart:37:23: Context: The first field.
// case Class(field: 1, field: 2): // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
// Try removing the duplicate rest element.
// case [..., ...]: // Error
// ^
// pkg/front_end/testcases/patterns/shared_errors.dart:44:11: Context: The first rest element.
// case [..., ...]: // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:45:11: Error: The '...' pattern can't appear in map patterns.
// case {..., ...}: // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:45:16: Error: The '...' pattern can't appear in map patterns.
// case {..., ...}: // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:51:10: Error: A map pattern must have at least one entry.
// Try replacing it with an object pattern 'Map()'.
// case {}: // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:57:11: Error: The '...' pattern can't appear in map patterns.
// case {...}: // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:68:21: Error: Conditions must have a static type of 'bool'.
// Try changing the condition.
// if (i case 0 when i) { // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:74:9: Error: Refutable patterns can't be used in an irrefutable context.
// Try using an if-case, a 'switch' statement, or a 'switch' expression instead.
// var (a?) = x; // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:78:15: Error: The '...' pattern can't appear in map patterns.
// if (o case {..., 5: 3}) { // Error
// ^
//
// pkg/front_end/testcases/patterns/shared_errors.dart:84:21: Error: The '...' pattern can't appear in map patterns.
// if (o case {5: 3, ...var a}) { // Error
// ^
//
import self as self;
import "dart:core" as core;
class Class extends core::Object {
synthetic constructor •() → self::Class
: super core::Object::•()
;
get field() → core::int
return 42;
operator >=(self::Class cls) → core::bool
return true;
operator >(core::int i) → self::Class
return new self::Class::•();
}
static method argumentTypeNotAssignable(self::Class cls) → dynamic {
#L1:
{
final synthesized self::Class #0#0 = cls;
{
if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:13:13: Error: The argument type 'int' can't be assigned to the parameter type 'Class'.
- 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
case >= 0: // Error
^") {
{
core::print(0);
}
}
}
}
}
static method relationalPatternOperatorReturnTypeNotAssignableToBool(self::Class cls) → dynamic {
#L2:
{
final synthesized self::Class #0#0 = cls;
{
if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:20:10: Error: A value of type 'Class' can't be assigned to a variable of type 'bool'.
- 'Class' is from 'pkg/front_end/testcases/patterns/shared_errors.dart'.
case > 0: // Error
^") {
{
core::print(0);
}
}
}
}
}
static method patternTypeMismatchInIrrefutableContext(core::List<core::String> list) → dynamic {
has-declared-initializer core::int a;
{
final synthesized core::List<core::String> #0#0 = list;
if(!invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:26:12: Error: The matched value of type 'List<String>' isn't assignable to the required type 'List<int>'.
- 'List' is from 'dart:core'.
Try changing the required type of the pattern, or the matched value type.
var <int>[a] = list; // Error
^")
throw{for-error-handling} new core::StateError::•("Pattern matching error");
}
}
static method duplicateAssignmentPatternVariable(core::List<core::String> list) → dynamic {
core::String a = "";
{
final synthesized core::List<core::String> #0#0 = list;
final const synthesized core::int #0#2 = #C1;
if(!(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t1 = a = #0#0.{core::List::[]}(0){(core::int) → core::String} in true) && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:31:7: Error: The variable 'a' is already assigned in this pattern.
Try renaming the variable.
[a, a] = list; // Error
^"))
throw{for-error-handling} new core::StateError::•("Pattern matching error");
}
}
static method duplicateRecordPatternField(dynamic o) → dynamic {
#L3:
{
final synthesized dynamic #0#0 = o;
final const synthesized core::int #0#3 = #C2;
synthesized core::int #0#2;
synthesized core::bool #0#2#isSet = false;
{
if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:36:28: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case (field: 1, field: 2): // Error
^" || #0#0 is self::Class && #C2 =={core::num::==}{(core::Object) → core::bool} (#0#2#isSet ?{core::int} #0#2 : let final dynamic #t2 = #0#2#isSet = true in #0#2 = #0#0{self::Class}.{self::Class::field}{core::int}) && (let final dynamic #t3 = #0#2#isSet ?{core::int} #0#2 : let final dynamic #t4 = #0#2#isSet = true in #0#2 = #0#0{self::Class}.{self::Class::field}{core::int} in invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:37:33: Error: The field 'field' is already matched in this pattern.
Try removing the duplicate field.
case Class(field: 1, field: 2): // Error
^")) {
{
core::print(0);
}
}
}
}
}
static method duplicateRestPattern(dynamic o) → dynamic {
#L4:
{
final synthesized dynamic #0#0 = o;
final const synthesized core::int #0#3 = #C2;
{
if(#0#0 is core::List<dynamic> && #0#0{core::List<dynamic>}.{core::List::length}{core::int}.{core::num::>=}(#C2){(core::num) → core::bool} && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:44:16: Error: At most one rest element is allowed in a list or map pattern.
Try removing the duplicate rest element.
case [..., ...]: // Error
^" || invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:45:11: Error: The '...' pattern can't appear in map patterns.
case {..., ...}: // Error
^") {
}
}
}
}
static method emptyMapPattern(dynamic o) → dynamic {
#L5:
{
final synthesized dynamic #0#0 = o;
{
if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:51:10: Error: A map pattern must have at least one entry.
Try replacing it with an object pattern 'Map()'.
case {}: // Error
^") {
}
}
}
}
static method singleRestPatternInMap(dynamic o) → dynamic {
#L6:
{
final synthesized dynamic #0#0 = o;
{
if(invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:57:11: Error: The '...' pattern can't appear in map patterns.
case {...}: // Error
^") {
}
}
}
}
static method matchedTypeIsStrictlyNonNullable(core::List<core::int> list) → dynamic {
{
final synthesized core::List<core::int> #0#0 = list;
final const synthesized core::int #0#2 = #C1;
synthesized core::int #0#4;
synthesized core::bool #0#4#isSet = false;
synthesized core::int #0#6;
synthesized core::bool #0#6#isSet = false;
{
hoisted core::int a;
hoisted core::int b;
if(#0#0.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && (let final dynamic #t5 = (#0#4#isSet ?{core::int} #0#4 : let final dynamic #t6 = #0#4#isSet = true in #0#4 = #0#0.{core::List::[]}(0){(core::int) → core::int})! in let final dynamic #t7 = a = (#0#4#isSet ?{core::int} #0#4 : let final dynamic #t8 = #0#4#isSet = true in #0#4 = #0#0.{core::List::[]}(0){(core::int) → core::int})! in true) && !((#0#6#isSet ?{core::int} #0#6 : let final dynamic #t9 = #0#6#isSet = true in #0#6 = #0#0.{core::List::[]}(1){(core::int) → core::int}) == null)) {
b = #0#6#isSet ?{core::int} #0#6 : let final dynamic #t10 = #0#6#isSet = true in #0#6 = #0#0.{core::List::[]}(1){(core::int) → core::int};
{
core::print(0);
}
}
}
}
}
static method nonBooleanCondition(core::int i) → dynamic {
{
final synthesized core::int #0#0 = i;
final const synthesized core::int #0#1 = #C3;
if(#C3 =={core::num::==}{(core::Object) → core::bool} #0#0 && invalid-expression "pkg/front_end/testcases/patterns/shared_errors.dart:68:21: Error: Conditions must have a static type of 'bool'.
Try changing the condition.
if (i case 0 when i) { // Error
^") {
core::print(0);
}
}
}
static method refutablePatternInIrrefutableContext(core::int? x) → dynamic {
hoisted has-declared-initializer core::int a;
{
final synthesized core::int? #0#0 = x;
if(!(!(#0#0 == null) && (let final dynamic #t11 = a = #0#0{core::int} in true)))
throw{for-error-handling} new core::StateError::•("Pattern matching error");
}
}
static method restPatternNotLastInMap(dynamic o) → dynamic {
{
final synthesized dynamic #0#0 = o;
synthesized dynamic #0#4;
synthesized core::bool #0#4#isSet = false;
final const synthesized core::int #0#2 = #C4;
final const synthesized core::int #0#5 = #C5;
if(#0#0 is core::Map<dynamic, dynamic> && (!((#0#4#isSet ?{dynamic} #0#4 : let final dynamic #t12 = #0#4#isSet = true in #0#4 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) == null) || null is dynamic && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool}) && #C5 =={core::num::==}{(core::Object) → core::bool} (#0#4#isSet ?{dynamic} #0#4 : let final dynamic #t13 = #0#4#isSet = true in #0#4 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic})) {
core::print(0);
}
}
}
static method restPatternWithSubPatternInMap(dynamic o) → dynamic {
{
final synthesized dynamic #0#0 = o;
synthesized dynamic #0#4;
synthesized core::bool #0#4#isSet = false;
final const synthesized core::int #0#2 = #C4;
final const synthesized core::int #0#5 = #C5;
if(#0#0 is core::Map<dynamic, dynamic> && (!((#0#4#isSet ?{dynamic} #0#4 : let final dynamic #t14 = #0#4#isSet = true in #0#4 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic}) == null) || null is dynamic && #0#0{core::Map<dynamic, dynamic>}.{core::Map::containsKey}(#C4){(core::Object?) → core::bool}) && #C5 =={core::num::==}{(core::Object) → core::bool} (#0#4#isSet ?{dynamic} #0#4 : let final dynamic #t15 = #0#4#isSet = true in #0#4 = #0#0{core::Map<dynamic, dynamic>}.{core::Map::[]}(#C4){(core::Object?) → dynamic})) {
core::print(0);
}
}
}
constants {
#C1 = 2
#C2 = 1
#C3 = 0
#C4 = 5
#C5 = 3
}