Skip to content

Commit 8266451

Browse files
committed
DerefChain
1 parent e269016 commit 8266451

File tree

2 files changed

+174
-70
lines changed

2 files changed

+174
-70
lines changed

rust/ql/lib/codeql/rust/internal/TypeInference.qll

Lines changed: 38 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ private import PathResolution
77
private import Type
88
private import Type as T
99
private import TypeMention
10+
private import typeinference.DerefChain
1011
private import typeinference.FunctionType
1112
private import typeinference.FunctionOverloading as FunctionOverloading
1213
private import typeinference.BlanketImplementation as BlanketImplementation
@@ -1553,13 +1554,13 @@ private module MethodResolution {
15531554
* Same as `getACandidateReceiverTypeAt`, but without borrows.
15541555
*/
15551556
pragma[nomagic]
1556-
Type getACandidateReceiverTypeAtNoBorrow(string derefChain, TypePath path) {
1557+
Type getACandidateReceiverTypeAtNoBorrow(DerefChain derefChain, TypePath path) {
15571558
result = this.getReceiverTypeAt(path) and
15581559
derefChain = ""
15591560
or
1560-
exists(ImplicitDeref::DerefImplItemNode impl, string derefChain0 |
1561-
result = ImplicitDeref::getDereferencedCandidateReceiverType(this, impl, derefChain0, path) and
1562-
derefChain = derefChain0 + "." + impl.getId()
1561+
exists(DerefImplItemNode impl, DerefChain suffix |
1562+
result = ImplicitDeref::getDereferencedCandidateReceiverType(this, impl, suffix, path) and
1563+
derefChain = DerefChain::cons(impl, suffix)
15631564
)
15641565
}
15651566

@@ -1573,7 +1574,7 @@ private module MethodResolution {
15731574
*/
15741575
pragma[nomagic]
15751576
private predicate hasIncompatibleTarget(
1576-
ImplOrTraitItemNode i, string derefChain, BorrowKind borrow, Type root
1577+
ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow, Type root
15771578
) {
15781579
exists(TypePath path |
15791580
ReceiverIsInstantiationOfSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this,
@@ -1590,7 +1591,7 @@ private module MethodResolution {
15901591
*/
15911592
pragma[nomagic]
15921593
private predicate hasIncompatibleBlanketLikeTarget(
1593-
ImplItemNode impl, string derefChain, BorrowKind borrow
1594+
ImplItemNode impl, DerefChain derefChain, BorrowKind borrow
15941595
) {
15951596
ReceiverIsNotInstantiationOfBlanketLikeSelfParam::argIsNotInstantiationOf(MkMethodCallCand(this,
15961597
derefChain, borrow), impl, _, _)
@@ -1603,23 +1604,25 @@ private module MethodResolution {
16031604
* Same as `getACandidateReceiverTypeAt`, but excludes pseudo types `!` and `unknown`.
16041605
*/
16051606
pragma[nomagic]
1606-
Type getANonPseudoCandidateReceiverTypeAt(string derefChain, BorrowKind borrow, TypePath path) {
1607+
Type getANonPseudoCandidateReceiverTypeAt(
1608+
DerefChain derefChain, BorrowKind borrow, TypePath path
1609+
) {
16071610
result = this.getACandidateReceiverTypeAt(derefChain, borrow, path) and
16081611
result != TNeverType() and
16091612
result != TUnknownType()
16101613
}
16111614

16121615
pragma[nomagic]
16131616
private Type getComplexStrippedType(
1614-
string derefChain, BorrowKind borrow, TypePath strippedTypePath
1617+
DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath
16151618
) {
16161619
result = this.getANonPseudoCandidateReceiverTypeAt(derefChain, borrow, strippedTypePath) and
16171620
isComplexRootStripped(strippedTypePath, result)
16181621
}
16191622

16201623
bindingset[derefChain, borrow, strippedTypePath, strippedType]
16211624
private predicate hasNoCompatibleNonBlanketLikeTargetCheck(
1622-
string derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType
1625+
DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType
16231626
) {
16241627
forall(ImplOrTraitItemNode i |
16251628
methodCallNonBlanketCandidate(this, _, i, _, strippedTypePath, strippedType)
@@ -1630,7 +1633,7 @@ private module MethodResolution {
16301633

16311634
bindingset[derefChain, borrow, strippedTypePath, strippedType]
16321635
private predicate hasNoCompatibleTargetCheck(
1633-
string derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType
1636+
DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType
16341637
) {
16351638
this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, borrow, strippedTypePath,
16361639
strippedType) and
@@ -1641,7 +1644,7 @@ private module MethodResolution {
16411644

16421645
bindingset[derefChain, borrow, strippedTypePath, strippedType]
16431646
private predicate hasNoCompatibleNonBlanketTargetCheck(
1644-
string derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType
1647+
DerefChain derefChain, BorrowKind borrow, TypePath strippedTypePath, Type strippedType
16451648
) {
16461649
this.hasNoCompatibleNonBlanketLikeTargetCheck(derefChain, borrow, strippedTypePath,
16471650
strippedType) and
@@ -1655,7 +1658,7 @@ private module MethodResolution {
16551658
// forex using recursion
16561659
pragma[nomagic]
16571660
private predicate hasNoCompatibleTargetNoBorrowToIndex(
1658-
string derefChain, TypePath strippedTypePath, Type strippedType, int n
1661+
DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n
16591662
) {
16601663
(
16611664
this.supportsAutoDerefAndBorrow()
@@ -1678,7 +1681,7 @@ private module MethodResolution {
16781681
* have a matching method target.
16791682
*/
16801683
pragma[nomagic]
1681-
predicate hasNoCompatibleTargetNoBorrow(string derefChain) {
1684+
predicate hasNoCompatibleTargetNoBorrow(DerefChain derefChain) {
16821685
exists(Type strippedType |
16831686
this.hasNoCompatibleTargetNoBorrowToIndex(derefChain, _, strippedType,
16841687
getLastLookupTypeIndex(strippedType))
@@ -1688,7 +1691,7 @@ private module MethodResolution {
16881691
// forex using recursion
16891692
pragma[nomagic]
16901693
private predicate hasNoCompatibleNonBlanketTargetNoBorrowToIndex(
1691-
string derefChain, TypePath strippedTypePath, Type strippedType, int n
1694+
DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n
16921695
) {
16931696
(
16941697
this.supportsAutoDerefAndBorrow()
@@ -1712,7 +1715,7 @@ private module MethodResolution {
17121715
* a matching non-blanket method target.
17131716
*/
17141717
pragma[nomagic]
1715-
predicate hasNoCompatibleNonBlanketTargetNoBorrow(string derefChain) {
1718+
predicate hasNoCompatibleNonBlanketTargetNoBorrow(DerefChain derefChain) {
17161719
exists(Type strippedType |
17171720
this.hasNoCompatibleNonBlanketTargetNoBorrowToIndex(derefChain, _, strippedType,
17181721
getLastLookupTypeIndex(strippedType))
@@ -1722,7 +1725,7 @@ private module MethodResolution {
17221725
// forex using recursion
17231726
pragma[nomagic]
17241727
private predicate hasNoCompatibleTargetSharedBorrowToIndex(
1725-
string derefChain, TypePath strippedTypePath, Type strippedType, int n
1728+
DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n
17261729
) {
17271730
this.hasNoCompatibleTargetNoBorrow(derefChain) and
17281731
strippedType = this.getComplexStrippedType(derefChain, TSharedBorrowKind(), strippedTypePath) and
@@ -1741,7 +1744,7 @@ private module MethodResolution {
17411744
* by a shared borrow, does not have a matching method target.
17421745
*/
17431746
pragma[nomagic]
1744-
predicate hasNoCompatibleTargetSharedBorrow(string derefChain) {
1747+
predicate hasNoCompatibleTargetSharedBorrow(DerefChain derefChain) {
17451748
exists(Type strippedType |
17461749
this.hasNoCompatibleTargetSharedBorrowToIndex(derefChain, _, strippedType,
17471750
getLastLookupTypeIndex(strippedType))
@@ -1751,7 +1754,7 @@ private module MethodResolution {
17511754
// forex using recursion
17521755
pragma[nomagic]
17531756
private predicate hasNoCompatibleTargetMutBorrowToIndex(
1754-
string derefChain, TypePath strippedTypePath, Type strippedType, int n
1757+
DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n
17551758
) {
17561759
this.hasNoCompatibleTargetSharedBorrow(derefChain) and
17571760
strippedType = this.getComplexStrippedType(derefChain, TMutBorrowKind(), strippedTypePath) and
@@ -1769,7 +1772,7 @@ private module MethodResolution {
17691772
* by a `mut` borrow, does not have a matching method target.
17701773
*/
17711774
pragma[nomagic]
1772-
predicate hasNoCompatibleTargetMutBorrow(string derefChain) {
1775+
predicate hasNoCompatibleTargetMutBorrow(DerefChain derefChain) {
17731776
exists(Type strippedType |
17741777
this.hasNoCompatibleTargetMutBorrowToIndex(derefChain, _, strippedType,
17751778
getLastLookupTypeIndex(strippedType))
@@ -1779,7 +1782,7 @@ private module MethodResolution {
17791782
// forex using recursion
17801783
pragma[nomagic]
17811784
private predicate hasNoCompatibleNonBlanketTargetSharedBorrowToIndex(
1782-
string derefChain, TypePath strippedTypePath, Type strippedType, int n
1785+
DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n
17831786
) {
17841787
this.hasNoCompatibleTargetNoBorrow(derefChain) and
17851788
strippedType = this.getComplexStrippedType(derefChain, TSharedBorrowKind(), strippedTypePath) and
@@ -1798,7 +1801,7 @@ private module MethodResolution {
17981801
* by a shared borrow, does not have a matching non-blanket method target.
17991802
*/
18001803
pragma[nomagic]
1801-
predicate hasNoCompatibleNonBlanketTargetSharedBorrow(string derefChain) {
1804+
predicate hasNoCompatibleNonBlanketTargetSharedBorrow(DerefChain derefChain) {
18021805
exists(Type strippedType |
18031806
this.hasNoCompatibleNonBlanketTargetSharedBorrowToIndex(derefChain, _, strippedType,
18041807
getLastLookupTypeIndex(strippedType))
@@ -1808,7 +1811,7 @@ private module MethodResolution {
18081811
// forex using recursion
18091812
pragma[nomagic]
18101813
private predicate hasNoCompatibleNonBlanketTargetMutBorrowToIndex(
1811-
string derefChain, TypePath strippedTypePath, Type strippedType, int n
1814+
DerefChain derefChain, TypePath strippedTypePath, Type strippedType, int n
18121815
) {
18131816
this.hasNoCompatibleNonBlanketTargetSharedBorrow(derefChain) and
18141817
strippedType = this.getComplexStrippedType(derefChain, TMutBorrowKind(), strippedTypePath) and
@@ -1826,7 +1829,7 @@ private module MethodResolution {
18261829
* by a `mut` borrow, does not have a matching non-blanket method target.
18271830
*/
18281831
pragma[nomagic]
1829-
predicate hasNoCompatibleNonBlanketTargetMutBorrow(string derefChain) {
1832+
predicate hasNoCompatibleNonBlanketTargetMutBorrow(DerefChain derefChain) {
18301833
exists(Type strippedType |
18311834
this.hasNoCompatibleNonBlanketTargetMutBorrowToIndex(derefChain, _, strippedType,
18321835
getLastLookupTypeIndex(strippedType))
@@ -1846,7 +1849,7 @@ private module MethodResolution {
18461849
* [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
18471850
*/
18481851
pragma[nomagic]
1849-
Type getACandidateReceiverTypeAt(string derefChain, BorrowKind borrow, TypePath path) {
1852+
Type getACandidateReceiverTypeAt(DerefChain derefChain, BorrowKind borrow, TypePath path) {
18501853
result = this.getACandidateReceiverTypeAtNoBorrow(derefChain, path) and
18511854
borrow = TNoBorrowKind()
18521855
or
@@ -1879,23 +1882,23 @@ private module MethodResolution {
18791882
* `derefChain` and the enum `borrow`.
18801883
*/
18811884
pragma[nomagic]
1882-
Method resolveCallTarget(ImplOrTraitItemNode i, string derefChain, BorrowKind borrow) {
1885+
Method resolveCallTarget(ImplOrTraitItemNode i, DerefChain derefChain, BorrowKind borrow) {
18831886
exists(MethodCallCand mcc |
18841887
mcc = MkMethodCallCand(this, derefChain, borrow) and
18851888
result = mcc.resolveCallTarget(i)
18861889
)
18871890
}
18881891

18891892
predicate receiverHasImplicitDeref(AstNode receiver) {
1890-
exists(ImplicitDeref::DerefImplItemNode impl |
1893+
exists(DerefImplItemNode impl |
18911894
impl.isRefImpl() and
1892-
exists(this.resolveCallTarget(_, "." + impl.getId(), TNoBorrowKind())) and
1895+
exists(this.resolveCallTarget(_, DerefChain::singleton(impl), TNoBorrowKind())) and
18931896
receiver = this.getArg(any(ArgumentPosition pos | pos.isSelf()))
18941897
)
18951898
}
18961899

18971900
predicate argumentHasImplicitBorrow(AstNode arg, BorrowKind borrow) {
1898-
exists(this.resolveCallTarget(_, "", borrow)) and
1901+
exists(this.resolveCallTarget(_, DerefChain::nil(), borrow)) and
18991902
borrow != TNoBorrowKind() and
19001903
arg = this.getArg(any(ArgumentPosition pos | pos.isSelf()))
19011904
}
@@ -2056,14 +2059,14 @@ private module MethodResolution {
20562059
}
20572060

20582061
private newtype TMethodCallCand =
2059-
MkMethodCallCand(MethodCall mc, string derefChain, BorrowKind borrow) {
2062+
MkMethodCallCand(MethodCall mc, DerefChain derefChain, BorrowKind borrow) {
20602063
exists(mc.getACandidateReceiverTypeAt(derefChain, borrow, _))
20612064
}
20622065

20632066
/** A method call with a dereference chain and a potential borrow. */
20642067
private class MethodCallCand extends MkMethodCallCand {
20652068
MethodCall mc_;
2066-
string derefChain;
2069+
DerefChain derefChain;
20672070
BorrowKind borrow;
20682071

20692072
MethodCallCand() { this = MkMethodCallCand(mc_, derefChain, borrow) }
@@ -2161,51 +2164,16 @@ private module MethodResolution {
21612164
}
21622165

21632166
module ImplicitDeref {
2164-
private import codeql.rust.elements.internal.generated.Raw
2165-
private import codeql.rust.elements.internal.generated.Synth
2166-
2167-
/** An `impl` block that implements the `Deref` trait. */
2168-
class DerefImplItemNode extends ImplItemNode {
2169-
DerefImplItemNode() { this.resolveTraitTy() instanceof DerefTrait }
2170-
2171-
/**
2172-
* Holds if this `impl` block is the special `Deref` implementation for
2173-
* `&T` or `&mut T`:
2174-
*
2175-
* ```rust
2176-
* impl<T: ?Sized> const Deref for &T
2177-
* ```
2178-
*
2179-
* or
2180-
*
2181-
* ```rust
2182-
* impl<T: ?Sized> const Deref for &mut T
2183-
* ```
2184-
*/
2185-
predicate isRefImpl() { this.resolveSelfTyBuiltin() instanceof Builtins::RefType }
2186-
2187-
/** Gets an internal unique ID used to identify this block amongst all `Deref` impl blocks. */
2188-
int getId() { idOfRaw(Synth::convertAstNodeToRaw(this), result) }
2189-
}
2190-
2191-
private class DerefImplItemRaw extends Raw::Impl {
2192-
DerefImplItemRaw() { this = Synth::convertAstNodeToRaw(any(DerefImplItemNode i)) }
2193-
}
2194-
2195-
private predicate id(DerefImplItemRaw x, DerefImplItemRaw y) { x = y }
2196-
2197-
private predicate idOfRaw(DerefImplItemRaw x, int y) = equivalenceRelation(id/2)(x, y)
2198-
21992167
private newtype TMethodCallDerefCand =
2200-
MkMethodCallDerefCand(MethodCall mc, string derefChain) {
2168+
MkMethodCallDerefCand(MethodCall mc, DerefChain derefChain) {
22012169
mc.supportsAutoDerefAndBorrow() and
22022170
mc.hasNoCompatibleTargetMutBorrow(derefChain) and
22032171
exists(mc.getACandidateReceiverTypeAtNoBorrow(derefChain, _))
22042172
}
22052173

22062174
private class MethodCallDerefCand extends MkMethodCallDerefCand {
22072175
MethodCall mc_;
2208-
string derefChain;
2176+
DerefChain derefChain;
22092177

22102178
MethodCallDerefCand() { this = MkMethodCallDerefCand(mc_, derefChain) }
22112179

@@ -2241,7 +2209,7 @@ private module MethodResolution {
22412209

22422210
pragma[nomagic]
22432211
Type getDereferencedCandidateReceiverType(
2244-
MethodCall mc, DerefImplItemNode impl, string derefChain, TypePath path
2212+
MethodCall mc, DerefImplItemNode impl, DerefChain derefChain, TypePath path
22452213
) {
22462214
exists(MethodCallDerefCand mcc, TypePath exprPath |
22472215
mcc = MkMethodCallDerefCand(mc, derefChain) and
@@ -2607,10 +2575,10 @@ private Type inferMethodCallType1(AstNode n, boolean isReturn, TypePath path) {
26072575
path = path0
26082576
or
26092577
// adjust for implicit deref
2610-
exists(MethodResolution::ImplicitDeref::DerefImplItemNode impl |
2578+
exists(DerefImplItemNode impl |
26112579
impl.isRefImpl() and
26122580
apos.isSelf() and
2613-
derefChainBorrow = "." + impl.getId() + ";" and
2581+
derefChainBorrow = DerefChain::singleton(impl) + ";" and
26142582
path = TypePath::cons(getRefTypeParameter(), path0)
26152583
)
26162584
or

0 commit comments

Comments
 (0)