Skip to content

Commit f443577

Browse files
committed
blanket2
1 parent 431179f commit f443577

File tree

3 files changed

+164
-58
lines changed

3 files changed

+164
-58
lines changed

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

Lines changed: 155 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,28 +1221,6 @@ private module MethodCallResolution {
12211221
)
12221222
}
12231223

1224-
/**
1225-
* Holds if method `m` with the name `name` and the arity `arity` exists in
1226-
* `i`, and the type of the `self` parameter is `selfType`.
1227-
*
1228-
* `strippedTypePath` points to the type `strippedType` inside `selfType`,
1229-
* which is the (possibly complex-stripped) root type of `selfType`.
1230-
*/
1231-
pragma[nomagic]
1232-
private predicate methodInfo0(
1233-
Function m, string name, int arity, ImplOrTraitItemNode i, FunctionType selfType,
1234-
TypePath strippedTypePath, Type strippedType
1235-
) {
1236-
exists(FunctionTypePosition pos |
1237-
m = i.getASuccessor(name) and
1238-
arity = m.getParamList().getNumberOfParams() and
1239-
strippedType = selfType.getTypeAt(strippedTypePath) and
1240-
isComplexRootStripped(strippedTypePath, strippedType) and
1241-
selfType.appliesTo(m, pos, i) and
1242-
pos.isSelf()
1243-
)
1244-
}
1245-
12461224
/**
12471225
* Holds if method `m` with the name `name` and the arity `arity` exists in
12481226
* `i`, and the type of the `self` parameter is `selfType`.
@@ -1261,41 +1239,55 @@ private module MethodCallResolution {
12611239
strippedType = selfType.getTypeAt(strippedTypePath) and
12621240
isComplexRootStripped(strippedTypePath, strippedType) and
12631241
selfType.appliesTo(m, pos, i) and
1264-
pos.isSelf() and
1265-
not i.(ImplItemNode).isBlanketImplementation()
1242+
pos.isSelf()
12661243
)
12671244
}
12681245

12691246
pragma[nomagic]
12701247
predicate methodInfoTypeParam(
12711248
Function m, string name, int arity, ImplOrTraitItemNode i, FunctionType selfType,
1272-
TypePath strippedTypePath
1249+
TypePath strippedTypePath, TypeParam tp
12731250
) {
1274-
methodInfo(m, name, arity, i, selfType, strippedTypePath, TTypeParamTypeParameter(_))
1251+
methodInfo(m, name, arity, i, selfType, strippedTypePath, TTypeParamTypeParameter(tp))
12751252
}
12761253

1254+
private import codeql.util.Option
1255+
1256+
private class TypeParamOption = Option<TypeParam>::Option;
1257+
12771258
/**
12781259
* Same as `methodInfo`, but allows for any `strippedType` when the
12791260
* corresponding type inside `m` is a type parameter.
12801261
*/
1281-
pragma[inline]
1262+
bindingset[strippedTypePath]
12821263
predicate methodInfoMatch(
12831264
Function m, string name, int arity, ImplOrTraitItemNode i, FunctionType selfType,
1284-
TypePath strippedTypePath, Type strippedType
1265+
TypePath strippedTypePath, Type strippedType, TypePath blanketPath,
1266+
TypeParamOption blanketTypeParam
12851267
) {
1286-
methodInfo(m, name, arity, i, selfType, strippedTypePath, strippedType)
1287-
or
1288-
methodInfoTypeParam(m, name, arity, i, selfType, strippedTypePath)
1268+
(
1269+
methodInfo(m, name, arity, i, selfType, strippedTypePath, strippedType) or
1270+
methodInfoTypeParam(m, name, arity, i, selfType, strippedTypePath, _)
1271+
) and
1272+
not i.(ImplItemNode).isBlanketImplementation() and
1273+
blanketPath = "" and
1274+
blanketTypeParam.isNone()
1275+
or
1276+
exists(TypeParam tp |
1277+
methodInfoTypeParam(m, name, arity, i, selfType, blanketPath, tp) and
1278+
tp = blanketTypeParam.asSome() and
1279+
tp = i.(ImplItemNode).getBlanketImplementationTypeParam()
1280+
)
12891281
}
12901282

12911283
pragma[nomagic]
12921284
private predicate methodTraitInfo(string name, int arity, Trait trait) {
12931285
exists(ImplItemNode i |
1294-
methodInfo0(_, name, arity, i, _, _, _) and
1286+
methodInfo(_, name, arity, i, _, _, _) and
12951287
trait = i.resolveTraitTy()
12961288
)
12971289
or
1298-
methodInfo0(_, name, arity, trait, _, _, _)
1290+
methodInfo(_, name, arity, trait, _, _, _)
12991291
}
13001292

13011293
pragma[nomagic]
@@ -1330,12 +1322,13 @@ private module MethodCallResolution {
13301322
bindingset[mc, strippedTypePath, strippedType]
13311323
pragma[inline_late]
13321324
private predicate methodCallCandidate(
1333-
MethodCall mc, ImplOrTraitItemNode i, FunctionType self, TypePath strippedTypePath,
1334-
Type strippedType
1325+
MethodCall mc, Function m, ImplOrTraitItemNode i, FunctionType self, TypePath strippedTypePath,
1326+
Type strippedType, TypePath blanketPath, TypeParamOption blanketTypeParam
13351327
) {
13361328
exists(string name, int arity |
13371329
mc.hasNameAndArity(name, arity) and
1338-
methodInfoMatch(_, name, arity, i, self, strippedTypePath, strippedType)
1330+
methodInfoMatch(m, name, arity, i, self, strippedTypePath, strippedType, blanketPath,
1331+
blanketTypeParam)
13391332
|
13401333
i =
13411334
any(Impl impl |
@@ -1430,8 +1423,9 @@ private module MethodCallResolution {
14301423
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
14311424
strippedType = this.getComplexstrippedType(strippedTypePath, derefChainBorrow)
14321425
|
1433-
forall(ImplOrTraitItemNode i |
1434-
methodCallCandidate(this, i, _, strippedTypePath, strippedType)
1426+
forall(ImplOrTraitItemNode i, TypeParamOption blanketTypeParam |
1427+
methodCallCandidate(this, _, i, _, strippedTypePath, strippedType, _, blanketTypeParam) and
1428+
blanketTypeParam.isNone()
14351429
|
14361430
this.hasIncompatibleTarget(i, derefChainBorrow)
14371431
)
@@ -1449,8 +1443,9 @@ private module MethodCallResolution {
14491443
this.hasNoCompatibleTargetNoBorrow(derefChain) and
14501444
strippedType = this.getComplexstrippedType(strippedTypePath, derefChainBorrow)
14511445
|
1452-
forall(ImplOrTraitItemNode i |
1453-
methodCallCandidate(this, i, _, strippedTypePath, strippedType)
1446+
forall(ImplOrTraitItemNode i, TypeParamOption blanketTypeParam |
1447+
methodCallCandidate(this, _, i, _, strippedTypePath, strippedType, _, blanketTypeParam) and
1448+
blanketTypeParam.isNone()
14541449
|
14551450
this.hasIncompatibleTarget(i, derefChainBorrow)
14561451
)
@@ -1590,7 +1585,7 @@ private module MethodCallResolution {
15901585
exists(TypePath strippedTypePath, Type strippedType, string name, int arity |
15911586
this.hasInfo(_, strippedTypePath, strippedType, name, arity) and
15921587
forall(Impl i |
1593-
methodInfoMatch(_, name, arity, i, _, strippedTypePath, strippedType) and
1588+
methodInfoMatch(_, name, arity, i, _, strippedTypePath, strippedType, _, _) and
15941589
not i.hasTrait()
15951590
|
15961591
this.hasIncompatibleInherentTarget(i)
@@ -1645,15 +1640,108 @@ private module MethodCallResolution {
16451640
result = this.resolveAmbigousCallTargetCand(pos, path, type) and
16461641
type = this.inferPositionalArgumentType(pos, path)
16471642
)
1648-
or
1649-
result = BlanketImplementation::getMethodFromBlanketImpl(this)
1643+
// or
1644+
// result = BlanketImplementation::getMethodFromBlanketImpl(this)
16501645
}
16511646

16521647
string toString() { result = mc_.toString() + " [" + derefChainBorrow + "]" }
16531648

16541649
Location getLocation() { result = mc_.getLocation() }
16551650
}
16561651

1652+
private newtype TMethodCallCandAndBlanketOffset =
1653+
MkMethodCallCandAndBlanketOffset(MethodCallCand mcc, TypePath blanketPath) {
1654+
exists(
1655+
MethodCall mc, string name, int arity, TypePath strippedTypePath, Type strippedType,
1656+
TypeParamOption blanketTypeParam
1657+
|
1658+
mcc.hasInfo(mc, strippedTypePath, strippedType, name, arity) and
1659+
methodCallCandidate(mc, _, _, _, strippedTypePath, strippedType, blanketPath,
1660+
blanketTypeParam) and
1661+
blanketTypeParam.isSome()
1662+
)
1663+
}
1664+
1665+
private class MethodCallCandAndBlanketOffset extends MkMethodCallCandAndBlanketOffset {
1666+
MethodCallCand mcc_;
1667+
TypePath blanketPath;
1668+
1669+
MethodCallCandAndBlanketOffset() { this = MkMethodCallCandAndBlanketOffset(mcc_, blanketPath) }
1670+
1671+
MethodCallCand getMethodCallCand() { result = mcc_ }
1672+
1673+
TypePath getBlanketPath() { result = blanketPath }
1674+
1675+
Location getLocation() { result = mcc_.getLocation() }
1676+
1677+
Type getTypeAt(TypePath path) { result = mcc_.getTypeAt(blanketPath.appendInverse(path)) }
1678+
1679+
string toString() { result = mcc_.toString() + " (blanket at " + blanketPath.toString() + ")" }
1680+
}
1681+
1682+
private module SatisfiesBlanketConstraintInput implements
1683+
SatisfiesConstraintInputSig<MethodCallCandAndBlanketOffset>
1684+
{
1685+
/**
1686+
* Holds if `impl` is a blanket implementation for a type parameter and
1687+
* `traitBound` is the first non-trivial trait bound of that type parameter.
1688+
*/
1689+
pragma[nomagic]
1690+
private predicate blanketImplementationTraitBound(TypeParamItemNode tp, Trait traitBound) {
1691+
tp = any(ImplItemNode impl).getBlanketImplementationTypeParam() and
1692+
traitBound =
1693+
min(Trait trait, int i |
1694+
trait = tp.resolveBound(i) and
1695+
// Exclude traits that are known to not narrow things down very much.
1696+
not trait.getName().getText() =
1697+
[
1698+
"Sized", "Clone",
1699+
// The auto traits
1700+
"Send", "Sync", "Unpin", "UnwindSafe", "RefUnwindSafe"
1701+
]
1702+
|
1703+
trait order by i
1704+
)
1705+
}
1706+
1707+
pragma[nomagic]
1708+
additional predicate relevantConstraint(
1709+
MethodCallCandAndBlanketOffset mcco, Function m, Trait traitBound
1710+
) {
1711+
exists(
1712+
MethodCallCand mcc, MethodCall mc, string name, int arity, TypePath strippedTypePath,
1713+
Type strippedType, TypePath blanketPath, TypeParamOption blanketTypeParam
1714+
|
1715+
mcco = MkMethodCallCandAndBlanketOffset(mcc, blanketPath) and
1716+
mcc.hasInfo(mc, strippedTypePath, strippedType, name, arity) and
1717+
methodCallCandidate(mc, m, _, _, strippedTypePath, strippedType, blanketPath,
1718+
blanketTypeParam) and
1719+
blanketImplementationTraitBound(blanketTypeParam.asSome(), traitBound)
1720+
)
1721+
// exists(MethodCall mc, Trait traitBound, Trait traitImpl |
1722+
// methodCallMatchesBlanketImpl(mcc, mc, _, _, traitBound, traitImpl, _) and
1723+
// methodCallVisibleTraitCandidate(mc, traitImpl) and
1724+
// traitBound = constraint.(TraitType).getTrait()
1725+
// )
1726+
}
1727+
1728+
pragma[nomagic]
1729+
predicate relevantConstraint(MethodCallCandAndBlanketOffset mcco, Type constraint) {
1730+
relevantConstraint(mcco, _, constraint.(TraitType).getTrait())
1731+
}
1732+
1733+
predicate useUniversalConditions() { none() }
1734+
}
1735+
1736+
private predicate hasBlanketImpl(MethodCallCand mcc, Function f) {
1737+
exists(MethodCallCandAndBlanketOffset mcco, Trait traitBound |
1738+
mcco = MkMethodCallCandAndBlanketOffset(mcc, _) and
1739+
SatisfiesBlanketConstraintInput::relevantConstraint(mcco, f, traitBound) and
1740+
SatisfiesConstraint<MethodCallCandAndBlanketOffset, SatisfiesBlanketConstraintInput>::satisfiesConstraintType(mcco,
1741+
TTrait(traitBound), _, _)
1742+
)
1743+
}
1744+
16571745
/**
16581746
* A configuration for matching the type of a receiver against the type of
16591747
* a `self` parameter.
@@ -1665,9 +1753,17 @@ private module MethodCallResolution {
16651753
predicate potentialInstantiationOf(
16661754
MethodCallCand mcc, TypeAbstraction abs, FunctionType constraint
16671755
) {
1668-
exists(MethodCall mc, string name, int arity, TypePath strippedTypePath, Type strippedType |
1756+
exists(
1757+
MethodCall mc, Function m, string name, int arity, TypePath strippedTypePath,
1758+
Type strippedType, TypePath blanketPath, TypeParamOption blanketTypeParam
1759+
|
16691760
mcc.hasInfo(mc, strippedTypePath, strippedType, name, arity) and
1670-
methodCallCandidate(mc, abs, constraint, strippedTypePath, strippedType)
1761+
methodCallCandidate(mc, m, abs, constraint, strippedTypePath, strippedType, blanketPath,
1762+
blanketTypeParam)
1763+
|
1764+
blanketTypeParam.isNone()
1765+
or
1766+
hasBlanketImpl(mcc, m)
16711767
)
16721768
}
16731769

@@ -2137,20 +2233,23 @@ private module FunctionCallResolution {
21372233
TypePath strippedTypePath, Type strippedType, TraitItemNode trait, Function f,
21382234
Function traitFunction
21392235
) {
2140-
MethodCallResolution::methodInfo(f, _, _, _, _, strippedTypePath, strippedType) and
2141-
traitFunction = trait.getAnAssocItem() and
2142-
(
2143-
f.implements(traitFunction)
2144-
or
2145-
f = traitFunction
2236+
exists(ImplOrTraitItemNode i |
2237+
MethodCallResolution::methodInfo(f, _, _, i, _, strippedTypePath, strippedType) and
2238+
not i.(ImplItemNode).isBlanketImplementation() and
2239+
traitFunction = trait.getAnAssocItem() and
2240+
(
2241+
f.implements(traitFunction)
2242+
or
2243+
f = traitFunction
2244+
)
21462245
)
21472246
}
21482247

21492248
pragma[nomagic]
21502249
private predicate methodInfoTypeParam(
21512250
TypePath strippedTypePath, TraitItemNode trait, Function f, Function traitFunction
21522251
) {
2153-
MethodCallResolution::methodInfoTypeParam(f, _, _, _, _, strippedTypePath) and
2252+
MethodCallResolution::methodInfoTypeParam(f, _, _, _, _, strippedTypePath, _) and
21542253
traitFunction = trait.getAnAssocItem() and
21552254
(
21562255
f.implements(traitFunction)
@@ -2430,13 +2529,15 @@ private module OperationResolution {
24302529
private module OperationIsInstantiationOfInput implements
24312530
IsInstantiationOfInputSig<Op, FunctionType>
24322531
{
2433-
pragma[inline]
2532+
// todo
2533+
bindingset[strippedTypePath]
24342534
private predicate methodInfoMatch(
24352535
TypeAbstraction abs, FunctionType constraint, Trait trait, string name, int arity,
24362536
TypePath strippedTypePath, Type strippedType
24372537
) {
24382538
MethodCallResolution::methodInfoMatch(_, name, arity, abs, constraint, strippedTypePath,
2439-
strippedType) and
2539+
strippedType, _, _) and
2540+
not abs.(ImplItemNode).isBlanketImplementation() and
24402541
(
24412542
trait = abs.(ImplItemNode).resolveTraitTy()
24422543
or

rust/ql/test/library-tests/type-inference/type-inference.expected

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,26 @@ inferType
4242
| blanket_impl.rs:49:18:49:25 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
4343
| blanket_impl.rs:49:18:49:25 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
4444
| blanket_impl.rs:49:20:49:21 | x2 | | blanket_impl.rs:6:5:7:14 | S1 |
45+
| blanket_impl.rs:50:13:50:14 | x3 | | blanket_impl.rs:6:5:7:14 | S1 |
4546
| blanket_impl.rs:50:18:50:19 | S1 | | blanket_impl.rs:6:5:7:14 | S1 |
46-
| blanket_impl.rs:50:18:50:19 | S1 | | file://:0:0:0:0 | & |
47+
| blanket_impl.rs:50:18:50:31 | S1.duplicate() | | blanket_impl.rs:6:5:7:14 | S1 |
4748
| blanket_impl.rs:51:18:51:25 | "{x3:?}\\n" | | file://:0:0:0:0 | & |
4849
| blanket_impl.rs:51:18:51:25 | "{x3:?}\\n" | &T | {EXTERNAL LOCATION} | str |
4950
| blanket_impl.rs:51:18:51:25 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
5051
| blanket_impl.rs:51:18:51:25 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
52+
| blanket_impl.rs:51:20:51:21 | x3 | | blanket_impl.rs:6:5:7:14 | S1 |
53+
| blanket_impl.rs:52:13:52:14 | x4 | | blanket_impl.rs:6:5:7:14 | S1 |
5154
| blanket_impl.rs:52:18:52:22 | (...) | | file://:0:0:0:0 | & |
5255
| blanket_impl.rs:52:18:52:22 | (...) | &T | blanket_impl.rs:6:5:7:14 | S1 |
53-
| blanket_impl.rs:52:18:52:22 | (...) | &T | file://:0:0:0:0 | & |
56+
| blanket_impl.rs:52:18:52:34 | ... .duplicate() | | blanket_impl.rs:6:5:7:14 | S1 |
5457
| blanket_impl.rs:52:19:52:21 | &S1 | | file://:0:0:0:0 | & |
5558
| blanket_impl.rs:52:19:52:21 | &S1 | &T | blanket_impl.rs:6:5:7:14 | S1 |
56-
| blanket_impl.rs:52:19:52:21 | &S1 | &T | file://:0:0:0:0 | & |
5759
| blanket_impl.rs:52:20:52:21 | S1 | | blanket_impl.rs:6:5:7:14 | S1 |
58-
| blanket_impl.rs:52:20:52:21 | S1 | | file://:0:0:0:0 | & |
5960
| blanket_impl.rs:53:18:53:25 | "{x4:?}\\n" | | file://:0:0:0:0 | & |
6061
| blanket_impl.rs:53:18:53:25 | "{x4:?}\\n" | &T | {EXTERNAL LOCATION} | str |
6162
| blanket_impl.rs:53:18:53:25 | FormatArgsExpr | | {EXTERNAL LOCATION} | Arguments |
6263
| blanket_impl.rs:53:18:53:25 | MacroExpr | | {EXTERNAL LOCATION} | Arguments |
64+
| blanket_impl.rs:53:20:53:21 | x4 | | blanket_impl.rs:6:5:7:14 | S1 |
6365
| blanket_impl.rs:54:18:54:19 | S2 | | blanket_impl.rs:9:5:10:14 | S2 |
6466
| blanket_impl.rs:55:18:55:25 | "{x5:?}\\n" | | file://:0:0:0:0 | & |
6567
| blanket_impl.rs:55:18:55:25 | "{x5:?}\\n" | &T | {EXTERNAL LOCATION} | str |

shared/util/codeql/util/Option.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ module Option<TypeWithToString T> {
4646

4747
/** Holds if this option is the singleton `None`. */
4848
predicate isNone() { this = TNone() }
49+
50+
/** Holds if this option contains a wrapped element. */
51+
predicate isSome() { this = TSome(_) }
4952
}
5053

5154
/** The singleton `None` element. */

0 commit comments

Comments
 (0)