[vm/kernel] Recognize desugared mixin applications in dart:mirrors
Kernel mixin transformation desugars mixin applications into normal
classes. Mixed-in type is pulled into interfaces list.
However, dart:mirrors needs to know the original mixed-in type of
a mixin application.
This change solves this problem by propagating a 'isTransformedMixinApplication'
attribute of a class through kernel AST, kernel binary and VM objects
into dart:mirrors implementation.
Fixes: https://github.com/dart-lang/sdk/issues/33240
Change-Id: I98ca69294e1ad445402a5ca91d90c30447aabcb2
Reviewed-on: https://dart-review.googlesource.com/56721
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index ac82f5f..822d245 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1281,7 +1281,7 @@
if (_kernel.mixedInType != null) {
_kernelMixins.add(_kernel.mixedInType);
}
- while (supertype.classNode.isSyntheticMixinImplementation) {
+ while (supertype.classNode.isAnonymousMixin) {
var superNode = supertype.classNode;
var substitute = kernel.Substitution.fromSupertype(supertype);
@@ -1855,7 +1855,7 @@
List<ClassElement> get types {
if (_kernelContext != null) {
_types ??= _kernelContext.kernelUnit.classes
- .where((k) => !k.isEnum && !k.isSyntheticMixinImplementation)
+ .where((k) => !k.isEnum && !k.isAnonymousMixin)
.map((k) => new ClassElementImpl.forKernel(this, k))
.toList(growable: false);
}
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index c9b9d93..dde76e85 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -297,7 +297,7 @@
ClassEnvImpl.internal(this.cls, this._constructorMap, this._memberMap,
this._setterMap, this._members);
- bool get isUnnamedMixinApplication => cls.isSyntheticMixinImplementation;
+ bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
/// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'.
ir.Constructor _buildForwardingConstructor(
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index b296f10..a8478d6 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -522,7 +522,7 @@
JS.Statement _emitClassDeclaration(Class c) {
// Mixins are unrolled in _defineClass.
- if (c.isSyntheticMixinImplementation) return null;
+ if (c.isAnonymousMixin) return null;
// If this class is annotated with `@JS`, then there is nothing to emit.
if (findAnnotation(c, isPublicJSAnnotation) != null) return null;
@@ -820,7 +820,7 @@
/// Defines all constructors for this class as ES5 constructors.
List<JS.Statement> _defineConstructors(Class c, JS.Expression className) {
var body = <JS.Statement>[];
- if (c.isSyntheticMixinImplementation || isMixinAliasClass(c)) {
+ if (c.isAnonymousMixin || isMixinAliasClass(c)) {
// We already handled this when we defined the class.
return body;
}
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index dc11518..44a8f0f 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -227,7 +227,7 @@
if (mixedInClass != null) mixins.add(mixedInClass);
var sc = c.superclass;
- for (; sc.isSyntheticMixinImplementation; sc = sc.superclass) {
+ for (; sc.isAnonymousMixin; sc = sc.superclass) {
mixins.add(sc.mixedInClass);
}
return sc;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 81b4f1f..c25088e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -449,8 +449,7 @@
// TODO(ahe, kmillikin): Should always be true?
// pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
// handle that :(
- application.cls.isSyntheticMixinImplementation =
- !isNamedMixinApplication;
+ application.cls.isAnonymousMixin = !isNamedMixinApplication;
addBuilder(fullname, application, charOffset);
supertype =
addNamedType(fullname, applicationTypeArguments, charOffset);
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 5b02dc9..7507777 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -664,7 +664,7 @@
TypeEnvironment env = new TypeEnvironment(coreTypes, hierarchy,
strongMode: target.strongMode);
- if (cls.isSyntheticMixinImplementation) return;
+ if (cls.isAnonymousMixin) return;
if (env.isSubtypeOf(a.asInterfaceType, b.asInterfaceType)) return;
addProblem(
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 58c6532..361dd77 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
@@ -1634,7 +1634,7 @@
Supertype baseType, Supertype mixinSupertype) {
if (mixinSupertype.typeArguments.isEmpty) {
// The supertype constraint isn't generic; it doesn't constrain anything.
- } else if (mixinSupertype.classNode.isSyntheticMixinImplementation) {
+ } else if (mixinSupertype.classNode.isAnonymousMixin) {
// We had a mixin M<X0, ..., Xn> with a superclass constraint of the form
// S0 with M0 where S0 and M0 each possibly have type arguments. That has
// been compiled a named mixin application class of the form
diff --git a/pkg/front_end/test/incremental_utils.dart b/pkg/front_end/test/incremental_utils.dart
index c8480bf..ef4626a 100644
--- a/pkg/front_end/test/incremental_utils.dart
+++ b/pkg/front_end/test/incremental_utils.dart
@@ -33,7 +33,7 @@
int empty = 0;
for (Library lib in component.libraries) {
for (Class c in lib.classes) {
- if (c.isSyntheticMixinImplementation) {
+ if (c.isAnonymousMixin) {
for (Procedure p in c.procedures) {
if (p.function.body is EmptyStatement) {
empty++;
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 13b28bf..d94fb18 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -131,7 +131,7 @@
type ComponentFile {
UInt32 magic = 0x90ABCDEF;
- UInt32 formatVersion = 6;
+ UInt32 formatVersion = 7;
Library[] libraries;
UriSource sourceMap;
List<CanonicalName> canonicalNames;
@@ -286,11 +286,14 @@
UriReference fileUri;
FileOffset fileOffset;
FileOffset fileEndOffset;
- Byte flags (isAbstract, isEnum, xx); // Where xx is index into ClassLevel
+ Byte flags (levelBit0, levelBit1, isAbstract, isEnum, isAnonymousMixin,
+ isEliminatedMixin); // Where level is index into ClassLevel
StringReference name;
List<Expression> annotations;
List<TypeParameter> typeParameters;
Option<DartType> superClass;
+ // For transformed mixin application classes (isEliminatedMixin),
+ // original mixedInType is pulled into the end of implementedClasses.
Option<DartType> mixedInType;
List<DartType> implementedClasses;
List<Field> fields;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index afe96c6..f7367b9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -696,10 +696,28 @@
/// applications.
@coq
String name;
- bool isAbstract;
+
+ // Must match serialized bit positions.
+ static const int LevelMask = 0x3; // Bits 0 and 1.
+ static const int FlagAbstract = 1 << 2;
+ static const int FlagEnum = 1 << 3;
+ static const int FlagAnonymousMixin = 1 << 4;
+ static const int FlagEliminatedMixin = 1 << 5;
+
+ int flags = 0;
+
+ bool get isAbstract => flags & FlagAbstract != 0;
+
+ void set isAbstract(bool value) {
+ flags = value ? (flags | FlagAbstract) : (flags & ~FlagAbstract);
+ }
/// Whether this class is an enum.
- bool isEnum = false;
+ bool get isEnum => flags & FlagEnum != 0;
+
+ void set isEnum(bool value) {
+ flags = value ? (flags | FlagEnum) : (flags & ~FlagEnum);
+ }
/// Whether this class is a synthetic implementation created for each
/// mixed-in class. For example the following code:
@@ -714,7 +732,22 @@
/// abstract class A&B&C&D extends A&B&C mixedIn D {}
/// class Z extends A&B&C&D {}
/// All X&Y classes are marked as synthetic.
- bool isSyntheticMixinImplementation;
+ bool get isAnonymousMixin => flags & FlagAnonymousMixin != 0;
+
+ void set isAnonymousMixin(bool value) {
+ flags =
+ value ? (flags | FlagAnonymousMixin) : (flags & ~FlagAnonymousMixin);
+ }
+
+ /// Whether this class was transformed from a mixin application.
+ /// In such case, its mixed-in type was pulled into the end of implemented
+ /// types list.
+ bool get isEliminatedMixin => flags & FlagEliminatedMixin != 0;
+
+ void set isEliminatedMixin(bool value) {
+ flags =
+ value ? (flags | FlagEliminatedMixin) : (flags & ~FlagEliminatedMixin);
+ }
/// The URI of the source file this class was loaded from.
Uri fileUri;
@@ -750,8 +783,8 @@
Class(
{this.name,
- this.isAbstract: false,
- this.isSyntheticMixinImplementation: false,
+ bool isAbstract: false,
+ bool isAnonymousMixin: false,
this.supertype,
this.mixedInType,
List<TypeParameter> typeParameters,
@@ -775,6 +808,8 @@
setParents(this.procedures, this);
setParents(this.fields, this);
setParents(this.redirectingFactoryConstructors, this);
+ this.isAbstract = isAbstract;
+ this.isAnonymousMixin = isAnonymousMixin;
}
void computeCanonicalNames() {
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index b75a3a3..5e01828 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -847,10 +847,8 @@
node.fileOffset = readOffset();
node.fileEndOffset = readOffset();
int flags = readByte();
- node.isAbstract = flags & 0x1 != 0;
- node.isEnum = flags & 0x2 != 0;
- node.isSyntheticMixinImplementation = flags & 0x4 != 0;
- int levelIndex = (flags >> 3) & 0x3;
+ node.flags = flags & ~Class.LevelMask;
+ int levelIndex = flags & Class.LevelMask;
var level = ClassLevel.values[levelIndex + 1];
if (level.index >= node.level.index) {
node.level = level;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 156d80b..ed89e92 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -725,25 +725,18 @@
}
}
- int _encodeClassFlags(bool isAbstract, bool isEnum,
- bool isSyntheticMixinImplementation, ClassLevel level) {
- int abstractFlag = isAbstract ? 1 : 0;
- int isEnumFlag = isEnum ? 2 : 0;
- int isSyntheticMixinImplementationFlag =
- isSyntheticMixinImplementation ? 4 : 0;
- int levelFlags = (level.index - 1) << 3;
- return abstractFlag |
- isEnumFlag |
- isSyntheticMixinImplementationFlag |
- levelFlags;
+ int _encodeClassFlags(int flags, ClassLevel level) {
+ assert((flags & Class.LevelMask) == 0);
+ final levelIndex = level.index - 1;
+ assert((levelIndex & Class.LevelMask) == levelIndex);
+ return flags | levelIndex;
}
@override
void visitClass(Class node) {
classOffsets.add(getBufferOffset());
- int flags = _encodeClassFlags(node.isAbstract, node.isEnum,
- node.isSyntheticMixinImplementation, node.level);
+ int flags = _encodeClassFlags(node.flags, node.level);
if (node.canonicalName == null) {
throw 'Missing canonical name for $node';
}
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 1d016af..9bb574b0 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -135,7 +135,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 = 6;
+ static const int BinaryFormatVersion = 7;
}
abstract class ConstantTag {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 3a9a036..ab527e5 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -23,7 +23,7 @@
{HandleAmbiguousSupertypes onAmbiguousSupertypes,
MixinInferrer mixinInferrer}) {
onAmbiguousSupertypes ??= (Class cls, Supertype a, Supertype b) {
- if (!cls.isSyntheticMixinImplementation) {
+ if (!cls.isAnonymousMixin) {
// See https://github.com/dart-lang/sdk/issues/32091
throw "$cls can't implement both $a and $b";
}
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index a2f392620..d546fe4 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -232,11 +232,15 @@
}
}
- // This class implements the mixin type.
+ // This class implements the mixin type. Also, backends rely on the fact
+ // that eliminated mixin is appended into the end of interfaces list.
class_.implementedTypes.add(class_.mixedInType);
// This class is now a normal class.
class_.mixedInType = null;
+
+ // Leave breadcrumbs for backends (e.g. for dart:mirrors implementation).
+ class_.isEliminatedMixin = true;
}
Constructor buildForwardingConstructor(
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index 2daf9a0..68ade75 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -79,7 +79,7 @@
_transformSupertype(c);
}
- if (!c.isSyntheticMixinImplementation) {
+ if (!c.isAnonymousMixin) {
return c;
}
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 3524eef..1651cfa 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -313,7 +313,7 @@
return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
}
- const Array& args = Array::Handle(Array::New(9));
+ const Array& args = Array::Handle(Array::New(10));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
// Note that the VM does not consider mixin application aliases to be mixin
@@ -328,8 +328,9 @@
args.SetAt(4, Bool::Get(cls.is_abstract()));
args.SetAt(5, Bool::Get(cls.IsGeneric()));
args.SetAt(6, Bool::Get(cls.is_mixin_app_alias()));
- args.SetAt(7, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
- args.SetAt(8, Bool::Get(cls.is_enum_class()));
+ args.SetAt(7, Bool::Get(cls.is_transformed_mixin_application()));
+ args.SetAt(8, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
+ args.SetAt(9, Bool::Get(cls.is_enum_class()));
return CreateMirror(Symbols::_LocalClassMirror(), args);
}
@@ -993,7 +994,13 @@
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
- const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+ AbstractType& mixin_type = AbstractType::Handle();
+ if (cls.is_transformed_mixin_application()) {
+ const Array& interfaces = Array::Handle(cls.interfaces());
+ mixin_type ^= interfaces.At(interfaces.Length() - 1);
+ } else {
+ mixin_type = cls.mixin();
+ }
ASSERT(mixin_type.IsNull() || mixin_type.IsFinalized());
return mixin_type.raw();
}
@@ -1005,7 +1012,13 @@
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
const Class& cls = Class::Handle(type.type_class());
- const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+ AbstractType& mixin_type = AbstractType::Handle();
+ if (cls.is_transformed_mixin_application()) {
+ const Array& interfaces = Array::Handle(cls.interfaces());
+ mixin_type ^= interfaces.At(interfaces.Length() - 1);
+ } else {
+ mixin_type = cls.mixin();
+ }
if (mixin_type.IsNull()) {
return mixin_type.raw();
}
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 5c42dc4..eb0becb 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -356,7 +356,16 @@
DeclarationMirror _owner;
final bool isAbstract;
final bool _isGeneric;
+
+ // Only used for Dart 1 named mixin applications.
+ // TODO(alexmarkov): Clean up after Dart 1 is gone.
final bool _isMixinAlias;
+
+ // Since Dart 2, mixins are erased by kernel transformation.
+ // Resulting classes have this flag set, and mixed-in type is pulled into
+ // the end of interfaces list.
+ final bool _isTransformedMixinApplication;
+
final bool _isGenericDeclaration;
final bool isEnum;
Type _instantiator;
@@ -369,6 +378,7 @@
this.isAbstract,
this._isGeneric,
this._isMixinAlias,
+ this._isTransformedMixinApplication,
this._isGenericDeclaration,
this.isEnum)
: this._simpleName = _s(simpleName),
@@ -443,6 +453,9 @@
var interfaceTypes = isOriginalDeclaration
? _nativeInterfaces(_reflectedType)
: _nativeInterfacesInstantiated(_reflectedType);
+ if (_isTransformedMixinApplication) {
+ interfaceTypes = interfaceTypes.sublist(0, interfaceTypes.length - 1);
+ }
var interfaceMirrors = new List<ClassMirror>();
for (var interfaceType in interfaceTypes) {
interfaceMirrors.add(reflectType(interfaceType));
@@ -570,6 +583,7 @@
new UnmodifiableMapView<Symbol, DeclarationMirror>(decls);
}
+ // Note: returns correct result only for Dart 1 anonymous mixin applications.
bool get _isAnonymousMixinApplication {
if (_isMixinAlias) return false; // Named mixin application.
if (mixin == this) return false; // Not a mixin application.
@@ -579,7 +593,7 @@
List<TypeVariableMirror> _typeVariables;
List<TypeVariableMirror> get typeVariables {
if (_typeVariables == null) {
- if (_isAnonymousMixinApplication) {
+ if (!_isTransformedMixinApplication && _isAnonymousMixinApplication) {
return _typeVariables = const <TypeVariableMirror>[];
}
_typeVariables = new List<TypeVariableMirror>();
@@ -600,7 +614,8 @@
List<TypeMirror> _typeArguments;
List<TypeMirror> get typeArguments {
if (_typeArguments == null) {
- if (_isGenericDeclaration || _isAnonymousMixinApplication) {
+ if (_isGenericDeclaration ||
+ (!_isTransformedMixinApplication && _isAnonymousMixinApplication)) {
_typeArguments = const <TypeMirror>[];
} else {
_typeArguments = new UnmodifiableListView<TypeMirror>(
@@ -734,7 +749,7 @@
final _functionReflectee;
_LocalFunctionTypeMirror(reflectee, this._functionReflectee, reflectedType)
: super(reflectee, reflectedType, null, null, false, false, false, false,
- false);
+ false, false);
bool get _isAnonymousMixinApplication => false;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index c83ac76..859d443 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -431,8 +431,10 @@
};
enum Flag {
- kIsAbstract = 1,
- kIsEnumClass = 2,
+ kIsAbstract = 1 << 2,
+ kIsEnumClass = 1 << 3,
+ kIsAnonymousMixin = 1 << 4,
+ kIsEliminatedMixin = 1 << 5,
};
explicit ClassHelper(KernelReaderHelper* helper)
@@ -447,9 +449,13 @@
void SetNext(Field field) { next_read_ = field; }
void SetJustRead(Field field) { next_read_ = field + 1; }
- bool is_abstract() { return flags_ & Flag::kIsAbstract; }
+ bool is_abstract() const { return flags_ & Flag::kIsAbstract; }
- bool is_enum_class() { return flags_ & Flag::kIsEnumClass; }
+ bool is_enum_class() const { return flags_ & Flag::kIsEnumClass; }
+
+ bool is_transformed_mixin_application() const {
+ return flags_ & Flag::kIsEliminatedMixin;
+ }
NameIndex canonical_name_;
TokenPosition position_;
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index ba05ff0..70a967b 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
// package:kernel/binary.md.
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kBinaryFormatVersion = 6;
+static const uint32_t kBinaryFormatVersion = 7;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 607c1e9..e7f45d2 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -967,6 +967,10 @@
klass->set_interfaces(interfaces);
if (class_helper->is_abstract()) klass->set_is_abstract();
+
+ if (class_helper->is_transformed_mixin_application()) {
+ klass->set_is_transformed_mixin_application();
+ }
}
// Workaround for http://dartbug.com/32087: currently Kernel front-end
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index de61db2..d379d22 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3792,6 +3792,11 @@
set_state_bits(MixinTypeAppliedBit::update(true, raw_ptr()->state_bits_));
}
+void Class::set_is_transformed_mixin_application() const {
+ set_state_bits(
+ TransformedMixinApplicationBit::update(true, raw_ptr()->state_bits_));
+}
+
void Class::set_is_fields_marked_nullable() const {
set_state_bits(FieldsMarkedNullableBit::update(true, raw_ptr()->state_bits_));
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 1d8dc12..ee04799 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1311,6 +1311,17 @@
}
void set_is_mixin_type_applied() const;
+ // Tests if this is a mixin application class which was desugared
+ // to a normal class by kernel mixin transformation
+ // (pkg/kernel/lib/transformations/mixin_full_resolution.dart).
+ //
+ // In such case, its mixed-in type was pulled into the end of
+ // interfaces list.
+ bool is_transformed_mixin_application() const {
+ return TransformedMixinApplicationBit::decode(raw_ptr()->state_bits_);
+ }
+ void set_is_transformed_mixin_application() const;
+
bool is_fields_marked_nullable() const {
return FieldsMarkedNullableBit::decode(raw_ptr()->state_bits_);
}
@@ -1470,6 +1481,7 @@
kFieldsMarkedNullableBit = 11,
kCycleFreeBit = 12,
kEnumBit = 13,
+ kTransformedMixinApplicationBit = 14,
kIsAllocatedBit = 15,
};
class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
@@ -1494,6 +1506,8 @@
: public BitField<uint16_t, bool, kFieldsMarkedNullableBit, 1> {};
class CycleFreeBit : public BitField<uint16_t, bool, kCycleFreeBit, 1> {};
class EnumBit : public BitField<uint16_t, bool, kEnumBit, 1> {};
+ class TransformedMixinApplicationBit
+ : public BitField<uint16_t, bool, kTransformedMixinApplicationBit, 1> {};
class IsAllocatedBit : public BitField<uint16_t, bool, kIsAllocatedBit, 1> {};
void set_name(const String& value) const;
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index 63aa705..da72614 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -133,12 +133,9 @@
mirrors/generic_f_bounded_mixin_application_test: RuntimeError
mirrors/generic_function_typedef_test: RuntimeError
mirrors/generic_interface_test/01: RuntimeError
-mirrors/generic_interface_test/none: RuntimeError
mirrors/generic_mixin_applications_test: RuntimeError
-mirrors/generic_mixin_test: RuntimeError
mirrors/hot_get_field_test: RuntimeError
mirrors/hot_set_field_test: RuntimeError
-mirrors/intercepted_object_test: RuntimeError # Issue 31402 (Invocation arguments)
mirrors/invocation_fuzz_test: RuntimeError, Crash
mirrors/invoke_private_test: RuntimeError
mirrors/invoke_private_wrong_library_test: RuntimeError
@@ -171,8 +168,6 @@
mirrors/mirrors_used_typedef_declaration_test/none: RuntimeError
mirrors/mixin_application_test: RuntimeError # Issue 31402 (Invocation arguments)
mirrors/mixin_members_test: CompileTimeError # Issue 31402 (Invocation arguments)
-mirrors/mixin_simple_test: RuntimeError
-mirrors/mixin_test: RuntimeError
mirrors/native_class_test: SkipByDesign # Imports dart:html
mirrors/operator_test: CompileTimeError # Issue 31402 (Invocation arguments)
mirrors/other_declarations_location_test: RuntimeError