@@ -415,15 +415,30 @@ 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+ exists ( FunctionCallMatchingInput:: Access call , FunctionPosition pos |
436+ result = inferCallArgumentTypeTopDown ( call , pos , n , _, _, path ) and
437+ not call .( AssocFunctionResolution:: AssocFunctionCall ) .hasReceiverAtPos ( pos )
438+ )
424439 or
425440 exists ( FunctionCallMatchingInput:: Access a |
426- result = inferFunctionCallTypeSelf ( a , n , DerefChain:: nil ( ) , path ) and
441+ result = inferFunctionCallSelfArgumentTypeTopDown ( a , n , DerefChain:: nil ( ) , path ) and
427442 if a .( AssocFunctionResolution:: AssocFunctionCall ) .hasReceiver ( )
428443 then not path .isEmpty ( )
429444 else any ( )
@@ -459,7 +474,7 @@ private module Input3 implements InputSig3 {
459474 )
460475 }
461476
462- Type inferTypeCertainInput ( AstNode n , TypePath path ) {
477+ Type inferTypeCertainSpecific ( AstNode n , TypePath path ) {
463478 result = inferFunctionBodyType ( n , path )
464479 or
465480 result = inferLiteralType ( n , path , true )
@@ -580,36 +595,31 @@ private module Input3 implements InputSig3 {
580595 prefix1 .isEmpty ( )
581596 }
582597
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 ) {
598+ predicate inferLubStep ( AstNode n1 , TypePath path1 , AstNode n2 , TypePath path2 ) {
595599 path1 .isEmpty ( ) and
596600 (
597- parent = any ( ArrayListExpr ale | child = ale .getAnExpr ( ) ) and
598- prefix = TypePath:: singleton ( getArrayTypeParameter ( ) )
601+ n2 = any ( ArrayListExpr ale | n1 = ale .getAnExpr ( ) ) and
602+ path2 = TypePath:: singleton ( getArrayTypeParameter ( ) )
599603 or
600- bodyReturns ( parent , child ) and
601- prefix .isEmpty ( )
604+ bodyReturns ( n2 , n1 ) and
605+ path2 .isEmpty ( )
602606 or
603607 exists ( Struct s |
604- child = [ parent .( RangeExpr ) .getStart ( ) , parent .( RangeExpr ) .getEnd ( ) ] and
605- prefix =
608+ n1 = [ n2 .( RangeExpr ) .getStart ( ) , n2 .( RangeExpr ) .getEnd ( ) ] and
609+ path2 =
606610 TypePath:: singleton ( TTypeParamTypeParameter ( s .getGenericParamList ( ) .getATypeParam ( ) ) ) and
607- s = getRangeType ( parent )
611+ s = getRangeType ( n2 )
608612 )
609613 )
610614 }
611615
612- Type inferTypeInput ( AstNode n , TypePath path ) {
616+ Type inferTypeTopDown ( AstNode n , TypePath path ) {
617+ result = inferTypeFromAnnotationTopDown ( n , path )
618+ or
619+ result = inferClosureExprBodyTypeTopDown ( n , path )
620+ }
621+
622+ Type inferTypeSpecific ( AstNode n , TypePath path ) {
613623 result = inferAssignmentOperationType ( n , path )
614624 or
615625 result = inferConstructionType ( n , path )
@@ -634,7 +644,7 @@ private module Input3 implements InputSig3 {
634644 or
635645 result = inferDeconstructionPatType ( n , path )
636646 or
637- result = inferUnknownTypeFromAnnotation ( n , path )
647+ result = inferUnknownType ( n , path )
638648 }
639649}
640650
@@ -928,9 +938,6 @@ private Type inferTypeFromAnnotationTopDown(AstNode n, TypePath path) {
928938 )
929939}
930940
931- private predicate inferUnknownTypeFromAnnotation =
932- TopDownTyping< inferTypeFromAnnotationTopDown / 2 > :: inferType / 2 ;
933-
934941pragma [ nomagic]
935942private TupleType inferTupleRootType ( AstNode n ) {
936943 // `typeEquality` handles the non-root cases
@@ -2802,36 +2809,13 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
28022809}
28032810
28042811pragma [ nomagic]
2805- private Type inferFunctionCallType0 (
2812+ private Type inferCallArgumentTypeTopDown (
28062813 FunctionCallMatchingInput:: Access call , FunctionPosition pos , AstNode n , DerefChain derefChain ,
28072814 BorrowKind borrow , TypePath path
28082815) {
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
2827- )
2828- }
2829-
2830- pragma [ nomagic]
2831- private Type inferFunctionCallTypeNonSelf ( AstNode n , FunctionPosition pos , TypePath path ) {
2832- exists ( FunctionCallMatchingInput:: Access call |
2833- result = inferFunctionCallType0 ( call , pos , n , _, _, path ) and
2834- not call .( AssocFunctionResolution:: AssocFunctionCall ) .hasReceiverAtPos ( pos )
2816+ exists ( string derefChainBorrow |
2817+ FunctionCallMatchingInput:: decodeDerefChainBorrow ( derefChainBorrow , derefChain , borrow ) and
2818+ result = inferCallArgumentTypeTopDown ( call , derefChainBorrow , pos , n , path )
28352819 )
28362820}
28372821
@@ -2843,12 +2827,12 @@ private Type inferFunctionCallTypeNonSelf(AstNode n, FunctionPosition pos, TypeP
28432827 * empty, at which point the inferred type can be applied back to `n`.
28442828 */
28452829pragma [ nomagic]
2846- private Type inferFunctionCallTypeSelf (
2830+ private Type inferFunctionCallSelfArgumentTypeTopDown (
28472831 FunctionCallMatchingInput:: Access call , AstNode n , DerefChain derefChain , TypePath path
28482832) {
28492833 exists ( FunctionPosition pos , BorrowKind borrow , TypePath path0 |
28502834 call .( AssocFunctionResolution:: AssocFunctionCall ) .hasReceiverAtPos ( pos ) and
2851- result = inferFunctionCallType0 ( call , pos , n , derefChain , borrow , path0 )
2835+ result = inferCallArgumentTypeTopDown ( call , pos , n , derefChain , borrow , path0 )
28522836 |
28532837 borrow .isNoBorrow ( ) and
28542838 path = path0
@@ -2865,7 +2849,7 @@ private Type inferFunctionCallTypeSelf(
28652849 DerefChain derefChain0 , Type t0 , TypePath path0 , DerefImplItemNode impl , Type selfParamType ,
28662850 TypePath selfPath
28672851 |
2868- t0 = inferFunctionCallTypeSelf ( call , n , derefChain0 , path0 ) and
2852+ t0 = inferFunctionCallSelfArgumentTypeTopDown ( call , n , derefChain0 , path0 ) and
28692853 derefChain0 .isCons ( impl , derefChain ) and
28702854 selfParamType = impl .resolveSelfTypeAt ( selfPath )
28712855 |
@@ -3041,17 +3025,37 @@ private module ConstructionMatching = Matching<ConstructionMatchingInput>;
30413025
30423026pragma [ nomagic]
30433027private Type inferConstructionTypePreCheck ( AstNode n , FunctionPosition pos , TypePath path ) {
3044- exists ( ConstructionMatchingInput:: Access a | n = a .getNodeAt ( pos ) |
3028+ exists ( ConstructionMatchingInput:: Access a |
3029+ n = a .getNodeAt ( pos ) and
30453030 result = ConstructionMatching:: inferAccessType ( a , pos , path )
3046- or
3047- a .hasUnknownTypeAt ( pos , path ) and
3048- result = TUnknownType ( )
30493031 )
30503032}
30513033
30523034private predicate inferConstructionType =
30533035 CheckContextTyping< inferConstructionTypePreCheck / 3 > :: check / 2 ;
30543036
3037+ pragma [ nomagic]
3038+ private Type inferUnknownType ( AstNode n , TypePath path ) {
3039+ result = TUnknownType ( ) and
3040+ (
3041+ exists ( FunctionCallMatchingInput:: Access call , FunctionPosition pos |
3042+ n = call .getNodeAt ( pos ) and
3043+ call .hasUnknownTypeAt ( _, pos , path )
3044+ )
3045+ or
3046+ exists ( ConstructionMatchingInput:: Access a , FunctionPosition pos |
3047+ n = a .getNodeAt ( pos ) and
3048+ a .hasUnknownTypeAt ( pos , path )
3049+ )
3050+ or
3051+ exists ( Param p |
3052+ not p .hasTypeRepr ( ) and
3053+ n = p .getPat ( ) and
3054+ path .isEmpty ( )
3055+ )
3056+ )
3057+ }
3058+
30553059/**
30563060 * A matching configuration for resolving types of operations like `a + b`.
30573061 */
@@ -3633,29 +3637,14 @@ private Type inferClosureExprBodyTypeTopDown(AstNode n, TypePath path) {
36333637}
36343638
36353639pragma [ 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- )
3640+ private Type inferClosureExprType ( ClosureExpr ce , TypePath path ) {
3641+ path = TypePath:: singleton ( TDynTraitTypeParameter ( _, any ( FnTrait t ) .getTypeParam ( ) ) ) and
3642+ result .( TupleType ) .getArity ( ) = ce .getNumberOfParams ( )
36573643 or
3658- result = TopDownTyping< inferClosureExprBodyTypeTopDown / 2 > :: inferType ( n , path )
3644+ exists ( TypePath suffix |
3645+ result = ce .getRetType ( ) .getTypeRepr ( ) .( TypeMention ) .getTypeAt ( suffix ) and
3646+ path = closureReturnPath ( ) .append ( suffix )
3647+ )
36593648}
36603649
36613650pragma [ nomagic]
0 commit comments