From cb3cac408d26057db4ce45dc717f93a7ca34d6df Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Fri, 20 May 2022 09:50:01 +0000 Subject: [PATCH] [kernel] Add AbstractSuper* nodes This adds AbstractSuperMethodInvocation, AbstractSuperPropertyGet, AbstractSuperPropertySet nodes which are to be used for super access in mixin declaration. These super accesses do not resolve to their statically bound target but instead the interface target on the types in the 'on' clauses, and need to be updated to the statically bound target upon mixin application. This has lead backends to disregard the interface target provided by the CFE and instead always compute targets for super accesses. This change is a step towards creating a clear separation between the two use cases, enabling a more precise handling of super accesses. The new nodes are not created yet with this CL. TEST=existing Change-Id: I70ea9baf5b4b970b10cc72b7409633d270d57755 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245168 Reviewed-by: Alexander Markov Reviewed-by: Nicholas Shahan Reviewed-by: Chloe Stefantsova Commit-Queue: Johnni Winther --- pkg/dev_compiler/lib/src/kernel/compiler.dart | 40 ++- .../src/fasta/kernel/constant_evaluator.dart | 13 + .../src/fasta/kernel/inference_visitor.dart | 103 +++++- .../fasta/type_inference/type_inferrer.dart | 14 +- pkg/kernel/binary.md | 28 +- pkg/kernel/lib/ast.dart | 305 ++++++++++++++++++ pkg/kernel/lib/binary/ast_from_binary.dart | 30 ++ pkg/kernel/lib/binary/ast_to_binary.dart | 26 ++ pkg/kernel/lib/binary/tag.dart | 5 +- pkg/kernel/lib/clone.dart | 19 ++ pkg/kernel/lib/src/coverage.dart | 21 ++ pkg/kernel/lib/src/equivalence.dart | 151 +++++++++ pkg/kernel/lib/src/node_creator.dart | 24 ++ pkg/kernel/lib/text/ast_to_text.dart | 11 + pkg/kernel/lib/type_checker.dart | 39 +++ pkg/kernel/lib/visitor.dart | 32 ++ .../frontend/kernel_binary_flowgraph.cc | 15 + .../compiler/frontend/kernel_fingerprints.cc | 15 + .../frontend/kernel_translation_helper.cc | 15 + runtime/vm/compiler/frontend/scope_builder.cc | 15 + runtime/vm/kernel_binary.h | 7 +- 21 files changed, 908 insertions(+), 20 deletions(-) diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart index e95a0afe84a..506b32d30ae 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart @@ -4779,9 +4779,18 @@ class ProgramCompiler extends ComputeOnceConstantVisitor return js.call('#.# = #', [jsReceiver, jsName, jsValue]); } + @override + js_ast.Expression visitAbstractSuperPropertyGet( + AbstractSuperPropertyGet node) { + return _emitSuperPropertyGet(node.interfaceTarget); + } + @override js_ast.Expression visitSuperPropertyGet(SuperPropertyGet node) { - var target = node.interfaceTarget; + return _emitSuperPropertyGet(node.interfaceTarget); + } + + js_ast.Expression _emitSuperPropertyGet(Member target) { if (_reifyTearoff(target)) { if (_superAllowed) { var jsTarget = _emitSuperTarget(target); @@ -4793,11 +4802,20 @@ class ProgramCompiler extends ComputeOnceConstantVisitor return _emitSuperTarget(target); } + @override + js_ast.Expression visitAbstractSuperPropertySet( + AbstractSuperPropertySet node) { + return _emitSuperPropertySet(node.interfaceTarget, node.value); + } + @override js_ast.Expression visitSuperPropertySet(SuperPropertySet node) { - var target = node.interfaceTarget; + return _emitSuperPropertySet(node.interfaceTarget, node.value); + } + + js_ast.Expression _emitSuperPropertySet(Member target, Expression value) { var jsTarget = _emitSuperTarget(target, setter: true); - return _visitExpression(node.value).toAssignExpression(jsTarget); + return _visitExpression(value).toAssignExpression(jsTarget); } @override @@ -5403,11 +5421,21 @@ class ProgramCompiler extends ComputeOnceConstantVisitor } // TODO(jmesserly): optimize super operators for kernel + @override + js_ast.Expression visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node) { + return _emitSuperMethodInvocation(node.interfaceTarget, node.arguments); + } + @override js_ast.Expression visitSuperMethodInvocation(SuperMethodInvocation node) { - var target = node.interfaceTarget; - return js_ast.Call(_emitSuperTarget(target), - _emitArgumentList(node.arguments, target: target)); + return _emitSuperMethodInvocation(node.interfaceTarget, node.arguments); + } + + js_ast.Expression _emitSuperMethodInvocation( + Member target, Arguments arguments) { + return js_ast.Call( + _emitSuperTarget(target), _emitArgumentList(arguments, target: target)); } /// Emits the [js_ast.PropertyAccess] for accessors or method calls to diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart index bd6983c9800..320a50cfe09 100644 --- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart +++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart @@ -3771,10 +3771,23 @@ class ConstantEvaluator implements ExpressionVisitor { @override Constant visitStaticSet(StaticSet node) => defaultExpression(node); + @override + Constant visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node) => + defaultExpression(node); + @override Constant visitSuperMethodInvocation(SuperMethodInvocation node) => defaultExpression(node); + @override + Constant visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) => + defaultExpression(node); + + @override + Constant visitAbstractSuperPropertySet(AbstractSuperPropertySet node) => + defaultExpression(node); + @override Constant visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node); diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart index dd68ba0b7cf..71ba7f611a8 100644 --- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart +++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart @@ -1196,6 +1196,8 @@ class InferenceVisitor return new LocalForInVariable(syntheticAssignment); } else if (syntheticAssignment is PropertySet) { return new PropertyForInVariable(syntheticAssignment); + } else if (syntheticAssignment is AbstractSuperPropertySet) { + return new AbstractSuperPropertyForInVariable(syntheticAssignment); } else if (syntheticAssignment is SuperPropertySet) { return new SuperPropertyForInVariable(syntheticAssignment); } else if (syntheticAssignment is StaticSet) { @@ -6148,6 +6150,21 @@ class InferenceVisitor inferenceResult); } + @override + ExpressionInferenceResult visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node, DartType typeContext) { + if (node.interfaceTarget != null) { + inferrer.instrumentation?.record( + inferrer.uriForInstrumentation, + node.fileOffset, + 'target', + new InstrumentationValueForMember(node.interfaceTarget!)); + } + assert(node.interfaceTarget == null || node.interfaceTarget is Procedure); + return inferrer.inferSuperMethodInvocation(node, node.name, + node.arguments as ArgumentsImpl, typeContext, node.interfaceTarget); + } + @override ExpressionInferenceResult visitSuperMethodInvocation( SuperMethodInvocation node, DartType typeContext) { @@ -6159,8 +6176,22 @@ class InferenceVisitor new InstrumentationValueForMember(node.interfaceTarget!)); } assert(node.interfaceTarget == null || node.interfaceTarget is Procedure); - return inferrer.inferSuperMethodInvocation( - node, typeContext, node.interfaceTarget); + return inferrer.inferSuperMethodInvocation(node, node.name, + node.arguments as ArgumentsImpl, typeContext, node.interfaceTarget); + } + + @override + ExpressionInferenceResult visitAbstractSuperPropertyGet( + AbstractSuperPropertyGet node, DartType typeContext) { + if (node.interfaceTarget != null) { + inferrer.instrumentation?.record( + inferrer.uriForInstrumentation, + node.fileOffset, + 'target', + new InstrumentationValueForMember(node.interfaceTarget!)); + } + return inferrer.inferSuperPropertyGet( + node, node.name, typeContext, node.interfaceTarget); } @override @@ -6174,7 +6205,33 @@ class InferenceVisitor new InstrumentationValueForMember(node.interfaceTarget!)); } return inferrer.inferSuperPropertyGet( - node, typeContext, node.interfaceTarget); + node, node.name, typeContext, node.interfaceTarget); + } + + @override + ExpressionInferenceResult visitAbstractSuperPropertySet( + AbstractSuperPropertySet node, DartType typeContext) { + DartType receiverType = inferrer.classHierarchy.getTypeAsInstanceOf( + inferrer.thisType!, + inferrer.thisType!.classNode.supertype!.classNode, + inferrer.libraryBuilder.library)!; + + ObjectAccessTarget writeTarget = node.interfaceTarget != null + ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget!, + isPotentiallyNullable: false) + : const ObjectAccessTarget.missing(); + DartType writeContext = inferrer.getSetterType(writeTarget, receiverType); + if (node.interfaceTarget != null) { + writeContext = inferrer.computeTypeFromSuperClass( + node.interfaceTarget!.enclosingClass!, writeContext); + } + ExpressionInferenceResult rhsResult = inferrer + .inferExpression(node.value, writeContext, true, isVoidAllowed: true); + rhsResult = inferrer.ensureAssignableResult(writeContext, rhsResult, + fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType); + Expression rhs = rhsResult.expression; + node.value = rhs..parent = node; + return new ExpressionInferenceResult(rhsResult.inferredType, node); } @override @@ -7158,6 +7215,46 @@ class PropertyForInVariable implements ForInVariable { } } +class AbstractSuperPropertyForInVariable implements ForInVariable { + final AbstractSuperPropertySet superPropertySet; + + DartType? _writeType; + + AbstractSuperPropertyForInVariable(this.superPropertySet); + + @override + DartType computeElementType(TypeInferrerImpl inferrer) { + DartType receiverType = inferrer.thisType!; + ObjectAccessTarget writeTarget = inferrer.findInterfaceMember( + receiverType, superPropertySet.name, superPropertySet.fileOffset, + callSiteAccessKind: CallSiteAccessKind.setterInvocation, + instrumented: true); + if (writeTarget.isInstanceMember || writeTarget.isObjectMember) { + superPropertySet.interfaceTarget = writeTarget.member; + } + return _writeType = inferrer.getSetterType(writeTarget, receiverType); + } + + @override + Expression inferAssignment(TypeInferrerImpl inferrer, DartType rhsType) { + Expression rhs = inferrer.ensureAssignable( + inferrer.computeGreatestClosure(_writeType!), + rhsType, + superPropertySet.value, + errorTemplate: templateForInLoopElementTypeNotAssignable, + nullabilityErrorTemplate: + templateForInLoopElementTypeNotAssignableNullability, + nullabilityPartErrorTemplate: + templateForInLoopElementTypeNotAssignablePartNullability, + isVoidAllowed: true); + superPropertySet.value = rhs..parent = superPropertySet; + ExpressionInferenceResult result = inferrer.inferExpression( + superPropertySet, const UnknownType(), !inferrer.isTopLevel, + isVoidAllowed: true); + return result.expression; + } +} + class SuperPropertyForInVariable implements ForInVariable { final SuperPropertySet superPropertySet; diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart index 979bf9dd504..bb6d2eee178 100644 --- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart +++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart @@ -4132,16 +4132,16 @@ class TypeInferrerImpl implements TypeInferrer { /// Performs the core type inference algorithm for super method invocations. ExpressionInferenceResult inferSuperMethodInvocation( - SuperMethodInvocation expression, + Expression expression, + Name methodName, + ArgumentsImpl arguments, DartType typeContext, Procedure? procedure) { + int fileOffset = expression.fileOffset; ObjectAccessTarget target = procedure != null ? new ObjectAccessTarget.interfaceMember(procedure, isPotentiallyNullable: false) : const ObjectAccessTarget.missing(); - int fileOffset = expression.fileOffset; - Name methodName = expression.name; - ArgumentsImpl arguments = expression.arguments as ArgumentsImpl; DartType receiverType = thisType!; bool isSpecialCasedBinaryOperator = isSpecialCasedBinaryOperatorForReceiverType(target, receiverType); @@ -4155,7 +4155,7 @@ class TypeInferrerImpl implements TypeInferrer { as FunctionType; } if (isNonNullableByDefault && - expression.name == equalsName && + methodName == equalsName && functionType.positionalParameters.length == 1) { // operator == always allows nullable arguments. functionType = new FunctionType([ @@ -4200,7 +4200,7 @@ class TypeInferrerImpl implements TypeInferrer { /// Performs the core type inference algorithm for super property get. ExpressionInferenceResult inferSuperPropertyGet( - SuperPropertyGet expression, DartType typeContext, Member? member) { + Expression expression, Name name, DartType typeContext, Member? member) { ObjectAccessTarget readTarget = member != null ? new ObjectAccessTarget.interfaceMember(member, isPotentiallyNullable: false) @@ -4215,7 +4215,7 @@ class TypeInferrerImpl implements TypeInferrer { return instantiateTearOff(inferredType, typeContext, expression); } flowAnalysis.thisOrSuperPropertyGet( - expression, expression.name.text, member, inferredType); + expression, name.text, member, inferredType); return new ExpressionInferenceResult(inferredType, expression); } diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md index 63f765a3196..25388c5c9a2 100644 --- a/pkg/kernel/binary.md +++ b/pkg/kernel/binary.md @@ -147,7 +147,7 @@ type CanonicalName { type ComponentFile { UInt32 magic = 0x90ABCDEF; - UInt32 formatVersion = 80; + UInt32 formatVersion = 81; Byte[10] shortSdkHash; List problemsAsJson; // Described in problems.md. Library[] libraries; @@ -598,6 +598,23 @@ type SpecializedVariableSet extends Expression { // Equivalent to VariableSet with index N. } +type AbstractSuperPropertyGet extends Expression { + Byte tag = 22; + FileOffset fileOffset; + Name name; + MemberReference interfaceTarget; // May be NullReference. + MemberReference interfaceTargetOrigin; // May be NullReference. +} + +type AbstractSuperPropertySet extends Expression { + Byte tag = 23; + FileOffset fileOffset; + Name name; + Expression value; + MemberReference interfaceTarget; // May be NullReference. + MemberReference interfaceTargetOrigin; // May be NullReference. +} + type SuperPropertyGet extends Expression { Byte tag = 24; FileOffset fileOffset; @@ -820,6 +837,15 @@ type EqualsCall extends Expression { MemberReference interfaceTargetOrigin; // May be NullReference. } +type AbstractSuperMethodInvocation extends Expression { + Byte tag = 28; + FileOffset fileOffset; + Name name; + Arguments arguments; + MemberReference interfaceTarget; // May be NullReference. + MemberReference interfaceTargetOrigin; // May be NullReference. +} + type SuperMethodInvocation extends Expression { Byte tag = 29; FileOffset fileOffset; diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart index 78972bc8874..5f049a00069 100644 --- a/pkg/kernel/lib/ast.dart +++ b/pkg/kernel/lib/ast.dart @@ -4772,6 +4772,99 @@ class InstanceSet extends Expression { } } +/// Expression of form `super.foo` occurring in a mixin declaration. +/// +/// In this setting, the target is looked up on the types in the mixin 'on' +/// clause and are therefore not necessary the runtime targets of the read. An +/// [AbstractSuperPropertyGet] must be converted into a [SuperPropertyGet] to +/// statically bind the target. +/// +/// For instance +/// +/// abstract class Interface { +/// get getter; +/// } +/// mixin Mixin on Interface { +/// get getter { +/// // This is an [AbstractSuperPropertyGet] with interface target +/// // `Interface.getter`. +/// return super.getter; +/// } +/// } +/// class Super implements Interface { +/// // This is the target when `Mixin` is applied to `Class`. +/// get getter => 42; +/// } +/// class Class extends Super with Mixin {} +/// +/// This may invoke a getter, read a field, or tear off a method. +class AbstractSuperPropertyGet extends Expression { + Name name; + + Reference? interfaceTargetReference; + + AbstractSuperPropertyGet(Name name, [Member? interfaceTarget]) + : this.byReference(name, getMemberReferenceGetter(interfaceTarget)); + + AbstractSuperPropertyGet.byReference( + this.name, this.interfaceTargetReference); + + Member? get interfaceTarget => interfaceTargetReference?.asMember; + + void set interfaceTarget(Member? member) { + interfaceTargetReference = getMemberReferenceGetter(member); + } + + @override + DartType getStaticTypeInternal(StaticTypeContext context) { + Member? interfaceTarget = this.interfaceTarget; + if (interfaceTarget == null) { + // TODO(johnniwinther): SuperPropertyGet without a target should be + // replaced by invalid expressions. + return const DynamicType(); + } + Class declaringClass = interfaceTarget.enclosingClass!; + if (declaringClass.typeParameters.isEmpty) { + return interfaceTarget.getterType; + } + List? receiverArguments = context.typeEnvironment + .getTypeArgumentsAsInstanceOf(context.thisType!, declaringClass); + return Substitution.fromPairs( + declaringClass.typeParameters, receiverArguments!) + .substituteType(interfaceTarget.getterType); + } + + @override + R accept(ExpressionVisitor v) => v.visitAbstractSuperPropertyGet(this); + + @override + R accept1(ExpressionVisitor1 v, A arg) => + v.visitAbstractSuperPropertyGet(this, arg); + + @override + void visitChildren(Visitor v) { + interfaceTarget?.acceptReference(v); + name.accept(v); + } + + @override + void transformChildren(Transformer v) {} + + @override + void transformOrRemoveChildren(RemovingTransformer v) {} + + @override + String toString() { + return "AbstractSuperPropertyGet(${toStringInternal()})"; + } + + @override + void toTextInternal(AstPrinter printer) { + printer.write('super.{abstract}'); + printer.writeInterfaceMemberName(interfaceTargetReference, name); + } +} + /// Expression of form `super.field`. /// /// This may invoke a getter, read a field, or tear off a method. @@ -4841,6 +4934,103 @@ class SuperPropertyGet extends Expression { } } +/// Expression of form `super.foo = x` occurring in a mixin declaration. +/// +/// In this setting, the target is looked up on the types in the mixin 'on' +/// clause and are therefore not necessary the runtime targets of the +/// assignment. An [AbstractSuperPropertySet] must be converted into a +/// [SuperPropertySet] to statically bind the target. +/// +/// For instance +/// +/// abstract class Interface { +/// void set setter(value); +/// } +/// mixin Mixin on Interface { +/// void set setter(value) { +/// // This is an [AbstractSuperPropertySet] with interface target +/// // `Interface.setter`. +/// super.setter = value; +/// } +/// } +/// class Super implements Interface { +/// // This is the target when `Mixin` is applied to `Class`. +/// void set setter(value) {} +/// } +/// class Class extends Super with Mixin {} +/// +/// This may invoke a setter or assign a field. +class AbstractSuperPropertySet extends Expression { + Name name; + Expression value; + + Reference? interfaceTargetReference; + + AbstractSuperPropertySet(Name name, Expression value, Member? interfaceTarget) + : this.byReference( + name, value, getMemberReferenceSetter(interfaceTarget)); + + AbstractSuperPropertySet.byReference( + this.name, this.value, this.interfaceTargetReference) { + value.parent = this; + } + + Member? get interfaceTarget => interfaceTargetReference?.asMember; + + void set interfaceTarget(Member? member) { + interfaceTargetReference = getMemberReferenceSetter(member); + } + + @override + DartType getStaticTypeInternal(StaticTypeContext context) => + value.getStaticType(context); + + @override + R accept(ExpressionVisitor v) => v.visitAbstractSuperPropertySet(this); + + @override + R accept1(ExpressionVisitor1 v, A arg) => + v.visitAbstractSuperPropertySet(this, arg); + + @override + void visitChildren(Visitor v) { + interfaceTarget?.acceptReference(v); + name.accept(v); + value.accept(v); + } + + @override + void transformChildren(Transformer v) { + // ignore: unnecessary_null_comparison + if (value != null) { + value = v.transform(value); + value.parent = this; + } + } + + @override + void transformOrRemoveChildren(RemovingTransformer v) { + // ignore: unnecessary_null_comparison + if (value != null) { + value = v.transform(value); + value.parent = this; + } + } + + @override + String toString() { + return "AbstractSuperPropertySet(${toStringInternal()})"; + } + + @override + void toTextInternal(AstPrinter printer) { + printer.write('super.{abstract}'); + printer.writeInterfaceMemberName(interfaceTargetReference, name); + printer.write(' = '); + printer.writeExpression(value); + } +} + /// Expression of form `super.field = value`. /// /// This may invoke a setter or assign a field. @@ -6158,6 +6348,121 @@ class EqualsCall extends Expression { } } +/// Expression of form `super.foo(x)` occurring in a mixin declaration. +/// +/// In this setting, the target is looked up on the types in the mixin 'on' +/// clause and are therefore not necessary the runtime targets of the +/// invocation. An [AbstractSuperMethodInvocation] must be converted into +/// a [SuperMethodInvocation] to statically bind the target. +/// +/// For instance +/// +/// abstract class Interface { +/// void method(); +/// } +/// mixin Mixin on Interface { +/// void method() { +/// // This is an [AbstractSuperMethodInvocation] with interface target +/// // `Interface.method`. +/// super.method(); // This targets Super.method. +/// } +/// } +/// class Super implements Interface { +/// // This is the target when `Mixin` is applied to `Class`. +/// void method() {} +/// } +/// class Class extends Super with Mixin {} +/// +class AbstractSuperMethodInvocation extends InvocationExpression { + @override + Name name; + + @override + Arguments arguments; + + Reference? interfaceTargetReference; + + AbstractSuperMethodInvocation(Name name, Arguments arguments, + [Procedure? interfaceTarget]) + : this.byReference( + name, + arguments, + // An invocation doesn't refer to the setter. + getMemberReferenceGetter(interfaceTarget)); + + AbstractSuperMethodInvocation.byReference( + this.name, this.arguments, this.interfaceTargetReference) { + arguments.parent = this; + } + + Procedure? get interfaceTarget => interfaceTargetReference?.asProcedure; + + void set interfaceTarget(Procedure? target) { + // An invocation doesn't refer to the setter. + interfaceTargetReference = getMemberReferenceGetter(target); + } + + @override + DartType getStaticTypeInternal(StaticTypeContext context) { + Procedure? interfaceTarget = this.interfaceTarget; + if (interfaceTarget == null) return const DynamicType(); + Class superclass = interfaceTarget.enclosingClass!; + List? receiverTypeArguments = context.typeEnvironment + .getTypeArgumentsAsInstanceOf(context.thisType!, superclass); + DartType returnType = Substitution.fromPairs( + superclass.typeParameters, receiverTypeArguments!) + .substituteType(interfaceTarget.function.returnType); + return Substitution.fromPairs( + interfaceTarget.function.typeParameters, arguments.types) + .substituteType(returnType); + } + + @override + R accept(ExpressionVisitor v) => + v.visitAbstractSuperMethodInvocation(this); + + @override + R accept1(ExpressionVisitor1 v, A arg) => + v.visitAbstractSuperMethodInvocation(this, arg); + + @override + void visitChildren(Visitor v) { + interfaceTarget?.acceptReference(v); + name.accept(v); + arguments.accept(v); + } + + @override + void transformChildren(Transformer v) { + // ignore: unnecessary_null_comparison + if (arguments != null) { + arguments = v.transform(arguments); + arguments.parent = this; + } + } + + @override + void transformOrRemoveChildren(RemovingTransformer v) { + // ignore: unnecessary_null_comparison + if (arguments != null) { + arguments = v.transform(arguments); + arguments.parent = this; + } + } + + @override + String toString() { + return "AbstractSuperMethodInvocation(${toStringInternal()})"; + } + + @override + void toTextInternal(AstPrinter printer) { + printer.write('super.{abstract}'); + printer.writeInterfaceMemberName(interfaceTargetReference, name); + printer.writeArguments(arguments); + } +} + /// Expression of form `super.foo(x)`. /// /// The provided arguments might not match the parameters of the target. diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart index 9df6792ab5f..d2a39f116b6 100644 --- a/pkg/kernel/lib/binary/ast_from_binary.dart +++ b/pkg/kernel/lib/binary/ast_from_binary.dart @@ -2001,6 +2001,10 @@ class BinaryBuilder { return _readInstanceSet(); case Tag.DynamicSet: return _readDynamicSet(); + case Tag.AbstractSuperPropertyGet: + return _readAbstractSuperPropertyGet(); + case Tag.AbstractSuperPropertySet: + return _readAbstractSuperPropertySet(); case Tag.SuperPropertyGet: return _readSuperPropertyGet(); case Tag.SuperPropertySet: @@ -2033,6 +2037,8 @@ class BinaryBuilder { return _readEqualsNull(); case Tag.EqualsCall: return _readEqualsCall(); + case Tag.AbstractSuperMethodInvocation: + return _readAbstractSuperMethodInvocation(); case Tag.SuperMethodInvocation: return _readSuperMethodInvocation(); case Tag.StaticInvocation: @@ -2209,6 +2215,22 @@ class BinaryBuilder { ..fileOffset = offset; } + Expression _readAbstractSuperPropertyGet() { + int offset = readOffset(); + addTransformerFlag(TransformerFlag.superCalls); + return new AbstractSuperPropertyGet.byReference( + readName(), readNullableInstanceMemberReference()) + ..fileOffset = offset; + } + + Expression _readAbstractSuperPropertySet() { + int offset = readOffset(); + addTransformerFlag(TransformerFlag.superCalls); + return new AbstractSuperPropertySet.byReference( + readName(), readExpression(), readNullableInstanceMemberReference()) + ..fileOffset = offset; + } + Expression _readSuperPropertyGet() { int offset = readOffset(); addTransformerFlag(TransformerFlag.superCalls); @@ -2347,6 +2369,14 @@ class BinaryBuilder { ..fileOffset = offset; } + Expression _readAbstractSuperMethodInvocation() { + int offset = readOffset(); + addTransformerFlag(TransformerFlag.superCalls); + return new AbstractSuperMethodInvocation.byReference( + readName(), readArguments(), readNullableInstanceMemberReference()) + ..fileOffset = offset; + } + Expression _readSuperMethodInvocation() { int offset = readOffset(); addTransformerFlag(TransformerFlag.superCalls); diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart index 1f678e9dda1..dab017c1dba 100644 --- a/pkg/kernel/lib/binary/ast_to_binary.dart +++ b/pkg/kernel/lib/binary/ast_to_binary.dart @@ -1578,6 +1578,23 @@ class BinaryPrinter implements Visitor, BinarySink { writeNonNullInstanceMemberReference(node.interfaceTargetReference); } + @override + void visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) { + writeByte(Tag.AbstractSuperPropertyGet); + writeOffset(node.fileOffset); + writeName(node.name); + writeNullAllowedInstanceMemberReference(node.interfaceTargetReference); + } + + @override + void visitAbstractSuperPropertySet(AbstractSuperPropertySet node) { + writeByte(Tag.AbstractSuperPropertySet); + writeOffset(node.fileOffset); + writeName(node.name); + writeNode(node.value); + writeNullAllowedInstanceMemberReference(node.interfaceTargetReference); + } + @override void visitSuperPropertyGet(SuperPropertyGet node) { writeByte(Tag.SuperPropertyGet); @@ -1717,6 +1734,15 @@ class BinaryPrinter implements Visitor, BinarySink { writeDartType(node.functionType); } + @override + void visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) { + writeByte(Tag.AbstractSuperMethodInvocation); + writeOffset(node.fileOffset); + writeName(node.name); + writeArgumentsNode(node.arguments); + writeNullAllowedInstanceMemberReference(node.interfaceTargetReference); + } + @override void visitSuperMethodInvocation(SuperMethodInvocation node) { writeByte(Tag.SuperMethodInvocation); diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart index aed4155fed5..b0a13a0214b 100644 --- a/pkg/kernel/lib/binary/tag.dart +++ b/pkg/kernel/lib/binary/tag.dart @@ -37,10 +37,13 @@ class Tag { static const int InvalidExpression = 19; static const int VariableGet = 20; static const int VariableSet = 21; + static const int AbstractSuperPropertyGet = 22; + static const int AbstractSuperPropertySet = 23; static const int SuperPropertyGet = 24; static const int SuperPropertySet = 25; static const int StaticGet = 26; static const int StaticSet = 27; + static const int AbstractSuperMethodInvocation = 28; static const int SuperMethodInvocation = 29; static const int StaticInvocation = 30; static const int ConstructorInvocation = 31; @@ -176,7 +179,7 @@ class Tag { /// Internal version of kernel binary format. /// Bump it when making incompatible changes in kernel binaries. /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md. - static const int BinaryFormatVersion = 80; + static const int BinaryFormatVersion = 81; } abstract class ConstantTag { diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart index c69fe096e45..348ff655fc4 100644 --- a/pkg/kernel/lib/clone.dart +++ b/pkg/kernel/lib/clone.dart @@ -175,6 +175,18 @@ class CloneVisitorNotMembers implements TreeVisitor { return new VariableSet(getVariableClone(node.variable)!, clone(node.value)); } + @override + TreeNode visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) { + return new AbstractSuperPropertyGet.byReference( + node.name, node.interfaceTargetReference); + } + + @override + TreeNode visitAbstractSuperPropertySet(AbstractSuperPropertySet node) { + return new AbstractSuperPropertySet.byReference( + node.name, clone(node.value), node.interfaceTargetReference); + } + @override TreeNode visitSuperPropertyGet(SuperPropertyGet node) { return new SuperPropertyGet.byReference( @@ -197,6 +209,13 @@ class CloneVisitorNotMembers implements TreeVisitor { return new StaticSet.byReference(node.targetReference, clone(node.value)); } + @override + TreeNode visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node) { + return new AbstractSuperMethodInvocation.byReference( + node.name, clone(node.arguments), node.interfaceTargetReference); + } + @override TreeNode visitSuperMethodInvocation(SuperMethodInvocation node) { return new SuperMethodInvocation.byReference( diff --git a/pkg/kernel/lib/src/coverage.dart b/pkg/kernel/lib/src/coverage.dart index 35a56929b5e..553e22f62e1 100644 --- a/pkg/kernel/lib/src/coverage.dart +++ b/pkg/kernel/lib/src/coverage.dart @@ -185,12 +185,24 @@ class CoverageVisitor implements Visitor { node.visitChildren(this); } + @override + void visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) { + visited.add(ExpressionKind.AbstractSuperPropertyGet); + node.visitChildren(this); + } + @override void visitSuperPropertyGet(SuperPropertyGet node) { visited.add(ExpressionKind.SuperPropertyGet); node.visitChildren(this); } + @override + void visitAbstractSuperPropertySet(AbstractSuperPropertySet node) { + visited.add(ExpressionKind.AbstractSuperPropertySet); + node.visitChildren(this); + } + @override void visitSuperPropertySet(SuperPropertySet node) { visited.add(ExpressionKind.SuperPropertySet); @@ -245,6 +257,12 @@ class CoverageVisitor implements Visitor { node.visitChildren(this); } + @override + void visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) { + visited.add(ExpressionKind.AbstractSuperMethodInvocation); + node.visitChildren(this); + } + @override void visitSuperMethodInvocation(SuperMethodInvocation node) { visited.add(ExpressionKind.SuperMethodInvocation); @@ -1009,6 +1027,9 @@ enum InitializerKind { } enum ExpressionKind { + AbstractSuperMethodInvocation, + AbstractSuperPropertyGet, + AbstractSuperPropertySet, AsExpression, AwaitExpression, BlockExpression, diff --git a/pkg/kernel/lib/src/equivalence.dart b/pkg/kernel/lib/src/equivalence.dart index 840f85bc831..015d0214d28 100644 --- a/pkg/kernel/lib/src/equivalence.dart +++ b/pkg/kernel/lib/src/equivalence.dart @@ -185,11 +185,23 @@ class EquivalenceVisitor implements Visitor1 { return strategy.checkInstanceSet(this, node, other); } + @override + bool visitAbstractSuperPropertyGet( + AbstractSuperPropertyGet node, Node other) { + return strategy.checkAbstractSuperPropertyGet(this, node, other); + } + @override bool visitSuperPropertyGet(SuperPropertyGet node, Node other) { return strategy.checkSuperPropertyGet(this, node, other); } + @override + bool visitAbstractSuperPropertySet( + AbstractSuperPropertySet node, Node other) { + return strategy.checkAbstractSuperPropertySet(this, node, other); + } + @override bool visitSuperPropertySet(SuperPropertySet node, Node other) { return strategy.checkSuperPropertySet(this, node, other); @@ -236,6 +248,12 @@ class EquivalenceVisitor implements Visitor1 { return strategy.checkLocalFunctionInvocation(this, node, other); } + @override + bool visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node, Node other) { + return strategy.checkAbstractSuperMethodInvocation(this, node, other); + } + @override bool visitSuperMethodInvocation(SuperMethodInvocation node, Node other) { return strategy.checkSuperMethodInvocation(this, node, other); @@ -2270,6 +2288,27 @@ class EquivalenceStrategy { return result; } + bool checkAbstractSuperPropertyGet(EquivalenceVisitor visitor, + AbstractSuperPropertyGet? node, Object? other) { + if (identical(node, other)) return true; + if (node is! AbstractSuperPropertyGet) return false; + if (other is! AbstractSuperPropertyGet) return false; + visitor.pushNodeState(node, other); + bool result = true; + if (!checkAbstractSuperPropertyGet_name(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperPropertyGet_interfaceTargetReference( + visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperPropertyGet_fileOffset(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + visitor.popState(); + return result; + } + bool checkSuperPropertyGet( EquivalenceVisitor visitor, SuperPropertyGet? node, Object? other) { if (identical(node, other)) return true; @@ -2290,6 +2329,30 @@ class EquivalenceStrategy { return result; } + bool checkAbstractSuperPropertySet(EquivalenceVisitor visitor, + AbstractSuperPropertySet? node, Object? other) { + if (identical(node, other)) return true; + if (node is! AbstractSuperPropertySet) return false; + if (other is! AbstractSuperPropertySet) return false; + visitor.pushNodeState(node, other); + bool result = true; + if (!checkAbstractSuperPropertySet_name(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperPropertySet_value(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperPropertySet_interfaceTargetReference( + visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperPropertySet_fileOffset(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + visitor.popState(); + return result; + } + bool checkSuperPropertySet( EquivalenceVisitor visitor, SuperPropertySet? node, Object? other) { if (identical(node, other)) return true; @@ -2514,6 +2577,30 @@ class EquivalenceStrategy { return result; } + bool checkAbstractSuperMethodInvocation(EquivalenceVisitor visitor, + AbstractSuperMethodInvocation? node, Object? other) { + if (identical(node, other)) return true; + if (node is! AbstractSuperMethodInvocation) return false; + if (other is! AbstractSuperMethodInvocation) return false; + visitor.pushNodeState(node, other); + bool result = true; + if (!checkAbstractSuperMethodInvocation_name(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperMethodInvocation_arguments(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperMethodInvocation_interfaceTargetReference( + visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + if (!checkAbstractSuperMethodInvocation_fileOffset(visitor, node, other)) { + result = visitor.resultOnInequivalence; + } + visitor.popState(); + return result; + } + bool checkSuperMethodInvocation( EquivalenceVisitor visitor, SuperMethodInvocation? node, Object? other) { if (identical(node, other)) return true; @@ -5604,6 +5691,24 @@ class EquivalenceStrategy { return checkExpression_fileOffset(visitor, node, other); } + bool checkAbstractSuperPropertyGet_name(EquivalenceVisitor visitor, + AbstractSuperPropertyGet node, AbstractSuperPropertyGet other) { + return visitor.checkNodes(node.name, other.name, 'name'); + } + + bool checkAbstractSuperPropertyGet_interfaceTargetReference( + EquivalenceVisitor visitor, + AbstractSuperPropertyGet node, + AbstractSuperPropertyGet other) { + return visitor.checkReferences(node.interfaceTargetReference, + other.interfaceTargetReference, 'interfaceTargetReference'); + } + + bool checkAbstractSuperPropertyGet_fileOffset(EquivalenceVisitor visitor, + AbstractSuperPropertyGet node, AbstractSuperPropertyGet other) { + return checkExpression_fileOffset(visitor, node, other); + } + bool checkSuperPropertyGet_name(EquivalenceVisitor visitor, SuperPropertyGet node, SuperPropertyGet other) { return visitor.checkNodes(node.name, other.name, 'name'); @@ -5622,6 +5727,29 @@ class EquivalenceStrategy { return checkExpression_fileOffset(visitor, node, other); } + bool checkAbstractSuperPropertySet_name(EquivalenceVisitor visitor, + AbstractSuperPropertySet node, AbstractSuperPropertySet other) { + return visitor.checkNodes(node.name, other.name, 'name'); + } + + bool checkAbstractSuperPropertySet_value(EquivalenceVisitor visitor, + AbstractSuperPropertySet node, AbstractSuperPropertySet other) { + return visitor.checkNodes(node.value, other.value, 'value'); + } + + bool checkAbstractSuperPropertySet_interfaceTargetReference( + EquivalenceVisitor visitor, + AbstractSuperPropertySet node, + AbstractSuperPropertySet other) { + return visitor.checkReferences(node.interfaceTargetReference, + other.interfaceTargetReference, 'interfaceTargetReference'); + } + + bool checkAbstractSuperPropertySet_fileOffset(EquivalenceVisitor visitor, + AbstractSuperPropertySet node, AbstractSuperPropertySet other) { + return checkExpression_fileOffset(visitor, node, other); + } + bool checkSuperPropertySet_name(EquivalenceVisitor visitor, SuperPropertySet node, SuperPropertySet other) { return visitor.checkNodes(node.name, other.name, 'name'); @@ -5853,6 +5981,29 @@ class EquivalenceStrategy { return checkInvocationExpression_fileOffset(visitor, node, other); } + bool checkAbstractSuperMethodInvocation_name(EquivalenceVisitor visitor, + AbstractSuperMethodInvocation node, AbstractSuperMethodInvocation other) { + return visitor.checkNodes(node.name, other.name, 'name'); + } + + bool checkAbstractSuperMethodInvocation_arguments(EquivalenceVisitor visitor, + AbstractSuperMethodInvocation node, AbstractSuperMethodInvocation other) { + return visitor.checkNodes(node.arguments, other.arguments, 'arguments'); + } + + bool checkAbstractSuperMethodInvocation_interfaceTargetReference( + EquivalenceVisitor visitor, + AbstractSuperMethodInvocation node, + AbstractSuperMethodInvocation other) { + return visitor.checkReferences(node.interfaceTargetReference, + other.interfaceTargetReference, 'interfaceTargetReference'); + } + + bool checkAbstractSuperMethodInvocation_fileOffset(EquivalenceVisitor visitor, + AbstractSuperMethodInvocation node, AbstractSuperMethodInvocation other) { + return checkInvocationExpression_fileOffset(visitor, node, other); + } + bool checkSuperMethodInvocation_name(EquivalenceVisitor visitor, SuperMethodInvocation node, SuperMethodInvocation other) { return visitor.checkNodes(node.name, other.name, 'name'); diff --git a/pkg/kernel/lib/src/node_creator.dart b/pkg/kernel/lib/src/node_creator.dart index 8c0337d4cb8..d51a1bb555e 100644 --- a/pkg/kernel/lib/src/node_creator.dart +++ b/pkg/kernel/lib/src/node_creator.dart @@ -859,6 +859,14 @@ class NodeCreator { ]); case ExpressionKind.StringLiteral: return StringLiteral('foo'); + case ExpressionKind.AbstractSuperMethodInvocation: + return _createOneOf(_pendingExpressions, kind, index, [ + () => AbstractSuperMethodInvocation(_createName(), _createArguments()) + ..fileOffset = _needFileOffset(), + () => AbstractSuperMethodInvocation( + _createName(), _createArguments(), _needProcedure()) + ..fileOffset = _needFileOffset(), + ]); case ExpressionKind.SuperMethodInvocation: return _createOneOf(_pendingExpressions, kind, index, [ () => SuperMethodInvocation(_createName(), _createArguments()) @@ -867,6 +875,22 @@ class NodeCreator { _createName(), _createArguments(), _needProcedure()) ..fileOffset = _needFileOffset(), ]); + case ExpressionKind.AbstractSuperPropertyGet: + return _createOneOf(_pendingExpressions, kind, index, [ + () => AbstractSuperPropertyGet(_createName()) + ..fileOffset = _needFileOffset(), + () => AbstractSuperPropertyGet(_createName(), _needField()) + ..fileOffset = _needFileOffset(), + ]); + case ExpressionKind.AbstractSuperPropertySet: + return _createOneOf(_pendingExpressions, kind, index, [ + () => + AbstractSuperPropertySet(_createName(), _createExpression(), null) + ..fileOffset = _needFileOffset(), + () => AbstractSuperPropertySet( + _createName(), _createExpression(), _needField()) + ..fileOffset = _needFileOffset(), + ]); case ExpressionKind.SuperPropertyGet: return _createOneOf(_pendingExpressions, kind, index, [ () => SuperPropertyGet(_createName())..fileOffset = _needFileOffset(), diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart index 542324eb634..722da3d6b0c 100644 --- a/pkg/kernel/lib/text/ast_to_text.dart +++ b/pkg/kernel/lib/text/ast_to_text.dart @@ -3009,6 +3009,10 @@ class Precedence implements ExpressionVisitor { @override int visitEqualsNull(EqualsNull node) => EQUALITY; + @override + int visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) => + CALLEE; + @override int visitSuperMethodInvocation(SuperMethodInvocation node) => CALLEE; @@ -3103,6 +3107,13 @@ class Precedence implements ExpressionVisitor { @override int visitFunctionTearOff(FunctionTearOff node) => PRIMARY; + @override + int visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) => PRIMARY; + + @override + int visitAbstractSuperPropertySet(AbstractSuperPropertySet node) => + EXPRESSION; + @override int visitSuperPropertyGet(SuperPropertyGet node) => PRIMARY; diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart index 293015daef6..6e444994a65 100644 --- a/pkg/kernel/lib/type_checker.dart +++ b/pkg/kernel/lib/type_checker.dart @@ -752,6 +752,19 @@ class TypeCheckingVisitor return environment.coreTypes.stringLegacyRawType; } + @override + DartType visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node) { + Member? target = node.interfaceTarget; + if (target == null) { + checkUnresolvedInvocation(currentThisType!, node); + return handleDynamicCall(currentThisType!, node.arguments); + } else { + return handleCall(node.arguments, target.superGetterType, + receiver: getSuperReceiverType(target)); + } + } + @override DartType visitSuperMethodInvocation(SuperMethodInvocation node) { Member? target = node.interfaceTarget; @@ -764,6 +777,32 @@ class TypeCheckingVisitor } } + @override + DartType visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) { + Member? target = node.interfaceTarget; + if (target == null) { + checkUnresolvedInvocation(currentThisType!, node); + return const DynamicType(); + } else { + Substitution receiver = getSuperReceiverType(target); + return receiver.substituteType(target.superGetterType); + } + } + + @override + DartType visitAbstractSuperPropertySet(AbstractSuperPropertySet node) { + Member? target = node.interfaceTarget; + DartType value = visitExpression(node.value); + if (target != null) { + Substitution receiver = getSuperReceiverType(target); + checkAssignable(node.value, value, + receiver.substituteType(target.superSetterType, contravariant: true)); + } else { + checkUnresolvedInvocation(currentThisType!, node); + } + return value; + } + @override DartType visitSuperPropertyGet(SuperPropertyGet node) { Member? target = node.interfaceTarget; diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart index d88c2a9dfff..64f3accd32f 100644 --- a/pkg/kernel/lib/visitor.dart +++ b/pkg/kernel/lib/visitor.dart @@ -23,6 +23,10 @@ abstract class ExpressionVisitor { R visitInstanceGet(InstanceGet node) => defaultExpression(node); R visitInstanceSet(InstanceSet node) => defaultExpression(node); R visitInstanceTearOff(InstanceTearOff node) => defaultExpression(node); + R visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) => + defaultExpression(node); + R visitAbstractSuperPropertySet(AbstractSuperPropertySet node) => + defaultExpression(node); R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node); R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node); R visitStaticGet(StaticGet node) => defaultExpression(node); @@ -37,6 +41,8 @@ abstract class ExpressionVisitor { defaultExpression(node); R visitEqualsNull(EqualsNull node) => defaultExpression(node); R visitEqualsCall(EqualsCall node) => defaultExpression(node); + R visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) => + defaultExpression(node); R visitSuperMethodInvocation(SuperMethodInvocation node) => defaultExpression(node); R visitStaticInvocation(StaticInvocation node) => defaultExpression(node); @@ -209,6 +215,12 @@ abstract class TreeVisitor @override R visitInstanceTearOff(InstanceTearOff node) => defaultExpression(node); @override + R visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) => + defaultExpression(node); + @override + R visitAbstractSuperPropertySet(AbstractSuperPropertySet node) => + defaultExpression(node); + @override R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node); @override R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node); @@ -235,6 +247,9 @@ abstract class TreeVisitor @override R visitEqualsCall(EqualsCall node) => defaultExpression(node); @override + R visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) => + defaultExpression(node); + @override R visitSuperMethodInvocation(SuperMethodInvocation node) => defaultExpression(node); @override @@ -457,6 +472,12 @@ abstract class TreeVisitor1 R visitInstanceTearOff(InstanceTearOff node, A arg) => defaultExpression(node, arg); @override + R visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node, A arg) => + defaultExpression(node, arg); + @override + R visitAbstractSuperPropertySet(AbstractSuperPropertySet node, A arg) => + defaultExpression(node, arg); + @override R visitSuperPropertyGet(SuperPropertyGet node, A arg) => defaultExpression(node, arg); @override @@ -489,6 +510,10 @@ abstract class TreeVisitor1 @override R visitEqualsCall(EqualsCall node, A arg) => defaultExpression(node, arg); @override + R visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node, A arg) => + defaultExpression(node, arg); + @override R visitSuperMethodInvocation(SuperMethodInvocation node, A arg) => defaultExpression(node, arg); @override @@ -1976,6 +2001,10 @@ abstract class ExpressionVisitor1 { R visitInstanceSet(InstanceSet node, T arg) => defaultExpression(node, arg); R visitInstanceTearOff(InstanceTearOff node, T arg) => defaultExpression(node, arg); + R visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node, T arg) => + defaultExpression(node, arg); + R visitAbstractSuperPropertySet(AbstractSuperPropertySet node, T arg) => + defaultExpression(node, arg); R visitSuperPropertyGet(SuperPropertyGet node, T arg) => defaultExpression(node, arg); R visitSuperPropertySet(SuperPropertySet node, T arg) => @@ -1996,6 +2025,9 @@ abstract class ExpressionVisitor1 { defaultExpression(node, arg); R visitEqualsNull(EqualsNull node, T arg) => defaultExpression(node, arg); R visitEqualsCall(EqualsCall node, T arg) => defaultExpression(node, arg); + R visitAbstractSuperMethodInvocation( + AbstractSuperMethodInvocation node, T arg) => + defaultExpression(node, arg); R visitSuperMethodInvocation(SuperMethodInvocation node, T arg) => defaultExpression(node, arg); R visitStaticInvocation(StaticInvocation node, T arg) => diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc index abfc8a7fbb4..a1f6765cfc5 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc @@ -1172,6 +1172,16 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) { return BuildInstanceSet(position); case kDynamicSet: return BuildDynamicSet(position); + case kAbstractSuperPropertyGet: + // Abstract super property getters must be converted into super property + // getters during mixin transformation. + UNREACHABLE(); + break; + case kAbstractSuperPropertySet: + // Abstract super property setters must be converted into super property + // setters during mixin transformation. + UNREACHABLE(); + break; case kSuperPropertyGet: return BuildSuperPropertyGet(position); case kSuperPropertySet: @@ -1192,6 +1202,11 @@ Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) { return BuildEqualsCall(position); case kEqualsNull: return BuildEqualsNull(position); + case kAbstractSuperMethodInvocation: + // Abstract super method invocations must be converted into super + // method invocations during mixin transformation. + UNREACHABLE(); + break; case kSuperMethodInvocation: return BuildSuperMethodInvocation(position); case kStaticInvocation: diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc index 3a888c48d92..73470298ca8 100644 --- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc +++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc @@ -412,6 +412,16 @@ void KernelFingerprintHelper::CalculateExpressionFingerprint() { BuildHash(ReadNameAsSetterName().Hash()); // read name. CalculateExpressionFingerprint(); // read value. return; + case kAbstractSuperPropertyGet: + // Abstract super property getters must be converted into super property + // getters during mixin transformation. + UNREACHABLE(); + break; + case kAbstractSuperPropertySet: + // Abstract super property setters must be converted into super property + // setters during mixin transformation. + UNREACHABLE(); + break; case kSuperPropertyGet: ReadPosition(); // read position. BuildHash(ReadNameAsGetterName().Hash()); // read name. @@ -474,6 +484,11 @@ void KernelFingerprintHelper::CalculateExpressionFingerprint() { ReadPosition(); // read position. CalculateExpressionFingerprint(); // read expression. return; + case kAbstractSuperMethodInvocation: + // Abstract super method invocations must be converted into super + // method invocations during mixin transformation. + UNREACHABLE(); + break; case kSuperMethodInvocation: ReadPosition(); // read position. BuildHash(ReadNameAsMethodName().Hash()); // read name. diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc index e3008020158..d52cc58fba7 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc @@ -2420,6 +2420,16 @@ void KernelReaderHelper::SkipExpression() { SkipName(); // read name. SkipExpression(); // read value. return; + case kAbstractSuperPropertyGet: + // Abstract super property getters must be converted into super property + // getters during mixin transformation. + UNREACHABLE(); + break; + case kAbstractSuperPropertySet: + // Abstract super property setters must be converted into super property + // setters during mixin transformation. + UNREACHABLE(); + break; case kSuperPropertyGet: ReadPosition(); // read position. SkipName(); // read name. @@ -2482,6 +2492,11 @@ void KernelReaderHelper::SkipExpression() { ReadPosition(); // read position. SkipExpression(); // read expression. return; + case kAbstractSuperMethodInvocation: + // Abstract super method invocations must be converted into super + // method invocations during mixin transformation. + UNREACHABLE(); + break; case kSuperMethodInvocation: ReadPosition(); // read position. SkipName(); // read name. diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc index 89d7660eee8..32821614cdf 100644 --- a/runtime/vm/compiler/frontend/scope_builder.cc +++ b/runtime/vm/compiler/frontend/scope_builder.cc @@ -748,6 +748,16 @@ void ScopeBuilder::VisitExpression() { helper_.SkipName(); // read name. VisitExpression(); // read value. return; + case kAbstractSuperPropertyGet: + // Abstract super property getters must be converted into super property + // getters during mixin transformation. + UNREACHABLE(); + break; + case kAbstractSuperPropertySet: + // Abstract super property setters must be converted into super property + // setters during mixin transformation. + UNREACHABLE(); + break; case kSuperPropertyGet: HandleLoadReceiver(); helper_.ReadPosition(); // read position. @@ -817,6 +827,11 @@ void ScopeBuilder::VisitExpression() { helper_.ReadPosition(); // read position. VisitExpression(); // read expression. return; + case kAbstractSuperMethodInvocation: + // Abstract super method invocations must be converted into super + // method invocations during mixin transformation. + UNREACHABLE(); + break; case kSuperMethodInvocation: HandleLoadReceiver(); helper_.ReadPosition(); // read position. diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h index 6e6972f3b30..96c196d7147 100644 --- a/runtime/vm/kernel_binary.h +++ b/runtime/vm/kernel_binary.h @@ -20,8 +20,8 @@ namespace kernel { static const uint32_t kMagicProgramFile = 0x90ABCDEFu; // Both version numbers are inclusive. -static const uint32_t kMinSupportedKernelFormatVersion = 80; -static const uint32_t kMaxSupportedKernelFormatVersion = 80; +static const uint32_t kMinSupportedKernelFormatVersion = 81; +static const uint32_t kMaxSupportedKernelFormatVersion = 81; // Keep in sync with package:kernel/lib/binary/tag.dart #define KERNEL_TAG_LIST(V) \ @@ -49,10 +49,13 @@ static const uint32_t kMaxSupportedKernelFormatVersion = 80; V(InvalidExpression, 19) \ V(VariableGet, 20) \ V(VariableSet, 21) \ + V(AbstractSuperPropertyGet, 22) \ + V(AbstractSuperPropertySet, 23) \ V(SuperPropertyGet, 24) \ V(SuperPropertySet, 25) \ V(StaticGet, 26) \ V(StaticSet, 27) \ + V(AbstractSuperMethodInvocation, 28) \ V(SuperMethodInvocation, 29) \ V(StaticInvocation, 30) \ V(ConstructorInvocation, 31) \