Skip to content

Commit 44dff4e

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Issue 40221. NNBD_TOP_MERGE super-interfaces when checking for implementing the same generic class more than once.
Bug: #40221 Change-Id: I776ee76ced12ec9ab0838f9bac76a3ec9fdb71b5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/133329 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 548127d commit 44dff4e

File tree

4 files changed

+77
-11
lines changed

4 files changed

+77
-11
lines changed

pkg/analyzer/lib/src/dart/element/normalize.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analyzer/dart/element/element.dart';
56
import 'package:analyzer/dart/element/nullability_suffix.dart';
67
import 'package:analyzer/dart/element/type.dart';
78
import 'package:analyzer/src/dart/element/element.dart';
@@ -19,6 +20,8 @@ class NormalizeHelper {
1920
final TypeSystemImpl typeSystem;
2021
final TypeProviderImpl typeProvider;
2122

23+
final Set<TypeParameterElement> _typeParameters = {};
24+
2225
NormalizeHelper(this.typeSystem) : typeProvider = typeSystem.typeProvider;
2326

2427
DartType normalize(DartType T) {
@@ -242,7 +245,13 @@ class NormalizeHelper {
242245
}
243246

244247
// * let S be NORM(T)
245-
var S = _normalize(bound);
248+
DartType S;
249+
if (_typeParameters.add(element)) {
250+
S = _normalize(bound);
251+
_typeParameters.remove(element);
252+
} else {
253+
return T;
254+
}
246255

247256
// * if S is Never then Never
248257
if (identical(S, NeverTypeImpl.instance)) {

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,16 +1967,35 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
19671967
visitedClasses.add(element);
19681968

19691969
if (element.typeParameters.isNotEmpty) {
1970-
type = _toLegacyType(type);
1971-
var oldType = interfaces[element];
1972-
if (oldType == null) {
1973-
interfaces[element] = type;
1974-
} else if (type != oldType) {
1975-
_errorReporter.reportErrorForNode(
1976-
CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
1977-
node,
1978-
[_enclosingClass.name, oldType, type],
1979-
);
1970+
if (_typeSystem.isNonNullableByDefault) {
1971+
type = _typeSystem.normalize(type);
1972+
var oldType = interfaces[element];
1973+
if (oldType == null) {
1974+
interfaces[element] = type;
1975+
} else {
1976+
try {
1977+
var result = _typeSystem.topMerge(oldType, type);
1978+
interfaces[element] = result;
1979+
} catch (_) {
1980+
_errorReporter.reportErrorForNode(
1981+
CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
1982+
node,
1983+
[_enclosingClass.name, oldType, type],
1984+
);
1985+
}
1986+
}
1987+
} else {
1988+
type = _toLegacyType(type);
1989+
var oldType = interfaces[element];
1990+
if (oldType == null) {
1991+
interfaces[element] = type;
1992+
} else if (type != oldType) {
1993+
_errorReporter.reportErrorForNode(
1994+
CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
1995+
node,
1996+
[_enclosingClass.name, oldType, type],
1997+
);
1998+
}
19801999
}
19812000
}
19822001

pkg/analyzer/test/src/dart/element/normalize_type_test.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,12 @@ class NormalizeTypeTest with ElementsTypesMixin {
404404
_check(typeParameterTypeNone(T), typeParameterTypeNone(T));
405405
}
406406

407+
test_typeParameter_bound_recursive() {
408+
var T = typeParameter('T');
409+
T.bound = iterableNone(typeParameterTypeNone(T));
410+
_check(typeParameterTypeNone(T), typeParameterTypeNone(T));
411+
}
412+
407413
test_typeParameter_promoted() {
408414
var T = typeParameter('T');
409415

pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,38 @@ class B extends A<int> {}
121121
// @dart = 2.5
122122
import 'a.dart';
123123
124+
class C extends B implements A<int> {}
125+
''');
126+
}
127+
128+
test_class_topMerge() async {
129+
await assertNoErrorsInCode('''
130+
import 'dart:async';
131+
132+
class A<T> {}
133+
134+
class B extends A<FutureOr<Object>> {}
135+
136+
class C extends B implements A<Object> {}
137+
''');
138+
}
139+
140+
test_class_topMerge_optIn_optOut() async {
141+
newFile('/test/lib/a.dart', content: r'''
142+
class A<T> {}
143+
''');
144+
145+
newFile('/test/lib/b.dart', content: r'''
146+
// @dart = 2.5
147+
import 'a.dart';
148+
149+
class B extends A<int> {}
150+
''');
151+
152+
await assertNoErrorsInCode('''
153+
import 'a.dart';
154+
import 'b.dart';
155+
124156
class C extends B implements A<int> {}
125157
''');
126158
}

0 commit comments

Comments
 (0)