Skip to content

Commit 71a5549

Browse files
committed
Rust: Address feedback from PR review
1 parent 12dcd75 commit 71a5549

File tree

3 files changed

+51
-52
lines changed

3 files changed

+51
-52
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,19 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
648648

649649
override Visibility getVisibility() { result = Impl.super.getVisibility() }
650650

651+
private TypeParamItemNode getBlanketImplementationTypeParam() {
652+
result = this.resolveSelfTy() and
653+
result = super.getGenericParamList().getAGenericParam() and
654+
// This impl block is not superseded by the expansion of an attribute macro.
655+
not exists(super.getAttributeMacroExpansion())
656+
}
657+
658+
/**
659+
* Holds if this impl block is a blanket implementation. That is, the
660+
* implementation targets a generic parameter of the impl block.
661+
*/
662+
predicate isBlanketImplementation() { exists(this.getBlanketImplementationTypeParam()) }
663+
651664
override predicate hasCanonicalPath(Crate c) { this.resolveSelfTy().hasCanonicalPathPrefix(c) }
652665

653666
/**

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

Lines changed: 36 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,9 +2178,17 @@ private module BlanketImplementation {
21782178
arity = result.(ImplItemNode).resolveTraitTy().(Trait).getNumberOfGenericParams()
21792179
}
21802180

2181+
private predicate duplicatedImpl(Impl impl1, Impl impl2) {
2182+
exists(string fileName, string traitName, int arity, string tpName |
2183+
impl1 = getPotentialDuplicated(fileName, traitName, arity, tpName) and
2184+
impl2 = getPotentialDuplicated(fileName, traitName, arity, tpName) and
2185+
impl1.getLocation().getFile().getAbsolutePath() <
2186+
impl2.getLocation().getFile().getAbsolutePath()
2187+
)
2188+
}
2189+
21812190
/**
2182-
* Holds if `impl1` and `impl2` are duplicates and `impl2` is strictly more
2183-
* "canonical" than `impl1`.
2191+
* Holds if `impl` is a canonical blanket implementation.
21842192
*
21852193
* Libraries can often occur several times in the database for different
21862194
* library versions. This causes the same blanket implementations to exist
@@ -2189,40 +2197,18 @@ private module BlanketImplementation {
21892197
* We detect these duplicates based on some simple heuristics (same trait
21902198
* name, file name, etc.). For these duplicates we select the one with the
21912199
* greatest file name (which usually is also the one with the greatest library
2192-
* version in the path)
2200+
* version in the path) as the "canonical" implementation.
21932201
*/
2194-
predicate duplicatedImpl(Impl impl1, Impl impl2) {
2195-
exists(string fileName, string traitName, int arity, string tpName |
2196-
impl1 = getPotentialDuplicated(fileName, traitName, arity, tpName) and
2197-
impl2 = getPotentialDuplicated(fileName, traitName, arity, tpName) and
2198-
impl1.getLocation().getFile().getAbsolutePath() <
2199-
impl2.getLocation().getFile().getAbsolutePath()
2200-
)
2202+
private predicate isCanonicalImpl(Impl impl) {
2203+
not duplicatedImpl(impl, _) and impl.(ImplItemNode).isBlanketImplementation()
22012204
}
22022205

2203-
predicate isCanonicalImpl(Impl impl) {
2204-
not duplicatedImpl(impl, _) and isBlanketImplementation(impl)
2205-
}
2206-
2207-
Impl getCanonicalImpl(Impl impl) {
2208-
result =
2209-
max(Impl impl0, Location l |
2210-
duplicatedImpl(impl, impl0) and l = impl0.getLocation()
2211-
|
2212-
impl0 order by l.getFile().getAbsolutePath(), l.getStartLine()
2213-
)
2214-
or
2215-
isCanonicalImpl(impl) and result = impl
2216-
}
2217-
2218-
predicate isCanonicalBlanketImplementation(Impl impl) { impl = getCanonicalImpl(impl) }
2219-
22202206
/**
2221-
* Holds if `impl` is a blanket implementation for a type parameter and the type
2222-
* parameter must implement `trait`.
2207+
* Holds if `impl` is a blanket implementation for a type parameter with trait
2208+
* bound `traitBound`.
22232209
*/
2224-
private predicate blanketImplementationTraitBound(Impl impl, Trait t) {
2225-
t =
2210+
private predicate blanketImplementationTraitBound(Impl impl, Trait traitBound) {
2211+
traitBound =
22262212
min(Trait trait, int i |
22272213
trait = getBlanketImplementationTypeParam(impl).resolveBound(i) and
22282214
// Exclude traits that are known to not narrow things down very much.
@@ -2243,10 +2229,10 @@ private module BlanketImplementation {
22432229
* `arity`.
22442230
*/
22452231
private predicate blanketImplementationMethod(
2246-
ImplItemNode impl, Trait trait, string name, int arity, Function f
2232+
ImplItemNode impl, Trait traitBound, string name, int arity, Function f
22472233
) {
2248-
isCanonicalBlanketImplementation(impl) and
2249-
blanketImplementationTraitBound(impl, trait) and
2234+
isCanonicalImpl(impl) and
2235+
blanketImplementationTraitBound(impl, traitBound) and
22502236
f.getParamList().hasSelfParam() and
22512237
arity = f.getParamList().getNumberOfParams() and
22522238
(
@@ -2258,48 +2244,48 @@ private module BlanketImplementation {
22582244
f = impl.resolveTraitTy().getAssocItem(name)
22592245
) and
22602246
// If the method is already available through one of the trait bounds on the
2261-
// type parameter (because they share a common ancestor trait) then ignore
2247+
// type parameter (because they share a common super trait) then ignore
22622248
// it.
22632249
not getBlanketImplementationTypeParam(impl).resolveABound().(TraitItemNode).getASuccessor(name) =
22642250
f
22652251
}
22662252

2267-
predicate methodCallMatchesBlanketImpl(MethodCall mc, Type t, Impl impl, Trait trait, Function f) {
2253+
pragma[nomagic]
2254+
predicate methodCallMatchesBlanketImpl(
2255+
MethodCall mc, Type t, ImplItemNode impl, Trait traitBound, Trait traitImpl, Function f
2256+
) {
22682257
// Only check method calls where we have ruled out inherent method targets.
22692258
// Ideally we would also check if non-blanket method targets have been ruled
22702259
// out.
22712260
methodCallHasNoInherentTarget(mc) and
22722261
exists(string name, int arity |
22732262
isMethodCall(mc, t, name, arity) and
2274-
blanketImplementationMethod(impl, trait, name, arity, f)
2275-
)
2263+
blanketImplementationMethod(impl, traitBound, name, arity, f)
2264+
) and
2265+
traitImpl = impl.resolveTraitTy()
22762266
}
22772267

22782268
private predicate relevantTraitVisible(Element mc, Trait trait) {
2279-
exists(ImplItemNode impl |
2280-
methodCallMatchesBlanketImpl(mc, _, impl, _, _) and
2281-
trait = impl.resolveTraitTy()
2282-
)
2269+
methodCallMatchesBlanketImpl(mc, _, _, _, trait, _)
22832270
}
22842271

22852272
module SatisfiesConstraintInput implements SatisfiesConstraintInputSig<MethodCall> {
22862273
pragma[nomagic]
22872274
predicate relevantConstraint(MethodCall mc, Type constraint) {
2288-
exists(Trait trait, Trait trait2, ImplItemNode impl |
2289-
methodCallMatchesBlanketImpl(mc, _, impl, trait, _) and
2290-
TraitIsVisible<relevantTraitVisible/2>::traitIsVisible(mc, pragma[only_bind_into](trait2)) and
2291-
trait2 = pragma[only_bind_into](impl.resolveTraitTy()) and
2292-
trait = constraint.(TraitType).getTrait()
2275+
exists(Trait traitBound, Trait traitImpl, ImplItemNode impl |
2276+
methodCallMatchesBlanketImpl(mc, _, impl, traitBound, traitImpl, _) and
2277+
TraitIsVisible<relevantTraitVisible/2>::traitIsVisible(mc, traitImpl) and
2278+
traitBound = constraint.(TraitType).getTrait()
22932279
)
22942280
}
22952281

22962282
predicate useUniversalConditions() { none() }
22972283
}
22982284

2299-
predicate hasBlanketImpl(MethodCall mc, Type t, Impl impl, Trait trait, Function f) {
2285+
predicate hasBlanketImpl(MethodCall mc, Type t, Impl impl, Trait traitBound, Function f) {
23002286
SatisfiesConstraint<MethodCall, SatisfiesConstraintInput>::satisfiesConstraintType(mc,
2301-
TTrait(trait), _, _) and
2302-
methodCallMatchesBlanketImpl(mc, t, impl, trait, f)
2287+
TTrait(traitBound), _, _) and
2288+
methodCallMatchesBlanketImpl(mc, t, impl, traitBound, _, f)
23032289
}
23042290

23052291
pragma[nomagic]

rust/ql/test/library-tests/type-inference/blanket_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ mod extension_trait_blanket_impl {
112112
let result = my_try_flag.try_read_flag_twice(); // $ target=TryFlagExt::try_read_flag_twice
113113

114114
let my_flag = MyFlag { flag: true };
115-
// Here `TryFlagExt::try_read_flag_twice` is since there is a blanket
116-
// implementaton of `TryFlag` for `Flag`.
115+
// Here `TryFlagExt::try_read_flag_twice` is a target since there is a
116+
// blanket implementaton of `TryFlag` for `Flag`.
117117
let result = my_flag.try_read_flag_twice(); // $ MISSING: target=TryFlagExt::try_read_flag_twice
118118

119119
let my_other_flag = MyOtherFlag { flag: true };

0 commit comments

Comments
 (0)