[cfe] Introduce a class to hold types for covariance check The CL also unifies the terminology used for the two types across the CFE, to `checkedType` and `operandStaticType`. In case of the latter, it prepares for the future update when the static type of the operand of the check will be more precise than `Object?`. This is a follow-up to https://dart-review.googlesource.com/c/sdk/+/510740/comment/eb702b53_12305509/ and https://dart-review.googlesource.com/c/sdk/+/510740/comment/4ba14f2f_6279bff1/. Change-Id: Ib3d904b72bbe17e35f566ad22a22411b852500dc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/522481 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/front_end/lib/src/kernel/external_ast_helper.dart b/pkg/front_end/lib/src/kernel/external_ast_helper.dart index ef7b825..20877e9 100644 --- a/pkg/front_end/lib/src/kernel/external_ast_helper.dart +++ b/pkg/front_end/lib/src/kernel/external_ast_helper.dart
@@ -330,8 +330,8 @@ Expression receiver, Name name, { required Member interfaceTarget, - required DartType checkType, - required DartType objectNullableType, + required DartType checkedType, + required DartType operandStaticType, required int fileOffset, }) { return new AsExpression( @@ -340,9 +340,9 @@ receiver, name, interfaceTarget: interfaceTarget, - resultType: objectNullableType, + resultType: operandStaticType, )..fileOffset = fileOffset, - checkType, + checkedType, ) ..isTypeError = true ..isCovarianceCheck = true @@ -356,8 +356,8 @@ Arguments arguments, { required Procedure interfaceTarget, required FunctionType functionType, - required DartType checkType, - required DartType objectNullableType, + required DartType checkedType, + required DartType operandStaticType, required int fileOffset, }) { return new AsExpression( @@ -368,9 +368,9 @@ arguments, interfaceTarget: interfaceTarget, functionType: functionType, - resultType: objectNullableType, + resultType: operandStaticType, )..fileOffset = fileOffset, - checkType, + checkedType, ) ..isTypeError = true ..isCovarianceCheck = true @@ -382,8 +382,8 @@ Expression receiver, Name name, { required Procedure interfaceTarget, - required DartType checkType, - required DartType objectNullableType, + required DartType checkedType, + required DartType operandStaticType, required int fileOffset, }) { return new AsExpression( @@ -392,9 +392,9 @@ receiver, name, interfaceTarget: interfaceTarget, - resultType: objectNullableType, + resultType: operandStaticType, )..fileOffset = fileOffset, - checkType, + checkedType, ) ..isTypeError = true ..isCovarianceCheck = true
diff --git a/pkg/front_end/lib/src/type_inference/delayed_expressions.dart b/pkg/front_end/lib/src/type_inference/delayed_expressions.dart index 1a458ca..2b2585e 100644 --- a/pkg/front_end/lib/src/type_inference/delayed_expressions.dart +++ b/pkg/front_end/lib/src/type_inference/delayed_expressions.dart
@@ -1012,46 +1012,7 @@ final DartType _resultType; final bool isObjectAccess; final int fileOffset; - - /// Static type of the covariance check operand for the created expression, - /// if any. - /// - /// If the created expression needs to be checked due to covariantly occurring - /// type parameters, [covarianceCheckedExpressionStaticType] returns the - /// static type of the expression being checked. Note that that type is - /// different from the target type of the check. Consider the following - /// example: - /// - /// e as{CovarianceChecks} T - /// - /// In the example, `e` is the created expression, `T` is the target type of - /// the check, and [covarianceCheckedExpressionStaticType], if not null, is - /// the static type of `e`, such that runtime type of all possible values `e` - /// evaluates to is a subtype of that static type. Not that the type is - /// different from the notion of static type as defined by the Dart language - /// specification. - /// - /// If the covariance check isn't needed for the created expression, - /// [covarianceCheckedExpressionStaticType] returns null. - /// - /// See also the documentation of [typeForCovariantCheck] - final DartType? covarianceCheckedExpressionStaticType; - - /// The target type of the covariance check for the created expression, if - /// any. - /// - /// Some [InstanceGet] expressions might require a type check due to the class - /// type parameters appearing contravariantly in the return type of the - /// getter. In that case [typeForCovariantCheck] represents the target type of - /// the check. Consider the following example: - /// - /// e as {CovarianceCheck} T - /// - /// In the example, `e` is the created expression, and `T` is the target type - /// of the check. - /// - /// See also the documentation of [covarianceCheckedExpressionStaticType]. - final DartType? typeForCovariantCheck; + final CovarianceCheckTypes? covarianceCheckTypes; new( this._receiver, @@ -1059,16 +1020,8 @@ this._resultType, { required this.fileOffset, this.isObjectAccess = false, - this.typeForCovariantCheck, - this.covarianceCheckedExpressionStaticType, - }) : assert( - // [typeForCovariantCheck] and [covarianceCheckedExpressionStaticType] - // should be provided together or absent together. - typeForCovariantCheck == null && - covarianceCheckedExpressionStaticType == null || - typeForCovariantCheck != null && - covarianceCheckedExpressionStaticType != null, - ); + this.covarianceCheckTypes, + }); @override Expression createVariableCacheReadExpression( @@ -1077,12 +1030,11 @@ required int fileOffset, }) { Expression cacheVariableReadExpression; - if (covarianceCheckedExpressionStaticType - case DartType covarianceCheckedExpressionStaticType?) { + if (covarianceCheckTypes case var covarianceCheckTypes?) { cacheVariableReadExpression = createCovarianceCheckedVariableGet( variableCache, - operandStaticType: covarianceCheckedExpressionStaticType, - checkedType: typeForCovariantCheck!, + operandStaticType: covarianceCheckTypes.operandStaticType, + checkedType: covarianceCheckTypes.checkedType, fileOffset: fileOffset, ); } else { @@ -1104,7 +1056,7 @@ Member target = _target; Expression result; if (target is Procedure && !target.isGetter) { - if (typeForCovariantCheck case var typeForCovariantCheck?) { + if (covarianceCheckTypes case var covarianceCheckTypes?) { // Coverage-ignore-block(suite): Not run. result = createCovarianceCheckedInstanceTearOff( isObjectAccess @@ -1117,8 +1069,8 @@ ), _target.name, interfaceTarget: target, - checkType: typeForCovariantCheck, - objectNullableType: typeEnvironment.objectNullableRawType, + checkedType: covarianceCheckTypes.checkedType, + operandStaticType: covarianceCheckTypes.operandStaticType, fileOffset: fileOffset, ); } else { @@ -1138,7 +1090,7 @@ ); } } else { - if (typeForCovariantCheck case var typeForCovariantCheck?) { + if (covarianceCheckTypes case var covarianceCheckTypes?) { result = createCovarianceCheckedInstanceGet( isObjectAccess ? InstanceAccessKind.Object @@ -1150,8 +1102,8 @@ ), _target.name, interfaceTarget: target, - checkType: typeForCovariantCheck, - objectNullableType: typeEnvironment.objectNullableRawType, + checkedType: covarianceCheckTypes.checkedType, + operandStaticType: covarianceCheckTypes.operandStaticType, fileOffset: fileOffset, ); } else { @@ -1694,3 +1646,22 @@ return identical(this, expression) || _expression.uses(expression); } } + +/// Target type of a covariance check and the static type of the operand. +/// +/// If an expression needs to be checked due to covariantly occurring type +/// parameters, [operandStaticType] is the static type of the expression being +/// checked, and [checkedType] is the target type of the check. Consider the +/// following example: +/// +/// e as{CovarianceChecks} T +/// +/// Here, `e` is the checked expression, `T` is the [checkedType], and +/// [operandStaticType] is the static type of `e` such that the runtime types of +/// all possible values `e` evaluates to are subtypes of [operandStaticType]. +/// Note that [operandStaticType] is different from the notion of static type as +/// defined by the Dart language specification. +class CovarianceCheckTypes({ + required final DartType operandStaticType, + required final DartType checkedType, +});
diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart index 4221c2f..b49a9fa 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
@@ -3098,8 +3098,8 @@ const InvalidType(), ), interfaceTarget: method!, - checkType: result.inferredType, - objectNullableType: coreTypes.objectNullableRawType, + checkedType: result.inferredType, + operandStaticType: coreTypes.objectNullableRawType, fileOffset: fileOffset, ); } else { @@ -3155,8 +3155,8 @@ arguments, ), functionType: inferredFunctionType as FunctionType, - checkType: result.inferredType, - objectNullableType: coreTypes.objectNullableRawType, + checkedType: result.inferredType, + operandStaticType: coreTypes.objectNullableRawType, interfaceTarget: method!, fileOffset: fileOffset, ); @@ -3310,8 +3310,8 @@ kind, receiver, originalName, - checkType: calleeType, - objectNullableType: coreTypes.objectNullableRawType, + checkedType: calleeType, + operandStaticType: coreTypes.objectNullableRawType, interfaceTarget: originalTarget, fileOffset: fileOffset, ); @@ -5415,8 +5415,8 @@ receiver, propertyName, interfaceTarget: member, - checkType: readType, - objectNullableType: coreTypes.objectNullableRawType, + checkedType: readType, + operandStaticType: coreTypes.objectNullableRawType, fileOffset: fileOffset, ); } else { @@ -5436,8 +5436,8 @@ receiver, propertyName, interfaceTarget: member, - checkType: readType, - objectNullableType: coreTypes.objectNullableRawType, + checkedType: readType, + operandStaticType: coreTypes.objectNullableRawType, fileOffset: fileOffset, ); } else {
diff --git a/pkg/front_end/lib/src/type_inference/matching_expressions.dart b/pkg/front_end/lib/src/type_inference/matching_expressions.dart index 5d810d1..73e692a 100644 --- a/pkg/front_end/lib/src/type_inference/matching_expressions.dart +++ b/pkg/front_end/lib/src/type_inference/matching_expressions.dart
@@ -529,9 +529,11 @@ field.resultType!, isObjectAccess: false, fileOffset: field.fileOffset, - typeForCovariantCheck: field.checkReturn ? field.resultType! : null, - covarianceCheckedExpressionStaticType: field.checkReturn - ? coreTypes.objectNullableRawType + covarianceCheckTypes: field.checkReturn + ? new CovarianceCheckTypes( + operandStaticType: coreTypes.objectNullableRawType, + checkedType: field.resultType!, + ) : null, ); break;
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt index b00f9fb..334f65a 100644 --- a/pkg/front_end/test/spell_checking_list_common.txt +++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -2859,7 +2859,6 @@ served set sets -settable setter setter's setters