@@ -415,15 +415,27 @@ private module Input3 implements InputSig3 {
415415 }
416416
417417 bindingset [ derefChainBorrow]
418- Type inferCallTypeIn ( Call call , string derefChainBorrow , FunctionPosition pos , TypePath path ) {
418+ Type inferCallTypeBottomUp ( Call call , string derefChainBorrow , FunctionPosition pos , TypePath path ) {
419419 result = call .( FunctionCallMatchingInput:: Access ) .getInferredType ( derefChainBorrow , pos , path )
420420 }
421421
422- Type inferCallTypeOut ( AstNode n , TypePosition pos , TypePath path ) {
423- result = inferFunctionCallTypeNonSelf ( n , pos , path )
422+ Type inferCallReturnType ( AstNode n , TypePath path ) {
423+ exists ( Call call , TypePath path0 |
424+ result = inferCallReturnType ( call , _, n , path0 ) and
425+ if
426+ // index expression `x[i]` desugars to `*x.index(i)`, so we must account for
427+ // the implicit deref
428+ call instanceof IndexExpr
429+ then path0 .isCons ( getRefTypeParameter ( _) , path )
430+ else path = path0
431+ )
432+ }
433+
434+ Type inferCallArgumentTypeTopDown ( AstNode n , TypePath path ) {
435+ result = inferFunctionCallNonSelfArgumentTypeTopDown ( n , path )
424436 or
425437 exists ( FunctionCallMatchingInput:: Access a |
426- result = inferFunctionCallTypeSelf ( a , n , DerefChain:: nil ( ) , path ) and
438+ result = inferFunctionCallSelfArgumentTypeTopDown ( a , n , DerefChain:: nil ( ) , path ) and
427439 if a .( AssocFunctionResolution:: AssocFunctionCall ) .hasReceiver ( )
428440 then not path .isEmpty ( )
429441 else any ( )
@@ -459,7 +471,7 @@ private module Input3 implements InputSig3 {
459471 )
460472 }
461473
462- Type inferTypeCertainInput ( AstNode n , TypePath path ) {
474+ Type inferTypeCertainSpecific ( AstNode n , TypePath path ) {
463475 result = inferFunctionBodyType ( n , path )
464476 or
465477 result = inferLiteralType ( n , path , true )
@@ -580,36 +592,31 @@ private module Input3 implements InputSig3 {
580592 prefix1 .isEmpty ( )
581593 }
582594
583- /**
584- * Holds if `child` is a child of `parent`, and the Rust compiler applies [least
585- * upper bound (LUB) coercion][1] to infer the type of `parent` from the type of
586- * `child`.
587- *
588- * In this case, we want type information to only flow from `child` to `parent`,
589- * to avoid (a) either having to model LUB coercions, or (b) risk combinatorial
590- * explosion in inferred types.
591- *
592- * [1]: https://doc.rust-lang.org/reference/type-coercions.html#r-coerce.least-upper-bound
593- */
594- predicate inferLubStep ( AstNode child , TypePath path1 , AstNode parent , TypePath prefix ) {
595+ predicate inferLubStep ( AstNode n1 , TypePath path1 , AstNode n2 , TypePath path2 ) {
595596 path1 .isEmpty ( ) and
596597 (
597- parent = any ( ArrayListExpr ale | child = ale .getAnExpr ( ) ) and
598- prefix = TypePath:: singleton ( getArrayTypeParameter ( ) )
598+ n2 = any ( ArrayListExpr ale | n1 = ale .getAnExpr ( ) ) and
599+ path2 = TypePath:: singleton ( getArrayTypeParameter ( ) )
599600 or
600- bodyReturns ( parent , child ) and
601- prefix .isEmpty ( )
601+ bodyReturns ( n2 , n1 ) and
602+ path2 .isEmpty ( )
602603 or
603604 exists ( Struct s |
604- child = [ parent .( RangeExpr ) .getStart ( ) , parent .( RangeExpr ) .getEnd ( ) ] and
605- prefix =
605+ n1 = [ n2 .( RangeExpr ) .getStart ( ) , n2 .( RangeExpr ) .getEnd ( ) ] and
606+ path2 =
606607 TypePath:: singleton ( TTypeParamTypeParameter ( s .getGenericParamList ( ) .getATypeParam ( ) ) ) and
607- s = getRangeType ( parent )
608+ s = getRangeType ( n2 )
608609 )
609610 )
610611 }
611612
612- Type inferTypeInput ( AstNode n , TypePath path ) {
613+ Type inferTypeTopDown ( AstNode n , TypePath path ) {
614+ result = inferTypeFromAnnotationTopDown ( n , path )
615+ or
616+ result = inferClosureExprBodyTypeTopDown ( n , path )
617+ }
618+
619+ Type inferTypeSpecific ( AstNode n , TypePath path ) {
613620 result = inferAssignmentOperationType ( n , path )
614621 or
615622 result = inferConstructionType ( n , path )
@@ -634,7 +641,7 @@ private module Input3 implements InputSig3 {
634641 or
635642 result = inferDeconstructionPatType ( n , path )
636643 or
637- result = inferUnknownTypeFromAnnotation ( n , path )
644+ result = inferUnknownType ( n , path )
638645 }
639646}
640647
@@ -928,9 +935,6 @@ private Type inferTypeFromAnnotationTopDown(AstNode n, TypePath path) {
928935 )
929936}
930937
931- private predicate inferUnknownTypeFromAnnotation =
932- TopDownTyping< inferTypeFromAnnotationTopDown / 2 > :: inferType / 2 ;
933-
934938pragma [ nomagic]
935939private TupleType inferTupleRootType ( AstNode n ) {
936940 // `typeEquality` handles the non-root cases
@@ -2802,35 +2806,20 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
28022806}
28032807
28042808pragma [ nomagic]
2805- private Type inferFunctionCallType0 (
2809+ private Type inferCallArgumentTypeTopDown (
28062810 FunctionCallMatchingInput:: Access call , FunctionPosition pos , AstNode n , DerefChain derefChain ,
28072811 BorrowKind borrow , TypePath path
28082812) {
2809- exists ( TypePath path0 |
2810- exists ( string derefChainBorrow |
2811- FunctionCallMatchingInput:: decodeDerefChainBorrow ( derefChainBorrow , derefChain , borrow )
2812- |
2813- n = call .getNodeAt ( pos ) and
2814- call .hasUnknownTypeAt ( derefChainBorrow , pos , path0 ) and
2815- result = TUnknownType ( )
2816- or
2817- result = inferCallTypeOut ( call , derefChainBorrow , pos , n , path0 )
2818- )
2819- |
2820- if
2821- // index expression `x[i]` desugars to `*x.index(i)`, so we must account for
2822- // the implicit deref
2823- pos .isReturn ( ) and
2824- call instanceof IndexExpr
2825- then path0 .isCons ( getRefTypeParameter ( _) , path )
2826- else path = path0
2813+ exists ( string derefChainBorrow |
2814+ FunctionCallMatchingInput:: decodeDerefChainBorrow ( derefChainBorrow , derefChain , borrow ) and
2815+ result = inferCallArgumentTypeTopDown ( call , derefChainBorrow , pos , n , path )
28272816 )
28282817}
28292818
28302819pragma [ nomagic]
2831- private Type inferFunctionCallTypeNonSelf ( AstNode n , FunctionPosition pos , TypePath path ) {
2832- exists ( FunctionCallMatchingInput:: Access call |
2833- result = inferFunctionCallType0 ( call , pos , n , _, _, path ) and
2820+ private Type inferFunctionCallNonSelfArgumentTypeTopDown ( AstNode n , TypePath path ) {
2821+ exists ( FunctionCallMatchingInput:: Access call , FunctionPosition pos |
2822+ result = inferCallArgumentTypeTopDown ( call , pos , n , _, _, path ) and
28342823 not call .( AssocFunctionResolution:: AssocFunctionCall ) .hasReceiverAtPos ( pos )
28352824 )
28362825}
@@ -2843,12 +2832,12 @@ private Type inferFunctionCallTypeNonSelf(AstNode n, FunctionPosition pos, TypeP
28432832 * empty, at which point the inferred type can be applied back to `n`.
28442833 */
28452834pragma [ nomagic]
2846- private Type inferFunctionCallTypeSelf (
2835+ private Type inferFunctionCallSelfArgumentTypeTopDown (
28472836 FunctionCallMatchingInput:: Access call , AstNode n , DerefChain derefChain , TypePath path
28482837) {
28492838 exists ( FunctionPosition pos , BorrowKind borrow , TypePath path0 |
28502839 call .( AssocFunctionResolution:: AssocFunctionCall ) .hasReceiverAtPos ( pos ) and
2851- result = inferFunctionCallType0 ( call , pos , n , derefChain , borrow , path0 )
2840+ result = inferCallArgumentTypeTopDown ( call , pos , n , derefChain , borrow , path0 )
28522841 |
28532842 borrow .isNoBorrow ( ) and
28542843 path = path0
@@ -2865,7 +2854,7 @@ private Type inferFunctionCallTypeSelf(
28652854 DerefChain derefChain0 , Type t0 , TypePath path0 , DerefImplItemNode impl , Type selfParamType ,
28662855 TypePath selfPath
28672856 |
2868- t0 = inferFunctionCallTypeSelf ( call , n , derefChain0 , path0 ) and
2857+ t0 = inferFunctionCallSelfArgumentTypeTopDown ( call , n , derefChain0 , path0 ) and
28692858 derefChain0 .isCons ( impl , derefChain ) and
28702859 selfParamType = impl .resolveSelfTypeAt ( selfPath )
28712860 |
@@ -3041,17 +3030,37 @@ private module ConstructionMatching = Matching<ConstructionMatchingInput>;
30413030
30423031pragma [ nomagic]
30433032private Type inferConstructionTypePreCheck ( AstNode n , FunctionPosition pos , TypePath path ) {
3044- exists ( ConstructionMatchingInput:: Access a | n = a .getNodeAt ( pos ) |
3033+ exists ( ConstructionMatchingInput:: Access a |
3034+ n = a .getNodeAt ( pos ) and
30453035 result = ConstructionMatching:: inferAccessType ( a , pos , path )
3046- or
3047- a .hasUnknownTypeAt ( pos , path ) and
3048- result = TUnknownType ( )
30493036 )
30503037}
30513038
30523039private predicate inferConstructionType =
30533040 CheckContextTyping< inferConstructionTypePreCheck / 3 > :: check / 2 ;
30543041
3042+ pragma [ nomagic]
3043+ private Type inferUnknownType ( AstNode n , TypePath path ) {
3044+ result = TUnknownType ( ) and
3045+ (
3046+ exists ( FunctionCallMatchingInput:: Access call , FunctionPosition pos |
3047+ n = call .getNodeAt ( pos ) and
3048+ call .hasUnknownTypeAt ( _, pos , path )
3049+ )
3050+ or
3051+ exists ( ConstructionMatchingInput:: Access a , FunctionPosition pos |
3052+ n = a .getNodeAt ( pos ) and
3053+ a .hasUnknownTypeAt ( pos , path )
3054+ )
3055+ or
3056+ exists ( Param p |
3057+ not p .hasTypeRepr ( ) and
3058+ n = p .getPat ( ) and
3059+ path .isEmpty ( )
3060+ )
3061+ )
3062+ }
3063+
30553064/**
30563065 * A matching configuration for resolving types of operations like `a + b`.
30573066 */
@@ -3633,29 +3642,14 @@ private Type inferClosureExprBodyTypeTopDown(AstNode n, TypePath path) {
36333642}
36343643
36353644pragma [ nomagic]
3636- private Type inferClosureExprType ( AstNode n , TypePath path ) {
3637- exists ( ClosureExpr ce |
3638- n = ce and
3639- (
3640- path = TypePath:: singleton ( TDynTraitTypeParameter ( _, any ( FnTrait t ) .getTypeParam ( ) ) ) and
3641- result .( TupleType ) .getArity ( ) = ce .getNumberOfParams ( )
3642- or
3643- exists ( TypePath path0 |
3644- result = ce .getRetType ( ) .getTypeRepr ( ) .( TypeMention ) .getTypeAt ( path0 ) and
3645- path = closureReturnPath ( ) .append ( path0 )
3646- )
3647- )
3648- or
3649- exists ( Param p |
3650- p = ce .getAParam ( ) and
3651- not p .hasTypeRepr ( ) and
3652- n = p .getPat ( ) and
3653- result = TUnknownType ( ) and
3654- path .isEmpty ( )
3655- )
3656- )
3645+ private Type inferClosureExprType ( ClosureExpr ce , TypePath path ) {
3646+ path = TypePath:: singleton ( TDynTraitTypeParameter ( _, any ( FnTrait t ) .getTypeParam ( ) ) ) and
3647+ result .( TupleType ) .getArity ( ) = ce .getNumberOfParams ( )
36573648 or
3658- result = TopDownTyping< inferClosureExprBodyTypeTopDown / 2 > :: inferType ( n , path )
3649+ exists ( TypePath suffix |
3650+ result = ce .getRetType ( ) .getTypeRepr ( ) .( TypeMention ) .getTypeAt ( suffix ) and
3651+ path = closureReturnPath ( ) .append ( suffix )
3652+ )
36593653}
36603654
36613655pragma [ nomagic]
0 commit comments