Skip to content
Draft
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,7 @@ module Impl {

private newtype TArgumentPosition =
TPositionalArgumentPosition(int i) {
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()])]
} 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
88 changes: 47 additions & 41 deletions rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,20 @@

predicate isReturn() { this = TReturnFunctionPosition() }

/** Gets the corresponding position when function call syntax is used. */
FunctionPosition getFunctionCallAdjusted() {
(this.isReturn() or this.isTypeQualifier()) and
result = this
or
this.isSelf() and result.asPosition() = 0
or
result.asPosition() = this.asPosition() + 1
}

/** 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
if f.hasSelfParam() then result = this.getFunctionCallAdjusted() else result = this
}

TypeMention getTypeMention(Function f) {
Expand Down Expand Up @@ -197,7 +199,7 @@
exists(Function f, ImplOrTraitItemNode i, FunctionPosition pos | this.appliesTo(f, i, pos) |
result = pos.getTypeMention(f)
or
pos.isSelf() and
pos.isSelfOrTypeQualifier() and
not f.hasSelfParam() and
result = [i.(Impl).getSelfTy().(AstNode), i.(Trait).getName()]
)
Expand All @@ -209,7 +211,7 @@
}

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 @@ -313,17 +315,17 @@
* 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).
*
* `pos` is one of the positions in `f` in which the relevant type occours.
* `posAdj` is one of the positions in `f` in which the relevant type occurs.
*/
predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition pos);
predicate toCheck(ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition posAdj);

/** A call whose argument types are to be checked. */
class Call {
string toString();

Location getLocation();

Type getArgType(FunctionPosition pos, TypePath path);
Type getArgType(FunctionPosition posAdj, TypePath path);

predicate hasTargetCand(ImplOrTraitItemNode i, Function f);
}
Expand All @@ -337,9 +339,9 @@
module ArgsAreInstantiationsOf<ArgsAreInstantiationsOfInputSig Input> {
pragma[nomagic]
private predicate toCheckRanked(
ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition pos, int rnk
ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition posAdj, int rnk
) {
Input::toCheck(i, f, tp, pos) and
Input::toCheck(i, f, tp, posAdj) and
tp =
rank[rnk + 1](TypeParameter tp0, int j |
Input::toCheck(i, f, tp0, _) and
Expand All @@ -351,41 +353,45 @@

pragma[nomagic]
private predicate toCheck(
ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition pos, AssocFunctionType t
ImplOrTraitItemNode i, Function f, TypeParameter tp, FunctionPosition posAdj,
AssocFunctionType t
) {
Input::toCheck(i, f, tp, pos) and
t.appliesTo(f, i, pos)
exists(FunctionPosition pos |
Input::toCheck(i, f, tp, posAdj) and
t.appliesTo(f, i, pos) and
posAdj = pos.getFunctionCallAdjusted(f)
)
}

private newtype TCallAndPos =
MkCallAndPos(Input::Call call, FunctionPosition pos) { exists(call.getArgType(pos, _)) }
MkCallAndPos(Input::Call call, FunctionPosition posAdj) { exists(call.getArgType(posAdj, _)) }

/** A call tagged with a position. */
private class CallAndPos extends MkCallAndPos {
Input::Call call;
FunctionPosition pos;
FunctionPosition posAdj;

CallAndPos() { this = MkCallAndPos(call, pos) }
CallAndPos() { this = MkCallAndPos(call, posAdj) }

Input::Call getCall() { result = call }

FunctionPosition getPos() { result = pos }
FunctionPosition getPosAdj() { result = posAdj }

Location getLocation() { result = call.getLocation() }

Type getTypeAt(TypePath path) { result = call.getArgType(pos, path) }
Type getTypeAt(TypePath path) { result = call.getArgType(posAdj, path) }

string toString() { result = call.toString() + " [arg " + pos + "]" }
string toString() { result = call.toString() + " [arg " + posAdj + "]" }
}

pragma[nomagic]
private predicate potentialInstantiationOf0(
CallAndPos cp, Input::Call call, TypeParameter tp, FunctionPosition pos, Function f,
CallAndPos cp, Input::Call call, TypeParameter tp, FunctionPosition posAdj, Function f,
TypeAbstraction abs, AssocFunctionType constraint
) {
cp = MkCallAndPos(call, pragma[only_bind_into](pos)) and
cp = MkCallAndPos(call, pragma[only_bind_into](posAdj)) and
call.hasTargetCand(abs, f) and
toCheck(abs, f, tp, pragma[only_bind_into](pos), constraint)
toCheck(abs, f, tp, pragma[only_bind_into](posAdj), constraint)
}

private module ArgIsInstantiationOfToIndexInput implements
Expand All @@ -395,9 +401,9 @@
predicate potentialInstantiationOf(
CallAndPos cp, TypeAbstraction abs, AssocFunctionType constraint
) {
exists(Input::Call call, TypeParameter tp, FunctionPosition pos, int rnk, Function f |
potentialInstantiationOf0(cp, call, tp, pos, f, abs, constraint) and
toCheckRanked(abs, f, tp, pos, rnk)
exists(Input::Call call, TypeParameter tp, FunctionPosition posAdj, int rnk, Function f |
potentialInstantiationOf0(cp, call, tp, posAdj, f, abs, constraint) and
toCheckRanked(abs, f, tp, posAdj, rnk)
|
rnk = 0
or
Expand All @@ -413,18 +419,18 @@

pragma[nomagic]
private predicate argIsInstantiationOf(
Input::Call call, FunctionPosition pos, ImplOrTraitItemNode i, Function f, int rnk
Input::Call call, FunctionPosition posAdj, ImplOrTraitItemNode i, Function f, int rnk
) {
ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, pos), i, _) and
toCheckRanked(i, f, _, pos, rnk)
ArgIsInstantiationOfToIndex::argIsInstantiationOf(MkCallAndPos(call, posAdj), i, _) and
toCheckRanked(i, f, _, posAdj, 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
exists(FunctionPosition posAdj |

Check warning

Code scanning / CodeQL

Omittable 'exists' variable Warning

This exists variable can be omitted by using a don't-care expression
in this argument
.
argIsInstantiationOf(call, posAdj, i, f, rnk) and
call.hasTargetCand(i, f)
|
rnk = 0
Expand Down Expand Up @@ -465,9 +471,9 @@

pragma[nomagic]
private predicate argsAreNotInstantiationsOf0(
Input::Call call, FunctionPosition pos, ImplOrTraitItemNode i
Input::Call call, FunctionPosition posAdj, ImplOrTraitItemNode i
) {
ArgsAreNotInstantiationOf::argIsNotInstantiationOf(MkCallAndPos(call, pos), i, _, _)
ArgsAreNotInstantiationOf::argIsNotInstantiationOf(MkCallAndPos(call, posAdj), i, _, _)
}

/**
Expand All @@ -478,10 +484,10 @@
*/
pragma[nomagic]
predicate argsAreNotInstantiationsOf(Input::Call call, ImplOrTraitItemNode i, Function f) {
exists(FunctionPosition pos |
argsAreNotInstantiationsOf0(call, pos, i) and
exists(FunctionPosition posAdj |
argsAreNotInstantiationsOf0(call, posAdj, i) and
call.hasTargetCand(i, f) and
Input::toCheck(i, f, _, pos)
Input::toCheck(i, f, _, posAdj)
)
}
}
Loading