mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
[cfe] Support nnbd platform without experiment enabled
All handling of the opt-out features were guarded by the experimental flag. With this CL the opt-out semantics is used irregardless of the the experimental flag. This supports compiling with opt-out semantics against libraries which have been compiled with the flag enabled, as will be the case when the nnbd sdk is unforked. Closes #40334 Change-Id: I2df5c700f97844bdd3e33bccba7e72013f0c831e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133780 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
parent
e1e0ae5898
commit
7248e98023
6 changed files with 119 additions and 100 deletions
|
@ -6,8 +6,35 @@
|
|||
|
||||
// @dart=2.6
|
||||
|
||||
/*class: Class:Class,Object*/
|
||||
class Class {
|
||||
/*member: Class.==:bool! Function(dynamic)**/
|
||||
/*class: Class1:Class1,Object*/
|
||||
class Class1 {
|
||||
/*member: Class1.==:bool! Function(dynamic)**/
|
||||
operator ==(other) => true;
|
||||
}
|
||||
|
||||
/*class: Class2a:Class2a,Object*/
|
||||
abstract class Class2a {
|
||||
/*member: Class2a.==:bool* Function(Object*)**/
|
||||
bool operator ==(Object other);
|
||||
}
|
||||
|
||||
/*class: Class2b:Class2a,Class2b,Object*/
|
||||
class Class2b extends Class2a {
|
||||
/*member: Class2b.==:bool* Function(Object*)**/
|
||||
}
|
||||
|
||||
/*class: Class3a:Class3a,Object*/
|
||||
class Class3a {
|
||||
/*member: Class3a.==:bool* Function(Object*)**/
|
||||
}
|
||||
|
||||
/*class: Class3b:Class3a,Class3b,Object*/
|
||||
abstract class Class3b extends Class3a {
|
||||
/*member: Class3b.==:bool* Function(Object*)**/
|
||||
bool operator ==(Object other);
|
||||
}
|
||||
|
||||
/*class: Class3c:Class3a,Class3b,Class3c,Object*/
|
||||
class Class3c extends Class3b {
|
||||
/*member: Class3c.==:bool* Function(Object*)**/
|
||||
}
|
||||
|
|
|
@ -375,11 +375,9 @@ class SourceFieldBuilder extends MemberBuilderImpl implements FieldBuilder {
|
|||
if (fieldType is ImplicitFieldType) {
|
||||
// `fieldType` may have changed if a circularity was detected when
|
||||
// [inferredType] was computed.
|
||||
if (library.loader.target.enableNonNullable) {
|
||||
if (!library.isNonNullableByDefault) {
|
||||
inferredType = legacyErasure(
|
||||
library.loader.typeInferenceEngine.coreTypes, inferredType);
|
||||
}
|
||||
if (!library.isNonNullableByDefault) {
|
||||
inferredType = legacyErasure(
|
||||
library.loader.typeInferenceEngine.coreTypes, inferredType);
|
||||
}
|
||||
fieldType = inferredType;
|
||||
|
||||
|
|
|
@ -142,6 +142,16 @@ abstract class MemberBuilderImpl extends ModifierBuilderImpl
|
|||
@override
|
||||
String get fullNameForErrors => name;
|
||||
|
||||
@override
|
||||
StringBuffer printOn(StringBuffer buffer) {
|
||||
if (isClassMember) {
|
||||
buffer.write(classBuilder.name);
|
||||
buffer.write('.');
|
||||
}
|
||||
buffer.write(name);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@override
|
||||
ClassBuilder get classBuilder => parent is ClassBuilder ? parent : null;
|
||||
}
|
||||
|
|
|
@ -240,9 +240,8 @@ class ClassHierarchyBuilder {
|
|||
}
|
||||
|
||||
ClassHierarchyNode getNodeFromClassBuilder(ClassBuilder classBuilder) {
|
||||
return nodes[classBuilder.cls] ??= new ClassHierarchyNodeBuilder(
|
||||
this, classBuilder, loader.target.enableNonNullable)
|
||||
.build();
|
||||
return nodes[classBuilder.cls] ??=
|
||||
new ClassHierarchyNodeBuilder(this, classBuilder).build();
|
||||
}
|
||||
|
||||
ClassHierarchyNode getNodeFromTypeBuilder(TypeBuilder type) {
|
||||
|
@ -409,9 +408,8 @@ class ClassHierarchyBuilder {
|
|||
for (int i = 0; i < classes.length; i++) {
|
||||
ClassBuilder classBuilder = classes[i];
|
||||
if (!classBuilder.isPatch) {
|
||||
hierarchy.nodes[classBuilder.cls] = new ClassHierarchyNodeBuilder(
|
||||
hierarchy, classBuilder, loader.target.enableNonNullable)
|
||||
.build();
|
||||
hierarchy.nodes[classBuilder.cls] =
|
||||
new ClassHierarchyNodeBuilder(hierarchy, classBuilder).build();
|
||||
} else {
|
||||
// TODO(ahe): Merge the injected members of patch into the hierarchy
|
||||
// node of `cls.origin`.
|
||||
|
@ -426,15 +424,11 @@ class ClassHierarchyNodeBuilder {
|
|||
|
||||
final ClassBuilder classBuilder;
|
||||
|
||||
/// Whether non-nullable types are supported.
|
||||
final bool enableNonNullable;
|
||||
|
||||
bool hasNoSuchMethod = false;
|
||||
|
||||
List<ClassMember> abstractMembers = null;
|
||||
|
||||
ClassHierarchyNodeBuilder(
|
||||
this.hierarchy, this.classBuilder, this.enableNonNullable);
|
||||
ClassHierarchyNodeBuilder(this.hierarchy, this.classBuilder);
|
||||
|
||||
ClassBuilder get objectClass => hierarchy.objectClassBuilder;
|
||||
|
||||
|
@ -736,7 +730,8 @@ class ClassHierarchyNodeBuilder {
|
|||
if (substitution != null) {
|
||||
bType = substitution.substituteType(bType);
|
||||
}
|
||||
if (enableNonNullable &&
|
||||
if (hierarchy
|
||||
.coreTypes.objectClass.enclosingLibrary.isNonNullableByDefault &&
|
||||
!a.classBuilder.library.isNonNullableByDefault &&
|
||||
b.member == hierarchy.coreTypes.objectEquals) {
|
||||
// In legacy code we special case `Object.==` to infer `dynamic` instead
|
||||
|
@ -1184,13 +1179,13 @@ class ClassHierarchyNodeBuilder {
|
|||
member = delayedMember.withParent(classBuilder);
|
||||
hierarchy.delayedMemberChecks.add(member);
|
||||
}
|
||||
if (mergeKind.intoCurrentClass &&
|
||||
hierarchy.loader.target.enableNonNullable) {
|
||||
if (mergeKind.intoCurrentClass) {
|
||||
if (member.classBuilder.library.isNonNullableByDefault &&
|
||||
!classBuilder.library.isNonNullableByDefault) {
|
||||
if (member is! DelayedMember) {
|
||||
member = new InterfaceConflict(
|
||||
classBuilder, [member], mergeKind.forSetters, shouldModifyKernel);
|
||||
classBuilder, [member], mergeKind.forSetters, shouldModifyKernel,
|
||||
isAbstract: isAbstract(member));
|
||||
hierarchy.delayedMemberChecks.add(member);
|
||||
}
|
||||
}
|
||||
|
@ -1506,8 +1501,7 @@ class ClassHierarchyNodeBuilder {
|
|||
|
||||
DartType addInterface(
|
||||
List<DartType> interfaces, List<DartType> superclasses, DartType type) {
|
||||
if (hierarchy.loader.target.enableNonNullable &&
|
||||
!classBuilder.library.isNonNullableByDefault) {
|
||||
if (!classBuilder.library.isNonNullableByDefault) {
|
||||
type = legacyErasure(hierarchy.coreTypes, type);
|
||||
}
|
||||
if (type is InterfaceType) {
|
||||
|
@ -1518,18 +1512,16 @@ class ClassHierarchyNodeBuilder {
|
|||
DartType superclass = depth < myDepth ? superclasses[depth] : null;
|
||||
if (superclass is InterfaceType &&
|
||||
superclass.classNode == type.classNode) {
|
||||
if (hierarchy.loader.target.enableNonNullable) {
|
||||
// This is a potential conflict.
|
||||
if (classBuilder.library.isNonNullableByDefault) {
|
||||
superclass = nnbdTopMerge(hierarchy.coreTypes, superclass, type);
|
||||
if (superclass == null) {
|
||||
// This is a conflict.
|
||||
// TODO(johnniwinther): Report errors here instead of through
|
||||
// the computation of the [ClassHierarchy].
|
||||
superclass = superclasses[depth];
|
||||
} else {
|
||||
superclasses[depth] = superclass;
|
||||
}
|
||||
// This is a potential conflict.
|
||||
if (classBuilder.library.isNonNullableByDefault) {
|
||||
superclass = nnbdTopMerge(hierarchy.coreTypes, superclass, type);
|
||||
if (superclass == null) {
|
||||
// This is a conflict.
|
||||
// TODO(johnniwinther): Report errors here instead of through
|
||||
// the computation of the [ClassHierarchy].
|
||||
superclass = superclasses[depth];
|
||||
} else {
|
||||
superclasses[depth] = superclass;
|
||||
}
|
||||
}
|
||||
return superclass;
|
||||
|
@ -1540,18 +1532,16 @@ class ClassHierarchyNodeBuilder {
|
|||
DartType interface = interfaces[i];
|
||||
if (interface is InterfaceType &&
|
||||
interface.classNode == type.classNode) {
|
||||
if (hierarchy.loader.target.enableNonNullable) {
|
||||
// This is a potential conflict.
|
||||
if (classBuilder.library.isNonNullableByDefault) {
|
||||
interface = nnbdTopMerge(hierarchy.coreTypes, interface, type);
|
||||
if (interface == null) {
|
||||
// This is a conflict.
|
||||
// TODO(johnniwinther): Report errors here instead of through
|
||||
// the computation of the [ClassHierarchy].
|
||||
interface = interfaces[i];
|
||||
} else {
|
||||
interfaces[i] = interface;
|
||||
}
|
||||
// This is a potential conflict.
|
||||
if (classBuilder.library.isNonNullableByDefault) {
|
||||
interface = nnbdTopMerge(hierarchy.coreTypes, interface, type);
|
||||
if (interface == null) {
|
||||
// This is a conflict.
|
||||
// TODO(johnniwinther): Report errors here instead of through
|
||||
// the computation of the [ClassHierarchy].
|
||||
interface = interfaces[i];
|
||||
} else {
|
||||
interfaces[i] = interface;
|
||||
}
|
||||
}
|
||||
return interface;
|
||||
|
@ -2469,8 +2459,11 @@ class InheritedImplementationInterfaceConflict extends DelayedMember {
|
|||
}
|
||||
|
||||
class InterfaceConflict extends DelayedMember {
|
||||
bool isAbstract;
|
||||
|
||||
InterfaceConflict(ClassBuilder parent, List<ClassMember> declarations,
|
||||
bool isSetter, bool modifyKernel)
|
||||
bool isSetter, bool modifyKernel,
|
||||
{this.isAbstract: true})
|
||||
: super(parent, declarations, isSetter, modifyKernel);
|
||||
|
||||
Member combinedMemberSignatureResult;
|
||||
|
@ -2717,6 +2710,8 @@ class AbstractMemberOverridingImplementation extends DelayedMember {
|
|||
static ClassMember selectConcrete(ClassMember declaration) {
|
||||
if (declaration is AbstractMemberOverridingImplementation) {
|
||||
return declaration.concreteImplementation;
|
||||
} else if (declaration is InterfaceConflict && !declaration.isAbstract) {
|
||||
return selectConcrete(declaration.declarations.single);
|
||||
} else {
|
||||
return declaration;
|
||||
}
|
||||
|
@ -2758,7 +2753,8 @@ int compareNamedParameters(VariableDeclaration a, VariableDeclaration b) {
|
|||
}
|
||||
|
||||
bool isAbstract(ClassMember declaration) {
|
||||
return declaration.member.isAbstract || declaration is InterfaceConflict;
|
||||
return declaration.member.isAbstract ||
|
||||
(declaration is InterfaceConflict && declaration.isAbstract);
|
||||
}
|
||||
|
||||
bool inferParameterType(
|
||||
|
|
|
@ -47,7 +47,7 @@ import 'class_hierarchy_builder.dart';
|
|||
class ForwardingNode {
|
||||
final ClassHierarchyBuilder hierarchy;
|
||||
|
||||
final SourceClassBuilder parent;
|
||||
final SourceClassBuilder classBuilder;
|
||||
|
||||
final ClassMember combinedMemberSignatureResult;
|
||||
|
||||
|
@ -57,12 +57,12 @@ class ForwardingNode {
|
|||
/// procedures of the class in question.
|
||||
final List<ClassMember> _candidates;
|
||||
|
||||
ForwardingNode(this.hierarchy, this.parent,
|
||||
ForwardingNode(this.hierarchy, this.classBuilder,
|
||||
this.combinedMemberSignatureResult, this._candidates, this.kind);
|
||||
|
||||
Name get name => combinedMemberSignatureResult.member.name;
|
||||
|
||||
Class get enclosingClass => parent.cls;
|
||||
Class get enclosingClass => classBuilder.cls;
|
||||
|
||||
/// Finishes handling of this node by propagating covariance and creating
|
||||
/// forwarding stubs if necessary.
|
||||
|
@ -169,12 +169,9 @@ class ForwardingNode {
|
|||
bool needsCheck(DartType type) => needsCheckVisitor == null
|
||||
? false
|
||||
: substitution.substituteType(type).accept(needsCheckVisitor);
|
||||
bool enableNonNullable = hierarchy.loader.target.enableNonNullable;
|
||||
bool isNonNullableByDefault =
|
||||
enableNonNullable && parent.library.isNonNullableByDefault;
|
||||
bool isNonNullableByDefault = classBuilder.library.isNonNullableByDefault;
|
||||
|
||||
DartType initialType(DartType a) {
|
||||
if (!enableNonNullable) return null;
|
||||
if (!isNonNullableByDefault) {
|
||||
a = legacyErasure(hierarchy.coreTypes, a);
|
||||
}
|
||||
|
@ -191,8 +188,8 @@ class ForwardingNode {
|
|||
|
||||
for (int i = 0; i < interfacePositionalParameters.length; i++) {
|
||||
VariableDeclaration parameter = interfacePositionalParameters[i];
|
||||
DartType parameterType = parameter.type;
|
||||
DartType type = initialType(substitution.substituteType(parameterType));
|
||||
DartType parameterType = substitution.substituteType(parameter.type);
|
||||
DartType type = initialType(parameterType);
|
||||
bool isGenericCovariantImpl =
|
||||
parameter.isGenericCovariantImpl || needsCheck(parameter.type);
|
||||
bool isCovariant = parameter.isCovariant;
|
||||
|
@ -232,19 +229,17 @@ class ForwardingNode {
|
|||
stub.function.positionalParameters[i].isCovariant = true;
|
||||
}
|
||||
}
|
||||
if (enableNonNullable) {
|
||||
if (type != null && type != parameterType) {
|
||||
// TODO(johnniwinther): Report an error when [type] is null; this
|
||||
// means that nnbd-top-merge was not defined.
|
||||
createStubIfNeeded(forMemberSignature: true);
|
||||
stub.function.positionalParameters[i].type = type;
|
||||
}
|
||||
if (type != null && type != parameterType) {
|
||||
// TODO(johnniwinther): Report an error when [type] is null; this
|
||||
// means that nnbd-top-merge was not defined.
|
||||
createStubIfNeeded(forMemberSignature: true);
|
||||
stub.function.positionalParameters[i].type = type;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < interfaceNamedParameters.length; i++) {
|
||||
VariableDeclaration parameter = interfaceNamedParameters[i];
|
||||
DartType parameterType = parameter.type;
|
||||
DartType type = initialType(substitution.substituteType(parameterType));
|
||||
DartType parameterType = substitution.substituteType(parameter.type);
|
||||
DartType type = initialType(parameterType);
|
||||
bool isGenericCovariantImpl =
|
||||
parameter.isGenericCovariantImpl || needsCheck(parameter.type);
|
||||
bool isCovariant = parameter.isCovariant;
|
||||
|
@ -284,13 +279,11 @@ class ForwardingNode {
|
|||
stub.function.namedParameters[i].isCovariant = true;
|
||||
}
|
||||
}
|
||||
if (enableNonNullable) {
|
||||
if (type != null && type != parameterType) {
|
||||
// TODO(johnniwinther): Report an error when [type] is null; this
|
||||
// means that nnbd-top-merge was not defined.
|
||||
createStubIfNeeded(forMemberSignature: true);
|
||||
stub.function.namedParameters[i].type = type;
|
||||
}
|
||||
if (type != null && type != parameterType) {
|
||||
// TODO(johnniwinther): Report an error when [type] is null; this
|
||||
// means that nnbd-top-merge was not defined.
|
||||
createStubIfNeeded(forMemberSignature: true);
|
||||
stub.function.namedParameters[i].type = type;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < interfaceTypeParameters.length; i++) {
|
||||
|
@ -321,21 +314,19 @@ class ForwardingNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (enableNonNullable) {
|
||||
DartType returnType =
|
||||
substitution.substituteType(getReturnType(interfaceMember));
|
||||
DartType type = initialType(returnType);
|
||||
for (int j = 0; j < _candidates.length; j++) {
|
||||
Member otherMember = getCandidateAt(j);
|
||||
type = mergeTypes(
|
||||
type, substitutions[j].substituteType(getReturnType(otherMember)));
|
||||
}
|
||||
if (type != null && type != returnType) {
|
||||
// TODO(johnniwinther): Report an error when [type] is null; this
|
||||
// means that nnbd-top-merge was not defined.
|
||||
createStubIfNeeded(forMemberSignature: true);
|
||||
stub.function.returnType = type;
|
||||
}
|
||||
DartType returnType =
|
||||
substitution.substituteType(getReturnType(interfaceMember));
|
||||
DartType type = initialType(returnType);
|
||||
for (int j = 0; j < _candidates.length; j++) {
|
||||
Member otherMember = getCandidateAt(j);
|
||||
type = mergeTypes(
|
||||
type, substitutions[j].substituteType(getReturnType(otherMember)));
|
||||
}
|
||||
if (type != null && type != returnType) {
|
||||
// TODO(johnniwinther): Report an error when [type] is null; this
|
||||
// means that nnbd-top-merge was not defined.
|
||||
createStubIfNeeded(forMemberSignature: true);
|
||||
stub.function.returnType = type;
|
||||
}
|
||||
return stub;
|
||||
}
|
||||
|
@ -447,13 +438,13 @@ class ForwardingNode {
|
|||
finalTarget = target;
|
||||
}
|
||||
Procedure referenceFrom;
|
||||
if (parent.referencesFromIndexed != null) {
|
||||
if (classBuilder.referencesFromIndexed != null) {
|
||||
if (kind == ProcedureKind.Setter) {
|
||||
referenceFrom =
|
||||
parent.referencesFromIndexed.lookupProcedureSetter(name.name);
|
||||
classBuilder.referencesFromIndexed.lookupProcedureSetter(name.name);
|
||||
} else {
|
||||
referenceFrom =
|
||||
parent.referencesFromIndexed.lookupProcedureNotSetter(name.name);
|
||||
referenceFrom = classBuilder.referencesFromIndexed
|
||||
.lookupProcedureNotSetter(name.name);
|
||||
}
|
||||
}
|
||||
return new Procedure(name, kind, function,
|
||||
|
|
|
@ -106,11 +106,8 @@ class _ImplicitFieldTypeAlias extends ImplicitFieldType {
|
|||
|
||||
DartType inferType() {
|
||||
DartType type = _root.inferType();
|
||||
if (_targetFieldBuilder.library.loader.target.enableNonNullable) {
|
||||
if (!_targetFieldBuilder.library.isNonNullableByDefault) {
|
||||
type =
|
||||
legacyErasure(_targetFieldBuilder.library.loader.coreTypes, type);
|
||||
}
|
||||
if (!_targetFieldBuilder.library.isNonNullableByDefault) {
|
||||
type = legacyErasure(_targetFieldBuilder.library.loader.coreTypes, type);
|
||||
}
|
||||
return _targetFieldBuilder.fieldType = type;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue