Skip to content

Commit fd992e4

Browse files
Dmitry Stefantsovjohnniwinther
Dmitry Stefantsov
authored andcommitted
[cfe] Normalize supertypes before nnbd-top-merging them
Closes #40454. Bug: http://dartbug.com/40454 Change-Id: Ia255c99c937a04876e04a0f0f5935147e55fbd35 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134842 Reviewed-by: Johnni Winther <[email protected]>
1 parent 8ef89b4 commit fd992e4

File tree

5 files changed

+60
-5
lines changed

5 files changed

+60
-5
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
/*library: nnbd=true*/
6+
7+
import 'dart:async';
8+
9+
/*class: A:A<T>,Object*/
10+
class A<T> {}
11+
12+
/*class: Foo:A<FutureOr<T?>!>,Foo<T!,S!>,Object*/
13+
class Foo<T extends S, S extends Never> implements A<FutureOr<T?>> {}
14+
15+
/*class: Bar:A<FutureOr<Never>!>,Bar,Object*/
16+
class Bar implements A<FutureOr<Never?>> {}
17+
18+
/*class: Baz:A<Future<Null>?>,Baz,Object*/
19+
class Baz implements A<Future<Null>?> {}
20+
21+
/*class: Hest:A<Future<Null>?>,Bar,Foo<Never,Never>,Hest,Object*/
22+
class Hest extends Foo implements Bar {}
23+
24+
/*class: Fisk:A<Future<Null>?>,Bar,Baz,Fisk,Object*/
25+
class Fisk extends Bar implements Baz {}
26+
27+
/*class: Naebdyr:A<Future<Null>?>,Baz,Foo<Never,Never>,Naebdyr,Object*/
28+
class Naebdyr extends Baz implements Foo {}
29+
30+
main() {}

pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:kernel/type_environment.dart';
1616
import 'package:kernel/src/future_or.dart';
1717
import 'package:kernel/src/legacy_erasure.dart';
1818
import 'package:kernel/src/nnbd_top_merge.dart';
19+
import 'package:kernel/src/norm.dart';
1920

2021
import '../../testing/id_testing_utils.dart' show typeToText;
2122

@@ -1536,7 +1537,10 @@ class ClassHierarchyNodeBuilder {
15361537
superclass.classNode == type.classNode) {
15371538
// This is a potential conflict.
15381539
if (classBuilder.library.isNonNullableByDefault) {
1539-
superclass = nnbdTopMerge(hierarchy.coreTypes, superclass, type);
1540+
superclass = nnbdTopMerge(
1541+
hierarchy.coreTypes,
1542+
norm(hierarchy.coreTypes, superclass),
1543+
norm(hierarchy.coreTypes, type));
15401544
if (superclass == null) {
15411545
// This is a conflict.
15421546
// TODO(johnniwinther): Report errors here instead of through
@@ -1556,7 +1560,10 @@ class ClassHierarchyNodeBuilder {
15561560
interface.classNode == type.classNode) {
15571561
// This is a potential conflict.
15581562
if (classBuilder.library.isNonNullableByDefault) {
1559-
interface = nnbdTopMerge(hierarchy.coreTypes, interface, type);
1563+
interface = nnbdTopMerge(
1564+
hierarchy.coreTypes,
1565+
norm(hierarchy.coreTypes, interface),
1566+
norm(hierarchy.coreTypes, type));
15601567
if (interface == null) {
15611568
// This is a conflict.
15621569
// TODO(johnniwinther): Report errors here instead of through

pkg/front_end/test/id_tests/inheritance_test.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ main(List<String> args) async {
2828
experimentalFlags: const {ExperimentalFlag.nonNullable: true},
2929
librariesSpecificationUri: createUriForFileName('libraries.json'),
3030
compileSdk: true),
31-
new TestConfig(
32-
cfeFromBuilderMarker, 'cfe from builder',
31+
new TestConfig(cfeFromBuilderMarker, 'cfe from builder',
3332
experimentalFlags: const {ExperimentalFlag.nonNullable: true},
3433
librariesSpecificationUri: createUriForFileName('libraries.json'),
3534
compileSdk: true)

pkg/kernel/lib/class_hierarchy.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'type_algebra.dart';
1515
import 'src/future_or.dart';
1616
import 'src/heap.dart';
1717
import 'src/legacy_erasure.dart';
18+
import 'src/norm.dart';
1819

1920
typedef HandleAmbiguousSupertypes = void Function(Class, Supertype, Supertype);
2021

@@ -1581,7 +1582,10 @@ class _ClassInfo {
15811582
genericSuperTypes[cls].add(type);
15821583

15831584
if (classNode.enclosingLibrary.isNonNullableByDefault) {
1584-
Supertype result = nnbdTopMergeSupertype(coreTypes, type, canonical);
1585+
Supertype result = nnbdTopMergeSupertype(
1586+
coreTypes,
1587+
normSupertype(coreTypes, type),
1588+
normSupertype(coreTypes, canonical));
15851589
if (result == null) {
15861590
onAmbiguousSupertypes(classNode, canonical, type);
15871591
} else {

pkg/kernel/lib/src/norm.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ DartType norm(CoreTypes coreTypes, DartType type) {
1313
return type.accept(new _Norm(coreTypes)) ?? type;
1414
}
1515

16+
Supertype normSupertype(CoreTypes coreTypes, Supertype supertype) {
17+
if (supertype.typeArguments.isEmpty) return supertype;
18+
_Norm normVisitor = new _Norm(coreTypes);
19+
List<DartType> typeArguments = null;
20+
for (int i = 0; i < supertype.typeArguments.length; ++i) {
21+
DartType typeArgument = supertype.typeArguments[i].accept(normVisitor);
22+
if (typeArgument != null) {
23+
typeArguments ??= supertype.typeArguments.toList();
24+
typeArguments[i] = typeArgument;
25+
}
26+
}
27+
if (typeArguments == null) return supertype;
28+
return new Supertype(supertype.classNode, typeArguments);
29+
}
30+
1631
/// Visitor implementing the NORM algorithm.
1732
///
1833
/// Visitor's methods return null if the type is unchanged by the NORM

0 commit comments

Comments
 (0)