Version 2.18.0-245.0.dev
Merge commit '99919c69ba1f374a8d793bcfe43e2a1702a1b82b' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index d91b11e..fbcedf8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -387,7 +387,7 @@
new ExpressionInfo<Variable, Type>(after, ifFalse, ifTrue);
ExpressionInfo<Variable, Type>? rebaseForward(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
FlowModel<Variable, Type> base) =>
new ExpressionInfo(base, ifTrue.rebaseForward(typeOperations, base),
ifFalse.rebaseForward(typeOperations, base));
@@ -405,22 +405,22 @@
/// while visiting the code for type inference.
abstract class FlowAnalysis<Node extends Object, Statement extends Node,
Expression extends Object, Variable extends Object, Type extends Object> {
- factory FlowAnalysis(TypeOperations<Variable, Type> typeOperations,
+ factory FlowAnalysis(Operations<Variable, Type> operations,
AssignedVariables<Node, Variable> assignedVariables,
{required bool respectImplicitlyTypedVarInitializers}) {
- return new _FlowAnalysisImpl(typeOperations, assignedVariables,
+ return new _FlowAnalysisImpl(operations, assignedVariables,
respectImplicitlyTypedVarInitializers:
respectImplicitlyTypedVarInitializers);
}
- factory FlowAnalysis.legacy(TypeOperations<Variable, Type> typeOperations,
+ factory FlowAnalysis.legacy(Operations<Variable, Type> operations,
AssignedVariables<Node, Variable> assignedVariables) =
_LegacyTypePromotion;
/// Return `true` if the current state is reachable.
bool get isReachable;
- TypeOperations<Variable, Type> get typeOperations;
+ TypeOperations<Type> get operations;
/// Call this method after visiting an "as" expression.
///
@@ -1040,22 +1040,21 @@
bool _exceptionOccurred = false;
- factory FlowAnalysisDebug(TypeOperations<Variable, Type> typeOperations,
+ factory FlowAnalysisDebug(Operations<Variable, Type> operations,
AssignedVariables<Node, Variable> assignedVariables,
{required bool respectImplicitlyTypedVarInitializers}) {
print('FlowAnalysisDebug()');
return new FlowAnalysisDebug._(new _FlowAnalysisImpl(
- typeOperations, assignedVariables,
+ operations, assignedVariables,
respectImplicitlyTypedVarInitializers:
respectImplicitlyTypedVarInitializers));
}
- factory FlowAnalysisDebug.legacy(
- TypeOperations<Variable, Type> typeOperations,
+ factory FlowAnalysisDebug.legacy(Operations<Variable, Type> operations,
AssignedVariables<Node, Variable> assignedVariables) {
print('FlowAnalysisDebug.legacy()');
return new FlowAnalysisDebug._(
- new _LegacyTypePromotion(typeOperations, assignedVariables));
+ new _LegacyTypePromotion(operations, assignedVariables));
}
FlowAnalysisDebug._(this._wrapped);
@@ -1065,7 +1064,7 @@
_wrap('isReachable', () => _wrapped.isReachable, isQuery: true);
@override
- TypeOperations<Variable, Type> get typeOperations => _wrapped.typeOperations;
+ TypeOperations<Type> get operations => _wrapped.operations;
@override
void asExpression_end(Expression subExpression, Type type) {
@@ -1680,7 +1679,7 @@
/// assignments that occurred during the `try` block, to the extent that they
/// weren't invalidated by later assignments in the `finally` block.
FlowModel<Variable, Type> attachFinally(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
FlowModel<Variable, Type> beforeFinally,
FlowModel<Variable, Type> afterFinally) {
// Code that follows the `try/finally` is reachable iff the end of the `try`
@@ -1854,8 +1853,7 @@
/// regardless of the type of loop.
@visibleForTesting
FlowModel<Variable, Type> inheritTested(
- TypeOperations<Variable, Type> typeOperations,
- FlowModel<Variable, Type> other) {
+ TypeOperations<Type> typeOperations, FlowModel<Variable, Type> other) {
Map<Variable?, VariableModel<Variable, Type>> newVariableInfo =
<Variable?, VariableModel<Variable, Type>>{};
Map<Variable?, VariableModel<Variable, Type>> otherVariableInfo =
@@ -1893,8 +1891,7 @@
/// will be promoted in the output model, provided that hasn't been reassigned
/// since then (which would make the promotion unsound).
FlowModel<Variable, Type> rebaseForward(
- TypeOperations<Variable, Type> typeOperations,
- FlowModel<Variable, Type> base) {
+ TypeOperations<Type> typeOperations, FlowModel<Variable, Type> base) {
// The rebased model is reachable iff both `this` and the new base are
// reachable.
Reachability newReachable = reachable.rebaseForward(base.reachable);
@@ -2004,7 +2001,7 @@
/// Note that the state is only changed if the previous type of [variable] was
/// potentially nullable.
ExpressionInfo<Variable, Type> tryMarkNonNullable(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
ReferenceWithType<Variable, Type> referenceWithType) {
VariableModel<Variable, Type> info =
referenceWithType.reference.getInfo(variableInfo);
@@ -2038,7 +2035,7 @@
/// TODO(paulberry): if the type is non-nullable, should this method mark the
/// variable as definitely assigned? Does it matter?
FlowModel<Variable, Type> tryPromoteForTypeCast(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
ReferenceWithType<Variable, Type> referenceWithType,
Type type) {
VariableModel<Variable, Type> info =
@@ -2069,7 +2066,7 @@
/// TODO(paulberry): if the type is non-nullable, should this method mark the
/// variable as definitely assigned? Does it matter?
ExpressionInfo<Variable, Type> tryPromoteForTypeCheck(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
ReferenceWithType<Variable, Type> referenceWithType,
Type type) {
VariableModel<Variable, Type> info =
@@ -2136,13 +2133,13 @@
Variable variable,
Type writtenType,
SsaNode<Variable, Type> newSsaNode,
- TypeOperations<Variable, Type> typeOperations,
+ Operations<Variable, Type> operations,
{bool promoteToTypeOfInterest = true}) {
VariableModel<Variable, Type>? infoForVar = variableInfo[variable];
if (infoForVar == null) return this;
VariableModel<Variable, Type> newInfoForVar = infoForVar.write(
- nonPromotionReason, variable, writtenType, typeOperations, newSsaNode,
+ nonPromotionReason, variable, writtenType, operations, newSsaNode,
promoteToTypeOfInterest: promoteToTypeOfInterest);
if (identical(newInfoForVar, infoForVar)) return this;
@@ -2161,7 +2158,7 @@
/// no redundant or side-promotions)
/// - The variable should not be write-captured.
FlowModel<Variable, Type> _finishTypeTest(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
Reference<Variable, Type> reference,
VariableModel<Variable, Type> info,
Type? testedType,
@@ -2223,7 +2220,7 @@
/// less specific type promotion is kept.
static FlowModel<Variable, Type>
join<Variable extends Object, Type extends Object>(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
FlowModel<Variable, Type>? first,
FlowModel<Variable, Type>? second,
Map<Variable?, VariableModel<Variable, Type>> emptyVariableMap,
@@ -2255,7 +2252,7 @@
@visibleForTesting
static Map<Variable?, VariableModel<Variable, Type>>
joinVariableInfo<Variable extends Object, Type extends Object>(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
Map<Variable?, VariableModel<Variable, Type>> first,
Map<Variable?, VariableModel<Variable, Type>> second,
Map<Variable?, VariableModel<Variable, Type>> emptyMap,
@@ -2295,7 +2292,7 @@
/// merge of two control flow paths.
static FlowModel<Variable, Type>
merge<Variable extends Object, Type extends Object>(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
FlowModel<Variable, Type>? first,
FlowModel<Variable, Type>? second,
Map<Variable?, VariableModel<Variable, Type>> emptyVariableMap,
@@ -2424,6 +2421,11 @@
R visitThisNotPromoted(ThisNotPromoted reason);
}
+/// Operations on types and variables, abstracted from concrete type interfaces.
+abstract class Operations<Variable extends Object, Type extends Object>
+ extends TypeOperations<Type> implements VariableOperations<Variable, Type> {
+}
+
/// Non-promotion reason describing the situation where an expression was not
/// promoted due to the fact that it's a property get.
class PropertyNotPromoted<Type extends Object> extends NonPromotionReason {
@@ -2614,7 +2616,7 @@
Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
Map<Variable?, VariableModel<Variable, Type>> variableInfo,
Type staticType,
- TypeOperations<Variable, Type> typeOperations);
+ Operations<Variable, Type> operations);
/// Creates a reference representing a get of a property called [propertyName]
/// on the reference represented by `this`.
@@ -2711,7 +2713,7 @@
}
/// Operations on types, abstracted from concrete type interfaces.
-abstract class TypeOperations<Variable extends Object, Type extends Object> {
+abstract class TypeOperations<Type extends Object> {
/// Classifies the given type into one of the three categories defined by
/// the [TypeClassification] enum.
TypeClassification classifyType(Type type);
@@ -2765,9 +2767,6 @@
/// Tries to promote to the first type from the second type, and returns the
/// promoted type if it succeeds, otherwise null.
Type? tryPromoteToType(Type to, Type from);
-
- /// Return the static type of the given [variable].
- Type variableType(Variable variable);
}
/// An instance of the [VariableModel] class represents the information gathered
@@ -2905,7 +2904,7 @@
NonPromotionReason? nonPromotionReason,
Variable variable,
Type writtenType,
- TypeOperations<Variable, Type> typeOperations,
+ Operations<Variable, Type> operations,
SsaNode<Variable, Type> newSsaNode,
{required bool promoteToTypeOfInterest}) {
if (writeCaptured) {
@@ -2918,13 +2917,13 @@
}
_DemotionResult<Type> demotionResult =
- _demoteViaAssignment(writtenType, typeOperations, nonPromotionReason);
+ _demoteViaAssignment(writtenType, operations, nonPromotionReason);
List<Type>? newPromotedTypes = demotionResult.promotedTypes;
- Type declaredType = typeOperations.variableType(variable);
+ Type declaredType = operations.variableType(variable);
if (promoteToTypeOfInterest) {
newPromotedTypes = _tryPromoteToTypeOfInterest(
- typeOperations, declaredType, newPromotedTypes, writtenType);
+ operations, declaredType, newPromotedTypes, writtenType);
}
// TODO(paulberry): remove demotions from demotionResult.nonPromotionHistory
// that are no longer in effect due to re-promotion.
@@ -2972,7 +2971,7 @@
/// describing the reason for the potential demotion.
_DemotionResult<Type> _demoteViaAssignment(
Type writtenType,
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
NonPromotionReason? nonPromotionReason) {
List<Type>? promotedTypes = this.promotedTypes;
if (promotedTypes == null) {
@@ -3012,11 +3011,8 @@
///
/// Note that since promotion chains are considered immutable, if promotion
/// is required, a new promotion chain will be created and returned.
- List<Type>? _tryPromoteToTypeOfInterest(
- TypeOperations<Variable, Type> typeOperations,
- Type declaredType,
- List<Type>? promotedTypes,
- Type writtenType) {
+ List<Type>? _tryPromoteToTypeOfInterest(TypeOperations<Type> typeOperations,
+ Type declaredType, List<Type>? promotedTypes, Type writtenType) {
assert(!writeCaptured);
if (typeOperations.forcePromotion(
@@ -3129,7 +3125,7 @@
@visibleForTesting
static VariableModel<Variable, Type>
inheritTested<Variable extends Object, Type extends Object>(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
VariableModel<Variable, Type> model,
List<Type> tested) {
List<Type> newTested = joinTested(tested, model.tested, typeOperations);
@@ -3145,7 +3141,7 @@
/// Joins two variable models. See [FlowModel.join] for details.
static VariableModel<Variable, Type>
join<Variable extends Object, Type extends Object>(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
VariableModel<Variable, Type> first,
VariableModel<Variable, Type> second) {
List<Type>? newPromotedTypes = joinPromotedTypes(
@@ -3175,7 +3171,7 @@
joinPromotedTypes<Variable extends Object, Type extends Object>(
List<Type>? chain1,
List<Type>? chain2,
- TypeOperations<Variable, Type> typeOperations) {
+ TypeOperations<Type> typeOperations) {
if (chain1 == null) return chain1;
if (chain2 == null) return chain2;
@@ -3221,7 +3217,7 @@
static List<Type> joinTested<Variable extends Object, Type extends Object>(
List<Type> types1,
List<Type> types2,
- TypeOperations<Variable, Type> typeOperations) {
+ TypeOperations<Type> typeOperations) {
// Ensure that types1 is the shorter list.
if (types1.length > types2.length) {
List<Type> tmp = types1;
@@ -3259,7 +3255,7 @@
/// [thisPromotedTypes] or [basePromotedTypes] (to make it easier for the
/// caller to detect when data structures may be re-used).
static List<Type>? rebasePromotedTypes<Type extends Object>(
- TypeOperations<Object, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
List<Type>? thisPromotedTypes,
List<Type>? basePromotedTypes) {
if (basePromotedTypes == null) {
@@ -3297,9 +3293,7 @@
static List<Type>
_addTypeToUniqueList<Variable extends Object, Type extends Object>(
- List<Type> types,
- Type newType,
- TypeOperations<Variable, Type> typeOperations) {
+ List<Type> types, Type newType, TypeOperations<Type> typeOperations) {
if (_typeListContains(typeOperations, types, newType)) return types;
return new List<Type>.of(types)..add(newType);
}
@@ -3338,9 +3332,7 @@
}
static bool _typeListContains<Variable extends Object, Type extends Object>(
- TypeOperations<Variable, Type> typeOperations,
- List<Type> list,
- Type searchType) {
+ TypeOperations<Type> typeOperations, List<Type> list, Type searchType) {
for (Type type in list) {
if (typeOperations.isSameType(type, searchType)) return true;
}
@@ -3348,6 +3340,13 @@
}
}
+/// Operations on variables, abstracted from concrete type interfaces.
+abstract class VariableOperations<Variable extends Object,
+ Type extends Object> {
+ /// Returns the static type of the given [variable].
+ Type variableType(Variable variable);
+}
+
/// Specialization of [Reference] representing a reference to a local variable
/// (or function parameter).
@visibleForTesting
@@ -3362,7 +3361,7 @@
Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
Map<Variable?, VariableModel<Variable, Type>> variableInfo,
Type staticType,
- TypeOperations<Variable, Type> typeOperations) {
+ Operations<Variable, Type> operations) {
VariableModel<Variable, Type>? currentVariableInfo = variableInfo[variable];
if (currentVariableInfo == null) {
return () => {};
@@ -3370,12 +3369,12 @@
return () {
Map<Type, NonPromotionReason> result = <Type, NonPromotionReason>{};
Type currentType = currentVariableInfo.promotedTypes?.last ??
- typeOperations.variableType(variable);
+ operations.variableType(variable);
NonPromotionHistory? nonPromotionHistory =
currentVariableInfo.nonPromotionHistory;
while (nonPromotionHistory != null) {
Type nonPromotedType = nonPromotionHistory.type;
- if (!typeOperations.isSubtypeOf(currentType, nonPromotedType)) {
+ if (!operations.isSubtypeOf(currentType, nonPromotedType)) {
result[nonPromotedType] ??= nonPromotionHistory.nonPromotionReason;
}
nonPromotionHistory = nonPromotionHistory.previous;
@@ -3483,9 +3482,10 @@
class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
Expression extends Object, Variable extends Object, Type extends Object>
implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
- /// The [TypeOperations], used to access types, and check subtyping.
+ /// The [Operations], used to access types, check subtyping, and query
+ /// variable types.
@override
- final TypeOperations<Variable, Type> typeOperations;
+ final Operations<Variable, Type> operations;
/// Stack of [_FlowContext] objects representing the statements and
/// expressions that are currently being visited.
@@ -3526,7 +3526,7 @@
/// analyzing old language versions).
final bool respectImplicitlyTypedVarInitializers;
- _FlowAnalysisImpl(this.typeOperations, this._assignedVariables,
+ _FlowAnalysisImpl(this.operations, this._assignedVariables,
{required this.respectImplicitlyTypedVarInitializers}) {
if (!_assignedVariables._isFinished) {
_assignedVariables.finish();
@@ -3551,7 +3551,7 @@
_getExpressionReference(subExpression);
if (referenceWithType == null) return;
_current =
- _current.tryPromoteForTypeCast(typeOperations, referenceWithType, type);
+ _current.tryPromoteForTypeCast(operations, referenceWithType, type);
}
@override
@@ -3673,9 +3673,9 @@
ReferenceWithType<Variable, Type>? rhsReference =
rightOperandInfo!._reference;
TypeClassification leftOperandTypeClassification =
- typeOperations.classifyType(leftOperandInfo._type);
+ operations.classifyType(leftOperandInfo._type);
TypeClassification rightOperandTypeClassification =
- typeOperations.classifyType(rightOperandInfo._type);
+ operations.classifyType(rightOperandInfo._type);
if (leftOperandTypeClassification == TypeClassification.nullOrEquivalent &&
rightOperandTypeClassification == TypeClassification.nullOrEquivalent) {
booleanLiteral(wholeExpression, !notEqual);
@@ -3692,13 +3692,13 @@
} else if (leftOperandInfo._expressionInfo is _NullInfo<Variable, Type> &&
rhsReference != null) {
ExpressionInfo<Variable, Type> equalityInfo =
- _current.tryMarkNonNullable(typeOperations, rhsReference);
+ _current.tryMarkNonNullable(operations, rhsReference);
_storeExpressionInfo(
wholeExpression, notEqual ? equalityInfo : equalityInfo.invert());
} else if (rightOperandInfo._expressionInfo is _NullInfo<Variable, Type> &&
lhsReference != null) {
ExpressionInfo<Variable, Type> equalityInfo =
- _current.tryMarkNonNullable(typeOperations, lhsReference);
+ _current.tryMarkNonNullable(operations, lhsReference);
_storeExpressionInfo(
wholeExpression, notEqual ? equalityInfo : equalityInfo.invert());
}
@@ -3743,8 +3743,8 @@
FlowModel<Variable, Type>? breakState = context._breakModel;
FlowModel<Variable, Type> falseCondition = context._conditionInfo.ifFalse;
- _current = _merge(falseCondition, breakState)
- .inheritTested(typeOperations, _current);
+ _current =
+ _merge(falseCondition, breakState).inheritTested(operations, _current);
}
@override
@@ -3840,7 +3840,7 @@
_current = _current.split();
if (lhsReference != null) {
ExpressionInfo<Variable, Type> promotionInfo =
- _current.tryMarkNonNullable(typeOperations, lhsReference);
+ _current.tryMarkNonNullable(operations, lhsReference);
_current = promotionInfo.ifFalse;
promoted = promotionInfo.ifTrue;
} else {
@@ -3906,17 +3906,15 @@
SsaNode<Variable, Type> newSsaNode = new SsaNode<Variable, Type>(
expressionInfo is _TrivialExpressionInfo ? null : expressionInfo);
_current = _current.write(
- null, variable, initializerType, newSsaNode, typeOperations,
+ null, variable, initializerType, newSsaNode, operations,
promoteToTypeOfInterest: !isImplicitlyTyped && !isFinal);
- if (isImplicitlyTyped &&
- typeOperations.isTypeParameterType(initializerType)) {
+ if (isImplicitlyTyped && operations.isTypeParameterType(initializerType)) {
_current = _current
.tryPromoteForTypeCheck(
- typeOperations,
+ operations,
new ReferenceWithType<Variable, Type>(
new VariableReference<Variable, Type>(variable),
- promotedType(variable) ??
- typeOperations.variableType(variable)),
+ promotedType(variable) ?? operations.variableType(variable)),
initializerType)
.ifTrue;
}
@@ -3934,7 +3932,7 @@
_getExpressionReference(subExpression);
if (subExpressionReference != null) {
ExpressionInfo<Variable, Type> expressionInfo = _current
- .tryPromoteForTypeCheck(typeOperations, subExpressionReference, type);
+ .tryPromoteForTypeCheck(operations, subExpressionReference, type);
_storeExpressionInfo(
isExpression, isNot ? expressionInfo.invert() : expressionInfo);
}
@@ -4028,7 +4026,7 @@
_getExpressionReference(operand);
if (operandReference != null) {
_current =
- _current.tryMarkNonNullable(typeOperations, operandReference).ifTrue;
+ _current.tryMarkNonNullable(operations, operandReference).ifTrue;
}
}
@@ -4049,7 +4047,7 @@
_getExpressionReference(target);
if (targetReference != null) {
_current =
- _current.tryMarkNonNullable(typeOperations, targetReference).ifTrue;
+ _current.tryMarkNonNullable(operations, targetReference).ifTrue;
}
}
@@ -4207,7 +4205,7 @@
_TryFinallyContext<Variable, Type> context =
_stack.removeLast() as _TryFinallyContext<Variable, Type>;
_current = context._afterBodyAndCatches!
- .attachFinally(typeOperations, context._beforeFinally, _current);
+ .attachFinally(operations, context._beforeFinally, _current);
}
@override
@@ -4229,12 +4227,12 @@
VariableModel<Variable, Type> variableModel =
variableReference.getInfo(_current.variableInfo);
Type? promotedType = variableModel.promotedTypes?.last;
- Type currentType = promotedType ?? typeOperations.variableType(variable);
+ Type currentType = promotedType ?? operations.variableType(variable);
_storeExpressionReference(expression,
new ReferenceWithType<Variable, Type>(variableReference, currentType));
ExpressionInfo<Variable, Type>? expressionInfo = variableModel
.ssaNode?.expressionInfo
- ?.rebaseForward(typeOperations, _current);
+ ?.rebaseForward(operations, _current);
if (expressionInfo != null) {
_storeExpressionInfo(expression, expressionInfo);
}
@@ -4265,7 +4263,7 @@
_WhileContext<Variable, Type> context =
_stack.removeLast() as _WhileContext<Variable, Type>;
_current = _merge(context._conditionInfo.ifFalse, context._breakModel)
- .inheritTested(typeOperations, _current);
+ .inheritTested(operations, _current);
}
@override
@@ -4275,7 +4273,7 @@
_expressionReference;
if (referenceWithType != null) {
return referenceWithType.reference.getNonPromotionReasons(
- _current.variableInfo, referenceWithType.type, typeOperations);
+ _current.variableInfo, referenceWithType.type, operations);
}
}
return () => {};
@@ -4284,8 +4282,8 @@
@override
Map<Type, NonPromotionReason> Function() whyNotPromotedImplicitThis(
Type staticType) {
- return new _ThisReference<Variable, Type>().getNonPromotionReasons(
- _current.variableInfo, staticType, typeOperations);
+ return new _ThisReference<Variable, Type>()
+ .getNonPromotionReasons(_current.variableInfo, staticType, operations);
}
@override
@@ -4301,7 +4299,7 @@
variable,
writtenType,
newSsaNode,
- typeOperations);
+ operations);
}
@override
@@ -4355,12 +4353,11 @@
FlowModel<Variable, Type> _join(FlowModel<Variable, Type>? first,
FlowModel<Variable, Type>? second) =>
- FlowModel.join(typeOperations, first, second, _current._emptyVariableMap);
+ FlowModel.join(operations, first, second, _current._emptyVariableMap);
FlowModel<Variable, Type> _merge(
FlowModel<Variable, Type> first, FlowModel<Variable, Type>? second) =>
- FlowModel.merge(
- typeOperations, first, second, _current._emptyVariableMap);
+ FlowModel.merge(operations, first, second, _current._emptyVariableMap);
/// Associates [expression], which should be the most recently visited
/// expression, with the given [expressionInfo] object, and updates the
@@ -4462,8 +4459,9 @@
class _LegacyTypePromotion<Node extends Object, Statement extends Node,
Expression extends Object, Variable extends Object, Type extends Object>
implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
- /// The [TypeOperations], used to access types, and check subtyping.
- final TypeOperations<Variable, Type> _typeOperations;
+ /// The [Operations], used to access types, check subtyping, and query
+ /// variable types.
+ final Operations<Variable, Type> _operations;
/// Information about variable assignments computed during the previous
/// compilation pass.
@@ -4493,13 +4491,13 @@
/// written to during the LHS of the "and".
final List<Set<Variable>> _writeStackForAnd = [{}];
- _LegacyTypePromotion(this._typeOperations, this._assignedVariables);
+ _LegacyTypePromotion(this._operations, this._assignedVariables);
@override
bool get isReachable => true;
@override
- TypeOperations<Variable, Type> get typeOperations => _typeOperations;
+ TypeOperations<Type> get operations => _operations;
@override
void asExpression_end(Expression subExpression, Type type) {}
@@ -4655,10 +4653,10 @@
if (!isNot && expressionInfo is _LegacyVariableReadInfo<Variable, Type>) {
Variable variable = expressionInfo._variable;
Type currentType =
- _knownTypes[variable] ?? _typeOperations.variableType(variable);
- Type? promotedType = _typeOperations.tryPromoteToType(type, currentType);
+ _knownTypes[variable] ?? _operations.variableType(variable);
+ Type? promotedType = _operations.tryPromoteToType(type, currentType);
if (promotedType != null &&
- !_typeOperations.isSameType(currentType, promotedType)) {
+ !_operations.isSameType(currentType, promotedType)) {
_storeExpressionInfo(
isExpression,
new _LegacyExpressionInfo<Variable, Type>(
@@ -4729,9 +4727,9 @@
newShownTypes[entry.key] = entry.value;
} else {
Type? newShownType =
- _typeOperations.tryPromoteToType(entry.value, previouslyShownType);
+ _operations.tryPromoteToType(entry.value, previouslyShownType);
if (newShownType != null &&
- !_typeOperations.isSameType(previouslyShownType, newShownType)) {
+ !_operations.isSameType(previouslyShownType, newShownType)) {
newShownTypes[entry.key] = newShownType;
}
}
@@ -5008,7 +5006,7 @@
@override
ExpressionInfo<Variable, Type>? rebaseForward(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
FlowModel<Variable, Type> base) =>
null;
}
@@ -5035,7 +5033,7 @@
Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
Map<Variable?, VariableModel<Variable, Type>> variableInfo,
Type staticType,
- TypeOperations<Variable, Type> typeOperations) {
+ TypeOperations<Type> typeOperations) {
List<Type>? promotedTypes = _getInfo(variableInfo)?.promotedTypes;
if (promotedTypes != null) {
return () {
@@ -5114,7 +5112,7 @@
Map<Type, NonPromotionReason> Function() getNonPromotionReasons(
Map<Variable?, VariableModel<Variable, Type>> variableInfo,
Type staticType,
- TypeOperations<Variable, Type> typeOperations) {
+ TypeOperations<Type> typeOperations) {
List<Type>? promotedTypes = _getInfo(variableInfo)?.promotedTypes;
if (promotedTypes != null) {
return () {
@@ -5161,7 +5159,7 @@
@override
ExpressionInfo<Variable, Type> rebaseForward(
- TypeOperations<Variable, Type> typeOperations,
+ TypeOperations<Type> typeOperations,
FlowModel<Variable, Type> base) =>
new _TrivialExpressionInfo(base);
}
diff --git a/pkg/_fe_analyzer_shared/test/mini_ast.dart b/pkg/_fe_analyzer_shared/test/mini_ast.dart
index 3a8528c..2267aaa 100644
--- a/pkg/_fe_analyzer_shared/test/mini_ast.dart
+++ b/pkg/_fe_analyzer_shared/test/mini_ast.dart
@@ -247,9 +247,9 @@
}
/// Test harness for creating flow analysis tests. This class implements all
-/// the [TypeOperations] needed by flow analysis, as well as other methods
-/// needed for testing.
-class Harness extends TypeOperations<Var, Type> {
+/// the [Operations] needed by flow analysis, as well as other methods needed
+/// for testing.
+class Harness extends Operations<Var, Type> {
static const Map<String, bool> _coreSubtypes = const {
'bool <: int': false,
'bool <: Object': true,
@@ -1486,7 +1486,7 @@
var rightType = analyzeExpression(rhs);
flow.ifNullExpression_end();
return leastUpperBound(
- flow.typeOperations.promoteToNonNull(leftType), rightType);
+ flow.operations.promoteToNonNull(leftType), rightType);
}
void analyzeIfStatement(Statement node, Expression condition,
@@ -1520,7 +1520,7 @@
Type analyzeNonNullAssert(Expression node, Expression expression) {
var type = analyzeExpression(expression);
flow.nonNullAssert_end(expression);
- return flow.typeOperations.promoteToNonNull(type);
+ return flow.operations.promoteToNonNull(type);
}
Type analyzeNullLiteral(Expression node) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 4b31179..7b8101e 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -59,7 +59,7 @@
/// be extracted.
class FlowAnalysisHelper {
/// The reused instance for creating new [FlowAnalysis] instances.
- final TypeSystemTypeOperations _typeOperations;
+ final TypeSystemOperations _typeOperations;
/// Precomputed sets of potentially assigned variables.
AssignedVariables<AstNode, PromotableElement>? assignedVariables;
@@ -82,7 +82,7 @@
FlowAnalysisHelper(TypeSystemImpl typeSystem, bool retainDataForTesting,
FeatureSet featureSet)
- : this._(TypeSystemTypeOperations(typeSystem),
+ : this._(TypeSystemOperations(typeSystem),
retainDataForTesting ? FlowAnalysisDataForTesting() : null,
isNonNullableByDefault: featureSet.isEnabled(Feature.non_nullable),
respectImplicitlyTypedVarInitializers:
@@ -375,11 +375,10 @@
}
}
-class TypeSystemTypeOperations
- extends TypeOperations<PromotableElement, DartType> {
+class TypeSystemOperations extends Operations<PromotableElement, DartType> {
final TypeSystemImpl typeSystem;
- TypeSystemTypeOperations(this.typeSystem);
+ TypeSystemOperations(this.typeSystem);
@override
TypeClassification classifyType(DartType type) {
diff --git a/pkg/dart2native/lib/dart2native_macho.dart b/pkg/dart2native/lib/dart2native_macho.dart
index 1c45d13..b10133e 100644
--- a/pkg/dart2native/lib/dart2native_macho.dart
+++ b/pkg/dart2native/lib/dart2native_macho.dart
@@ -369,15 +369,20 @@
// Thus, to sign the binary, the developer must force signature overwriting.
final signingProcess = await Process.run('codesign', args);
if (signingProcess.exitCode != 0) {
- print('Failed to replace the dartaotruntime signature, ');
- print('subcommand terminated with exit code ${signingProcess.exitCode}.');
+ stderr
+ ..write('Failed to replace the dartaotruntime signature, ')
+ ..write('subcommand terminated with exit code ')
+ ..write(signingProcess.exitCode)
+ ..writeln('.');
if (signingProcess.stdout.isNotEmpty) {
- print('Subcommand stdout:');
- print(signingProcess.stdout);
+ stderr
+ ..writeln('Subcommand stdout:')
+ ..writeln(signingProcess.stdout);
}
if (signingProcess.stderr.isNotEmpty) {
- print('Subcommand stderr:');
- print(signingProcess.stderr);
+ stderr
+ ..writeln('Subcommand stderr:')
+ ..writeln(signingProcess.stderr);
}
throw 'Could not sign the new executable';
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 9a94858..23cc739 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -260,10 +260,10 @@
}
/// CFE-specific implementation of [TypeOperations].
-class TypeOperationsCfe extends TypeOperations<VariableDeclaration, DartType> {
+class OperationsCfe extends Operations<VariableDeclaration, DartType> {
final TypeEnvironment typeEnvironment;
- TypeOperationsCfe(this.typeEnvironment);
+ OperationsCfe(this.typeEnvironment);
@override
TypeClassification classifyType(DartType? type) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index fb520a1..68129b6 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -228,16 +228,14 @@
@override
late final FlowAnalysis<TreeNode, Statement, Expression, VariableDeclaration,
- DartType> flowAnalysis =
- libraryBuilder.isNonNullableByDefault
- ? new FlowAnalysis(
- new TypeOperationsCfe(engine.typeSchemaEnvironment),
- assignedVariables,
- respectImplicitlyTypedVarInitializers:
- libraryBuilder.libraryFeatures.constructorTearoffs.isEnabled)
- : new FlowAnalysis.legacy(
- new TypeOperationsCfe(engine.typeSchemaEnvironment),
- assignedVariables);
+ DartType> flowAnalysis = libraryBuilder
+ .isNonNullableByDefault
+ ? new FlowAnalysis(
+ new OperationsCfe(engine.typeSchemaEnvironment), assignedVariables,
+ respectImplicitlyTypedVarInitializers:
+ libraryBuilder.libraryFeatures.constructorTearoffs.isEnabled)
+ : new FlowAnalysis.legacy(
+ new OperationsCfe(engine.typeSchemaEnvironment), assignedVariables);
@override
final AssignedVariables<TreeNode, VariableDeclaration> assignedVariables;
diff --git a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
index a93fa35..69012f6 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
@@ -11,9 +11,9 @@
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/variables.dart';
-/// [TypeOperations] that works with [DecoratedType]s.
+/// [Operations] that works with [DecoratedType]s.
class DecoratedTypeOperations
- implements TypeOperations<PromotableElement, DecoratedType> {
+ implements Operations<PromotableElement, DecoratedType> {
final TypeSystem _typeSystem;
final Variables? _variableRepository;
final NullabilityGraph _graph;
diff --git a/runtime/tests/vm/dart/flutter_regress_106510_test.dart b/runtime/tests/vm/dart/flutter_regress_106510_test.dart
new file mode 100644
index 0000000..7c41c20
--- /dev/null
+++ b/runtime/tests/vm/dart/flutter_regress_106510_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2022, 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.
+
+// VMOptions=--use_slow_path --stress_write_barrier_elimination
+
+// Test that array allocation in noSuchMethod dispatcher is preserving the
+// length register correctly.
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+final List<dynamic> list = <dynamic>[];
+
+final List<int> invocations = <int>[];
+
+abstract class B {
+ void someMethod(int v);
+}
+
+class A {
+ noSuchMethod(Invocation i) {
+ Expect.equals(#someMethod, i.memberName);
+ invocations.add(i.positionalArguments[0] as int);
+ }
+}
+
+class C implements B {
+ void someMethod(int v) {
+ invocations.add(v);
+ }
+}
+
+void main() {
+ for (var i = 0; i < 10; i++) {
+ list.add(A());
+ list.add(C());
+ }
+
+ for (var i = 0; i < list.length; i++) {
+ list[i].someMethod(i);
+ }
+
+ Expect.equals(list.length, invocations.length);
+ for (var i = 0; i < list.length; i++) {
+ Expect.equals(i, invocations[i]);
+ }
+}
diff --git a/runtime/tests/vm/dart_2/flutter_regress_106510_test.dart b/runtime/tests/vm/dart_2/flutter_regress_106510_test.dart
new file mode 100644
index 0000000..5139e57
--- /dev/null
+++ b/runtime/tests/vm/dart_2/flutter_regress_106510_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2022, 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.
+// @dart=2.9
+
+// VMOptions=--use_slow_path --stress_write_barrier_elimination
+
+// Test that array allocation in noSuchMethod dispatcher is preserving the
+// length register correctly.
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+final List<dynamic> list = <dynamic>[];
+
+final List<int> invocations = <int>[];
+
+abstract class B {
+ void someMethod(int v);
+}
+
+class A {
+ noSuchMethod(Invocation i) {
+ Expect.equals(#someMethod, i.memberName);
+ invocations.add(i.positionalArguments[0] as int);
+ }
+}
+
+class C implements B {
+ void someMethod(int v) {
+ invocations.add(v);
+ }
+}
+
+void main() {
+ for (var i = 0; i < 10; i++) {
+ list.add(A());
+ list.add(C());
+ }
+
+ for (var i = 0; i < list.length; i++) {
+ list[i].someMethod(i);
+ }
+
+ Expect.equals(list.length, invocations.length);
+ for (var i = 0; i < list.length; i++) {
+ Expect.equals(i, invocations[i]);
+ }
+}
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index fc6b0ea..6f62456 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -46,7 +46,7 @@
{
LeafRuntimeScope rt(assembler,
/*frame_size=*/0,
- /*preserve_registers=*/false);
+ /*preserve_registers=*/preserve_registers);
// [R0] already contains first argument.
__ mov(R1, Operand(THR));
rt.Call(kEnsureRememberedAndMarkingDeferredRuntimeEntry, 2);
diff --git a/tools/VERSION b/tools/VERSION
index 1525dd4..55034e0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 244
+PRERELEASE 245
PRERELEASE_PATCH 0
\ No newline at end of file