From a7fecaaa1be67079279beae619cabe42784b38a9 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Mon, 26 Jan 2026 09:28:43 +0100 Subject: [PATCH 1/3] Shared: Use `HasTypeTreeSig` for `TypeMention` --- .../typeinference/internal/TypeInference.qll | 136 ++++++++---------- 1 file changed, 58 insertions(+), 78 deletions(-) diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 0a20bd59f1b2..654102ce2167 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -281,43 +281,36 @@ module Make1 Input1> { /** Gets the type at `path` in the type tree. */ Type getTypeAt(TypePath path); - /** Gets a textual representation of this type. */ + /** Gets a textual representation of this type tree. */ string toString(); - /** Gets the location of this type. */ + /** Gets the location of this type tree. */ Location getLocation(); } - /** Provides the input to `Make2`. */ - signature module InputSig2 { - /** A type mention, for example a type annotation in a local variable declaration. */ - class TypeMention { - /** - * Gets the type being mentioned at `path` inside this type mention. - * - * For example, in - * - * ```csharp - * C x = ... - * ``` - * - * the type mention in the declaration of `x` resolves to the following - * types: - * - * `TypePath` | `Type` - * ---------- | ------- - * `""` | ``C`1`` - * `"0"` | `int` - */ - Type resolveTypeAt(TypePath path); - - /** Gets a textual representation of this type mention. */ - string toString(); - - /** Gets the location of this type mention. */ - Location getLocation(); - } - + /** + * Provides the input to `Make2`. + * + * The `TypeMention` parameter is used to build the base type hierarchy based on + * `getABaseTypeMention` and to construct the constraint satisfaction + * hierarchy based on `conditionSatisfiesConstraint`. + * + * It will usually be based on syntactic occurrences of types in the source + * code. For example, in + * + * ```csharp + * class C : Base, Interface { } + * ``` + * + * a type mention would exist for `Base` and resolve to the following + * types: + * + * `TypePath` | `Type` + * ---------- | ------- + * `""` | ``Base`1`` + * `"0"` | `T` + */ + signature module InputSig2 { /** * Gets a base type mention of `t`, if any. Example: * @@ -394,22 +387,13 @@ module Make1 Input1> { ); } - module Make2 { + module Make2 Input2> { private import Input2 - final private class FinalTypeMention = TypeMention; - - /** An adapter for type mentions to implement `HasTypeTreeSig`. */ - final class TypeMentionTypeTree extends FinalTypeMention { - Type getTypeAt(TypePath path) { result = this.resolveTypeAt(path) } - } - /** Gets the type at the empty path of `tm`. */ bindingset[tm] pragma[inline_late] - private Type resolveTypeMentionRoot(TypeMention tm) { - result = tm.resolveTypeAt(TypePath::nil()) - } + private Type getTypeMentionRoot(TypeMention tm) { result = tm.getTypeAt(TypePath::nil()) } /** Provides the input to `IsInstantiationOf`. */ signature module IsInstantiationOfInputSig { @@ -467,17 +451,17 @@ module Make1 Input1> { } pragma[nomagic] - private Type resolveTypeAt(App app, TypeAbstraction abs, Constraint constraint, TypePath path) { + private Type getTypeAt(App app, TypeAbstraction abs, Constraint constraint, TypePath path) { potentialInstantiationOf(app, abs, constraint) and result = constraint.getTypeAt(path) } pragma[nomagic] - private Type resolveNthTypeAt( + private Type getNthTypeAt( App app, TypeAbstraction abs, Constraint constraint, int i, TypePath path ) { path = getNthPath(constraint, i) and - result = resolveTypeAt(app, abs, constraint, path) + result = getTypeAt(app, abs, constraint, path) } pragma[nomagic] @@ -485,7 +469,7 @@ module Make1 Input1> { App app, TypeAbstraction abs, Constraint constraint, int i ) { exists(Type t, TypePath path | - t = resolveNthTypeAt(app, abs, constraint, i, path) and + t = getNthTypeAt(app, abs, constraint, i, path) and if t = abs.getATypeParameter() then any() else app.getTypeAt(path) = t ) and // Recurse unless we are at the first path @@ -622,7 +606,7 @@ module Make1 Input1> { ) { // `app` and `constraint` differ on a concrete type exists(Type t, Type t2 | - t = resolveTypeAt(app, abs, constraint, path) and + t = getTypeAt(app, abs, constraint, path) and not t = abs.getATypeParameter() and app.getTypeAt(path) = t2 and t2 != t @@ -645,29 +629,27 @@ module Make1 Input1> { TypeMention tm1, TypeMention tm2, TypeParameter tp, TypePath path, Type t ) { exists(TypePath prefix | - tm2.resolveTypeAt(prefix) = tp and t = tm1.resolveTypeAt(prefix.appendInverse(path)) + tm2.getTypeAt(prefix) = tp and t = tm1.getTypeAt(prefix.appendInverse(path)) ) } private module IsInstantiationOfInput implements - IsInstantiationOfInputSig + IsInstantiationOfInputSig { pragma[nomagic] - private predicate typeCondition( - Type type, TypeAbstraction abs, TypeMentionTypeTree condition - ) { + private predicate typeCondition(Type type, TypeAbstraction abs, TypeMention condition) { conditionSatisfiesConstraint(abs, condition, _, _) and - type = resolveTypeMentionRoot(condition) + type = getTypeMentionRoot(condition) } pragma[nomagic] - private predicate typeConstraint(Type type, TypeMentionTypeTree constraint) { + private predicate typeConstraint(Type type, TypeMention constraint) { conditionSatisfiesConstraint(_, _, constraint, _) and - type = resolveTypeMentionRoot(constraint) + type = getTypeMentionRoot(constraint) } predicate potentialInstantiationOf( - TypeMentionTypeTree constraint, TypeAbstraction abs, TypeMentionTypeTree condition + TypeMention constraint, TypeAbstraction abs, TypeMention condition ) { exists(Type type | typeConstraint(type, constraint) and typeCondition(type, abs, condition) @@ -684,14 +666,14 @@ module Make1 Input1> { ) { // base case conditionSatisfiesConstraint(abs, condition, constraint, _) and - constraint.resolveTypeAt(path) = t + constraint.getTypeAt(path) = t or // recursive case exists(TypeAbstraction midAbs, TypeMention midConstraint, TypeMention midCondition | conditionSatisfiesConstraint(abs, condition, midConstraint, true) and // NOTE: `midAbs` describe the free type variables in `midCondition`, hence // we use that for instantiation check. - IsInstantiationOf::isInstantiationOf(midConstraint, + IsInstantiationOf::isInstantiationOf(midConstraint, midAbs, midCondition) | conditionSatisfiesConstraintTypeAt(midAbs, midCondition, constraint, path, t) and @@ -716,8 +698,8 @@ module Make1 Input1> { TypeMention constraint ) { conditionSatisfiesConstraintTypeAt(abs, condition, constraint, _, _) and - conditionRoot = resolveTypeMentionRoot(condition) and - constraintRoot = resolveTypeMentionRoot(constraint) + conditionRoot = getTypeMentionRoot(condition) and + constraintRoot = getTypeMentionRoot(constraint) } /** @@ -778,10 +760,10 @@ module Make1 Input1> { | // immediate base class baseMention = immediateBaseMention and - t = immediateBaseMention.resolveTypeAt(path) + t = immediateBaseMention.getTypeAt(path) or // transitive base class - exists(Type immediateBase | immediateBase = resolveTypeMentionRoot(immediateBaseMention) | + exists(Type immediateBase | immediateBase = getTypeMentionRoot(immediateBaseMention) | baseTypeMentionHasNonTypeParameterAt(immediateBase, baseMention, path, t) or exists(TypePath path0, TypePath prefix, TypePath suffix, TypeParameter tp | @@ -811,7 +793,7 @@ module Make1 Input1> { */ baseTypeMentionHasTypeParameterAt(immediateBase, baseMention, prefix, tp) and - t = immediateBaseMention.resolveTypeAt(path0) and + t = immediateBaseMention.getTypeAt(path0) and path0.isCons(tp, suffix) and path = prefix.append(suffix) ) @@ -862,11 +844,9 @@ module Make1 Input1> { } private module IsInstantiationOfInput implements - IsInstantiationOfInputSig + IsInstantiationOfInputSig { - predicate potentialInstantiationOf( - HasTypeTree tt, TypeAbstraction abs, TypeMentionTypeTree cond - ) { + predicate potentialInstantiationOf(HasTypeTree tt, TypeAbstraction abs, TypeMention cond) { exists(Type constraint, Type type | hasTypeConstraint(tt, type, constraint) and rootTypesSatisfaction(type, constraint, abs, cond, _) and @@ -875,13 +855,13 @@ module Make1 Input1> { ) } - predicate relevantConstraint(TypeMentionTypeTree constraint) { + predicate relevantConstraint(TypeMention constraint) { rootTypesSatisfaction(_, _, _, constraint, _) } } private module SatisfiesConstraintIsInstantiationOf = - IsInstantiationOf; + IsInstantiationOf; /** * Holds if `tt` satisfies `constraint` through `abs`, `sub`, and `constraintMention`. @@ -897,8 +877,8 @@ module Make1 Input1> { // // not exists(countConstraintImplementations(type, constraint)) and // conditionSatisfiesConstraintTypeAt(abs, condition, constraintMention, _, _) and - // resolveTypeMentionRoot(condition) = abs.getATypeParameter() and - // constraint = resolveTypeMentionRoot(constraintMention) + // getTypeMentionRoot(condition) = abs.getATypeParameter() and + // constraint = getTypeMentionRoot(constraintMention) // or countConstraintImplementations(type, constraint) > 0 and rootTypesSatisfaction(type, constraint, abs, condition, constraintMention) and @@ -935,9 +915,9 @@ module Make1 Input1> { // or // forall(TypeAbstraction abs, TypeMention condition, TypeMention constraintMention | // conditionSatisfiesConstraintTypeAt(abs, condition, constraintMention, _, _) and - // resolveTypeMentionRoot(condition) = abs.getATypeParameter() + // getTypeMentionRoot(condition) = abs.getATypeParameter() // | - // not constraint = resolveTypeMentionRoot(constraintMention) + // not constraint = getTypeMentionRoot(constraintMention) // ) // ) and ( @@ -973,7 +953,7 @@ module Make1 Input1> { exists(TypeMention sub, TypeParameter tp | satisfiesConstraintTypeMention0(tt, constraint, abs, sub, path, tp) and tp = abs.getATypeParameter() and - sub.resolveTypeAt(pathToTypeParamInSub) = tp + sub.getTypeAt(pathToTypeParamInSub) = tp ) } @@ -1265,7 +1245,7 @@ module Make1 Input1> { Access a, AccessEnvironment e, AccessPosition apos, TypeMention baseMention, TypePath path, Type t ) { - relevantAccess(a, e, apos, resolveTypeMentionRoot(baseMention)) and + relevantAccess(a, e, apos, getTypeMentionRoot(baseMention)) and exists(Type sub | sub = a.getInferredType(e, apos, TypePath::nil()) | baseTypeMentionHasNonTypeParameterAt(sub, baseMention, path, t) or @@ -1351,7 +1331,7 @@ module Make1 Input1> { ) { exists(TypeMention tm | AccessBaseType::hasBaseTypeMention(a, e, apos, tm, path, t) and - base = resolveTypeMentionRoot(tm) + base = getTypeMentionRoot(tm) ) } @@ -1680,7 +1660,7 @@ module Make1 Input1> { } query predicate illFormedTypeMention(TypeMention tm) { - not exists(tm.resolveTypeAt(TypePath::nil())) and exists(tm.getLocation()) + not exists(tm.getTypeAt(TypePath::nil())) and exists(tm.getLocation()) } } } From 7100ca42628ac4a3709dc6e649eecf6c0f4e74e6 Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Mon, 26 Jan 2026 09:33:50 +0100 Subject: [PATCH 2/3] Rust: Adapt to changes in shared type inference library --- .../rust/internal/typeinference/TypeInference.qll | 13 +++++-------- .../rust/internal/typeinference/TypeMention.qll | 7 +++++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index ebf7bd2aa82d..e2b687a0079e 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -134,12 +134,8 @@ class TypePath = M1::TypePath; module TypePath = M1::TypePath; -private module Input2 implements InputSig2 { - private import TypeMention as TM - - class TypeMention = TM::TypeMention; - - TypeMention getABaseTypeMention(Type t) { none() } +private module Input2 implements InputSig2 { + TypeMentionTypeTree getABaseTypeMention(Type t) { none() } Type getATypeParameterConstraint(TypeParameter tp, TypePath path) { exists(TypeMention tm | result = tm.resolveTypeAt(path) | @@ -162,7 +158,8 @@ private module Input2 implements InputSig2 { * inference module for more information. */ predicate conditionSatisfiesConstraint( - TypeAbstraction abs, TypeMention condition, TypeMention constraint, boolean transitive + TypeAbstraction abs, TypeMentionTypeTree condition, TypeMentionTypeTree constraint, + boolean transitive ) { // `impl` blocks implementing traits transitive = false and @@ -212,7 +209,7 @@ private module Input2 implements InputSig2 { } } -private module M2 = Make2; +private module M2 = Make2; import M2 diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll index 063e9beffd39..7e5abaa5a3a3 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll @@ -18,6 +18,13 @@ abstract class TypeMention extends AstNode { final Type resolveType() { result = this.resolveTypeAt(TypePath::nil()) } } +final private class FinalTypeMention = TypeMention; + +/** An adapter for type mentions to implement `HasTypeTreeSig`. */ +final class TypeMentionTypeTree extends FinalTypeMention { + Type getTypeAt(TypePath path) { result = this.resolveTypeAt(path) } +} + class TupleTypeReprMention extends TypeMention instanceof TupleTypeRepr { override Type resolveTypeAt(TypePath path) { path.isEmpty() and From 452d307fd58381979dc1ff9c2006a746490d7eeb Mon Sep 17 00:00:00 2001 From: Simon Friis Vindum Date: Mon, 26 Jan 2026 09:46:33 +0100 Subject: [PATCH 3/3] Rust: Make `TypeMention` directly satisfy `HasTypeTree` --- .../rust/dataflow/internal/ModelsAsData.qll | 4 +- .../typeinference/BlanketImplementation.qll | 4 +- .../internal/typeinference/DerefChain.qll | 4 +- .../typeinference/FunctionOverloading.qll | 4 +- .../internal/typeinference/FunctionType.qll | 4 +- .../internal/typeinference/TypeInference.qll | 70 ++++++++-------- .../TypeInferenceConsistency.qll | 2 +- .../internal/typeinference/TypeMention.qll | 83 +++++++++---------- 8 files changed, 83 insertions(+), 92 deletions(-) diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll index a0c6caf85423..efd1fc35dc57 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll @@ -224,7 +224,7 @@ private module Debug { sc.propagatesFlow(input, _, _, _) and input.head() = SummaryComponent::argument(pos) and p = pos.getParameterIn(sc.getParamList()) and - tm.resolveType() instanceof RefType and + tm.getType() instanceof RefType and not input.tail().head() = SummaryComponent::content(TSingletonContentSet(TReferenceContent())) | tm = p.getTypeRepr() @@ -239,7 +239,7 @@ private module Debug { exists(TypeMention tm | relevantManualModel(sc, can) and sc.propagatesFlow(_, output, _, _) and - tm.resolveType() instanceof RefType and + tm.getType() instanceof RefType and output.head() = SummaryComponent::return(_) and not output.tail().head() = SummaryComponent::content(TSingletonContentSet(TReferenceContent())) and diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll index 8526e1199425..51781a473057 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll @@ -47,8 +47,8 @@ predicate isBlanketLike(ImplItemNode i, TypePath blanketSelfPath, TypeParam blan exists(TypeMention tm, Type root, TypeParameter tp | tm = i.(Impl).getSelfTy() and complexSelfRoot(root, tp) and - tm.resolveType() = root and - tm.resolveTypeAt(blanketSelfPath) = TTypeParamTypeParameter(blanketTypeParam) and + tm.getType() = root and + tm.getTypeAt(blanketSelfPath) = TTypeParamTypeParameter(blanketTypeParam) and blanketSelfPath = TypePath::singleton(tp) and hasFirstNonTrivialTraitBound(blanketTypeParam, _) ) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/DerefChain.qll b/rust/ql/lib/codeql/rust/internal/typeinference/DerefChain.qll index c568fca48b61..6b8c57812486 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/DerefChain.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/DerefChain.qll @@ -25,8 +25,8 @@ class DerefImplItemNode extends ImplItemNode { */ pragma[nomagic] predicate targetHasTypeParameterAt(TypePath path) { - this.getAssocItem("Target").(TypeAlias).getTypeRepr().(TypeMention).resolveTypeAt(path) - instanceof TypeParameter + this.getAssocItem("Target").(TypeAlias).getTypeRepr().(TypeMention).getTypeAt(path) instanceof + TypeParameter } /** Gets the first type parameter of the type being implemented, if any. */ diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll index 0e4bc2729051..e1da3352d0cd 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll @@ -15,7 +15,7 @@ private import FunctionType pragma[nomagic] private Type resolveNonTypeParameterTypeAt(TypeMention tm, TypePath path) { - result = tm.resolveTypeAt(path) and + result = tm.getTypeAt(path) and not result instanceof TypeParameter } @@ -32,7 +32,7 @@ private predicate implSiblingCandidate( ) { trait = impl.(ImplItemNode).resolveTraitTy() and selfTy = impl.getSelfTy() and - rootType = selfTy.resolveType() + rootType = selfTy.getType() } pragma[nomagic] diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll index d375ddfc9847..02c0b45c8e9b 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll @@ -103,12 +103,12 @@ Type getAssocFunctionTypeAt(Function f, ImplOrTraitItemNode i, FunctionPosition // No specialization needed when the function is directly in the trait or // impl block or the declared type is not a type parameter (parent = i or not result instanceof TypeParameter) and - result = pos.getTypeMention(f).resolveTypeAt(path) + result = pos.getTypeMention(f).getTypeAt(path) or exists(TypePath prefix, TypePath suffix, TypeParameter tp, TypeMention constraint | BaseTypes::rootTypesSatisfaction(_, TTrait(parent), i, _, constraint) and path = prefix.append(suffix) and - tp = pos.getTypeMention(f).resolveTypeAt(prefix) and + tp = pos.getTypeMention(f).getTypeAt(prefix) and if tp = TSelfTypeParameter(_) then result = resolveImplOrTraitType(i, suffix) else result = getTraitConstraintTypeAt(i, constraint, tp, suffix) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index e2b687a0079e..b051d60d8b4d 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -134,11 +134,11 @@ class TypePath = M1::TypePath; module TypePath = M1::TypePath; -private module Input2 implements InputSig2 { - TypeMentionTypeTree getABaseTypeMention(Type t) { none() } +private module Input2 implements InputSig2 { + TypeMention getABaseTypeMention(Type t) { none() } Type getATypeParameterConstraint(TypeParameter tp, TypePath path) { - exists(TypeMention tm | result = tm.resolveTypeAt(path) | + exists(TypeMention tm | result = tm.getTypeAt(path) | tm = tp.(TypeParamTypeParameter).getTypeParam().getATypeBound().getTypeRepr() or tm = tp.(SelfTypeParameter).getTrait() or tm = @@ -158,8 +158,7 @@ private module Input2 implements InputSig2 { * inference module for more information. */ predicate conditionSatisfiesConstraint( - TypeAbstraction abs, TypeMentionTypeTree condition, TypeMentionTypeTree constraint, - boolean transitive + TypeAbstraction abs, TypeMention condition, TypeMention constraint, boolean transitive ) { // `impl` blocks implementing traits transitive = false and @@ -209,7 +208,7 @@ private module Input2 implements InputSig2 { } } -private module M2 = Make2; +private module M2 = Make2; import M2 @@ -228,7 +227,7 @@ module Consistency { // mention for the self type has multiple types for a path. not exists(ImplItemNode impl, TypePath selfTypePath | n = impl.getAnAssocItem().(Function).getSelfParam() and - strictcount(impl.(Impl).getSelfTy().(TypeMention).resolveTypeAt(selfTypePath)) > 1 + strictcount(impl.(Impl).getSelfTy().(TypeMention).getTypeAt(selfTypePath)) > 1 ) } } @@ -294,7 +293,7 @@ private class FunctionDeclaration extends Function { result = getAssocFunctionTypeAt(this, i.asSome(), pos, path) or i.isNone() and - result = this.getParam(pos.asPosition()).getTypeRepr().(TypeMention).resolveTypeAt(path) + result = this.getParam(pos.asPosition()).getTypeRepr().(TypeMention).getTypeAt(path) ) } @@ -305,7 +304,7 @@ private class FunctionDeclaration extends Function { getAssocFunctionTypeAt(this, i.asSome(), any(FunctionPosition pos | pos.isReturn()), path) or i.isNone() and - result = getReturnTypeMention(this).resolveTypeAt(path) + result = getReturnTypeMention(this).getTypeAt(path) ) } @@ -349,12 +348,12 @@ private TypeMention getCallExprTypeMentionArgument(CallExpr ce, TypeArgumentPosi pragma[nomagic] private Type getCallExprTypeArgument(CallExpr ce, TypeArgumentPosition apos, TypePath path) { - result = getCallExprTypeMentionArgument(ce, apos).resolveTypeAt(path) + result = getCallExprTypeMentionArgument(ce, apos).getTypeAt(path) or // Handle constructions that use `Self(...)` syntax exists(Path p, TypePath path0 | p = CallExprImpl::getFunctionPath(ce) and - result = p.(TypeMention).resolveTypeAt(path0) and + result = p.(TypeMention).getTypeAt(path0) and path0.isCons(TTypeParamTypeParameter(apos.asTypeParam()), path) ) } @@ -377,16 +376,16 @@ private TypeMention getTypeAnnotation(AstNode n) { /** Gets the type of `n`, which has an explicit type annotation. */ pragma[nomagic] private Type inferAnnotatedType(AstNode n, TypePath path) { - result = getTypeAnnotation(n).resolveTypeAt(path) + result = getTypeAnnotation(n).getTypeAt(path) or - result = n.(ShorthandSelfParameterMention).resolveTypeAt(path) + result = n.(ShorthandSelfParameterMention).getTypeAt(path) } pragma[nomagic] private Type inferFunctionBodyType(AstNode n, TypePath path) { exists(Function f | n = f.getFunctionBody() and - result = getReturnTypeMention(f).resolveTypeAt(path) and + result = getReturnTypeMention(f).getTypeAt(path) and not exists(ImplTraitReturnType i | i.getFunction() = f | result = i or result = i.getATypeParameter() ) @@ -430,7 +429,7 @@ module CertainTypeInference { private TypePath getPathToImplSelfTypeParam(TypeParam tp) { exists(ImplItemNode impl | tp = impl.getTypeParam(_) and - TTypeParamTypeParameter(tp) = impl.(Impl).getSelfTy().(TypeMention).resolveTypeAt(result) + TTypeParamTypeParameter(tp) = impl.(Impl).getSelfTy().(TypeMention).getTypeAt(result) ) } @@ -446,7 +445,7 @@ module CertainTypeInference { // and the path `Foo::bar` we must resolve `A` to `i64`. exists(TypePath pathToTp | pathToTp = getPathToImplSelfTypeParam(tp) and - result = p.getQualifier().(TypeMention).resolveTypeAt(pathToTp.appendInverse(suffix)) + result = p.getQualifier().(TypeMention).getTypeAt(pathToTp.appendInverse(suffix)) ) or // For type parameters of the function we must resolve their @@ -462,11 +461,11 @@ module CertainTypeInference { } private Type inferCertainStructExprType(StructExpr se, TypePath path) { - result = se.getPath().(TypeMention).resolveTypeAt(path) + result = se.getPath().(TypeMention).getTypeAt(path) } private Type inferCertainStructPatType(StructPat sp, TypePath path) { - result = sp.getPath().(TypeMention).resolveTypeAt(path) + result = sp.getPath().(TypeMention).getTypeAt(path) } predicate certainTypeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePath prefix2) { @@ -902,7 +901,7 @@ private module StructExprMatchingInput implements MatchingInputSig { // type of a field exists(TypeMention tp | tp = this.getField(dpos.asFieldPos()).getTypeRepr() and - result = tp.resolveTypeAt(path) + result = tp.getTypeAt(path) ) or // type parameter of the struct itself @@ -955,7 +954,7 @@ private module StructExprMatchingInput implements MatchingInputSig { // Handle constructions that use `Self {...}` syntax exists(TypeMention tm, TypePath path0 | tm = this.getStructPath() and - result = tm.resolveTypeAt(path0) and + result = tm.getTypeAt(path0) and path0.isCons(TTypeParamTypeParameter(apos.asTypeParam()), path) ) } @@ -1065,7 +1064,7 @@ pragma[nomagic] private Type getCallExprTypeQualifier(CallExpr ce, TypePath path) { exists(TypeMention tm | tm = getCallExprPathQualifier(ce) and - result = tm.resolveTypeAt(path) and + result = tm.getTypeAt(path) and not resolvePath(tm) instanceof Trait ) } @@ -2327,11 +2326,11 @@ private module MethodResolution { * instance of the type being implemented. */ private module TypeQualifierIsInstantiationOfImplSelfInput implements - IsInstantiationOfInputSig + IsInstantiationOfInputSig { pragma[nomagic] private predicate potentialInstantiationOf0( - MethodCallCallExpr ce, ImplItemNode impl, TypeMentionTypeTree constraint + MethodCallCallExpr ce, ImplItemNode impl, TypeMention constraint ) { ce.hasTypeQualifiedCandidate(impl) and constraint = impl.getSelfPath() @@ -2339,7 +2338,7 @@ private module MethodResolution { pragma[nomagic] predicate potentialInstantiationOf( - MethodCallCallExpr ce, TypeAbstraction abs, TypeMentionTypeTree constraint + MethodCallCallExpr ce, TypeAbstraction abs, TypeMention constraint ) { potentialInstantiationOf0(ce, abs, constraint) and if abs.(Impl).hasTrait() @@ -2350,14 +2349,13 @@ private module MethodResolution { else any() } - predicate relevantConstraint(TypeMentionTypeTree constraint) { + predicate relevantConstraint(TypeMention constraint) { potentialInstantiationOf0(_, _, constraint) } } private module TypeQualifierIsInstantiationOfImplSelf = - IsInstantiationOf; + IsInstantiationOf; /** * A configuration for anti-matching the type of a receiver against the type of @@ -2478,7 +2476,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi .getGenericArgList() .getTypeArg(apos.asMethodTypeArgumentPosition()) .(TypeMention) - .resolveTypeAt(path) + .getTypeAt(path) or result = getCallExprTypeArgument(this, apos, path) } @@ -3009,7 +3007,7 @@ abstract private class TupleLikeConstructor extends Addressable { } Type getParameterType(FunctionPosition pos, TypePath path) { - result = this.getTupleField(pos.asPosition()).getTypeRepr().(TypeMention).resolveTypeAt(path) + result = this.getTupleField(pos.asPosition()).getTypeRepr().(TypeMention).getTypeAt(path) } } @@ -3364,7 +3362,7 @@ private module FieldExprMatchingInput implements MatchingInputSig { ) or dpos.isField() and - result = this.getTypeRepr().(TypeMention).resolveTypeAt(path) + result = this.getTypeRepr().(TypeMention).getTypeAt(path) } override string toString() { result = this.getAstNode().toString() } @@ -3716,7 +3714,7 @@ private module StructPatMatchingInput implements MatchingInputSig { // The struct/enum type is supplied explicitly as a type qualifier, e.g. // `let Foo::Variant { ... } = ...`. apos.isStructPos() and - result = this.getPath().(TypeMention).resolveTypeAt(path) + result = this.getPath().(TypeMention).getTypeAt(path) } Declaration getTarget() { result = resolvePath(this.getPath()) } @@ -3766,7 +3764,7 @@ private module TupleStructPatMatchingInput implements MatchingInputSig { // The struct/enum type is supplied explicitly as a type qualifier, e.g. // `let Option::::Some(x) = ...`. apos.isSelf() and - result = this.getPath().(TypeMention).resolveTypeAt(path) + result = this.getPath().(TypeMention).getTypeAt(path) } Declaration getTarget() { result = resolvePath(this.getPath()) } @@ -3955,13 +3953,13 @@ private Type inferClosureExprType(AstNode n, TypePath path) { or // Propagate return type annotation to body n = ce.getClosureBody() and - result = ce.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path) + result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path) ) } pragma[nomagic] private Type inferCastExprType(CastExpr ce, TypePath path) { - result = ce.getTypeRepr().(TypeMention).resolveTypeAt(path) + result = ce.getTypeRepr().(TypeMention).getTypeAt(path) } cached @@ -4159,7 +4157,7 @@ private module Debug { predicate debugInferShorthandSelfType(ShorthandSelfParameterMention self, TypePath path, Type t) { self = getRelevantLocatable() and - t = self.resolveTypeAt(path) + t = self.getTypeAt(path) } predicate debugInferMethodCallType(AstNode n, TypePath path, Type t) { @@ -4174,7 +4172,7 @@ private module Debug { predicate debugTypeMention(TypeMention tm, TypePath path, Type type) { tm = getRelevantLocatable() and - tm.resolveTypeAt(path) = type + tm.getTypeAt(path) = type } Type debugInferAnnotatedType(AstNode n, TypePath path) { diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInferenceConsistency.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInferenceConsistency.qll index cde873f3685b..e50c7393f727 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInferenceConsistency.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInferenceConsistency.qll @@ -17,7 +17,7 @@ query predicate illFormedTypeMention(TypeMention tm) { not tm = any(PathTypeMention ptm | exists(ptm.resolvePathTypeAt(TypePath::nil())) and - not exists(ptm.resolveType()) + not exists(ptm.getType()) or ptm.(NonAliasPathTypeMention).getResolved() instanceof TypeAlias ) and diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll index 7e5abaa5a3a3..a5a9eae37156 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll @@ -11,51 +11,44 @@ private import TypeInference abstract class TypeMention extends AstNode { /** Gets the type at `path` that this mention resolves to, if any. */ pragma[nomagic] - abstract Type resolveTypeAt(TypePath path); + abstract Type getTypeAt(TypePath path); /** Gets the type that this node resolves to, if any. */ pragma[nomagic] - final Type resolveType() { result = this.resolveTypeAt(TypePath::nil()) } -} - -final private class FinalTypeMention = TypeMention; - -/** An adapter for type mentions to implement `HasTypeTreeSig`. */ -final class TypeMentionTypeTree extends FinalTypeMention { - Type getTypeAt(TypePath path) { result = this.resolveTypeAt(path) } + final Type getType() { result = this.getTypeAt(TypePath::nil()) } } class TupleTypeReprMention extends TypeMention instanceof TupleTypeRepr { - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result.(TupleType).getArity() = super.getNumberOfFields() or exists(TypePath suffix, int i | - result = super.getField(i).(TypeMention).resolveTypeAt(suffix) and + result = super.getField(i).(TypeMention).getTypeAt(suffix) and path = TypePath::cons(getTupleTypeParameter(super.getNumberOfFields(), i), suffix) ) } } class ParenthesizedArgListMention extends TypeMention instanceof ParenthesizedArgList { - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result.(TupleType).getArity() = super.getNumberOfTypeArgs() or exists(TypePath suffix, int index | - result = super.getTypeArg(index).getTypeRepr().(TypeMention).resolveTypeAt(suffix) and + result = super.getTypeArg(index).getTypeRepr().(TypeMention).getTypeAt(suffix) and path = TypePath::cons(getTupleTypeParameter(super.getNumberOfTypeArgs(), index), suffix) ) } } class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr { - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result instanceof ArrayType or exists(TypePath suffix | - result = super.getElementTypeRepr().(TypeMention).resolveTypeAt(suffix) and + result = super.getElementTypeRepr().(TypeMention).getTypeAt(suffix) and path = TypePath::cons(getArrayTypeParameter(), suffix) ) } @@ -66,23 +59,23 @@ class RefTypeReprMention extends TypeMention instanceof RefTypeRepr { if super.isMut() then result instanceof RefMutType else result instanceof RefSharedType } - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result = this.resolveRootType() or exists(TypePath suffix | - result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and + result = super.getTypeRepr().(TypeMention).getTypeAt(suffix) and path = TypePath::cons(this.resolveRootType().getPositionalTypeParameter(0), suffix) ) } } class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr { - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result instanceof SliceType or exists(TypePath suffix | - result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and + result = super.getTypeRepr().(TypeMention).getTypeAt(suffix) and path = TypePath::cons(getSliceTypeParameter(), suffix) ) } @@ -91,7 +84,7 @@ class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr { abstract class PathTypeMention extends TypeMention, Path { abstract Type resolvePathTypeAt(TypePath typePath); - final override Type resolveTypeAt(TypePath typePath) { + final override Type getTypeAt(TypePath typePath) { result = this.resolvePathTypeAt(typePath) and ( not result instanceof TypeParameter @@ -118,14 +111,14 @@ class AliasPathTypeMention extends PathTypeMention { * resulting type at `typePath`. */ override Type resolvePathTypeAt(TypePath typePath) { - result = rhs.resolveTypeAt(typePath) and + result = rhs.getTypeAt(typePath) and not result = pathGetTypeParameter(resolved, _) or exists(TypeParameter tp, TypeMention arg, TypePath prefix, TypePath suffix, int i | - tp = rhs.resolveTypeAt(prefix) and + tp = rhs.getTypeAt(prefix) and tp = pathGetTypeParameter(resolved, pragma[only_bind_into](i)) and arg = this.getSegment().getGenericArgList().getTypeArg(pragma[only_bind_into](i)) and - result = arg.resolveTypeAt(suffix) and + result = arg.getTypeAt(suffix) and typePath = prefix.append(suffix) ) } @@ -183,7 +176,7 @@ class NonAliasPathTypeMention extends PathTypeMention { // Defaults only apply to type mentions in type annotations this = any(PathTypeRepr ptp).getPath().getQualifier*() and exists(Type ty, TypePath prefix | - ty = this.resolveRootType().getTypeParameterDefault(i).resolveTypeAt(prefix) and + ty = this.resolveRootType().getTypeParameterDefault(i).getTypeAt(prefix) and if not ty = TSelfTypeParameter(resolved) then result = ty and path = prefix else @@ -191,13 +184,13 @@ class NonAliasPathTypeMention extends PathTypeMention { // be substituted for the type that implements the trait. exists(TypePath suffix | path = prefix.append(suffix) and - result = this.getSelfTraitBoundArg().resolveTypeAt(suffix) + result = this.getSelfTraitBoundArg().getTypeAt(suffix) ) ) } private Type getPositionalTypeArgument(int i, TypePath path) { - result = getPathTypeArgument(this, i).resolveTypeAt(path) + result = getPathTypeArgument(this, i).getTypeAt(path) or result = this.getDefaultPositionalTypeArgument(i, path) } @@ -226,11 +219,11 @@ class NonAliasPathTypeMention extends PathTypeMention { s.hasParenthesizedArgList() | tp = TTypeParamTypeParameter(t.getTypeParam()) and - result = s.getParenthesizedArgList().(TypeMention).resolveTypeAt(path) + result = s.getParenthesizedArgList().(TypeMention).getTypeAt(path) or tp = TAssociatedTypeTypeParameter(t, any(FnOnceTrait tr).getOutputType()) and ( - result = s.getRetType().getTypeRepr().(TypeMention).resolveTypeAt(path) + result = s.getRetType().getTypeRepr().(TypeMention).getTypeAt(path) or // When the `-> ...` return type is omitted, it defaults to `()`. not s.hasRetType() and @@ -326,24 +319,24 @@ class NonAliasPathTypeMention extends PathTypeMention { exists(TypeParameter tp, TypePath suffix | typePath = TypePath::cons(tp, suffix) | result = this.getTypeForTypeParameterAt(tp, suffix) or - result = this.getTypeMentionForTypeParameter(tp).resolveTypeAt(suffix) + result = this.getTypeMentionForTypeParameter(tp).getTypeAt(suffix) ) or // When the path refers to a trait, then the implicit `Self` type parameter // should be instantiated from the context. exists(TypePath suffix | - result = this.getSelfTraitBoundArg().resolveTypeAt(suffix) and + result = this.getSelfTraitBoundArg().getTypeAt(suffix) and typePath = TypePath::cons(TSelfTypeParameter(resolved), suffix) ) or not this.getSegment().hasTraitTypeRepr() and - result = this.getSegment().getTypeRepr().(TypeMention).resolveTypeAt(typePath) + result = this.getSegment().getTypeRepr().(TypeMention).getTypeAt(typePath) } } pragma[nomagic] Type resolveImplSelfTypeAt(Impl i, TypePath path) { - result = i.getSelfTy().(TypeMention).resolveTypeAt(path) + result = i.getSelfTy().(TypeMention).getTypeAt(path) } class ImplSelfMention extends PathTypeMention { @@ -361,11 +354,11 @@ class PathTypeReprMention extends TypeMention, PathTypeRepr { PathTypeReprMention() { path = this.getPath() } - override Type resolveTypeAt(TypePath typePath) { result = path.resolveTypeAt(typePath) } + override Type getTypeAt(TypePath typePath) { result = path.getTypeAt(typePath) } } class ImplTraitTypeReprMention extends TypeMention instanceof ImplTraitTypeRepr { - override Type resolveTypeAt(TypePath typePath) { + override Type getTypeAt(TypePath typePath) { typePath.isEmpty() and result.(ImplTraitType).getImplTraitTypeRepr() = this or @@ -384,14 +377,14 @@ private TypeParameter pathGetTypeParameter(TypeAlias alias, int i) { // Used to represent implicit `Self` type arguments in traits and `impl` blocks, // see `PathMention` for details. class TypeParamMention extends TypeMention instanceof TypeParam { - override Type resolveTypeAt(TypePath typePath) { + override Type getTypeAt(TypePath typePath) { typePath.isEmpty() and result = TTypeParamTypeParameter(this) } } class TraitMention extends TypeMention instanceof TraitItemNode { - override Type resolveTypeAt(TypePath typePath) { + override Type getTypeAt(TypePath typePath) { typePath.isEmpty() and result = TTrait(this) or @@ -424,7 +417,7 @@ class SelfTypeParameterMention extends TypeMention instanceof Name { Trait getTrait() { result = trait } - override Type resolveTypeAt(TypePath typePath) { + override Type getTypeAt(TypePath typePath) { typePath.isEmpty() and result = TSelfTypeParameter(trait) } @@ -474,7 +467,7 @@ class ShorthandSelfParameterMention extends TypeMention instanceof SelfParam { if super.isMut() then result instanceof RefMutType else result instanceof RefSharedType } - override Type resolveTypeAt(TypePath typePath) { + override Type getTypeAt(TypePath typePath) { // `fn f(&self, ...)` typePath.isEmpty() and result = this.resolveSelfRefRootType() @@ -512,7 +505,7 @@ class ShorthandReturnTypeMention extends TypeMention instanceof Name { not f.getRetType().hasTypeRepr() } - override Type resolveTypeAt(TypePath typePath) { + override Type getTypeAt(TypePath typePath) { typePath.isEmpty() and result instanceof UnitType } @@ -534,14 +527,14 @@ class DynTraitTypeReprMention extends TypeMention instanceof DynTraitTypeRepr { dynType.getTrait() = super.getTrait() } - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result = dynType or exists(DynTraitTypeParameter tp, TypePath path0, TypePath suffix | dynType = tp.getDynTraitType() and path = TypePath::cons(tp, suffix) and - result = super.getTypeBoundList().getBound(0).getTypeRepr().(TypeMention).resolveTypeAt(path0) and + result = super.getTypeBoundList().getBound(0).getTypeRepr().(TypeMention).getTypeAt(path0) and path0.isCons(tp.getTraitTypeParameter(), suffix) ) } @@ -581,7 +574,7 @@ class DynTypeBoundListMention extends TypeMention instanceof TypeBoundList { ) } - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result.(DynTraitType).getTrait() = trait or @@ -594,7 +587,7 @@ class DynTypeBoundListMention extends TypeMention instanceof TypeBoundList { } class NeverTypeReprMention extends TypeMention, NeverTypeRepr { - override Type resolveTypeAt(TypePath path) { result = TNeverType() and path.isEmpty() } + override Type getTypeAt(TypePath path) { result = TNeverType() and path.isEmpty() } } class PtrTypeReprMention extends TypeMention instanceof PtrTypeRepr { @@ -604,11 +597,11 @@ class PtrTypeReprMention extends TypeMention instanceof PtrTypeRepr { super.isMut() and result instanceof PtrMutType } - override Type resolveTypeAt(TypePath path) { + override Type getTypeAt(TypePath path) { path.isEmpty() and result = this.resolveRootType() or exists(TypePath suffix | - result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and + result = super.getTypeRepr().(TypeMention).getTypeAt(suffix) and path = TypePath::cons(this.resolveRootType().getPositionalTypeParameter(0), suffix) ) }