Skip to content

Commit fd51708

Browse files
committed
Rust: Improve performance maybe
1 parent f91aadc commit fd51708

File tree

2 files changed

+80
-41
lines changed

2 files changed

+80
-41
lines changed

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

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -240,12 +240,7 @@ abstract class ItemNode extends Locatable {
240240
)
241241
or
242242
// items made available by an implementation where `this` is the implementing type
243-
exists(ItemNode node |
244-
this = node.(ImplItemNodeImpl).resolveSelfTyCand() and
245-
result = node.getASuccessor(name, kind) and
246-
kind.isExternalOrBoth() and
247-
result instanceof AssocItemNode
248-
)
243+
typeImplEdge(this, _, name, kind, result)
249244
or
250245
// trait items with default implementations made available in an implementation
251246
exists(ImplItemNodeImpl impl, ItemNode trait |
@@ -1422,10 +1417,33 @@ private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKi
14221417
pragma[nomagic]
14231418
private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") }
14241419

1425-
/** Holds if the trait `trait` is visible at the element `element`. */
1426-
bindingset[element, trait]
1427-
predicate traitIsVisible(Element element, TraitItemNode trait) {
1428-
exists(ItemNode encl | encl.getADescendant*() = element and trait = encl.getASuccessor(_, _))
1420+
/** Provides the input to `TraitIsVisible`. */
1421+
signature predicate relevantTraitVisibleSig(Element element, Trait trait);
1422+
1423+
/**
1424+
* Provides the `traitIsVisible` predicate for determining if a trait is visible
1425+
* at a given element.
1426+
*/
1427+
module TraitIsVisible<relevantTraitVisibleSig/2 relevantTraitVisible> {
1428+
/** Holds if the trait might be looked up in `encl`. */
1429+
private predicate traitLookup(ItemNode encl, Element element, Trait trait) {
1430+
// lookup in immediately enclosing item
1431+
relevantTraitVisible(element, trait) and
1432+
encl.getADescendant() = element
1433+
or
1434+
// lookup in an outer scope, but only if the trait is not declared in inner scope
1435+
exists(ItemNode mid |
1436+
traitLookup(mid, element, trait) and
1437+
not trait = mid.getASuccessor(_, _) and
1438+
encl = getOuterScope(mid)
1439+
)
1440+
}
1441+
1442+
/** Holds if the trait `trait` is visible at `element`. */
1443+
pragma[nomagic]
1444+
predicate traitIsVisible(Element element, Trait trait) {
1445+
exists(ItemNode encl | traitLookup(encl, element, trait) and trait = encl.getASuccessor(_, _))
1446+
}
14291447
}
14301448

14311449
pragma[nomagic]
@@ -1453,14 +1471,6 @@ private ItemNode resolvePathCandQualifier(RelevantPath qualifier, RelevantPath p
14531471
name = path.getText()
14541472
}
14551473

1456-
pragma[nomagic]
1457-
private TraitItemNode assocItemImplementsTrait(AssocItemNode assoc) {
1458-
exists(ImplItemNodeImpl impl |
1459-
impl.getAnAssocItem() = assoc and
1460-
result = impl.resolveTraitTyCand()
1461-
)
1462-
}
1463-
14641474
/**
14651475
* Gets the item that `path` resolves to in `ns` when `qualifier` is the
14661476
* qualifier of `path` and `qualifier` resolves to `q`, if any.
@@ -1539,6 +1549,19 @@ private ItemNode resolvePathCand(RelevantPath path) {
15391549
)
15401550
}
15411551

1552+
/** Get a trait that should be visible when `path` resolves to `node`, if any. */
1553+
private Trait getResolvePathTraitUsed(RelevantPath path, AssocItemNode node) {
1554+
exists(TypeItemNode type, ImplItemNodeImpl impl |
1555+
node = resolvePathCandQualified(_, type, path, _) and
1556+
typeImplEdge(type, impl, _, _, node) and
1557+
result = impl.resolveTraitTyCand()
1558+
)
1559+
}
1560+
1561+
private predicate pathTraitUsed(Element path, Trait trait) {
1562+
trait = getResolvePathTraitUsed(path, _)
1563+
}
1564+
15421565
/** Gets the item that `path` resolves to, if any. */
15431566
cached
15441567
ItemNode resolvePath(RelevantPath path) {
@@ -1547,9 +1570,9 @@ ItemNode resolvePath(RelevantPath path) {
15471570
(
15481571
// When the result is an associated item of a trait implementation the
15491572
// implemented trait must be visible.
1550-
traitIsVisible(path, assocItemImplementsTrait(pragma[only_bind_out](result)))
1573+
TraitIsVisible<pathTraitUsed/2>::traitIsVisible(path, getResolvePathTraitUsed(path, result))
15511574
or
1552-
not exists(ImplItemNode impl | impl.getAnAssocItem() = result and impl.(Impl).hasTrait())
1575+
not exists(getResolvePathTraitUsed(path, result))
15531576
)
15541577
or
15551578
// if `path` is the qualifier of a resolvable `parent`, then we should
@@ -1663,6 +1686,18 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
16631686
)
16641687
}
16651688

1689+
/**
1690+
* Holds if `typeItem` is the implementing type of `impl` and the implementation
1691+
* makes `assoc` available as `name` at `kind`.
1692+
*/
1693+
private predicate typeImplEdge(
1694+
TypeItemNode typeItem, ImplItemNodeImpl impl, string name, SuccessorKind kind, AssocItemNode assoc
1695+
) {
1696+
typeItem = impl.resolveSelfTyCand() and
1697+
assoc = impl.getASuccessor(name, kind) and
1698+
kind.isExternalOrBoth()
1699+
}
1700+
16661701
pragma[nomagic]
16671702
private predicate preludeItem(string name, ItemNode i) {
16681703
exists(Crate stdOrCore, ModuleLikeNode mod, ModuleItemNode prelude, ModuleItemNode rust |

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

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,16 +1885,6 @@ private predicate methodCandidate(Type type, string name, int arity, Impl impl)
18851885
)
18861886
}
18871887

1888-
/**
1889-
* Holds if a method for `type` for `trait` with the name `name` and the arity
1890-
* `arity` exists in `impl`.
1891-
*/
1892-
pragma[nomagic]
1893-
private predicate methodCandidateTrait(Type type, Trait trait, string name, int arity, Impl impl) {
1894-
trait = impl.(ImplItemNode).resolveTraitTy() and
1895-
methodCandidate(type, name, arity, impl)
1896-
}
1897-
18981888
pragma[nomagic]
18991889
private predicate isMethodCall(MethodCall mc, Type rootType, string name, int arity) {
19001890
rootType = mc.getTypeAt(TypePath::nil()) and
@@ -1903,21 +1893,35 @@ private predicate isMethodCall(MethodCall mc, Type rootType, string name, int ar
19031893
}
19041894

19051895
private module IsInstantiationOfInput implements IsInstantiationOfInputSig<MethodCall> {
1906-
pragma[nomagic]
1907-
predicate potentialInstantiationOf(MethodCall mc, TypeAbstraction impl, TypeMention constraint) {
1896+
private predicate methodCallMethodCandidate(MethodCall mc, Impl impl) {
19081897
exists(Type rootType, string name, int arity |
19091898
isMethodCall(mc, rootType, name, arity) and
1910-
constraint = impl.(ImplTypeAbstraction).getSelfTy()
1899+
methodCandidate(rootType, name, arity, impl)
1900+
)
1901+
}
1902+
1903+
private predicate relevantTraitVisible(Element mc, Trait trait) {
1904+
not exists(mc.(MethodCall).getTrait()) and
1905+
trait = any(ImplItemNode impl | methodCallMethodCandidate(mc, impl)).resolveTraitTy()
1906+
}
1907+
1908+
pragma[nomagic]
1909+
predicate potentialInstantiationOf(MethodCall mc, TypeAbstraction abs, TypeMention constraint) {
1910+
exists(ImplItemNode impl |
1911+
impl = abs and
1912+
methodCallMethodCandidate(mc, impl) and
1913+
constraint = impl.(Impl).getSelfTy()
19111914
|
1912-
methodCandidateTrait(rootType, mc.getTrait(), name, arity, impl)
1915+
not exists(impl.resolveTraitTy())
19131916
or
1914-
not exists(mc.getTrait()) and
1915-
methodCandidate(rootType, name, arity, impl) and
1916-
(
1917-
traitIsVisible(mc, impl.(ImplItemNode).resolveTraitTy())
1918-
or
1919-
not exists(impl.(ImplItemNode).resolveTraitTy())
1920-
)
1917+
// If the method call has a trait, the trait is mentioned fully qualified
1918+
// and need not be visible.
1919+
impl.resolveTraitTy() = mc.getTrait()
1920+
or
1921+
// If the `impl` block implements a trait, that trait must be visible in
1922+
// order for the `impl` to be valid.
1923+
TraitIsVisible<relevantTraitVisible/2>::traitIsVisible(mc,
1924+
pragma[only_bind_into](impl.resolveTraitTy()))
19211925
)
19221926
}
19231927

0 commit comments

Comments
 (0)