diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart index 480d68deace..9e1f0159ad4 100644 --- a/pkg/front_end/lib/src/fasta/parser/parser.dart +++ b/pkg/front_end/lib/src/fasta/parser/parser.dart @@ -4875,7 +4875,9 @@ class Parser { if (optional('!', token.next)) { not = token = token.next; } - token = computeType(token, true).ensureTypeNotVoid(token, this); + // Ignore trailing `?` if there is one as it may be part of an expression + TypeInfo typeInfo = computeType(token, true).asNonNullableType(); + token = typeInfo.ensureTypeNotVoid(token, this); listener.handleIsOperator(operator, not); return skipChainedAsIsOperators(token); } @@ -4888,7 +4890,9 @@ class Parser { Token parseAsOperatorRest(Token token) { Token operator = token = token.next; assert(optional('as', operator)); - token = computeType(token, true).ensureTypeNotVoid(token, this); + // Ignore trailing `?` if there is one as it may be part of an expression + TypeInfo typeInfo = computeType(token, true).asNonNullableType(); + token = typeInfo.ensureTypeNotVoid(token, this); listener.handleAsOperator(operator); return skipChainedAsIsOperators(token); } diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart index 585fedf332a..5e9f6363a3f 100644 --- a/pkg/front_end/lib/src/fasta/parser/type_info.dart +++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart @@ -17,6 +17,10 @@ import 'util.dart' show isOneOf, optional; /// [TypeInfo] provides information collected by [computeType] /// about a particular type reference. abstract class TypeInfo { + /// Return type info representing the receiver without the trailing `?` + /// or the receiver if the receiver does not represent a nullable type. + TypeInfo asNonNullableType(); + /// Return `true` if the tokens comprising the type represented by the /// receiver could be interpreted as a valid standalone expression. /// For example, `A` or `A.b` could be interpreted as a type references diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart index 6ec0d201459..8a29317b80b 100644 --- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart +++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart @@ -84,6 +84,9 @@ class NoType implements TypeInfo { @override bool get couldBeExpression => false; + @override + TypeInfo asNonNullableType() => this; + @override Token ensureTypeNotVoid(Token token, Parser parser) { parser.reportRecoverableErrorWithToken( @@ -119,6 +122,9 @@ class PrefixedType implements TypeInfo { @override bool get couldBeExpression => true; + @override + TypeInfo asNonNullableType() => this; + @override Token ensureTypeNotVoid(Token token, Parser parser) => parseType(token, parser); @@ -167,6 +173,9 @@ class SimpleTypeWith1Argument implements TypeInfo { @override bool get couldBeExpression => false; + @override + TypeInfo asNonNullableType() => this; + @override Token ensureTypeNotVoid(Token token, Parser parser) => parseType(token, parser); @@ -208,6 +217,9 @@ class SimpleType implements TypeInfo { @override bool get couldBeExpression => true; + @override + TypeInfo asNonNullableType() => this; + @override Token ensureTypeNotVoid(Token token, Parser parser) => parseType(token, parser); @@ -247,6 +259,9 @@ class VoidType implements TypeInfo { @override bool get couldBeExpression => false; + @override + TypeInfo asNonNullableType() => this; + @override Token ensureTypeNotVoid(Token token, Parser parser) { // Report an error, then parse `void` as if it were a type name. @@ -324,6 +339,11 @@ class ComplexTypeInfo implements TypeInfo { @override bool get couldBeExpression => false; + @override + TypeInfo asNonNullableType() { + return this; + } + @override Token ensureTypeNotVoid(Token token, Parser parser) => parseType(token, parser);