[cfe] Remove isNonNullableByDefault from class hierarchy

Change-Id: Ib5942357578a6481e8038dd090e4a9d9ff49f831
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/369022
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
This commit is contained in:
Johnni Winther
2024-06-03 06:42:54 +00:00
committed by Commit Queue
parent a446cd9667
commit ce12e3c8ac
18 changed files with 82 additions and 266 deletions
+1 -2
View File
@@ -318,8 +318,7 @@ class ImpactBuilder extends ir.RecursiveVisitor implements ImpactRegistry {
if (member != null) {
iteratorType = ir.Substitution.fromTypeDeclarationType(
typeEnvironment.getTypeAsInstanceOf(iterableInterfaceType,
member.enclosingClass!, typeEnvironment.coreTypes,
isNonNullableByDefault: true)!)
member.enclosingClass!, typeEnvironment.coreTypes)!)
.substituteType(member.getterType);
}
}
@@ -671,8 +671,7 @@ abstract class CombinedMemberSignatureBase {
return type;
}
TypeDeclarationType instance = hierarchy.getTypeAsInstanceOf(
thisType, member.enclosingTypeDeclaration!,
isNonNullableByDefault: true)!;
thisType, member.enclosingTypeDeclaration!)!;
return Substitution.fromTypeDeclarationType(instance).substituteType(type);
}
@@ -142,8 +142,7 @@ class CfeTypeOperations implements TypeOperations<DartType> {
if (declaringClass.typeParameters.isNotEmpty) {
Substitution substitution = substitutions[declaringClass] ??=
Substitution.fromInterfaceType(_classHierarchy
.getInterfaceTypeAsInstanceOfClass(type, declaringClass,
isNonNullableByDefault: true)!);
.getInterfaceTypeAsInstanceOfClass(type, declaringClass)!);
fieldType = substitution.substituteType(fieldType);
}
fieldTypes[new NameKey(member.name.text)] = fieldType;
@@ -161,8 +160,7 @@ class CfeTypeOperations implements TypeOperations<DartType> {
if (implementedType.typeDeclaration.typeParameters.isNotEmpty) {
Substitution substitution = Substitution.fromTypeDeclarationType(
_classHierarchy.getTypeAsInstanceOf(
type, implementedType.typeDeclaration,
isNonNullableByDefault: true)!);
type, implementedType.typeDeclaration)!);
for (MapEntry<Key, DartType> entry in implementedFieldTypes.entries) {
fieldTypes[entry.key] = substitution.substituteType(entry.value);
}
@@ -270,8 +268,7 @@ class CfeTypeOperations implements TypeOperations<DartType> {
type = type.nonTypeVariableBound;
if (type is TypeDeclarationType) {
return _classHierarchy.getTypeAsInstanceOf(
type, _typeEnvironment.coreTypes.listClass,
isNonNullableByDefault: true);
type, _typeEnvironment.coreTypes.listClass);
}
return null;
}
@@ -467,8 +464,8 @@ class CfeSealedClassOperations
InterfaceType thisType = subClass.getThisType(
_typeEnvironment.coreTypes, Nullability.nonNullable);
InterfaceType asSealedType = _typeEnvironment.hierarchy
.getInterfaceTypeAsInstanceOfClass(thisType, sealedClassType.classNode,
isNonNullableByDefault: true)!;
.getInterfaceTypeAsInstanceOfClass(
thisType, sealedClassType.classNode)!;
if (thisType.typeArguments.isEmpty) {
return thisType;
}
@@ -113,8 +113,7 @@ class ClassHierarchyBuilder
@override
InterfaceType? getInterfaceTypeAsInstanceOfClass(
InterfaceType type, Class superclass,
{required bool isNonNullableByDefault}) {
InterfaceType type, Class superclass) {
if (type.classNode == superclass) return type;
return asSupertypeOf(type, superclass)
?.asInterfaceType
@@ -137,8 +136,7 @@ class ClassHierarchyBuilder
TypeDeclarationType type1,
TypeDeclarationType type2,
List<ClassHierarchyNode> supertypeNodes1,
List<ClassHierarchyNode> supertypeNodes2,
{required bool isNonNullableByDefault}) {
List<ClassHierarchyNode> supertypeNodes2) {
Set<ClassHierarchyNode> supertypeNodesSet1 = supertypeNodes1.toSet();
List<ClassHierarchyNode> common = <ClassHierarchyNode>[];
@@ -149,10 +147,10 @@ class ClassHierarchyBuilder
continue;
}
if (supertypeNodesSet1.contains(node)) {
DartType candidate1 = getTypeAsInstanceOf(type1, node.classBuilder.cls,
isNonNullableByDefault: isNonNullableByDefault)!;
DartType candidate2 = getTypeAsInstanceOf(type2, node.classBuilder.cls,
isNonNullableByDefault: isNonNullableByDefault)!;
DartType candidate1 =
getTypeAsInstanceOf(type1, node.classBuilder.cls)!;
DartType candidate2 =
getTypeAsInstanceOf(type2, node.classBuilder.cls)!;
if (candidate1 == candidate2) {
common.add(node);
}
@@ -174,8 +172,7 @@ class ClassHierarchyBuilder
for (int i = 0; i < common.length - 1; i++) {
ClassHierarchyNode node = common[i];
if (node.maxInheritancePath != common[i + 1].maxInheritancePath) {
return getTypeAsInstanceOf(type1, node.classBuilder.cls,
isNonNullableByDefault: isNonNullableByDefault)!
return getTypeAsInstanceOf(type1, node.classBuilder.cls)!
.withDeclaredNullability(
uniteNullabilities(type1.nullability, type2.nullability))
as InterfaceType;
@@ -196,26 +193,11 @@ class ClassHierarchyBuilder
@override
InterfaceType getLegacyLeastUpperBound(
InterfaceType type1, InterfaceType type2,
{required bool isNonNullableByDefault}) {
InterfaceType type1, InterfaceType type2) {
if (type1 == type2) return type1;
// LLUB(Null, List<dynamic>*) works differently for opt-in and opt-out
// libraries. In opt-out libraries the legacy behavior is preserved, so
// LLUB(Null, List<dynamic>*) = List<dynamic>*. In opt-out libraries the
// rules imply that LLUB(Null, List<dynamic>*) = List<dynamic>?.
if (!isNonNullableByDefault) {
if (type1 is NullType) {
return type2;
}
if (type2 is NullType) {
return type1;
}
}
return getLegacyLeastUpperBoundFromSupertypeLists(
type1, type2, <InterfaceType>[type1], <InterfaceType>[type2],
isNonNullableByDefault: isNonNullableByDefault);
type1, type2, <InterfaceType>[type1], <InterfaceType>[type2]);
}
@override
@@ -223,8 +205,7 @@ class ClassHierarchyBuilder
TypeDeclarationType type1,
TypeDeclarationType type2,
List<InterfaceType> supertypes1,
List<InterfaceType> supertypes2,
{required bool isNonNullableByDefault}) {
List<InterfaceType> supertypes2) {
List<ClassHierarchyNode> supertypeNodes1 = <ClassHierarchyNode>[
for (InterfaceType supertype in supertypes1)
...getNodeFromClass(supertype.classNode).computeAllSuperNodes(this)
@@ -235,8 +216,7 @@ class ClassHierarchyBuilder
];
return _getLegacyLeastUpperBoundInternal(
type1, type2, supertypeNodes1, supertypeNodes2,
isNonNullableByDefault: isNonNullableByDefault);
type1, type2, supertypeNodes1, supertypeNodes2);
}
static ClassHierarchyBuilder build(
@@ -345,13 +345,11 @@ class _StaticTypeImpl extends macro.StaticTypeImpl {
identifier.typeDeclarationBuilder;
switch (declarationBuilder) {
case ClassBuilder():
result = types._sourceLoader.hierarchyBuilder.getTypeAsInstanceOf(
type, declarationBuilder.cls,
isNonNullableByDefault: true);
result = types._sourceLoader.hierarchyBuilder
.getTypeAsInstanceOf(type, declarationBuilder.cls);
case ExtensionTypeDeclarationBuilder():
result = types._sourceLoader.hierarchyBuilder.getTypeAsInstanceOf(
type, declarationBuilder.extensionTypeDeclaration,
isNonNullableByDefault: true);
type, declarationBuilder.extensionTypeDeclaration);
case BuiltinTypeDeclarationBuilder():
case InvalidTypeDeclarationBuilder():
case OmittedTypeDeclarationBuilder():
@@ -943,8 +943,7 @@ class SourceClassBuilder extends ClassBuilderImpl
substitution.substituteSupertype(constraint).asInterfaceType;
InterfaceType? implementedInterface =
hierarchy.getInterfaceTypeAsInstanceOfClass(
supertype, requiredInterface.classNode,
isNonNullableByDefault: true);
supertype, requiredInterface.classNode);
if (implementedInterface == null ||
!typeEnvironment.areMutualSubtypes(implementedInterface,
requiredInterface, SubtypeCheckMode.withNullabilities)) {
@@ -821,8 +821,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
case ExtensionType():
return typeSchemaEnvironment.hierarchy
.getExtensionTypeAsInstanceOfClass(
type, coreTypes.futureClass,
isNonNullableByDefault: true) ==
type, coreTypes.futureClass) ==
null;
case TypeParameterType():
return _isIncompatibleWithAwait(type.parameter.bound);
@@ -4595,8 +4594,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
null;
}
typeContextAsIterable = hierarchyBuilder.getTypeAsInstanceOf(
unfuturedTypeContext, coreTypes.iterableClass,
isNonNullableByDefault: true);
unfuturedTypeContext, coreTypes.iterableClass);
if (node.entries.isEmpty &&
typeContextAsIterable != null &&
!typeContextIsMap) {
@@ -788,8 +788,7 @@ class OperationsCfe
return null;
} else {
TypeDeclarationType? mapType = typeEnvironment.getTypeAsInstanceOf(
type, typeEnvironment.coreTypes.mapClass, typeEnvironment.coreTypes,
isNonNullableByDefault: true);
type, typeEnvironment.coreTypes.mapClass, typeEnvironment.coreTypes);
if (mapType == null) {
return null;
} else {
@@ -830,8 +829,7 @@ class OperationsCfe
TypeDeclarationType? interfaceType = typeEnvironment.getTypeAsInstanceOf(
type,
typeEnvironment.coreTypes.iterableClass,
typeEnvironment.coreTypes,
isNonNullableByDefault: true);
typeEnvironment.coreTypes);
if (interfaceType == null) {
return null;
} else {
@@ -1,74 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// 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 "package:kernel/ast.dart" show DartType, InterfaceType;
import "package:kernel/target/targets.dart" show NoneTarget, TargetFlags;
import "package:front_end/src/api_prototype/compiler_options.dart"
show CompilerOptions;
import "package:front_end/src/base/processed_options.dart"
show ProcessedOptions;
import "package:front_end/src/fasta/builder/declaration_builders.dart";
import "package:front_end/src/fasta/compiler_context.dart" show CompilerContext;
import "package:front_end/src/fasta/dill/dill_loader.dart" show DillLoader;
import "package:front_end/src/fasta/dill/dill_target.dart" show DillTarget;
import "package:front_end/src/fasta/kernel/hierarchy/hierarchy_builder.dart"
show ClassHierarchyBuilder;
import "package:front_end/src/fasta/ticker.dart" show Ticker;
import "legacy_upper_bound_helper.dart" show LegacyUpperBoundTest;
class FastaLegacyUpperBoundTest extends LegacyUpperBoundTest {
final Ticker ticker;
final CompilerContext context;
late ClassHierarchyBuilder hierarchy;
FastaLegacyUpperBoundTest(this.ticker, this.context);
@override
bool get isNonNullableByDefault => false;
@override
Future<void> parseComponent(String source) async {
await super.parseComponent(source);
DillTarget target = new DillTarget(
ticker,
await context.options.getUriTranslator(),
new NoneTarget(new TargetFlags()));
final DillLoader loader = target.loader;
loader.appendLibraries(env.component);
target.buildOutlines();
ClassBuilder objectClass = loader.coreLibrary
.lookupLocalMember("Object", required: true) as ClassBuilder;
hierarchy = new ClassHierarchyBuilder(objectClass, loader, env.coreTypes);
}
@override
DartType getLegacyLeastUpperBound(DartType a, DartType b,
{required bool isNonNullableByDefault}) {
return hierarchy.getLegacyLeastUpperBound(
a as InterfaceType, b as InterfaceType,
isNonNullableByDefault: isNonNullableByDefault);
}
}
void main() {
final Ticker ticker = new Ticker();
final CompilerContext context = new CompilerContext(new ProcessedOptions(
options: new CompilerOptions()
..packagesFileUri =
Uri.base.resolve(".dart_tool/package_config.json")));
context.runInContext<void>(
(_) => new FastaLegacyUpperBoundTest(ticker, context).test());
}
@@ -11,9 +11,6 @@ import "package:kernel/class_hierarchy.dart" show ClassHierarchy;
class KernelLegacyUpperBoundTest extends LegacyUpperBoundTest {
late ClassHierarchy hierarchy;
@override
bool get isNonNullableByDefault => true;
@override
Future<void> parseComponent(String source) async {
await super.parseComponent(source);
@@ -21,11 +18,9 @@ class KernelLegacyUpperBoundTest extends LegacyUpperBoundTest {
}
@override
DartType getLegacyLeastUpperBound(DartType a, DartType b,
{required bool isNonNullableByDefault}) {
DartType getLegacyLeastUpperBound(DartType a, DartType b) {
return hierarchy.getLegacyLeastUpperBound(
a as InterfaceType, b as InterfaceType,
isNonNullableByDefault: isNonNullableByDefault);
a as InterfaceType, b as InterfaceType);
}
}
@@ -17,11 +17,8 @@ abstract class LegacyUpperBoundTest {
late Library coreLibrary;
late Library testLibrary;
bool get isNonNullableByDefault;
Future<void> parseComponent(String source) {
env =
new parser.Env(source, isNonNullableByDefault: isNonNullableByDefault);
env = new parser.Env(source, isNonNullableByDefault: true);
assert(
env.component.libraries.length == 2,
"The test component is expected to have exactly two libraries: "
@@ -43,20 +40,16 @@ abstract class LegacyUpperBoundTest {
return new Future<void>.value();
}
DartType getLegacyLeastUpperBound(DartType a, DartType b,
{required bool isNonNullableByDefault});
DartType getLegacyLeastUpperBound(DartType a, DartType b);
void checkLegacyUpTypes(DartType a, DartType b, DartType expected,
{required bool isNonNullableByDefault}) {
DartType actual = getLegacyLeastUpperBound(a, b,
isNonNullableByDefault: isNonNullableByDefault);
void checkLegacyUpTypes(DartType a, DartType b, DartType expected) {
DartType actual = getLegacyLeastUpperBound(a, b);
Expect.equals(expected, actual);
}
void checkLegacyUp(String type1, String type2, String expectedType) {
checkLegacyUpTypes(
env.parseType(type1), env.parseType(type2), env.parseType(expectedType),
isNonNullableByDefault: true);
checkLegacyUpTypes(env.parseType(type1), env.parseType(type2),
env.parseType(expectedType));
}
Future<void> test() {
@@ -113,8 +113,7 @@ class InheritanceDataExtractor extends CfeDataExtractor<String> {
}
InterfaceType supertype = _hierarchy.getInterfaceTypeAsInstanceOfClass(
_coreTypes.thisInterfaceType(node, node.enclosingLibrary.nonNullable),
member.enclosingClass!,
isNonNullableByDefault: true)!;
member.enclosingClass!)!;
Substitution substitution = Substitution.fromInterfaceType(supertype);
DartType? type;
if (member is Procedure) {
+32 -81
View File
@@ -12,7 +12,6 @@ import 'ast.dart';
import 'core_types.dart';
import 'type_algebra.dart';
import 'src/heap.dart';
import 'src/legacy_erasure.dart';
import 'src/nnbd_top_merge.dart';
import 'src/norm.dart';
@@ -34,8 +33,7 @@ abstract class ClassHierarchyBase {
/// Returns the instantiation of [typeDeclaration] that is implemented by
/// [type], or `null` if [type] does not implement [typeDeclaration] at all.
TypeDeclarationType? getTypeAsInstanceOf(
TypeDeclarationType type, TypeDeclaration typeDeclaration,
{required bool isNonNullableByDefault});
TypeDeclarationType type, TypeDeclaration typeDeclaration);
/// Returns the type arguments of the instantiation of [typeDeclaration] that
/// is implemented by [type], or `null` if [type] does not implement
@@ -46,8 +44,7 @@ abstract class ClassHierarchyBase {
/// Returns the instantiation of [superclass] that is implemented by [type],
/// or `null` if [type] does not implement [superclass] at all.
InterfaceType? getInterfaceTypeAsInstanceOfClass(
InterfaceType type, Class superclass,
{required bool isNonNullableByDefault});
InterfaceType type, Class superclass);
/// Returns the type arguments of the instantiation of [superclass] that is
/// implemented by [type], or `null` if [type] does not implement [superclass]
@@ -58,14 +55,12 @@ abstract class ClassHierarchyBase {
/// Returns the instantiation of [superDeclaration] that is implemented by
/// [type], or `null` if [type] does not implement [superDeclaration] at all.
ExtensionType? getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
ExtensionType type, ExtensionTypeDeclaration superDeclaration,
{required bool isNonNullableByDefault});
ExtensionType type, ExtensionTypeDeclaration superDeclaration);
/// Returns the instantiation of [superclass] that is implemented by [type],
/// or `null` if [type] does not implement [superclass] at all.
InterfaceType? getExtensionTypeAsInstanceOfClass(
ExtensionType type, Class superclass,
{required bool isNonNullableByDefault});
ExtensionType type, Class superclass);
/// Returns the type arguments of the instantiation of [superDeclaration] that
/// is implemented by [type], or `null` if [type] does not implement
@@ -99,8 +94,7 @@ abstract class ClassHierarchyBase {
/// one type is a subtype of the other, or where both types are based on the
/// same class.
InterfaceType getLegacyLeastUpperBound(
InterfaceType type1, InterfaceType type2,
{required bool isNonNullableByDefault});
InterfaceType type1, InterfaceType type2);
/// Computes an upper bound of two types found in their given supertype lists
///
@@ -117,33 +111,28 @@ abstract class ClassHierarchyBase {
TypeDeclarationType type1,
TypeDeclarationType type2,
List<InterfaceType> supertypes1,
List<InterfaceType> supertypes2,
{required bool isNonNullableByDefault});
List<InterfaceType> supertypes2);
}
mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
@override
TypeDeclarationType? getTypeAsInstanceOf(
TypeDeclarationType type, TypeDeclaration typeDeclaration,
{required bool isNonNullableByDefault}) {
TypeDeclarationType type, TypeDeclaration typeDeclaration) {
switch (type) {
case InterfaceType():
switch (typeDeclaration) {
case Class():
return getInterfaceTypeAsInstanceOfClass(type, typeDeclaration,
isNonNullableByDefault: isNonNullableByDefault);
return getInterfaceTypeAsInstanceOfClass(type, typeDeclaration);
case ExtensionTypeDeclaration():
return null;
}
case ExtensionType():
switch (typeDeclaration) {
case Class():
return getExtensionTypeAsInstanceOfClass(type, typeDeclaration,
isNonNullableByDefault: isNonNullableByDefault);
return getExtensionTypeAsInstanceOfClass(type, typeDeclaration);
case ExtensionTypeDeclaration():
return getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
type, typeDeclaration,
isNonNullableByDefault: isNonNullableByDefault);
type, typeDeclaration);
}
}
}
@@ -176,22 +165,17 @@ mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
ExtensionType?
getExtensionTypeDeclarationAsInstanceOfExtensionTypeDeclaration(
ExtensionTypeDeclaration subDeclaration,
ExtensionTypeDeclaration superDeclaration,
{required bool isNonNullableByDefault}) {
ExtensionTypeDeclaration superDeclaration) {
// TODO(johnniwinther): Improve lookup performance.
if (identical(subDeclaration, superDeclaration)) {
return coreTypes.thisExtensionType(
subDeclaration,
isNonNullableByDefault
? Nullability.nonNullable
: Nullability.legacy);
subDeclaration, Nullability.nonNullable);
}
for (DartType implement in subDeclaration.implements) {
if (implement is ExtensionType) {
ExtensionType? supertype =
getExtensionTypeDeclarationAsInstanceOfExtensionTypeDeclaration(
implement.extensionTypeDeclaration, superDeclaration,
isNonNullableByDefault: isNonNullableByDefault);
implement.extensionTypeDeclaration, superDeclaration);
if (supertype != null) {
if (implement.typeArguments.isNotEmpty) {
supertype = Substitution.fromExtensionType(implement)
@@ -212,14 +196,12 @@ mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
}
InterfaceType? getExtensionTypeDeclarationAsInstanceOfClass(
ExtensionTypeDeclaration subDeclaration, Class superclass,
{required bool isNonNullableByDefault}) {
ExtensionTypeDeclaration subDeclaration, Class superclass) {
// TODO(johnniwinther): Improve lookup performance.
for (DartType implement in subDeclaration.implements) {
if (implement is ExtensionType) {
InterfaceType? supertype = getExtensionTypeDeclarationAsInstanceOfClass(
implement.extensionTypeDeclaration, superclass,
isNonNullableByDefault: isNonNullableByDefault);
implement.extensionTypeDeclaration, superclass);
if (supertype != null) {
if (implement.typeArguments.isNotEmpty) {
supertype = Substitution.fromExtensionType(implement)
@@ -250,12 +232,10 @@ mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
@override
ExtensionType? getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
ExtensionType type, ExtensionTypeDeclaration superclass,
{required bool isNonNullableByDefault}) {
ExtensionType type, ExtensionTypeDeclaration superclass) {
ExtensionType? supertype =
getExtensionTypeDeclarationAsInstanceOfExtensionTypeDeclaration(
type.extensionTypeDeclaration, superclass,
isNonNullableByDefault: isNonNullableByDefault);
type.extensionTypeDeclaration, superclass);
if (supertype != null) {
if (type.typeArguments.isNotEmpty) {
supertype = Substitution.fromExtensionType(type)
@@ -268,11 +248,9 @@ mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
@override
InterfaceType? getExtensionTypeAsInstanceOfClass(
ExtensionType type, Class superclass,
{required bool isNonNullableByDefault}) {
ExtensionType type, Class superclass) {
InterfaceType? supertype = getExtensionTypeDeclarationAsInstanceOfClass(
type.extensionTypeDeclaration, superclass,
isNonNullableByDefault: isNonNullableByDefault);
type.extensionTypeDeclaration, superclass);
if (supertype != null) {
if (type.typeArguments.isNotEmpty) {
supertype = Substitution.fromExtensionType(type)
@@ -287,17 +265,14 @@ mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
List<DartType>? getExtensionTypeArgumentsAsInstanceOfExtensionTypeDeclaration(
ExtensionType type, ExtensionTypeDeclaration superDeclaration) {
return getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
type, superDeclaration,
isNonNullableByDefault: true)
type, superDeclaration)
?.typeArguments;
}
@override
List<DartType>? getExtensionTypeArgumentsAsInstanceOfClass(
ExtensionType type, Class superclass) {
return getExtensionTypeAsInstanceOfClass(type, superclass,
isNonNullableByDefault: true)
?.typeArguments;
return getExtensionTypeAsInstanceOfClass(type, superclass)?.typeArguments;
}
}
@@ -849,8 +824,7 @@ class ClosedWorldClassHierarchy
@override
InterfaceType getLegacyLeastUpperBound(
InterfaceType type1, InterfaceType type2,
{required bool isNonNullableByDefault}) {
InterfaceType type1, InterfaceType type2) {
// The algorithm is: first we compute a list of superclasses for both types,
// ordered from greatest to least depth, and ordered by topological sort
// index within each depth. Due to the sort order, we can find the
@@ -871,15 +845,6 @@ class ClosedWorldClassHierarchy
// Compute the list of superclasses for both types, with the above
// optimization.
// LLUB(Null, List<dynamic>*) works differently for opt-in and opt-out
// libraries. In opt-out libraries the legacy behavior is preserved, so
// LLUB(Null, List<dynamic>*) = List<dynamic>*. In opt-in libraries the
// rules imply that LLUB(Null, List<dynamic>*) = List<dynamic>?.
if (!isNonNullableByDefault) {
if (type1 is NullType) return type2;
if (type2 is NullType) return type1;
}
_ClassInfo info1 = infoFor(type1.classNode);
_ClassInfo info2 = infoFor(type2.classNode);
List<_ClassInfo> classes1;
@@ -894,8 +859,7 @@ class ClosedWorldClassHierarchy
}
return _getLegacyLeastUpperBoundInternal(
type1, type2, info1, info2, classes1, classes2,
isNonNullableByDefault: isNonNullableByDefault);
type1, type2, info1, info2, classes1, classes2);
}
InterfaceType _getLegacyLeastUpperBoundInternal(
@@ -904,8 +868,7 @@ class ClosedWorldClassHierarchy
_ClassInfo? info1,
_ClassInfo? info2,
List<_ClassInfo> classInfos1,
List<_ClassInfo> classInfos2,
{required bool isNonNullableByDefault}) {
List<_ClassInfo> classInfos2) {
assert(type1 is! InterfaceType || info1 != null);
assert(type2 is! InterfaceType || info2 != null);
@@ -970,8 +933,8 @@ class ClosedWorldClassHierarchy
as InterfaceType;
} else {
type1 as ExtensionType;
superType1 = getExtensionTypeAsInstanceOfClass(type1, next.classNode,
isNonNullableByDefault: isNonNullableByDefault)!;
superType1 =
getExtensionTypeAsInstanceOfClass(type1, next.classNode)!;
}
InterfaceType superType2;
@@ -983,14 +946,10 @@ class ClosedWorldClassHierarchy
as InterfaceType;
} else {
type2 as ExtensionType;
superType2 = getExtensionTypeAsInstanceOfClass(type2, next.classNode,
isNonNullableByDefault: isNonNullableByDefault)!;
superType2 =
getExtensionTypeAsInstanceOfClass(type2, next.classNode)!;
}
if (!isNonNullableByDefault) {
superType1 = legacyErasure(superType1) as InterfaceType;
superType2 = legacyErasure(superType2) as InterfaceType;
}
if (superType1 == superType2) {
candidate = superType1.withDeclaredNullability(
uniteNullabilities(type1.nullability, type2.nullability));
@@ -1005,8 +964,7 @@ class ClosedWorldClassHierarchy
TypeDeclarationType type1,
TypeDeclarationType type2,
List<InterfaceType> supertypes1,
List<InterfaceType> supertypes2,
{required bool isNonNullableByDefault}) {
List<InterfaceType> supertypes2) {
assert(supertypes1.isNotEmpty || type1 is ExtensionType);
assert(supertypes2.isNotEmpty || type2 is ExtensionType);
@@ -1035,8 +993,7 @@ class ClosedWorldClassHierarchy
type1 is InterfaceType ? infoFor(type1.classNode) : null,
type2 is InterfaceType ? infoFor(type2.classNode) : null,
combinedInfos1,
combinedInfos2,
isNonNullableByDefault: isNonNullableByDefault);
combinedInfos2);
}
@override
@@ -1053,17 +1010,11 @@ class ClosedWorldClassHierarchy
@override
InterfaceType? getInterfaceTypeAsInstanceOfClass(
InterfaceType type, Class superclass,
{required bool isNonNullableByDefault}) {
InterfaceType type, Class superclass) {
List<DartType>? typeArguments =
getInterfaceTypeArgumentsAsInstanceOfClass(type, superclass);
if (typeArguments == null) return null;
// The return value should be a legacy type if it's computed for an
// opted-out library, unless the return value is Null? which is always
// nullable.
Nullability nullability =
isNonNullableByDefault ? type.nullability : Nullability.legacy;
return new InterfaceType(superclass, nullability, typeArguments);
return new InterfaceType(superclass, type.nullability, typeArguments);
}
@override
@@ -21,10 +21,8 @@ class HierarchyBasedTypeEnvironment extends TypeEnvironment {
@override
TypeDeclarationType? getTypeAsInstanceOf(TypeDeclarationType type,
TypeDeclaration typeDeclaration, CoreTypes coreTypes,
{required bool isNonNullableByDefault}) {
return hierarchy.getTypeAsInstanceOf(type, typeDeclaration,
isNonNullableByDefault: isNonNullableByDefault);
TypeDeclaration typeDeclaration, CoreTypes coreTypes) {
return hierarchy.getTypeAsInstanceOf(type, typeDeclaration);
}
@override
+5 -10
View File
@@ -894,8 +894,7 @@ mixin StandardBounds {
DartType _getLegacyLeastUpperBound(
TypeDeclarationType type1, TypeDeclarationType type2) {
if (type1 is InterfaceType && type2 is InterfaceType) {
return hierarchy.getLegacyLeastUpperBound(type1, type2,
isNonNullableByDefault: true);
return hierarchy.getLegacyLeastUpperBound(type1, type2);
} else if (type1 is ExtensionType || type2 is ExtensionType) {
// This mimics the legacy least upper bound implementation for regular
// classes, where the least upper bound is found as the single common
@@ -939,8 +938,7 @@ mixin StandardBounds {
if (implemented is ExtensionType) {
ExtensionType supertype =
hierarchy.getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
type, implemented.extensionTypeDeclaration,
isNonNullableByDefault: true)!;
type, implemented.extensionTypeDeclaration)!;
computeSuperTypes(supertype, supertypes, superInterfaceTypes);
}
}
@@ -984,8 +982,7 @@ mixin StandardBounds {
}
return hierarchy.getLegacyLeastUpperBoundFromSupertypeLists(
type1, type2, superInterfaceTypes1, superInterfaceTypes2,
isNonNullableByDefault: true);
type1, type2, superInterfaceTypes1, superInterfaceTypes2);
}
if (type1 is ExtensionType && type1.isPotentiallyNullable ||
type2 is ExtensionType && type2.isPotentiallyNullable) {
@@ -1827,8 +1824,7 @@ mixin StandardBounds {
if (!areMutualSubtypes(
tArgs1[i], tArgs2[i], SubtypeCheckMode.withNullabilities)) {
// No bound will be valid, find bound at the interface level.
return hierarchy.getLegacyLeastUpperBound(type1, type2,
isNonNullableByDefault: true);
return hierarchy.getLegacyLeastUpperBound(type1, type2);
}
// TODO (kallentu) : Fix asymmetric bounds behavior for invariant type
// parameters.
@@ -1843,8 +1839,7 @@ mixin StandardBounds {
type1.declaredNullability, type2.declaredNullability),
tArgs);
}
return hierarchy.getLegacyLeastUpperBound(type1, type2,
isNonNullableByDefault: true);
return hierarchy.getLegacyLeastUpperBound(type1, type2);
}
DartType _getNullabilityObliviousTypeParameterStandardUpperBound(
+2 -4
View File
@@ -419,10 +419,8 @@ class Types with StandardBounds {
static List<Object>? typeChecksForTesting;
TypeDeclarationType? getTypeAsInstanceOf(TypeDeclarationType type,
TypeDeclaration typeDeclaration, CoreTypes coreTypes,
{required bool isNonNullableByDefault}) {
return hierarchy.getTypeAsInstanceOf(type, typeDeclaration,
isNonNullableByDefault: isNonNullableByDefault);
TypeDeclaration typeDeclaration, CoreTypes coreTypes) {
return hierarchy.getTypeAsInstanceOf(type, typeDeclaration);
}
List<DartType>? getTypeArgumentsAsInstanceOf(
+4 -7
View File
@@ -85,9 +85,8 @@ abstract class TypeEnvironment extends Types {
// future type.
DartType resolved = t.nonTypeVariableBound;
if (resolved is TypeDeclarationType) {
DartType? futureType = getTypeAsInstanceOf(
resolved, coreTypes.futureClass, coreTypes,
isNonNullableByDefault: true);
DartType? futureType =
getTypeAsInstanceOf(resolved, coreTypes.futureClass, coreTypes);
if (futureType != null) {
// TODO(johnniwinther): The two implementations are inconsistent wrt.
// how [isNonNullableByDefault] is treated.
@@ -421,8 +420,7 @@ abstract class TypeEnvironment extends Types {
// is the static type of `e`.
InterfaceType? testedAgainstTypeAsOperandClass = hierarchy
.getInterfaceTypeAsInstanceOfClass(
checkTargetType, expressionStaticType.classNode,
isNonNullableByDefault: true)
checkTargetType, expressionStaticType.classNode)
?.withDeclaredNullability(checkTargetType.declaredNullability);
// If `A<T1, ..., Tn>` isn't an instance of `B`, the full type check
@@ -446,8 +444,7 @@ abstract class TypeEnvironment extends Types {
TypeParameterType.computeNullabilityFromBound(
typeParameter))
]),
expressionStaticType.classNode,
isNonNullableByDefault: true)!;
expressionStaticType.classNode)!;
// Now we search for the occurrences of `X1`, ..., `Xn` in `B<R1,
// ..., Rk>`. Those that are found indicate the positions in `A<T1,
// ..., Tn>` that are fixed and supposed to be the same for every
+2 -6
View File
@@ -1345,13 +1345,9 @@ class B<T*> extends self::A<self::B::T*, core::bool*> {}
''');
var b_int = new InterfaceType(b, Nullability.legacy, [int]);
expect(
hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, a,
isNonNullableByDefault: true),
expect(hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, a),
new InterfaceType(a, Nullability.legacy, [int, bool]));
expect(
hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, objectClass,
isNonNullableByDefault: true),
expect(hierarchy.getInterfaceTypeAsInstanceOfClass(b_int, objectClass),
new InterfaceType(objectClass, Nullability.legacy));
}