[dart2js] Clean up handling of missing super methods.

Issue: #47406
Issue: #48820
Change-Id: I19de399c4670f9866cffceae3bc3ce19201d1ed3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352963
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Mayank Patke <fishythefish@google.com>
This commit is contained in:
Mayank Patke 2024-02-20 21:01:14 +00:00 committed by Commit Queue
parent 3722837cec
commit b0a96bf950
9 changed files with 55 additions and 252 deletions

View file

@ -243,16 +243,6 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault<TypeInformation?>
return visit(_analyzedNode)!;
}
bool isIncompatibleInvoke(FunctionEntity function, ArgumentsTypes arguments) {
ParameterStructure parameterStructure = function.parameterStructure;
return arguments.positional.length <
parameterStructure.requiredPositionalParameters ||
arguments.positional.length > parameterStructure.positionalParameters ||
arguments.named.keys
.any((name) => !parameterStructure.namedParameters.contains(name));
}
void recordReturnType(TypeInformation type) {
final analyzedMethod = _analyzedMember as FunctionEntity;
_returnType = _inferrer.addReturnTypeForMethod(analyzedMethod, type);
@ -940,10 +930,6 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault<TypeInformation?>
ClosureRepresentationInfo info =
_closureDataLookup.getClosureInfo(function);
final callMethod = info.callMethod!;
if (isIncompatibleInvoke(callMethod, argumentsTypes)) {
return _types.dynamicType;
}
TypeInformation type =
handleStaticInvoke(node, selector, callMethod, argumentsTypes);
FunctionType functionType =
@ -2153,15 +2139,6 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault<TypeInformation?>
return _types.nonNullEmpty();
}
TypeInformation handleSuperNoSuchMethod(
ir.Node node, Selector selector, ArgumentsTypes? arguments) {
// Ensure we create a node, to make explicit the call to the
// `noSuchMethod` handler.
FunctionEntity noSuchMethod =
_elementMap.getSuperNoSuchMethod(_analyzedMember.enclosingClass!);
return handleStaticInvoke(node, selector, noSuchMethod, arguments);
}
@override
TypeInformation visitSuperPropertyGet(ir.SuperPropertyGet node) {
// TODO(herhut): We could do better here if we knew what we
@ -2170,13 +2147,6 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault<TypeInformation?>
final target = getEffectiveSuperTarget(node.interfaceTarget);
Selector selector = Selector.getter(_elementMap.getName(node.name));
if (target == null) {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
// TODO(48820): If this path is infeasible, update types on
// getEffectiveSuperTarget.
return handleSuperNoSuchMethod(node, selector, null);
}
MemberEntity member = _elementMap.getMember(target);
TypeInformation type = handleStaticInvoke(node, selector, member, null);
if (member.isGetter) {
@ -2208,11 +2178,6 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault<TypeInformation?>
final target = getEffectiveSuperTarget(node.interfaceTarget);
Selector selector = Selector.setter(_elementMap.getName(node.name));
ArgumentsTypes arguments = ArgumentsTypes([rhsType], null);
if (target == null) {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
return handleSuperNoSuchMethod(node, selector, arguments);
}
final member = _elementMap.getMember(target);
handleStaticInvoke(node, selector, member, arguments);
return rhsType;
@ -2227,27 +2192,19 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault<TypeInformation?>
final target = getEffectiveSuperTarget(node.interfaceTarget);
ArgumentsTypes arguments = analyzeArguments(node.arguments);
Selector selector = _elementMap.getSelector(node);
if (target == null) {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
return handleSuperNoSuchMethod(node, selector, arguments);
}
MemberEntity member = _elementMap.getMember(target);
assert(member.isFunction, "Unexpected super invocation target: $member");
if (isIncompatibleInvoke(member as FunctionEntity, arguments)) {
return handleSuperNoSuchMethod(node, selector, arguments);
} else {
TypeInformation type =
handleStaticInvoke(node, selector, member, arguments);
FunctionType functionType =
_elementMap.elementEnvironment.getFunctionType(member);
if (functionType.returnType.containsFreeTypeVariables) {
// The return type varies with the call site so we narrow the static
// return type.
type = _types.narrowType(type, _getStaticType(node));
}
return type;
member as FunctionEntity;
TypeInformation type =
handleStaticInvoke(node, selector, member, arguments);
FunctionType functionType =
_elementMap.elementEnvironment.getFunctionType(member);
if (functionType.returnType.containsFreeTypeVariables) {
// The return type varies with the call site so we narrow the static
// return type.
type = _types.narrowType(type, _getStaticType(node));
}
return type;
}
@override

View file

@ -156,12 +156,12 @@ abstract class ImpactRegistry {
void registerInstanceSet(ir.DartType receiverType, ir.Member target);
void registerSuperInvocation(ir.Member? target, int positionalArguments,
void registerSuperInvocation(ir.Member target, int positionalArguments,
List<String> namedArguments, List<ir.DartType> typeArguments);
void registerSuperGet(ir.Member? target);
void registerSuperGet(ir.Member target);
void registerSuperSet(ir.Member? target);
void registerSuperSet(ir.Member target);
void registerSuperInitializer(
ir.Constructor source,

View file

@ -679,7 +679,7 @@ class ImpactBuilder extends ir.RecursiveVisitor implements ImpactRegistry {
@override
void visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
registerSuperInvocation(
getEffectiveSuperTarget(node.interfaceTarget)!,
getEffectiveSuperTarget(node.interfaceTarget),
node.arguments.positional.length,
_getNamedArguments(node.arguments),
node.arguments.types);
@ -688,12 +688,12 @@ class ImpactBuilder extends ir.RecursiveVisitor implements ImpactRegistry {
@override
void visitSuperPropertyGet(ir.SuperPropertyGet node) {
registerSuperGet(getEffectiveSuperTarget(node.interfaceTarget)!);
registerSuperGet(getEffectiveSuperTarget(node.interfaceTarget));
}
@override
void visitSuperPropertySet(ir.SuperPropertySet node) {
registerSuperSet(getEffectiveSuperTarget(node.interfaceTarget)!);
registerSuperSet(getEffectiveSuperTarget(node.interfaceTarget));
node.value.accept(this);
}
@ -788,19 +788,19 @@ class ImpactBuilder extends ir.RecursiveVisitor implements ImpactRegistry {
}
@override
void registerSuperSet(ir.Member? target) {
(_data._superSets ??= []).add(target!);
void registerSuperSet(ir.Member target) {
(_data._superSets ??= []).add(target);
}
@override
void registerSuperGet(ir.Member? target) {
(_data._superGets ??= []).add(target!);
void registerSuperGet(ir.Member target) {
(_data._superGets ??= []).add(target);
}
@override
void registerSuperInvocation(ir.Member? target, int positionalArguments,
void registerSuperInvocation(ir.Member target, int positionalArguments,
List<String> namedArguments, List<ir.DartType> typeArguments) {
(_data._superInvocations ??= []).add(_SuperInvocation(target!,
(_data._superInvocations ??= []).add(_SuperInvocation(target,
_CallStructure(positionalArguments, namedArguments, typeArguments)));
}

View file

@ -315,15 +315,10 @@ bool memberEntityIsInWebLibrary(MemberEntity entity) {
///
/// See [ir.ProcedureStubKind.ConcreteMixinStub] for why concrete mixin stubs
/// are inserted in the first place.
ir.Member? getEffectiveSuperTarget(ir.Member? target) {
ir.Member getEffectiveSuperTarget(ir.Member target) {
if (target is ir.Procedure) {
if (target.stubKind == ir.ProcedureStubKind.ConcreteMixinStub) {
return getEffectiveSuperTarget(target.stubTarget);
}
// TODO(johnniwinther): Remove this when the CFE reports an error on
// missing concrete super targets.
if (target.isAbstract) {
return null;
return getEffectiveSuperTarget(target.stubTarget!);
}
}
return target;

View file

@ -201,18 +201,6 @@ class BackendImpacts {
],
);
late final BackendImpact superNoSuchMethod = BackendImpact(
staticUses: [
_commonElements.createInvocationMirror,
_commonElements.objectNoSuchMethod!
],
otherImpacts: [
_needsInt('Needed to encode the invocation kind of super.noSuchMethod.'),
_needsList('Needed to encode the arguments of super.noSuchMethod.'),
_needsString('Needed to encode the name of super.noSuchMethod.')
],
);
late final BackendImpact constantMapLiteral = BackendImpact(
instantiatedClasses: [
_commonElements.constantMapClass,
@ -239,12 +227,6 @@ class BackendImpacts {
return intValues;
}
/// Helper for registering that `List` is needed.
BackendImpact _needsList(String reason) {
// TODO(johnniwinther): Register [reason] for use in dump-info.
return listValues;
}
/// Helper for registering that `String` is needed.
BackendImpact _needsString(String reason) {
// TODO(johnniwinther): Register [reason] for use in dump-info.

View file

@ -78,10 +78,6 @@ abstract class JsToElementMap {
/// Returns the [ClassEntity] corresponding to the class [node].
ClassEntity getClass(ir.Class node);
/// Returns the `noSuchMethod` [FunctionEntity] call from a
/// `super.noSuchMethod` invocation within [cls].
FunctionEntity getSuperNoSuchMethod(ClassEntity cls);
/// Returns the [Name] corresponding to [name].
Name getName(ir.Name name);

View file

@ -1336,30 +1336,6 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
return ConstructedConstantValue(_commonElements.requiredSentinelType, {});
}
@override
FunctionEntity getSuperNoSuchMethod(ClassEntity cls) {
while (true) {
ClassEntity? superclass = elementEnvironment.getSuperClass(cls);
if (superclass == null) break;
MemberEntity? member = elementEnvironment.lookupLocalClassMember(
superclass, Names.noSuchMethod_);
if (member != null && !member.isAbstract) {
if (member.isFunction) {
final function = member as FunctionEntity;
if (function.parameterStructure.positionalParameters >= 1) {
return function;
}
}
// If [member] is not a valid `noSuchMethod` the target is
// `Object.superNoSuchMethod`.
break;
}
cls = superclass;
}
return elementEnvironment.lookupLocalClassMember(
commonElements.objectClass, Names.noSuchMethod_)! as FunctionEntity;
}
JTypeVariable createTypeVariable(
Entity typeDeclaration, String name, int index) {
return JTypeVariable(typeDeclaration, name, index);

View file

@ -474,63 +474,36 @@ class KernelImpactConverter implements ImpactRegistry {
}
@override
void registerSuperInvocation(ir.Member? target, int positionalArguments,
void registerSuperInvocation(ir.Member target, int positionalArguments,
List<String> namedArguments, List<ir.DartType> typeArguments) {
if (target != null) {
FunctionEntity method = elementMap.getMember(target) as FunctionEntity;
List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
impactBuilder.registerStaticUse(StaticUse.superInvoke(
method,
CallStructure(positionalArguments + namedArguments.length,
namedArguments, typeArguments.length),
dartTypeArguments));
FunctionEntity method = elementMap.getMember(target) as FunctionEntity;
List<DartType>? dartTypeArguments = _getTypeArguments(typeArguments);
impactBuilder.registerStaticUse(StaticUse.superInvoke(
method,
CallStructure(positionalArguments + namedArguments.length,
namedArguments, typeArguments.length),
dartTypeArguments));
}
@override
void registerSuperGet(ir.Member target) {
MemberEntity member = elementMap.getMember(target);
if (member.isFunction) {
impactBuilder
.registerStaticUse(StaticUse.superTearOff(member as FunctionEntity));
} else {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
impactBuilder.registerStaticUse(StaticUse.superInvoke(
elementMap.getSuperNoSuchMethod(currentMember.enclosingClass!),
CallStructure.ONE_ARG));
registerBackendImpact(_impacts.superNoSuchMethod);
impactBuilder.registerStaticUse(StaticUse.superGet(member));
}
}
@override
void registerSuperGet(ir.Member? target) {
if (target != null) {
MemberEntity member = elementMap.getMember(target);
if (member.isFunction) {
impactBuilder.registerStaticUse(
StaticUse.superTearOff(member as FunctionEntity));
} else {
impactBuilder.registerStaticUse(StaticUse.superGet(member));
}
void registerSuperSet(ir.Member target) {
MemberEntity member = elementMap.getMember(target);
if (member is FieldEntity) {
impactBuilder.registerStaticUse(StaticUse.superFieldSet(member));
} else {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
impactBuilder.registerStaticUse(StaticUse.superInvoke(
elementMap.getSuperNoSuchMethod(currentMember.enclosingClass!),
CallStructure.ONE_ARG));
registerBackendImpact(_impacts.superNoSuchMethod);
}
}
@override
void registerSuperSet(ir.Member? target) {
if (target != null) {
MemberEntity member = elementMap.getMember(target);
if (member is FieldEntity) {
impactBuilder.registerStaticUse(StaticUse.superFieldSet(member));
} else {
impactBuilder.registerStaticUse(
StaticUse.superSetterSet(member as FunctionEntity));
}
} else {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
impactBuilder.registerStaticUse(StaticUse.superInvoke(
elementMap.getSuperNoSuchMethod(currentMember.enclosingClass!),
CallStructure.ONE_ARG));
registerBackendImpact(_impacts.superNoSuchMethod);
impactBuilder.registerStaticUse(
StaticUse.superSetterSet(member as FunctionEntity));
}
}

View file

@ -4003,21 +4003,14 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
HInstruction value = pop();
final target = getEffectiveSuperTarget(node.interfaceTarget);
if (target == null) {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
_generateSuperNoSuchMethod(node, _elementMap.getSelector(node).name + "=",
[value], const <DartType>[], sourceInformation);
} else {
MemberEntity member = _elementMap.getMember(target);
_buildInvokeSuper(
_elementMap.getSelector(node),
_elementMap.getClass(_containingClass(node)),
member,
[value],
const <DartType>[],
sourceInformation);
}
MemberEntity member = _elementMap.getMember(target);
_buildInvokeSuper(
_elementMap.getSelector(node),
_elementMap.getClass(_containingClass(node)),
member,
[value],
const <DartType>[],
sourceInformation);
pop();
stack.add(value);
}
@ -5919,55 +5912,6 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
throw ArgumentError.value(node, 'node', 'No containing class found.');
}
void _generateSuperNoSuchMethod(
ir.Expression invocation,
String publicName,
List<HInstruction> arguments,
List<DartType> typeArguments,
SourceInformation? sourceInformation) {
Selector selector = _elementMap.getSelector(invocation);
ClassEntity containingClass =
_elementMap.getClass(_containingClass(invocation));
FunctionEntity noSuchMethod =
_elementMap.getSuperNoSuchMethod(containingClass);
ConstantValue nameConstant = constant_system.createString(publicName);
js.Name internalName = _namer.invocationName(selector);
var argumentsInstruction = _buildLiteralList(arguments);
add(argumentsInstruction);
List<HInstruction> argumentNames = [];
for (String argumentName in selector.namedArguments) {
ConstantValue argumentNameConstant =
constant_system.createString(argumentName);
argumentNames.add(graph.addConstant(argumentNameConstant, closedWorld));
}
var argumentNamesInstruction = _buildLiteralList(argumentNames);
add(argumentNamesInstruction);
ConstantValue kindConstant =
constant_system.createIntFromInt(selector.invocationMirrorKind);
_pushStaticInvocation(
_commonElements.createInvocationMirror,
[
graph.addConstant(nameConstant, closedWorld),
graph.addConstantStringFromName(internalName, closedWorld),
graph.addConstant(kindConstant, closedWorld),
argumentsInstruction,
argumentNamesInstruction,
graph.addConstantInt(typeArguments.length, closedWorld),
],
_abstractValueDomain.dynamicType,
typeArguments,
sourceInformation: sourceInformation);
_buildInvokeSuper(Selectors.noSuchMethod_, containingClass, noSuchMethod,
[pop()], typeArguments, sourceInformation);
}
HInstruction _buildInvokeSuper(
Selector selector,
ClassEntity containingClass,
@ -6008,13 +5952,6 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
void visitSuperPropertyGet(ir.SuperPropertyGet node) {
final sourceInformation = _sourceInformationBuilder.buildGet(node);
final target = getEffectiveSuperTarget(node.interfaceTarget);
if (target == null) {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
_generateSuperNoSuchMethod(node, _elementMap.getSelector(node).name,
const <HInstruction>[], const <DartType>[], sourceInformation);
return;
}
MemberEntity member = _elementMap.getMember(target);
if (member is FieldEntity) {
FieldAnalysisData fieldData = _fieldAnalysis.getFieldData(member);
@ -6038,19 +5975,6 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
void visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
final sourceInformation = _sourceInformationBuilder.buildCall(node, node);
final superTarget = getEffectiveSuperTarget(node.interfaceTarget);
if (superTarget == null) {
// TODO(johnniwinther): Remove this when the CFE checks for missing
// concrete super targets.
Selector selector = _elementMap.getSelector(node);
List<DartType> typeArguments = <DartType>[];
selector =
_fillDynamicTypeArguments(selector, node.arguments, typeArguments);
List<HInstruction> arguments = _visitArgumentsForDynamicTarget(
selector, node.arguments, typeArguments);
_generateSuperNoSuchMethod(
node, selector.name, arguments, typeArguments, sourceInformation);
return;
}
MemberEntity member = _elementMap.getMember(superTarget);
List<DartType> typeArguments =
_getStaticTypeArguments(member as FunctionEntity, node.arguments);