Rust: Take additional type parameter constraints into account

This commit is contained in:
Tom Hvitved
2026-03-24 12:58:26 +01:00
parent ddc407257f
commit 6295f57a87
7 changed files with 225 additions and 46 deletions

View File

@@ -1296,6 +1296,15 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
Type getDeclaredType(DeclarationPosition dpos, TypePath path);
}
/**
* Gets a type constraint on the type parameter `tp` that applies to `decl`,
* if any.
*/
bindingset[decl]
default TypeMention getATypeParameterConstraint(TypeParameter tp, Declaration decl) {
result = getATypeParameterConstraint(tp)
}
/**
* A position inside an access. For example, the integer position of an
* argument inside a method call.
@@ -1643,6 +1652,24 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
t = getTypeArgument(a, target, tp, path)
}
/**
* Holds if the type parameter `constrainedTp` occurs in the declared type of
* `target` at `apos` and `pathToConstrained`, and there is a constraint
* `constraint` on `constrainedTp`.
*/
pragma[nomagic]
private predicate typeParameterHasConstraint(
Declaration target, AccessPosition apos, TypeParameter constrainedTp,
TypePath pathToConstrained, TypeMention constraint
) {
exists(DeclarationPosition dpos |
accessDeclarationPositionMatch(apos, dpos) and
constrainedTp = target.getTypeParameter(_) and
constrainedTp = target.getDeclaredType(dpos, pathToConstrained) and
constraint = getATypeParameterConstraint(constrainedTp, target)
)
}
/**
* Holds if the declared type of `target` contains a type parameter at
* `apos` and `pathToConstrained` that must satisfy `constraint` and `tp`
@@ -1665,14 +1692,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
Declaration target, AccessPosition apos, TypePath pathToConstrained, TypeMention constraint,
TypePath pathToTp, TypeParameter tp
) {
exists(DeclarationPosition dpos, TypeParameter constrainedTp |
accessDeclarationPositionMatch(apos, dpos) and
constrainedTp = target.getTypeParameter(_) and
constraint = getATypeParameterConstraint(constrainedTp) and
exists(TypeParameter constrainedTp |
typeParameterHasConstraint(target, apos, constrainedTp, pathToConstrained, constraint) and
tp = target.getTypeParameter(_) and
tp = constraint.getTypeAt(pathToTp) and
constrainedTp != tp and
constrainedTp = target.getDeclaredType(dpos, pathToConstrained)
constrainedTp != tp
)
}
@@ -1799,6 +1823,15 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
Type getDeclaredType(DeclarationPosition dpos, TypePath path);
}
/**
* Gets a type constraint on the type parameter `tp` that applies to `decl`,
* if any.
*/
bindingset[decl]
default TypeMention getATypeParameterConstraint(TypeParameter tp, Declaration decl) {
result = getATypeParameterConstraint(tp)
}
/**
* A position inside an access. For example, the integer position of an
* argument inside a method call.
@@ -1856,6 +1889,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
private import codeql.util.Unit
import Input
predicate getATypeParameterConstraint = Input::getATypeParameterConstraint/2;
class AccessEnvironment = Unit;
final private class AccessFinal = Input::Access;