mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 15:57:17 +00:00
[cfe] Remove isNonNullableByDefault from TypeSchemaEnvironment
Change-Id: Ife1951833bf5e6f5146e33734ae3b0cd3805bdc7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/368640 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
parent
450ddd82f8
commit
1b9ccb9b08
|
@ -53,15 +53,13 @@ abstract class ClosureContext {
|
|||
if (isGenerator) {
|
||||
if (isAsync) {
|
||||
DartType yieldContext = inferrer.getTypeArgumentOf(
|
||||
inferrer.typeSchemaEnvironment
|
||||
.getUnionFreeType(returnContext, isNonNullableByDefault: true),
|
||||
inferrer.typeSchemaEnvironment.getUnionFreeType(returnContext),
|
||||
inferrer.coreTypes.streamClass);
|
||||
return new _AsyncStarClosureContext(
|
||||
inferrer, yieldContext, declaredReturnType, needToInferReturnType);
|
||||
} else {
|
||||
DartType yieldContext = inferrer.getTypeArgumentOf(
|
||||
inferrer.typeSchemaEnvironment
|
||||
.getUnionFreeType(returnContext, isNonNullableByDefault: true),
|
||||
inferrer.typeSchemaEnvironment.getUnionFreeType(returnContext),
|
||||
inferrer.coreTypes.iterableClass);
|
||||
return new _SyncStarClosureContext(
|
||||
inferrer, yieldContext, declaredReturnType, needToInferReturnType);
|
||||
|
@ -313,8 +311,7 @@ class _SyncClosureContext implements ClosureContext {
|
|||
_returnExpressionTypes![i]);
|
||||
}
|
||||
|
||||
return _inferredReturnType =
|
||||
demoteTypeInLibrary(inferredReturnType, isNonNullableByDefault: true);
|
||||
return _inferredReturnType = demoteTypeInLibrary(inferredReturnType);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -603,8 +600,7 @@ class _AsyncClosureContext implements ClosureContext {
|
|||
inferredType, _returnStatements![i], _returnExpressionTypes![i]);
|
||||
}
|
||||
|
||||
return _inferredReturnType =
|
||||
demoteTypeInLibrary(inferredType, isNonNullableByDefault: true);
|
||||
return _inferredReturnType = demoteTypeInLibrary(inferredType);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -764,11 +760,9 @@ class _SyncStarClosureContext implements ClosureContext {
|
|||
inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
|
||||
}
|
||||
|
||||
DartType demotedType =
|
||||
demoteTypeInLibrary(inferredType, isNonNullableByDefault: true);
|
||||
DartType demotedType = demoteTypeInLibrary(inferredType);
|
||||
_emittedValueType = inferrer.getTypeArgumentOf(
|
||||
inferrer.typeSchemaEnvironment
|
||||
.getUnionFreeType(demotedType, isNonNullableByDefault: true),
|
||||
inferrer.typeSchemaEnvironment.getUnionFreeType(demotedType),
|
||||
inferrer.coreTypes.iterableClass);
|
||||
return demotedType;
|
||||
}
|
||||
|
@ -900,11 +894,9 @@ class _AsyncStarClosureContext implements ClosureContext {
|
|||
inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
|
||||
}
|
||||
|
||||
DartType demotedType =
|
||||
demoteTypeInLibrary(inferredType, isNonNullableByDefault: true);
|
||||
DartType demotedType = demoteTypeInLibrary(inferredType);
|
||||
_emittedValueType = inferrer.getTypeArgumentOf(
|
||||
inferrer.typeSchemaEnvironment
|
||||
.getUnionFreeType(demotedType, isNonNullableByDefault: true),
|
||||
inferrer.typeSchemaEnvironment.getUnionFreeType(demotedType),
|
||||
inferrer.coreTypes.streamClass);
|
||||
return demotedType;
|
||||
}
|
||||
|
|
|
@ -2664,14 +2664,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
if (inferenceNeeded) {
|
||||
gatherer = typeSchemaEnvironment.setupGenericTypeInference(
|
||||
listType, typeParametersToInfer, typeContext,
|
||||
isNonNullableByDefault: true,
|
||||
isConst: node.isConst,
|
||||
typeOperations: operations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: node);
|
||||
inferredTypes = typeSchemaEnvironment.choosePreliminaryTypes(
|
||||
gatherer, typeParametersToInfer, null,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, null);
|
||||
inferredTypeArgument = inferredTypes[0];
|
||||
} else {
|
||||
inferredTypeArgument = node.typeArgument;
|
||||
|
@ -2689,8 +2687,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
gatherer!.constrainArguments(formalTypes, actualTypes,
|
||||
treeNodeForTesting: node);
|
||||
inferredTypes = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParametersToInfer, inferredTypes!,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, inferredTypes!);
|
||||
if (dataForTesting != null) {
|
||||
dataForTesting!.typeInferenceResult.inferredTypeArguments[node] =
|
||||
inferredTypes;
|
||||
|
@ -4637,14 +4634,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
if (inferenceNeeded) {
|
||||
gatherer = typeSchemaEnvironment.setupGenericTypeInference(
|
||||
mapType, typeParametersToInfer, typeContext,
|
||||
isNonNullableByDefault: true,
|
||||
isConst: node.isConst,
|
||||
typeOperations: operations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: node);
|
||||
inferredTypes = typeSchemaEnvironment.choosePreliminaryTypes(
|
||||
gatherer, typeParametersToInfer, null,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, null);
|
||||
inferredKeyType = inferredTypes[0];
|
||||
inferredValueType = inferredTypes[1];
|
||||
} else {
|
||||
|
@ -4715,19 +4710,16 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
TypeConstraintGatherer gatherer =
|
||||
typeSchemaEnvironment.setupGenericTypeInference(
|
||||
setType, typeParametersToInfer, typeContext,
|
||||
isNonNullableByDefault: true,
|
||||
isConst: node.isConst,
|
||||
typeOperations: operations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: node);
|
||||
List<DartType> inferredTypesForSet = typeSchemaEnvironment
|
||||
.choosePreliminaryTypes(gatherer, typeParametersToInfer, null,
|
||||
isNonNullableByDefault: true);
|
||||
.choosePreliminaryTypes(gatherer, typeParametersToInfer, null);
|
||||
gatherer.constrainArguments(formalTypesForSet, actualTypesForSet,
|
||||
treeNodeForTesting: node);
|
||||
inferredTypesForSet = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParametersToInfer, inferredTypesForSet,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, inferredTypesForSet);
|
||||
DartType inferredTypeArgument = inferredTypesForSet[0];
|
||||
instrumentation?.record(
|
||||
uriForInstrumentation,
|
||||
|
@ -4767,8 +4759,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
gatherer!.constrainArguments(formalTypes, actualTypes,
|
||||
treeNodeForTesting: node);
|
||||
inferredTypes = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParametersToInfer, inferredTypes!,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, inferredTypes!);
|
||||
if (dataForTesting != null) {
|
||||
dataForTesting!.typeInferenceResult.inferredTypeArguments[node] =
|
||||
inferredTypes;
|
||||
|
@ -6160,8 +6151,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
if (isSpecialCasedBinaryOperator) {
|
||||
rightContextType =
|
||||
typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
|
||||
contextType, leftType, rightType,
|
||||
isNonNullableByDefault: true);
|
||||
contextType, leftType, rightType);
|
||||
}
|
||||
|
||||
ExpressionInferenceResult rightResult =
|
||||
|
@ -6172,8 +6162,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
|
||||
if (isSpecialCasedBinaryOperator) {
|
||||
binaryType = typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
|
||||
leftType, rightResult.inferredType,
|
||||
isNonNullableByDefault: true);
|
||||
leftType, rightResult.inferredType);
|
||||
}
|
||||
|
||||
Expression binary;
|
||||
|
@ -7945,14 +7934,12 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
if (inferenceNeeded) {
|
||||
gatherer = typeSchemaEnvironment.setupGenericTypeInference(
|
||||
setType, typeParametersToInfer, typeContext,
|
||||
isNonNullableByDefault: true,
|
||||
isConst: node.isConst,
|
||||
typeOperations: operations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: node);
|
||||
inferredTypes = typeSchemaEnvironment.choosePreliminaryTypes(
|
||||
gatherer, typeParametersToInfer, null,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, null);
|
||||
inferredTypeArgument = inferredTypes[0];
|
||||
} else {
|
||||
inferredTypeArgument = node.typeArgument;
|
||||
|
@ -7971,8 +7958,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
gatherer!.constrainArguments(formalTypes, actualTypes,
|
||||
treeNodeForTesting: node);
|
||||
inferredTypes = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParametersToInfer, inferredTypes!,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, inferredTypes!);
|
||||
if (dataForTesting != null) {
|
||||
dataForTesting!.typeInferenceResult.inferredTypeArguments[node] =
|
||||
inferredTypes;
|
||||
|
@ -10226,8 +10212,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
node.minusType = replaceReturnType(
|
||||
minusTarget.getFunctionType(this),
|
||||
typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
|
||||
lengthType, coreTypes.intNonNullableRawType,
|
||||
isNonNullableByDefault: true));
|
||||
lengthType, coreTypes.intNonNullableRawType));
|
||||
|
||||
ObjectAccessTarget indexGetTarget = findInterfaceMember(
|
||||
lookupType, indexGetName, node.fileOffset,
|
||||
|
@ -10926,13 +10911,11 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
TypeConstraintGatherer gatherer =
|
||||
typeSchemaEnvironment.setupGenericTypeInference(
|
||||
declaredType, typeParametersToInfer, contextType,
|
||||
isNonNullableByDefault: true,
|
||||
typeOperations: operations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: treeNodeForTesting);
|
||||
return typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParametersToInfer, null,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParametersToInfer, null);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -947,15 +947,13 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
new List<DartType>.filled(typeParameters.length, const UnknownType());
|
||||
TypeConstraintGatherer gatherer = typeSchemaEnvironment
|
||||
.setupGenericTypeInference(null, typeParameters, null,
|
||||
isNonNullableByDefault: true,
|
||||
typeOperations: cfeOperations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: treeNodeForTesting);
|
||||
gatherer.constrainArguments([onType], [receiverType],
|
||||
treeNodeForTesting: treeNodeForTesting);
|
||||
inferredTypes = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParameters, inferredTypes,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParameters, inferredTypes);
|
||||
return inferredTypes;
|
||||
}
|
||||
|
||||
|
@ -1391,7 +1389,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
// not spec'ed anywhere.
|
||||
return const DynamicType();
|
||||
} else {
|
||||
return demoteTypeInLibrary(initializerType, isNonNullableByDefault: true);
|
||||
return demoteTypeInLibrary(initializerType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1622,13 +1620,11 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
}
|
||||
gatherer = typeSchemaEnvironment.setupGenericTypeInference(
|
||||
calleeType.returnType, calleeTypeParameters, typeContext,
|
||||
isNonNullableByDefault: true,
|
||||
typeOperations: cfeOperations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: arguments);
|
||||
inferredTypes = typeSchemaEnvironment.choosePreliminaryTypes(
|
||||
gatherer, calleeTypeParameters, null,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, calleeTypeParameters, null);
|
||||
instantiator = new FunctionTypeInstantiator.fromIterables(
|
||||
calleeTypeParameters, inferredTypes);
|
||||
} else if (explicitTypeArguments != null &&
|
||||
|
@ -1696,13 +1692,11 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
if (isSpecialCasedBinaryOperator) {
|
||||
inferredFormalType =
|
||||
typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
|
||||
typeContext, receiverType!, inferredFormalType,
|
||||
isNonNullableByDefault: true);
|
||||
typeContext, receiverType!, inferredFormalType);
|
||||
} else if (isSpecialCasedTernaryOperator) {
|
||||
inferredFormalType =
|
||||
typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator(
|
||||
typeContext, receiverType!, inferredFormalType,
|
||||
isNonNullableByDefault: true);
|
||||
typeContext, receiverType!, inferredFormalType);
|
||||
}
|
||||
}
|
||||
return visitor.inferExpression(argumentExpression, inferredFormalType);
|
||||
|
@ -1801,8 +1795,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
.planReconciliationStages()) {
|
||||
if (gatherer != null && !isFirstStage) {
|
||||
inferredTypes = typeSchemaEnvironment.choosePreliminaryTypes(
|
||||
gatherer, calleeTypeParameters, inferredTypes,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, calleeTypeParameters, inferredTypes);
|
||||
instantiator = new FunctionTypeInstantiator.fromIterables(
|
||||
calleeTypeParameters, inferredTypes);
|
||||
}
|
||||
|
@ -1863,8 +1856,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
calleeType = replaceReturnType(
|
||||
calleeType,
|
||||
typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
|
||||
receiverType!, actualTypes[0],
|
||||
isNonNullableByDefault: true));
|
||||
receiverType!, actualTypes[0]));
|
||||
} else if (isSpecialCasedTernaryOperator) {
|
||||
calleeType = replaceReturnType(
|
||||
calleeType,
|
||||
|
@ -1905,8 +1897,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
|
||||
if (inferenceNeeded) {
|
||||
inferredTypes = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer!, calleeTypeParameters, inferredTypes!,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer!, calleeTypeParameters, inferredTypes!);
|
||||
assert(inferredTypes.every((type) => isKnown(type)),
|
||||
"Unknown type(s) in inferred types: $inferredTypes.");
|
||||
assert(inferredTypes.every((type) => !hasPromotedTypeVariable(type)),
|
||||
|
@ -2114,8 +2105,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
}
|
||||
instrumentation?.record(uriForInstrumentation, formal.fileOffset,
|
||||
'type', new InstrumentationValueForType(inferredType));
|
||||
formal.type =
|
||||
demoteTypeInLibrary(inferredType, isNonNullableByDefault: true);
|
||||
formal.type = demoteTypeInLibrary(inferredType);
|
||||
if (dataForTesting != null) {
|
||||
dataForTesting!.typeInferenceResult.inferredVariableTypes[formal] =
|
||||
formal.type;
|
||||
|
@ -3451,13 +3441,11 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
|
|||
TypeConstraintGatherer gatherer =
|
||||
typeSchemaEnvironment.setupGenericTypeInference(
|
||||
instantiatedType, typeParameters, context,
|
||||
isNonNullableByDefault: true,
|
||||
typeOperations: cfeOperations,
|
||||
inferenceResultForTesting: dataForTesting?.typeInferenceResult,
|
||||
treeNodeForTesting: treeNodeForTesting);
|
||||
inferredTypes = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParameters, inferredTypes,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParameters, inferredTypes);
|
||||
FunctionTypeInstantiator instantiator =
|
||||
new FunctionTypeInstantiator.fromIterables(
|
||||
typeParameters, inferredTypes);
|
||||
|
|
|
@ -508,17 +508,15 @@ class InstanceAccessTarget extends ObjectAccessTarget {
|
|||
@override
|
||||
bool isSpecialCasedBinaryOperator(InferenceVisitorBase base) {
|
||||
return member is Procedure &&
|
||||
base.typeSchemaEnvironment.isSpecialCasesBinaryForReceiverType(
|
||||
member as Procedure, receiverType,
|
||||
isNonNullableByDefault: true);
|
||||
base.typeSchemaEnvironment
|
||||
.isSpecialCasedBinaryOperator(member as Procedure);
|
||||
}
|
||||
|
||||
@override
|
||||
bool isSpecialCasedTernaryOperator(InferenceVisitorBase base) {
|
||||
return member is Procedure &&
|
||||
base.typeSchemaEnvironment.isSpecialCasedTernaryOperator(
|
||||
member as Procedure,
|
||||
isNonNullableByDefault: true);
|
||||
base.typeSchemaEnvironment
|
||||
.isSpecialCasedTernaryOperator(member as Procedure);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -32,8 +32,6 @@ class TypeConstraintGatherer {
|
|||
|
||||
final List<StructuralParameter> _parametersToConstrain;
|
||||
|
||||
final bool _isNonNullableByDefault;
|
||||
|
||||
final OperationsCfe typeOperations;
|
||||
|
||||
final TypeSchemaEnvironment _environment;
|
||||
|
@ -42,11 +40,9 @@ class TypeConstraintGatherer {
|
|||
|
||||
TypeConstraintGatherer(
|
||||
this._environment, Iterable<StructuralParameter> typeParameters,
|
||||
{required bool isNonNullableByDefault,
|
||||
required OperationsCfe typeOperations,
|
||||
{required OperationsCfe typeOperations,
|
||||
required TypeInferenceResultForTesting? inferenceResultForTesting})
|
||||
: typeOperations = typeOperations,
|
||||
_isNonNullableByDefault = isNonNullableByDefault,
|
||||
_parametersToConstrain =
|
||||
new List<StructuralParameter>.of(typeParameters),
|
||||
_inferenceResultForTesting = inferenceResultForTesting;
|
||||
|
@ -76,8 +72,7 @@ class TypeConstraintGatherer {
|
|||
}
|
||||
|
||||
/// Returns the set of type constraints that was gathered.
|
||||
Map<StructuralParameter, MergedTypeConstraint> computeConstraints(
|
||||
{required bool isNonNullableByDefault}) {
|
||||
Map<StructuralParameter, MergedTypeConstraint> computeConstraints() {
|
||||
Map<StructuralParameter, MergedTypeConstraint> result = {};
|
||||
for (StructuralParameter parameter in _parametersToConstrain) {
|
||||
result[parameter] = new MergedTypeConstraint(
|
||||
|
@ -98,13 +93,8 @@ class TypeConstraintGatherer {
|
|||
/// a subtype of [type] under any set of constraints.
|
||||
bool tryConstrainLower(DartType type, DartType bound,
|
||||
{required TreeNode? treeNodeForTesting}) {
|
||||
if (_isNonNullableByDefault) {
|
||||
return _tryNullabilityAwareSubtypeMatch(bound, type,
|
||||
constrainSupertype: true, treeNodeForTesting: treeNodeForTesting);
|
||||
} else {
|
||||
return _tryNullabilityObliviousSubtypeMatch(bound, type,
|
||||
treeNodeForTesting: treeNodeForTesting);
|
||||
}
|
||||
return _tryNullabilityAwareSubtypeMatch(bound, type,
|
||||
constrainSupertype: true, treeNodeForTesting: treeNodeForTesting);
|
||||
}
|
||||
|
||||
/// Tries to constrain type parameters in [type], so that [type] <: [bound].
|
||||
|
@ -113,13 +103,8 @@ class TypeConstraintGatherer {
|
|||
/// a subtype of [bound] under any set of constraints.
|
||||
bool tryConstrainUpper(DartType type, DartType bound,
|
||||
{required TreeNode? treeNodeForTesting}) {
|
||||
if (_isNonNullableByDefault) {
|
||||
return _tryNullabilityAwareSubtypeMatch(type, bound,
|
||||
constrainSupertype: false, treeNodeForTesting: treeNodeForTesting);
|
||||
} else {
|
||||
return _tryNullabilityObliviousSubtypeMatch(type, bound,
|
||||
treeNodeForTesting: treeNodeForTesting);
|
||||
}
|
||||
return _tryNullabilityAwareSubtypeMatch(type, bound,
|
||||
constrainSupertype: false, treeNodeForTesting: treeNodeForTesting);
|
||||
}
|
||||
|
||||
/// Tries to match [subtype] against [supertype].
|
||||
|
|
|
@ -26,21 +26,10 @@ class _HasPromotedTypeVariableVisitor extends FindTypeVisitor {
|
|||
/// If [library] is non-nullable by default all legacy types have been replaced
|
||||
/// with non-nullable types. Otherwise all non-legacy types have been replaced
|
||||
/// with legacy types.
|
||||
DartType demoteTypeInLibrary(DartType type,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
if (isNonNullableByDefault) {
|
||||
return type.accept1(
|
||||
const _DemotionNullabilityNormalization(
|
||||
demoteTypeVariables: true, forNonNullableByDefault: true),
|
||||
Variance.covariant) ??
|
||||
type;
|
||||
} else {
|
||||
return type.accept1(
|
||||
const _DemotionNullabilityNormalization(
|
||||
demoteTypeVariables: true, forNonNullableByDefault: false),
|
||||
Variance.covariant) ??
|
||||
type;
|
||||
}
|
||||
DartType demoteTypeInLibrary(DartType type) {
|
||||
return type.accept1(
|
||||
const _DemotionNullabilityNormalization(), Variance.covariant) ??
|
||||
type;
|
||||
}
|
||||
|
||||
/// Visitor that replaces all promoted type variables the type variable itself
|
||||
|
@ -48,23 +37,12 @@ DartType demoteTypeInLibrary(DartType type,
|
|||
///
|
||||
/// The visitor returns `null` if the type wasn't changed.
|
||||
class _DemotionNullabilityNormalization extends ReplacementVisitor {
|
||||
final bool demoteTypeVariables;
|
||||
final bool forNonNullableByDefault;
|
||||
|
||||
const _DemotionNullabilityNormalization(
|
||||
{required this.demoteTypeVariables,
|
||||
required this.forNonNullableByDefault});
|
||||
const _DemotionNullabilityNormalization();
|
||||
|
||||
@override
|
||||
Nullability? visitNullability(DartType node) {
|
||||
if (forNonNullableByDefault) {
|
||||
if (node.declaredNullability == Nullability.legacy) {
|
||||
return Nullability.nonNullable;
|
||||
}
|
||||
} else {
|
||||
if (node.declaredNullability != Nullability.legacy) {
|
||||
return Nullability.legacy;
|
||||
}
|
||||
if (node.declaredNullability == Nullability.legacy) {
|
||||
return Nullability.nonNullable;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -78,10 +56,7 @@ class _DemotionNullabilityNormalization extends ReplacementVisitor {
|
|||
@override
|
||||
DartType? visitIntersectionType(IntersectionType node, Variance variance) {
|
||||
Nullability? newNullability = visitNullability(node);
|
||||
if (demoteTypeVariables) {
|
||||
return new TypeParameterType(
|
||||
node.left.parameter, newNullability ?? node.left.nullability);
|
||||
}
|
||||
return createTypeParameterType(node.left, newNullability);
|
||||
return new TypeParameterType(
|
||||
node.left.parameter, newNullability ?? node.left.nullability);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,104 +86,74 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
List<DartType> choosePreliminaryTypes(
|
||||
TypeConstraintGatherer gatherer,
|
||||
List<StructuralParameter> typeParametersToInfer,
|
||||
List<DartType>? previouslyInferredTypes,
|
||||
{required bool isNonNullableByDefault}) =>
|
||||
List<DartType>? previouslyInferredTypes) =>
|
||||
_chooseTypes(gatherer, typeParametersToInfer, previouslyInferredTypes,
|
||||
isNonNullableByDefault: isNonNullableByDefault, preliminary: true);
|
||||
|
||||
@override
|
||||
DartType getTypeOfSpecialCasedBinaryOperator(DartType type1, DartType type2,
|
||||
{bool isNonNullableByDefault = false}) {
|
||||
if (isNonNullableByDefault) {
|
||||
return super.getTypeOfSpecialCasedBinaryOperator(type1, type2,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
} else {
|
||||
// TODO(paulberry): this matches what is defined in the spec. It would be
|
||||
// nice if we could change kernel to match the spec and not have to
|
||||
// override.
|
||||
if (type1 is InterfaceType && type1.classNode == coreTypes.intClass) {
|
||||
if (type2 is InterfaceType && type2.classNode == coreTypes.intClass) {
|
||||
return type2.withDeclaredNullability(type1.nullability);
|
||||
}
|
||||
if (type2 is InterfaceType &&
|
||||
type2.classNode == coreTypes.doubleClass) {
|
||||
return type2.withDeclaredNullability(type1.nullability);
|
||||
}
|
||||
}
|
||||
return coreTypes.numRawType(type1.nullability);
|
||||
}
|
||||
}
|
||||
preliminary: true);
|
||||
|
||||
DartType getContextTypeOfSpecialCasedBinaryOperator(
|
||||
DartType contextType, DartType type1, DartType type2,
|
||||
{bool isNonNullableByDefault = false}) {
|
||||
if (isNonNullableByDefault) {
|
||||
if (contextType is! NeverType &&
|
||||
type1 is! NeverType &&
|
||||
isSubtypeOf(type1, coreTypes.numNonNullableRawType,
|
||||
DartType contextType, DartType type1, DartType type2) {
|
||||
if (contextType is! NeverType &&
|
||||
type1 is! NeverType &&
|
||||
isSubtypeOf(type1, coreTypes.numNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If e is an expression of the form e1 + e2, e1 - e2, e1 * e2, e1 % e2
|
||||
// or e1.remainder(e2), where C is the context type of e and T is the
|
||||
// static type of e1, and where T is a non-Never subtype of num, then:
|
||||
if (isSubtypeOf(coreTypes.intNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
isSubtypeOf(type1, coreTypes.intNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If e is an expression of the form e1 + e2, e1 - e2, e1 * e2, e1 % e2
|
||||
// or e1.remainder(e2), where C is the context type of e and T is the
|
||||
// static type of e1, and where T is a non-Never subtype of num, then:
|
||||
if (isSubtypeOf(coreTypes.intNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
isSubtypeOf(type1, coreTypes.intNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If int <: C, not num <: C, and T <: int, then the context type of
|
||||
// e2 is int.
|
||||
return coreTypes.intNonNullableRawType;
|
||||
} else if (isSubtypeOf(coreTypes.doubleNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(type1, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If double <: C, not num <: C, and not T <: double, then the context
|
||||
// type of e2 is double.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else {
|
||||
// Otherwise, the context type of e2 is num.
|
||||
return coreTypes.numNonNullableRawType;
|
||||
}
|
||||
// If int <: C, not num <: C, and T <: int, then the context type of
|
||||
// e2 is int.
|
||||
return coreTypes.intNonNullableRawType;
|
||||
} else if (isSubtypeOf(coreTypes.doubleNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(type1, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If double <: C, not num <: C, and not T <: double, then the context
|
||||
// type of e2 is double.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else {
|
||||
// Otherwise, the context type of e2 is num.
|
||||
return coreTypes.numNonNullableRawType;
|
||||
}
|
||||
}
|
||||
return type2;
|
||||
}
|
||||
|
||||
DartType getContextTypeOfSpecialCasedTernaryOperator(
|
||||
DartType contextType, DartType receiverType, DartType operandType,
|
||||
{bool isNonNullableByDefault = false}) {
|
||||
if (isNonNullableByDefault) {
|
||||
if (receiverType is! NeverType &&
|
||||
isSubtypeOf(receiverType, coreTypes.numNonNullableRawType,
|
||||
DartType contextType, DartType receiverType, DartType operandType) {
|
||||
if (receiverType is! NeverType &&
|
||||
isSubtypeOf(receiverType, coreTypes.numNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If e is an expression of the form e1.clamp(e2, e3) where C is the
|
||||
// context type of e and T is the static type of e1 where T is a
|
||||
// non-Never subtype of num, then:
|
||||
if (isSubtypeOf(coreTypes.intNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
isSubtypeOf(receiverType, coreTypes.intNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If e is an expression of the form e1.clamp(e2, e3) where C is the
|
||||
// context type of e and T is the static type of e1 where T is a
|
||||
// non-Never subtype of num, then:
|
||||
if (isSubtypeOf(coreTypes.intNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
isSubtypeOf(receiverType, coreTypes.intNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If int <: C, not num <: C, and T <: int, then the context type of
|
||||
// e2 and e3 is int.
|
||||
return coreTypes.intNonNullableRawType;
|
||||
} else if (isSubtypeOf(coreTypes.doubleNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
isSubtypeOf(receiverType, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If double <: C, not num <: C, and T <: double, then the context
|
||||
// type of e2 and e3 is double.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else {
|
||||
// Otherwise the context type of e2 an e3 is num
|
||||
return coreTypes.numNonNullableRawType;
|
||||
}
|
||||
// If int <: C, not num <: C, and T <: int, then the context type of
|
||||
// e2 and e3 is int.
|
||||
return coreTypes.intNonNullableRawType;
|
||||
} else if (isSubtypeOf(coreTypes.doubleNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
!isSubtypeOf(coreTypes.numNonNullableRawType, contextType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
isSubtypeOf(receiverType, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If double <: C, not num <: C, and T <: double, then the context
|
||||
// type of e2 and e3 is double.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else {
|
||||
// Otherwise the context type of e2 an e3 is num
|
||||
return coreTypes.numNonNullableRawType;
|
||||
}
|
||||
}
|
||||
return operandType;
|
||||
|
@ -221,8 +191,7 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
Map<StructuralParameter, MergedTypeConstraint> constraints,
|
||||
List<StructuralParameter> typeParametersToInfer,
|
||||
List<DartType>? previouslyInferredTypes,
|
||||
{required bool isNonNullableByDefault,
|
||||
bool preliminary = false,
|
||||
{bool preliminary = false,
|
||||
required OperationsCfe operations}) {
|
||||
List<DartType> inferredTypes =
|
||||
previouslyInferredTypes?.toList(growable: false) ??
|
||||
|
@ -243,13 +212,11 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
if (preliminary) {
|
||||
inferredTypes[i] = _inferTypeParameterFromContext(
|
||||
previouslyInferredTypes?[i], constraint, extendsConstraint,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
isLegacyCovariant: typeParam.isLegacyCovariant,
|
||||
operations: operations);
|
||||
} else {
|
||||
inferredTypes[i] = _inferTypeParameterFromAll(
|
||||
previouslyInferredTypes?[i], constraint, extendsConstraint,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
isContravariant:
|
||||
typeParam.variance == shared.Variance.contravariant,
|
||||
isLegacyCovariant: typeParam.isLegacyCovariant,
|
||||
|
@ -285,7 +252,7 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
}
|
||||
List<DartType> instantiatedTypes = calculateBounds(
|
||||
helperTypeParameters, coreTypes.objectClass,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
isNonNullableByDefault: true);
|
||||
for (int i = 0; i < instantiatedTypes.length; ++i) {
|
||||
if (inferredTypes[i] is UnknownType) {
|
||||
inferredTypes[i] = instantiatedTypes[i];
|
||||
|
@ -331,20 +298,8 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
/// This is a case of type-based overloading, which in Dart is only supported
|
||||
/// by giving special treatment to certain arithmetic operators.
|
||||
bool isSpecialCasesBinaryForReceiverType(
|
||||
Procedure member, DartType receiverType,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
if (!isNonNullableByDefault) {
|
||||
// TODO(paulberry): this matches what is defined in the spec. It would be
|
||||
// nice if we could change kernel to match the spec and not have to
|
||||
// override.
|
||||
if (member.name.text == 'remainder') return false;
|
||||
if (!(receiverType is InterfaceType &&
|
||||
identical(receiverType.classNode, coreTypes.intClass))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return isSpecialCasedBinaryOperator(member,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
Procedure member, DartType receiverType) {
|
||||
return isSpecialCasedBinaryOperator(member);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -363,8 +318,7 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
DartType? declaredReturnType,
|
||||
List<StructuralParameter> typeParametersToInfer,
|
||||
DartType? returnContextType,
|
||||
{required bool isNonNullableByDefault,
|
||||
bool isConst = false,
|
||||
{bool isConst = false,
|
||||
required OperationsCfe typeOperations,
|
||||
required TypeInferenceResultForTesting? inferenceResultForTesting,
|
||||
required TreeNode? treeNodeForTesting}) {
|
||||
|
@ -376,23 +330,16 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
// are implied by this.
|
||||
TypeConstraintGatherer gatherer = new TypeConstraintGatherer(
|
||||
this, typeParametersToInfer,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
typeOperations: typeOperations,
|
||||
inferenceResultForTesting: inferenceResultForTesting);
|
||||
|
||||
if (!isEmptyContext(returnContextType)) {
|
||||
if (isConst) {
|
||||
if (isNonNullableByDefault) {
|
||||
returnContextType = new NullabilityAwareFreeTypeVariableEliminator(
|
||||
bottomType: const NeverType.nonNullable(),
|
||||
topType: objectNullableRawType,
|
||||
topFunctionType: functionRawType(Nullability.nonNullable))
|
||||
.eliminateToLeast(returnContextType!);
|
||||
} else {
|
||||
returnContextType =
|
||||
new TypeVariableEliminator(const NullType(), objectLegacyRawType)
|
||||
.substituteType(returnContextType!);
|
||||
}
|
||||
returnContextType = new NullabilityAwareFreeTypeVariableEliminator(
|
||||
bottomType: const NeverType.nonNullable(),
|
||||
topType: objectNullableRawType,
|
||||
topFunctionType: functionRawType(Nullability.nonNullable))
|
||||
.eliminateToLeast(returnContextType!);
|
||||
}
|
||||
gatherer.tryConstrainUpper(declaredReturnType!, returnContextType!,
|
||||
treeNodeForTesting: treeNodeForTesting);
|
||||
|
@ -467,10 +414,9 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
List<DartType> chooseFinalTypes(
|
||||
TypeConstraintGatherer gatherer,
|
||||
List<StructuralParameter> typeParametersToInfer,
|
||||
List<DartType>? previouslyInferredTypes,
|
||||
{required bool isNonNullableByDefault}) =>
|
||||
List<DartType>? previouslyInferredTypes) =>
|
||||
_chooseTypes(gatherer, typeParametersToInfer, previouslyInferredTypes,
|
||||
isNonNullableByDefault: isNonNullableByDefault, preliminary: false);
|
||||
preliminary: false);
|
||||
|
||||
/// Computes (or recomputes) a set of [inferredTypes] based on the constraints
|
||||
/// that have been recorded so far.
|
||||
|
@ -478,28 +424,23 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
TypeConstraintGatherer gatherer,
|
||||
List<StructuralParameter> typeParametersToInfer,
|
||||
List<DartType>? previouslyInferredTypes,
|
||||
{required bool isNonNullableByDefault,
|
||||
required bool preliminary}) {
|
||||
{required bool preliminary}) {
|
||||
List<DartType> inferredTypes = inferTypeFromConstraints(
|
||||
gatherer.computeConstraints(
|
||||
isNonNullableByDefault: isNonNullableByDefault),
|
||||
gatherer.computeConstraints(),
|
||||
typeParametersToInfer,
|
||||
previouslyInferredTypes,
|
||||
isNonNullableByDefault: isNonNullableByDefault,
|
||||
preliminary: preliminary,
|
||||
operations: gatherer.typeOperations);
|
||||
|
||||
for (int i = 0; i < inferredTypes.length; i++) {
|
||||
inferredTypes[i] = demoteTypeInLibrary(inferredTypes[i],
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
inferredTypes[i] = demoteTypeInLibrary(inferredTypes[i]);
|
||||
}
|
||||
return inferredTypes;
|
||||
}
|
||||
|
||||
DartType _inferTypeParameterFromAll(DartType? typeFromPreviousInference,
|
||||
MergedTypeConstraint constraint, DartType? extendsConstraint,
|
||||
{required bool isNonNullableByDefault,
|
||||
bool isContravariant = false,
|
||||
{bool isContravariant = false,
|
||||
bool isLegacyCovariant = true,
|
||||
required OperationsCfe operations}) {
|
||||
// See if we already fixed this type in a previous inference step.
|
||||
|
@ -516,23 +457,14 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
constraint.mergeInTypeSchemaUpper(extendsConstraint, operations);
|
||||
}
|
||||
|
||||
return solveTypeConstraint(
|
||||
constraint,
|
||||
isNonNullableByDefault
|
||||
? coreTypes.objectNullableRawType
|
||||
: const DynamicType(),
|
||||
isNonNullableByDefault
|
||||
? const NeverType.nonNullable()
|
||||
: const NullType(),
|
||||
grounded: true,
|
||||
isContravariant: isContravariant);
|
||||
return solveTypeConstraint(constraint, coreTypes.objectNullableRawType,
|
||||
const NeverType.nonNullable(),
|
||||
grounded: true, isContravariant: isContravariant);
|
||||
}
|
||||
|
||||
DartType _inferTypeParameterFromContext(DartType? typeFromPreviousInference,
|
||||
MergedTypeConstraint constraint, DartType? extendsConstraint,
|
||||
{required bool isNonNullableByDefault,
|
||||
bool isLegacyCovariant = true,
|
||||
required OperationsCfe operations}) {
|
||||
{bool isLegacyCovariant = true, required OperationsCfe operations}) {
|
||||
// See if we already fixed this type in a previous inference step.
|
||||
// If so, then we aren't allowed to change it unless [isLegacyCovariant] is
|
||||
// false.
|
||||
|
@ -542,14 +474,8 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
return typeFromPreviousInference;
|
||||
}
|
||||
|
||||
DartType t = solveTypeConstraint(
|
||||
constraint,
|
||||
isNonNullableByDefault
|
||||
? coreTypes.objectNullableRawType
|
||||
: const DynamicType(),
|
||||
isNonNullableByDefault
|
||||
? const NeverType.nonNullable()
|
||||
: const NullType());
|
||||
DartType t = solveTypeConstraint(constraint,
|
||||
coreTypes.objectNullableRawType, const NeverType.nonNullable());
|
||||
if (!isKnown(t)) {
|
||||
return t;
|
||||
}
|
||||
|
@ -564,14 +490,8 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
|||
if (extendsConstraint != null) {
|
||||
constraint = constraint.clone();
|
||||
constraint.mergeInTypeSchemaUpper(extendsConstraint, operations);
|
||||
return solveTypeConstraint(
|
||||
constraint,
|
||||
isNonNullableByDefault
|
||||
? coreTypes.objectNullableRawType
|
||||
: const DynamicType(),
|
||||
isNonNullableByDefault
|
||||
? const NeverType.nonNullable()
|
||||
: const NullType());
|
||||
return solveTypeConstraint(constraint, coreTypes.objectNullableRawType,
|
||||
const NeverType.nonNullable());
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -396,7 +396,6 @@ class TypeConstraintGathererTest {
|
|||
coreTypes, new ClassHierarchy(component, coreTypes));
|
||||
var typeConstraintGatherer = new TypeConstraintGatherer(
|
||||
typeSchemaEnvironment, typeParameterNodesToConstrain,
|
||||
isNonNullableByDefault: true,
|
||||
typeOperations: new OperationsCfe(typeSchemaEnvironment,
|
||||
fieldNonPromotabilityInfo: new FieldNonPromotabilityInfo(
|
||||
fieldNameInfo: {}, individualPropertyReasons: {}),
|
||||
|
@ -405,8 +404,7 @@ class TypeConstraintGathererTest {
|
|||
typeCacheLegacy: {}),
|
||||
inferenceResultForTesting: null);
|
||||
var constraints = tryConstrain(typeConstraintGatherer, a, b)
|
||||
? typeConstraintGatherer.computeConstraints(
|
||||
isNonNullableByDefault: true)
|
||||
? typeConstraintGatherer.computeConstraints()
|
||||
: null;
|
||||
if (expectedConstraints == null) {
|
||||
expect(constraints, isNull);
|
||||
|
|
|
@ -304,7 +304,6 @@ class TypeConstraintGathererTest {
|
|||
coreTypes, new ClassHierarchy(component, coreTypes));
|
||||
var typeConstraintGatherer = new TypeConstraintGatherer(
|
||||
typeSchemaEnvironment, typeParameterNodesToConstrain,
|
||||
isNonNullableByDefault: true,
|
||||
typeOperations: new OperationsCfe(typeSchemaEnvironment,
|
||||
fieldNonPromotabilityInfo: new FieldNonPromotabilityInfo(
|
||||
fieldNameInfo: {}, individualPropertyReasons: {}),
|
||||
|
@ -313,8 +312,7 @@ class TypeConstraintGathererTest {
|
|||
typeCacheLegacy: {}),
|
||||
inferenceResultForTesting: null);
|
||||
var constraints = tryConstrain(typeConstraintGatherer, a, b)
|
||||
? typeConstraintGatherer.computeConstraints(
|
||||
isNonNullableByDefault: true)
|
||||
? typeConstraintGatherer.computeConstraints()
|
||||
: null;
|
||||
if (expectedConstraints == null) {
|
||||
expect(constraints, isNull);
|
||||
|
|
|
@ -174,7 +174,6 @@ abstract class TypeSchemaEnvironmentTestBase {
|
|||
declaredReturnTypeNode,
|
||||
typeParameterNodesToInfer,
|
||||
returnContextTypeNode,
|
||||
isNonNullableByDefault: true,
|
||||
typeOperations: new OperationsCfe(typeSchemaEnvironment,
|
||||
fieldNonPromotabilityInfo: new FieldNonPromotabilityInfo(
|
||||
fieldNameInfo: {}, individualPropertyReasons: {}),
|
||||
|
@ -185,14 +184,12 @@ abstract class TypeSchemaEnvironmentTestBase {
|
|||
treeNodeForTesting: null);
|
||||
if (formalTypeNodes == null) {
|
||||
inferredTypeNodes = typeSchemaEnvironment.choosePreliminaryTypes(
|
||||
gatherer, typeParameterNodesToInfer, inferredTypeNodes,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParameterNodesToInfer, inferredTypeNodes);
|
||||
} else {
|
||||
gatherer.constrainArguments(formalTypeNodes, actualTypeNodes!,
|
||||
treeNodeForTesting: null);
|
||||
inferredTypeNodes = typeSchemaEnvironment.chooseFinalTypes(
|
||||
gatherer, typeParameterNodesToInfer, inferredTypeNodes!,
|
||||
isNonNullableByDefault: true);
|
||||
gatherer, typeParameterNodesToInfer, inferredTypeNodes!);
|
||||
}
|
||||
|
||||
assert(
|
||||
|
@ -228,7 +225,6 @@ abstract class TypeSchemaEnvironmentTestBase {
|
|||
{typeParameterNode: typeConstraint},
|
||||
[typeParameterNode],
|
||||
inferredTypeNodes,
|
||||
isNonNullableByDefault: true,
|
||||
preliminary: downwardsInferPhase,
|
||||
operations: _operations);
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
library;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:7:3: Error: Method not found: 'z'.
|
||||
// z("Hello, World!");
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:8:3: Error: Undefined name 'z'.
|
||||
// z.print("Hello, World!");
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:9:3: Error: Undefined name 'y'.
|
||||
// y.z.print("Hello, World!");
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:10:3: Error: Undefined name 'x'.
|
||||
// x.y.z.print("Hello, World!");
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:14:7: Error: Method not found: 'z'.
|
||||
// z("Hello, World!") +
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:15:7: Error: Undefined name 'z'.
|
||||
// z.print("Hello, World!") +
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:16:7: Error: Undefined name 'y'.
|
||||
// y.z.print("Hello, World!") +
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:17:7: Error: Undefined name 'x'.
|
||||
// x.y.z.print("Hello, World!");
|
||||
// ^
|
||||
//
|
||||
// pkg/front_end/testcases/general/invocations.dart:13:7: Error: This expression has type 'void' and can't be used.
|
||||
// print("Hello, World!") +
|
||||
// ^
|
||||
//
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method main() → dynamic {
|
||||
core::print("Hello, World!");
|
||||
invalid-expression "pkg/front_end/testcases/general/invocations.dart:7:3: Error: Method not found: 'z'.
|
||||
z(\"Hello, World!\");
|
||||
^";
|
||||
invalid-expression "pkg/front_end/testcases/general/invocations.dart:8:3: Error: Undefined name 'z'.
|
||||
z.print(\"Hello, World!\");
|
||||
^"{dynamic}.print("Hello, World!");
|
||||
invalid-expression "pkg/front_end/testcases/general/invocations.dart:9:3: Error: Undefined name 'y'.
|
||||
y.z.print(\"Hello, World!\");
|
||||
^"{<invalid>}.z{dynamic}.print("Hello, World!");
|
||||
invalid-expression "pkg/front_end/testcases/general/invocations.dart:10:3: Error: Undefined name 'x'.
|
||||
x.y.z.print(\"Hello, World!\");
|
||||
^"{<invalid>}.y{<invalid>}.z{dynamic}.print("Hello, World!");
|
||||
1.{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:13:7: Error: This expression has type 'void' and can't be used.
|
||||
print(\"Hello, World!\") +
|
||||
^" in core::print("Hello, World!")){(core::num) → core::num}.{core::num::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:14:7: Error: Method not found: 'z'.
|
||||
z(\"Hello, World!\") +
|
||||
^"){(core::num) → core::double}.{core::double::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:15:7: Error: Undefined name 'z'.
|
||||
z.print(\"Hello, World!\") +
|
||||
^"{dynamic}.print("Hello, World!") as{TypeError,ForDynamic} core::num){(core::num) → core::double}.{core::double::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:16:7: Error: Undefined name 'y'.
|
||||
y.z.print(\"Hello, World!\") +
|
||||
^"{<invalid>}.z{dynamic}.print("Hello, World!") as{TypeError,ForDynamic} core::num){(core::num) → core::double}.{core::double::+}(invalid-expression "pkg/front_end/testcases/general/invocations.dart:17:7: Error: Undefined name 'x'.
|
||||
x.y.z.print(\"Hello, World!\");
|
||||
^"{<invalid>}.y{<invalid>}.z{dynamic}.print("Hello, World!") as{TypeError,ForDynamic} core::num){(core::num) → core::double};
|
||||
}
|
|
@ -41,7 +41,6 @@ general/infer_field_from_multiple2: TypeCheckError
|
|||
general/infer_field_from_multiple: TypeCheckError
|
||||
general/invalid_operator: TypeCheckError
|
||||
general/invalid_operator_override: TypeCheckError
|
||||
general/invocations: TypeCheckError
|
||||
general/issue41210a: TypeCheckError
|
||||
general/issue41210b/issue41210.no_link: TypeCheckError
|
||||
general/issue41210b/issue41210: TypeCheckError
|
||||
|
@ -66,7 +65,9 @@ inference/mixin_inference_outwards_4: TypeCheckError
|
|||
inference/mixin_inference_unification_1: TypeCheckError
|
||||
inference/mixin_inference_unification_2: TypeCheckError
|
||||
late_lowering/covariant_late_field: TypeCheckError
|
||||
late_lowering/definitely_unassigned: TypeCheckError
|
||||
nnbd/covariant_late_field: TypeCheckError
|
||||
nnbd/definitely_unassigned: TypeCheckError
|
||||
nnbd/getter_vs_setter_type: TypeCheckError
|
||||
nnbd/issue42603: TypeCheckError
|
||||
no_such_method_forwarders/mixin_nsm: TypeCheckError
|
||||
|
|
|
@ -211,7 +211,7 @@ general/infer_field_from_multiple2: TypeCheckError
|
|||
general/infer_field_from_multiple: TypeCheckError
|
||||
general/invalid_operator: TypeCheckError
|
||||
general/invalid_operator_override: TypeCheckError
|
||||
general/invocations: TypeCheckError
|
||||
general/invocations: RuntimeError
|
||||
general/issue37776: RuntimeError
|
||||
general/issue41210a: TypeCheckError
|
||||
general/issue41210b/issue41210.no_link: TypeCheckError
|
||||
|
@ -252,7 +252,9 @@ inference/mixin_inference_outwards_4: TypeCheckError
|
|||
inference/mixin_inference_unification_1: TypeCheckError
|
||||
inference/mixin_inference_unification_2: TypeCheckError
|
||||
late_lowering/covariant_late_field: TypeCheckError
|
||||
late_lowering/definitely_unassigned: TypeCheckError
|
||||
nnbd/covariant_late_field: TypeCheckError
|
||||
nnbd/definitely_unassigned: TypeCheckError
|
||||
nnbd/getter_vs_setter_type: TypeCheckError
|
||||
nnbd/issue42603: TypeCheckError
|
||||
nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
|
||||
|
|
|
@ -160,16 +160,12 @@ abstract class TypeEnvironment extends Types {
|
|||
/// getUnionFreeType(int?) = int
|
||||
/// getUnionFreeType(FutureOr<int>) = int
|
||||
/// getUnionFreeType(FutureOr<int?>?) = int
|
||||
DartType getUnionFreeType(DartType type,
|
||||
{required bool isNonNullableByDefault}) {
|
||||
DartType getUnionFreeType(DartType type) {
|
||||
if (isNullableTypeConstructorApplication(type)) {
|
||||
return getUnionFreeType(
|
||||
computeTypeWithoutNullabilityMarker(type,
|
||||
isNonNullableByDefault: isNonNullableByDefault),
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
return getUnionFreeType(computeTypeWithoutNullabilityMarker(type,
|
||||
isNonNullableByDefault: true));
|
||||
} else if (type is FutureOrType) {
|
||||
return getUnionFreeType(type.typeArgument,
|
||||
isNonNullableByDefault: isNonNullableByDefault);
|
||||
return getUnionFreeType(type.typeArgument);
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
|
@ -177,46 +173,30 @@ abstract class TypeEnvironment extends Types {
|
|||
|
||||
/// True if [member] is a binary operator whose return type is defined by
|
||||
/// the both operand types.
|
||||
bool isSpecialCasedBinaryOperator(Procedure member,
|
||||
{bool isNonNullableByDefault = false}) {
|
||||
if (isNonNullableByDefault) {
|
||||
Class? class_ = member.enclosingClass;
|
||||
// TODO(johnniwinther): Do we need to recognize backend implementation
|
||||
// methods?
|
||||
if (class_ == coreTypes.intClass ||
|
||||
class_ == coreTypes.numClass ||
|
||||
class_ == coreTypes.doubleClass) {
|
||||
String name = member.name.text;
|
||||
return name == '+' ||
|
||||
name == '-' ||
|
||||
name == '*' ||
|
||||
name == 'remainder' ||
|
||||
name == '%';
|
||||
}
|
||||
} else {
|
||||
Class? class_ = member.enclosingClass;
|
||||
if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) {
|
||||
String name = member.name.text;
|
||||
return name == '+' ||
|
||||
name == '-' ||
|
||||
name == '*' ||
|
||||
name == 'remainder' ||
|
||||
name == '%';
|
||||
}
|
||||
bool isSpecialCasedBinaryOperator(Procedure member) {
|
||||
Class? class_ = member.enclosingClass;
|
||||
// TODO(johnniwinther): Do we need to recognize backend implementation
|
||||
// methods?
|
||||
if (class_ == coreTypes.intClass ||
|
||||
class_ == coreTypes.numClass ||
|
||||
class_ == coreTypes.doubleClass) {
|
||||
String name = member.name.text;
|
||||
return name == '+' ||
|
||||
name == '-' ||
|
||||
name == '*' ||
|
||||
name == 'remainder' ||
|
||||
name == '%';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// True if [member] is a ternary operator whose return type is defined by
|
||||
/// the least upper bound of the operand types.
|
||||
bool isSpecialCasedTernaryOperator(Procedure member,
|
||||
{bool isNonNullableByDefault = false}) {
|
||||
if (isNonNullableByDefault) {
|
||||
Class? class_ = member.enclosingClass;
|
||||
if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) {
|
||||
String name = member.name.text;
|
||||
return name == 'clamp';
|
||||
}
|
||||
bool isSpecialCasedTernaryOperator(Procedure member) {
|
||||
Class? class_ = member.enclosingClass;
|
||||
if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) {
|
||||
String name = member.name.text;
|
||||
return name == 'clamp';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -224,64 +204,44 @@ abstract class TypeEnvironment extends Types {
|
|||
/// Returns the static return type of a special cased binary operator
|
||||
/// (see [isSpecialCasedBinaryOperator]) given the static type of the
|
||||
/// operands.
|
||||
DartType getTypeOfSpecialCasedBinaryOperator(DartType type1, DartType type2,
|
||||
{bool isNonNullableByDefault = false}) {
|
||||
if (isNonNullableByDefault) {
|
||||
// Let e be an expression of one of the forms e1 + e2, e1 - e2, e1 * e2,
|
||||
// e1 % e2 or e1.remainder(e2), where the static type of e1 is a non-Never
|
||||
// type T and T <: num, and where the static type of e2 is S and S is
|
||||
// assignable to num. Then:
|
||||
if (type1 is! NeverType &&
|
||||
isSubtypeOf(type1, coreTypes.numNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
type2 is DynamicType ||
|
||||
isSubtypeOf(type2, coreTypes.numNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
if (isSubtypeOf(type1, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If T <: double then the static type of e is double. This includes S
|
||||
// being dynamic or Never.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else if (type2 is! NeverType &&
|
||||
isSubtypeOf(type2, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If S <: double and not S <:Never, then the static type of e is
|
||||
// double.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else if (isSubtypeOf(type1, coreTypes.intNonNullableRawType,
|
||||
DartType getTypeOfSpecialCasedBinaryOperator(DartType type1, DartType type2) {
|
||||
// Let e be an expression of one of the forms e1 + e2, e1 - e2, e1 * e2,
|
||||
// e1 % e2 or e1.remainder(e2), where the static type of e1 is a non-Never
|
||||
// type T and T <: num, and where the static type of e2 is S and S is
|
||||
// assignable to num. Then:
|
||||
if (type1 is! NeverType &&
|
||||
isSubtypeOf(type1, coreTypes.numNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
type2 is! NeverType &&
|
||||
isSubtypeOf(type2, coreTypes.intNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If T <: int , S <: int and not S <: Never, then the static type of
|
||||
// e is int.
|
||||
return coreTypes.intNonNullableRawType;
|
||||
} else if (type2 is! NeverType &&
|
||||
isSubtypeOf(type2, type1, SubtypeCheckMode.withNullabilities)) {
|
||||
// Otherwise the static type of e is num.
|
||||
return coreTypes.numNonNullableRawType;
|
||||
}
|
||||
type2 is DynamicType ||
|
||||
isSubtypeOf(type2, coreTypes.numNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
if (isSubtypeOf(type1, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If T <: double then the static type of e is double. This includes S
|
||||
// being dynamic or Never.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else if (type2 is! NeverType &&
|
||||
isSubtypeOf(type2, coreTypes.doubleNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If S <: double and not S <:Never, then the static type of e is
|
||||
// double.
|
||||
return coreTypes.doubleNonNullableRawType;
|
||||
} else if (isSubtypeOf(type1, coreTypes.intNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities) &&
|
||||
type2 is! NeverType &&
|
||||
isSubtypeOf(type2, coreTypes.intNonNullableRawType,
|
||||
SubtypeCheckMode.withNullabilities)) {
|
||||
// If T <: int , S <: int and not S <: Never, then the static type of
|
||||
// e is int.
|
||||
return coreTypes.intNonNullableRawType;
|
||||
} else if (type2 is! NeverType &&
|
||||
isSubtypeOf(type2, type1, SubtypeCheckMode.withNullabilities)) {
|
||||
// Otherwise the static type of e is num.
|
||||
return coreTypes.numNonNullableRawType;
|
||||
}
|
||||
// Otherwise the static type of e is num.
|
||||
return coreTypes.numNonNullableRawType;
|
||||
} else {
|
||||
type1 = type1.nonTypeVariableBound;
|
||||
type2 = type2.nonTypeVariableBound;
|
||||
|
||||
if (type1 == type2) return type1;
|
||||
|
||||
if (type1 is InterfaceType && type2 is InterfaceType) {
|
||||
if (type1.classNode == type2.classNode) {
|
||||
return type1;
|
||||
}
|
||||
if (type1.classNode == coreTypes.doubleClass ||
|
||||
type2.classNode == coreTypes.doubleClass) {
|
||||
return coreTypes.doubleRawType(type1.nullability);
|
||||
}
|
||||
}
|
||||
|
||||
return coreTypes.numRawType(type1.nullability);
|
||||
}
|
||||
// Otherwise the static type of e is num.
|
||||
return coreTypes.numNonNullableRawType;
|
||||
}
|
||||
|
||||
DartType getTypeOfSpecialCasedTernaryOperator(
|
||||
|
|
Loading…
Reference in a new issue