Skip to content

Commit 63046da

Browse files
author
John Messerly
committed
fix #25740 again, making sure we have the substituted bound in inference
The first fix only addressed part of the problem. Unfortunately we go back and forth between .element and .type, assuming they always return the other one, which was not the case for TypeParameterMember. [email protected] Review URL: https://codereview.chromium.org/2291103004 .
1 parent 2ee5807 commit 63046da

File tree

3 files changed

+97
-6
lines changed

3 files changed

+97
-6
lines changed

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -937,9 +937,13 @@ class TypeParameterMember extends Member implements TypeParameterElement {
937937
@override
938938
final DartType bound;
939939

940+
DartType _type;
941+
940942
TypeParameterMember(
941943
TypeParameterElement baseElement, DartType definingType, this.bound)
942-
: super(baseElement, definingType);
944+
: super(baseElement, definingType) {
945+
_type = new TypeParameterTypeImpl(this);
946+
}
943947

944948
@override
945949
TypeParameterElement get baseElement =>
@@ -949,11 +953,20 @@ class TypeParameterMember extends Member implements TypeParameterElement {
949953
Element get enclosingElement => baseElement.enclosingElement;
950954

951955
@override
952-
TypeParameterType get type => baseElement.type;
956+
TypeParameterType get type => _type;
953957

954958
@override
955959
accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);
956960

961+
@override
962+
int get hashCode => baseElement.hashCode;
963+
964+
@override
965+
bool operator ==(obj) =>
966+
// TODO(jmesserly): this equality should consider the bound, see:
967+
// https://github.com/dart-lang/sdk/issues/27210
968+
obj is TypeParameterMember && obj.baseElement == baseElement;
969+
957970
/**
958971
* If the given [parameter]'s type is different when any type parameters from
959972
* the defining type's declaration are replaced with the actual type

pkg/analyzer/test/generated/type_system_test.dart

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,80 @@ class StrongGenericFunctionInferenceTest {
881881
]);
882882
}
883883

884+
void test_boundedByOuterClass() {
885+
// Regression test for https://github.com/dart-lang/sdk/issues/25740.
886+
887+
// class A {}
888+
var a = ElementFactory.classElement('A', objectType);
889+
890+
// class B extends A {}
891+
var b = ElementFactory.classElement('B', a.type);
892+
893+
// class C<T extends A> {
894+
var c = ElementFactory.classElement('C', objectType, ['T']);
895+
(c.typeParameters[0] as TypeParameterElementImpl).bound = a.type;
896+
// S m<S extends T>(S);
897+
var s = TypeBuilder.variable('S');
898+
(s.element as TypeParameterElementImpl).bound = c.typeParameters[0].type;
899+
var m = ElementFactory.methodElement('m', s, [s]);
900+
m.typeParameters = [s.element];
901+
c.methods = [m];
902+
// }
903+
904+
// C<Object> cOfObject;
905+
var cOfObject = c.type.instantiate([objectType]);
906+
// C<A> cOfA;
907+
var cOfA = c.type.instantiate([a.type]);
908+
// C<B> cOfB;
909+
var cOfB = c.type.instantiate([b.type]);
910+
// B b;
911+
// cOfB.m(b); // infer <B>
912+
expect(_inferCall(cOfB.getMethod('m').type, [b.type]), [b.type, b.type]);
913+
// cOfA.m(b); // infer <B>
914+
expect(_inferCall(cOfA.getMethod('m').type, [b.type]), [a.type, b.type]);
915+
// cOfObject.m(b); // infer <B>
916+
expect(_inferCall(cOfObject.getMethod('m').type, [b.type]),
917+
[objectType, b.type]);
918+
}
919+
920+
void test_boundedByOuterClassSubstituted() {
921+
// Regression test for https://github.com/dart-lang/sdk/issues/25740.
922+
923+
// class A {}
924+
var a = ElementFactory.classElement('A', objectType);
925+
926+
// class B extends A {}
927+
var b = ElementFactory.classElement('B', a.type);
928+
929+
// class C<T extends A> {
930+
var c = ElementFactory.classElement('C', objectType, ['T']);
931+
(c.typeParameters[0] as TypeParameterElementImpl).bound = a.type;
932+
// S m<S extends Iterable<T>>(S);
933+
var s = TypeBuilder.variable('S');
934+
var iterableOfT = iterableType.instantiate([c.typeParameters[0].type]);
935+
(s.element as TypeParameterElementImpl).bound = iterableOfT;
936+
var m = ElementFactory.methodElement('m', s, [s]);
937+
m.typeParameters = [s.element];
938+
c.methods = [m];
939+
// }
940+
941+
// C<Object> cOfObject;
942+
var cOfObject = c.type.instantiate([objectType]);
943+
// C<A> cOfA;
944+
var cOfA = c.type.instantiate([a.type]);
945+
// C<B> cOfB;
946+
var cOfB = c.type.instantiate([b.type]);
947+
// List<B> b;
948+
var listOfB = listType.instantiate([b.type]);
949+
// cOfB.m(b); // infer <B>
950+
expect(_inferCall(cOfB.getMethod('m').type, [listOfB]), [b.type, listOfB]);
951+
// cOfA.m(b); // infer <B>
952+
expect(_inferCall(cOfA.getMethod('m').type, [listOfB]), [a.type, listOfB]);
953+
// cOfObject.m(b); // infer <B>
954+
expect(_inferCall(cOfObject.getMethod('m').type, [listOfB]),
955+
[objectType, listOfB]);
956+
}
957+
884958
void test_boundedRecursively() {
885959
// class Clonable<T extends Clonable<T>>
886960
ClassElementImpl clonable =

pkg/analyzer/test/src/task/strong/inferred_type_test.dart

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,14 +1761,18 @@ main() {
17611761
// Regression test for https://github.com/dart-lang/sdk/issues/25740.
17621762
checkFile(r'''
17631763
class Foo<T extends Pattern> {
1764-
void method/*<U extends T>*/(dynamic/*=U*/ u) {}
1764+
/*=U*/ method/*<U extends T>*/(/*=U*/ u) => u;
17651765
}
17661766
main() {
1767-
new Foo().method/*<String>*/("str");
1767+
String s;
1768+
var a = new Foo().method/*<String>*/("str");
1769+
s = a;
17681770
new Foo();
17691771
1770-
new Foo<String>().method("str");
1771-
new Foo().method("str");
1772+
var b = new Foo<String>().method("str");
1773+
s = b;
1774+
var c = new Foo().method("str");
1775+
s = c;
17721776
17731777
new Foo<String>().method(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/42);
17741778
}

0 commit comments

Comments
 (0)