@@ -1858,6 +1858,275 @@ private module AssocFunctionResolution {
18581858 }
18591859}
18601860
1861+ /**
1862+ * A matching configuration for resolving types of function call expressions
1863+ * like `foo.bar(baz)` and `Foo::bar(baz)`.
1864+ */
1865+ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInputSig {
1866+ import FunctionPositionMatchingInput
1867+
1868+ private newtype TDeclaration =
1869+ TFunctionDeclaration ( ImplOrTraitItemNodeOption i , FunctionDeclaration f ) { f .isFor ( i ) }
1870+
1871+ final class Declaration extends TFunctionDeclaration {
1872+ ImplOrTraitItemNodeOption i ;
1873+ FunctionDeclaration f ;
1874+
1875+ Declaration ( ) { this = TFunctionDeclaration ( i , f ) }
1876+
1877+ FunctionDeclaration getFunction ( ) { result = f }
1878+
1879+ predicate isAssocFunction ( ImplOrTraitItemNode i_ , Function f_ ) {
1880+ i_ = i .asSome ( ) and
1881+ f_ = f
1882+ }
1883+
1884+ TypeParameter getTypeParameter ( TypeParameterPosition ppos ) {
1885+ result = f .getTypeParameter ( i , ppos )
1886+ }
1887+
1888+ Type getDeclaredType ( FunctionPosition pos , TypePath path ) {
1889+ result = f .getParameterType ( i , pos , path )
1890+ or
1891+ pos .isReturn ( ) and
1892+ result = f .getReturnType ( i , path )
1893+ }
1894+
1895+ string toString ( ) {
1896+ i .isNone ( ) and result = f .toString ( )
1897+ or
1898+ result = f .toStringExt ( i .asSome ( ) )
1899+ }
1900+
1901+ Location getLocation ( ) { result = f .getLocation ( ) }
1902+ }
1903+
1904+ pragma [ nomagic]
1905+ private TypeMention getAdditionalTypeParameterConstraint ( TypeParameter tp , Declaration decl ) {
1906+ result =
1907+ tp .( TypeParamTypeParameter )
1908+ .getTypeParam ( )
1909+ .getAdditionalTypeBound ( decl .getFunction ( ) , _)
1910+ .getTypeRepr ( )
1911+ }
1912+
1913+ bindingset [ decl]
1914+ TypeMention getATypeParameterConstraint ( TypeParameter tp , Declaration decl ) {
1915+ result = Input2:: getATypeParameterConstraint ( tp ) and
1916+ exists ( decl )
1917+ or
1918+ result = getAdditionalTypeParameterConstraint ( tp , decl )
1919+ }
1920+
1921+ class AccessEnvironment = string ;
1922+
1923+ bindingset [ derefChain, borrow]
1924+ private AccessEnvironment encodeDerefChainBorrow ( DerefChain derefChain , BorrowKind borrow ) {
1925+ result = derefChain + ";" + borrow
1926+ }
1927+
1928+ bindingset [ derefChainBorrow]
1929+ additional predicate decodeDerefChainBorrow (
1930+ string derefChainBorrow , DerefChain derefChain , BorrowKind borrow
1931+ ) {
1932+ exists ( int i |
1933+ i = derefChainBorrow .indexOf ( ";" ) and
1934+ derefChain = derefChainBorrow .prefix ( i ) and
1935+ borrow .toString ( ) = derefChainBorrow .suffix ( i + 1 )
1936+ )
1937+ }
1938+
1939+ private string noDerefChainBorrow ( ) {
1940+ exists ( DerefChain derefChain , BorrowKind borrow |
1941+ derefChain .isEmpty ( ) and
1942+ borrow .isNoBorrow ( ) and
1943+ result = encodeDerefChainBorrow ( derefChain , borrow )
1944+ )
1945+ }
1946+
1947+ abstract class Access extends ContextTyping:: ContextTypedCallCand {
1948+ abstract AstNode getNodeAt ( FunctionPosition pos ) ;
1949+
1950+ bindingset [ derefChainBorrow]
1951+ abstract Type getInferredType ( string derefChainBorrow , FunctionPosition pos , TypePath path ) ;
1952+
1953+ abstract Declaration getTarget ( string derefChainBorrow ) ;
1954+
1955+ /**
1956+ * Holds if the return type of this call at `path` may have to be inferred
1957+ * from the context.
1958+ */
1959+ abstract predicate hasUnknownTypeAt ( string derefChainBorrow , FunctionPosition pos , TypePath path ) ;
1960+ }
1961+
1962+ private class AssocFunctionCallAccess extends Access instanceof AssocFunctionResolution:: AssocFunctionCall
1963+ {
1964+ AssocFunctionCallAccess ( ) {
1965+ // handled in the `OperationMatchingInput` module
1966+ not this instanceof Operation
1967+ }
1968+
1969+ pragma [ nomagic]
1970+ override Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) {
1971+ result =
1972+ this .( MethodCallExpr )
1973+ .getGenericArgList ( )
1974+ .getTypeArg ( apos .asMethodTypeArgumentPosition ( ) )
1975+ .( TypeMention )
1976+ .getTypeAt ( path )
1977+ or
1978+ result = getCallExprTypeArgument ( this , apos , path )
1979+ }
1980+
1981+ override AstNode getNodeAt ( FunctionPosition pos ) {
1982+ result = AssocFunctionResolution:: AssocFunctionCall .super .getNodeAt ( pos )
1983+ }
1984+
1985+ pragma [ nomagic]
1986+ private Type getInferredSelfType ( FunctionPosition pos , string derefChainBorrow , TypePath path ) {
1987+ exists ( DerefChain derefChain , BorrowKind borrow |
1988+ result = super .getSelfTypeAt ( pos , derefChain , borrow , path ) and
1989+ derefChainBorrow = encodeDerefChainBorrow ( derefChain , borrow ) and
1990+ super .hasReceiverAtPos ( pos )
1991+ )
1992+ }
1993+
1994+ pragma [ nomagic]
1995+ private Type getInferredNonSelfType ( FunctionPosition pos , TypePath path ) {
1996+ if
1997+ // index expression `x[i]` desugars to `*x.index(i)`, so we must account for
1998+ // the implicit deref
1999+ pos .isReturn ( ) and
2000+ this instanceof IndexExpr
2001+ then
2002+ path .isEmpty ( ) and
2003+ result instanceof RefType
2004+ or
2005+ exists ( TypePath suffix |
2006+ result = super .getTypeAt ( pos , suffix ) and
2007+ path = TypePath:: cons ( getRefTypeParameter ( _) , suffix )
2008+ )
2009+ else (
2010+ not super .hasReceiverAtPos ( pos ) and
2011+ result = super .getTypeAt ( pos , path )
2012+ )
2013+ }
2014+
2015+ bindingset [ derefChainBorrow]
2016+ override Type getInferredType ( string derefChainBorrow , FunctionPosition pos , TypePath path ) {
2017+ result = this .getInferredSelfType ( pos , derefChainBorrow , path )
2018+ or
2019+ result = this .getInferredNonSelfType ( pos , path )
2020+ }
2021+
2022+ private AssocFunctionDeclaration getTarget ( ImplOrTraitItemNode i , string derefChainBorrow ) {
2023+ exists ( DerefChain derefChain , BorrowKind borrow |
2024+ derefChainBorrow = encodeDerefChainBorrow ( derefChain , borrow ) and
2025+ result = super .resolveCallTarget ( i , _, derefChain , borrow ) // mutual recursion; resolving method calls requires resolving types and vice versa
2026+ )
2027+ }
2028+
2029+ override Declaration getTarget ( string derefChainBorrow ) {
2030+ exists ( ImplOrTraitItemNode i | result .isAssocFunction ( i , this .getTarget ( i , derefChainBorrow ) ) )
2031+ }
2032+
2033+ pragma [ nomagic]
2034+ override predicate hasUnknownTypeAt ( string derefChainBorrow , FunctionPosition pos , TypePath path ) {
2035+ exists ( ImplOrTraitItemNode i |
2036+ this .hasUnknownTypeAt ( i , this .getTarget ( i , derefChainBorrow ) , pos , path )
2037+ )
2038+ or
2039+ derefChainBorrow = noDerefChainBorrow ( ) and
2040+ forex ( ImplOrTraitItemNode i , Function f |
2041+ f = CallExprImpl:: getResolvedFunction ( this ) and
2042+ f = i .getAnAssocItem ( )
2043+ |
2044+ this .hasUnknownTypeAt ( i , f , pos , path )
2045+ )
2046+ }
2047+ }
2048+
2049+ private class NonAssocFunctionCallAccess extends Access instanceof NonAssocCallExpr ,
2050+ CallExprImpl:: CallExprCall
2051+ {
2052+ pragma [ nomagic]
2053+ override Type getTypeArgument ( TypeArgumentPosition apos , TypePath path ) {
2054+ result = NonAssocCallExpr .super .getTypeArgument ( apos , path )
2055+ }
2056+
2057+ override AstNode getNodeAt ( FunctionPosition pos ) {
2058+ result = NonAssocCallExpr .super .getNodeAt ( pos )
2059+ }
2060+
2061+ pragma [ nomagic]
2062+ private Type getInferredType ( FunctionPosition pos , TypePath path ) {
2063+ result = super .getInferredType ( pos , path )
2064+ }
2065+
2066+ bindingset [ derefChainBorrow]
2067+ override Type getInferredType ( string derefChainBorrow , FunctionPosition pos , TypePath path ) {
2068+ exists ( derefChainBorrow ) and
2069+ result = this .getInferredType ( pos , path )
2070+ }
2071+
2072+ pragma [ nomagic]
2073+ private Declaration getTarget ( ) {
2074+ result =
2075+ TFunctionDeclaration ( ImplOrTraitItemNodeOption:: none_ ( ) ,
2076+ super .resolveCallTargetViaPathResolution ( ) )
2077+ }
2078+
2079+ override Declaration getTarget ( string derefChainBorrow ) {
2080+ result = this .getTarget ( ) and
2081+ derefChainBorrow = noDerefChainBorrow ( )
2082+ }
2083+
2084+ pragma [ nomagic]
2085+ override predicate hasUnknownTypeAt ( string derefChainBorrow , FunctionPosition pos , TypePath path ) {
2086+ derefChainBorrow = noDerefChainBorrow ( ) and
2087+ exists ( FunctionDeclaration f , TypeParameter tp |
2088+ f = super .resolveCallTargetViaPathResolution ( ) and
2089+ pos .isReturn ( ) and
2090+ tp = f .getReturnType ( _, path ) and
2091+ not tp = f .getParameterType ( _, _, _) and
2092+ // check that no explicit type arguments have been supplied for `tp`
2093+ not exists ( TypeArgumentPosition tapos |
2094+ this .hasTypeArgument ( tapos ) and
2095+ TTypeParamTypeParameter ( tapos .asTypeParam ( ) ) = tp
2096+ )
2097+ )
2098+ }
2099+ }
2100+ }
2101+
2102+ private module FunctionCallMatching = MatchingWithEnvironment< FunctionCallMatchingInput > ;
2103+
2104+ pragma [ nomagic]
2105+ private Type inferFunctionCallType0 (
2106+ FunctionCallMatchingInput:: Access call , FunctionPosition pos , AstNode n , DerefChain derefChain ,
2107+ BorrowKind borrow , TypePath path
2108+ ) {
2109+ exists ( TypePath path0 |
2110+ n = call .getNodeAt ( pos ) and
2111+ exists ( string derefChainBorrow |
2112+ FunctionCallMatchingInput:: decodeDerefChainBorrow ( derefChainBorrow , derefChain , borrow )
2113+ |
2114+ result = FunctionCallMatching:: inferAccessType ( call , derefChainBorrow , pos , path0 )
2115+ or
2116+ call .hasUnknownTypeAt ( derefChainBorrow , pos , path0 ) and
2117+ result = TUnknownType ( )
2118+ )
2119+ |
2120+ if
2121+ // index expression `x[i]` desugars to `*x.index(i)`, so we must account for
2122+ // the implicit deref
2123+ pos .isReturn ( ) and
2124+ call instanceof IndexExpr
2125+ then path0 .isCons ( getRefTypeParameter ( _) , path )
2126+ else path = path0
2127+ )
2128+ }
2129+
18612130pragma [ nomagic]
18622131private Type getFieldExprLookupType ( FieldExpr fe , string name , DerefChain derefChain ) {
18632132 exists ( TypePath path |
0 commit comments