Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions rust/ql/lib/codeql/rust/elements/internal/ImplImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,11 @@ module Impl {
result = "impl " + trait + this.getSelfTy().toAbbreviatedString() + " { ... }"
)
}

/**
* Holds if this is an inherent `impl` block, that is, one that does not implement a trait.
*/
pragma[nomagic]
predicate isInherent() { not this.hasTrait() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ module Impl {

private newtype TArgumentPosition =
TPositionalArgumentPosition(int i) {
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
// For the type `FunctionPosition` used by type inference, we work with function-call syntax
// adjusted positions, so a call like `x.m(a, b, c)` needs positions `0` through `3`; for this
// reason, there is no `- 1` after `max(...)` below.
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()])]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When looking at this in isolation the - 1 makes sense, so it might be worth it to add a comment mentioning that we also use this for adjusted positions where we need an extra index.

} or
TSelfArgumentPosition() or
TTypeQualifierArgumentPosition()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,19 @@ private predicate hasFirstNonTrivialTraitBound(TypeParamItemNode tp, Trait trait
*/
pragma[nomagic]
predicate isBlanketLike(ImplItemNode i, TypePath blanketSelfPath, TypeParam blanketTypeParam) {
blanketTypeParam = i.getBlanketImplementationTypeParam() and
blanketSelfPath.isEmpty()
or
exists(TypeMention tm, Type root, TypeParameter tp |
tm = i.(Impl).getSelfTy() and
complexSelfRoot(root, tp) and
tm.getType() = root and
tm.getTypeAt(blanketSelfPath) = TTypeParamTypeParameter(blanketTypeParam) and
blanketSelfPath = TypePath::singleton(tp) and
hasFirstNonTrivialTraitBound(blanketTypeParam, _)
i.(Impl).hasTrait() and
(
blanketTypeParam = i.getBlanketImplementationTypeParam() and
blanketSelfPath.isEmpty()
or
exists(TypeMention tm, Type root, TypeParameter tp |
tm = i.(Impl).getSelfTy() and
complexSelfRoot(root, tp) and
tm.getType() = root and
tm.getTypeAt(blanketSelfPath) = TTypeParamTypeParameter(blanketTypeParam) and
blanketSelfPath = TypePath::singleton(tp) and
hasFirstNonTrivialTraitBound(blanketTypeParam, _)
)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ private predicate functionResolutionDependsOnArgumentCand(
implHasSibling(impl, trait) and
traitTypeParameterOccurrence(trait, _, functionName, pos, path, traitTp) and
f = impl.getASuccessor(functionName) and
not pos.isSelfOrTypeQualifier()
not pos.isTypeQualifier() and
not (f instanceof Method and pos.asPosition() = 0)
)
}

Expand Down
68 changes: 29 additions & 39 deletions rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ private import TypeMention
private import TypeInference

private newtype TFunctionPosition =
TArgumentFunctionPosition(ArgumentPosition pos) or
TArgumentFunctionPosition(ArgumentPosition pos) { not pos.isSelf() } or
TReturnFunctionPosition()

/**
* A position of a type related to a function.
* A function-call adjusted position of a type related to a function.
*
* Either `self`, `return`, or a positional parameter index.
* Either `return` or a positional parameter index, where `self` is translated
* to position `0` and subsequent positional parameters at index `i` are
* translated to position `i + 1`.
*/
class FunctionPosition extends TFunctionPosition {
predicate isSelf() { this.asArgumentPosition().isSelf() }

int asPosition() { result = this.asArgumentPosition().asPosition() }

predicate isPosition() { exists(this.asPosition()) }
Expand All @@ -25,29 +25,18 @@ class FunctionPosition extends TFunctionPosition {

predicate isTypeQualifier() { this.asArgumentPosition().isTypeQualifier() }

predicate isSelfOrTypeQualifier() { this.isSelf() or this.isTypeQualifier() }

predicate isReturn() { this = TReturnFunctionPosition() }

/** Gets the corresponding position when `f` is invoked via a function call. */
bindingset[f]
FunctionPosition getFunctionCallAdjusted(Function f) {
this.isReturn() and
result = this
or
if f.hasSelfParam()
then
this.isSelf() and result.asPosition() = 0
or
result.asPosition() = this.asPosition() + 1
else result = this
}

TypeMention getTypeMention(Function f) {
this.isSelf() and
result = getSelfParamTypeMention(f.getSelfParam())
or
result = f.getParam(this.asPosition()).getTypeRepr()
(
if f instanceof Method
then
result = f.getParam(this.asPosition() - 1).getTypeRepr()
or
result = getSelfParamTypeMention(f.getSelfParam()) and
this.asPosition() = 0
else result = f.getParam(this.asPosition()).getTypeRepr()
)
or
this.isReturn() and
result = getReturnTypeMention(f)
Expand Down Expand Up @@ -197,8 +186,7 @@ class AssocFunctionType extends MkAssocFunctionType {
exists(Function f, ImplOrTraitItemNode i, FunctionPosition pos | this.appliesTo(f, i, pos) |
result = pos.getTypeMention(f)
or
pos.isSelf() and
not f.hasSelfParam() and
pos.isTypeQualifier() and
result = [i.(Impl).getSelfTy().(AstNode), i.(Trait).getName()]
)
}
Expand All @@ -209,7 +197,7 @@ class AssocFunctionType extends MkAssocFunctionType {
}

pragma[nomagic]
private Trait getALookupTrait(Type t) {
Trait getALookupTrait(Type t) {
result = t.(TypeParamTypeParameter).getTypeParam().(TypeParamItemNode).resolveABound()
or
result = t.(SelfTypeParameter).getTrait()
Expand Down Expand Up @@ -310,10 +298,11 @@ signature module ArgsAreInstantiationsOfInputSig {
* Holds if `f` inside `i` needs to have the type corresponding to type parameter
* `tp` checked.
*
* If `i` is an inherent implementation, `tp` is a type parameter of the type being
* implemented, otherwise `tp` is a type parameter of the trait (being implemented).
* `tp` is a type parameter of the trait being implemented by `f` or the trait to which
* `f` belongs.
*
* `pos` is one of the positions in `f` in which the relevant type occours.
* `pos` is one of the function-call adjusted positions in `f` in which the relevant
* type occurs.
*/
predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition pos);

Expand Down Expand Up @@ -360,7 +349,7 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
private newtype TCallAndPos =
MkCallAndPos(Input::Call call, FunctionPosition pos) { exists(call.getArgType(pos, _)) }

/** A call tagged with a position. */
/** A call tagged with a function-call adjusted position. */
private class CallAndPos extends MkCallAndPos {
Input::Call call;
FunctionPosition pos;
Expand Down Expand Up @@ -413,20 +402,21 @@ module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {

pragma[nomagic]
private predicate argIsInstantiationOf(
Input::Call call, FunctionPosition pos, ImplOrTraitItemNode i, Function f, int rnk
Input::Call call, ImplOrTraitItemNode i, Function f, int rnk
) {
ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
toCheckRanked(i, f, _, pos, rnk)
exists(FunctionPosition pos |
ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
toCheckRanked(i, f, _, pos, rnk)
)
}

pragma[nomagic]
private predicate argsAreInstantiationsOfToIndex(
Input::Call call, ImplOrTraitItemNode i, Function f, int rnk
) {
exists(FunctionPosition pos |
argIsInstantiationOf(call, pos, i, f, rnk) and
call.hasTargetCand(i, f)
|
argIsInstantiationOf(call, i, f, rnk) and
call.hasTargetCand(i, f) and
(
rnk = 0
or
argsAreInstantiationsOfToIndex(call, i, f, rnk - 1)
Expand Down
Loading
Loading