[cfe][InternalNodes] Separate Variable from InternalVariable
This adds an InternalLegacyVariable the doesn't derive from LegacyVariable. This fully separates InternalVariable from Variable and assigned variable tracking and flow analysis is now changed to used InternalVariable instead. TEST=existing Change-Id: Ida9dc78d4f0e3fab3baf7a965273e1ddf68a80b8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/510341 Reviewed-by: Chloe Stefantsova <cstefantsova@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
680f6e24d7
commit
c390eb0931
@@ -91,6 +91,7 @@ import '../dill/dill_loader.dart' show DillLoader;
|
||||
import '../dill/dill_target.dart' show DillTarget;
|
||||
import '../kernel/benchmarker.dart' show BenchmarkPhases, Benchmarker;
|
||||
import '../kernel/dart_scope_calculator.dart' show DartScope, DartScopeBuilder2;
|
||||
import '../kernel/external_ast_helper.dart' as extern;
|
||||
import '../kernel/hierarchy/hierarchy_builder.dart' show ClassHierarchyBuilder;
|
||||
import '../kernel/internal_ast.dart'
|
||||
show InternalVariableGet, InternalVariableSet, InternalVariable;
|
||||
@@ -2228,7 +2229,7 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
|
||||
MemoryFileSystem fs = hfs.memory;
|
||||
fs.entityForUri(debugExprUri).writeAsStringSync(expression);
|
||||
|
||||
InternalVariable? extensionThis;
|
||||
Variable? extensionThis;
|
||||
|
||||
// TODO: pass variable declarations instead of
|
||||
// parameter names for proper location detection.
|
||||
@@ -2239,13 +2240,18 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
|
||||
positionalParameters: usedDefinitions.entries.map<Variable>((
|
||||
MapEntry<String, DartType> def,
|
||||
) {
|
||||
InternalVariable variable = intern.createPositionalParameter(
|
||||
isClosureContextLoweringEnabled:
|
||||
lastGoodKernelTarget.loader.isClosureContextLoweringEnabled,
|
||||
cosmeticName: def.key,
|
||||
type: def.value,
|
||||
fileOffset: offsetToUse ?? libraryBuilder.library.fileOffset,
|
||||
);
|
||||
Variable variable =
|
||||
lastGoodKernelTarget.loader.isClosureContextLoweringEnabled
|
||||
? extern.createPositionalParameter(
|
||||
cosmeticName: def.key,
|
||||
type: def.value,
|
||||
fileOffset: offsetToUse ?? libraryBuilder.library.fileOffset,
|
||||
)
|
||||
: extern.createLegacyVariable(
|
||||
name: def.key,
|
||||
type: def.value,
|
||||
fileOffset: offsetToUse ?? libraryBuilder.library.fileOffset,
|
||||
);
|
||||
|
||||
if (isExtensionOrExtensionTypeInstanceMember &&
|
||||
isExtensionThisName(def.key) &&
|
||||
@@ -2253,7 +2259,7 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
|
||||
// The `#this` variable is special.
|
||||
extensionThis = variable..isLowered = true;
|
||||
}
|
||||
return variable.astVariable;
|
||||
return variable;
|
||||
}).toList(),
|
||||
);
|
||||
|
||||
|
||||
@@ -422,7 +422,7 @@ class FormalParameterBuilder extends NamedBuilderImpl
|
||||
declaredType: variable.type,
|
||||
hasDeclaredInitializer: hasDeclaredInitializer,
|
||||
);
|
||||
variable.initializer = initializer..parent = variable;
|
||||
variable.initializer = initializer..parent = variable.astVariable;
|
||||
if (initializer is InvalidExpression) {
|
||||
variable.isErroneouslyInitialized = true;
|
||||
}
|
||||
@@ -430,7 +430,7 @@ class FormalParameterBuilder extends NamedBuilderImpl
|
||||
} else if (kind.isOptional) {
|
||||
// As done by BodyBuilder.endFormalParameter.
|
||||
variable.initializer = extern.createNullLiteral(fileOffset: fileOffset)
|
||||
..parent = variable;
|
||||
..parent = variable.astVariable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import '../../kernel/body_builder_context.dart';
|
||||
import '../../kernel/hierarchy/class_member.dart';
|
||||
import '../../kernel/hierarchy/members_builder.dart';
|
||||
import '../../kernel/implicit_field_type.dart';
|
||||
import '../../kernel/internal_ast.dart';
|
||||
import '../../kernel/late_lowering.dart' as late_lowering;
|
||||
import '../../kernel/macro/metadata.dart';
|
||||
import '../../kernel/type_algorithms.dart';
|
||||
@@ -947,7 +948,7 @@ abstract class FieldFragmentDeclaration {
|
||||
required CoreTypes coreTypes,
|
||||
required Uri fileUri,
|
||||
Expression? initializer,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
});
|
||||
|
||||
BodyBuilderContext createBodyBuilderContext();
|
||||
@@ -1003,7 +1004,7 @@ mixin FieldFragmentDeclarationMixin implements FieldFragmentDeclaration {
|
||||
required CoreTypes coreTypes,
|
||||
required Uri fileUri,
|
||||
Expression? initializer,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) {
|
||||
if (_fieldInitializerCache != null) {
|
||||
if (!hasBodyBeenBuilt) {
|
||||
|
||||
@@ -6,10 +6,13 @@ import 'package:_fe_analyzer_shared/src/type_inference/assigned_variables.dart';
|
||||
import 'package:_fe_analyzer_shared/src/type_inference/promotion_key_store.dart';
|
||||
import 'package:kernel/ast.dart';
|
||||
|
||||
class AssignedVariablesImpl implements AssignedVariables<TreeNode, Variable> {
|
||||
final AssignedVariables<TreeNode, Variable> _delegate;
|
||||
final AssignedVariables<TreeNode, Variable>? _insideAsserts;
|
||||
final AssignedVariables<TreeNode, Variable>? _outsideAsserts;
|
||||
import 'internal_ast.dart';
|
||||
|
||||
class AssignedVariablesImpl
|
||||
implements AssignedVariables<TreeNode, InternalVariable> {
|
||||
final AssignedVariables<TreeNode, InternalVariable> _delegate;
|
||||
final AssignedVariables<TreeNode, InternalVariable>? _insideAsserts;
|
||||
final AssignedVariables<TreeNode, InternalVariable>? _outsideAsserts;
|
||||
int _assertDepth = 0;
|
||||
final Map<AssignedVariablesNodeInfo, AssignedVariablesNodeInfo>?
|
||||
_deferredInsideAssertsByDeferredDelegate;
|
||||
@@ -18,10 +21,10 @@ class AssignedVariablesImpl implements AssignedVariables<TreeNode, Variable> {
|
||||
|
||||
new(this._delegate, {required bool isClosureContextLoweringEnabled})
|
||||
: _insideAsserts = isClosureContextLoweringEnabled
|
||||
? new AssignedVariables<TreeNode, Variable>()
|
||||
? new AssignedVariables<TreeNode, InternalVariable>()
|
||||
: null,
|
||||
_outsideAsserts = isClosureContextLoweringEnabled
|
||||
? new AssignedVariables<TreeNode, Variable>()
|
||||
? new AssignedVariables<TreeNode, InternalVariable>()
|
||||
: null,
|
||||
_deferredInsideAssertsByDeferredDelegate = isClosureContextLoweringEnabled
|
||||
? new Map<
|
||||
@@ -68,7 +71,7 @@ class AssignedVariablesImpl implements AssignedVariables<TreeNode, Variable> {
|
||||
}
|
||||
|
||||
@override
|
||||
void declare(Variable variable, {bool ignoreDuplicates = false}) {
|
||||
void declare(InternalVariable variable, {bool ignoreDuplicates = false}) {
|
||||
_delegate.declare(variable, ignoreDuplicates: ignoreDuplicates);
|
||||
_insideAsserts?.declare(variable, ignoreDuplicates: ignoreDuplicates);
|
||||
_outsideAsserts?.declare(variable, ignoreDuplicates: ignoreDuplicates);
|
||||
@@ -149,7 +152,7 @@ class AssignedVariablesImpl implements AssignedVariables<TreeNode, Variable> {
|
||||
}
|
||||
|
||||
@override
|
||||
PromotionKeyStore<Variable> get promotionKeyStore {
|
||||
PromotionKeyStore<InternalVariable> get promotionKeyStore {
|
||||
return _delegate.promotionKeyStore;
|
||||
}
|
||||
|
||||
@@ -161,7 +164,7 @@ class AssignedVariablesImpl implements AssignedVariables<TreeNode, Variable> {
|
||||
}
|
||||
|
||||
@override
|
||||
void read(Variable variable) {
|
||||
void read(InternalVariable variable) {
|
||||
_delegate.read(variable);
|
||||
if (_isInsideAssert) {
|
||||
_insideAsserts?.read(variable);
|
||||
@@ -199,7 +202,7 @@ class AssignedVariablesImpl implements AssignedVariables<TreeNode, Variable> {
|
||||
}
|
||||
|
||||
@override
|
||||
void write(Variable variable) {
|
||||
void write(InternalVariable variable) {
|
||||
_delegate.write(variable);
|
||||
if (_isInsideAssert) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
|
||||
@@ -337,7 +337,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
/// If the current member is an instance member of a non-extension
|
||||
/// declaration, and the closure context lowering experiment is enabled, this
|
||||
/// field contains the variable representing `this`.
|
||||
ThisVariable? _internalThisVariable;
|
||||
InternalThisVariable? _internalThisVariable;
|
||||
|
||||
final List<TypeParameter>? thisTypeParameters;
|
||||
|
||||
@@ -370,7 +370,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
required this.typeEnvironment,
|
||||
required ConstantContext constantContext,
|
||||
required this.extensionScope,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) : _context = context,
|
||||
benchmarker = libraryBuilder.loader.target.benchmarker,
|
||||
_localScopes = new LocalStack([enclosingScope]),
|
||||
@@ -380,13 +380,13 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
this.constantContext = constantContext;
|
||||
if (formalParameterScope != null) {
|
||||
for (VariableBuilder builder in formalParameterScope!.localVariables) {
|
||||
assignedVariables.declare(builder.variable.astVariable);
|
||||
assignedVariables.declare(builder.variable);
|
||||
}
|
||||
}
|
||||
if (thisVariable != null && context.isConstructor) {
|
||||
// The this variable is not part of the [formalParameterScope] in
|
||||
// constructors.
|
||||
assignedVariables.declare(thisVariable.astVariable);
|
||||
assignedVariables.declare(thisVariable);
|
||||
}
|
||||
if (isClosureContextLoweringEnabled && _internalThisVariable != null) {
|
||||
assignedVariables.declare(_internalThisVariable!);
|
||||
@@ -623,7 +623,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
// when [InferenceVisitorBase.flowAnalysis] will use
|
||||
// [InternalExpressionVariable] instead of [ExpressionVariable] (that is,
|
||||
// pass it for the `VariableDeclaration` type parameter of [FlowAnalysis]).
|
||||
assignedVariables.write(variable.astVariable);
|
||||
assignedVariables.write(variable);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -632,7 +632,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
expression,
|
||||
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
|
||||
);
|
||||
assignedVariables.declare(variable.astVariable);
|
||||
assignedVariables.declare(variable);
|
||||
return variable;
|
||||
}
|
||||
|
||||
@@ -1990,7 +1990,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
];
|
||||
for (InternalVariable variable in jointVariables) {
|
||||
declareVariable(variable, _localScope);
|
||||
assignedVariables.declare(variable.astVariable);
|
||||
assignedVariables.declare(variable);
|
||||
}
|
||||
push(
|
||||
intern.createOrPattern(
|
||||
@@ -2495,7 +2495,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
@override
|
||||
void registerVariableRead(InternalVariable variable) {
|
||||
if (!variable.isLocalFunction && !variable.isWildcard) {
|
||||
assignedVariables.read(variable.astVariable);
|
||||
assignedVariables.read(variable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3424,7 +3424,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
internalVariable,
|
||||
fileOffset: offsetForToken(equalsToken),
|
||||
);
|
||||
assignedVariables.declare(internalVariable.astVariable);
|
||||
assignedVariables.declare(internalVariable);
|
||||
push(variableDeclaration);
|
||||
}
|
||||
|
||||
@@ -3441,7 +3441,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
if (parameters != null) {
|
||||
Map<String, VariableBuilder> local = {};
|
||||
for (FormalParameterBuilder formal in parameters) {
|
||||
assignedVariables.declare(formal.variable.astVariable);
|
||||
assignedVariables.declare(formal.variable);
|
||||
local[formal.name] = formal;
|
||||
}
|
||||
_localScopes.push(
|
||||
@@ -3869,7 +3869,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
internalVariables.add(internalVariable);
|
||||
|
||||
declareVariable(internalVariable, _localScope);
|
||||
assignedVariables.declare(internalVariable.astVariable);
|
||||
assignedVariables.declare(internalVariable);
|
||||
}
|
||||
push(intermediateVariables);
|
||||
push(internalVariables);
|
||||
@@ -5550,10 +5550,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
// previously passed to `declare` in the `BodyBuilder` constructor.
|
||||
// TODO(62401): Remove the cast when the flow analysis uses
|
||||
// [InternalExpressionVariable]s.
|
||||
assignedVariables.declare(
|
||||
functionParameter.astVariable,
|
||||
ignoreDuplicates: true,
|
||||
);
|
||||
assignedVariables.declare(functionParameter, ignoreDuplicates: true);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -8071,7 +8068,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
_thisVariables.push(variable);
|
||||
_parameterlessAnonymousMethodDepth++;
|
||||
|
||||
assignedVariables.declare(variable.astVariable);
|
||||
assignedVariables.declare(variable);
|
||||
push(NullValues.FormalParameters);
|
||||
}
|
||||
|
||||
@@ -9032,7 +9029,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
for (InternalVariable jointVariable in jointPatternVariables) {
|
||||
assert(_localScope.kind == LocalScopeKind.jointVariables);
|
||||
declareVariable(jointVariable, _localScope);
|
||||
assignedVariables.declare(jointVariable.astVariable);
|
||||
assignedVariables.declare(jointVariable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11104,7 +11101,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
declaredVariable,
|
||||
);
|
||||
declareVariable(declaredVariable, _localScope);
|
||||
assignedVariables.declare(declaredVariable.astVariable);
|
||||
assignedVariables.declare(declaredVariable);
|
||||
}
|
||||
push(pattern);
|
||||
}
|
||||
@@ -11496,10 +11493,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
for (FormalParameterBuilder formal in formals) {
|
||||
// We pass `ignoreDuplicates: true` because the variable might have been
|
||||
// previously passed to `declare` in the `BodyBuilder` constructor.
|
||||
assignedVariables.declare(
|
||||
formal.variable.astVariable,
|
||||
ignoreDuplicates: true,
|
||||
);
|
||||
assignedVariables.declare(formal.variable, ignoreDuplicates: true);
|
||||
}
|
||||
}
|
||||
token = parser.parseInitializersOpt(token);
|
||||
@@ -11648,7 +11642,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
|
||||
if (formals != null) {
|
||||
for (FormalParameterBuilder formalParameterBuilder in formals) {
|
||||
assignedVariables.declare(formalParameterBuilder.variable.astVariable);
|
||||
assignedVariables.declare(formalParameterBuilder.variable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11674,7 +11668,7 @@ class BodyBuilderImpl extends StackListenerImpl
|
||||
enterLocalScope(extraKnownVariablesScope);
|
||||
for (InternalVariable extraVariable in extraKnownVariables) {
|
||||
declareVariable(extraVariable, _localScope);
|
||||
assignedVariables.declare(extraVariable.astVariable);
|
||||
assignedVariables.declare(extraVariable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -401,7 +401,7 @@ abstract class BodyBuilderContext {
|
||||
/// Declarations with synthesized `this`, such as extensions and extension
|
||||
/// types, don't have an internal [ThisVariable] because `this` is desugared
|
||||
/// as a parameter in that case.
|
||||
ThisVariable? createInternalThisVariable() {
|
||||
InternalThisVariable? createInternalThisVariable() {
|
||||
return thisType != null && isDeclarationInstanceContext
|
||||
? intern.createThisVariable(
|
||||
type: thisType!,
|
||||
|
||||
@@ -109,12 +109,14 @@ AssertStatement createAssertStatement(
|
||||
|
||||
AssignedVariablePattern createAssignedVariablePattern({
|
||||
required Variable variable,
|
||||
required Variable? setter,
|
||||
required DartType matchedValueType,
|
||||
required bool needsCast,
|
||||
required bool hasObservableEffect,
|
||||
required int fileOffset,
|
||||
}) {
|
||||
return new AssignedVariablePattern(variable)
|
||||
..setter = setter
|
||||
..matchedValueType = matchedValueType
|
||||
..needsCast = needsCast
|
||||
..hasObservableEffect = hasObservableEffect
|
||||
@@ -601,6 +603,44 @@ LateVariable createLateVariable({
|
||||
)..fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
LegacyVariable createLegacyVariable({
|
||||
required String? name,
|
||||
required DartType type,
|
||||
bool isFinal = false,
|
||||
bool isConst = false,
|
||||
bool isWildcard = false,
|
||||
bool isLate = false,
|
||||
bool isInitializingFormal = false,
|
||||
bool isSuperInitializingFormal = false,
|
||||
bool isCovariantByDeclaration = false,
|
||||
bool isRequired = false,
|
||||
bool isLowered = false,
|
||||
bool isSynthesized = false,
|
||||
required int fileOffset,
|
||||
int fileEqualsOffset = TreeNode.noOffset,
|
||||
Expression? initializer,
|
||||
bool hasDeclaredInitializer = false,
|
||||
}) {
|
||||
return new LegacyVariable(
|
||||
name,
|
||||
type: type,
|
||||
isFinal: isFinal,
|
||||
isConst: isConst,
|
||||
isLate: isLate,
|
||||
isWildcard: isWildcard,
|
||||
isInitializingFormal: isInitializingFormal,
|
||||
isSuperInitializingFormal: isSuperInitializingFormal,
|
||||
isCovariantByDeclaration: isCovariantByDeclaration,
|
||||
isRequired: isRequired,
|
||||
isLowered: isLowered,
|
||||
isSynthesized: isSynthesized,
|
||||
initializer: initializer,
|
||||
hasDeclaredInitializer: hasDeclaredInitializer,
|
||||
)
|
||||
..fileOffset = fileOffset
|
||||
..fileEqualsOffset = fileEqualsOffset;
|
||||
}
|
||||
|
||||
/// Creates a [Let] of [variable] with the given [body] using
|
||||
/// `variable.fileOffset` as the file offset for the let.
|
||||
Let createLet(Variable variable, Expression body, {int? fileOffset}) {
|
||||
@@ -1326,9 +1366,10 @@ Expression createVariableSet(
|
||||
bool allowFinalAssignment = false,
|
||||
required int fileOffset,
|
||||
}) {
|
||||
if (variable is VariableDeclarationImpl && variable.lateSetter != null) {
|
||||
// TODO(johnniwinther):
|
||||
if (variable.parent is FunctionDeclaration) {
|
||||
return createLocalFunctionInvocation(
|
||||
variable.lateSetter!,
|
||||
variable,
|
||||
arguments: createArguments([value], fileOffset: fileOffset),
|
||||
fileOffset: fileOffset,
|
||||
);
|
||||
|
||||
@@ -21,7 +21,6 @@ library;
|
||||
|
||||
import 'package:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart'
|
||||
as shared;
|
||||
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/names.dart';
|
||||
import 'package:kernel/src/printer.dart';
|
||||
@@ -41,7 +40,12 @@ import 'external_ast_helper.dart' as extern;
|
||||
/// @docImport 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
|
||||
|
||||
typedef SharedMatchContext =
|
||||
shared.MatchContext<TreeNode, Expression, InternalPattern, Variable>;
|
||||
shared.MatchContext<
|
||||
TreeNode,
|
||||
Expression,
|
||||
InternalPattern,
|
||||
InternalVariable
|
||||
>;
|
||||
|
||||
mixin InternalTreeNode implements TreeNode {
|
||||
@override
|
||||
@@ -1150,11 +1154,11 @@ class ReturnStatementImpl extends ReturnStatement {
|
||||
}
|
||||
|
||||
/// Front end specific implementation of [Variable].
|
||||
class VariableDeclarationImpl extends LegacyVariable
|
||||
with InternalVariableMixin
|
||||
implements InternalVariable {
|
||||
class InternalLegacyVariable extends TreeNode
|
||||
with InternalVariableMixin, DelegatingVariableMixin
|
||||
implements LegacyVariable, InternalVariable {
|
||||
@override
|
||||
Variable get astVariable => this;
|
||||
final Variable astVariable;
|
||||
|
||||
@override
|
||||
final bool forSyntheticToken;
|
||||
@@ -1165,69 +1169,22 @@ class VariableDeclarationImpl extends LegacyVariable
|
||||
@override
|
||||
final bool isLocalFunction;
|
||||
|
||||
new(
|
||||
String? name, {
|
||||
new({
|
||||
required this.astVariable,
|
||||
this.forSyntheticToken = false,
|
||||
bool hasDeclaredInitializer = false,
|
||||
Expression? initializer,
|
||||
DartType? type,
|
||||
bool isFinal = false,
|
||||
bool isConst = false,
|
||||
bool isInitializingFormal = false,
|
||||
bool isSuperInitializingFormal = false,
|
||||
bool isCovariantByDeclaration = false,
|
||||
this.isImplicitlyTyped = false,
|
||||
bool isLocalFunction = false,
|
||||
bool isLate = false,
|
||||
bool isRequired = false,
|
||||
bool isLowered = false,
|
||||
bool isSynthesized = false,
|
||||
bool isStaticLate = false,
|
||||
bool isWildcard = false,
|
||||
bool isLateFinalWithoutInitializer = false,
|
||||
required int fileOffset,
|
||||
int fileEqualsOffset = TreeNode.noOffset,
|
||||
}) : isImplicitlyTyped = type == null,
|
||||
isLocalFunction = isLocalFunction,
|
||||
super(
|
||||
name,
|
||||
initializer: initializer,
|
||||
type: type ?? const DynamicType(),
|
||||
isFinal: isFinal,
|
||||
isConst: isConst,
|
||||
isInitializingFormal: isInitializingFormal,
|
||||
isSuperInitializingFormal: isSuperInitializingFormal,
|
||||
isCovariantByDeclaration: isCovariantByDeclaration,
|
||||
isLate: isLate,
|
||||
isRequired: isRequired,
|
||||
isLowered: isLowered,
|
||||
isSynthesized: isSynthesized,
|
||||
hasDeclaredInitializer: hasDeclaredInitializer,
|
||||
isWildcard: isWildcard,
|
||||
) {
|
||||
}) : isLocalFunction = isLocalFunction {
|
||||
this.isStaticLate = isStaticLate;
|
||||
this.isLateFinalWithoutInitializer = isLateFinalWithoutInitializer;
|
||||
this.fileOffset = fileOffset;
|
||||
this.fileEqualsOffset = fileEqualsOffset;
|
||||
}
|
||||
|
||||
// Coverage-ignore(suite): Not run.
|
||||
new forEffect(Expression initializer)
|
||||
: forSyntheticToken = false,
|
||||
isImplicitlyTyped = false,
|
||||
isLocalFunction = false,
|
||||
super.forValue(initializer) {
|
||||
isStaticLate = false;
|
||||
}
|
||||
|
||||
// Coverage-ignore(suite): Not run.
|
||||
new forValue(Expression initializer)
|
||||
: forSyntheticToken = false,
|
||||
isImplicitlyTyped = true,
|
||||
isLocalFunction = false,
|
||||
super.forValue(initializer) {
|
||||
isStaticLate = false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isAssignable {
|
||||
if (isStaticLate) return true;
|
||||
@@ -1240,13 +1197,14 @@ class VariableDeclarationImpl extends LegacyVariable
|
||||
printer.writeVariableInitialization(
|
||||
this,
|
||||
isLate: isLate || lateGetter != null,
|
||||
isImplicitlyTyped: isImplicitlyTyped,
|
||||
type: lateType ?? type,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "VariableDeclarationImpl(${toStringInternal()})";
|
||||
return "$runtimeType(${toStringInternal()})";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1775,7 +1733,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
String? get cosmeticName => astVariable.cosmeticName;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
TreeNode? get parent => astVariable.parent;
|
||||
|
||||
@override
|
||||
@@ -1793,13 +1750,11 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void addAnnotation(Expression node) {
|
||||
astVariable.addAnnotation(node);
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set cosmeticName(String? value) {
|
||||
astVariable.cosmeticName = value;
|
||||
}
|
||||
@@ -1824,7 +1779,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
bool get isConst => astVariable.isConst;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set isConst(bool value) {
|
||||
astVariable.isConst = value;
|
||||
}
|
||||
@@ -1850,11 +1804,9 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bool get isErroneouslyInitialized => astVariable.isErroneouslyInitialized;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set isErroneouslyInitialized(bool value) {
|
||||
astVariable.isErroneouslyInitialized = value;
|
||||
}
|
||||
@@ -1863,7 +1815,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
bool get isFinal => astVariable.isFinal;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set isFinal(bool value) {
|
||||
astVariable.isFinal = value;
|
||||
}
|
||||
@@ -1901,7 +1852,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
bool get isLowered => astVariable.isLowered;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set isLowered(bool value) {
|
||||
astVariable.isLowered = value;
|
||||
}
|
||||
@@ -1926,7 +1876,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bool get isSynthesized => astVariable.isSynthesized;
|
||||
|
||||
@override
|
||||
@@ -2158,13 +2107,11 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
int get fileEqualsOffset => astVariable.fileEqualsOffset;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void set fileEqualsOffset(int value) {
|
||||
astVariable.fileEqualsOffset = value;
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
Variable get variable => astVariable.variable;
|
||||
|
||||
@override
|
||||
@@ -2174,7 +2121,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
|
||||
}
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void clearAnnotations() {
|
||||
astVariable.clearAnnotations();
|
||||
}
|
||||
@@ -5938,6 +5884,8 @@ sealed class InternalForInElement {
|
||||
|
||||
/// Base implementation for non-pattern for-in elements.
|
||||
sealed class _BaseForInElement extends InternalForInElement {
|
||||
InternalVariable? get _declaredVariable => null;
|
||||
|
||||
/// Computes the type context from the element. This is type context used for
|
||||
/// inferring the for-in iterable.
|
||||
DartType _computeElementTypeContext(InferenceVisitorBase visitor);
|
||||
@@ -6004,6 +5952,7 @@ sealed class _BaseForInElement extends InternalForInElement {
|
||||
);
|
||||
|
||||
return new ForInHeaderResult(
|
||||
declaredVariable: _declaredVariable,
|
||||
loopVariable: variable,
|
||||
iterable: iterableResult.expression,
|
||||
computeEncoding: () => _computeEncoding(visitor, loopVariable: variable),
|
||||
@@ -6028,6 +5977,9 @@ class SingleVariableDeclarationForInElement extends _BaseForInElement {
|
||||
|
||||
new({required this.variableDeclaration, required this.error});
|
||||
|
||||
@override
|
||||
InternalVariable get _declaredVariable => variableDeclaration.variable;
|
||||
|
||||
@override
|
||||
Variable _computeLoopVariable(
|
||||
InferenceVisitorBase visitor,
|
||||
@@ -6035,6 +5987,7 @@ class SingleVariableDeclarationForInElement extends _BaseForInElement {
|
||||
required int forOffset,
|
||||
required bool isClosureContextLoweringEnabled,
|
||||
}) {
|
||||
//InternalVariable internalLoopVariable = variableDeclaration.variable;
|
||||
Variable loopVariable = variableDeclaration.variable.astVariable;
|
||||
DartType loopVariableType;
|
||||
bool checkAssignment = true;
|
||||
@@ -6070,11 +6023,11 @@ class SingleVariableDeclarationForInElement extends _BaseForInElement {
|
||||
// and assign to the declared variable in the loop.
|
||||
loopVariable.initializer = assignmentResult.expression
|
||||
..parent = loopVariable;
|
||||
visitor.flowAnalysis.declare(
|
||||
loopVariable,
|
||||
new SharedTypeView(loopVariableType),
|
||||
initialized: true,
|
||||
);
|
||||
// visitor.flowAnalysis.declare(
|
||||
// internalLoopVariable,
|
||||
// new SharedTypeView(loopVariableType),
|
||||
// initialized: true,
|
||||
// );
|
||||
_variableForSideEffect = extern.createVariableDeclaration(loopVariable);
|
||||
loopVariable = tempVariable;
|
||||
}
|
||||
@@ -6267,6 +6220,7 @@ class PatternForInElement extends InternalForInElement {
|
||||
inOffset: inOffset,
|
||||
);
|
||||
return new ForInHeaderResult(
|
||||
declaredVariable: null,
|
||||
loopVariable: data.loopVariable,
|
||||
iterable: data.iterable,
|
||||
computeEncoding: () => new ForInEncoding(
|
||||
@@ -6362,7 +6316,7 @@ class ExistingVariableForInElement extends _BaseForInElement {
|
||||
@override
|
||||
DartType _computeElementTypeContext(InferenceVisitorBase visitor) {
|
||||
DartType? promotedType = visitor.flowAnalysis
|
||||
.promotedType(variable.astVariable)
|
||||
.promotedType(variable)
|
||||
?.unwrapTypeView();
|
||||
return promotedType ?? variable.type;
|
||||
}
|
||||
@@ -6668,6 +6622,9 @@ class ForInEncoding {
|
||||
|
||||
/// The result of inferring a for-in loop element and iterable.
|
||||
class ForInHeaderResult {
|
||||
/// The [InternalVariable] declared in the for-in statement, if any.
|
||||
final InternalVariable? declaredVariable;
|
||||
|
||||
/// The [Variable] that should be used as the variable in the
|
||||
/// emitted [ForInStatement].
|
||||
final Variable loopVariable;
|
||||
@@ -6684,6 +6641,7 @@ class ForInHeaderResult {
|
||||
final ForInEncoding Function() computeEncoding;
|
||||
|
||||
new({
|
||||
required this.declaredVariable,
|
||||
required this.loopVariable,
|
||||
required this.iterable,
|
||||
required this.computeEncoding,
|
||||
@@ -8459,6 +8417,43 @@ class InternalLet extends InternalExpression {
|
||||
}
|
||||
}
|
||||
|
||||
class InternalThisVariable extends TreeNode
|
||||
with InternalVariableMixin, DelegatingVariableMixin
|
||||
implements ThisVariable, InternalVariable {
|
||||
@override
|
||||
final ThisVariable astVariable;
|
||||
|
||||
new({required this.astVariable, required int fileOffset}) {
|
||||
this.fileOffset = fileOffset;
|
||||
}
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
String get cosmeticName => astVariable.cosmeticName;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bool get forSyntheticToken => false;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bool get isImplicitlyTyped => false;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
bool get isLocalFunction => false;
|
||||
|
||||
@override
|
||||
// Coverage-ignore(suite): Not run.
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.write('this');
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$runtimeType(${toStringInternal()})";
|
||||
}
|
||||
}
|
||||
|
||||
final InternalPattern dummyInternalPattern = new InternalConstantPattern(
|
||||
expression: dummyExpression,
|
||||
fileOffset: TreeNode.noOffset,
|
||||
@@ -8495,10 +8490,9 @@ final InternalCatch dummyInternalCatch = new InternalCatch(
|
||||
fileOffset: TreeNode.noOffset,
|
||||
);
|
||||
|
||||
final InternalVariable dummyInternalVariable = new VariableDeclarationImpl(
|
||||
null,
|
||||
final InternalVariable dummyInternalVariable = new InternalLegacyVariable(
|
||||
astVariable: dummyVariable,
|
||||
fileOffset: TreeNode.noOffset,
|
||||
isSynthesized: true,
|
||||
);
|
||||
|
||||
final InternalVariableDeclaration dummyInternalVariableDeclaration =
|
||||
|
||||
@@ -211,13 +211,16 @@ InternalVariable createCatchVariable({
|
||||
fileOffset: fileOffset,
|
||||
);
|
||||
} else {
|
||||
return new VariableDeclarationImpl(
|
||||
name,
|
||||
return new InternalLegacyVariable(
|
||||
astVariable: extern.createLegacyVariable(
|
||||
name: name,
|
||||
type: type,
|
||||
isWildcard: isWildcard,
|
||||
isFinal: isFinal,
|
||||
fileOffset: fileOffset,
|
||||
),
|
||||
fileOffset: fileOffset,
|
||||
// [VariableDeclarationImpl] uses `null` to signal an omitted type.
|
||||
type: isImplicitlyTyped ? null : type,
|
||||
isWildcard: isWildcard,
|
||||
isFinal: isFinal,
|
||||
isImplicitlyTyped: isImplicitlyTyped,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -677,19 +680,24 @@ InternalVariable createLateVariable({
|
||||
fileOffset: fileOffset,
|
||||
);
|
||||
} else {
|
||||
return new VariableDeclarationImpl(
|
||||
name,
|
||||
return new InternalLegacyVariable(
|
||||
astVariable: extern.createLegacyVariable(
|
||||
name: name,
|
||||
fileOffset: fileOffset,
|
||||
hasDeclaredInitializer: hasDeclaredInitializer,
|
||||
initializer: initializer,
|
||||
type: type ?? const DynamicType(),
|
||||
isFinal: isFinal,
|
||||
isConst: isConst,
|
||||
isLate: true,
|
||||
isWildcard: isWildcard,
|
||||
fileEqualsOffset: fileEqualsOffset,
|
||||
),
|
||||
fileOffset: fileOffset,
|
||||
forSyntheticToken: forSyntheticToken,
|
||||
hasDeclaredInitializer: hasDeclaredInitializer,
|
||||
initializer: initializer,
|
||||
type: type,
|
||||
isFinal: isFinal,
|
||||
isConst: isConst,
|
||||
isLate: true,
|
||||
isStaticLate: isStaticLate,
|
||||
isWildcard: isWildcard,
|
||||
fileEqualsOffset: fileEqualsOffset,
|
||||
isImplicitlyTyped: isImplicitlyTyped,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -785,19 +793,24 @@ InternalVariable createLocalVariable({
|
||||
fileEqualsOffset: fileEqualsOffset,
|
||||
);
|
||||
} else {
|
||||
return new VariableDeclarationImpl(
|
||||
name,
|
||||
return new InternalLegacyVariable(
|
||||
astVariable: extern.createLegacyVariable(
|
||||
name: name,
|
||||
fileOffset: fileOffset,
|
||||
hasDeclaredInitializer: hasDeclaredInitializer,
|
||||
initializer: initializer,
|
||||
type: type ?? const DynamicType(),
|
||||
isFinal: isFinal,
|
||||
isConst: isConst,
|
||||
isWildcard: isWildcard,
|
||||
fileEqualsOffset: fileEqualsOffset,
|
||||
),
|
||||
fileOffset: fileOffset,
|
||||
forSyntheticToken: forSyntheticToken,
|
||||
hasDeclaredInitializer: hasDeclaredInitializer,
|
||||
initializer: initializer,
|
||||
type: type,
|
||||
isFinal: isFinal,
|
||||
isConst: isConst,
|
||||
isLocalFunction: isLocalFunction,
|
||||
isStaticLate: isStaticLate,
|
||||
isWildcard: isWildcard,
|
||||
fileEqualsOffset: fileEqualsOffset,
|
||||
isImplicitlyTyped: isImplicitlyTyped,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -961,22 +974,25 @@ InternalVariable createNamedParameter({
|
||||
fileOffset: fileOffset,
|
||||
);
|
||||
} else {
|
||||
return new VariableDeclarationImpl(
|
||||
parameterName,
|
||||
return new InternalLegacyVariable(
|
||||
astVariable: extern.createLegacyVariable(
|
||||
name: parameterName,
|
||||
fileOffset: fileOffset,
|
||||
hasDeclaredInitializer: hasDeclaredDefaultValue,
|
||||
initializer: defaultValue,
|
||||
type: type,
|
||||
isFinal: isFinal,
|
||||
isInitializingFormal: isInitializingFormal,
|
||||
isSuperInitializingFormal: isSuperInitializingFormal,
|
||||
isCovariantByDeclaration: isCovariantByDeclaration,
|
||||
isRequired: isRequired,
|
||||
isLowered: isLowered,
|
||||
isSynthesized: isSynthesized,
|
||||
isWildcard: isWildcard,
|
||||
),
|
||||
fileOffset: fileOffset,
|
||||
forSyntheticToken: forSyntheticToken,
|
||||
hasDeclaredInitializer: hasDeclaredDefaultValue,
|
||||
initializer: defaultValue,
|
||||
// [VariableDeclarationImpl] uses `null` to signal an omitted type.
|
||||
type: isImplicitlyTyped ? null : type,
|
||||
isFinal: isFinal,
|
||||
isInitializingFormal: isInitializingFormal,
|
||||
isSuperInitializingFormal: isSuperInitializingFormal,
|
||||
isCovariantByDeclaration: isCovariantByDeclaration,
|
||||
isRequired: isRequired,
|
||||
isLowered: isLowered,
|
||||
isSynthesized: isSynthesized,
|
||||
isWildcard: isWildcard,
|
||||
isImplicitlyTyped: isImplicitlyTyped,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1232,23 +1248,25 @@ InternalVariable createPositionalParameter({
|
||||
fileOffset: fileOffset,
|
||||
);
|
||||
} else {
|
||||
return new VariableDeclarationImpl(
|
||||
cosmeticName,
|
||||
return new InternalLegacyVariable(
|
||||
astVariable: extern.createLegacyVariable(
|
||||
name: cosmeticName,
|
||||
fileOffset: fileOffset,
|
||||
hasDeclaredInitializer: hasDeclaredDefaultValue,
|
||||
initializer: defaultValue,
|
||||
type: type,
|
||||
isFinal: isFinal,
|
||||
isInitializingFormal: isInitializingFormal,
|
||||
isSuperInitializingFormal: isSuperInitializingFormal,
|
||||
isCovariantByDeclaration: isCovariantByDeclaration,
|
||||
isRequired: isRequired,
|
||||
isLowered: isLowered,
|
||||
isSynthesized: isSynthesized,
|
||||
isWildcard: isWildcard,
|
||||
),
|
||||
fileOffset: fileOffset,
|
||||
forSyntheticToken: forSyntheticToken,
|
||||
hasDeclaredInitializer: hasDeclaredDefaultValue,
|
||||
initializer: defaultValue,
|
||||
// [VariableDeclarationImpl] uses `null` to signal an omitted
|
||||
// type.
|
||||
type: isImplicitlyTyped ? null : type,
|
||||
isFinal: isFinal,
|
||||
isInitializingFormal: isInitializingFormal,
|
||||
isSuperInitializingFormal: isSuperInitializingFormal,
|
||||
isCovariantByDeclaration: isCovariantByDeclaration,
|
||||
isRequired: isRequired,
|
||||
isLowered: isLowered,
|
||||
isSynthesized: isSynthesized,
|
||||
isWildcard: isWildcard,
|
||||
isImplicitlyTyped: isImplicitlyTyped,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1524,14 +1542,18 @@ InternalVariable createSyntheticVariable({
|
||||
fileOffset: fileOffset,
|
||||
);
|
||||
} else {
|
||||
return new VariableDeclarationImpl(
|
||||
name,
|
||||
type: type,
|
||||
initializer: initializer,
|
||||
isFinal: isFinal,
|
||||
isSynthesized: isSynthesized,
|
||||
hasDeclaredInitializer: initializer != null,
|
||||
return new InternalLegacyVariable(
|
||||
astVariable: extern.createLegacyVariable(
|
||||
name: name,
|
||||
type: type ?? const DynamicType(),
|
||||
initializer: initializer,
|
||||
isFinal: isFinal,
|
||||
isSynthesized: isSynthesized,
|
||||
hasDeclaredInitializer: initializer != null,
|
||||
fileOffset: fileOffset,
|
||||
),
|
||||
fileOffset: fileOffset,
|
||||
isImplicitlyTyped: type == null,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1569,11 +1591,14 @@ Expression createThisExpression({required int fileOffset}) {
|
||||
return new ThisExpression()..fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
ThisVariable createThisVariable({
|
||||
InternalThisVariable createThisVariable({
|
||||
required DartType type,
|
||||
required int fileOffset,
|
||||
}) {
|
||||
return new ThisVariable(type: type)..fileOffset = fileOffset;
|
||||
return new InternalThisVariable(
|
||||
astVariable: new ThisVariable(type: type)..fileOffset = fileOffset,
|
||||
fileOffset: fileOffset,
|
||||
);
|
||||
}
|
||||
|
||||
/// Return a representation of a throw expression at the given [fileOffset].
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
|
||||
show FormalParameterKind;
|
||||
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
|
||||
import 'package:_fe_analyzer_shared/src/type_inference/assigned_variables.dart';
|
||||
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
|
||||
import 'package:front_end/src/codes/diagnostic.dart' as diag;
|
||||
import 'package:kernel/ast.dart';
|
||||
@@ -275,7 +274,7 @@ class Resolver {
|
||||
ConstantContext constantContext = bodyBuilderContext.constantContext;
|
||||
List<FormalParameterBuilder>? primaryConstructorInitializerScopeParameters =
|
||||
bodyBuilderContext.primaryConstructorInitializerScopeParameters;
|
||||
ThisVariable? internalThisVariable = bodyBuilderContext
|
||||
InternalThisVariable? internalThisVariable = bodyBuilderContext
|
||||
.createInternalThisVariable();
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
@@ -404,7 +403,7 @@ class Resolver {
|
||||
functionBodyBuildingContext.inferenceDataForTesting,
|
||||
);
|
||||
ConstantContext constantContext = bodyBuilderContext.constantContext;
|
||||
ThisVariable? internalThisVariable = bodyBuilderContext
|
||||
InternalThisVariable? internalThisVariable = bodyBuilderContext
|
||||
.createInternalThisVariable();
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
@@ -476,7 +475,7 @@ class Resolver {
|
||||
ProblemReporting problemReporting = libraryBuilder;
|
||||
LibraryFeatures libraryFeatures = libraryBuilder.libraryFeatures;
|
||||
ConstantContext constantContext = bodyBuilderContext.constantContext;
|
||||
ThisVariable? internalThisVariable = bodyBuilderContext
|
||||
InternalThisVariable? internalThisVariable = bodyBuilderContext
|
||||
.createInternalThisVariable();
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
@@ -689,7 +688,7 @@ class Resolver {
|
||||
functionBodyBuildingContext.inferenceDataForTesting,
|
||||
);
|
||||
ConstantContext constantContext = bodyBuilderContext.constantContext;
|
||||
ThisVariable? internalThisVariable = bodyBuilderContext
|
||||
InternalThisVariable? internalThisVariable = bodyBuilderContext
|
||||
.createInternalThisVariable();
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
@@ -768,7 +767,7 @@ class Resolver {
|
||||
ProblemReporting problemReporting = libraryBuilder;
|
||||
LibraryFeatures libraryFeatures = libraryBuilder.libraryFeatures;
|
||||
ConstantContext constantContext = bodyBuilderContext.constantContext;
|
||||
ThisVariable? internalThisVariable = bodyBuilderContext
|
||||
InternalThisVariable? internalThisVariable = bodyBuilderContext
|
||||
.createInternalThisVariable();
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
@@ -874,7 +873,7 @@ class Resolver {
|
||||
required Procedure procedure,
|
||||
required List<InternalVariable> extraKnownVariables,
|
||||
required ExpressionEvaluationHelper expressionEvaluationHelper,
|
||||
required InternalVariable? extensionThis,
|
||||
required Variable? extensionThis,
|
||||
}) {
|
||||
_ResolverContext context = new _ResolverContext(
|
||||
typeInferenceEngine: _typeInferenceEngine,
|
||||
@@ -886,42 +885,30 @@ class Resolver {
|
||||
|
||||
LibraryFeatures libraryFeatures = libraryBuilder.libraryFeatures;
|
||||
ConstantContext constantContext = bodyBuilderContext.constantContext;
|
||||
ThisVariable? internalThisVariable = bodyBuilderContext
|
||||
InternalThisVariable? internalThisVariable = bodyBuilderContext
|
||||
.createInternalThisVariable();
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
bodyBuilderContext: bodyBuilderContext,
|
||||
scope: scope,
|
||||
thisVariable: extensionThis,
|
||||
constantContext: constantContext,
|
||||
// TODO(johnniwinther): Should we provide these?
|
||||
thisTypeParameters: null,
|
||||
formalParameterScope: null,
|
||||
internalThisVariable: internalThisVariable,
|
||||
);
|
||||
int fileOffset = token.charOffset;
|
||||
|
||||
FunctionNode parameters = procedure.function;
|
||||
|
||||
List<NominalParameterBuilder>? typeParameterBuilders;
|
||||
for (TypeParameter typeParameter in parameters.typeParameters) {
|
||||
typeParameterBuilders ??= <NominalParameterBuilder>[];
|
||||
typeParameterBuilders.add(
|
||||
new DillNominalParameterBuilder(
|
||||
typeParameter,
|
||||
loader: libraryBuilder.loader,
|
||||
),
|
||||
);
|
||||
}
|
||||
int wildcardVariableIndex = 0;
|
||||
InternalVariable? internalExtensionThis;
|
||||
List<FormalParameterBuilder>? formals =
|
||||
parameters.positionalParameters.length == 0
|
||||
? null
|
||||
: new List<FormalParameterBuilder>.generate(
|
||||
parameters.positionalParameters.length,
|
||||
(int i) {
|
||||
Variable parameter = parameters.positionalParameters[i];
|
||||
InternalVariable formal =
|
||||
parameters.positionalParameters[i] as InternalVariable;
|
||||
libraryBuilder.loader.isClosureContextLoweringEnabled
|
||||
? new InternalPositionalParameter(
|
||||
astVariable: parameter as PositionalParameter,
|
||||
isImplicitlyTyped: false,
|
||||
fileOffset: parameter.fileOffset,
|
||||
)
|
||||
: new InternalLegacyVariable(
|
||||
astVariable: parameter,
|
||||
fileOffset: parameter.fileOffset,
|
||||
);
|
||||
String formalName = formal.cosmeticName!;
|
||||
bool isWildcard =
|
||||
libraryFeatures.wildcardVariables.isEnabled &&
|
||||
@@ -930,6 +917,9 @@ class Resolver {
|
||||
if (isWildcard) {
|
||||
wildcardIndex = wildcardVariableIndex++;
|
||||
}
|
||||
if (parameter == extensionThis) {
|
||||
internalExtensionThis = formal;
|
||||
}
|
||||
return new FormalParameterBuilder(
|
||||
kind: FormalParameterKind.requiredPositional,
|
||||
modifiers: Modifiers.empty,
|
||||
@@ -948,6 +938,30 @@ class Resolver {
|
||||
growable: false,
|
||||
);
|
||||
|
||||
BodyBuilder bodyBuilder = _createBodyBuilder(
|
||||
context: context,
|
||||
bodyBuilderContext: bodyBuilderContext,
|
||||
scope: scope,
|
||||
thisVariable: internalExtensionThis,
|
||||
constantContext: constantContext,
|
||||
// TODO(johnniwinther): Should we provide these?
|
||||
thisTypeParameters: null,
|
||||
formalParameterScope: null,
|
||||
internalThisVariable: internalThisVariable,
|
||||
);
|
||||
int fileOffset = token.charOffset;
|
||||
|
||||
List<NominalParameterBuilder>? typeParameterBuilders;
|
||||
for (TypeParameter typeParameter in parameters.typeParameters) {
|
||||
typeParameterBuilders ??= <NominalParameterBuilder>[];
|
||||
typeParameterBuilders.add(
|
||||
new DillNominalParameterBuilder(
|
||||
typeParameter,
|
||||
loader: libraryBuilder.loader,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
BuildSingleExpressionResult result = bodyBuilder.buildSingleExpression(
|
||||
token: token,
|
||||
extraKnownVariables: extraKnownVariables,
|
||||
@@ -960,7 +974,7 @@ class Resolver {
|
||||
for (int i = 0; i < formals.length; i++) {
|
||||
InternalVariable variable = formals[i].variable;
|
||||
context.typeInferrer.flowAnalysis.declare(
|
||||
variable.astVariable,
|
||||
variable,
|
||||
new SharedTypeView(variable.type),
|
||||
initialized: true,
|
||||
);
|
||||
@@ -968,7 +982,7 @@ class Resolver {
|
||||
}
|
||||
for (InternalVariable extraVariable in extraKnownVariables) {
|
||||
context.typeInferrer.flowAnalysis.declare(
|
||||
extraVariable.astVariable,
|
||||
extraVariable,
|
||||
new SharedTypeView(extraVariable.type),
|
||||
initialized: true,
|
||||
);
|
||||
@@ -1129,7 +1143,7 @@ class Resolver {
|
||||
required InternalVariable? thisVariable,
|
||||
required List<TypeParameter>? thisTypeParameters,
|
||||
required LocalScope? formalParameterScope,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) {
|
||||
_benchmarker
|
||||
// Coverage-ignore(suite): Not run.
|
||||
@@ -1158,7 +1172,7 @@ class Resolver {
|
||||
required InternalVariable? thisVariable,
|
||||
required List<TypeParameter>? thisTypeParameters,
|
||||
required ConstantContext constantContext,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) {
|
||||
return new BodyBuilderImpl(
|
||||
libraryBuilder: context.libraryBuilder,
|
||||
@@ -1179,7 +1193,7 @@ class Resolver {
|
||||
}
|
||||
|
||||
_SuperParameterArguments? _createSuperParameterArguments({
|
||||
required AssignedVariables assignedVariables,
|
||||
required AssignedVariablesImpl assignedVariables,
|
||||
required List<FormalParameterBuilder>? formals,
|
||||
}) {
|
||||
if (formals == null) {
|
||||
@@ -1232,12 +1246,12 @@ class Resolver {
|
||||
/// Helper method to create a [VariableGet] of the [variable] using
|
||||
/// [fileOffset] as the file offset.
|
||||
Expression _createVariableGet({
|
||||
required AssignedVariables assignedVariables,
|
||||
required AssignedVariablesImpl assignedVariables,
|
||||
required InternalVariable variable,
|
||||
required int fileOffset,
|
||||
}) {
|
||||
if (!variable.isLocalFunction && !variable.isWildcard) {
|
||||
assignedVariables.read(variable.astVariable);
|
||||
assignedVariables.read(variable);
|
||||
}
|
||||
return intern.createVariableGet(variable, fileOffset: fileOffset);
|
||||
}
|
||||
@@ -1252,7 +1266,7 @@ class Resolver {
|
||||
// `thisVariable` usually appears in `_context.formals`, but for a
|
||||
// constructor, it doesn't. So declare it separately.
|
||||
typeInferrer.flowAnalysis.declare(
|
||||
thisVariable.astVariable,
|
||||
thisVariable,
|
||||
new SharedTypeView(thisVariable.type),
|
||||
initialized: true,
|
||||
);
|
||||
@@ -1264,7 +1278,7 @@ class Resolver {
|
||||
// TODO(62401): Remove the cast when the flow analysis uses
|
||||
// [InternalExpressionVariable]s.
|
||||
typeInferrer.flowAnalysis.declare(
|
||||
variable.astVariable,
|
||||
variable,
|
||||
new SharedTypeView(variable.type),
|
||||
initialized: true,
|
||||
);
|
||||
@@ -1287,7 +1301,7 @@ class Resolver {
|
||||
required List<Initializer> initializers,
|
||||
required bool forPrimaryConstructor,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
}) {
|
||||
_InitializerBuilder initializerBuilder = new _InitializerBuilder(
|
||||
@@ -1354,10 +1368,10 @@ class Resolver {
|
||||
required InternalVariable? thisVariable,
|
||||
required List<Initializer> initializers,
|
||||
required ConstantContext constantContext,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required bool forPrimaryConstructor,
|
||||
}) {
|
||||
AssignedVariables assignedVariables = context.assignedVariables;
|
||||
AssignedVariablesImpl assignedVariables = context.assignedVariables;
|
||||
|
||||
// Create variable get expressions for super parameters before finishing
|
||||
// the analysis of the assigned variables. Creating the expressions later
|
||||
|
||||
@@ -42,7 +42,7 @@ class ResolverForTesting extends Resolver {
|
||||
required InternalVariable? thisVariable,
|
||||
required List<TypeParameter>? thisTypeParameters,
|
||||
required ConstantContext constantContext,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) {
|
||||
return bodyBuilderCreator(
|
||||
libraryBuilder: context.libraryBuilder,
|
||||
@@ -218,7 +218,7 @@ class _InitializerBuilder {
|
||||
ScopeProviderInfo? _inferInitializers(
|
||||
List<Initializer> initializers, {
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required bool isConstructorWithoutBody,
|
||||
}) {
|
||||
@@ -248,7 +248,7 @@ class _InitializerBuilder {
|
||||
required AsyncModifier asyncModifier,
|
||||
required bool forPrimaryConstructor,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required bool isConstructorWithoutBody,
|
||||
}) {
|
||||
@@ -603,7 +603,7 @@ class _InitializerBuilder {
|
||||
required TypeInferrer typeInferrer,
|
||||
required _SuperParameterArguments? superParameterArguments,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ScopeProviderInfo? scopeProviderInfo,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required bool isFirstInitializer,
|
||||
|
||||
@@ -1490,7 +1490,7 @@ severity: $severity
|
||||
String? enclosingClassOrExtension,
|
||||
bool isClassInstanceMember,
|
||||
Procedure procedure,
|
||||
InternalVariable? extensionThis,
|
||||
Variable? extensionThis,
|
||||
List<InternalVariable> extraKnownVariables,
|
||||
ExpressionEvaluationHelper expressionEvaluationHelper,
|
||||
) async {
|
||||
|
||||
@@ -130,13 +130,13 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
TreeNode,
|
||||
Statement,
|
||||
Expression,
|
||||
Variable,
|
||||
InternalVariable,
|
||||
InternalPattern,
|
||||
InvalidExpression,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration
|
||||
>,
|
||||
NullShortingMixin<NullAwareGuard, Expression, Variable>,
|
||||
NullShortingMixin<NullAwareGuard, Expression, InternalVariable>,
|
||||
StackChecker,
|
||||
ExpressionVisitor1ExperimentExclusionMixin<
|
||||
ExpressionInferenceResult,
|
||||
@@ -354,7 +354,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
new NullAwareGuard(variable, variable.fileOffset, this),
|
||||
flowAnalysis.getExpressionInfo(variable.initializer!),
|
||||
new SharedTypeView(variable.type),
|
||||
guardVariable: variable,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1364,7 +1363,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
flowAnalysis.getExpressionInfo(result.expression),
|
||||
new SharedTypeView(result.inferredType),
|
||||
isNullAware: node.isNullAware,
|
||||
guardVariable: node.variable.astVariable,
|
||||
guardVariable: node.variable,
|
||||
);
|
||||
|
||||
Cascade? previousEnclosingCascade = _enclosingCascade;
|
||||
@@ -3402,17 +3401,29 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
flowAnalysis.forEach_bodyBegin(node);
|
||||
|
||||
flowAnalysis.declare(
|
||||
variable,
|
||||
new SharedTypeView(variable.type),
|
||||
initialized: true,
|
||||
);
|
||||
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
variable,
|
||||
captureKind: _captureKindForVariable(variable),
|
||||
InternalVariable? declaredVariable = headerResult.declaredVariable;
|
||||
if (declaredVariable != null) {
|
||||
flowAnalysis.declare(
|
||||
declaredVariable,
|
||||
new SharedTypeView(declaredVariable.type),
|
||||
initialized: true,
|
||||
);
|
||||
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
declaredVariable.astVariable,
|
||||
captureKind: _captureKindForVariable(declaredVariable),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
if (declaredVariable?.astVariable != variable) {
|
||||
// [variable] is synthesized.
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
variable,
|
||||
captureKind: CaptureKind.notCaptured,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ForInEncoding encoding = headerResult.computeEncoding();
|
||||
@@ -3590,7 +3601,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
node.variable.astVariable,
|
||||
captureKind: _captureKindForVariable(node.variable.astVariable),
|
||||
captureKind: _captureKindForVariable(node.variable),
|
||||
);
|
||||
capturedContexts = _contextAllocationStrategy
|
||||
.computeCapturedVariableContexts(_capturedVariablesForNode(node));
|
||||
@@ -3627,7 +3638,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
variable.type = inferredType;
|
||||
flowAnalysis.declare(
|
||||
variable.astVariable,
|
||||
variable,
|
||||
new SharedTypeView(variable.type),
|
||||
initialized: true,
|
||||
);
|
||||
@@ -3650,6 +3661,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
);
|
||||
libraryBuilder.loader.dataForTesting
|
||||
// Coverage-ignore(suite): Not run.
|
||||
?.registerAlias(variable, variable.astVariable);
|
||||
libraryBuilder.loader.dataForTesting
|
||||
// Coverage-ignore(suite): Not run.
|
||||
?.registerAlias(node, replacement);
|
||||
return new StatementInferenceResult.single(replacement);
|
||||
}
|
||||
@@ -3657,7 +3671,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
@override
|
||||
ScopeProviderInfo beginClosureContextAllocation(
|
||||
List<InternalVariable> parameters, {
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ScopeProviderInfo? scopeProviderInfo,
|
||||
}) {
|
||||
scopeProviderInfo ??= _contextAllocationStrategy.enterScopeProvider(
|
||||
@@ -3667,7 +3681,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
);
|
||||
if (internalThisVariable != null) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
internalThisVariable,
|
||||
internalThisVariable.astVariable,
|
||||
captureKind: _captureKindForVariable(internalThisVariable),
|
||||
);
|
||||
}
|
||||
@@ -3682,10 +3696,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
void _handleDeclarationsOfParameters(List<InternalVariable> parameters) {
|
||||
for (InternalVariable parameter in parameters) {
|
||||
Variable parameterAstVariable = parameter.astVariable;
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
parameterAstVariable,
|
||||
captureKind: _captureKindForVariable(parameterAstVariable),
|
||||
parameter.astVariable,
|
||||
captureKind: _captureKindForVariable(parameter),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3911,7 +3924,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
{
|
||||
for (InternalVariable variable
|
||||
in node.patternGuard.pattern.declaredVariables)
|
||||
variable.cosmeticName!: variable.astVariable,
|
||||
variable.cosmeticName!: variable,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -4334,7 +4347,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
variables: {
|
||||
for (InternalVariable variable
|
||||
in element.internalPatternGuard.pattern.declaredVariables)
|
||||
variable.cosmeticName!: variable.astVariable,
|
||||
variable.cosmeticName!: variable,
|
||||
},
|
||||
guard: element.internalPatternGuard.guard,
|
||||
ifTrue: element.then,
|
||||
@@ -4601,16 +4614,29 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
flowAnalysis.forEach_bodyBegin(node);
|
||||
|
||||
flowAnalysis.declare(
|
||||
variable,
|
||||
new SharedTypeView(variable.type),
|
||||
initialized: true,
|
||||
);
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
variable,
|
||||
captureKind: _captureKindForVariable(variable),
|
||||
InternalVariable? declaredVariable = result.declaredVariable;
|
||||
if (declaredVariable != null) {
|
||||
flowAnalysis.declare(
|
||||
declaredVariable,
|
||||
new SharedTypeView(declaredVariable.type),
|
||||
initialized: true,
|
||||
);
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
declaredVariable.astVariable,
|
||||
captureKind: _captureKindForVariable(declaredVariable),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
if (declaredVariable?.astVariable != variable) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
// [variable] is synthesized.
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
variable,
|
||||
captureKind: CaptureKind.notCaptured,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
node.encoding = result.computeEncoding();
|
||||
@@ -7486,7 +7512,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
variables: {
|
||||
for (InternalVariable variable
|
||||
in entry.internalPatternGuard.pattern.declaredVariables)
|
||||
variable.cosmeticName!: variable.astVariable,
|
||||
variable.cosmeticName!: variable,
|
||||
},
|
||||
guard: entry.internalPatternGuard.guard,
|
||||
ifTrue: entry.then,
|
||||
@@ -7807,18 +7833,30 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
flowAnalysis.forEach_bodyBegin(node);
|
||||
|
||||
flowAnalysis.declare(
|
||||
variable,
|
||||
new SharedTypeView(variable.type),
|
||||
initialized: true,
|
||||
);
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
variable,
|
||||
captureKind: _captureKindForVariable(variable),
|
||||
InternalVariable? declaredVariable = result.declaredVariable;
|
||||
if (declaredVariable != null) {
|
||||
flowAnalysis.declare(
|
||||
declaredVariable,
|
||||
new SharedTypeView(declaredVariable.type),
|
||||
initialized: true,
|
||||
);
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
declaredVariable.astVariable,
|
||||
captureKind: _captureKindForVariable(declaredVariable),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
if (declaredVariable?.astVariable != variable) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
// [variable] is synthesized.
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
variable,
|
||||
captureKind: CaptureKind.notCaptured,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
node.encoding = result.computeEncoding();
|
||||
|
||||
// Actual types are added by the recursive call.
|
||||
@@ -11975,12 +12013,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
node.variable.initializer = initializer..parent = node.variable;
|
||||
|
||||
flowAnalysis.declare(
|
||||
node.variable.astVariable,
|
||||
node.variable,
|
||||
new SharedTypeView(node.variable.type),
|
||||
initialized: false,
|
||||
);
|
||||
flowAnalysis.initialize(
|
||||
node.variable.astVariable,
|
||||
node.variable,
|
||||
new SharedTypeView(node.variable.type),
|
||||
flowAnalysis.getExpressionInfo(node.variable.initializer!),
|
||||
isFinal: false,
|
||||
@@ -11992,7 +12030,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
flow.nullAwareAccess_rightBegin(
|
||||
flowAnalysis.getExpressionInfo(node.variable.initializer!),
|
||||
new SharedTypeView(initializerType),
|
||||
guardVariable: node.variable.astVariable,
|
||||
guardVariable: node.variable,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12168,12 +12206,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
node.variable.initializer = initializer..parent = node.variable;
|
||||
|
||||
flowAnalysis.declare(
|
||||
node.variable.astVariable,
|
||||
node.variable,
|
||||
new SharedTypeView(node.variable.type),
|
||||
initialized: false,
|
||||
);
|
||||
flowAnalysis.initialize(
|
||||
node.variable.astVariable,
|
||||
node.variable,
|
||||
new SharedTypeView(node.variable.type),
|
||||
flowAnalysis.getExpressionInfo(node.variable.initializer!),
|
||||
isFinal: false,
|
||||
@@ -12204,7 +12242,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
new NullAwareGuard(tempVar!, node.variable.fileOffset, this),
|
||||
flowAnalysis.getExpressionInfo(tempVar.initializer!),
|
||||
new SharedTypeView(tempVar.type),
|
||||
guardVariable: tempVar,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13624,8 +13661,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
Catch visitCatch(InternalCatch node) {
|
||||
ScopeProviderInfo? scopeProviderInfo;
|
||||
Variable? exception = node.exception?.astVariable;
|
||||
Variable? stackTrace = node.stackTrace?.astVariable;
|
||||
InternalVariable? exception = node.exception;
|
||||
InternalVariable? stackTrace = node.stackTrace;
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
scopeProviderInfo = _contextAllocationStrategy.enterScopeProvider(
|
||||
scopeProviderInfoKind: ScopeProviderInfoKind.Catch,
|
||||
@@ -13634,7 +13671,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
// TODO(62401): Remove the casts when the flow analysis uses
|
||||
// [InternalExpressionVariable]s.
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
exception,
|
||||
exception.astVariable,
|
||||
captureKind: _captureKindForVariable(exception),
|
||||
);
|
||||
}
|
||||
@@ -13642,7 +13679,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
// TODO(62401): Remove the casts when the flow analysis uses
|
||||
// [InternalExpressionVariable]s.
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
stackTrace,
|
||||
stackTrace.astVariable,
|
||||
captureKind: _captureKindForVariable(stackTrace),
|
||||
);
|
||||
}
|
||||
@@ -13656,8 +13693,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
return extern.createCatch(
|
||||
guard: node.guard,
|
||||
exception: exception,
|
||||
stackTrace: stackTrace,
|
||||
exception: exception?.astVariable,
|
||||
stackTrace: stackTrace?.astVariable,
|
||||
body: body,
|
||||
scope: scope,
|
||||
fileOffset: node.fileOffset,
|
||||
@@ -13685,8 +13722,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
// TODO(62401): Remove the casts when the flow analysis uses
|
||||
// [InternalExpressionVariable]s.
|
||||
flowAnalysis.tryCatchStatement_catchBegin(
|
||||
catchBlock.exception?.astVariable,
|
||||
catchBlock.stackTrace?.astVariable,
|
||||
catchBlock.exception,
|
||||
catchBlock.stackTrace,
|
||||
);
|
||||
catchBlocks.add(visitCatch(catchBlock));
|
||||
flowAnalysis.tryCatchStatement_catchEnd();
|
||||
@@ -13791,7 +13828,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
node.variable.astVariable,
|
||||
captureKind: _captureKindForVariable(node.variable.astVariable),
|
||||
captureKind: _captureKindForVariable(node.variable),
|
||||
);
|
||||
}
|
||||
return variableDeclarationInferenceResult;
|
||||
@@ -14506,9 +14543,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
case InternalAndPattern():
|
||||
return analyzeLogicalAndPatternSchema(node.left, node.right);
|
||||
case InternalAssignedVariablePattern():
|
||||
return analyzeAssignedVariablePatternSchema(
|
||||
node.variable.astVariable,
|
||||
);
|
||||
return analyzeAssignedVariablePatternSchema(node.variable);
|
||||
case InternalCastPattern():
|
||||
return analyzeCastPatternSchema();
|
||||
case InternalConstantPattern():
|
||||
@@ -14818,21 +14853,25 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
|
||||
@override
|
||||
FlowAnalysis<TreeNode, Statement, Expression, Variable> get flow =>
|
||||
FlowAnalysis<TreeNode, Statement, Expression, InternalVariable> get flow =>
|
||||
flowAnalysis;
|
||||
|
||||
@override
|
||||
SwitchExpressionMemberInfo<TreeNode, Expression, Variable>
|
||||
SwitchExpressionMemberInfo<TreeNode, Expression, InternalVariable>
|
||||
getSwitchExpressionMemberInfo(Expression node, int index) {
|
||||
InternalSwitchExpressionCase switchExpressionCase =
|
||||
(node as InternalSwitchExpression).cases[index];
|
||||
InternalPattern pattern = switchExpressionCase.patternGuard.pattern;
|
||||
Map<String, Variable> variables = {
|
||||
Map<String, InternalVariable> variables = {
|
||||
for (InternalVariable declaredVariable in pattern.declaredVariables)
|
||||
declaredVariable.cosmeticName!: declaredVariable.astVariable,
|
||||
declaredVariable.cosmeticName!: declaredVariable,
|
||||
};
|
||||
return new SwitchExpressionMemberInfo<TreeNode, Expression, Variable>(
|
||||
head: new CaseHeadOrDefaultInfo<TreeNode, Expression, Variable>(
|
||||
return new SwitchExpressionMemberInfo<
|
||||
TreeNode,
|
||||
Expression,
|
||||
InternalVariable
|
||||
>(
|
||||
head: new CaseHeadOrDefaultInfo<TreeNode, Expression, InternalVariable>(
|
||||
pattern: pattern,
|
||||
guard: switchExpressionCase.patternGuard.guard,
|
||||
variables: variables,
|
||||
@@ -14842,7 +14881,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
|
||||
@override
|
||||
SwitchStatementMemberInfo<TreeNode, Statement, Expression, Variable>
|
||||
SwitchStatementMemberInfo<TreeNode, Statement, Expression, InternalVariable>
|
||||
getSwitchStatementMemberInfo(
|
||||
covariant InternalSwitchStatement node,
|
||||
int caseIndex,
|
||||
@@ -14872,7 +14911,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
variables: {
|
||||
for (InternalVariable variable
|
||||
in patternGuard.pattern.declaredVariables)
|
||||
variable.cosmeticName!: variable.astVariable,
|
||||
variable.cosmeticName!: variable,
|
||||
},
|
||||
),
|
||||
if (case_.isDefault)
|
||||
@@ -14881,7 +14920,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
body: [case_.body],
|
||||
variables: {
|
||||
for (InternalVariable jointVariable in case_.jointVariables)
|
||||
jointVariable.cosmeticName!: jointVariable.astVariable,
|
||||
jointVariable.cosmeticName!: jointVariable,
|
||||
},
|
||||
hasLabels: case_.hasLabel,
|
||||
);
|
||||
@@ -15003,7 +15042,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
void handleCase_afterCaseHeads(
|
||||
Statement node,
|
||||
int caseIndex,
|
||||
Iterable<Variable> variables,
|
||||
Iterable<InternalVariable> variables,
|
||||
) {}
|
||||
|
||||
@override
|
||||
@@ -15079,7 +15118,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
|
||||
@override
|
||||
void setVariableType(Variable variable, SharedTypeView type) {
|
||||
void setVariableType(InternalVariable variable, SharedTypeView type) {
|
||||
variable.type = type.unwrapTypeView();
|
||||
}
|
||||
|
||||
@@ -15111,7 +15150,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
analyzeDeclaredVariablePattern(
|
||||
context,
|
||||
node,
|
||||
node.variable.astVariable,
|
||||
node.variable,
|
||||
node.variableName,
|
||||
node.type?.wrapSharedTypeView(),
|
||||
);
|
||||
@@ -16425,10 +16464,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
// TODO(johnniwinther): Share this through the type analyzer.
|
||||
Pattern? replacement;
|
||||
InternalVariable variable = node.variable;
|
||||
bool isDefinitelyAssigned = flowAnalysis.isAssigned(variable.astVariable);
|
||||
bool isDefinitelyUnassigned = flowAnalysis.isUnassigned(
|
||||
variable.astVariable,
|
||||
);
|
||||
bool isDefinitelyAssigned = flowAnalysis.isAssigned(variable);
|
||||
bool isDefinitelyUnassigned = flowAnalysis.isUnassigned(variable);
|
||||
if ((variable.isLate && variable.isFinal) ||
|
||||
variable.isLateFinalWithoutInitializer) {
|
||||
if (isDefinitelyAssigned) {
|
||||
@@ -16479,11 +16516,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
}
|
||||
|
||||
AssignedVariablePatternResult<InvalidExpression> analysisResult =
|
||||
analyzeAssignedVariablePattern(
|
||||
context,
|
||||
node,
|
||||
node.variable.astVariable,
|
||||
);
|
||||
analyzeAssignedVariablePattern(context, node, node.variable);
|
||||
|
||||
DartType matchedValueType = analysisResult.matchedValueType
|
||||
.unwrapTypeView();
|
||||
@@ -16507,6 +16540,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
replacement ??
|
||||
extern.createAssignedVariablePattern(
|
||||
variable: node.variable.astVariable,
|
||||
setter: node.variable.lateSetter,
|
||||
matchedValueType: matchedValueType,
|
||||
needsCast: needsCast,
|
||||
hasObservableEffect: hasObservableEffect,
|
||||
@@ -16725,7 +16759,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
@override
|
||||
void finishJoinedPatternVariable(
|
||||
Variable variable, {
|
||||
InternalVariable variable, {
|
||||
required JoinedPatternVariableLocation location,
|
||||
required JoinedPatternVariableInconsistency inconsistency,
|
||||
required bool isFinal,
|
||||
@@ -17363,7 +17397,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
return node is DotShorthand;
|
||||
}
|
||||
|
||||
CaptureKind _captureKindForVariable(Variable variable) {
|
||||
CaptureKind _captureKindForVariable(InternalVariable variable) {
|
||||
int variableKey = assignedVariables.promotionKeyStore.keyForVariable(
|
||||
variable,
|
||||
);
|
||||
@@ -17384,12 +17418,16 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
AssignedVariablesNodeInfo nodeInfo = assignedVariables.getInfoForNode(node);
|
||||
for (int variableKey in nodeInfo.read) {
|
||||
capturedVariables.add(
|
||||
assignedVariables.promotionKeyStore.variableForKey(variableKey)!,
|
||||
assignedVariables.promotionKeyStore
|
||||
.variableForKey(variableKey)!
|
||||
.astVariable,
|
||||
);
|
||||
}
|
||||
for (int variableKey in nodeInfo.written) {
|
||||
capturedVariables.add(
|
||||
assignedVariables.promotionKeyStore.variableForKey(variableKey)!,
|
||||
assignedVariables.promotionKeyStore
|
||||
.variableForKey(variableKey)!
|
||||
.astVariable,
|
||||
);
|
||||
}
|
||||
return capturedVariables;
|
||||
@@ -17466,14 +17504,14 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
internalVariable.type = inferredType;
|
||||
}
|
||||
flowAnalysis.declare(
|
||||
internalVariable.astVariable,
|
||||
internalVariable,
|
||||
new SharedTypeView(internalVariable.type),
|
||||
initialized: internalVariable.hasDeclaredInitializer,
|
||||
);
|
||||
if (initializerResult != null) {
|
||||
DartType initializerType = initializerResult.inferredType;
|
||||
flowAnalysis.initialize(
|
||||
internalVariable.astVariable,
|
||||
internalVariable,
|
||||
new SharedTypeView(initializerType),
|
||||
flowAnalysis.getExpressionInfo(initializerResult.expression),
|
||||
isFinal: internalVariable.isFinal,
|
||||
@@ -17682,6 +17720,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
fileOffset: internalVariable.fileOffset,
|
||||
);
|
||||
}
|
||||
libraryBuilder.loader.dataForTesting
|
||||
// Coverage-ignore(suite): Not run.
|
||||
?.registerAlias(internalVariable, internalVariable.astVariable);
|
||||
return new VariableDeclarationInferenceResult.direct(
|
||||
extern.createVariableDeclaration(
|
||||
internalVariable.astVariable,
|
||||
@@ -17693,7 +17734,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
|
||||
@override
|
||||
ScopeProviderInfo beginFieldInference({
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) {
|
||||
ScopeProviderInfo scopeProviderInfo = _contextAllocationStrategy
|
||||
.enterScopeProvider(
|
||||
@@ -17703,7 +17744,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||
);
|
||||
if (internalThisVariable != null) {
|
||||
_contextAllocationStrategy.handleDeclarationOfVariable(
|
||||
internalThisVariable,
|
||||
internalThisVariable.astVariable,
|
||||
captureKind: _captureKindForVariable(internalThisVariable),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -159,8 +159,8 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
|
||||
InferenceDataForTesting? get dataForTesting => _inferrer.dataForTesting;
|
||||
|
||||
FlowAnalysis<TreeNode, Statement, Expression, Variable> get flowAnalysis =>
|
||||
_inferrer.flowAnalysis;
|
||||
FlowAnalysis<TreeNode, Statement, Expression, InternalVariable>
|
||||
get flowAnalysis => _inferrer.flowAnalysis;
|
||||
|
||||
/// Provides access to the [OperationsCfe] object. This is needed by
|
||||
/// [isAssignable] and for caching types.
|
||||
@@ -2302,7 +2302,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
|
||||
for (InternalVariable parameter in function.positionalParameters) {
|
||||
flowAnalysis.declare(
|
||||
parameter.astVariable,
|
||||
parameter,
|
||||
new SharedTypeView(parameter.type),
|
||||
initialized: true,
|
||||
);
|
||||
@@ -2318,7 +2318,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
}
|
||||
for (InternalVariable parameter in function.namedParameters) {
|
||||
flowAnalysis.declare(
|
||||
parameter.astVariable,
|
||||
parameter,
|
||||
new SharedTypeView(parameter.type),
|
||||
initialized: true,
|
||||
);
|
||||
@@ -2398,6 +2398,22 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
for (InternalVariable parameter in function.namedParameters)
|
||||
parameter.astVariable,
|
||||
];
|
||||
if (libraryBuilder.loader.dataForTesting != null) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
for (InternalVariable parameter in function.positionalParameters) {
|
||||
libraryBuilder.loader.dataForTesting?.registerAlias(
|
||||
parameter,
|
||||
parameter.astVariable,
|
||||
);
|
||||
}
|
||||
for (InternalVariable parameter in function.namedParameters) {
|
||||
libraryBuilder.loader.dataForTesting?.registerAlias(
|
||||
parameter,
|
||||
parameter.astVariable,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new LocalFunctionResult(
|
||||
returnType: returnType,
|
||||
positionalParameters: positionalParameters,
|
||||
@@ -4164,7 +4180,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
// Don't promote local functions.
|
||||
SharedTypeView? wrappedPromotedType;
|
||||
(wrappedPromotedType, expressionInfo) = flowAnalysis.variableRead(
|
||||
variable.astVariable,
|
||||
variable,
|
||||
);
|
||||
promotedType = wrappedPromotedType?.unwrapTypeView();
|
||||
}
|
||||
@@ -4191,7 +4207,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
resultExpression = result..variable = variable.astVariable;
|
||||
}
|
||||
|
||||
bool isUnassigned = !flowAnalysis.isAssigned(variable.astVariable);
|
||||
bool isUnassigned = !flowAnalysis.isAssigned(variable);
|
||||
if (isUnassigned) {
|
||||
dataForTesting
|
||||
// Coverage-ignore(suite): Not run.
|
||||
@@ -4199,9 +4215,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
.potentiallyUnassignedNodes // Coverage-ignore(suite): Not run.
|
||||
.add(result);
|
||||
}
|
||||
bool isDefinitelyUnassigned = flowAnalysis.isUnassigned(
|
||||
variable.astVariable,
|
||||
);
|
||||
bool isDefinitelyUnassigned = flowAnalysis.isUnassigned(variable);
|
||||
if (isDefinitelyUnassigned) {
|
||||
dataForTesting
|
||||
// Coverage-ignore(suite): Not run.
|
||||
@@ -4275,7 +4289,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
computeVariableSetTypeAndWriteContext(InternalVariable variable) {
|
||||
DartType declaredOrInferredType = variable.lateType ?? variable.type;
|
||||
DartType? promotedType = flowAnalysis
|
||||
.promotedType(variable.astVariable)
|
||||
.promotedType(variable)
|
||||
?.unwrapTypeView();
|
||||
return (declaredOrInferredType, promotedType ?? declaredOrInferredType);
|
||||
}
|
||||
@@ -4292,10 +4306,8 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
required int assignOffset,
|
||||
required int nameOffset,
|
||||
}) {
|
||||
bool isDefinitelyAssigned = flowAnalysis.isAssigned(variable.astVariable);
|
||||
bool isDefinitelyUnassigned = flowAnalysis.isUnassigned(
|
||||
variable.astVariable,
|
||||
);
|
||||
bool isDefinitelyAssigned = flowAnalysis.isAssigned(variable);
|
||||
bool isDefinitelyUnassigned = flowAnalysis.isUnassigned(variable);
|
||||
rhsResult = ensureAssignableResult(
|
||||
variableType,
|
||||
rhsResult,
|
||||
@@ -4309,7 +4321,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
result,
|
||||
flowAnalysis.write(
|
||||
result,
|
||||
variable.astVariable,
|
||||
variable,
|
||||
new SharedTypeView(rhsResult.inferredType),
|
||||
flowAnalysis.getExpressionInfo(rhsResult.expression),
|
||||
),
|
||||
@@ -5576,7 +5588,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
/// [parameters] are those of the function being inferred.
|
||||
ScopeProviderInfo beginClosureContextAllocation(
|
||||
List<InternalVariable> parameters, {
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ScopeProviderInfo? scopeProviderInfo,
|
||||
});
|
||||
|
||||
@@ -5585,7 +5597,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
||||
|
||||
/// Performs preliminary computations before inferring the field initializer.
|
||||
ScopeProviderInfo beginFieldInference({
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
});
|
||||
|
||||
/// Finishes computations after inferring the field initializer.
|
||||
@@ -5653,7 +5665,12 @@ FunctionType replaceReturnType(FunctionType functionType, DartType returnType) {
|
||||
}
|
||||
|
||||
class _WhyNotPromotedVisitor
|
||||
implements NonPromotionReasonVisitor<List<LocatedMessage>, Node, Variable> {
|
||||
implements
|
||||
NonPromotionReasonVisitor<
|
||||
List<LocatedMessage>,
|
||||
Node,
|
||||
InternalVariable
|
||||
> {
|
||||
final InferenceVisitorBase inferrer;
|
||||
|
||||
Member? propertyReference;
|
||||
@@ -5662,7 +5679,7 @@ class _WhyNotPromotedVisitor
|
||||
|
||||
@override
|
||||
List<LocatedMessage> visitDemoteViaExplicitWrite(
|
||||
DemoteViaExplicitWrite<Variable> reason,
|
||||
DemoteViaExplicitWrite<InternalVariable> reason,
|
||||
) {
|
||||
TreeNode node = reason.node as TreeNode;
|
||||
if (inferrer.dataForTesting != null) {
|
||||
|
||||
@@ -57,7 +57,7 @@ class MatchingExpressionVisitor
|
||||
}
|
||||
return new DelayedAssignment(
|
||||
matchingCache,
|
||||
node.variable,
|
||||
node.setter ?? node.variable,
|
||||
node.variable.type,
|
||||
valueExpression,
|
||||
fileOffset: node.fileOffset,
|
||||
|
||||
@@ -23,7 +23,7 @@ class SharedTypeAnalyzerErrors
|
||||
TreeNode,
|
||||
Statement,
|
||||
Expression,
|
||||
Variable,
|
||||
InternalVariable,
|
||||
InternalPattern,
|
||||
InvalidExpression
|
||||
> {
|
||||
@@ -75,14 +75,14 @@ class SharedTypeAnalyzerErrors
|
||||
|
||||
@override
|
||||
InvalidExpression duplicateAssignmentPatternVariable({
|
||||
required Variable variable,
|
||||
required InternalVariable variable,
|
||||
required InternalPattern original,
|
||||
required InternalPattern duplicate,
|
||||
}) {
|
||||
return problemReporting.buildProblem(
|
||||
compilerContext: compilerContext,
|
||||
message: diag.duplicatePatternAssignmentVariable.withArguments(
|
||||
variableName: variable.name!,
|
||||
variableName: variable.cosmeticName!,
|
||||
),
|
||||
fileUri: uri,
|
||||
fileOffset: duplicate.fileOffset,
|
||||
@@ -155,8 +155,8 @@ class SharedTypeAnalyzerErrors
|
||||
|
||||
@override
|
||||
void inconsistentJoinedPatternVariable({
|
||||
required Variable variable,
|
||||
required Variable component,
|
||||
required InternalVariable variable,
|
||||
required InternalVariable component,
|
||||
}) {
|
||||
// TODO(johnniwinther): How should we handle errors that are not report
|
||||
// here? Should we have a sentinel error node, allow a nullable result, or ?
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/type_algebra.dart';
|
||||
|
||||
import '../kernel/internal_ast.dart';
|
||||
import 'type_inference_engine.dart';
|
||||
import 'type_schema.dart';
|
||||
import 'type_schema_environment.dart';
|
||||
@@ -21,14 +22,14 @@ import 'type_schema_environment.dart';
|
||||
class TypeConstraintGatherer
|
||||
extends
|
||||
shared.TypeConstraintGenerator<
|
||||
Variable,
|
||||
InternalVariable,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration,
|
||||
TreeNode
|
||||
>
|
||||
with
|
||||
shared.TypeConstraintGeneratorMixin<
|
||||
Variable,
|
||||
InternalVariable,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration,
|
||||
TreeNode
|
||||
|
||||
@@ -379,14 +379,14 @@ class TypeInferenceEngineImpl extends TypeInferenceEngine {
|
||||
if (dataForTesting != null) {
|
||||
// Coverage-ignore-block(suite): Not run.
|
||||
dataForTesting.flowAnalysisResult.assignedVariables =
|
||||
new AssignedVariablesForTesting<TreeNode, Variable>();
|
||||
new AssignedVariablesForTesting<TreeNode, InternalVariable>();
|
||||
assignedVariables = new AssignedVariablesImpl(
|
||||
dataForTesting.flowAnalysisResult.assignedVariables!,
|
||||
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
|
||||
);
|
||||
} else {
|
||||
assignedVariables = new AssignedVariablesImpl(
|
||||
new AssignedVariables<TreeNode, Variable>(),
|
||||
new AssignedVariables<TreeNode, InternalVariable>(),
|
||||
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
|
||||
);
|
||||
}
|
||||
@@ -415,7 +415,11 @@ class TypeInferenceEngineImpl extends TypeInferenceEngine {
|
||||
|
||||
// TODO(cstefantsova): Merge with [TypeInferenceResultForTesting].
|
||||
class InferenceDataForTesting
|
||||
extends shared.TypeConstraintGenerationDataForTesting<Variable, TreeNode> {
|
||||
extends
|
||||
shared.TypeConstraintGenerationDataForTesting<
|
||||
InternalVariable,
|
||||
TreeNode
|
||||
> {
|
||||
final FlowAnalysisResult flowAnalysisResult = new FlowAnalysisResult();
|
||||
|
||||
final TypeInferenceResultForTesting typeInferenceResult =
|
||||
@@ -446,7 +450,7 @@ class FlowAnalysisResult {
|
||||
final List<TreeNode> definitelyUnassignedNodes = [];
|
||||
|
||||
/// The assigned variables information that computed for the member.
|
||||
AssignedVariablesForTesting<TreeNode, Variable>? assignedVariables;
|
||||
AssignedVariablesForTesting<TreeNode, InternalVariable>? assignedVariables;
|
||||
|
||||
/// For each expression that led to an error because it was not promoted, a
|
||||
/// string describing the reason it was not promoted.
|
||||
@@ -461,14 +465,14 @@ class FlowAnalysisResult {
|
||||
class OperationsCfe
|
||||
with
|
||||
TypeAnalyzerOperationsMixin<
|
||||
Variable,
|
||||
InternalVariable,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration,
|
||||
TreeNode
|
||||
>
|
||||
implements
|
||||
TypeAnalyzerOperations<
|
||||
Variable,
|
||||
InternalVariable,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration,
|
||||
TreeNode
|
||||
@@ -595,7 +599,7 @@ class OperationsCfe
|
||||
bool isExtensionTypeInternal(DartType type) => type is ExtensionType;
|
||||
|
||||
@override
|
||||
bool isFinal(Variable variable) {
|
||||
bool isFinal(InternalVariable variable) {
|
||||
return variable.isFinal;
|
||||
}
|
||||
|
||||
@@ -683,14 +687,11 @@ class OperationsCfe
|
||||
}
|
||||
|
||||
@override
|
||||
SharedTypeView variableType(Variable variable) {
|
||||
SharedTypeView variableType(InternalVariable variable) {
|
||||
// When late variables get lowered, their type is changed, but the
|
||||
// original type is stored in `VariableDeclarationImpl.lateType`, so we
|
||||
// use that if it exists.
|
||||
DartType? lateType = variable is InternalVariable
|
||||
? (variable as InternalVariable).lateType
|
||||
: null;
|
||||
return new SharedTypeView(lateType ?? variable.type);
|
||||
return new SharedTypeView(variable.lateType ?? variable.type);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -772,7 +773,7 @@ class OperationsCfe
|
||||
}
|
||||
|
||||
@override
|
||||
bool isVariableFinal(Variable node) {
|
||||
bool isVariableFinal(InternalVariable node) {
|
||||
return node.isFinal;
|
||||
}
|
||||
|
||||
@@ -1097,7 +1098,7 @@ class OperationsCfe
|
||||
|
||||
@override
|
||||
TypeConstraintGenerator<
|
||||
Variable,
|
||||
InternalVariable,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration,
|
||||
TreeNode
|
||||
@@ -1184,7 +1185,11 @@ class OperationsCfe
|
||||
|
||||
/// Type inference results used for testing.
|
||||
class TypeInferenceResultForTesting
|
||||
extends shared.TypeConstraintGenerationDataForTesting<Variable, TreeNode> {
|
||||
extends
|
||||
shared.TypeConstraintGenerationDataForTesting<
|
||||
InternalVariable,
|
||||
TreeNode
|
||||
> {
|
||||
final Map<TreeNode, List<DartType>> inferredTypeArguments = {};
|
||||
final Map<TreeNode, DartType> inferredVariableTypes = {};
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ abstract class TypeInferrer {
|
||||
ExtensionScope get extensionScope;
|
||||
|
||||
/// Returns the [FlowAnalysis] used during inference.
|
||||
FlowAnalysis<TreeNode, Statement, Expression, Variable> get flowAnalysis;
|
||||
FlowAnalysis<TreeNode, Statement, Expression, InternalVariable>
|
||||
get flowAnalysis;
|
||||
|
||||
AssignedVariablesImpl get assignedVariables;
|
||||
|
||||
@@ -55,7 +56,7 @@ abstract class TypeInferrer {
|
||||
DartType? declaredType,
|
||||
required Expression initializer,
|
||||
required InferenceDefaultType inferenceDefaultType,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
});
|
||||
|
||||
/// Performs type inference on the given function body.
|
||||
@@ -66,7 +67,7 @@ abstract class TypeInferrer {
|
||||
required AsyncModifier asyncModifier,
|
||||
required Statement body,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ScopeProviderInfo? scopeProviderInfo,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required ConstructorContext? constructorContext,
|
||||
@@ -79,7 +80,7 @@ abstract class TypeInferrer {
|
||||
required ConstructorContext constructorContext,
|
||||
required List<Initializer> initializers,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required bool isConstructorWithoutBody,
|
||||
});
|
||||
@@ -124,7 +125,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
TypeAnalyzerOptions typeAnalyzerOptions;
|
||||
|
||||
@override
|
||||
late final FlowAnalysis<TreeNode, Statement, Expression, Variable>
|
||||
late final FlowAnalysis<TreeNode, Statement, Expression, InternalVariable>
|
||||
flowAnalysis = new FlowAnalysis(
|
||||
operations,
|
||||
assignedVariables,
|
||||
@@ -210,7 +211,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
DartType? declaredType,
|
||||
required Expression initializer,
|
||||
required InferenceDefaultType inferenceDefaultType,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) {
|
||||
InferenceVisitorBase visitor = _createInferenceVisitor(
|
||||
fileUri: fileUri,
|
||||
@@ -261,7 +262,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
required AsyncModifier asyncModifier,
|
||||
required Statement body,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ScopeProviderInfo? scopeProviderInfo,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required ConstructorContext? constructorContext,
|
||||
@@ -331,25 +332,39 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
InferenceVisitorBase.createContextAllocationStrategy(),
|
||||
);
|
||||
|
||||
List<InternalVariable> positionalParameters = [
|
||||
for (Variable positionalParameter
|
||||
in redirectingFactoryFunction.positionalParameters)
|
||||
isClosureContextLoweringEnabled
|
||||
? new InternalPositionalParameter(
|
||||
astVariable: positionalParameter as PositionalParameter,
|
||||
isImplicitlyTyped: false,
|
||||
fileOffset: positionalParameter.fileOffset,
|
||||
)
|
||||
: new InternalLegacyVariable(
|
||||
astVariable: positionalParameter,
|
||||
fileOffset: positionalParameter.fileOffset,
|
||||
),
|
||||
];
|
||||
List<InternalVariable> namedParameters = [
|
||||
for (Variable namedParameter
|
||||
in redirectingFactoryFunction.namedParameters)
|
||||
isClosureContextLoweringEnabled
|
||||
? new InternalNamedParameter(
|
||||
astVariable: namedParameter as NamedParameter,
|
||||
isImplicitlyTyped: false,
|
||||
fileOffset: namedParameter.fileOffset,
|
||||
)
|
||||
: new InternalLegacyVariable(
|
||||
astVariable: namedParameter,
|
||||
fileOffset: namedParameter.fileOffset,
|
||||
),
|
||||
];
|
||||
|
||||
ScopeProviderInfo? scopeProviderInfo;
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
scopeProviderInfo = visitor.beginClosureContextAllocation(
|
||||
[
|
||||
for (Variable positionalParameter
|
||||
in redirectingFactoryFunction.positionalParameters)
|
||||
new InternalPositionalParameter(
|
||||
astVariable: positionalParameter as PositionalParameter,
|
||||
isImplicitlyTyped: false,
|
||||
fileOffset: positionalParameter.fileOffset,
|
||||
),
|
||||
for (Variable namedParameter
|
||||
in redirectingFactoryFunction.namedParameters)
|
||||
new InternalNamedParameter(
|
||||
astVariable: namedParameter as NamedParameter,
|
||||
isImplicitlyTyped: false,
|
||||
fileOffset: namedParameter.fileOffset,
|
||||
),
|
||||
],
|
||||
[...positionalParameters, ...namedParameters],
|
||||
internalThisVariable: null,
|
||||
scopeProviderInfo: null,
|
||||
);
|
||||
@@ -357,60 +372,30 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
|
||||
List<Argument> arguments = [];
|
||||
int positionalCount = 0;
|
||||
for (Variable parameter
|
||||
in redirectingFactoryFunction.positionalParameters) {
|
||||
for (InternalVariable parameter in positionalParameters) {
|
||||
flowAnalysis.declare(
|
||||
parameter,
|
||||
new SharedTypeView(parameter.type),
|
||||
initialized: true,
|
||||
);
|
||||
Expression variableGet;
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
variableGet = intern.createVariableGet(
|
||||
new InternalPositionalParameter(
|
||||
astVariable: parameter as PositionalParameter,
|
||||
isImplicitlyTyped: false,
|
||||
fileOffset: parameter.fileOffset,
|
||||
),
|
||||
fileOffset: parameter.fileOffset,
|
||||
);
|
||||
} else {
|
||||
variableGet = intern.createVariableGet(
|
||||
parameter as InternalVariable,
|
||||
fileOffset: parameter.fileOffset,
|
||||
);
|
||||
}
|
||||
Expression variableGet = intern.createVariableGet(
|
||||
parameter,
|
||||
fileOffset: parameter.fileOffset,
|
||||
);
|
||||
arguments.add(new PositionalArgument(variableGet));
|
||||
positionalCount++;
|
||||
}
|
||||
for (Variable parameter in redirectingFactoryFunction.namedParameters) {
|
||||
for (InternalVariable parameter in namedParameters) {
|
||||
flowAnalysis.declare(
|
||||
parameter,
|
||||
new SharedTypeView(parameter.type),
|
||||
initialized: true,
|
||||
);
|
||||
NamedExpression namedExpression;
|
||||
if (isClosureContextLoweringEnabled) {
|
||||
namedExpression = new NamedExpression(
|
||||
parameter.name!,
|
||||
intern.createVariableGet(
|
||||
new InternalNamedParameter(
|
||||
astVariable: parameter as NamedParameter,
|
||||
isImplicitlyTyped: false,
|
||||
fileOffset: parameter.fileOffset,
|
||||
),
|
||||
fileOffset: parameter.fileOffset,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
namedExpression = new NamedExpression(
|
||||
parameter.name!,
|
||||
intern.createVariableGet(
|
||||
parameter as InternalVariable,
|
||||
fileOffset: parameter.fileOffset,
|
||||
),
|
||||
);
|
||||
}
|
||||
NamedExpression namedExpression = new NamedExpression(
|
||||
parameter.cosmeticName!,
|
||||
intern.createVariableGet(parameter, fileOffset: parameter.fileOffset),
|
||||
);
|
||||
|
||||
arguments.add(new NamedArgument(namedExpression));
|
||||
}
|
||||
// If arguments are created using [ArgumentsImpl], and the
|
||||
@@ -451,7 +436,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
required ConstructorContext constructorContext,
|
||||
required List<Initializer> initializers,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required bool isConstructorWithoutBody,
|
||||
}) {
|
||||
@@ -554,8 +539,8 @@ class TypeInferrerImplBenchmarked implements TypeInferrer {
|
||||
AssignedVariablesImpl get assignedVariables => impl.assignedVariables;
|
||||
|
||||
@override
|
||||
FlowAnalysis<TreeNode, Statement, Expression, Variable> get flowAnalysis =>
|
||||
impl.flowAnalysis;
|
||||
FlowAnalysis<TreeNode, Statement, Expression, InternalVariable>
|
||||
get flowAnalysis => impl.flowAnalysis;
|
||||
|
||||
@override
|
||||
TypeSchemaEnvironment get typeSchemaEnvironment => impl.typeSchemaEnvironment;
|
||||
@@ -566,7 +551,7 @@ class TypeInferrerImplBenchmarked implements TypeInferrer {
|
||||
DartType? declaredType,
|
||||
required Expression initializer,
|
||||
required InferenceDefaultType inferenceDefaultType,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
}) {
|
||||
benchmarker.beginSubdivide(BenchmarkSubdivides.inferFieldInitializer);
|
||||
InferredFieldInitializer result = impl.inferFieldInitializer(
|
||||
@@ -588,7 +573,7 @@ class TypeInferrerImplBenchmarked implements TypeInferrer {
|
||||
required AsyncModifier asyncModifier,
|
||||
required Statement body,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ScopeProviderInfo? scopeProviderInfo,
|
||||
required ContextAllocationStrategy contextAllocationStrategy,
|
||||
required ConstructorContext? constructorContext,
|
||||
@@ -618,7 +603,7 @@ class TypeInferrerImplBenchmarked implements TypeInferrer {
|
||||
required ConstructorContext constructorContext,
|
||||
required List<Initializer> initializers,
|
||||
required List<InternalVariable> parameters,
|
||||
required ThisVariable? internalThisVariable,
|
||||
required InternalThisVariable? internalThisVariable,
|
||||
required ContextAllocationStrategy<ScopeProviderInfo>
|
||||
contextAllocationStrategy,
|
||||
required bool isConstructorWithoutBody,
|
||||
|
||||
@@ -14,17 +14,19 @@ import 'package:kernel/src/hierarchy_based_type_environment.dart'
|
||||
import 'package:kernel/type_algebra.dart';
|
||||
import 'package:kernel/type_environment.dart';
|
||||
|
||||
import '../kernel/internal_ast.dart';
|
||||
import 'standard_bounds.dart' show TypeSchemaStandardBounds;
|
||||
import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
|
||||
import 'type_inference_engine.dart';
|
||||
import 'type_demotion.dart';
|
||||
import 'type_schema.dart' show UnknownType;
|
||||
|
||||
typedef GeneratedTypeConstraint = shared.GeneratedTypeConstraint<Variable>;
|
||||
typedef GeneratedTypeConstraint =
|
||||
shared.GeneratedTypeConstraint<InternalVariable>;
|
||||
|
||||
typedef MergedTypeConstraint =
|
||||
shared.MergedTypeConstraint<
|
||||
Variable,
|
||||
InternalVariable,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration,
|
||||
TreeNode
|
||||
@@ -32,7 +34,7 @@ typedef MergedTypeConstraint =
|
||||
|
||||
typedef UnknownTypeConstraintOrigin =
|
||||
shared.UnknownTypeConstraintOrigin<
|
||||
Variable,
|
||||
InternalVariable,
|
||||
TypeDeclarationType,
|
||||
TypeDeclaration,
|
||||
TreeNode
|
||||
|
||||
@@ -52,7 +52,8 @@ import 'package:kernel/ast.dart'
|
||||
TypeParameter,
|
||||
Variable,
|
||||
VariableGet,
|
||||
defaultLanguageVersion;
|
||||
defaultLanguageVersion,
|
||||
LegacyVariable;
|
||||
import 'package:kernel/class_hierarchy.dart';
|
||||
import 'package:kernel/core_types.dart';
|
||||
import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;
|
||||
@@ -177,9 +178,8 @@ Future<void> main() async {
|
||||
new TypeParameter("T", const DynamicType(), const DynamicType()),
|
||||
loader: null,
|
||||
);
|
||||
InternalVariable variable = new VariableDeclarationImpl(
|
||||
null,
|
||||
isSynthesized: true,
|
||||
InternalVariable variable = new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable(null, isSynthesized: true),
|
||||
fileOffset: -1,
|
||||
);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:_fe_analyzer_shared/src/testing/id.dart'
|
||||
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
|
||||
show DataInterpreter, runTests;
|
||||
import 'package:_fe_analyzer_shared/src/type_inference/assigned_variables.dart';
|
||||
import 'package:front_end/src/kernel/internal_ast.dart';
|
||||
import 'package:front_end/src/source/source_loader.dart';
|
||||
import 'package:front_end/src/source/source_member_builder.dart';
|
||||
import 'package:front_end/src/testing/id_testing_helper.dart';
|
||||
@@ -50,10 +51,11 @@ class AssignedVariablesDataComputer extends CfeDataComputer<_Data> {
|
||||
Map<Id, ActualData<_Data>> actualMap, {
|
||||
bool? verbose,
|
||||
}) {
|
||||
SourceMemberBuilder memberBuilder =
|
||||
lookupMemberBuilder(testResultData.compilerResult, member)
|
||||
as SourceMemberBuilder;
|
||||
AssignedVariablesForTesting<TreeNode, Variable>? assignedVariables =
|
||||
SourceMemberBuilder memberBuilder = lookupMemberBuilder(
|
||||
testResultData.compilerResult,
|
||||
member,
|
||||
) as SourceMemberBuilder;
|
||||
AssignedVariablesForTesting<TreeNode, InternalVariable>? assignedVariables =
|
||||
memberBuilder
|
||||
.dataForTesting!
|
||||
.inferenceData
|
||||
@@ -72,7 +74,8 @@ class AssignedVariablesDataComputer extends CfeDataComputer<_Data> {
|
||||
|
||||
class AssignedVariablesDataExtractor extends CfeDataExtractor<_Data> {
|
||||
final SourceLoaderDataForTesting _sourceLoaderDataForTesting;
|
||||
final AssignedVariablesForTesting<TreeNode, Variable> _assignedVariables;
|
||||
final AssignedVariablesForTesting<TreeNode, InternalVariable>
|
||||
_assignedVariables;
|
||||
|
||||
new(
|
||||
InternalCompilerResult compilerResult,
|
||||
|
||||
+109
-63
@@ -226,10 +226,16 @@ void _testVariableDeclarations() {
|
||||
testStatement(
|
||||
forest.variablesDeclaration([
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('a', fileOffset: TreeNode.noOffset),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('a'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('b', fileOffset: TreeNode.noOffset),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('b'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
),
|
||||
], dummyUri),
|
||||
'''
|
||||
@@ -238,16 +244,14 @@ dynamic a, b;''',
|
||||
testStatement(
|
||||
forest.variablesDeclaration([
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'a',
|
||||
type: const VoidType(),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('a', type: const VoidType()),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'b',
|
||||
initializer: new NullLiteral(),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('b', initializer: new NullLiteral()),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
),
|
||||
@@ -263,23 +267,35 @@ void _testTryStatement() {
|
||||
Block returnBlock1 = new Block([new ReturnStatement()]);
|
||||
Block returnBlock2 = new Block([new ReturnStatement()]);
|
||||
InternalCatch emptyCatchBlock = new InternalCatch(
|
||||
exception: new VariableDeclarationImpl('e', fileOffset: TreeNode.noOffset),
|
||||
exception: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('e'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
body: new Block([]),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
);
|
||||
InternalCatch emptyCatchBlockOnVoid = new InternalCatch(
|
||||
exception: new VariableDeclarationImpl('e', fileOffset: TreeNode.noOffset),
|
||||
exception: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('e'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
body: new Block([]),
|
||||
guard: const VoidType(),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
);
|
||||
InternalCatch returnCatchBlock = new InternalCatch(
|
||||
exception: new VariableDeclarationImpl('e', fileOffset: TreeNode.noOffset),
|
||||
exception: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('e'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
body: new Block([new ReturnStatement()]),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
);
|
||||
InternalCatch returnCatchBlockOnVoid = new InternalCatch(
|
||||
exception: new VariableDeclarationImpl('e', fileOffset: TreeNode.noOffset),
|
||||
exception: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('e'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
body: new Block([new ReturnStatement()]),
|
||||
guard: const VoidType(),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
@@ -393,7 +409,11 @@ void _testInternalForInStatement() {
|
||||
new InternalForInStatement(
|
||||
new SingleVariableDeclarationForInElement(
|
||||
variableDeclaration: new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('e', fileOffset: -1),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('e'),
|
||||
isImplicitlyTyped: true,
|
||||
fileOffset: -1,
|
||||
),
|
||||
),
|
||||
error: null,
|
||||
),
|
||||
@@ -411,9 +431,8 @@ for (var e in null) {}''',
|
||||
new InternalForInStatement(
|
||||
new SingleVariableDeclarationForInElement(
|
||||
variableDeclaration: new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'e',
|
||||
type: const VoidType(),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('e', type: const VoidType()),
|
||||
fileOffset: -1,
|
||||
),
|
||||
),
|
||||
@@ -436,16 +455,16 @@ for (void e in null) {}''',
|
||||
patterns: [
|
||||
new InternalVariablePattern(
|
||||
type: const VoidType(),
|
||||
variable: new VariableDeclarationImpl(
|
||||
'a',
|
||||
variable: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('a'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
new InternalVariablePattern(
|
||||
type: null,
|
||||
variable: new VariableDeclarationImpl(
|
||||
'b',
|
||||
variable: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('b'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
@@ -468,7 +487,10 @@ for (var (void a, var b) in null) {}''',
|
||||
testStatement(
|
||||
new InternalForInStatement(
|
||||
new ExistingVariableForInElement(
|
||||
variable: new VariableDeclarationImpl('a', fileOffset: -1),
|
||||
variable: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('a'),
|
||||
fileOffset: -1,
|
||||
),
|
||||
nameOffset: -1,
|
||||
inOffset: -1,
|
||||
),
|
||||
@@ -557,10 +579,18 @@ for (null in null) {}''',
|
||||
new MultiVariableDeclarationForInElement(
|
||||
variableDeclarations: [
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('a', fileOffset: -1),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('a'),
|
||||
isImplicitlyTyped: true,
|
||||
fileOffset: -1,
|
||||
),
|
||||
),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('b', fileOffset: -1),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('b'),
|
||||
isImplicitlyTyped: true,
|
||||
fileOffset: -1,
|
||||
),
|
||||
),
|
||||
],
|
||||
error: new InvalidExpression('error'),
|
||||
@@ -580,14 +610,16 @@ for (var a, b in null) {}''',
|
||||
new MultiVariableDeclarationForInElement(
|
||||
variableDeclarations: [
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'a',
|
||||
type: const VoidType(),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('a', type: const VoidType()),
|
||||
fileOffset: -1,
|
||||
),
|
||||
),
|
||||
new InternalVariableDeclaration(
|
||||
new VariableDeclarationImpl('b', fileOffset: -1),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('b'),
|
||||
fileOffset: -1,
|
||||
),
|
||||
),
|
||||
],
|
||||
error: new InvalidExpression('error'),
|
||||
@@ -882,9 +914,10 @@ continue label0;''',
|
||||
void _testCascade() {
|
||||
// TODO(johnniwinther): Add better text representation support for internal
|
||||
// synthetic variables.
|
||||
InternalVariable variable = new VariableDeclarationImpl.forValue(
|
||||
new IntLiteral(0),
|
||||
)..name = '#0';
|
||||
InternalVariable variable = new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable.forValue(new IntLiteral(0))..name = '#0',
|
||||
fileOffset: TreeNode.noOffset,
|
||||
);
|
||||
Cascade cascade = new Cascade(variable, isNullAware: false);
|
||||
testExpression(cascade, '''
|
||||
let final dynamic #0 = 0 in cascade {} => #0''');
|
||||
@@ -933,8 +966,11 @@ void _testDeferredCheck() {
|
||||
library,
|
||||
'pre',
|
||||
);
|
||||
InternalVariable check = new VariableDeclarationImpl.forValue(
|
||||
new CheckLibraryIsLoaded(dependency),
|
||||
InternalVariable check = new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable.forValue(
|
||||
new CheckLibraryIsLoaded(dependency),
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
);
|
||||
testExpression(
|
||||
new DeferredCheck(check, new IntLiteral(0), fileOffset: TreeNode.noOffset),
|
||||
@@ -1267,8 +1303,8 @@ const library test:dummy::Typedef<void>.foo(0, bar: 1)''',
|
||||
void _testFunctionDeclarationImpl() {
|
||||
testStatement(
|
||||
new InternalFunctionDeclaration(
|
||||
variable: new VariableDeclarationImpl(
|
||||
'foo',
|
||||
variable: new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('foo'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
@@ -1504,65 +1540,75 @@ return 0;''');
|
||||
|
||||
void _testVariableDeclarationImpl() {
|
||||
testVariableDeclaration(
|
||||
new VariableDeclarationImpl('foo', fileOffset: TreeNode.noOffset),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('foo'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
'''
|
||||
dynamic foo''',
|
||||
);
|
||||
testVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'foo',
|
||||
initializer: new IntLiteral(0),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('foo', initializer: new IntLiteral(0)),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
'''
|
||||
dynamic foo = 0''',
|
||||
);
|
||||
testVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
isFinal: true,
|
||||
isRequired: true,
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
isFinal: true,
|
||||
isRequired: true,
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
'''
|
||||
required final void foo''',
|
||||
);
|
||||
testVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
isLate: true,
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
isLate: true,
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
'''
|
||||
late void foo = 0''',
|
||||
);
|
||||
testVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
)
|
||||
..lateGetter = new VariableDeclarationImpl(
|
||||
'foo#getter',
|
||||
..lateGetter = new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('foo#getter'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
),
|
||||
'''
|
||||
late void foo = 0''',
|
||||
);
|
||||
testVariableDeclaration(
|
||||
new VariableDeclarationImpl(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable(
|
||||
'foo',
|
||||
type: const VoidType(),
|
||||
initializer: new IntLiteral(0),
|
||||
),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
)
|
||||
..lateGetter = new VariableDeclarationImpl(
|
||||
'foo#getter',
|
||||
..lateGetter = new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('foo#getter'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
)
|
||||
..lateType = const DynamicType(),
|
||||
@@ -1981,8 +2027,8 @@ void _testPropertyIncDec() {
|
||||
}
|
||||
|
||||
void _testLocalIncDec() {
|
||||
VariableDeclarationImpl variable = new VariableDeclarationImpl(
|
||||
'foo',
|
||||
InternalLegacyVariable variable = new InternalLegacyVariable(
|
||||
astVariable: new LegacyVariable('foo'),
|
||||
fileOffset: TreeNode.noOffset,
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2026, 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.
|
||||
|
||||
// Derived from tests/language/why_not_promoted/assignment_error_test.dart
|
||||
|
||||
abstract class C {
|
||||
C? operator +(int i);
|
||||
int get cProperty => 0;
|
||||
}
|
||||
|
||||
direct_assignment(int? i, int? j) {
|
||||
if (i == null) return;
|
||||
i = j;
|
||||
i.isEven;
|
||||
}
|
||||
|
||||
compound_assignment(C? c, int i) {
|
||||
if (c == null) return;
|
||||
c += i;
|
||||
c.cProperty;
|
||||
}
|
||||
|
||||
via_postfix_op(C? c) {
|
||||
if (c == null) return;
|
||||
c++;
|
||||
c.cProperty;
|
||||
}
|
||||
|
||||
via_prefix_op(C? c) {
|
||||
if (c == null) return;
|
||||
++c;
|
||||
c.cProperty;
|
||||
}
|
||||
|
||||
via_for_each_statement(int? i, List<int?> list) {
|
||||
if (i == null) return;
|
||||
for (i in list) {
|
||||
i.isEven;
|
||||
}
|
||||
}
|
||||
|
||||
via_for_each_list_element(int? i, List<int?> list) {
|
||||
if (i == null) return;
|
||||
[for (i in list) i.isEven];
|
||||
}
|
||||
|
||||
via_for_each_set_element(int? i, List<int?> list) {
|
||||
if (i == null) return;
|
||||
({for (i in list) i.isEven});
|
||||
}
|
||||
|
||||
via_for_each_map_key(int? i, List<int?> list) {
|
||||
if (i == null) return;
|
||||
({for (i in list) i.isEven: null});
|
||||
}
|
||||
|
||||
via_for_each_map_value(int? i, List<int?> list) {
|
||||
if (i == null) return;
|
||||
({for (i in list) null: i.isEven});
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:15:5: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// i.isEven;
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:14:3: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// i = j;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:21:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:20:3: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// c += i;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:27:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:26:3: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// c++;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:33:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:32:5: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ++c;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:39:7: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// i.isEven;
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:38:8: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// for (i in list) {
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:22: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// [for (i in list) i.isEven];
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:9: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// [for (i in list) i.isEven];
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) i.isEven});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) i.isEven});
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) i.isEven: null});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) i.isEven: null});
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:29: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) null: i.isEven});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) null: i.isEven});
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
|
||||
abstract class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
abstract operator +(core::int i) → self::C?;
|
||||
get cProperty() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method direct_assignment(core::int? i, core::int? j) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
i = j;
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:15:5: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
i.isEven;
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool};
|
||||
}
|
||||
static method compound_assignment(self::C? c, core::int i) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(i){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:21:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_postfix_op(self::C? c) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(1){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:27:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_prefix_op(self::C? c) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(1){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:33:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_for_each_statement(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
for (final core::int? #t1 in list) {
|
||||
i = #t1;
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:39:7: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
i.isEven;
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool};
|
||||
}
|
||||
}
|
||||
static method via_for_each_list_element(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::List<core::bool> #t2 = <core::bool>[];
|
||||
for (final core::int? #t3 in list) {
|
||||
i = #t3;
|
||||
#t2.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:22: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
[for (i in list) i.isEven];
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(core::bool) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_set_element(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Set<core::bool> #t4 = col::LinkedHashSet::•<core::bool>();
|
||||
for (final core::int? #t5 in list) {
|
||||
i = #t5;
|
||||
#t4.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) i.isEven});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(core::bool) → core::bool};
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_map_key(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Map<core::bool, Null> #t6 = <core::bool, Null>{};
|
||||
for (final core::int? #t7 in list) {
|
||||
i = #t7;
|
||||
#t6.{core::Map::[]=}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) i.isEven: null});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}, null){(core::bool, Null) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_map_value(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Map<Null, core::bool> #t8 = <Null, core::bool>{};
|
||||
for (final core::int? #t9 in list) {
|
||||
i = #t9;
|
||||
#t8.{core::Map::[]=}{Invariant}(null, invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:29: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) null: i.isEven});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(Null, core::bool) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:15:5: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// i.isEven;
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:14:3: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// i = j;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:21:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:20:3: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// c += i;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:27:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:26:3: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// c++;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:33:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:32:5: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ++c;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:39:7: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// i.isEven;
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:38:8: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// for (i in list) {
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:22: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// [for (i in list) i.isEven];
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:9: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// [for (i in list) i.isEven];
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) i.isEven});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) i.isEven});
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) i.isEven: null});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) i.isEven: null});
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:29: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) null: i.isEven});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) null: i.isEven});
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
|
||||
abstract class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
abstract operator +(core::int i) → self::C?;
|
||||
get cProperty() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method direct_assignment(core::int? i, core::int? j) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
i = j;
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:15:5: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
i.isEven;
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool};
|
||||
}
|
||||
static method compound_assignment(self::C? c, core::int i) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(i){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:21:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_postfix_op(self::C? c) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(1){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:27:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_prefix_op(self::C? c) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(1){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:33:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_for_each_statement(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
for (final core::int? #t1 in list) {
|
||||
i = #t1;
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:39:7: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
i.isEven;
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool};
|
||||
}
|
||||
}
|
||||
static method via_for_each_list_element(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::List<core::bool> #t2 = <core::bool>[];
|
||||
for (final core::int? #t3 in list) {
|
||||
i = #t3;
|
||||
#t2.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:22: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
[for (i in list) i.isEven];
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(core::bool) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_set_element(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Set<core::bool> #t4 = col::LinkedHashSet::•<core::bool>();
|
||||
for (final core::int? #t5 in list) {
|
||||
i = #t5;
|
||||
#t4.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) i.isEven});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(core::bool) → core::bool};
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_map_key(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Map<core::bool, Null> #t6 = <core::bool, Null>{};
|
||||
for (final core::int? #t7 in list) {
|
||||
i = #t7;
|
||||
#t6.{core::Map::[]=}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) i.isEven: null});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}, null){(core::bool, Null) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_map_value(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Map<Null, core::bool> #t8 = <Null, core::bool>{};
|
||||
for (final core::int? #t9 in list) {
|
||||
i = #t9;
|
||||
#t8.{core::Map::[]=}{Invariant}(null, invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:29: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) null: i.isEven});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(Null, core::bool) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
library;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
abstract class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
;
|
||||
abstract operator +(core::int i) → self::C?;
|
||||
get cProperty() → core::int
|
||||
;
|
||||
}
|
||||
static method direct_assignment(core::int? i, core::int? j) → dynamic
|
||||
;
|
||||
static method compound_assignment(self::C? c, core::int i) → dynamic
|
||||
;
|
||||
static method via_postfix_op(self::C? c) → dynamic
|
||||
;
|
||||
static method via_prefix_op(self::C? c) → dynamic
|
||||
;
|
||||
static method via_for_each_statement(core::int? i, core::List<core::int?> list) → dynamic
|
||||
;
|
||||
static method via_for_each_list_element(core::int? i, core::List<core::int?> list) → dynamic
|
||||
;
|
||||
static method via_for_each_set_element(core::int? i, core::List<core::int?> list) → dynamic
|
||||
;
|
||||
static method via_for_each_map_key(core::int? i, core::List<core::int?> list) → dynamic
|
||||
;
|
||||
static method via_for_each_map_value(core::int? i, core::List<core::int?> list) → dynamic
|
||||
;
|
||||
@@ -0,0 +1,236 @@
|
||||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:15:5: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// i.isEven;
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:14:3: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// i = j;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:21:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:20:3: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// c += i;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:27:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:26:3: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// c++;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:33:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
// - 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
// Try accessing using ?. instead.
|
||||
// c.cProperty;
|
||||
// ^^^^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:32:5: Context: Variable 'c' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ++c;
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:39:7: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// i.isEven;
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:38:8: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// for (i in list) {
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:22: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// [for (i in list) i.isEven];
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:9: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// [for (i in list) i.isEven];
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) i.isEven});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) i.isEven});
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) i.isEven: null});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) i.isEven: null});
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:29: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
// Try accessing using ?. instead.
|
||||
// ({for (i in list) null: i.isEven});
|
||||
// ^^^^^^
|
||||
// pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:10: Context: Variable 'i' could not be promoted due to an assignment.
|
||||
// Try null checking the variable after the assignment. See http://dart.dev/go/non-promo-write
|
||||
// ({for (i in list) null: i.isEven});
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:_compact_hash" as _co;
|
||||
|
||||
abstract class C extends core::Object {
|
||||
synthetic constructor •() → self::C
|
||||
: super core::Object::•()
|
||||
;
|
||||
abstract operator +(core::int i) → self::C?;
|
||||
get cProperty() → core::int
|
||||
return 0;
|
||||
}
|
||||
static method direct_assignment(core::int? i, core::int? j) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
i = j;
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:15:5: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
i.isEven;
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool};
|
||||
}
|
||||
static method compound_assignment(self::C? c, core::int i) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(i){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:21:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_postfix_op(self::C? c) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(1){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:27:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_prefix_op(self::C? c) → dynamic {
|
||||
if(c == null)
|
||||
return;
|
||||
c = c{self::C}.{self::C::+}(1){(core::int) → self::C?};
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:33:5: Error: Property 'cProperty' cannot be accessed on 'C?' because it is potentially null.
|
||||
- 'C' is from 'pkg/front_end/testcases/nnbd/why_not_promoted.dart'.
|
||||
Try accessing using ?. instead.
|
||||
c.cProperty;
|
||||
^^^^^^^^^" in c.{self::C::cProperty}{<nullable>}.{core::int};
|
||||
}
|
||||
static method via_for_each_statement(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
synthesized core::Iterator<core::int?> :sync-for-iterator = list.{core::Iterable::iterator}{core::Iterator<core::int?>};
|
||||
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
|
||||
final core::int? #t1 = :sync-for-iterator.{core::Iterator::current}{core::int?};
|
||||
{
|
||||
i = #t1;
|
||||
invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:39:7: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
i.isEven;
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_list_element(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::List<core::bool> #t2 = core::_GrowableList::•<core::bool>(0);
|
||||
{
|
||||
synthesized core::Iterator<core::int?> :sync-for-iterator = list.{core::Iterable::iterator}{core::Iterator<core::int?>};
|
||||
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
|
||||
final core::int? #t3 = :sync-for-iterator.{core::Iterator::current}{core::int?};
|
||||
{
|
||||
i = #t3;
|
||||
#t2.{core::List::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:45:22: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
[for (i in list) i.isEven];
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(core::bool) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_set_element(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Set<core::bool> #t4 = new _co::_Set::•<core::bool>();
|
||||
{
|
||||
synthesized core::Iterator<core::int?> :sync-for-iterator = list.{core::Iterable::iterator}{core::Iterator<core::int?>};
|
||||
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
|
||||
final core::int? #t5 = :sync-for-iterator.{core::Iterator::current}{core::int?};
|
||||
{
|
||||
i = #t5;
|
||||
#t4.{core::Set::add}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:50:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) i.isEven});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(core::bool) → core::bool};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_map_key(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Map<core::bool, Null> #t6 = <core::bool, Null>{};
|
||||
{
|
||||
synthesized core::Iterator<core::int?> :sync-for-iterator = list.{core::Iterable::iterator}{core::Iterator<core::int?>};
|
||||
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
|
||||
final core::int? #t7 = :sync-for-iterator.{core::Iterator::current}{core::int?};
|
||||
{
|
||||
i = #t7;
|
||||
#t6.{core::Map::[]=}{Invariant}(invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:55:23: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) i.isEven: null});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}, null){(core::bool, Null) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static method via_for_each_map_value(core::int? i, core::List<core::int?> list) → dynamic {
|
||||
if(i == null)
|
||||
return;
|
||||
{
|
||||
final core::Map<Null, core::bool> #t8 = <Null, core::bool>{};
|
||||
{
|
||||
synthesized core::Iterator<core::int?> :sync-for-iterator = list.{core::Iterable::iterator}{core::Iterator<core::int?>};
|
||||
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
|
||||
final core::int? #t9 = :sync-for-iterator.{core::Iterator::current}{core::int?};
|
||||
{
|
||||
i = #t9;
|
||||
#t8.{core::Map::[]=}{Invariant}(null, invalid-expression "pkg/front_end/testcases/nnbd/why_not_promoted.dart:60:29: Error: Property 'isEven' cannot be accessed on 'int?' because it is potentially null.
|
||||
Try accessing using ?. instead.
|
||||
({for (i in list) null: i.isEven});
|
||||
^^^^^^" in i.{core::int::isEven}{<nullable>}.{core::bool}){(Null, core::bool) → void};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
abstract class C {
|
||||
C? operator +(int i);
|
||||
int get cProperty => 0;
|
||||
}
|
||||
|
||||
direct_assignment(int? i, int? j) {}
|
||||
|
||||
compound_assignment(C? c, int i) {}
|
||||
|
||||
via_postfix_op(C? c) {}
|
||||
|
||||
via_prefix_op(C? c) {}
|
||||
|
||||
via_for_each_statement(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_list_element(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_set_element(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_map_key(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_map_value(int? i, List<int?> list) {}
|
||||
@@ -0,0 +1,22 @@
|
||||
abstract class C {
|
||||
C? operator +(int i);
|
||||
int get cProperty => 0;
|
||||
}
|
||||
|
||||
compound_assignment(C? c, int i) {}
|
||||
|
||||
direct_assignment(int? i, int? j) {}
|
||||
|
||||
via_for_each_list_element(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_map_key(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_map_value(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_set_element(int? i, List<int?> list) {}
|
||||
|
||||
via_for_each_statement(int? i, List<int?> list) {}
|
||||
|
||||
via_postfix_op(C? c) {}
|
||||
|
||||
via_prefix_op(C? c) {}
|
||||
@@ -147,7 +147,7 @@ type CanonicalName {
|
||||
|
||||
type ComponentFile {
|
||||
UInt32 magic = 0x90ABCDEF;
|
||||
UInt32 formatVersion = 131;
|
||||
UInt32 formatVersion = 132;
|
||||
Byte[10] shortSdkHash;
|
||||
List<String> problemsAsJson; // Described in problems.md.
|
||||
Library[] libraries;
|
||||
@@ -1743,6 +1743,7 @@ type AssignedVariablePattern extends Pattern {
|
||||
Byte tag = 129;
|
||||
FileOffset fileOffset;
|
||||
VariableReference variable;
|
||||
Option<VariableReference> setter;
|
||||
Option<DartType> matchedType;
|
||||
Byte needsCast;
|
||||
}
|
||||
|
||||
@@ -2237,6 +2237,10 @@ class BinaryBuilder {
|
||||
variableStack.addAll(variables);
|
||||
}
|
||||
|
||||
Variable? readVariableReferenceOption() {
|
||||
return readAndCheckOptionTag() ? readVariableReference() : null;
|
||||
}
|
||||
|
||||
Variable readVariableReference() {
|
||||
readUInt30(); // offset of the variable declaration in the binary.
|
||||
return _readVariableReferenceInternal();
|
||||
@@ -3311,12 +3315,14 @@ class BinaryBuilder {
|
||||
AssignedVariablePattern _readAssignedVariablePattern() {
|
||||
int fileOffset = readOffset();
|
||||
Variable variable = readVariableReference();
|
||||
Variable? setter = readVariableReferenceOption();
|
||||
DartType? matchedType = readDartTypeOption();
|
||||
bool needsCheck = readByte() == 1;
|
||||
return AssignedVariablePattern(variable)
|
||||
..fileOffset = fileOffset
|
||||
..matchedValueType = matchedType
|
||||
..needsCast = needsCheck;
|
||||
..needsCast = needsCheck
|
||||
..setter = setter;
|
||||
}
|
||||
|
||||
CastPattern _readCastPattern() {
|
||||
|
||||
@@ -2864,6 +2864,15 @@ class BinaryPrinter
|
||||
writeNode(node.receiver);
|
||||
}
|
||||
|
||||
void _writeVariableReferenceOption(Variable? variable) {
|
||||
if (variable == null) {
|
||||
writeByte(Tag.Nothing);
|
||||
} else {
|
||||
writeByte(Tag.Something);
|
||||
_writeVariableReference(variable);
|
||||
}
|
||||
}
|
||||
|
||||
void _writeVariableReference(Variable variable) {
|
||||
int index = _getVariableIndex(variable);
|
||||
writeUInt30(variable.binaryOffsetNoTag);
|
||||
@@ -2883,6 +2892,7 @@ class BinaryPrinter
|
||||
writeByte(Tag.AssignedVariablePattern);
|
||||
writeOffset(node.fileOffset);
|
||||
_writeVariableReference(node.variable);
|
||||
_writeVariableReferenceOption(node.setter);
|
||||
writeOptionalNode(node.matchedValueType);
|
||||
writeByte(node.needsCast ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ class Tag {
|
||||
/// Internal version of kernel binary format.
|
||||
/// Bump it when making incompatible changes in kernel binaries.
|
||||
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
|
||||
static const int BinaryFormatVersion = 131;
|
||||
static const int BinaryFormatVersion = 132;
|
||||
}
|
||||
|
||||
abstract class ConstantTag {
|
||||
|
||||
@@ -871,6 +871,10 @@ class WildcardPattern extends Pattern {
|
||||
class AssignedVariablePattern extends Pattern {
|
||||
final Variable variable;
|
||||
|
||||
/// If [variable] is a lowered late variable, [setter] holds the variable of
|
||||
/// the local function that should be used for assignment.
|
||||
Variable? setter;
|
||||
|
||||
/// The type of the expression against which this pattern is matched.
|
||||
///
|
||||
/// This is set during inference.
|
||||
|
||||
@@ -4996,6 +4996,9 @@ class EquivalenceStrategy {
|
||||
if (!checkAssignedVariablePattern_variable(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkAssignedVariablePattern_setter(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
if (!checkAssignedVariablePattern_matchedValueType(visitor, node, other)) {
|
||||
result = visitor.resultOnInequivalence;
|
||||
}
|
||||
@@ -11972,6 +11975,14 @@ class EquivalenceStrategy {
|
||||
return visitor.checkNodes(node.variable, other.variable, 'variable');
|
||||
}
|
||||
|
||||
bool checkAssignedVariablePattern_setter(
|
||||
EquivalenceVisitor visitor,
|
||||
AssignedVariablePattern node,
|
||||
AssignedVariablePattern other,
|
||||
) {
|
||||
return visitor.checkNodes(node.setter, other.setter, 'setter');
|
||||
}
|
||||
|
||||
bool checkAssignedVariablePattern_matchedValueType(
|
||||
EquivalenceVisitor visitor,
|
||||
AssignedVariablePattern node,
|
||||
|
||||
+4
-4
@@ -12,13 +12,13 @@ RESULT: t3
|
||||
%this = _Parameter #0 [_T (#lib::C)+]
|
||||
%x = _Parameter #1
|
||||
t2 = _Extract (%this[#lib::C/0])
|
||||
t3 = _TypeCheck (%x against t2) (for #lib::C.T% x)
|
||||
t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;)
|
||||
RESULT: t3
|
||||
------------ C.id2 ------------
|
||||
%this = _Parameter #0 [_T (#lib::C)+]
|
||||
%x = _Parameter #1
|
||||
t2 = _Extract (%this[#lib::C/0])
|
||||
t3 = _TypeCheck (%x against t2) (for #lib::C.T% x)
|
||||
t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;)
|
||||
RESULT: t3
|
||||
------------ D. ------------
|
||||
%this = _Parameter #0 [_T (#lib::D)+]
|
||||
@@ -77,7 +77,7 @@ RESULT: _T {}
|
||||
%x = _Parameter #1
|
||||
t2 = _Extract (%this[#lib::C2/0])
|
||||
t3 = _CreateRuntimeType (dart.core::Comparable @ (t2))
|
||||
t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T%> x)
|
||||
t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T%> x;)
|
||||
RESULT: t4
|
||||
------------ C2.id4 ------------
|
||||
%this = _Parameter #0 [_T (#lib::C2)+]
|
||||
@@ -85,7 +85,7 @@ RESULT: t4
|
||||
t2 = _Extract (%this[#lib::C2/0])
|
||||
t3 = _CreateRuntimeType (#lib::I @ (t2))
|
||||
t4 = _CreateRuntimeType (#lib::K @ (t3))
|
||||
t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T%>> x)
|
||||
t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T%>> x;)
|
||||
RESULT: t5
|
||||
------------ main ------------
|
||||
t0* = _Call direct [#lib::C.] (_T (#lib::C<dart.core::int>))
|
||||
|
||||
+2
-2
@@ -17,9 +17,9 @@ RESULT: _T {}
|
||||
%key = _Parameter #1
|
||||
%value = _Parameter #2
|
||||
t3 = _Extract (%this[#lib::_NotRealHashMap/0])
|
||||
t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K% key)
|
||||
t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K% key;)
|
||||
t5 = _Extract (%this[#lib::_NotRealHashMap/1])
|
||||
t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V% value)
|
||||
t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V% value;)
|
||||
RESULT: _T {}?
|
||||
------------ InheritedElement. ------------
|
||||
%this = _Parameter #0 [_T (#lib::InheritedElement)+]
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace kernel {
|
||||
// package:kernel/binary.md.
|
||||
|
||||
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
|
||||
static const uint32_t kSupportedKernelFormatVersion = 131;
|
||||
static const uint32_t kSupportedKernelFormatVersion = 132;
|
||||
|
||||
// Keep in sync with package:kernel/lib/binary/tag.dart
|
||||
#define KERNEL_TAG_LIST(V) \
|
||||
|
||||
Reference in New Issue
Block a user