Skip to content

Commit 50e34d7

Browse files
committed
WIP
1 parent 6fa9048 commit 50e34d7

File tree

4 files changed

+4868
-4155
lines changed

4 files changed

+4868
-4155
lines changed

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

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,13 @@ private module Input2 implements InputSig2 {
205205
constraint = object.getTrait()
206206
)
207207
}
208+
209+
private predicate testConditionSatisfiesConstraint(
210+
TypeAbstraction abs, TypeMention condition, TypeMention constraint
211+
) {
212+
conditionSatisfiesConstraint(abs, condition, constraint) and
213+
constraint.resolveType().(TraitType).getTrait().getName().getText() = "TryFuture"
214+
}
208215
}
209216

210217
private module M2 = Make2<Input2>;
@@ -1725,6 +1732,31 @@ private module BlanketImplementation {
17251732
not exists(impl.getAttributeMacroExpansion())
17261733
}
17271734

1735+
predicate isBlanketImplementation(Impl impl) { exists(getBlanketImplementationTypeParam(impl)) }
1736+
1737+
predicate duplicatedImpl(Impl impl1, Impl impl2) {
1738+
isBlanketImplementation(impl1) and
1739+
isBlanketImplementation(impl2) and
1740+
impl1 != impl2 and
1741+
getBlanketImplementationTypeParam(impl1).toString() =
1742+
getBlanketImplementationTypeParam(impl2).toString() and
1743+
impl1.getTrait().toString() = impl2.getTrait().toString() and
1744+
impl1.getLocation().getFile() != impl2.getLocation().getFile() and
1745+
impl1.getLocation().getFile().getBaseName() = impl2.getLocation().getFile().getBaseName()
1746+
}
1747+
1748+
Impl getCanonicalImpl(Impl impl) {
1749+
isBlanketImplementation(impl) and
1750+
result =
1751+
max(Impl impl0 |
1752+
duplicatedImpl(impl, impl0) or impl = impl0
1753+
|
1754+
impl0 order by impl0.getLocation().getFile().getAbsolutePath()
1755+
)
1756+
}
1757+
1758+
predicate isCanonicalBlanketImplementation(Impl impl) { impl = getCanonicalImpl(impl) }
1759+
17281760
/**
17291761
* Holds if `impl` is a blanket implementation for a type parameter and the type
17301762
* parameter must implement `trait`.
@@ -1760,6 +1792,7 @@ private module BlanketImplementation {
17601792
private predicate blanketImplementationMethod(
17611793
Impl impl, Trait trait, string name, int arity, Function f
17621794
) {
1795+
isCanonicalBlanketImplementation(impl) and
17631796
f = impl.(ImplItemNode).getASuccessor(name) and
17641797
blanketImplementationTraitBound(impl, trait) and
17651798
f.getParamList().hasSelfParam() and
@@ -1780,11 +1813,15 @@ private module BlanketImplementation {
17801813
predicate relevantConstraint(MethodCall mc, Type constraint) {
17811814
methodCallMatchesBlanketImpl(mc, _, _, constraint.(TraitType).getTrait(), _)
17821815
}
1816+
1817+
predicate useUniversalConditions() { none() }
17831818
}
17841819

17851820
predicate debugSatisfiesConstraintType(MethodCall mc, Trait trait, TypePath path, Type ty) {
17861821
SatisfiesConstraint<MethodCall, SatisfiesConstraintInput>::satisfiesConstraintType(mc,
1787-
TTrait(trait), path, ty)
1822+
TTrait(trait), path, ty) and
1823+
// 521 results
1824+
trait.getName().getText() = "TryFuture"
17881825
}
17891826

17901827
predicate getBlanketImpl(MethodCall mc, Type t, Impl impl, Trait trait, Function f) {
@@ -1834,8 +1871,8 @@ private Function resolveMethodCallTarget(MethodCall mc) {
18341871
// The method comes from an `impl` block targeting the type of the receiver.
18351872
result = getMethodFromImpl(mc)
18361873
or
1837-
result = BlanketImplementation::getMethodFromBlanketImpl(mc)
1838-
or
1874+
// result = BlanketImplementation::getMethodFromBlanketImpl(mc)
1875+
// or
18391876
// The type of the receiver is a type parameter and the method comes from a
18401877
// trait bound on the type parameter.
18411878
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,59 @@ mod higher_ranked_blanket_impl {
401401
}
402402
}
403403

404+
mod TST {
405+
// 1. Elements a trait that is implemented for a type parameter
406+
// 2. An extension trait
407+
// 3. A blanket implementation of the extension trait for a type parameter
408+
409+
trait Flag {
410+
fn read_flag(&self) -> bool;
411+
}
412+
413+
trait TryFlag {
414+
fn try_read_flag(&self) -> Option<bool>;
415+
}
416+
417+
impl<Fl> TryFlag for Fl
418+
where
419+
Fl: Flag,
420+
{
421+
fn try_read_flag(&self) -> Option<bool> {
422+
Some(self.read_flag())
423+
}
424+
}
425+
426+
trait TryFlagExt: TryFlag {
427+
// TryFlagExt::try_read_flag_twice
428+
fn try_read_flag_twice(&self) -> Option<bool> {
429+
self.try_read_flag()
430+
}
431+
}
432+
433+
impl<T: TryFlag> TryFlagExt for T {}
434+
435+
trait AnotherTryFlag {
436+
// AnotherTryFlag::try_read_flag_twice
437+
fn try_read_flag_twice(&self) -> Option<bool>;
438+
}
439+
440+
struct MyFlag {
441+
flag: bool,
442+
}
443+
444+
impl AnotherTryFlag for MyFlag {
445+
// MyFlag::try_read_flag_twice
446+
fn try_read_flag_twice(&self) -> Option<bool> {
447+
Some(self.flag)
448+
}
449+
}
450+
451+
fn test() {
452+
let my_flag = MyFlag { flag: true };
453+
let result = my_flag.try_read_flag_twice(); // $ target=MyFlag::try_read_flag_twice
454+
}
455+
}
456+
404457
pub fn test() {
405458
basic_blanket_impl::test_basic_blanket(); // $ target=test_basic_blanket
406459
nested_blanket_impl::test_nested_blanket(); // $ target=test_nested_blanket

0 commit comments

Comments
 (0)