@@ -1611,7 +1611,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
16111611 }
16121612
16131613 pragma [ inline]
1614- private predicate typeMatch (
1614+ predicate typeMatch (
16151615 Access a , AccessEnvironment e , Declaration target , TypePath path , Type t , TypeParameter tp
16161616 ) {
16171617 // A type given at the access corresponds directly to the type parameter
@@ -1831,7 +1831,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
18311831 Location getLocation ( ) ;
18321832
18331833 /**
1834- * Gets the type at `path` for the type argument at position `tapos ` of
1834+ * Gets the type at `path` for the type argument at position `pos ` of
18351835 * this access, if any.
18361836 *
18371837 * For example, in a method call like `M<int>()`, `int` is an explicit
@@ -2152,7 +2152,13 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21522152
21532153 /** An invocation expression, for example a call or a variant construction. */
21542154 class Invocation extends Expr {
2155- /** Gets the explicit type argument at position `pos` and `path` for this invocation, if any. */
2155+ /**
2156+ * Gets the explicit type argument at position `pos` and `path` for this invocation, if any.
2157+ *
2158+ * This should only include type arguments that are explicitly provided for the target
2159+ * and not type arguments that are part of a type qualifier (those should be
2160+ * handled via `getTypeQualifier`).
2161+ */
21562162 Type getTypeArgument ( int pos , TypePath path ) ;
21572163
21582164 /**
@@ -2165,6 +2171,14 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
21652171 TypeMention getTypeQualifier ( ) ;
21662172
21672173 /** Gets the target of this invocation in the given resolution context. */
2174+ Parameterizable getTargetForTypeQualifierMatching ( ) ;
2175+
2176+ /**
2177+ * Gets the target of this invocation in the given resolution context.
2178+ *
2179+ * This predicate may depend possitively on the `inferType` predicate, for example
2180+ * in order to resolve a method call one needs to know the type of the receiver.
2181+ */
21682182 Parameterizable getTarget ( ResolutionContext ctx ) ;
21692183 }
21702184
@@ -2234,11 +2248,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
22342248 result = inferTypeForDefaults ( invocation , path )
22352249 }
22362250
2237- /** TODO. */
2238- default Parameterizable getAdditionalTargetForContextualReturnTyping ( Invocation invocation ) {
2239- none ( )
2240- }
2241-
22422251 /** A member that can be accessed, such as a field. */
22432252 class Member extends AstNode {
22442253 /** Gets the type at `path` of the entity that declares this member. */
@@ -2621,42 +2630,35 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
26212630 not mentionsTypeParameterAtParameter ( p , tp )
26222631 }
26232632
2624- // only needed to get access to `Matching::getTypeArgument`.
2625- private module InvocationMatchingGetTypeArgumentInput implements MatchingInputSig {
2626- import InvocationMatchingInput
2627-
2628- predicate getATypeParameterConstraint =
2629- InvocationMatchingInput:: getATypeParameterConstraint / 2 ;
2630-
2631- class Access extends InvocationMatchingInput:: Access {
2632- Type getInferredType ( AccessPosition apos , TypePath path ) { none ( ) }
2633-
2634- Declaration getTarget ( ) {
2635- result = this .getTarget ( _)
2636- or
2637- result = getAdditionalTargetForContextualReturnTyping ( this )
2638- }
2639- }
2633+ bindingset [ invocation, target]
2634+ pragma [ inline_late]
2635+ private predicate hasTypeArgument (
2636+ Invocation invocation , Parameterizable target , TypeParameter tp
2637+ ) {
2638+ exists ( Type t |
2639+ InvocationTypeQualifierMatching:: typeMatch ( invocation , _, _, _, t , tp ) and
2640+ not t instanceof PseudoType
2641+ )
2642+ or
2643+ exists ( InvocationMatching:: getTypeArgument ( invocation , target , tp , _) )
26402644 }
26412645
2642- private module InvocationMatchingGetTypeArgument =
2643- Matching< InvocationMatchingGetTypeArgumentInput > ;
2644-
26452646 /**
26462647 * Holds if `invocation` resolves some target where the return type at `path`
26472648 * may have to be inferred from the context.
26482649 */
26492650 pragma [ nomagic]
26502651 predicate needsContextualTyping ( Invocation invocation , TypePath path ) {
26512652 exists ( Parameterizable target , TypeParameter tp |
2652- target = invocation .( InvocationMatchingGetTypeArgumentInput:: Access ) .getTarget ( ) and
2653+ target = invocation .( InvocationTypeQualifierMatchingInput:: Access ) .getTarget ( )
2654+ or
2655+ target = invocation .getTarget ( _)
2656+ |
26532657 parameterizableReturnContextTypedAt ( target , path , tp ) and
26542658 // check that no explicit type arguments have been supplied which bind `tp`
26552659 not exists ( TypeParameter supplied |
26562660 tp = getAConstrained * ( supplied ) and
2657- exists (
2658- InvocationMatchingGetTypeArgument:: getTypeArgument ( invocation , target , supplied , _)
2659- )
2661+ hasTypeArgument ( invocation , target , supplied )
26602662 )
26612663 )
26622664 }
@@ -2890,10 +2892,57 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
28902892 )
28912893 }
28922894
2895+ final private class ParameterizableFinal = Parameterizable ;
2896+
2897+ final private class InvocationFinal = Invocation ;
2898+
2899+ private module InvocationTypeQualifierMatchingInput implements MatchingInputSig {
2900+ private import codeql.util.Unit
2901+
2902+ class DeclarationPosition = Unit ;
2903+
2904+ class AccessPosition = Unit ;
2905+
2906+ bindingset [ apos]
2907+ bindingset [ dpos]
2908+ predicate accessDeclarationPositionMatch ( AccessPosition apos , DeclarationPosition dpos ) {
2909+ apos = dpos
2910+ }
2911+
2912+ final class Declaration extends ParameterizableFinal {
2913+ Type getDeclaredType ( DeclarationPosition dpos , TypePath path ) {
2914+ result = this .getDeclaringType ( path ) and
2915+ exists ( dpos )
2916+ }
2917+ }
2918+
2919+ bindingset [ decl]
2920+ TypeMention getATypeParameterConstraint ( TypeParameter tp , Declaration decl ) {
2921+ result = Input2:: getATypeParameterConstraint ( tp ) and
2922+ exists ( decl )
2923+ or
2924+ result = decl .getAdditionalTypeParameterConstraint ( tp )
2925+ }
2926+
2927+ final class Access extends InvocationFinal {
2928+ Type getInferredType ( AccessPosition apos , TypePath path ) {
2929+ result = this .getTypeQualifier ( ) .getTypeAt ( path ) and
2930+ exists ( apos )
2931+ }
2932+
2933+ Declaration getTarget ( ) { result = super .getTargetForTypeQualifierMatching ( ) }
2934+ }
2935+ }
2936+
2937+ private module InvocationTypeQualifierMatching =
2938+ Matching< InvocationTypeQualifierMatchingInput > ;
2939+
28932940 /**
28942941 * A matching configuration for resolving types of invocations.
28952942 */
28962943 private module InvocationMatchingInput implements MatchingWithEnvironmentInputSig {
2944+ import InvocationTypeQualifierMatchingInput
2945+
28972946 class DeclarationPosition = int ;
28982947
28992948 class AccessPosition = DeclarationPosition ;
@@ -2907,36 +2956,44 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
29072956 /** Gets the position used to represent the return type of a callable/type of a call. */
29082957 additional int getReturnPosition ( ) { result = - 1 }
29092958
2910- /** Gets the position used to represent the declaring type of a callable/type qualifier of a call. */
2911- additional int getDeclaringPosition ( ) { result = - 2 }
2912-
2913- final private class ParameterizableFinal = Parameterizable ;
2914-
2959+ // /** Gets the position used to represent the declaring type of a callable/type qualifier of a call. */
29152960 class Declaration extends ParameterizableFinal {
2961+ TypeParameter getTypeParameter ( int pos ) {
2962+ InvocationTypeQualifierMatching:: typeMatch ( _, _, this , _, _, result ) and
2963+ pos = - getTypeParameterId ( result ) - 1
2964+ or
2965+ result = super .getTypeParameter ( pos )
2966+ // none()
2967+ }
2968+
29162969 Type getDeclaredType ( DeclarationPosition dpos , TypePath path ) {
29172970 result = this .getParameter ( dpos ) .getType ( ) .getTypeAt ( path )
29182971 or
29192972 dpos = getReturnPosition ( ) and
29202973 result = getParameterizableType ( this , path )
2921- or
2922- dpos = getDeclaringPosition ( ) and
2923- result = this .getDeclaringType ( path )
2974+ // or
2975+ // dpos = getDeclaringPosition() and
2976+ // result = this.getDeclaringType(path)
29242977 }
29252978 }
29262979
29272980 bindingset [ decl]
29282981 TypeMention getATypeParameterConstraint ( TypeParameter tp , Declaration decl ) {
2929- result = Input2:: getATypeParameterConstraint ( tp ) and
2930- exists ( decl )
2931- or
2932- result = decl .getAdditionalTypeParameterConstraint ( tp )
2982+ result = InvocationTypeQualifierMatchingInput:: getATypeParameterConstraint ( tp , decl )
29332983 }
29342984
29352985 class AccessEnvironment = ResolutionContext ;
29362986
2937- final private class InvocationFinal = Invocation ;
2938-
29392987 class Access extends InvocationFinal {
2988+ Type getTypeArgument ( int pos , TypePath path ) {
2989+ exists ( TypeParameter tp |
2990+ InvocationTypeQualifierMatching:: typeMatch ( this , _, _, path , result , tp ) and
2991+ pos = - getTypeParameterId ( tp ) - 1
2992+ )
2993+ or
2994+ result = super .getTypeArgument ( pos , path )
2995+ }
2996+
29402997 pragma [ nomagic]
29412998 private Type getInferredResultType ( AccessPosition apos , TypePath path ) {
29422999 result = inferInvocationTypeContextual ( this , path ) and
@@ -2949,10 +3006,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
29493006 or
29503007 result = this .getInferredResultType ( apos , path ) and
29513008 exists ( e )
2952- or
2953- result = this .getTypeQualifier ( ) .getTypeAt ( path ) and
2954- apos = getDeclaringPosition ( ) and
2955- exists ( e )
29563009 }
29573010
29583011 Declaration getTarget ( AccessEnvironment e ) { result = super .getTarget ( e ) }
0 commit comments