Skip to content

Commit

Permalink
Version 3.5.0-121.0.dev
Browse files Browse the repository at this point in the history
Merge 842ce82 into dev
  • Loading branch information
Dart CI committed May 1, 2024
2 parents 9298823 + 842ce82 commit 04d373e
Show file tree
Hide file tree
Showing 48 changed files with 657 additions and 398 deletions.
50 changes: 27 additions & 23 deletions pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2464,7 +2464,7 @@ class FlowModel<Type extends Object> {

Type previousType = reference._type;
Type newType = helper.typeOperations.promoteToNonNull(previousType);
if (helper.typeOperations.isSameType(newType, previousType)) {
if (newType == previousType) {
return new ExpressionInfo<Type>.trivial(
after: this, type: helper.boolType);
}
Expand Down Expand Up @@ -2495,8 +2495,7 @@ class FlowModel<Type extends Object> {

Type previousType = reference._type;
Type? newType = helper.typeOperations.tryPromoteToType(type, previousType);
if (newType == null ||
helper.typeOperations.isSameType(newType, previousType)) {
if (newType == null || newType == previousType) {
return this;
}

Expand Down Expand Up @@ -2527,8 +2526,7 @@ class FlowModel<Type extends Object> {
FlowModel<Type> ifTrue = this;
Type? typeIfSuccess =
helper.typeOperations.tryPromoteToType(type, previousType);
if (typeIfSuccess != null &&
!helper.typeOperations.isSameType(typeIfSuccess, previousType)) {
if (typeIfSuccess != null && typeIfSuccess != previousType) {
assert(helper.typeOperations.isSubtypeOf(typeIfSuccess, previousType),
"Expected $typeIfSuccess to be a subtype of $previousType.");
ifTrue = _finishTypeTest(helper, reference, info, type, typeIfSuccess);
Expand All @@ -2540,7 +2538,7 @@ class FlowModel<Type extends Object> {
// Promoting to `Never` would mark the code as unreachable. But it might
// be reachable due to mixed mode unsoundness. So don't promote.
typeIfFalse = null;
} else if (helper.typeOperations.isSameType(factoredType, previousType)) {
} else if (factoredType == previousType) {
// No change to the type, so don't promote.
typeIfFalse = null;
} else {
Expand Down Expand Up @@ -3210,7 +3208,7 @@ class PromotionModel<Type extends Object> {

// Must be more specific that the currently promoted type.
if (currentlyPromotedType != null) {
if (typeOperations.isSameType(type, currentlyPromotedType)) {
if (type == currentlyPromotedType) {
return;
}
if (!typeOperations.isSubtypeOf(type, currentlyPromotedType)) {
Expand All @@ -3219,7 +3217,7 @@ class PromotionModel<Type extends Object> {
}

// This is precisely the type we want to promote to; take it.
if (typeOperations.isSameType(type, writtenType)) {
if (type == writtenType) {
result = _addToPromotedTypes(promotedTypes, writtenType);
}

Expand All @@ -3238,7 +3236,7 @@ class PromotionModel<Type extends Object> {
// The declared type is always a type of interest, but we never promote
// to the declared type. So, try NonNull of it.
Type declaredTypeNonNull = typeOperations.promoteToNonNull(declaredType);
if (!typeOperations.isSameType(declaredTypeNonNull, declaredType)) {
if (declaredTypeNonNull != declaredType) {
handleTypeOfInterest(declaredTypeNonNull);
if (result != null) {
return result!;
Expand All @@ -3254,7 +3252,7 @@ class PromotionModel<Type extends Object> {
}

Type typeNonNull = typeOperations.promoteToNonNull(type);
if (!typeOperations.isSameType(typeNonNull, type)) {
if (typeNonNull != type) {
handleTypeOfInterest(typeNonNull);
if (result != null) {
return result!;
Expand Down Expand Up @@ -3378,7 +3376,7 @@ class PromotionModel<Type extends Object> {
while (index1 < chain1.length && index2 < chain2.length) {
Type type1 = chain1[index1];
Type type2 = chain2[index2];
if (typeOperations.isSameType(type1, type2)) {
if (type1 == type2) {
result ??= <Type>[];
result.add(type1);
index1++;
Expand Down Expand Up @@ -3420,7 +3418,7 @@ class PromotionModel<Type extends Object> {
// Determine the length of the common prefix the two lists share.
int shared = 0;
for (; shared < types1.length; shared++) {
if (!typeOperations.isSameType(types1[shared], types2[shared])) break;
if (types1[shared] != types2[shared]) break;
}
// Use types2 as a starting point and add any entries from types1 that are
// not present in it.
Expand Down Expand Up @@ -3468,7 +3466,7 @@ class PromotionModel<Type extends Object> {
for (int i = 0; i < thisPromotedTypes.length; i++) {
Type nextType = thisPromotedTypes[i];
if (typeOperations.isSubtypeOf(nextType, otherPromotedType) &&
!typeOperations.isSameType(nextType, otherPromotedType)) {
nextType != otherPromotedType) {
newPromotedTypes = basePromotedTypes.toList()
..addAll(thisPromotedTypes.skip(i));
break;
Expand Down Expand Up @@ -3527,7 +3525,7 @@ class PromotionModel<Type extends Object> {
List<Type> list,
Type searchType) {
for (Type type in list) {
if (typeOperations.isSameType(type, searchType)) return true;
if (type == searchType) return true;
}
return false;
}
Expand Down Expand Up @@ -4506,8 +4504,7 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
@override
void declare(Variable variable, Type staticType,
{required bool initialized, bool skipDuplicateCheck = false}) {
assert(
operations.isSameType(staticType, operations.variableType(variable)));
assert(staticType == operations.variableType(variable));
assert(_debugDeclaredVariables.add(variable) || skipDuplicateCheck,
'Variable $variable already declared');
_current = _current.declare(
Expand Down Expand Up @@ -5203,9 +5200,18 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
.ifFalse;
}
_current = ifTrue;
if (matchMayFailEvenIfCorrectType ||
(matchFailsIfWrongType && !coversMatchedType)) {
_unmatched = _join(_unmatched!, coversMatchedType ? ifTrue : ifFalse);
if (matchFailsIfWrongType && !coversMatchedType) {
// There's a reachable control flow path where the match might fail due to
// a type mismatch. Therefore, we must update the `_unmatched` flow state
// based on the state of flow analysis assuming the type check failed.
_unmatched = _join(_unmatched!, ifFalse);
}
if (matchMayFailEvenIfCorrectType) {
// There's a reachable control flow path where the type might match, but
// the match might nonetheless fail for some other reason. Therefore, we
// must update the `_unmatched` flow state based on the state of flow
// analysis assuming the type check succeeded.
_unmatched = _join(_unmatched!, ifTrue);
}
return coversMatchedType;
}
Expand Down Expand Up @@ -6500,8 +6506,7 @@ class _LegacyTypePromotion<Node extends Object, Statement extends Node,
Type currentType =
_knownTypes[variableKey] ?? _operations.variableType(variable);
Type? promotedType = _operations.tryPromoteToType(type, currentType);
if (promotedType != null &&
!_operations.isSameType(currentType, promotedType)) {
if (promotedType != null && currentType != promotedType) {
_storeExpressionInfo(isExpression,
new _LegacyExpressionInfo<Type>({variableKey: promotedType}));
}
Expand Down Expand Up @@ -6571,8 +6576,7 @@ class _LegacyTypePromotion<Node extends Object, Statement extends Node,
} else {
Type? newShownType =
_operations.tryPromoteToType(entry.value, previouslyShownType);
if (newShownType != null &&
!_operations.isSameType(previouslyShownType, newShownType)) {
if (newShownType != null && previouslyShownType != newShownType) {
newShownTypes[entry.key] = newShownType;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ abstract interface class FlowAnalysisTypeOperations<Type extends Object> {
/// (c) is a type variable that has been promoted to `Never`
bool isNever(Type type);

/// Returns `true` if [type1] and [type2] are the same type.
bool isSameType(Type type1, Type type2);

/// Return `true` if the [leftType] is a subtype of the [rightType].
bool isSubtypeOf(Type leftType, Type rightType);

Expand Down
27 changes: 13 additions & 14 deletions pkg/_fe_analyzer_shared/lib/src/type_inference/type_analyzer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import '../flow_analysis/flow_analysis.dart';
import '../types/shared_type.dart';
import 'type_analysis_result.dart';
import 'type_analyzer_operations.dart';

Expand Down Expand Up @@ -129,7 +130,7 @@ enum RelationalOperatorKind {
}

/// Information about a relational operator.
class RelationalOperatorResolution<Type extends Object> {
class RelationalOperatorResolution<Type extends SharedType> {
final RelationalOperatorKind kind;
final Type parameterType;
final Type returnType;
Expand Down Expand Up @@ -264,7 +265,7 @@ mixin TypeAnalyzer<
Statement extends Node,
Expression extends Node,
Variable extends Object,
Type extends Object,
Type extends SharedType,
Pattern extends Node,
Error,
TypeSchema extends Object,
Expand Down Expand Up @@ -1547,10 +1548,8 @@ mixin TypeAnalyzer<
matchedType: matchedValueType, knownType: requiredType);

// Stack: ()
RecordType<Type>? matchedRecordType =
operations.asRecordType(matchedValueType);
if (matchedRecordType != null) {
List<Type>? fieldTypes = _matchRecordTypeShape(fields, matchedRecordType);
if (matchedValueType is SharedRecordType<Type>) {
List<Type>? fieldTypes = _matchRecordTypeShape(fields, matchedValueType);
if (fieldTypes != null) {
assert(fieldTypes.length == fields.length);
for (int i = 0; i < fields.length; i++) {
Expand Down Expand Up @@ -2447,16 +2446,16 @@ mixin TypeAnalyzer<
/// Otherwise returns `null`.
List<Type>? _matchRecordTypeShape(
List<RecordPatternField<Node, Pattern>> fields,
RecordType<Type> matchedType,
SharedRecordType<Type> matchedType,
) {
Map<String, Type> matchedTypeNamed = {};
for (var (:name, :type) in matchedType.named) {
for (var SharedNamedType(:name, :type) in matchedType.namedTypes) {
matchedTypeNamed[name] = type;
}

List<Type> result = [];
int positionalIndex = 0;
int namedCount = 0;
Iterator<Type> positionalIterator = matchedType.positionalTypes.iterator;
for (RecordPatternField<Node, Pattern> field in fields) {
Type? fieldType;
String? name = field.name;
Expand All @@ -2467,14 +2466,14 @@ mixin TypeAnalyzer<
}
namedCount++;
} else {
if (positionalIndex >= matchedType.positional.length) {
if (!positionalIterator.moveNext()) {
return null;
}
fieldType = matchedType.positional[positionalIndex++];
fieldType = positionalIterator.current;
}
result.add(fieldType);
}
if (positionalIndex != matchedType.positional.length) {
if (positionalIterator.moveNext()) {
return null;
}
if (namedCount != matchedTypeNamed.length) {
Expand Down Expand Up @@ -2513,7 +2512,7 @@ mixin TypeAnalyzer<
bool _structurallyEqualAfterNormTypes(Type type1, Type type2) {
Type norm1 = operations.normalize(type1);
Type norm2 = operations.normalize(type2);
return operations.areStructurallyEqual(norm1, norm2);
return norm1.isStructurallyEqualTo(norm2);
}
}

Expand All @@ -2524,7 +2523,7 @@ abstract class TypeAnalyzerErrors<
Statement extends Node,
Expression extends Node,
Variable extends Object,
Type extends Object,
Type extends SharedType,
Pattern extends Node,
Error> implements TypeAnalyzerErrorsBase {
/// Called if pattern support is disabled and a case constant's static type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,14 @@
// BSD-style license that can be found in the LICENSE file.

import '../flow_analysis/flow_analysis_operations.dart';
import '../types/shared_type.dart';
import 'nullability_suffix.dart';

class RecordType<Type extends Object> {
final List<Type> positional;
final List<({String name, Type type})> named;

RecordType({
required this.positional,
required this.named,
});
}

/// Callback API used by the shared type analyzer to query and manipulate the
/// client's representation of variables and types.
abstract interface class TypeAnalyzerOperations<
Variable extends Object,
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
InferableParameter extends Object,
TypeDeclarationType extends Object,
Expand Down Expand Up @@ -52,12 +43,6 @@ abstract interface class TypeAnalyzerOperations<
/// Returns the unknown type schema (`_`) used in type inference.
TypeSchema get unknownType;

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

/// If [type] is a record type, returns it.
RecordType<Type>? asRecordType(Type type);

/// Returns the type `Future` with omitted nullability and type argument
/// [argumentType].
Type futureType(Type argumentType);
Expand Down Expand Up @@ -154,9 +139,6 @@ abstract interface class TypeAnalyzerOperations<
bool isTypeSchemaSatisfied(
{required TypeSchema typeSchema, required Type type});

/// Returns `true` if [typeSchema] is the unknown type context (`_`).
bool isUnknownType(TypeSchema typeSchema);

/// Returns whether [node] is final.
bool isVariableFinal(Variable node);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// 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.

import '../types/shared_type.dart';
import 'type_analyzer_operations.dart';

/// Tracks a single constraint on a single type parameter.
Expand Down Expand Up @@ -36,7 +37,7 @@ class GeneratedTypeConstraint<Type extends Object, TypeSchema extends Object,

/// A constraint on a type parameter that we're inferring.
class MergedTypeConstraint<
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
TypeParameter extends Object,
Variable extends Object,
Expand Down Expand Up @@ -119,8 +120,7 @@ class MergedTypeConstraint<
TypeAnalyzerOperations<Variable, Type, TypeSchema, TypeParameter,
TypeDeclarationType, TypeDeclaration>
typeAnalyzerOperations) {
return typeAnalyzerOperations.isUnknownType(lower) &&
typeAnalyzerOperations.isUnknownType(upper);
return lower is SharedUnknownType && upper is SharedUnknownType;
}

bool isSatisfiedBy(
Expand Down Expand Up @@ -173,7 +173,7 @@ class MergedTypeConstraint<
/// readable error message during type inference as well as determining whether
/// the constraint was used to fix the type parameter or not.
abstract class TypeConstraintOrigin<
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
Variable extends Object,
TypeParameter extends Object,
Expand All @@ -188,7 +188,7 @@ abstract class TypeConstraintOrigin<
}

class UnknownTypeConstraintOrigin<
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
Variable extends Object,
InferableParameter extends Object,
Expand All @@ -208,7 +208,7 @@ class UnknownTypeConstraintOrigin<
}

class TypeConstraintFromArgument<
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
Variable extends Object,
InferableParameter extends Object,
Expand Down Expand Up @@ -260,7 +260,7 @@ class TypeConstraintFromArgument<
}

class TypeConstraintFromExtendsClause<
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
Variable extends Object,
InferableParameter extends Object,
Expand Down Expand Up @@ -303,7 +303,7 @@ class TypeConstraintFromExtendsClause<
}

class TypeConstraintFromFunctionContext<
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
Variable extends Object,
InferableParameter extends Object,
Expand Down Expand Up @@ -332,7 +332,7 @@ class TypeConstraintFromFunctionContext<
}

class TypeConstraintFromReturnType<
Type extends Object,
Type extends SharedType,
TypeSchema extends Object,
Variable extends Object,
InferableParameter extends Object,
Expand Down
Loading

0 comments on commit 04d373e

Please sign in to comment.