[cfe] Account for parser recovery in const pattern arguments

Part of https://github.com/dart-lang/sdk/issues/49749

Change-Id: I35801c7b0c6046076c8c31e66d684445654a8573
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286480
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Chloe Stefantsova 2023-03-02 16:07:59 +00:00 committed by Commit Queue
parent 2e1dfef731
commit b1d7d84030
10 changed files with 297 additions and 3 deletions

View file

@ -6161,7 +6161,8 @@ class BodyBuilder extends StackListenerImpl
Token nameToken, int offset, Constness constness,
{required bool inMetadata, required bool inImplicitCreationContext}) {
assert(checkState(nameToken, [
/*arguments*/ ValueKinds.Arguments,
/*arguments*/ unionOfKinds(
[ValueKinds.Arguments, ValueKinds.ParserRecovery]),
/*constructor name identifier*/ ValueKinds.IdentifierOrNull,
/*constructor name*/ ValueKinds.Name,
/*type arguments*/ ValueKinds.TypeArgumentsOrNull,
@ -6173,7 +6174,7 @@ class BodyBuilder extends StackListenerImpl
]),
/*previous constant context*/ ValueKinds.ConstantContext,
]));
Arguments arguments = pop() as Arguments;
Object? arguments = pop();
Identifier? nameLastIdentifier = pop(NullValues.Identifier) as Identifier?;
Token nameLastToken = nameLastIdentifier?.token ?? nameToken;
String name = pop() as String;
@ -6188,7 +6189,12 @@ class BodyBuilder extends StackListenerImpl
Object? type = pop();
ConstantContext savedConstantContext = pop() as ConstantContext;
if (type is Generator) {
if (arguments is! Arguments) {
push(new ParserErrorGenerator(
this, nameToken, fasta.messageSyntheticToken));
arguments = forest.createArguments(offset, []);
} else if (type is Generator) {
push(type.invokeConstructor(
typeArguments, name, arguments, nameToken, nameLastToken, constness,
inImplicitCreationContext: inImplicitCreationContext));

View file

@ -0,0 +1,14 @@
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
class C<T> {
final T t;
const C(this.t);
}
Map<C<String>, int> foo() => throw 0;
test() {
var {const C(:var t): a1} = foo();
}

View file

@ -0,0 +1,49 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:16: Error: Expected an identifier, but got ':'.
// Try inserting an identifier before ':'.
// var {const C(:var t): a1} = foo();
// ^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected an identifier, but got 'var'.
// Try inserting an identifier before 'var'.
// var {const C(:var t): a1} = foo();
// ^^^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected ')' before this.
// var {const C(:var t): a1} = foo();
// ^^^
//
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class C<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
final field self::C::T% t;
const constructor •(self::C::T% t) → self::C<self::C::T%>
: self::C::t = t, super core::Object::•()
;
}
static method foo() → core::Map<self::C<core::String>, core::int>
return throw 0;
static method test() → dynamic {
dynamic a1;
{
final dynamic #0#0 = self::foo();
final const dynamic #0#4 = invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^";
if(!(#0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::containsKey}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → core::bool} && (let final dynamic #t1 = a1 = #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::[]}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → dynamic} in true)))
throw new _in::ReachabilityError::•();
}
}
constants {
#C1 = 1
}

View file

@ -0,0 +1,49 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:16: Error: Expected an identifier, but got ':'.
// Try inserting an identifier before ':'.
// var {const C(:var t): a1} = foo();
// ^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected an identifier, but got 'var'.
// Try inserting an identifier before 'var'.
// var {const C(:var t): a1} = foo();
// ^^^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected ')' before this.
// var {const C(:var t): a1} = foo();
// ^^^
//
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class C<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
final field self::C::T% t;
const constructor •(self::C::T% t) → self::C<self::C::T%>
: self::C::t = t, super core::Object::•()
;
}
static method foo() → core::Map<self::C<core::String>, core::int>
return throw 0;
static method test() → dynamic {
dynamic a1;
{
final dynamic #0#0 = self::foo();
final const dynamic #0#4 = invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^";
if(!(#0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::containsKey}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → core::bool} && (let final core::int? #t1 = a1 = #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::[]}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → dynamic} in true)))
throw new _in::ReachabilityError::•();
}
}
constants {
#C1 = 1
}

View file

@ -0,0 +1,7 @@
class C<T> {
final T t;
const C(this.t);
}
Map<C<String>, int> foo() => throw 0;
test() {}

View file

@ -0,0 +1,8 @@
Map<C<String>, int> foo() => throw 0;
class C<T> {
const C(this.t);
final T t;
}
test() {}

View file

@ -0,0 +1,49 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:16: Error: Expected an identifier, but got ':'.
// Try inserting an identifier before ':'.
// var {const C(:var t): a1} = foo();
// ^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected an identifier, but got 'var'.
// Try inserting an identifier before 'var'.
// var {const C(:var t): a1} = foo();
// ^^^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected ')' before this.
// var {const C(:var t): a1} = foo();
// ^^^
//
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class C<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
final field self::C::T% t;
const constructor •(self::C::T% t) → self::C<self::C::T%>
: self::C::t = t, super core::Object::•()
;
}
static method foo() → core::Map<self::C<core::String>, core::int>
return throw 0;
static method test() → dynamic {
dynamic a1;
{
final dynamic #0#0 = self::foo();
final const dynamic #0#4 = invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^";
if(!(#0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::containsKey}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → core::bool} && (let final dynamic #t1 = a1 = #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::[]}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → dynamic} in true)))
throw new _in::ReachabilityError::•();
}
}
constants {
#C1 = 1
}

View file

@ -0,0 +1,49 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:16: Error: Expected an identifier, but got ':'.
// Try inserting an identifier before ':'.
// var {const C(:var t): a1} = foo();
// ^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected an identifier, but got 'var'.
// Try inserting an identifier before 'var'.
// var {const C(:var t): a1} = foo();
// ^^^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected ')' before this.
// var {const C(:var t): a1} = foo();
// ^^^
//
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class C<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
final field self::C::T% t;
const constructor •(self::C::T% t) → self::C<self::C::T%>
: self::C::t = t, super core::Object::•()
;
}
static method foo() → core::Map<self::C<core::String>, core::int>
return throw 0;
static method test() → dynamic {
dynamic a1;
{
final dynamic #0#0 = self::foo();
final const dynamic #0#4 = invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^";
if(!(#0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::containsKey}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → core::bool} && (let final dynamic #t1 = a1 = #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::[]}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → dynamic} in true)))
throw new _in::ReachabilityError::•();
}
}
constants {
#C1 = 1
}

View file

@ -0,0 +1,14 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class C<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
final field self::C::T% t;
const constructor •(self::C::T% t) → self::C<self::C::T%>
: self::C::t = t, super core::Object::•()
;
}
static method foo() → core::Map<self::C<core::String>, core::int>
;
static method test() → dynamic
;

View file

@ -0,0 +1,49 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:16: Error: Expected an identifier, but got ':'.
// Try inserting an identifier before ':'.
// var {const C(:var t): a1} = foo();
// ^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected an identifier, but got 'var'.
// Try inserting an identifier before 'var'.
// var {const C(:var t): a1} = foo();
// ^^^
//
// pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:17: Error: Expected ')' before this.
// var {const C(:var t): a1} = foo();
// ^^^
//
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class C<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ {
final field self::C::T% t;
const constructor •(self::C::T% t) → self::C<self::C::T%>
: self::C::t = t, super core::Object::•()
;
}
static method foo() → core::Map<self::C<core::String>, core::int>
return throw 0;
static method test() → dynamic {
dynamic a1;
{
final dynamic #0#0 = self::foo();
final const dynamic #0#4 = invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^";
if(!(#0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::length}{core::int} =={core::num::==}{(core::Object) → core::bool} #C1 && #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::containsKey}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → core::bool} && (let final core::int? #t1 = a1 = #0#0{core::Map<self::C<core::String>, core::int>}.{core::Map::[]}(invalid-expression "pkg/front_end/testcases/patterns/parser_recovery_in_pattern_arguments.dart:13:14: Error: This couldn't be parsed.
var {const C(:var t): a1} = foo();
^"){(core::Object?) → dynamic} in true)))
throw new _in::ReachabilityError::•();
}
}
constants {
#C1 = 1
}