Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit dcdc71d

Browse files
committed
Report CONFLICTING_GENERIC_INTERFACES using ClassHierarchy.
Change-Id: Ib5d79403358efffd5365ac4931c3163d746d933a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/142567 Reviewed-by: Brian Wilkerson <[email protected]>
1 parent e2e7224 commit dcdc71d

File tree

4 files changed

+51
-73
lines changed

4 files changed

+51
-73
lines changed

pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,26 @@ class SubClass2 extends LegacyClass2 implements Interface {
1717
/*member: SubClass2.method:int? Function(int)*/
1818
}
1919

20-
// TODO: Solve CFE / analyzer difference.
21-
// This an following examples end up with implementing `GenericInterface`
22-
// with `int` and `int?` type arguments, and their NNBD_TOP_MERGE does not
23-
// exist. it does not matter that some of these interfaces come through a
24-
// legacy library.
25-
2620
/*class: GenericSubClass1a:GenericClass1,GenericInterface<int?>,GenericLegacyClass1a,GenericSubClass1a,Object*/
27-
/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass1a
28-
extends GenericLegacyClass1a implements GenericInterface<int?> {
21+
abstract class GenericSubClass1a extends GenericLegacyClass1a
22+
implements GenericInterface<int?> {
2923
/*member: GenericSubClass1a.method:int? Function(int?)*/
3024
}
3125

3226
/*class: GenericSubClass1b:GenericClass1,GenericInterface<int?>,GenericLegacyClass1b,GenericSubClass1b,Object*/
33-
/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass1b
34-
extends GenericLegacyClass1b implements GenericInterface<int?> {
27+
abstract class GenericSubClass1b extends GenericLegacyClass1b
28+
implements GenericInterface<int?> {
3529
/*member: GenericSubClass1b.method:int? Function(int?)*/
3630
}
3731

3832
/*class: GenericSubClass2a:GenericClass2,GenericInterface<int>,GenericLegacyClass2a,GenericSubClass2a,Object*/
39-
/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass2a
40-
extends GenericLegacyClass2a implements GenericInterface<int> {
33+
abstract class GenericSubClass2a extends GenericLegacyClass2a
34+
implements GenericInterface<int> {
4135
/*member: GenericSubClass2a.method:int Function(int)*/
4236
}
4337

4438
/*class: GenericSubClass2b:GenericClass2,GenericInterface<int>,GenericLegacyClass2b,GenericSubClass2b,Object*/
45-
/*analyzer.error: CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES*/ abstract class GenericSubClass2b
46-
extends GenericLegacyClass2b implements GenericInterface<int> {
39+
abstract class GenericSubClass2b extends GenericLegacyClass2b
40+
implements GenericInterface<int> {
4741
/*member: GenericSubClass2b.method:int Function(int)*/
4842
}

pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/opt_out.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ abstract class LegacyClass2 extends Class {
1818
/*member: LegacyClass2.method:int* Function(int*)**/
1919
}
2020

21-
/// TODO: Solve CFE / analyzer difference.
22-
/// Classes in legacy libraries can only have members with legacy signatures.
2321
/*class: GenericLegacyClass1a:GenericClass1,GenericInterface<int*>,GenericLegacyClass1a,Object*/
2422
abstract class GenericLegacyClass1a extends GenericClass1 {
2523
/*member: GenericLegacyClass1a.method:int* Function(int*)**/

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

Lines changed: 19 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ import 'package:analyzer/dart/element/type.dart';
1515
import 'package:analyzer/dart/element/type_provider.dart';
1616
import 'package:analyzer/error/error.dart';
1717
import 'package:analyzer/error/listener.dart';
18+
import 'package:analyzer/src/dart/analysis/session.dart';
1819
import 'package:analyzer/src/dart/ast/ast.dart';
20+
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
1921
import 'package:analyzer/src/dart/element/element.dart';
2022
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
21-
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
2223
import 'package:analyzer/src/dart/element/type.dart';
2324
import 'package:analyzer/src/dart/resolver/variance.dart';
2425
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
@@ -1957,58 +1958,26 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
19571958
}
19581959

19591960
void _checkForConflictingGenerics(NamedCompilationUnitMember node) {
1960-
var visitedClasses = <ClassElement>[];
1961-
var interfaces = <ClassElement, InterfaceType>{};
1962-
1963-
void visit(InterfaceType type) {
1964-
if (type == null) return;
1965-
1966-
var element = type.element;
1967-
if (visitedClasses.contains(element)) return;
1968-
visitedClasses.add(element);
1969-
1970-
if (element.typeParameters.isNotEmpty) {
1971-
if (_typeSystem.isNonNullableByDefault) {
1972-
type = _typeSystem.normalize(type);
1973-
var oldType = interfaces[element];
1974-
if (oldType == null) {
1975-
interfaces[element] = type;
1976-
} else {
1977-
try {
1978-
var result = _typeSystem.topMerge(oldType, type);
1979-
interfaces[element] = result;
1980-
} catch (_) {
1981-
_errorReporter.reportErrorForNode(
1982-
CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
1983-
node,
1984-
[_enclosingClass.name, oldType, type],
1985-
);
1986-
}
1987-
}
1988-
} else {
1989-
type = _toLegacyType(type);
1990-
var oldType = interfaces[element];
1991-
if (oldType == null) {
1992-
interfaces[element] = type;
1993-
} else if (type != oldType) {
1994-
_errorReporter.reportErrorForNode(
1995-
CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
1996-
node,
1997-
[_enclosingClass.name, oldType, type],
1998-
);
1999-
}
2000-
}
2001-
}
1961+
var element = node.declaredElement as ClassElement;
20021962

2003-
visit(type.superclass);
2004-
type.mixins.forEach(visit);
2005-
type.superclassConstraints.forEach(visit);
2006-
type.interfaces.forEach(visit);
1963+
var analysisSession = _currentLibrary.session as AnalysisSessionImpl;
1964+
var errors = analysisSession.classHierarchy.errors(element);
20071965

2008-
visitedClasses.removeLast();
1966+
for (var error in errors) {
1967+
if (error is IncompatibleInterfacesClassHierarchyError) {
1968+
_errorReporter.reportErrorForNode(
1969+
CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
1970+
node,
1971+
[
1972+
_enclosingClass.name,
1973+
error.first.getDisplayString(withNullability: true),
1974+
error.second.getDisplayString(withNullability: true),
1975+
],
1976+
);
1977+
} else {
1978+
throw UnimplementedError('${error.runtimeType}');
1979+
}
20091980
}
2010-
2011-
visit(_enclosingClass.thisType);
20121981
}
20131982

20141983
/**
@@ -5552,13 +5521,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
55525521
return null;
55535522
}
55545523

5555-
/// If in a legacy library, return the legacy version of the [type].
5556-
/// Otherwise, return the original type.
5557-
DartType _toLegacyType(DartType type) {
5558-
if (_isNonNullableByDefault) return type;
5559-
return NullabilityEliminator.perform(_typeProvider, type);
5560-
}
5561-
55625524
/**
55635525
* Return [FieldElement]s that are declared in the [ClassDeclaration] with
55645526
* the given [constructor], but are not initialized.

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,30 @@ class C extends B implements A<int> {}
125125
''');
126126
}
127127

128+
test_class_mixed_viaLegacy() async {
129+
newFile('/test/lib/a.dart', content: r'''
130+
class A<T> {}
131+
132+
class Bi implements A<int> {}
133+
134+
class Biq implements A<int?> {}
135+
''');
136+
137+
// Both `Bi` and `Biq` implement `A<int*>` in legacy, so identical.
138+
newFile('/test/lib/b.dart', content: r'''
139+
// @dart = 2.7
140+
import 'a.dart';
141+
142+
class C extends Bi implements Biq {}
143+
''');
144+
145+
await assertNoErrorsInCode(r'''
146+
import 'b.dart';
147+
148+
abstract class D implements C {}
149+
''');
150+
}
151+
128152
test_class_topMerge() async {
129153
await assertNoErrorsInCode('''
130154
import 'dart:async';

0 commit comments

Comments
 (0)