[cfe] Fix sound mode failures

Closes #46704

Change-Id: I39b05b8432a8c316c4bca8679531d663e46817a9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208084
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2021-07-26 15:14:17 +00:00 committed by commit-bot@chromium.org
parent db90fd784b
commit eb1a2166cd
13 changed files with 92 additions and 61 deletions

View file

@ -51,6 +51,8 @@ import 'variable_builder.dart';
/// constructor.
class FormalParameterBuilder extends ModifierBuilderImpl
implements VariableBuilder {
static const String noNameSentinel = 'no name sentinel';
/// List of metadata builders for the metadata declared on this parameter.
final List<MetadataBuilder>? metadata;
@ -130,7 +132,8 @@ class FormalParameterBuilder extends ModifierBuilderImpl
if (!library.isNonNullableByDefault && builtType != null) {
builtType = legacyErasure(builtType);
}
variable = new VariableDeclarationImpl(name, functionNestingLevel,
variable = new VariableDeclarationImpl(
name == noNameSentinel ? null : name, functionNestingLevel,
type: builtType,
isFinal: isFinal,
isConst: isConst,

View file

@ -1256,12 +1256,16 @@ class BodyBuilder extends ScopeListener<JumpTarget>
} else {
Substitution substitution = Substitution.fromPairs(
initialTarget.function.typeParameters, arguments.types);
arguments.types.clear();
arguments.types.length = redirectionTarget!.typeArguments.length;
for (int i = 0; i < arguments.types.length; i++) {
arguments.types[i] =
for (int i = 0; i < redirectionTarget!.typeArguments.length; i++) {
DartType typeArgument =
substitution.substituteType(redirectionTarget.typeArguments[i]);
if (i < arguments.types.length) {
arguments.types[i] = typeArgument;
} else {
arguments.types.add(typeArgument);
}
}
arguments.types.length = redirectionTarget.typeArguments.length;
replacementNode = buildStaticInvocation(
resolvedTarget,
@ -2679,7 +2683,7 @@ class BodyBuilder extends ScopeListener<JumpTarget>
if (!libraryBuilder.isNonNullableByDefault) {
reportNonNullableModifierError(lateToken);
}
UnresolvedType type = pop() as UnresolvedType;
UnresolvedType? type = pop() as UnresolvedType?;
int modifiers = (lateToken != null ? lateMask : 0) |
Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
_enterLocalState(inLateLocalInitializer: lateToken != null);
@ -4954,7 +4958,8 @@ class BodyBuilder extends ScopeListener<JumpTarget>
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
push(const FixedNullableList<UnresolvedType>().pop(stack, count) ??
push(const FixedNullableList<UnresolvedType>()
.popNonNullable(stack, count, dummyUnresolvedType) ??
NullValue.TypeArguments);
}

View file

@ -943,7 +943,7 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
: numberSemantics = backend.numberSemantics,
coreTypes = typeEnvironment.coreTypes,
canonicalizationCache = <Constant, Constant>{},
nodeCache = <Node, Constant>{},
nodeCache = <Node, Constant?>{},
env = new EvaluationEnvironment() {
if (environmentDefines == null && !backend.supportsUnevaluatedConstants) {
throw new ArgumentError(

View file

@ -2078,7 +2078,7 @@ class InferenceVisitor
DartType inferredKeyType,
DartType inferredValueType,
DartType spreadContext,
List<DartType?> actualTypes,
List<DartType> actualTypes,
List<DartType> actualTypesForSet,
Map<TreeNode, DartType> inferredSpreadTypes,
Map<Expression, DartType> inferredConditionTypes,
@ -2096,8 +2096,8 @@ class InferenceVisitor
DartType spreadType = spreadResult.inferredType;
inferredSpreadTypes[entry.expression] = spreadType;
int length = actualTypes.length;
actualTypes.add(null);
actualTypes.add(null);
actualTypes.add(noInferredType);
actualTypes.add(noInferredType);
storeSpreadMapEntryElementTypes(
spreadType, entry.isNullAware, actualTypes, length);
DartType? actualKeyType = actualTypes[length];
@ -2108,7 +2108,7 @@ class InferenceVisitor
MapLiteralEntry replacement = entry;
if (typeChecksNeeded) {
if (actualKeyType == null) {
if (actualKeyType == noInferredType) {
if (inferrer.coreTypes.isNull(spreadTypeBound) &&
!entry.isNullAware) {
replacement = new MapLiteralEntry(
@ -2204,7 +2204,7 @@ class InferenceVisitor
1);
}
}
if (!inferrer.isAssignable(inferredValueType, actualValueType!)) {
if (!inferrer.isAssignable(inferredValueType, actualValueType)) {
if (inferrer.isNonNullableByDefault) {
IsSubtypeOf subtypeCheckResult = inferrer.typeSchemaEnvironment
.performNullabilityAwareSubtypeCheck(
@ -2273,7 +2273,7 @@ class InferenceVisitor
}
// Use 'dynamic' for error recovery.
if (actualKeyType == null) {
if (actualKeyType == noInferredType) {
actualKeyType = actualTypes[length] = const DynamicType();
actualValueType = actualTypes[length + 1] = const DynamicType();
}
@ -2287,7 +2287,7 @@ class InferenceVisitor
entry.entryType = new InterfaceType(
mapEntryClass!,
inferrer.library.nonNullable,
<DartType>[actualKeyType, actualValueType!]);
<DartType>[actualKeyType, actualValueType]);
bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
spreadType,
@ -2354,10 +2354,10 @@ class InferenceVisitor
typeChecksNeeded);
int length = actualTypes.length;
actualTypes[length - 2] = inferrer.typeSchemaEnvironment
.getStandardUpperBound(actualKeyType!, actualTypes[length - 2]!,
.getStandardUpperBound(actualKeyType, actualTypes[length - 2],
inferrer.library.library);
actualTypes[length - 1] = inferrer.typeSchemaEnvironment
.getStandardUpperBound(actualValueType!, actualTypes[length - 1]!,
.getStandardUpperBound(actualValueType, actualTypes[length - 1],
inferrer.library.library);
int lengthForSet = actualTypesForSet.length;
actualTypesForSet[lengthForSet - 1] = inferrer.typeSchemaEnvironment
@ -2622,7 +2622,7 @@ class InferenceVisitor
inferredConditionTypes = new Map<Expression, DartType>.identity();
}
if (inferenceNeeded) {
inferredTypes = [const UnknownType(), const UnknownType()];
inferredTypes = [noInferredType, noInferredType];
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
mapType,
mapClass.typeParameters,
@ -2701,7 +2701,7 @@ class InferenceVisitor
formalTypesForSet.add(setType.typeArguments[0]);
}
List<DartType> inferredTypesForSet = <DartType>[const UnknownType()];
List<DartType> inferredTypesForSet = <DartType>[noInferredType];
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
setType,
inferrer.coreTypes.setClass.typeParameters,

View file

@ -179,12 +179,11 @@ class RedirectionTarget {
}
RedirectionTarget? getRedirectionTarget(Procedure member, EnsureLoaded helper) {
List<DartType> typeArguments = <DartType>[]..length =
member.function.typeParameters.length;
for (int i = 0; i < typeArguments.length; i++) {
typeArguments[i] = new TypeParameterType.withDefaultNullabilityForLibrary(
List<DartType> typeArguments = new List<DartType>.generate(
member.function.typeParameters.length, (int i) {
return new TypeParameterType.withDefaultNullabilityForLibrary(
member.function.typeParameters[i], member.enclosingLibrary);
}
}, growable: true);
// We use the [tortoise and hare algorithm]
// (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
@ -201,15 +200,15 @@ RedirectionTarget? getRedirectionTarget(Procedure member, EnsureLoaded helper) {
Member nextTortoise = tortoiseBody!.target!;
helper.ensureLoaded(nextTortoise);
List<DartType>? nextTypeArguments = tortoiseBody.typeArguments;
if (nextTypeArguments == null) {
nextTypeArguments = <DartType>[];
}
Substitution sub = Substitution.fromPairs(
tortoise.function!.typeParameters, typeArguments);
typeArguments = <DartType>[]..length = nextTypeArguments.length;
for (int i = 0; i < typeArguments.length; i++) {
typeArguments[i] = sub.substituteType(nextTypeArguments[i]);
if (nextTypeArguments != null) {
Substitution sub = Substitution.fromPairs(
tortoise.function!.typeParameters, typeArguments);
typeArguments =
new List<DartType>.generate(nextTypeArguments.length, (int i) {
return sub.substituteType(nextTypeArguments[i]);
}, growable: true);
} else {
typeArguments = <DartType>[];
}
tortoise = nextTortoise;

View file

@ -32,9 +32,12 @@ import 'package:kernel/text/ast_to_text.dart' show Printer;
import '../builder/fixed_type_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
import '../builder/unresolved_type.dart';
import '../combinator.dart';
import '../configuration.dart';
import '../identifiers.dart';
import '../source/source_library_builder.dart';
import 'body_builder.dart';
@ -159,6 +162,7 @@ class ByteSink implements Sink<List<int>> {
final Token dummyToken = new SyntheticToken(TokenType.AT, -1);
final Identifier dummyIdentifier = new Identifier(dummyToken);
final Combinator dummyCombinator = new Combinator(false, {}, -1, dummyUri);
final MetadataBuilder dummyMetadataBuilder = new MetadataBuilder(dummyToken);
final TypeBuilder dummyTypeBuilder =
new FixedTypeBuilder(dummyDartType, dummyUri, -1);
final FormalParameterBuilder dummyFormalParameterBuilder =
@ -167,3 +171,6 @@ final TypeVariableBuilder dummyTypeVariableBuilder =
new TypeVariableBuilder(TypeVariableBuilder.noNameSentinel, null, -1, null);
final Label dummyLabel = new Label('', -1);
final FieldInfo dummyFieldInfo = new FieldInfo('', -1, null, dummyToken, -1);
final Configuration dummyConfiguration = new Configuration(-1, '', '', '');
final UnresolvedType dummyUnresolvedType =
new UnresolvedType(dummyTypeBuilder, -1, dummyUri);

View file

@ -339,7 +339,7 @@ class DietListener extends StackListenerImpl {
debugEvent("TopLevelMethod");
Token bodyToken = pop() as Token;
Object? name = pop();
Token metadata = pop() as Token;
Token? metadata = pop() as Token?;
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery) return;
@ -509,7 +509,7 @@ class DietListener extends StackListenerImpl {
debugEvent("Import");
Object? name = pop(NullValue.Prefix);
Token metadata = pop() as Token;
Token? metadata = pop() as Token?;
checkEmpty(importKeyword.charOffset);
if (name is ParserRecovery) return;
@ -535,7 +535,7 @@ class DietListener extends StackListenerImpl {
void endExport(Token exportKeyword, Token semicolon) {
debugEvent("Export");
Token metadata = pop() as Token;
Token? metadata = pop() as Token?;
Library libraryNode = libraryBuilder.library;
LibraryDependency dependency =
libraryNode.dependencies[importExportDirectiveIndex++];
@ -546,7 +546,7 @@ class DietListener extends StackListenerImpl {
void endPart(Token partKeyword, Token semicolon) {
debugEvent("Part");
Token metadata = pop() as Token;
Token? metadata = pop() as Token?;
Library libraryNode = libraryBuilder.library;
if (libraryNode.parts.length > partDirectiveIndex) {
// If partDirectiveIndex >= libraryNode.parts.length we are in a case of
@ -588,7 +588,7 @@ class DietListener extends StackListenerImpl {
debugEvent("ClassFactoryMethod");
Token bodyToken = pop() as Token;
Object? name = pop();
Token metadata = pop() as Token;
Token? metadata = pop() as Token?;
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery || currentClassIsParserRecovery) return;
@ -699,7 +699,7 @@ class DietListener extends StackListenerImpl {
// in handleNoFormalParameters rather than the supplied token.
pop(); // bodyToken
Object? name = pop();
Token metadata = pop() as Token;
Token? metadata = pop() as Token?;
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery || currentClassIsParserRecovery) return;
FunctionBuilderImpl builder;

View file

@ -162,7 +162,8 @@ class OutlineBuilder extends StackListenerImpl {
@override
void endMetadataStar(int count) {
debugEvent("MetadataStar");
push(const FixedNullableList<MetadataBuilder>().pop(stack, count) ??
push(const FixedNullableList<MetadataBuilder>()
.popNonNullable(stack, count, dummyMetadataBuilder) ??
NullValue.Metadata);
}
@ -259,7 +260,8 @@ class OutlineBuilder extends StackListenerImpl {
@override
void endConditionalUris(int count) {
debugEvent("EndConditionalUris");
push(const FixedNullableList<Configuration>().pop(stack, count) ??
push(const FixedNullableList<Configuration>()
.popNonNullable(stack, count, dummyConfiguration) ??
NullValue.ConditionalUris);
}
@ -1369,7 +1371,8 @@ class OutlineBuilder extends StackListenerImpl {
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
push(const FixedNullableList<TypeBuilder>().pop(stack, count) ??
push(const FixedNullableList<TypeBuilder>()
.popNonNullable(stack, count, dummyTypeBuilder) ??
NullValue.TypeArguments);
}
@ -1468,8 +1471,14 @@ class OutlineBuilder extends StackListenerImpl {
if (name is ParserRecovery) {
push(name);
} else {
push(libraryBuilder.addFormalParameter(metadata, modifiers, type,
name as String, thisKeyword != null, charOffset, initializerStart));
push(libraryBuilder.addFormalParameter(
metadata,
modifiers,
type,
name == null ? FormalParameterBuilder.noNameSentinel : name as String,
thisKeyword != null,
charOffset,
initializerStart));
}
}
@ -1557,8 +1566,8 @@ class OutlineBuilder extends StackListenerImpl {
assert(formals.isNotEmpty);
if (formals.length == 2) {
// The name may be null for generalized function types.
// ignore: unnecessary_null_comparison
if (formals[0].name != null && formals[0].name == formals[1].name) {
if (formals[0].name != FormalParameterBuilder.noNameSentinel &&
formals[0].name == formals[1].name) {
addProblem(
templateDuplicatedParameterName.withArguments(formals[1].name),
formals[1].charOffset,
@ -1574,8 +1583,7 @@ class OutlineBuilder extends StackListenerImpl {
Map<String, FormalParameterBuilder> seenNames =
<String, FormalParameterBuilder>{};
for (FormalParameterBuilder formal in formals) {
// ignore: unnecessary_null_comparison
if (formal.name == null) continue;
if (formal.name == FormalParameterBuilder.noNameSentinel) continue;
if (seenNames.containsKey(formal.name)) {
addProblem(
templateDuplicatedParameterName.withArguments(formal.name),
@ -1877,7 +1885,7 @@ class OutlineBuilder extends StackListenerImpl {
bool isParserRecovery = false;
for (int i = count - 1; i != -1; i--) {
int charEndOffset = popCharOffset();
Token beforeLast = pop() as Token;
Token? beforeLast = pop() as Token?;
Token? initializerTokenForInference = pop() as Token?;
int charOffset = popCharOffset();
Object? name = pop(NullValue.Identifier);
@ -1909,7 +1917,8 @@ class OutlineBuilder extends StackListenerImpl {
void handleTypeVariablesDefined(Token token, int count) {
debugEvent("TypeVariablesDefined");
assert(count > 0);
push(const FixedNullableList<TypeVariableBuilder>().pop(stack, count) ??
push(const FixedNullableList<TypeVariableBuilder>()
.popNonNullable(stack, count, dummyTypeVariableBuilder) ??
NullValue.TypeVariables);
}

View file

@ -803,7 +803,7 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
if (startToken != null) {
// Extract only the tokens for the initializer expression from the
// token stream.
Token endToken = info.beforeLast;
Token endToken = info.beforeLast!;
endToken.setNext(new Token.eof(endToken.next!.offset));
new Token.eof(startToken.previous!.offset).setNext(startToken);
}
@ -4241,12 +4241,11 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
Builder? declaration = iterator.current;
while (declaration != null) {
if (declaration is SourceTypeAliasBuilder) {
declaration.buildTypedefTearOffs(this,
(Procedure procedure) {
procedure.isStatic = true;
if (!declaration!.isPatch && !declaration.isDuplicate) {
library.addProcedure(procedure);
}
declaration.buildTypedefTearOffs(this, (Procedure procedure) {
procedure.isStatic = true;
if (!declaration!.isPatch && !declaration.isDuplicate) {
library.addProcedure(procedure);
}
});
}
declaration = declaration.next;
@ -4523,7 +4522,7 @@ class FieldInfo {
final String name;
final int charOffset;
final Token? initializerToken;
final Token beforeLast;
final Token? beforeLast;
final int charEndOffset;
const FieldInfo(this.name, this.charOffset, this.initializerToken,

View file

@ -25,8 +25,8 @@ class BinaryPrinter implements Visitor<void>, BinarySink {
final ConstantIndexer _constantIndexer;
final UriIndexer _sourceUriIndexer = new UriIndexer();
bool _currentlyInNonimplementation = false;
final List<bool> _sourcesFromRealImplementation = <bool>[];
final List<bool> _sourcesUsedInLibrary = <bool>[];
final List<bool?> _sourcesFromRealImplementation = <bool?>[];
final List<bool?> _sourcesUsedInLibrary = <bool?>[];
Map<LibraryDependency, int> _libraryDependencyIndex =
<LibraryDependency, int>{};
NonNullableByDefaultCompiledMode? compilationMode;

View file

@ -1722,6 +1722,8 @@ class ClassSet extends IterableBase<Class> {
/// are removed first; in the case of ties, classes with lower topological sort
/// index are removed first.
class _LubHeap extends Heap<_ClassInfo> {
_LubHeap() : super(_dummyClassInfo);
@override
bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b);
@ -1731,3 +1733,5 @@ class _LubHeap extends Heap<_ClassInfo> {
return a.topologicalIndex < b.topologicalIndex;
}
}
final _ClassInfo _dummyClassInfo = new _ClassInfo(dummyClass);

View file

@ -5,6 +5,9 @@
/// Basic implementation of a heap, with O(log n) insertion and removal.
abstract class Heap<T> {
final _items = <T>[];
final T _dummyValue;
Heap(this._dummyValue);
bool get isEmpty => _items.isEmpty;
@ -12,7 +15,7 @@ abstract class Heap<T> {
void add(T item) {
int index = _items.length;
_items.length += 1;
_items.add(_dummyValue);
while (index > 0) {
T parent = _items[_parentIndex(index)];
if (sortsBefore(parent, item)) break;

View file

@ -36,5 +36,7 @@ main() {
}
class _intHeap extends Heap<int> {
_intHeap() : super(0);
bool sortsBefore(int a, int b) => a < b;
}