Skip to content

Commit

Permalink
Version 3.2.0-106.0.dev
Browse files Browse the repository at this point in the history
Merge 30e8ed8 into dev
  • Loading branch information
Dart CI committed Aug 24, 2023
2 parents bcad589 + 30e8ed8 commit e9c749f
Show file tree
Hide file tree
Showing 229 changed files with 6,185 additions and 2,740 deletions.
62 changes: 41 additions & 21 deletions pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2280,7 +2280,7 @@ class FlowModel<Type extends Object> {
/// will be promoted in the output model, provided that hasn't been reassigned
/// since then (which would make the promotion unsound).
FlowModel<Type> rebaseForward(
TypeOperations<Type> typeOperations, FlowModel<Type> base) {
FlowModelHelper<Type> helper, FlowModel<Type> base) {
// The rebased model is reachable iff both `this` and the new base are
// reachable.
Reachability newReachable = reachable.rebaseForward(base.reachable);
Expand Down Expand Up @@ -2312,7 +2312,9 @@ class FlowModel<Type extends Object> {
if (newWriteCaptured) {
// Write captured variables can't be promoted.
newPromotedTypes = null;
} else if (baseModel.ssaNode != thisModel.ssaNode) {
} else if (helper.promotionKeyStore.variableForKey(promotionKey) !=
null &&
baseModel.ssaNode != thisModel.ssaNode) {
// The variable may have been written to since `thisModel`, so we can't
// use any of the promotions from `thisModel`.
newPromotedTypes = baseModel.promotedTypes;
Expand All @@ -2322,12 +2324,14 @@ class FlowModel<Type extends Object> {
// usual "promotion chain" invariant (each promoted type is a subtype of
// the previous).
newPromotedTypes = PromotionModel.rebasePromotedTypes(
typeOperations, thisModel.promotedTypes, baseModel.promotedTypes);
helper.typeOperations,
thisModel.promotedTypes,
baseModel.promotedTypes);
}
// Tests are kept regardless of whether they are in `this` model or the
// new base model.
List<Type> newTested = PromotionModel.joinTested(
thisModel.tested, baseModel.tested, typeOperations);
thisModel.tested, baseModel.tested, helper.typeOperations);
// The variable is definitely assigned if it was definitely assigned
// either in `this` model or the new base model.
bool newAssigned = thisModel.assigned || baseModel.assigned;
Expand All @@ -2346,15 +2350,24 @@ class FlowModel<Type extends Object> {
if (!identical(newModel, thisModel)) promotionInfoMatchesThis = false;
if (!identical(newModel, baseModel)) promotionInfoMatchesBase = false;
}
// newPromotionInfo is now correct. However, if there are any variables
// present in `this` that aren't present in `base`, we may erroneously think
// that `newPromotionInfo` matches `this`. If so, correct that.
if (promotionInfoMatchesThis) {
for (int promotionKey in promotionInfo.keys) {
if (!base.promotionInfo.containsKey(promotionKey)) {
promotionInfoMatchesThis = false;
break;
}
// Check promotion keys that exist in `this` model but not in the new `base`
// model. This happens when either:
// - The promotion key is associated with a local variable that was in scope
// at the time `this` model was created, but is no longer in scope as of
// the `base` model, or:
// - The promotion key is associated with a property that was promoted in
// `this` model.
//
// In the first case, it doesn't matter what we do, because the variable is
// no longer in scope. But in the second case, we need to preserve the
// promotion.
for (var MapEntry(
key: int promotionKey,
value: PromotionModel<Type> thisModel
) in promotionInfo.entries) {
if (!base.promotionInfo.containsKey(promotionKey)) {
newPromotionInfo[promotionKey] = thisModel;
promotionInfoMatchesBase = false;
}
}
assert(promotionInfoMatchesThis ==
Expand Down Expand Up @@ -2844,6 +2857,14 @@ class PromotionModel<Type extends Object> {
/// `null` if the variable has been write captured.
///
/// Not relevant for properties.
///
/// Note: currently this field stores a bogus SSA node when the PromotionModel
/// represents a property; it's not the SSA node of the value stored in the
/// property, and it's not guaranteed to be a stable value (even if the
/// property itself is promotable, and thus stable).
/// TODO(paulberry): either ensure that flow analysis doesn't try to access
/// this field when the PromotionModel represents a property, or ensure that
/// this field always properly reflects the SSA node of the property.
final SsaNode<Type>? ssaNode;

/// Non-promotion history of this variable. Not relevant for properties.
Expand Down Expand Up @@ -3829,7 +3850,7 @@ class TrivialVariableReference<Type extends Object> extends _Reference<Type> {
/// [current] should be the current flow model, and [typeOperations] should be
/// the callback object provided by the client for manipulating types.
_Reference<Type> addPreviousInfo(ExpressionInfo<Type>? previousExpressionInfo,
TypeOperations<Type> typeOperations, FlowModel<Type> current) {
FlowModelHelper<Type> helper, FlowModel<Type> current) {
if (previousExpressionInfo != null && previousExpressionInfo.isNonTrivial) {
// [previousExpression] contained non-trivial flow analysis information,
// so we need to rebase its [ifTrue] and [ifFalse] flow models. We don't
Expand All @@ -3841,10 +3862,9 @@ class TrivialVariableReference<Type extends Object> extends _Reference<Type> {
after: current,
type: _type,
isThisOrSuper: isThisOrSuper,
ifTrue: previousExpressionInfo.ifTrue
.rebaseForward(typeOperations, current),
ifFalse: previousExpressionInfo.ifFalse
.rebaseForward(typeOperations, current),
ifTrue: previousExpressionInfo.ifTrue.rebaseForward(helper, current),
ifFalse:
previousExpressionInfo.ifFalse.rebaseForward(helper, current),
ssaNode: ssaNode);
} else {
// [previousExpression] didn't contain any non-trivial flow analysis
Expand Down Expand Up @@ -5184,7 +5204,7 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
PromotionModel<Type> promotionModel = _current._getInfo(variableKey);
_Reference<Type> expressionInfo =
_variableReference(variableKey, unpromotedType).addPreviousInfo(
promotionModel.ssaNode?.expressionInfo, operations, _current);
promotionModel.ssaNode?.expressionInfo, this, _current);
_storeExpressionReference(expression, expressionInfo);
_storeExpressionInfo(expression, expressionInfo);
return promotionModel.promotedTypes?.last;
Expand Down Expand Up @@ -5445,7 +5465,7 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
_PatternContext<Type> context = _stack.last as _PatternContext<Type>;
_Reference<Type> newReference = context
.createReference(getMatchedValueType(), _current)
.addPreviousInfo(context._matchedValueInfo, typeOperations, _current);
.addPreviousInfo(context._matchedValueInfo, this, _current);
_EqualityCheckResult equalityCheckResult =
_equalityCheck(newReference, equalityOperand_end(operand, operandType));
if (equalityCheckResult is _NoEqualityInformation) {
Expand Down Expand Up @@ -5711,7 +5731,7 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
}
return _makeTemporaryReference(
scrutineeSsaNode ?? new SsaNode<Type>(null), scrutineeType)
.addPreviousInfo(scrutineeInfo, typeOperations, _current);
.addPreviousInfo(scrutineeInfo, this, _current);
}

/// Associates [expression], which should be the most recently visited
Expand Down
24 changes: 24 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4267,6 +4267,30 @@ const MessageCode messageExtensionTypeDeclarationCause = const MessageCode(
problemMessage:
r"""The issue arises via this extension type declaration.""");

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeExtensionTypeExtends = messageExtensionTypeExtends;

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageExtensionTypeExtends = const MessageCode(
"ExtensionTypeExtends",
index: 164,
problemMessage:
r"""An extension type declaration can't have an 'extends' clause.""",
correctionMessage:
r"""Try removing the 'extends' clause or replacing the 'extends' with 'implements'.""");

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeExtensionTypeWith = messageExtensionTypeWith;

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageExtensionTypeWith = const MessageCode(
"ExtensionTypeWith",
index: 165,
problemMessage:
r"""An extension type declaration can't have a 'with' clause.""",
correctionMessage:
r"""Try removing the 'with' clause or replacing the 'with' with 'implements'.""");

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeExternalClass = messageExternalClass;

Expand Down
15 changes: 15 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/parser/declaration_kind.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,18 @@ enum DeclarationKind {
/// An enum.
Enum,
}

/// Enum to specify in which declaration a header occurs.
enum DeclarationHeaderKind {
/// Class declaration header, for instance `extends S with M implements I` in
///
/// class C extends S with M implements I {}
///
Class,

/// Extension type declaration header, for instance `implements I` in
///
/// extension type E(T t) implements I {}
///
ExtensionType,
}
Original file line number Diff line number Diff line change
Expand Up @@ -1918,8 +1918,8 @@ class ForwardingListener implements Listener {
}

@override
void handleRecoverClassHeader() {
listener?.handleRecoverClassHeader();
void handleRecoverDeclarationHeader(DeclarationHeaderKind kind) {
listener?.handleRecoverDeclarationHeader(kind);
}

@override
Expand Down
8 changes: 4 additions & 4 deletions pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import 'formal_parameter_kind.dart' show FormalParameterKind;

import 'identifier_context.dart' show IdentifierContext;

import 'declaration_kind.dart' show DeclarationKind;
import 'declaration_kind.dart' show DeclarationHeaderKind, DeclarationKind;

import 'member_kind.dart' show MemberKind;

Expand Down Expand Up @@ -174,16 +174,16 @@ class Listener implements UnescapeErrorListener {
logEvent("ClassHeader");
}

/// Handle recovery associated with a class header.
/// Handle recovery associated with a class or extension type header.
/// This may be called multiple times after [handleClassHeader]
/// to recover information about the previous class header.
/// The substructures are a subset of
/// and in the same order as [handleClassHeader]:
/// - supertype
/// - with clause
/// - implemented types
void handleRecoverClassHeader() {
logEvent("RecoverClassHeader");
void handleRecoverDeclarationHeader(DeclarationHeaderKind kind) {
logEvent("RecoverDeclarationHeader");
}

/// Handle the end of a class declaration. Substructures:
Expand Down
2 changes: 1 addition & 1 deletion pkg/_fe_analyzer_shared/lib/src/parser/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export 'identifier_context.dart' show IdentifierContext;

export 'listener.dart' show Listener;

export 'declaration_kind.dart' show DeclarationKind;
export 'declaration_kind.dart' show DeclarationHeaderKind, DeclarationKind;

export 'directive_context.dart' show DirectiveContext;

Expand Down
Loading

0 comments on commit e9c749f

Please sign in to comment.