Skip to content

Commit

Permalink
Version 3.1.0-164.0.dev
Browse files Browse the repository at this point in the history
Merge 63d856d into dev
  • Loading branch information
Dart CI committed Jun 1, 2023
2 parents 3d4d29d + 63d856d commit 2c9bc7b
Show file tree
Hide file tree
Showing 28 changed files with 693 additions and 431 deletions.
757 changes: 451 additions & 306 deletions pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ enum TypeClassification {
/// This mixin provides default implementations for some members that won't need
/// to be overridden very frequently.
mixin TypeOperations<Type extends Object> {
/// Returns the client's representation of the type `bool`.
Type get boolType;

/// Returns `true` if [type1] and [type2] are structurally equal.
bool areStructurallyEqual(Type type1, Type type2);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class FlowAnalysisTestHarness extends Harness implements FlowModelHelper<Type> {
@override
final PromotionKeyStore<Var> promotionKeyStore = PromotionKeyStore();

@override
final Type boolType = Type('bool');

@override
Operations<Var, Type> get typeOperations => typeAnalyzer.operations;
}
Expand Down
24 changes: 12 additions & 12 deletions pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1393,17 +1393,16 @@ main() {
test('initialize() stores expressionInfo when not late', () {
var x = Var('x');
var y = Var('y');
late ExpressionInfo<Type> writtenValueInfo;
h.run([
declare(y, type: 'int?', initializer: expr('int?')),
declare(x,
type: 'Object',
initializer: y.expr.eq(nullLiteral).getExpressionInfo((info) {
expect(info, isNotNull);
writtenValueInfo = info!;
})),
declare(x, type: 'Object', initializer: y.expr.eq(nullLiteral)),
getSsaNodes((nodes) {
expect(nodes[x]!.expressionInfo, same(writtenValueInfo));
var info = nodes[x]!.expressionInfo!;
var key = h.promotionKeyStore.keyForVariable(y);
expect(info.after.variableInfo[key]!.promotedTypes, null);
expect(info.ifTrue.variableInfo[key]!.promotedTypes, null);
expect(info.ifFalse.variableInfo[key]!.promotedTypes!.single.type,
'int');
}),
]);
});
Expand Down Expand Up @@ -9846,11 +9845,12 @@ extension on FlowModel<Type> {
int _varRef(FlowAnalysisTestHarness h, Var variable) =>
h.promotionKeyStore.keyForVariable(variable);

ReferenceWithType<Type> _varRefWithType(
TrivialVariableReference<Type> _varRefWithType(
FlowAnalysisTestHarness h, Var variable) =>
new ReferenceWithType<Type>(
_varRef(h, variable),
variableInfo[h.promotionKeyStore.keyForVariable(variable)]
new TrivialVariableReference<Type>(
promotionKey: _varRef(h, variable),
after: this,
type: variableInfo[h.promotionKeyStore.keyForVariable(variable)]
?.promotedTypes
?.last ??
variable.type,
Expand Down
17 changes: 10 additions & 7 deletions pkg/_fe_analyzer_shared/test/mini_ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/// analysis testing.
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart'
show
EqualityInfo,
ExpressionInfo,
ExpressionPropertyTarget,
FlowAnalysis,
Operations,
Expand Down Expand Up @@ -2375,6 +2375,9 @@ class MiniAstOperations

final TypeSystem _typeSystem = TypeSystem();

@override
final Type boolType = Type('bool');

bool get legacy => _legacy ?? false;

set legacy(bool value) {
Expand Down Expand Up @@ -4486,7 +4489,7 @@ class _MiniAstTypeAnalyzer
flow.logicalBinaryOp_begin();
}
var leftType = analyzeExpression(lhs, unknownType);
EqualityInfo<Type>? leftInfo;
ExpressionInfo<Type>? leftInfo;
if (isEquals) {
leftInfo = flow.equalityOperand_end(lhs, leftType);
} else if (isLogical) {
Expand Down Expand Up @@ -4524,11 +4527,11 @@ class _MiniAstTypeAnalyzer
analyzeExpression(condition, unknownType);
flow.conditional_thenBegin(condition, node);
var ifTrueType = analyzeExpression(ifTrue, unknownType);
flow.conditional_elseBegin(ifTrue);
flow.conditional_elseBegin(ifTrue, ifTrueType);
var ifFalseType = analyzeExpression(ifFalse, unknownType);
flow.conditional_end(node, ifFalse);
return new SimpleTypeAnalysisResult<Type>(
type: leastUpperBound(ifTrueType, ifFalseType));
var lubType = leastUpperBound(ifTrueType, ifFalseType);
flow.conditional_end(node, lubType, ifFalse, ifFalseType);
return new SimpleTypeAnalysisResult<Type>(type: lubType);
}

void analyzeContinueStatement(Statement? target) {
Expand Down Expand Up @@ -4580,7 +4583,7 @@ class _MiniAstTypeAnalyzer
}

SimpleTypeAnalysisResult<Type> analyzeNullLiteral(Expression node) {
flow.nullLiteral(node);
flow.nullLiteral(node, nullType);
return new SimpleTypeAnalysisResult<Type>(type: nullType);
}

Expand Down
87 changes: 48 additions & 39 deletions pkg/analyzer/lib/src/dart/constant/evaluation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -574,20 +574,8 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
TypeProvider get _typeProvider => _library.typeProvider;

@override
Constant? visitAdjacentStrings(AdjacentStrings node) {
DartObjectImpl? result;
for (StringLiteral string in node.strings) {
// TODO(kallentu): Remove unwrapping when concatenate handles Constant.
var stringConstant = string.accept(this);
var stringResult =
stringConstant is DartObjectImpl ? stringConstant : null;
if (result == null) {
result = stringResult;
} else {
result = _dartObjectComputer.concatenate(node, result, stringResult);
}
}
return result;
Constant visitAdjacentStrings(AdjacentStrings node) {
return _concatenateNodes(node, node.strings);
}

@override
Expand Down Expand Up @@ -1218,22 +1206,8 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
}

@override
Constant? visitStringInterpolation(StringInterpolation node) {
DartObjectImpl? result;
bool first = true;
for (InterpolationElement element in node.elements) {
// TODO(kallentu): Remove unwrapping when concatenate handles Constant.
var elementConstant = element.accept(this);
var elementResult =
elementConstant is DartObjectImpl ? elementConstant : null;
if (first) {
result = elementResult;
first = false;
} else {
result = _dartObjectComputer.concatenate(node, result, elementResult);
}
}
return result;
Constant visitStringInterpolation(StringInterpolation node) {
return _concatenateNodes(node, node.elements);
}

@override
Expand Down Expand Up @@ -1383,6 +1357,42 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
return true;
}

/// Returns the result of concatenating [astNodes].
///
/// If there's an [InvalidConstant] found, it will return early.
Constant _concatenateNodes(Expression node, List<AstNode> astNodes) {
Constant? result;
for (AstNode astNode in astNodes) {
var constant = astNode.accept(this);
switch (constant) {
case null:
// Should never reach this.
return InvalidConstant(node, CompileTimeErrorCode.INVALID_CONSTANT);
case InvalidConstant():
return constant;
case DartObjectImpl dartObject:
if (result == null) {
result = constant;
} else if (result is DartObjectImpl) {
result = _dartObjectComputer.concatenate(node, result, dartObject);
if (result is InvalidConstant) {
return result;
}
}
}
}

if (result == null) {
// No errors have been detected, but we did not concatenate any nodes.
return DartObjectImpl(
typeSystem,
_typeProvider.stringType,
StringState.UNKNOWN_VALUE,
);
}
return result;
}

/// Create an error associated with the given [node]. The error will have the
/// given error [code].
void _error(AstNode node, ErrorCode? code) {
Expand Down Expand Up @@ -1745,16 +1755,15 @@ class DartObjectComputer {
return null;
}

DartObjectImpl? concatenate(Expression node, DartObjectImpl? leftOperand,
DartObjectImpl? rightOperand) {
if (leftOperand != null && rightOperand != null) {
try {
return leftOperand.concatenate(_typeSystem, rightOperand);
} on EvaluationException catch (exception) {
_errorReporter.reportErrorForNode(exception.errorCode, node);
}
Constant concatenate(Expression node, DartObjectImpl leftOperand,
DartObjectImpl rightOperand) {
try {
return leftOperand.concatenate(_typeSystem, rightOperand);
} on EvaluationException catch (exception) {
// TODO(kallentu): Don't report error here.
_errorReporter.reportErrorForNode(exception.errorCode, node);
return InvalidConstant(node, exception.errorCode);
}
return null;
}

DartObjectImpl? divide(BinaryExpression node, DartObjectImpl? leftOperand,
Expand Down
6 changes: 4 additions & 2 deletions pkg/analyzer/lib/src/dart/constant/value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class BoolState extends InstanceState {
/// [DartObjectImpl] represents a valid result. Note that the [DartObjectImpl]
/// could have an unknown state and still be a valid constant.
/// [InvalidConstant] represents an invalid result with error information.
abstract class Constant {}
sealed class Constant {}

/// Information about a const constructor invocation.
class ConstructorInvocation {
Expand Down Expand Up @@ -2356,6 +2356,8 @@ class InvalidConstant implements Constant {
/// information if the error occurs within a constructor.
final List<DiagnosticMessage> contextMessages;

InvalidConstant(this.node, this.errorCode) : contextMessages = [];

InvalidConstant.withContextMessages(
this.node, this.errorCode, this.contextMessages);
}
Expand Down Expand Up @@ -2779,7 +2781,7 @@ class SetState extends InstanceState {

/// The state of an object representing a string.
class StringState extends InstanceState {
/// A state that can be used to represent a double whose value is not known.
/// A state that can be used to represent a string whose value is not known.
static StringState UNKNOWN_VALUE = StringState(null);

/// The value of this instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class BinaryExpressionResolver {

var flowAnalysis = _resolver.flowAnalysis;
var flow = flowAnalysis.flow;
EqualityInfo<DartType>? leftInfo;
ExpressionInfo<DartType>? leftInfo;
var leftExtensionOverride = left is ExtensionOverride;
if (!leftExtensionOverride) {
leftInfo = flow?.equalityOperand_end(left, left.typeOrThrow);
Expand Down
3 changes: 3 additions & 0 deletions pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,9 @@ class TypeSystemOperations

TypeSystemOperations(this.typeSystem);

@override
DartType get boolType => typeSystem.typeProvider.boolType;

@override
bool areStructurallyEqual(DartType type1, DartType type2) {
return type1 == type2;
Expand Down
8 changes: 4 additions & 4 deletions pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ abstract class FullInvocationInferrer<Node extends AstNodeImpl>
rawType.typeFormals, inferrer.choosePreliminaryTypes());
}

List<EqualityInfo<DartType>?>? identicalInfo = _isIdentical ? [] : null;
List<ExpressionInfo<DartType>?>? identicalInfo = _isIdentical ? [] : null;
var parameterMap = _computeParameterMap(rawType?.parameters ?? const []);
var deferredFunctionLiterals = _visitArguments(
parameterMap: parameterMap,
Expand Down Expand Up @@ -433,7 +433,7 @@ class InvocationInferrer<Node extends AstNodeImpl> {

/// If the invocation being processed is a call to `identical`, informs flow
/// analysis about it, so that it can do appropriate promotions.
void _recordIdenticalInfo(List<EqualityInfo<DartType>?>? identicalInfo) {
void _recordIdenticalInfo(List<ExpressionInfo<DartType>?>? identicalInfo) {
var flow = resolver.flowAnalysis.flow;
if (identicalInfo != null) {
flow?.equalityOperation_end(argumentList.parent as Expression,
Expand All @@ -444,7 +444,7 @@ class InvocationInferrer<Node extends AstNodeImpl> {
/// Resolves any function literals that were deferred by [_visitArguments].
void _resolveDeferredFunctionLiterals(
{required List<_DeferredParamInfo> deferredFunctionLiterals,
List<EqualityInfo<DartType>?>? identicalInfo,
List<ExpressionInfo<DartType>?>? identicalInfo,
Substitution? substitution,
GenericInferrer? inferrer}) {
var flow = resolver.flowAnalysis.flow;
Expand Down Expand Up @@ -478,7 +478,7 @@ class InvocationInferrer<Node extends AstNodeImpl> {
/// returned.
List<_DeferredParamInfo>? _visitArguments(
{required Map<Object, ParameterElement> parameterMap,
List<EqualityInfo<DartType>?>? identicalInfo,
List<ExpressionInfo<DartType>?>? identicalInfo,
Substitution? substitution,
GenericInferrer? inferrer}) {
assert(whyNotPromotedList.isEmpty);
Expand Down
14 changes: 9 additions & 5 deletions pkg/analyzer/lib/src/generated/resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2182,18 +2182,22 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
Expression elseExpression = node.elseExpression;

if (flow != null) {
flow.conditional_elseBegin(node.thenExpression);
flow.conditional_elseBegin(
node.thenExpression, node.thenExpression.typeOrThrow);
checkUnreachableNode(elseExpression);
analyzeExpression(elseExpression, contextType);
flow.conditional_end(node, elseExpression);
nullSafetyDeadCodeVerifier.flowEnd(elseExpression);
} else {
analyzeExpression(elseExpression, contextType);
}
elseExpression = popRewrite()!;

typeAnalyzer.visitConditionalExpression(node as ConditionalExpressionImpl,
contextType: contextType);
if (flow != null) {
flow.conditional_end(
node, node.typeOrThrow, elseExpression, elseExpression.typeOrThrow);
nullSafetyDeadCodeVerifier.flowEnd(elseExpression);
}
_insertImplicitCallReference(node, contextType: contextType);
}

Expand Down Expand Up @@ -3088,11 +3092,11 @@ class ResolverVisitor extends ThrowingAstVisitor<void>

@override
void visitNullLiteral(NullLiteral node, {DartType? contextType}) {
flowAnalysis.flow?.nullLiteral(node);
checkUnreachableNode(node);
node.visitChildren(this);
typeAnalyzer.visitNullLiteral(node as NullLiteralImpl,
contextType: contextType);
flowAnalysis.flow?.nullLiteral(node, node.typeOrThrow);
checkUnreachableNode(node);
}

@override
Expand Down
Loading

0 comments on commit 2c9bc7b

Please sign in to comment.