@@ -467,11 +467,12 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
467
467
isNonNullableByDefault: isNonNullableByDefault,
468
468
isVoidAllowed: isVoidAllowed,
469
469
isExpressionTypePrecise: preciseTypeErrorTemplate != null ,
470
- coerceExpression: coerceExpression);
470
+ coerceExpression: coerceExpression,
471
+ fileOffset: fileOffset);
471
472
472
473
if (assignabilityResult.needsTearOff) {
473
- TypedTearoff typedTearoff = _tearOffCall (inferenceResult.expression,
474
- inferenceResult.inferredType as InterfaceType , fileOffset);
474
+ TypedTearoff typedTearoff = _tearOffCall (
475
+ inferenceResult.expression, inferenceResult.inferredType , fileOffset);
475
476
inferenceResult = new ExpressionInferenceResult (
476
477
typedTearoff.tearoffType, typedTearoff.tearoff);
477
478
}
@@ -577,11 +578,12 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
577
578
isNonNullableByDefault: isNonNullableByDefault,
578
579
isVoidAllowed: isVoidAllowed,
579
580
isExpressionTypePrecise: preciseTypeErrorTemplate != null ,
580
- coerceExpression: isCoercionAllowed);
581
+ coerceExpression: isCoercionAllowed,
582
+ fileOffset: fileOffset);
581
583
582
584
if (assignabilityResult.needsTearOff) {
583
- TypedTearoff typedTearoff = _tearOffCall (inferenceResult.expression,
584
- inferenceResult.inferredType as InterfaceType , fileOffset);
585
+ TypedTearoff typedTearoff = _tearOffCall (
586
+ inferenceResult.expression, inferenceResult.inferredType , fileOffset);
585
587
inferenceResult = new ExpressionInferenceResult (
586
588
typedTearoff.tearoffType, typedTearoff.tearoff);
587
589
}
@@ -788,10 +790,10 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
788
790
}
789
791
790
792
TypedTearoff _tearOffCall (
791
- Expression expression, InterfaceType expressionType, int fileOffset) {
792
- Class classNode = expressionType.classNode;
793
- Member callMember = membersBuilder. getInterfaceMember (classNode , callName) ! ;
794
- assert (callMember is Procedure && callMember.kind == ProcedureKind . Method );
793
+ Expression expression, DartType expressionType, int fileOffset) {
794
+ ObjectAccessTarget target = findInterfaceMember (
795
+ expressionType , callName, fileOffset,
796
+ isSetter : false );
795
797
796
798
// Replace expression with:
797
799
// `let t = expression in t == null ? null : t.call`
@@ -804,13 +806,44 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
804
806
new EqualsNull (new VariableGet (t)..fileOffset = fileOffset)
805
807
..fileOffset = fileOffset;
806
808
807
- DartType tearoffType =
808
- getGetterTypeForMemberTarget (callMember, expressionType, isSuper: false )
809
- .withDeclaredNullability (expressionType.nullability);
810
- Expression tearOff = new InstanceTearOff (
811
- InstanceAccessKind .Instance , new VariableGet (t), callName,
812
- interfaceTarget: callMember as Procedure , resultType: tearoffType)
813
- ..fileOffset = fileOffset;
809
+ DartType tearoffType = target.getGetterType (this );
810
+ Expression tearOff;
811
+ switch (target.kind) {
812
+ case ObjectAccessTargetKind .instanceMember:
813
+ tearOff = new InstanceTearOff (
814
+ InstanceAccessKind .Instance , new VariableGet (t), callName,
815
+ interfaceTarget: target.member as Procedure ,
816
+ resultType: tearoffType)
817
+ ..fileOffset = fileOffset;
818
+ case ObjectAccessTargetKind .extensionTypeMember:
819
+ tearOff = new StaticInvocation (
820
+ target.tearoffTarget as Procedure ,
821
+ new Arguments ([new VariableGet (t)],
822
+ types: target.receiverTypeArguments)
823
+ ..fileOffset = fileOffset)
824
+ ..fileOffset = fileOffset;
825
+ case ObjectAccessTargetKind .extensionTypeRepresentation:
826
+ case ObjectAccessTargetKind .nullableInstanceMember:
827
+ case ObjectAccessTargetKind .objectMember:
828
+ case ObjectAccessTargetKind .superMember:
829
+ case ObjectAccessTargetKind .callFunction:
830
+ case ObjectAccessTargetKind .nullableCallFunction:
831
+ case ObjectAccessTargetKind .extensionMember:
832
+ case ObjectAccessTargetKind .nullableExtensionMember:
833
+ case ObjectAccessTargetKind .dynamic :
834
+ case ObjectAccessTargetKind .never:
835
+ case ObjectAccessTargetKind .invalid:
836
+ case ObjectAccessTargetKind .missing:
837
+ case ObjectAccessTargetKind .ambiguous:
838
+ case ObjectAccessTargetKind .recordIndexed:
839
+ case ObjectAccessTargetKind .recordNamed:
840
+ case ObjectAccessTargetKind .nullableRecordIndexed:
841
+ case ObjectAccessTargetKind .nullableRecordNamed:
842
+ case ObjectAccessTargetKind .nullableExtensionTypeMember:
843
+ case ObjectAccessTargetKind .nullableExtensionTypeRepresentation:
844
+ throw new UnsupportedError ("Unexpected call tear-off $target ." );
845
+ }
846
+
814
847
ConditionalExpression conditional = new ConditionalExpression (nullCheck,
815
848
new NullLiteral ()..fileOffset = fileOffset, tearOff, tearoffType);
816
849
return new TypedTearoff (
@@ -825,30 +858,53 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
825
858
{required bool isNonNullableByDefault,
826
859
required bool isVoidAllowed,
827
860
required bool isExpressionTypePrecise,
828
- required bool coerceExpression}) {
861
+ required bool coerceExpression,
862
+ required int fileOffset}) {
829
863
// If an interface type is being assigned to a function type, see if we
830
864
// should tear off `.call`.
831
865
// TODO(paulberry): use resolveTypeParameter. See findInterfaceMember.
832
866
bool needsTearoff = false ;
833
- if (coerceExpression &&
834
- expressionType is InterfaceType &&
835
- _shouldMaybeTearOffCall (contextType)) {
836
- Class classNode = expressionType.classNode;
837
- Member ? callMember =
838
- membersBuilder.getInterfaceMember (classNode, callName);
839
- if (callMember is Procedure && callMember.kind == ProcedureKind .Method ) {
840
- if (_shouldTearOffCall (contextType, expressionType)) {
841
- needsTearoff = true ;
842
- if (isNonNullableByDefault && expressionType.isPotentiallyNullable) {
843
- return const AssignabilityResult (
844
- AssignabilityKind .unassignableCantTearoff,
845
- needsTearOff: false );
846
- }
847
- expressionType = getGetterTypeForMemberTarget (
848
- callMember, expressionType,
849
- isSuper: false )
850
- .withDeclaredNullability (expressionType.nullability);
867
+ if (coerceExpression && _shouldTearOffCall (contextType, expressionType)) {
868
+ ObjectAccessTarget target = findInterfaceMember (
869
+ expressionType, callName, fileOffset,
870
+ isSetter: false );
871
+ bool shouldTearOff;
872
+ switch (target.kind) {
873
+ case ObjectAccessTargetKind .instanceMember:
874
+ case ObjectAccessTargetKind .nullableInstanceMember:
875
+ Member ? member = target.member;
876
+ shouldTearOff =
877
+ member is Procedure && member.kind == ProcedureKind .Method ;
878
+ case ObjectAccessTargetKind .extensionTypeMember:
879
+ case ObjectAccessTargetKind .nullableExtensionTypeMember:
880
+ shouldTearOff = target.tearoffTarget is Procedure ;
881
+ case ObjectAccessTargetKind .objectMember:
882
+ case ObjectAccessTargetKind .superMember:
883
+ case ObjectAccessTargetKind .extensionMember:
884
+ case ObjectAccessTargetKind .nullableExtensionMember:
885
+ case ObjectAccessTargetKind .dynamic :
886
+ case ObjectAccessTargetKind .never:
887
+ case ObjectAccessTargetKind .invalid:
888
+ case ObjectAccessTargetKind .missing:
889
+ case ObjectAccessTargetKind .ambiguous:
890
+ case ObjectAccessTargetKind .recordIndexed:
891
+ case ObjectAccessTargetKind .recordNamed:
892
+ case ObjectAccessTargetKind .nullableRecordIndexed:
893
+ case ObjectAccessTargetKind .nullableRecordNamed:
894
+ case ObjectAccessTargetKind .callFunction:
895
+ case ObjectAccessTargetKind .nullableCallFunction:
896
+ case ObjectAccessTargetKind .extensionTypeRepresentation:
897
+ case ObjectAccessTargetKind .nullableExtensionTypeRepresentation:
898
+ shouldTearOff = false ;
899
+ }
900
+ if (shouldTearOff) {
901
+ needsTearoff = true ;
902
+ if (isNonNullableByDefault && target.isNullable) {
903
+ return const AssignabilityResult (
904
+ AssignabilityKind .unassignableCantTearoff,
905
+ needsTearOff: false );
851
906
}
907
+ expressionType = target.getGetterType (this );
852
908
}
853
909
}
854
910
ImplicitInstantiation ? implicitInstantiation;
@@ -3838,19 +3894,6 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
3838
3894
return false ;
3839
3895
}
3840
3896
3841
- bool _shouldMaybeTearOffCall (DartType contextType) {
3842
- if (contextType is FutureOrType ) {
3843
- contextType = contextType.typeArgument;
3844
- }
3845
- if (contextType is FunctionType ) return true ;
3846
- if (contextType is InterfaceType &&
3847
- contextType.classReference ==
3848
- typeSchemaEnvironment.functionClass.reference) {
3849
- return true ;
3850
- }
3851
- return false ;
3852
- }
3853
-
3854
3897
/// Creates an expression the represents the invalid invocation of [name] on
3855
3898
/// [receiver] with [arguments] .
3856
3899
///
0 commit comments