mirror of
https://github.com/dart-lang/sdk
synced 2024-10-02 00:22:55 +00:00
analyzer: Support implicit call tearoff from type variable
Fixes https://github.com/dart-lang/sdk/issues/54353 Change-Id: I0b7725efb6380de35832f1a713df3b4139990f0b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/346947 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
parent
6f97eb264a
commit
63399a992c
|
@ -293,6 +293,14 @@ mixin ErrorDetectionHelpers {
|
|||
/// > is a function type or the type `Function`, `e` is treated as `e.call`.
|
||||
MethodElement? getImplicitCallMethod(
|
||||
DartType type, DartType? context, SyntacticEntity errorNode) {
|
||||
var visitedTypes = {type};
|
||||
while (type is TypeParameterType) {
|
||||
type = type.bound;
|
||||
if (!visitedTypes.add(type)) {
|
||||
// A cycle!
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (context != null &&
|
||||
typeSystem.acceptsFunctionType(context) &&
|
||||
type is InterfaceType &&
|
||||
|
|
|
@ -538,6 +538,68 @@ ImplicitCallReference
|
|||
staticType: C
|
||||
staticElement: self::@class::C::@method::call
|
||||
staticType: void Function(int)
|
||||
''');
|
||||
}
|
||||
|
||||
test_simpleIdentifier_typeAlias() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A {
|
||||
void call() {}
|
||||
}
|
||||
typedef B = A;
|
||||
Function f(B b) => b;
|
||||
''');
|
||||
|
||||
final node = findNode.implicitCallReference('b;');
|
||||
assertResolvedNodeText(node, r'''
|
||||
ImplicitCallReference
|
||||
expression: SimpleIdentifier
|
||||
token: b
|
||||
staticElement: self::@function::f::@parameter::b
|
||||
staticType: A
|
||||
alias: self::@typeAlias::B
|
||||
staticElement: self::@class::A::@method::call
|
||||
staticType: void Function()
|
||||
''');
|
||||
}
|
||||
|
||||
test_simpleIdentifier_typeVariable() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A {
|
||||
void call() {}
|
||||
}
|
||||
Function f<X extends A>(X x) => x;
|
||||
''');
|
||||
|
||||
final node = findNode.implicitCallReference('x;');
|
||||
assertResolvedNodeText(node, r'''
|
||||
ImplicitCallReference
|
||||
expression: SimpleIdentifier
|
||||
token: x
|
||||
staticElement: self::@function::f::@parameter::x
|
||||
staticType: X
|
||||
staticElement: self::@class::A::@method::call
|
||||
staticType: void Function()
|
||||
''');
|
||||
}
|
||||
|
||||
test_simpleIdentifier_typeVariable2() async {
|
||||
await assertNoErrorsInCode('''
|
||||
class A {
|
||||
void call() {}
|
||||
}
|
||||
Function f<X extends A, Y extends X>(Y y) => y;
|
||||
''');
|
||||
|
||||
final node = findNode.implicitCallReference('y;');
|
||||
assertResolvedNodeText(node, r'''
|
||||
ImplicitCallReference
|
||||
expression: SimpleIdentifier
|
||||
token: y
|
||||
staticElement: self::@function::f::@parameter::y
|
||||
staticType: Y
|
||||
staticElement: self::@class::A::@method::call
|
||||
staticType: void Function()
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue