[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:
committed by
Commit Queue
parent
a446cd9667
commit
ce12e3c8ac
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user