Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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()])]
Comment thread
hvitved marked this conversation as resolved.
} 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`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This might be a good spot to also explain why we need this. That "erasing" the difference between positions in methods and non-methods lets us handle calls of the form Type::foo(...) where we can't know a priori whether foo is a method or a non-method and hence we need to match up the arguments in the call against both.

*/
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