[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 <alexmarkov@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index e95a0af..506b32d 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -4780,8 +4780,17 @@
   }
 
   @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);
@@ -4794,10 +4803,19 @@
   }
 
   @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
@@ -5404,10 +5422,20 @@
 
   // 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 bd6983c..320a50c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -3772,10 +3772,23 @@
   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 dd68ba0..71ba7f6 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 @@
       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) {
@@ -6149,6 +6151,21 @@
   }
 
   @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) {
     if (node.interfaceTarget != null) {
@@ -6159,8 +6176,22 @@
           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 @@
           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 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 979bf9d..bb6d2ee 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 @@
 
   /// 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 @@
               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 @@
 
   /// 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 @@
       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 63f765a..25388c5 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 80;
+  UInt32 formatVersion = 81;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -598,6 +598,23 @@
   // 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 @@
   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 78972bc..5f049a0 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -4772,6 +4772,99 @@
   }
 }
 
+/// 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<DartType>? receiverArguments = context.typeEnvironment
+        .getTypeArgumentsAsInstanceOf(context.thisType!, declaringClass);
+    return Substitution.fromPairs(
+            declaringClass.typeParameters, receiverArguments!)
+        .substituteType(interfaceTarget.getterType);
+  }
+
+  @override
+  R accept<R>(ExpressionVisitor<R> v) => v.visitAbstractSuperPropertyGet(this);
+
+  @override
+  R accept1<R, A>(ExpressionVisitor1<R, A> 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 @@
   }
 }
 
+/// 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<R>(ExpressionVisitor<R> v) => v.visitAbstractSuperPropertySet(this);
+
+  @override
+  R accept1<R, A>(ExpressionVisitor1<R, A> 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 @@
   }
 }
 
+/// 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<DartType>? 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<R>(ExpressionVisitor<R> v) =>
+      v.visitAbstractSuperMethodInvocation(this);
+
+  @override
+  R accept1<R, A>(ExpressionVisitor1<R, A> 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 9df6792..d2a39f1 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -2001,6 +2001,10 @@
         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 @@
         return _readEqualsNull();
       case Tag.EqualsCall:
         return _readEqualsCall();
+      case Tag.AbstractSuperMethodInvocation:
+        return _readAbstractSuperMethodInvocation();
       case Tag.SuperMethodInvocation:
         return _readSuperMethodInvocation();
       case Tag.StaticInvocation:
@@ -2209,6 +2215,22 @@
       ..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 @@
       ..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 1f678e9..dab017c 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1579,6 +1579,23 @@
   }
 
   @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);
     writeOffset(node.fileOffset);
@@ -1718,6 +1735,15 @@
   }
 
   @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);
     writeOffset(node.fileOffset);
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index aed4155..b0a13a0 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -37,10 +37,13 @@
   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 @@
   /// 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 c69fe09..348ff65 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -176,6 +176,18 @@
   }
 
   @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(
         node.name, node.interfaceTargetReference);
@@ -198,6 +210,13 @@
   }
 
   @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(
         node.name, clone(node.arguments), node.interfaceTargetReference);
diff --git a/pkg/kernel/lib/src/coverage.dart b/pkg/kernel/lib/src/coverage.dart
index 35a5692..553e22f 100644
--- a/pkg/kernel/lib/src/coverage.dart
+++ b/pkg/kernel/lib/src/coverage.dart
@@ -186,12 +186,24 @@
   }
 
   @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);
     node.visitChildren(this);
@@ -246,6 +258,12 @@
   }
 
   @override
+  void visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) {
+    visited.add(ExpressionKind.AbstractSuperMethodInvocation);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
     visited.add(ExpressionKind.SuperMethodInvocation);
     node.visitChildren(this);
@@ -1009,6 +1027,9 @@
 }
 
 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 840f85b..015d021 100644
--- a/pkg/kernel/lib/src/equivalence.dart
+++ b/pkg/kernel/lib/src/equivalence.dart
@@ -186,11 +186,23 @@
   }
 
   @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);
   }
@@ -237,6 +249,12 @@
   }
 
   @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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 8c0337d..d51a1bb 100644
--- a/pkg/kernel/lib/src/node_creator.dart
+++ b/pkg/kernel/lib/src/node_creator.dart
@@ -859,6 +859,14 @@
         ]);
       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 @@
               _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 542324e..722da3d 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -3010,6 +3010,10 @@
   int visitEqualsNull(EqualsNull node) => EQUALITY;
 
   @override
+  int visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) =>
+      CALLEE;
+
+  @override
   int visitSuperMethodInvocation(SuperMethodInvocation node) => CALLEE;
 
   @override
@@ -3104,6 +3108,13 @@
   int visitFunctionTearOff(FunctionTearOff node) => PRIMARY;
 
   @override
+  int visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) => PRIMARY;
+
+  @override
+  int visitAbstractSuperPropertySet(AbstractSuperPropertySet node) =>
+      EXPRESSION;
+
+  @override
   int visitSuperPropertyGet(SuperPropertyGet node) => PRIMARY;
 
   @override
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 293015d..6e44499 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -753,6 +753,19 @@
   }
 
   @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;
     if (target == null) {
@@ -765,6 +778,32 @@
   }
 
   @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;
     if (target == null) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index d88c2a9..64f3acc 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -23,6 +23,10 @@
   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 @@
       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 @@
   @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 @@
   @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 @@
   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 @@
   @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 @@
   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 @@
       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 abfc8a7..a1f6765 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1172,6 +1172,16 @@
       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 @@
       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 3a888c4..7347029 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -412,6 +412,16 @@
       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 @@
       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 e300802..d52cc58 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2420,6 +2420,16 @@
       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 @@
       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 89d7660..3282161 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -748,6 +748,16 @@
       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 @@
       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 6e6972f..96c196d 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,8 +20,8 @@
 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 @@
   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)                                                 \