Skip to content

Commit da663d6

Browse files
committed
[cfe] Fix bad supertype substitution in mixin check.
Closes #42792 Change-Id: I21757f0f8417ad677d075e8417e390e1fa532a2b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155444 Reviewed-by: Dmitry Stefantsov <[email protected]>
1 parent fad5548 commit da663d6

File tree

8 files changed

+129
-5
lines changed

8 files changed

+129
-5
lines changed

pkg/front_end/lib/src/fasta/builder/class_builder.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,15 +1419,15 @@ abstract class ClassBuilderImpl extends DeclarationBuilderImpl
14191419
InterfaceType supertype = cls.supertype.asInterfaceType;
14201420
Substitution substitution = Substitution.fromSupertype(cls.mixedInType);
14211421
for (Supertype constraint in cls.mixedInClass.superclassConstraints()) {
1422-
InterfaceType interface =
1422+
InterfaceType requiredInterface =
14231423
substitution.substituteSupertype(constraint).asInterfaceType;
1424-
if (hierarchy.getTypeAsInstanceOf(
1425-
supertype, interface.classNode, library.library, coreTypes) !=
1426-
interface) {
1424+
InterfaceType implementedInterface = hierarchy.getTypeAsInstanceOf(
1425+
supertype, requiredInterface.classNode, library.library, coreTypes);
1426+
if (implementedInterface != requiredInterface) {
14271427
library.addProblem(
14281428
templateMixinApplicationIncompatibleSupertype.withArguments(
14291429
supertype,
1430-
interface,
1430+
requiredInterface,
14311431
cls.mixedInType.asInterfaceType,
14321432
library.isNonNullableByDefault),
14331433
cls.fileOffset,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'issue42792_lib.dart';
6+
7+
mixin M<T> on A<T> {}
8+
9+
class B extends A<int> with M {}
10+
11+
void main() {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import 'issue42792_lib.dart';
2+
3+
mixin M<T> on A<T> {}
4+
5+
class B extends A<int> with M {}
6+
7+
void main() {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import 'issue42792_lib.dart';
2+
3+
class B extends A<int> with M {}
4+
5+
mixin M<T> on A<T> {}
6+
void main() {}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "issue42792_lib.dart" as iss;
5+
6+
import "org-dartlang-testcase:///issue42792_lib.dart";
7+
8+
abstract class M<T extends core::Object? = dynamic> extends iss::A<self::M::T%> /*isMixinDeclaration*/ {
9+
}
10+
abstract class _B&A&M = iss::A<core::int> with self::M<core::int> /*isAnonymousMixin*/ {
11+
synthetic constructor •() → self::_B&A&M
12+
: super iss::A::•()
13+
;
14+
}
15+
class B extends self::_B&A&M {
16+
synthetic constructor •() → self::B
17+
: super self::_B&A&M::•()
18+
;
19+
}
20+
static method main() → void {}
21+
22+
library;
23+
import self as iss;
24+
import "dart:core" as core;
25+
26+
abstract class A<T extends core::Object* = dynamic> extends core::Object {
27+
synthetic constructor •() → iss::A<iss::A::T*>*
28+
: super core::Object::•()
29+
;
30+
abstract member-signature get _identityHashCode() → core::int*;
31+
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
32+
abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
33+
abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
34+
abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
35+
abstract member-signature operator ==(dynamic other) → core::bool*;
36+
abstract member-signature get hashCode() → core::int*;
37+
abstract member-signature method toString() → core::String*;
38+
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
39+
abstract member-signature get runtimeType() → core::Type*;
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "issue42792_lib.dart" as iss;
5+
6+
import "org-dartlang-testcase:///issue42792_lib.dart";
7+
8+
abstract class M<T extends core::Object? = dynamic> extends iss::A<self::M::T%> /*isMixinDeclaration*/ {
9+
}
10+
abstract class _B&A&M extends iss::A<core::int> implements self::M<core::int> /*isAnonymousMixin,isEliminatedMixin*/ {
11+
synthetic constructor •() → self::_B&A&M
12+
: super iss::A::•()
13+
;
14+
}
15+
class B extends self::_B&A&M {
16+
synthetic constructor •() → self::B
17+
: super self::_B&A&M::•()
18+
;
19+
}
20+
static method main() → void {}
21+
22+
library;
23+
import self as iss;
24+
import "dart:core" as core;
25+
26+
abstract class A<T extends core::Object* = dynamic> extends core::Object {
27+
synthetic constructor •() → iss::A<iss::A::T*>*
28+
: super core::Object::•()
29+
;
30+
abstract member-signature get _identityHashCode() → core::int*;
31+
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
32+
abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
33+
abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
34+
abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
35+
abstract member-signature operator ==(dynamic other) → core::bool*;
36+
abstract member-signature get hashCode() → core::int*;
37+
abstract member-signature method toString() → core::String*;
38+
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
39+
abstract member-signature get runtimeType() → core::Type*;
40+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// @dart = 2.8
6+
7+
abstract class A<T> {}

pkg/kernel/lib/class_hierarchy.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,19 @@ class ClosedWorldClassHierarchy implements ClassHierarchy {
715715
@override
716716
List<DartType> getTypeArgumentsAsInstanceOf(
717717
InterfaceType type, Class superclass) {
718+
if (type.classNode == superclass) {
719+
// TODO(johnniwinther): This is necessary because [getClassAsInstanceOf]
720+
// returns a [Supertype] whose type arguments are type parameter types
721+
// whose nullability is set to the default nullability of the
722+
// enclosing library. If for instance [type] is `A<int!>` but `A` is
723+
// declared in an opt-out library, the substitution below will combine
724+
// nullabilities of the type arguments in [type] with the type parameters
725+
// and thus give the result `A<int*>`. See issue #42792.
726+
// For now we bypass the substitution but long term we need to ensure
727+
// that [getClassAsInstanceOf] doesn't cause similar problems in other
728+
// situations.
729+
return type.typeArguments;
730+
}
718731
Supertype castedType = getClassAsInstanceOf(type.classNode, superclass);
719732
if (castedType == null) return null;
720733
if (superclass.typeParameters.isEmpty) return const <DartType>[];

0 commit comments

Comments
 (0)