From 16613d173ff92ad99e621c1acd127de7f996d060 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 12 Mar 2026 10:39:22 +0100 Subject: [PATCH 1/4] Rust: Add type inference test --- .../type-inference/overloading.rs | 72 +++++++++ .../type-inference/type-inference.expected | 146 ++++++++++++++++++ 2 files changed, 218 insertions(+) diff --git a/rust/ql/test/library-tests/type-inference/overloading.rs b/rust/ql/test/library-tests/type-inference/overloading.rs index 94b5a8b69e41..e0f3dbf69540 100644 --- a/rust/ql/test/library-tests/type-inference/overloading.rs +++ b/rust/ql/test/library-tests/type-inference/overloading.rs @@ -449,3 +449,75 @@ mod inherent_before_trait { } } } + +mod trait_bound_impl_overlap { + trait MyTrait { + fn f(&self) -> T; + } + + trait MyTrait2 { + type Output; + + fn f(&self, x: T) -> Self::Output; + } + + struct S(T); + + impl MyTrait for S { + fn f(&self) -> i32 { + 0 + } + } + + impl MyTrait for S { + fn f(&self) -> i64 { + 0 + } + } + + impl MyTrait2> for S { + type Output = i32; + + fn f(&self, x: S) -> Self::Output { + 0 + } + } + + impl MyTrait2> for S { + type Output = >>::Output; + + fn f(&self, x: S) -> Self::Output { + 0 + } + } + + impl MyTrait2> for S { + type Output = i64; + + fn f(&self, x: S) -> Self::Output { + 0 + } + } + + fn call_f>(x: T2) -> T1 { + x.f() // $ target=f + } + + fn call_f2>(x: T1, y: T2) -> T2::Output { + y.f(x) // $ target=f + } + + fn test() { + let x = S(0); + let y = call_f(x); // $ target=call_f type=y:i32 $ SPURIOUS: type=y:i64 + let z: i32 = y; + + let x = S(0); + let y = call_f::(x); // $ target=call_f type=y:i32 + + let x = S(0); + let y = call_f2(S(0i32), x); // $ target=call_f2 type=y:i32 $ SPURIOUS: type=y:i64 + let x = S(0); + let y = call_f2(S(0i64), x); // $ target=call_f2 type=y:i64 $ SPURIOUS: type=y:i32 + } +} diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index feba4891a664..b71bcf643924 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -4079,6 +4079,51 @@ inferCertainType | overloading.rs:448:13:448:16 | self | | {EXTERNAL LOCATION} | & | | overloading.rs:448:13:448:16 | self | TRef | overloading.rs:405:5:405:19 | S | | overloading.rs:448:13:448:16 | self | TRef.T | {EXTERNAL LOCATION} | i64 | +| overloading.rs:455:14:455:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:455:14:455:18 | SelfParam | TRef | overloading.rs:454:5:456:5 | Self [trait MyTrait] | +| overloading.rs:461:14:461:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:461:14:461:18 | SelfParam | TRef | overloading.rs:458:5:462:5 | Self [trait MyTrait2] | +| overloading.rs:461:21:461:21 | x | | overloading.rs:458:20:458:27 | T | +| overloading.rs:467:14:467:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:467:14:467:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:467:14:467:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:467:28:469:9 | { ... } | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:473:14:473:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:473:14:473:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:473:14:473:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:473:28:475:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:481:14:481:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:481:14:481:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:481:14:481:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:481:21:481:21 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:481:21:481:21 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:481:48:483:9 | { ... } | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:489:14:489:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:489:14:489:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:489:14:489:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:489:21:489:21 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:489:21:489:21 | x | T | {EXTERNAL LOCATION} | i64 | +| overloading.rs:489:48:491:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:497:14:497:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:497:14:497:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:497:14:497:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:497:21:497:21 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:497:21:497:21 | x | T | {EXTERNAL LOCATION} | bool | +| overloading.rs:497:49:499:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:502:36:502:36 | x | | overloading.rs:502:19:502:33 | T2 | +| overloading.rs:502:49:504:5 | { ... } | | overloading.rs:502:15:502:16 | T1 | +| overloading.rs:503:9:503:9 | x | | overloading.rs:502:19:502:33 | T2 | +| overloading.rs:506:38:506:38 | x | | overloading.rs:506:16:506:17 | T1 | +| overloading.rs:506:45:506:45 | y | | overloading.rs:506:20:506:35 | T2 | +| overloading.rs:506:66:508:5 | { ... } | | overloading.rs:506:20:506:35 | T2::Output[MyTrait2] | +| overloading.rs:507:9:507:9 | y | | overloading.rs:506:20:506:35 | T2 | +| overloading.rs:507:13:507:13 | x | | overloading.rs:506:16:506:17 | T1 | +| overloading.rs:510:15:522:5 | { ... } | | {EXTERNAL LOCATION} | () | +| overloading.rs:513:13:513:13 | z | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:516:13:516:13 | y | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:516:17:516:35 | call_f::<...>(...) | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:519:27:519:30 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:521:27:521:30 | 0i64 | | {EXTERNAL LOCATION} | i64 | | pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option | | pattern_matching.rs:13:26:133:1 | { ... } | T | {EXTERNAL LOCATION} | () | | pattern_matching.rs:15:5:18:5 | if ... {...} | | {EXTERNAL LOCATION} | () | @@ -12830,6 +12875,107 @@ inferType | overloading.rs:448:13:448:16 | self | TRef | overloading.rs:405:5:405:19 | S | | overloading.rs:448:13:448:16 | self | TRef.T | {EXTERNAL LOCATION} | i64 | | overloading.rs:448:13:448:22 | self.bar() | | {EXTERNAL LOCATION} | () | +| overloading.rs:455:14:455:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:455:14:455:18 | SelfParam | TRef | overloading.rs:454:5:456:5 | Self [trait MyTrait] | +| overloading.rs:461:14:461:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:461:14:461:18 | SelfParam | TRef | overloading.rs:458:5:462:5 | Self [trait MyTrait2] | +| overloading.rs:461:21:461:21 | x | | overloading.rs:458:20:458:27 | T | +| overloading.rs:467:14:467:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:467:14:467:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:467:14:467:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:467:28:469:9 | { ... } | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:468:13:468:13 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:473:14:473:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:473:14:473:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:473:14:473:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:473:28:475:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:474:13:474:13 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:474:13:474:13 | 0 | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:481:14:481:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:481:14:481:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:481:14:481:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:481:21:481:21 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:481:21:481:21 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:481:48:483:9 | { ... } | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:482:13:482:13 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:489:14:489:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:489:14:489:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:489:14:489:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:489:21:489:21 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:489:21:489:21 | x | T | {EXTERNAL LOCATION} | i64 | +| overloading.rs:489:48:491:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:490:13:490:13 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:490:13:490:13 | 0 | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:497:14:497:18 | SelfParam | | {EXTERNAL LOCATION} | & | +| overloading.rs:497:14:497:18 | SelfParam | TRef | overloading.rs:464:5:464:19 | S | +| overloading.rs:497:14:497:18 | SelfParam | TRef.T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:497:21:497:21 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:497:21:497:21 | x | T | {EXTERNAL LOCATION} | bool | +| overloading.rs:497:49:499:9 | { ... } | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:498:13:498:13 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:498:13:498:13 | 0 | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:502:36:502:36 | x | | overloading.rs:502:19:502:33 | T2 | +| overloading.rs:502:49:504:5 | { ... } | | overloading.rs:502:15:502:16 | T1 | +| overloading.rs:503:9:503:9 | x | | overloading.rs:502:19:502:33 | T2 | +| overloading.rs:503:9:503:13 | x.f() | | overloading.rs:502:15:502:16 | T1 | +| overloading.rs:506:38:506:38 | x | | overloading.rs:506:16:506:17 | T1 | +| overloading.rs:506:45:506:45 | y | | overloading.rs:506:20:506:35 | T2 | +| overloading.rs:506:66:508:5 | { ... } | | overloading.rs:506:20:506:35 | T2::Output[MyTrait2] | +| overloading.rs:507:9:507:9 | y | | overloading.rs:506:20:506:35 | T2 | +| overloading.rs:507:9:507:14 | y.f(...) | | overloading.rs:506:20:506:35 | T2::Output[MyTrait2] | +| overloading.rs:507:13:507:13 | x | | overloading.rs:506:16:506:17 | T1 | +| overloading.rs:510:15:522:5 | { ... } | | {EXTERNAL LOCATION} | () | +| overloading.rs:511:13:511:13 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:511:13:511:13 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:511:17:511:20 | S(...) | | overloading.rs:464:5:464:19 | S | +| overloading.rs:511:17:511:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:511:19:511:19 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:512:13:512:13 | y | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:512:13:512:13 | y | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:512:17:512:25 | call_f(...) | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:512:17:512:25 | call_f(...) | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:512:24:512:24 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:512:24:512:24 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:513:13:513:13 | z | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:513:22:513:22 | y | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:513:22:513:22 | y | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:515:13:515:13 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:515:13:515:13 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:515:17:515:20 | S(...) | | overloading.rs:464:5:464:19 | S | +| overloading.rs:515:17:515:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:515:19:515:19 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:516:13:516:13 | y | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:516:17:516:35 | call_f::<...>(...) | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:516:34:516:34 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:516:34:516:34 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:518:13:518:13 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:518:13:518:13 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:518:17:518:20 | S(...) | | overloading.rs:464:5:464:19 | S | +| overloading.rs:518:17:518:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:518:19:518:19 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:519:13:519:13 | y | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:519:13:519:13 | y | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:519:17:519:35 | call_f2(...) | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:519:17:519:35 | call_f2(...) | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:519:25:519:31 | S(...) | | overloading.rs:464:5:464:19 | S | +| overloading.rs:519:25:519:31 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:519:27:519:30 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:519:34:519:34 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:519:34:519:34 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:520:13:520:13 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:520:13:520:13 | x | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:520:17:520:20 | S(...) | | overloading.rs:464:5:464:19 | S | +| overloading.rs:520:17:520:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| overloading.rs:520:19:520:19 | 0 | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:521:13:521:13 | y | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:521:13:521:13 | y | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:521:17:521:35 | call_f2(...) | | {EXTERNAL LOCATION} | i32 | +| overloading.rs:521:17:521:35 | call_f2(...) | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:521:25:521:31 | S(...) | | overloading.rs:464:5:464:19 | S | +| overloading.rs:521:25:521:31 | S(...) | T | {EXTERNAL LOCATION} | i64 | +| overloading.rs:521:27:521:30 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| overloading.rs:521:34:521:34 | x | | overloading.rs:464:5:464:19 | S | +| overloading.rs:521:34:521:34 | x | T | {EXTERNAL LOCATION} | i32 | | pattern_matching.rs:13:26:133:1 | { ... } | | {EXTERNAL LOCATION} | Option | | pattern_matching.rs:13:26:133:1 | { ... } | T | {EXTERNAL LOCATION} | () | | pattern_matching.rs:14:9:14:13 | value | | {EXTERNAL LOCATION} | Option | From 7a5a89a4443b691cec504d43b1870c7b3cfded20 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 12 Mar 2026 11:50:46 +0100 Subject: [PATCH 2/4] Rust: Only infer types from trait bounds when their implementation is unambiguous --- .../typeinference/BlanketImplementation.qll | 4 +- .../typeinference/FunctionOverloading.qll | 145 ++++++---- .../rust/internal/typeinference/Type.qll | 12 +- .../internal/typeinference/TypeInference.qll | 59 ++-- .../internal/typeinference/TypeMention.qll | 79 ++--- .../type-inference/overloading.rs | 6 +- .../type-inference/type-inference.expected | 29 +- .../typeinference/internal/TypeInference.qll | 273 ++++++++++++------ shared/util/codeql/util/UnboundList.qll | 8 + 9 files changed, 388 insertions(+), 227 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll index db1402280d4d..97dbf2d8f3a9 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll @@ -103,7 +103,7 @@ module SatisfiesBlanketConstraint< } private module SatisfiesBlanketConstraintInput implements - SatisfiesConstraintInputSig + SatisfiesTypeInputSig { pragma[nomagic] additional predicate relevantConstraint( @@ -123,7 +123,7 @@ module SatisfiesBlanketConstraint< } private module SatisfiesBlanketConstraint = - SatisfiesConstraint; + SatisfiesType; /** * Holds if the argument type `at` satisfies the first non-trivial blanket diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll index 6e4cc6e2c2e8..9722b9333ae9 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll @@ -13,68 +13,105 @@ private import TypeMention private import TypeInference private import FunctionType -pragma[nomagic] -private Type resolveNonTypeParameterTypeAt(TypeMention tm, TypePath path) { - result = tm.getTypeAt(path) and - not result instanceof TypeParameter -} +private signature Type resolveTypeMentionAtSig(AstNode tm, TypePath path); -bindingset[t1, t2] -private predicate typeMentionEqual(TypeMention t1, TypeMention t2) { - forex(TypePath path, Type type | resolveNonTypeParameterTypeAt(t1, path) = type | - resolveNonTypeParameterTypeAt(t2, path) = type - ) -} +/** + * Provides logic for identifying sibling implementations, parameterized over + * how to resolve type mentions (`PreTypeMention` vs. `TypeMention`). + */ +private module MkSiblingImpls { + pragma[nomagic] + private Type resolveNonTypeParameterTypeAt(AstNode tm, TypePath path) { + result = resolveTypeMentionAt(tm, path) and + not result instanceof TypeParameter + } -pragma[nomagic] -private predicate implSiblingCandidate( - Impl impl, TraitItemNode trait, Type rootType, TypeMention selfTy -) { - trait = impl.(ImplItemNode).resolveTraitTy() and - selfTy = impl.getSelfTy() and - rootType = selfTy.getType() + bindingset[t1, t2] + private predicate typeMentionEqual(AstNode t1, AstNode t2) { + forex(TypePath path, Type type | resolveNonTypeParameterTypeAt(t1, path) = type | + resolveNonTypeParameterTypeAt(t2, path) = type + ) + } + + pragma[nomagic] + private predicate implSiblingCandidate( + Impl impl, TraitItemNode trait, Type rootType, AstNode selfTy + ) { + trait = impl.(ImplItemNode).resolveTraitTy() and + selfTy = impl.getSelfTy() and + rootType = resolveTypeMentionAt(selfTy, TypePath::nil()) + } + + pragma[nomagic] + private predicate blanketImplSiblingCandidate(ImplItemNode impl, Trait trait) { + impl.isBlanketImplementation() and + trait = impl.resolveTraitTy() + } + + /** + * Holds if `impl1` and `impl2` are a sibling implementations of `trait`. We + * consider implementations to be siblings if they implement the same trait for + * the same type. In that case `Self` is the same type in both implementations, + * and method calls to the implementations cannot be resolved unambiguously + * based only on the receiver type. + */ + pragma[inline] + predicate implSiblings(TraitItemNode trait, Impl impl1, Impl impl2) { + impl1 != impl2 and + ( + exists(Type rootType, AstNode selfTy1, AstNode selfTy2 | + implSiblingCandidate(impl1, trait, rootType, selfTy1) and + implSiblingCandidate(impl2, trait, rootType, selfTy2) and + // In principle the second conjunct below should be superflous, but we still + // have ill-formed type mentions for types that we don't understand. For + // those checking both directions restricts further. Note also that we check + // syntactic equality, whereas equality up to renaming would be more + // correct. + typeMentionEqual(selfTy1, selfTy2) and + typeMentionEqual(selfTy2, selfTy1) + ) + or + blanketImplSiblingCandidate(impl1, trait) and + blanketImplSiblingCandidate(impl2, trait) + ) + } + + /** + * Holds if `impl` is an implementation of `trait` and if another implementation + * exists for the same type. + */ + pragma[nomagic] + predicate implHasSibling(ImplItemNode impl, Trait trait) { implSiblings(trait, impl, _) } + + pragma[nomagic] + predicate implHasAmbigousSiblingAt(ImplItemNode impl, Trait trait, TypePath path) { + exists(ImplItemNode impl2, Type t1, Type t2 | + implSiblings(trait, impl, impl2) and + t1 = resolveTypeMentionAt(impl.getTraitPath(), path) and + t2 = resolveTypeMentionAt(impl2.getTraitPath(), path) and + t1 != t2 + | + not t1 instanceof TypeParameter or + not t2 instanceof TypeParameter + ) + } } -pragma[nomagic] -private predicate blanketImplSiblingCandidate(ImplItemNode impl, Trait trait) { - impl.isBlanketImplementation() and - trait = impl.resolveTraitTy() +private Type resolvePreTypeMention(AstNode tm, TypePath path) { + result = tm.(PreTypeMention).getTypeAt(path) } -/** - * Holds if `impl1` and `impl2` are a sibling implementations of `trait`. We - * consider implementations to be siblings if they implement the same trait for - * the same type. In that case `Self` is the same type in both implementations, - * and method calls to the implementations cannot be resolved unambiguously - * based only on the receiver type. - */ -pragma[inline] -private predicate implSiblings(TraitItemNode trait, Impl impl1, Impl impl2) { - impl1 != impl2 and - ( - exists(Type rootType, TypeMention selfTy1, TypeMention selfTy2 | - implSiblingCandidate(impl1, trait, rootType, selfTy1) and - implSiblingCandidate(impl2, trait, rootType, selfTy2) and - // In principle the second conjunct below should be superflous, but we still - // have ill-formed type mentions for types that we don't understand. For - // those checking both directions restricts further. Note also that we check - // syntactic equality, whereas equality up to renaming would be more - // correct. - typeMentionEqual(selfTy1, selfTy2) and - typeMentionEqual(selfTy2, selfTy1) - ) - or - blanketImplSiblingCandidate(impl1, trait) and - blanketImplSiblingCandidate(impl2, trait) - ) +private module PreSiblingImpls = MkSiblingImpls; + +predicate preImplHasAmbigousSiblingAt = PreSiblingImpls::implHasAmbigousSiblingAt/3; + +private Type resolveTypeMention(AstNode tm, TypePath path) { + result = tm.(TypeMention).getTypeAt(path) } -/** - * Holds if `impl` is an implementation of `trait` and if another implementation - * exists for the same type. - */ -pragma[nomagic] -private predicate implHasSibling(ImplItemNode impl, Trait trait) { implSiblings(trait, impl, _) } +private module SiblingImpls = MkSiblingImpls; + +import SiblingImpls /** * Holds if `f` is a function declared inside `trait`, and the type of `f` at diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll b/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll index 05b6557522af..9ae79f2d58c9 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/Type.qll @@ -439,11 +439,11 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter { */ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypeParameter { private Trait trait; - private TypeAlias typeAlias; + private AssocType typeAlias; AssociatedTypeTypeParameter() { this = TAssociatedTypeTypeParameter(trait, typeAlias) } - TypeAlias getTypeAlias() { result = typeAlias } + AssocType getTypeAlias() { result = typeAlias } /** Gets the trait that contains this associated type declaration. */ TraitItemNode getTrait() { result = trait } @@ -457,7 +457,13 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara override ItemNode getDeclaringItem() { result = trait } override string toString() { - result = typeAlias.getName().getText() + "[" + trait.getName().toString() + "]" + exists(string fromString, TraitItemNode trait2 | + result = typeAlias.getName().getText() + "[" + trait.getName() + fromString + "]" and + trait2 = typeAlias.getTrait() and + if trait = trait2 + then fromString = "" + else fromString = " (inherited from " + trait2.getName() + ")" + ) } override Location getLocation() { result = typeAlias.getLocation() } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index c194531a0781..798ee76c7be9 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -41,6 +41,12 @@ private module Input implements InputSig1, InputSig2 { class TypeAbstraction = TA::TypeAbstraction; + predicate typeAbstractionHasAmbigousConstraintAt( + TypeAbstraction abs, Type constraint, TypePath path + ) { + FunctionOverloading::implHasAmbigousSiblingAt(abs, constraint.(TraitType).getTrait(), path) + } + class TypeArgumentPosition extends TTypeArgumentPosition { int asMethodTypeArgumentPosition() { this = TMethodTypeArgumentPosition(result) } @@ -127,17 +133,15 @@ private module Input implements InputSig1, InputSig2 { PreTypeMention getABaseTypeMention(Type t) { none() } - Type getATypeParameterConstraint(TypeParameter tp, TypePath path) { - exists(TypeMention tm | result = tm.getTypeAt(path) | - tm = tp.(TypeParamTypeParameter).getTypeParam().getATypeBound().getTypeRepr() or - tm = tp.(SelfTypeParameter).getTrait() or - tm = - tp.(ImplTraitTypeTypeParameter) - .getImplTraitTypeRepr() - .getTypeBoundList() - .getABound() - .getTypeRepr() - ) + PreTypeMention getATypeParameterConstraint(TypeParameter tp) { + result = tp.(TypeParamTypeParameter).getTypeParam().getATypeBound().getTypeRepr() or + result = tp.(SelfTypeParameter).getTrait() or + result = + tp.(ImplTraitTypeTypeParameter) + .getImplTraitTypeRepr() + .getTypeBoundList() + .getABound() + .getTypeRepr() } /** @@ -1170,7 +1174,7 @@ private module ContextTyping { or exists(TypeParameter mid | assocFunctionMentionsTypeParameterAtNonRetPos(i, f, mid) and - tp = getATypeParameterConstraint(mid, _) + tp = getATypeParameterConstraint(mid).getTypeAt(_) ) } @@ -2544,8 +2548,7 @@ private module AssocFunctionResolution { Location getLocation() { result = afc.getLocation() } } - private module CallSatisfiesDerefConstraintInput implements - SatisfiesConstraintInputSig + private module CallSatisfiesDerefConstraintInput implements SatisfiesTypeInputSig { pragma[nomagic] predicate relevantConstraint(CallDerefCand mc, Type constraint) { @@ -2555,7 +2558,7 @@ private module AssocFunctionResolution { } private module CallSatisfiesDerefConstraint = - SatisfiesConstraint; + SatisfiesType; pragma[nomagic] private AssociatedTypeTypeParameter getDerefTargetTypeParameter() { @@ -3586,7 +3589,7 @@ final private class AwaitTarget extends Expr { Type getTypeAt(TypePath path) { result = inferType(this, path) } } -private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInputSig { +private module AwaitSatisfiesTypeInput implements SatisfiesTypeInputSig { pragma[nomagic] predicate relevantConstraint(AwaitTarget term, Type constraint) { exists(term) and @@ -3594,13 +3597,12 @@ private module AwaitSatisfiesConstraintInput implements SatisfiesConstraintInput } } -private module AwaitSatisfiesConstraint = - SatisfiesConstraint; +private module AwaitSatisfiesType = SatisfiesType; pragma[nomagic] private Type inferAwaitExprType(AstNode n, TypePath path) { exists(TypePath exprPath | - AwaitSatisfiesConstraint::satisfiesConstraintType(n.(AwaitExpr).getExpr(), _, exprPath, result) and + AwaitSatisfiesType::satisfiesConstraintType(n.(AwaitExpr).getExpr(), _, exprPath, result) and exprPath.isCons(getFutureOutputTypeParameter(), path) ) } @@ -3779,9 +3781,7 @@ final private class ForIterableExpr extends Expr { Type getTypeAt(TypePath path) { result = inferType(this, path) } } -private module ForIterableSatisfiesConstraintInput implements - SatisfiesConstraintInputSig -{ +private module ForIterableSatisfiesTypeInput implements SatisfiesTypeInputSig { predicate relevantConstraint(ForIterableExpr term, Type constraint) { exists(term) and exists(Trait t | t = constraint.(TraitType).getTrait() | @@ -3802,15 +3802,15 @@ private AssociatedTypeTypeParameter getIntoIteratorItemTypeParameter() { result = getAssociatedTypeTypeParameter(any(IntoIteratorTrait t).getItemType()) } -private module ForIterableSatisfiesConstraint = - SatisfiesConstraint; +private module ForIterableSatisfiesType = + SatisfiesType; pragma[nomagic] private Type inferForLoopExprType(AstNode n, TypePath path) { // type of iterable -> type of pattern (loop variable) exists(ForExpr fe, TypePath exprPath, AssociatedTypeTypeParameter tp | n = fe.getPat() and - ForIterableSatisfiesConstraint::satisfiesConstraintType(fe.getIterable(), _, exprPath, result) and + ForIterableSatisfiesType::satisfiesConstraintType(fe.getIterable(), _, exprPath, result) and exprPath.isCons(tp, path) | tp = getIntoIteratorItemTypeParameter() @@ -3836,8 +3836,7 @@ final private class InvokedClosureExpr extends Expr { CallExpr getCall() { result = call } } -private module InvokedClosureSatisfiesConstraintInput implements - SatisfiesConstraintInputSig +private module InvokedClosureSatisfiesTypeInput implements SatisfiesTypeInputSig { predicate relevantConstraint(InvokedClosureExpr term, Type constraint) { exists(term) and @@ -3845,12 +3844,12 @@ private module InvokedClosureSatisfiesConstraintInput implements } } -private module InvokedClosureSatisfiesConstraint = - SatisfiesConstraint; +private module InvokedClosureSatisfiesType = + SatisfiesType; /** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */ private Type invokedClosureFnTypeAt(InvokedClosureExpr ce, TypePath path) { - InvokedClosureSatisfiesConstraint::satisfiesConstraintType(ce, _, path, result) + InvokedClosureSatisfiesType::satisfiesConstraintType(ce, _, path, result) } /** diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll index dcb3fc0b0f49..7de2ba0d3414 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll @@ -7,6 +7,7 @@ private import Type private import TypeAbstraction private import TypeInference private import AssociatedType +private import FunctionOverloading bindingset[trait, name] pragma[inline_late] @@ -205,6 +206,13 @@ private module MkTypeMention::...` + exists(PathTypeRepr typeRepr, PathTypeRepr traitRepr | + pathTypeAsTraitAssoc(_, typeRepr, traitRepr, _, _) and + this = traitRepr.getPath() and + result = typeRepr.getPath() + ) } pragma[nomagic] @@ -696,16 +704,26 @@ private module PreTypeMention = MkTypeMention; class PreTypeMention = PreTypeMention::TypeMention; +private class TraitOrTmTrait extends AstNode { + Type getTypeAt(TypePath path) { + pathTypeAsTraitAssoc(_, _, this, _, _) and + result = this.(PreTypeMention).getTypeAt(path) + or + result = TTrait(this) and + path.isEmpty() + } +} + /** * Holds if `path` accesses an associated type `alias` from `trait` on a * concrete type given by `tm`. * - * `implOrTmTrait` is either the mention that resolves to `trait` when `path` - * is of the form `::AssocType`, or the enclosing `impl` block - * when `path` is of the form `Self::AssocType`. + * `traitOrTmTrait` is either the mention that resolves to `trait` when `path` + * is of the form `::AssocType`, or the trait being implemented + * when `path` is of the form `Self::AssocType` within an `impl` block. */ private predicate pathConcreteTypeAssocType( - Path path, PreTypeMention tm, TraitItemNode trait, AstNode implOrTmTrait, TypeAlias alias + Path path, PreTypeMention tm, TraitItemNode trait, TraitOrTmTrait traitOrTmTrait, TypeAlias alias ) { exists(Path qualifier | qualifier = path.getQualifier() and @@ -713,31 +731,40 @@ private predicate pathConcreteTypeAssocType( | // path of the form `::AssocType` // ^^^ tm ^^^^^^^^^ name + // ^^^^^ traitOrTmTrait exists(string name | - pathTypeAsTraitAssoc(path, tm, implOrTmTrait, trait, name) and + pathTypeAsTraitAssoc(path, tm, traitOrTmTrait, trait, name) and getTraitAssocType(trait, name) = alias ) or // path of the form `Self::AssocType` within an `impl` block // tm ^^^^ ^^^^^^^^^ name - implOrTmTrait = - any(ImplItemNode impl | - alias = resolvePath(path) and - qualifier = impl.getASelfPath() and - tm = impl.(Impl).getSelfTy() and - trait.getAnAssocItem() = alias - ) + exists(ImplItemNode impl | + alias = resolvePath(path) and + qualifier = impl.getASelfPath() and + tm = impl.(Impl).getSelfTy() and + trait.getAnAssocItem() = alias and + traitOrTmTrait = trait + ) ) } -private module PathSatisfiesConstraintInput implements SatisfiesConstraintInputSig { - predicate relevantConstraint(PreTypeMention tm, Type constraint) { - pathConcreteTypeAssocType(_, tm, constraint.(TraitType).getTrait(), _, _) +private module PathSatisfiesConstraintInput implements + SatisfiesConstraintInputSig +{ + predicate relevantConstraint(PreTypeMention tm, TraitOrTmTrait constraint) { + pathConcreteTypeAssocType(_, tm, _, constraint, _) + } + + predicate typeAbstractionHasAmbigousConstraintAtOverride( + TypeAbstraction abs, Type constraint, TypePath path + ) { + preImplHasAmbigousSiblingAt(abs, constraint.(TraitType).getTrait(), path) } } private module PathSatisfiesConstraint = - SatisfiesConstraint; + SatisfiesConstraint; /** * Gets the type of `path` at `typePath` when `path` accesses an associated type @@ -745,26 +772,12 @@ private module PathSatisfiesConstraint = */ private Type getPathConcreteAssocTypeAt(Path path, TypePath typePath) { exists( - PreTypeMention tm, ImplItemNode impl, TraitItemNode trait, TraitType t, AstNode implOrTmTrait, + PreTypeMention tm, ImplItemNode impl, TraitItemNode trait, TraitOrTmTrait traitOrTmTrait, TypeAlias alias, TypePath path0 | - pathConcreteTypeAssocType(path, tm, trait, implOrTmTrait, alias) and - t = TTrait(trait) and - PathSatisfiesConstraint::satisfiesConstraintTypeThrough(tm, impl, t, path0, result) and + pathConcreteTypeAssocType(path, tm, trait, traitOrTmTrait, alias) and + PathSatisfiesConstraint::satisfiesConstraintTypeThrough(tm, impl, traitOrTmTrait, path0, result) and path0.isCons(TAssociatedTypeTypeParameter(trait, alias), typePath) - | - implOrTmTrait instanceof Impl - or - // When `path` is of the form `::AssocType` we need to check - // that `impl` is not more specific than the mentioned trait - implOrTmTrait = - any(PreTypeMention tmTrait | - not exists(TypePath path1, Type t1 | - t1 = impl.getTraitPath().(PreTypeMention).getTypeAt(path1) and - not t1 instanceof TypeParameter and - t1 != tmTrait.getTypeAt(path1) - ) - ) ) } diff --git a/rust/ql/test/library-tests/type-inference/overloading.rs b/rust/ql/test/library-tests/type-inference/overloading.rs index e0f3dbf69540..854338fcaf4c 100644 --- a/rust/ql/test/library-tests/type-inference/overloading.rs +++ b/rust/ql/test/library-tests/type-inference/overloading.rs @@ -509,15 +509,15 @@ mod trait_bound_impl_overlap { fn test() { let x = S(0); - let y = call_f(x); // $ target=call_f type=y:i32 $ SPURIOUS: type=y:i64 + let y = call_f(x); // $ target=call_f type=y:i32 let z: i32 = y; let x = S(0); let y = call_f::(x); // $ target=call_f type=y:i32 let x = S(0); - let y = call_f2(S(0i32), x); // $ target=call_f2 type=y:i32 $ SPURIOUS: type=y:i64 + let y = call_f2(S(0i32), x); // $ target=call_f2 $ MISSING: type=y:i32 let x = S(0); - let y = call_f2(S(0i64), x); // $ target=call_f2 type=y:i64 $ SPURIOUS: type=y:i32 + let y = call_f2(S(0i64), x); // $ target=call_f2 $ MISSING: type=y:i64 } } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index b71bcf643924..3837d8d8273a 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -209,15 +209,15 @@ inferCertainType | associated_types.rs:454:24:454:28 | SelfParam | TRef | associated_types.rs:452:5:455:5 | Self [trait Subtrait] | | associated_types.rs:463:23:463:27 | SelfParam | | {EXTERNAL LOCATION} | & | | associated_types.rs:463:23:463:27 | SelfParam | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] | -| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | -| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | +| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | +| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | | associated_types.rs:463:66:466:9 | { ... } | | {EXTERNAL LOCATION} | () | | associated_types.rs:464:13:464:16 | self | | {EXTERNAL LOCATION} | & | | associated_types.rs:464:13:464:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] | -| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | +| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | | associated_types.rs:465:13:465:16 | self | | {EXTERNAL LOCATION} | & | | associated_types.rs:465:13:465:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] | -| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | +| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | | associated_types.rs:474:16:474:20 | SelfParam | | {EXTERNAL LOCATION} | & | | associated_types.rs:474:16:474:20 | SelfParam | TRef | associated_types.rs:469:5:469:24 | MyType | | associated_types.rs:474:16:474:20 | SelfParam | TRef.T | associated_types.rs:471:10:471:16 | T | @@ -5441,17 +5441,17 @@ inferType | associated_types.rs:454:24:454:28 | SelfParam | TRef | associated_types.rs:452:5:455:5 | Self [trait Subtrait] | | associated_types.rs:463:23:463:27 | SelfParam | | {EXTERNAL LOCATION} | & | | associated_types.rs:463:23:463:27 | SelfParam | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] | -| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | -| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | +| associated_types.rs:463:30:463:31 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | +| associated_types.rs:463:48:463:49 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | | associated_types.rs:463:66:466:9 | { ... } | | {EXTERNAL LOCATION} | () | | associated_types.rs:464:13:464:16 | self | | {EXTERNAL LOCATION} | & | | associated_types.rs:464:13:464:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] | | associated_types.rs:464:13:464:24 | self.set(...) | | {EXTERNAL LOCATION} | () | -| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | +| associated_types.rs:464:22:464:23 | c1 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | | associated_types.rs:465:13:465:16 | self | | {EXTERNAL LOCATION} | & | | associated_types.rs:465:13:465:16 | self | TRef | associated_types.rs:457:5:467:5 | Self [trait Subtrait2] | | associated_types.rs:465:13:465:24 | self.set(...) | | {EXTERNAL LOCATION} | () | -| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2] | +| associated_types.rs:465:22:465:23 | c2 | | associated_types.rs:20:5:20:16 | Output[Subtrait2 (inherited from GetSet)] | | associated_types.rs:474:16:474:20 | SelfParam | | {EXTERNAL LOCATION} | & | | associated_types.rs:474:16:474:20 | SelfParam | TRef | associated_types.rs:469:5:469:24 | MyType | | associated_types.rs:474:16:474:20 | SelfParam | TRef.T | associated_types.rs:471:10:471:16 | T | @@ -10775,7 +10775,6 @@ inferType | main.rs:2032:56:2034:9 | { ... } | | {EXTERNAL LOCATION} | & | | main.rs:2032:56:2034:9 | { ... } | TRef | main.rs:2028:10:2028:10 | T | | main.rs:2033:13:2033:29 | &... | | {EXTERNAL LOCATION} | & | -| main.rs:2033:13:2033:29 | &... | TRef | {EXTERNAL LOCATION} | u8 | | main.rs:2033:13:2033:29 | &... | TRef | main.rs:2028:10:2028:10 | T | | main.rs:2033:14:2033:17 | self | | {EXTERNAL LOCATION} | & | | main.rs:2033:14:2033:17 | self | TRef | main.rs:2013:5:2016:5 | MyVec | @@ -10783,7 +10782,6 @@ inferType | main.rs:2033:14:2033:22 | self.data | | {EXTERNAL LOCATION} | Vec | | main.rs:2033:14:2033:22 | self.data | A | {EXTERNAL LOCATION} | Global | | main.rs:2033:14:2033:22 | self.data | T | main.rs:2028:10:2028:10 | T | -| main.rs:2033:14:2033:29 | ...[index] | | {EXTERNAL LOCATION} | u8 | | main.rs:2033:14:2033:29 | ...[index] | | main.rs:2028:10:2028:10 | T | | main.rs:2033:24:2033:28 | index | | {EXTERNAL LOCATION} | usize | | main.rs:2037:22:2037:26 | slice | | {EXTERNAL LOCATION} | & | @@ -12931,14 +12929,11 @@ inferType | overloading.rs:511:17:511:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | | overloading.rs:511:19:511:19 | 0 | | {EXTERNAL LOCATION} | i32 | | overloading.rs:512:13:512:13 | y | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:512:13:512:13 | y | | {EXTERNAL LOCATION} | i64 | | overloading.rs:512:17:512:25 | call_f(...) | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:512:17:512:25 | call_f(...) | | {EXTERNAL LOCATION} | i64 | | overloading.rs:512:24:512:24 | x | | overloading.rs:464:5:464:19 | S | | overloading.rs:512:24:512:24 | x | T | {EXTERNAL LOCATION} | i32 | | overloading.rs:513:13:513:13 | z | | {EXTERNAL LOCATION} | i32 | | overloading.rs:513:22:513:22 | y | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:513:22:513:22 | y | | {EXTERNAL LOCATION} | i64 | | overloading.rs:515:13:515:13 | x | | overloading.rs:464:5:464:19 | S | | overloading.rs:515:13:515:13 | x | T | {EXTERNAL LOCATION} | i32 | | overloading.rs:515:17:515:20 | S(...) | | overloading.rs:464:5:464:19 | S | @@ -12953,10 +12948,6 @@ inferType | overloading.rs:518:17:518:20 | S(...) | | overloading.rs:464:5:464:19 | S | | overloading.rs:518:17:518:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | | overloading.rs:518:19:518:19 | 0 | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:519:13:519:13 | y | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:519:13:519:13 | y | | {EXTERNAL LOCATION} | i64 | -| overloading.rs:519:17:519:35 | call_f2(...) | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:519:17:519:35 | call_f2(...) | | {EXTERNAL LOCATION} | i64 | | overloading.rs:519:25:519:31 | S(...) | | overloading.rs:464:5:464:19 | S | | overloading.rs:519:25:519:31 | S(...) | T | {EXTERNAL LOCATION} | i32 | | overloading.rs:519:27:519:30 | 0i32 | | {EXTERNAL LOCATION} | i32 | @@ -12967,10 +12958,6 @@ inferType | overloading.rs:520:17:520:20 | S(...) | | overloading.rs:464:5:464:19 | S | | overloading.rs:520:17:520:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | | overloading.rs:520:19:520:19 | 0 | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:521:13:521:13 | y | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:521:13:521:13 | y | | {EXTERNAL LOCATION} | i64 | -| overloading.rs:521:17:521:35 | call_f2(...) | | {EXTERNAL LOCATION} | i32 | -| overloading.rs:521:17:521:35 | call_f2(...) | | {EXTERNAL LOCATION} | i64 | | overloading.rs:521:25:521:31 | S(...) | | overloading.rs:464:5:464:19 | S | | overloading.rs:521:25:521:31 | S(...) | T | {EXTERNAL LOCATION} | i64 | | overloading.rs:521:27:521:30 | 0i64 | | {EXTERNAL LOCATION} | i64 | diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index c33c49e7a168..87f4e659d8c4 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -336,7 +336,7 @@ module Make1 Input1> { * ``` * the type parameter `T` has the constraint `IComparable`. */ - Type getATypeParameterConstraint(TypeParameter tp, TypePath path); + TypeMention getATypeParameterConstraint(TypeParameter tp); /** * Holds if @@ -385,6 +385,36 @@ module Make1 Input1> { predicate conditionSatisfiesConstraint( TypeAbstraction abs, TypeMention condition, TypeMention constraint, boolean transitive ); + + /** + * Holds if the constraint belonging to `abs` with root type `constraint` is + * ambigous at `path`, meaning that there is _some_ other abstraction `abs2` + * with a structurally identical condition and same root constraint type + * `constraint`, and where the constraints differ at `path`. + * + * Example: + * + * ```rust + * trait Trait { } + * + * impl Trait for Foo { ... } + * // ^^^ `abs` + * // ^^^^^ `constraint` + * // ^^^^^^ `condition` + * + * impl Trait for Foo { } + * // ^^^ `abs2` + * // ^^^^^ `constraint` + * // ^^^^^^ `condition2` + * ``` + * + * In the above, `abs` and `abs2` have structurally identical conditions, + * `condition` and `condition2`, and they differ at the path `"T1"`, but + * not at the path `"T2"`. + */ + predicate typeAbstractionHasAmbigousConstraintAt( + TypeAbstraction abs, Type constraint, TypePath path + ); } module Make2 Input2> { @@ -820,38 +850,53 @@ module Make1 Input1> { private import BaseTypes - signature module SatisfiesConstraintInputSig { + /** Provides the input to `SatisfiesConstraint`. */ + signature module SatisfiesConstraintInputSig { /** Holds if it is relevant to know if `term` satisfies `constraint`. */ - predicate relevantConstraint(HasTypeTree term, Type constraint); + predicate relevantConstraint(Term term, Constraint constraint); + + /** + * Provides a means to override the predicate `typeAbstractionHasAmbigousConstraintAt` + * from `InputSig2`; this may be needed to avoid non-monotonic recursion. + */ + default predicate typeAbstractionHasAmbigousConstraintAtOverride( + TypeAbstraction abs, Type constraint, TypePath path + ) { + typeAbstractionHasAmbigousConstraintAt(abs, constraint, path) + } } module SatisfiesConstraint< - HasTypeTreeSig HasTypeTree, SatisfiesConstraintInputSig Input> + HasTypeTreeSig Term, HasTypeTreeSig Constraint, + SatisfiesConstraintInputSig Input> { private import Input pragma[nomagic] - private Type getTypeAt(HasTypeTree term, TypePath path) { + private Type getTypeAt(Term term, TypePath path) { relevantConstraint(term, _) and result = term.getTypeAt(path) } /** Holds if the type tree has the type `type` and should satisfy `constraint`. */ pragma[nomagic] - private predicate hasTypeConstraint(HasTypeTree term, Type type, Type constraint) { + private predicate hasTypeConstraint( + Term term, Type type, Constraint constraint, Type constraintRoot + ) { type = getTypeAt(term, TypePath::nil()) and - relevantConstraint(term, constraint) + relevantConstraint(term, constraint) and + constraintRoot = constraint.getTypeAt(TypePath::nil()) } - private module IsInstantiationOfInput implements - IsInstantiationOfInputSig + private module TermIsInstantiationOfConditionInput implements + IsInstantiationOfInputSig { - predicate potentialInstantiationOf(HasTypeTree tt, TypeAbstraction abs, TypeMention cond) { - exists(Type constraint, Type type | - hasTypeConstraint(tt, type, constraint) and - rootTypesSatisfaction(type, constraint, abs, cond, _) and + predicate potentialInstantiationOf(Term term, TypeAbstraction abs, TypeMention cond) { + exists(Constraint constraint, Type type, Type constraintRoot | + hasTypeConstraint(term, type, constraint, constraintRoot) and + rootTypesSatisfaction(type, constraintRoot, abs, cond, _) and // We only need to check instantiations where there are multiple candidates. - multipleConstraintImplementations(type, constraint) + multipleConstraintImplementations(type, constraintRoot) ) } @@ -860,18 +905,18 @@ module Make1 Input1> { } } - private module SatisfiesConstraintIsInstantiationOf = - IsInstantiationOf; + private module TermIsInstantiationOfCondition = + IsInstantiationOf; /** - * Holds if `tt` satisfies `constraint` through `abs`, `sub`, and `constraintMention`. + * Holds if `term` satisfies `constraint` through `abs`, `sub`, and `constraintMention`. */ pragma[nomagic] private predicate hasConstraintMention( - HasTypeTree tt, TypeAbstraction abs, TypeMention condition, Type constraint, - TypeMention constraintMention + Term term, TypeAbstraction abs, TypeMention condition, Constraint constraint, + Type constraintRoot, TypeMention constraintMention ) { - exists(Type type | hasTypeConstraint(tt, type, constraint) | + exists(Type type | hasTypeConstraint(term, type, constraint, constraintRoot) | // TODO: Handle universal conditions properly, which means checking type parameter constraints // Also remember to update logic in `hasNotConstraintMention` // @@ -880,35 +925,37 @@ module Make1 Input1> { // getTypeMentionRoot(condition) = abs.getATypeParameter() and // constraint = getTypeMentionRoot(constraintMention) // or - countConstraintImplementations(type, constraint) > 0 and - rootTypesSatisfaction(type, constraint, abs, condition, constraintMention) and + countConstraintImplementations(type, constraintRoot) > 0 and + rootTypesSatisfaction(type, constraintRoot, abs, condition, constraintMention) and // When there are multiple ways the type could implement the // constraint we need to find the right implementation, which is the // one where the type instantiates the precondition. - if multipleConstraintImplementations(type, constraint) - then SatisfiesConstraintIsInstantiationOf::isInstantiationOf(tt, abs, condition) + if multipleConstraintImplementations(type, constraintRoot) + then TermIsInstantiationOfCondition::isInstantiationOf(term, abs, condition) else any() ) } pragma[nomagic] private predicate isNotInstantiationOf( - HasTypeTree tt, TypeAbstraction abs, TypeMention condition, Type root + Term term, TypeAbstraction abs, TypeMention condition, Type root ) { exists(TypePath path | - SatisfiesConstraintIsInstantiationOf::isNotInstantiationOf(tt, abs, condition, path) and + TermIsInstantiationOfCondition::isNotInstantiationOf(term, abs, condition, path) and path.isCons(root.getATypeParameter(), _) ) } /** - * Holds if `tt` does not satisfy `constraint`. + * Holds if `term` does not satisfy `constraint`. * - * This predicate is an approximation of `not hasConstraintMention(tt, constraint)`. + * This predicate is an approximation of `not hasConstraintMention(term, constraint)`. */ pragma[nomagic] - private predicate hasNotConstraintMention(HasTypeTree tt, Type constraint) { - exists(Type type | hasTypeConstraint(tt, type, constraint) | + private predicate hasNotConstraintMention( + Term term, Constraint constraint, Type constraintRoot + ) { + exists(Type type | hasTypeConstraint(term, type, constraint, constraintRoot) | // TODO: Handle universal conditions properly, which means taking type parameter constraints into account // ( // exists(countConstraintImplementations(type, constraint)) @@ -921,15 +968,15 @@ module Make1 Input1> { // ) // ) and ( - countConstraintImplementations(type, constraint) = 0 + countConstraintImplementations(type, constraintRoot) = 0 or - not rootTypesSatisfaction(type, constraint, _, _, _) + not rootTypesSatisfaction(type, constraintRoot, _, _, _) or - multipleConstraintImplementations(type, constraint) and + multipleConstraintImplementations(type, constraintRoot) and forex(TypeAbstraction abs, TypeMention condition | - rootTypesSatisfaction(type, constraint, abs, condition, _) + rootTypesSatisfaction(type, constraintRoot, abs, condition, _) | - isNotInstantiationOf(tt, abs, condition, type) + isNotInstantiationOf(term, abs, condition, type) ) ) ) @@ -937,21 +984,51 @@ module Make1 Input1> { pragma[nomagic] private predicate satisfiesConstraintTypeMention0( - HasTypeTree tt, Type constraint, TypeAbstraction abs, TypeMention sub, TypePath path, Type t + Term term, Constraint constraint, Type constraintRoot, TypeMention constraintMention, + TypeAbstraction abs, TypeMention sub, TypePath path, Type t, boolean ambigous ) { - exists(TypeMention constraintMention | - hasConstraintMention(tt, abs, sub, constraint, constraintMention) and - conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, path, t) + hasConstraintMention(term, abs, sub, constraint, constraintRoot, constraintMention) and + conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, path, t) and + if + exists(TypePath prefix | + typeAbstractionHasAmbigousConstraintAtOverride(abs, constraintRoot, prefix) and + prefix.isPrefixOf(path) + ) + then ambigous = true + else ambigous = false + } + + pragma[nomagic] + private predicate satisfiesConstraintTypeMention1( + Term term, Constraint constraint, TypeAbstraction abs, TypeMention sub, TypePath path, + Type t + ) { + exists(Type constraintRoot, TypeMention constraintMention, boolean ambigous | + satisfiesConstraintTypeMention0(term, constraint, constraintRoot, constraintMention, abs, + sub, path, t, ambigous) + | + if ambigous = true + then + // When the constraint is not uniquely satisfied, we check that the satisfying + // abstraction is not more specific than the constraint to be satisfied. For example, + // if the constraint is `MyTrait` and there is both `impl MyTrait for ...` and + // `impl MyTrait for ...`, then the latter will be filtered away + not exists(TypePath path1, Type t1 | + conditionSatisfiesConstraintTypeAt(abs, sub, constraintMention, path1, t1) and + not t1 instanceof TypeParameter and + t1 != constraint.getTypeAt(path1) + ) + else any() ) } pragma[inline] private predicate satisfiesConstraintTypeMentionInline( - HasTypeTree tt, TypeAbstraction abs, Type constraint, TypePath path, + Term term, Constraint constraint, TypeAbstraction abs, TypePath path, TypePath pathToTypeParamInSub ) { exists(TypeMention sub, TypeParameter tp | - satisfiesConstraintTypeMention0(tt, constraint, abs, sub, path, tp) and + satisfiesConstraintTypeMention1(term, constraint, abs, sub, path, tp) and tp = abs.getATypeParameter() and sub.getTypeAt(pathToTypeParamInSub) = tp ) @@ -959,91 +1036,125 @@ module Make1 Input1> { pragma[nomagic] private predicate satisfiesConstraintTypeMention( - HasTypeTree tt, Type constraint, TypePath path, TypePath pathToTypeParamInSub + Term term, Constraint constraint, TypePath path, TypePath pathToTypeParamInSub ) { - satisfiesConstraintTypeMentionInline(tt, _, constraint, path, pathToTypeParamInSub) + satisfiesConstraintTypeMentionInline(term, constraint, _, path, pathToTypeParamInSub) } pragma[nomagic] private predicate satisfiesConstraintTypeMentionThrough( - HasTypeTree tt, TypeAbstraction abs, Type constraint, TypePath path, + Term term, Constraint constraint, TypeAbstraction abs, TypePath path, TypePath pathToTypeParamInSub ) { - satisfiesConstraintTypeMentionInline(tt, abs, constraint, path, pathToTypeParamInSub) + satisfiesConstraintTypeMentionInline(term, constraint, abs, path, pathToTypeParamInSub) } pragma[inline] private predicate satisfiesConstraintTypeNonTypeParamInline( - HasTypeTree tt, TypeAbstraction abs, Type constraint, TypePath path, Type t + Term term, TypeAbstraction abs, Constraint constraint, TypePath path, Type t ) { - satisfiesConstraintTypeMention0(tt, constraint, abs, _, path, t) and + satisfiesConstraintTypeMention1(term, constraint, abs, _, path, t) and not t = abs.getATypeParameter() } pragma[nomagic] - private predicate hasTypeConstraint(HasTypeTree term, Type constraint) { - hasTypeConstraint(term, constraint, constraint) + private predicate hasTypeConstraint(Term term, Constraint constraint) { + exists(Type constraintRoot | + hasTypeConstraint(term, constraintRoot, constraint, constraintRoot) + ) } /** - * Holds if the type tree at `tt` satisfies the constraint `constraint` + * Holds if the type tree at `term` satisfies the constraint `constraint` * with the type `t` at `path`. */ pragma[nomagic] - predicate satisfiesConstraintType(HasTypeTree tt, Type constraint, TypePath path, Type t) { - satisfiesConstraintTypeNonTypeParamInline(tt, _, constraint, path, t) + predicate satisfiesConstraintType(Term term, Constraint constraint, TypePath path, Type t) { + satisfiesConstraintTypeNonTypeParamInline(term, _, constraint, path, t) or exists(TypePath prefix0, TypePath pathToTypeParamInSub, TypePath suffix | - satisfiesConstraintTypeMention(tt, constraint, prefix0, pathToTypeParamInSub) and - getTypeAt(tt, pathToTypeParamInSub.appendInverse(suffix)) = t and + satisfiesConstraintTypeMention(term, constraint, prefix0, pathToTypeParamInSub) and + getTypeAt(term, pathToTypeParamInSub.appendInverse(suffix)) = t and path = prefix0.append(suffix) ) or - hasTypeConstraint(tt, constraint) and - t = getTypeAt(tt, path) + hasTypeConstraint(term, constraint) and + t = getTypeAt(term, path) } /** - * Holds if the type tree at `tt` satisfies the constraint `constraint` + * Holds if the type tree at `term` satisfies the constraint `constraint` * through `abs` with the type `t` at `path`. */ pragma[nomagic] predicate satisfiesConstraintTypeThrough( - HasTypeTree tt, TypeAbstraction abs, Type constraint, TypePath path, Type t + Term term, TypeAbstraction abs, Constraint constraint, TypePath path, Type t ) { - satisfiesConstraintTypeNonTypeParamInline(tt, abs, constraint, path, t) + satisfiesConstraintTypeNonTypeParamInline(term, abs, constraint, path, t) or exists(TypePath prefix0, TypePath pathToTypeParamInSub, TypePath suffix | - satisfiesConstraintTypeMentionThrough(tt, abs, constraint, prefix0, pathToTypeParamInSub) and - getTypeAt(tt, pathToTypeParamInSub.appendInverse(suffix)) = t and + satisfiesConstraintTypeMentionThrough(term, constraint, abs, prefix0, pathToTypeParamInSub) and + getTypeAt(term, pathToTypeParamInSub.appendInverse(suffix)) = t and path = prefix0.append(suffix) ) } /** - * Holds if the type tree at `tt` does _not_ satisfy the constraint `constraint`. + * Holds if the type tree at `term` does _not_ satisfy the constraint `constraint`. * - * This is an approximation of `not satisfiesConstraintType(tt, constraint, _, _)`, + * This is an approximation of `not satisfiesConstraintType(term, constraint, _, _)`, * but defined without a negative occurrence of `satisfiesConstraintType`. * * Due to the approximation, both `satisfiesConstraintType` and `dissatisfiesConstraint` - * can hold for the same values. For example, if `tt` has two different types `t1` + * can hold for the same values. For example, if `term` has two different types `t1` * and `t2`, and `t1` satisfies `constraint` while `t2` does not, then both * `satisfiesConstraintType` and `dissatisfiesConstraint` will hold. * - * Dually, if `tt` does not have a type, then neither `satisfiesConstraintType` nor + * Dually, if `term` does not have a type, then neither `satisfiesConstraintType` nor * `dissatisfiesConstraint` will hold. */ pragma[nomagic] - predicate dissatisfiesConstraint(HasTypeTree tt, Type constraint) { - hasNotConstraintMention(tt, constraint) and - exists(Type t | - hasTypeConstraint(tt, t, constraint) and - t != constraint + predicate dissatisfiesConstraint(Term term, Constraint constraint) { + hasNotConstraintMention(term, constraint, _) and + exists(Type t, Type constraintRoot | + hasTypeConstraint(term, t, constraint, constraintRoot) and // todo + t != constraintRoot ) } } + /** Provides the input to `SatisfiesType`. */ + signature module SatisfiesTypeInputSig { + /** Holds if it is relevant to know if `term` satisfies `type`. */ + predicate relevantConstraint(Term term, Type type); + } + + /** + * A helper module wrapping `SatisfiesConstraint` where the constraint is simply a type. + */ + module SatisfiesType Input> { + private import Input + + final private class TypeFinal = Type; + + private class TypeAsTypeTree extends TypeFinal { + Type getTypeAt(TypePath path) { + result = this and + path.isEmpty() + } + } + + private module SatisfiesConstraintInput implements + SatisfiesConstraintInputSig + { + predicate relevantConstraint(Term term, TypeAsTypeTree constraint) { + Input::relevantConstraint(term, constraint) + } + } + + import SatisfiesConstraint + } + /** Provides the input to `MatchingWithEnvironment`. */ signature module MatchingWithEnvironmentInputSig { /** @@ -1266,7 +1377,7 @@ module Make1 Input1> { private module AccessConstraint { predicate relevantAccessConstraint( Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath path, - Type constraint + TypeMention constraint ) { target = a.getTarget(e) and typeParameterConstraintHasTypeParameter(target, apos, path, constraint, _, _) @@ -1294,7 +1405,7 @@ module Make1 Input1> { } /** Gets the constraint that this relevant access should satisfy. */ - Type getConstraint(Declaration target) { + TypeMention getConstraint(Declaration target) { relevantAccessConstraint(a, e, target, apos, path, result) } @@ -1306,20 +1417,20 @@ module Make1 Input1> { } private module SatisfiesConstraintInput implements - SatisfiesConstraintInputSig + SatisfiesConstraintInputSig { - predicate relevantConstraint(RelevantAccess at, Type constraint) { + predicate relevantConstraint(RelevantAccess at, TypeMention constraint) { constraint = at.getConstraint(_) } } predicate satisfiesConstraintType( Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, - Type constraint, TypePath path, Type t + TypeMention constraint, TypePath path, Type t ) { exists(RelevantAccess ra | ra = MkRelevantAccess(a, apos, e, prefix) and - SatisfiesConstraint::satisfiesConstraintType(ra, + SatisfiesConstraint::satisfiesConstraintType(ra, constraint, path, t) and constraint = ra.getConstraint(target) ) @@ -1429,17 +1540,17 @@ module Make1 Input1> { */ pragma[nomagic] private predicate typeParameterConstraintHasTypeParameter( - Declaration target, AccessPosition apos, TypePath pathToConstrained, Type constraint, + Declaration target, AccessPosition apos, TypePath pathToConstrained, TypeMention constraint, TypePath pathToTp, TypeParameter tp ) { exists(DeclarationPosition dpos, TypeParameter constrainedTp | accessDeclarationPositionMatch(apos, dpos) and constrainedTp = target.getTypeParameter(_) and + constraint = getATypeParameterConstraint(constrainedTp) and tp = target.getTypeParameter(_) and - tp = getATypeParameterConstraint(constrainedTp, pathToTp) and + tp = constraint.getTypeAt(pathToTp) and constrainedTp != tp and - constrainedTp = target.getDeclaredType(dpos, pathToConstrained) and - constraint = getATypeParameterConstraint(constrainedTp, TypePath::nil()) + constrainedTp = target.getDeclaredType(dpos, pathToConstrained) ) } @@ -1448,7 +1559,7 @@ module Make1 Input1> { Access a, AccessEnvironment e, Declaration target, TypePath path, Type t, TypeParameter tp ) { not exists(getTypeArgument(a, target, tp, _)) and - exists(Type constraint, AccessPosition apos, TypePath pathToTp, TypePath pathToTp2 | + exists(TypeMention constraint, AccessPosition apos, TypePath pathToTp, TypePath pathToTp2 | typeParameterConstraintHasTypeParameter(target, apos, pathToTp2, constraint, pathToTp, tp) and AccessConstraint::satisfiesConstraintType(a, e, target, apos, pathToTp2, constraint, pathToTp.appendInverse(path), t) diff --git a/shared/util/codeql/util/UnboundList.qll b/shared/util/codeql/util/UnboundList.qll index 79fac6506d6a..6f05d6cddfc2 100644 --- a/shared/util/codeql/util/UnboundList.qll +++ b/shared/util/codeql/util/UnboundList.qll @@ -167,6 +167,14 @@ module Make Input> { */ bindingset[this] UnboundList getAPrefix() { result = [this, this.getAProperPrefix()] } + + /** + * Holds if this list is a prefix of `other`. + * + * This is equivalent to `this = other.getAPrefix()`, but more performant. + */ + bindingset[this, other] + predicate isPrefixOf(UnboundList other) { this = other.prefix(this.stringLength()) } } /** Provides predicates for constructing `UnboundList`s. */ From 5e187b43c92e072105263efcb1a4004892db71f6 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 19 Jan 2026 14:53:10 +0100 Subject: [PATCH 3/4] Rust: More type inference tests --- .../library-tests/type-inference/closure.rs | 87 ++++ .../test/library-tests/type-inference/main.rs | 24 + .../type-inference/type-inference.expected | 493 +++++++++++++++--- 3 files changed, 520 insertions(+), 84 deletions(-) diff --git a/rust/ql/test/library-tests/type-inference/closure.rs b/rust/ql/test/library-tests/type-inference/closure.rs index cc756a6b2678..cbcf154563ad 100644 --- a/rust/ql/test/library-tests/type-inference/closure.rs +++ b/rust/ql/test/library-tests/type-inference/closure.rs @@ -152,3 +152,90 @@ mod dyn_fn_once { let _r2 = apply_boxed(Box::new(|_: i64| true), 3); // $ target=apply_boxed target=new type=_r2:bool } } + +mod closure_infer_param { + fn apply1 i64>(f: F, a: i64) -> i64 { + f(a) + } + + fn apply2(f: impl Fn(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply3(f: &dyn Fn(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply4 i64>(mut f: F, a: i64) -> i64 { + f(a) + } + + fn apply5(f: &mut dyn FnMut(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply6(f: impl Fn(T) -> i64, a: T) -> i64 { + f(a) + } + + fn apply7 i64>(mut f: F, a: T) -> i64 { + f(a) + } + + fn test() { + let f = |x| x; // $ MISSING: type=x:i64 + let _r = apply1(f, 1i64); // $ target=apply1 + + let f = |x| x; // $ MISSING: type=x:i64 + let _r = apply2(f, 2i64); // $ target=apply2 + + let f = |x| x; // $ MISSING: type=x:i64 + let _r = apply3(&f, 3i64); // $ target=apply3 + + let f = |x| x; // $ MISSING: type=x:i64 + let _r = apply4(f, 4i64); // $ target=apply4 + + let mut f = |x| x; // $ MISSING: type=x:i64 + let _r = apply5(&mut f, 5i64); // $ target=apply5 + + let f = |x| x; // $ MISSING: type=x:i64 + let _r = apply6(f, 6i64); // $ target=apply6 + + let f = |x| x; // $ MISSING: type=x:i64 + let _r = apply7(f, 7i64); // $ target=apply7 + } +} + +mod implicit_deref { + use std::ops::Deref; + + struct S(T); + + impl Deref for S { + type Target = dyn Fn(T) -> bool; + + fn deref(&self) -> &Self::Target { + &|_| false + } + } + + pub fn test() { + let x = 0i64; + let v = Default::default(); // $ MISSING: type=v:i64 target=default + let s = S(v); + let _ret = s(x); // $ MISSING: type=_ret:bool + + let x = 0i32; + let v = Default::default(); // $ MISSING: type=v:i32 target=default + let s = S(v); + let s_ref = &s; + let _ret = s_ref(x); // $ MISSING: type=_ret:bool + + // The call below is not an implicit deref, instead it will target + // `impl FnOnce for &F` from + // https://doc.rust-lang.org/std/ops/trait.FnOnce.html#impl-FnOnce%3CA%3E-for-%26F + // and we currently cannot handle inferring the output type + let c = |x| x; // $ MISSING: type=x:i64 + (&c)(x); // $ MISSING: type=_:i64 + } +} diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 6c9f2c801d59..3e3d9f851080 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -2759,6 +2759,30 @@ mod dereference; mod dyn_type; mod regressions; +mod arg_trait_bounds { + struct Gen(T); + + trait Container { + fn get_input(&self) -> T; + } + + fn my_get>(c: &T) -> bool { + c.get_input() == 42 // $ target=get_input target=eq + } + + impl Container for Gen { + fn get_input(&self) -> GT { + self.0 // $ fieldof=Gen + } + } + + fn test() { + let v = Default::default(); // $ MISSING: type=v:i64 target=default + let g = Gen(v); + let _ = my_get(&g); // $ target=my_get + } +} + fn main() { field_access::f(); // $ target=f method_impl::f(); // $ target=f diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index 3837d8d8273a..e42e3070218d 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -661,6 +661,104 @@ inferCertainType | closure.rs:152:31:152:53 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | | closure.rs:152:41:152:41 | _ | | {EXTERNAL LOCATION} | i64 | | closure.rs:152:49:152:52 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:157:34:157:34 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:157:40:157:40 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:39:165:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:54:167:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:166:9:166:9 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:46:173:46 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:61:175:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:174:9:174:9 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:18:187:32 | apply1(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:28:187:31 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:13:190:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:18:190:32 | apply2(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:28:190:31 | 2i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:13:193:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:18:193:33 | apply3(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | | {EXTERNAL LOCATION} | & | +| closure.rs:193:29:193:32 | 3i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:13:196:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:18:196:32 | apply4(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:28:196:31 | 4i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:13:199:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:18:199:37 | apply5(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:25:199:30 | &mut f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:199:33:199:36 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:13:202:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:18:202:32 | apply6(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:28:202:31 | 6i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:13:205:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:18:205:32 | apply7(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:28:205:31 | 7i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:217:18:217:22 | SelfParam | | {EXTERNAL LOCATION} | & | +| closure.rs:217:18:217:22 | SelfParam | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:217:18:217:22 | SelfParam | TRef.T | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | | {EXTERNAL LOCATION} | & | +| closure.rs:217:42:219:9 | { ... } | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:13:218:22 | &... | | {EXTERNAL LOCATION} | & | +| closure.rs:218:18:218:22 | false | | {EXTERNAL LOCATION} | bool | +| closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | +| closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | +| closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | +| closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | | dereference.rs:13:29:15:5 | { ... } | | {EXTERNAL LOCATION} | & | @@ -3715,48 +3813,65 @@ inferCertainType | main.rs:2747:21:2747:21 | y | | {EXTERNAL LOCATION} | & | | main.rs:2750:13:2750:13 | y | | {EXTERNAL LOCATION} | usize | | main.rs:2751:23:2751:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2762:11:2797:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:5:2765:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:20:2765:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:41:2765:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2766:5:2766:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2778:5:2778:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2779:5:2779:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2780:5:2780:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2781:5:2781:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2781:5:2781:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2782:5:2782:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2783:5:2783:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2784:5:2784:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2785:5:2785:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2786:5:2786:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2787:5:2787:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2788:5:2788:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2789:5:2789:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2790:5:2790:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2791:5:2791:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2792:5:2792:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2793:5:2793:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2794:5:2794:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2795:5:2795:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2795:5:2795:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2795:5:2795:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2795:5:2795:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2795:16:2795:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2796:5:2796:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:22:2766:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2766:22:2766:26 | SelfParam | TRef | main.rs:2765:5:2767:5 | Self [trait Container] | +| main.rs:2769:34:2769:34 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2769:34:2769:34 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2769:49:2771:5 | { ... } | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:9:2770:9 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2770:9:2770:9 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2774:22:2774:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2774:22:2774:26 | SelfParam | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2774:22:2774:26 | SelfParam | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2774:35:2776:9 | { ... } | | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:16 | self | | {EXTERNAL LOCATION} | & | +| main.rs:2775:13:2775:16 | self | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2775:13:2775:16 | self | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2779:15:2783:5 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2782:17:2782:26 | my_get(...) | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:24:2782:25 | &g | | {EXTERNAL LOCATION} | & | +| main.rs:2786:11:2821:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2787:5:2787:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2788:5:2788:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:5:2789:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:20:2789:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:41:2789:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2790:5:2790:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2791:5:2791:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2792:5:2792:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2793:5:2793:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2794:5:2794:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2795:5:2795:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2796:5:2796:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2797:5:2797:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2798:5:2798:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2799:5:2799:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2800:5:2800:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2801:5:2801:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2802:5:2802:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2803:5:2803:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2804:5:2804:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2805:5:2805:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2805:5:2805:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2806:5:2806:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2807:5:2807:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2808:5:2808:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2809:5:2809:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2810:5:2810:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2811:5:2811:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2812:5:2812:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2813:5:2813:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2814:5:2814:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2815:5:2815:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2816:5:2816:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2817:5:2817:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2818:5:2818:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2819:5:2819:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2819:5:2819:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2819:5:2819:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2819:5:2819:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2819:16:2819:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2820:5:2820:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | @@ -6376,6 +6491,190 @@ inferType | closure.rs:152:41:152:41 | _ | | {EXTERNAL LOCATION} | i64 | | closure.rs:152:49:152:52 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:152:56:152:56 | 3 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:157:34:157:34 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:157:40:157:40 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:158:9:158:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:162:9:162:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:39:165:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:54:167:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:166:9:166:9 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:12 | f(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:166:9:166:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:170:9:170:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:46:173:46 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:61:175:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:174:9:174:9 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:12 | f(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:174:9:174:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:178:9:178:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:182:9:182:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:186:13:186:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:13:186:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:186:17:186:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:18:187:32 | apply1(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:187:25:187:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:187:28:187:31 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:13:189:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:189:17:189:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:190:13:190:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:18:190:32 | apply2(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:190:25:190:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:190:28:190:31 | 2i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:13:192:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:192:17:192:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:13:193:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:18:193:33 | apply3(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | | {EXTERNAL LOCATION} | & | +| closure.rs:193:25:193:26 | &f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:26:193:26 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:26:193:26 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:29:193:32 | 3i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:13:195:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:195:17:195:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:196:13:196:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:18:196:32 | apply4(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:196:25:196:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:196:28:196:31 | 4i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:198:17:198:17 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:17:198:17 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:198:21:198:25 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:21:198:25 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:13:199:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:18:199:37 | apply5(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:25:199:30 | &mut f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:199:25:199:30 | &mut f | TRefMut | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:25:199:30 | &mut f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:30:199:30 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:30:199:30 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:33:199:36 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:13:201:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:201:17:201:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:202:13:202:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:18:202:32 | apply6(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:202:25:202:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:202:28:202:31 | 6i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:13:204:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:204:17:204:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:205:13:205:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:18:205:32 | apply7(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:205:25:205:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:205:28:205:31 | 7i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:217:18:217:22 | SelfParam | | {EXTERNAL LOCATION} | & | +| closure.rs:217:18:217:22 | SelfParam | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:217:18:217:22 | SelfParam | TRef.T | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | | {EXTERNAL LOCATION} | & | +| closure.rs:217:42:219:9 | { ... } | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:13:218:22 | &... | | {EXTERNAL LOCATION} | & | +| closure.rs:218:13:218:22 | &... | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:14:218:22 | \|...\| false | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:15:218:15 | _ | | closure.rs:214:10:214:10 | T | +| closure.rs:218:18:218:22 | false | | {EXTERNAL LOCATION} | bool | +| closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:13:225:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:225:17:225:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:226:20:226:20 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:13:230:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:230:17:230:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:231:13:231:17 | s_ref | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | +| closure.rs:231:21:231:22 | &s | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:22:231:22 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:232:13:232:16 | _ret | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:232:20:232:24 | s_ref | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:232:20:232:27 | s_ref(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:13:238:13 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:238:17:238:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | +| closure.rs:239:9:239:12 | (...) | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:9:239:15 | ...(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | +| closure.rs:239:10:239:11 | &c | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:11:239:11 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:11:239:11 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | | dereference.rs:13:29:15:5 | { ... } | | {EXTERNAL LOCATION} | & | @@ -12307,48 +12606,74 @@ inferType | main.rs:2751:17:2751:17 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2751:17:2751:24 | x.max(...) | | {EXTERNAL LOCATION} | i32 | | main.rs:2751:23:2751:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2762:11:2797:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:5:2765:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:20:2765:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:41:2765:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2766:5:2766:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2778:5:2778:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2779:5:2779:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2780:5:2780:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2781:5:2781:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2781:5:2781:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2782:5:2782:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2783:5:2783:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2784:5:2784:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2785:5:2785:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2786:5:2786:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2787:5:2787:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2788:5:2788:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2789:5:2789:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2790:5:2790:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2791:5:2791:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2792:5:2792:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2793:5:2793:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2794:5:2794:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2795:5:2795:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2795:5:2795:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2795:5:2795:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2795:5:2795:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2795:16:2795:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2796:5:2796:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:22:2766:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2766:22:2766:26 | SelfParam | TRef | main.rs:2765:5:2767:5 | Self [trait Container] | +| main.rs:2769:34:2769:34 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2769:34:2769:34 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2769:49:2771:5 | { ... } | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:9:2770:9 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2770:9:2770:9 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2770:9:2770:21 | c.get_input() | | {EXTERNAL LOCATION} | i64 | +| main.rs:2770:9:2770:27 | ... == ... | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:26:2770:27 | 42 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2774:22:2774:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2774:22:2774:26 | SelfParam | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2774:22:2774:26 | SelfParam | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2774:35:2776:9 | { ... } | | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:16 | self | | {EXTERNAL LOCATION} | & | +| main.rs:2775:13:2775:16 | self | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2775:13:2775:16 | self | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:18 | self.0 | | main.rs:2773:10:2773:17 | GT | +| main.rs:2779:15:2783:5 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2781:13:2781:13 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2781:17:2781:22 | Gen(...) | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:13:2782:13 | _ | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:17:2782:26 | my_get(...) | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:24:2782:25 | &g | | {EXTERNAL LOCATION} | & | +| main.rs:2782:24:2782:25 | &g | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:25:2782:25 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2786:11:2821:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2787:5:2787:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2788:5:2788:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:5:2789:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:20:2789:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:41:2789:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2790:5:2790:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2791:5:2791:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2792:5:2792:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2793:5:2793:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2794:5:2794:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2795:5:2795:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2796:5:2796:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2797:5:2797:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2798:5:2798:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2799:5:2799:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2800:5:2800:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2801:5:2801:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2802:5:2802:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2803:5:2803:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2804:5:2804:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2805:5:2805:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2805:5:2805:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2806:5:2806:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2807:5:2807:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2808:5:2808:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2809:5:2809:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2810:5:2810:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2811:5:2811:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2812:5:2812:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2813:5:2813:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2814:5:2814:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2815:5:2815:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2816:5:2816:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2817:5:2817:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2818:5:2818:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2819:5:2819:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2819:5:2819:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2819:5:2819:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2819:5:2819:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2819:16:2819:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2820:5:2820:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | From 888f87a5fccb382abf27f58855b6c4e766d1b447 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 19 Jan 2026 14:53:22 +0100 Subject: [PATCH 4/4] Rust: Improve type inference for closures --- .../internal/typeinference/TypeInference.qll | 197 ++++++----- .../library-tests/type-inference/closure.rs | 26 +- .../test/library-tests/type-inference/main.rs | 4 +- .../type-inference/type-inference.expected | 329 +++++++++++++++--- .../typeinference/internal/TypeInference.qll | 152 +++++++- 5 files changed, 553 insertions(+), 155 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 798ee76c7be9..a79863e047f3 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -416,6 +416,14 @@ private predicate isPanicMacroCall(MacroExpr me) { me.getMacroCall().resolveMacro().(MacroRules).getName().getText() = "panic" } +// Due to "binding modes" the type of the pattern is not necessarily the +// same as the type of the initializer. The pattern being an identifier +// pattern is sufficient to ensure that this is not the case. +private predicate identLetStmt(LetStmt let, IdentPat lhs, Expr rhs) { + let.getPat() = lhs and + let.getInitializer() = rhs +} + /** Module for inferring certain type information. */ module CertainTypeInference { pragma[nomagic] @@ -493,11 +501,7 @@ module CertainTypeInference { // is not a certain type equality. exists(LetStmt let | not let.hasTypeRepr() and - // Due to "binding modes" the type of the pattern is not necessarily the - // same as the type of the initializer. The pattern being an identifier - // pattern is sufficient to ensure that this is not the case. - let.getPat().(IdentPat) = n1 and - let.getInitializer() = n2 + identLetStmt(let, n1, n2) ) or exists(LetExpr let | @@ -521,6 +525,25 @@ module CertainTypeInference { ) else prefix2.isEmpty() ) + or + exists(CallExprImpl::DynamicCallExpr dce, TupleType tt, int i | + n1 = dce.getArgList() and + tt.getArity() = dce.getNumberOfSyntacticArguments() and + n2 = dce.getSyntacticPositionalArgument(i) and + prefix1 = TypePath::singleton(tt.getPositionalTypeParameter(i)) and + prefix2.isEmpty() + ) + or + exists(ClosureExpr ce, int index | + n1 = ce and + n2 = ce.getParam(index).getPat() and + prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and + prefix2.isEmpty() + ) + or + n1 = any(ClosureExpr ce | not ce.hasRetType() and ce.getClosureBody() = n2) and + prefix1 = closureReturnPath() and + prefix2.isEmpty() } pragma[nomagic] @@ -783,17 +806,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and prefix1 = TypePath::singleton(getArrayTypeParameter()) and prefix2.isEmpty() - or - exists(ClosureExpr ce, int index | - n1 = ce and - n2 = ce.getParam(index).getPat() and - prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and - prefix2.isEmpty() - ) - or - n1.(ClosureExpr).getClosureBody() = n2 and - prefix1 = closureReturnPath() and - prefix2.isEmpty() } /** @@ -836,6 +848,19 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) { ) } +private Type inferUnknownTypeFromAnnotation(AstNode n, TypePath path) { + inferType(n, path) = TUnknownType() and + // Normally, these are coercion sites, but in case a type is unknown we + // allow for type information to flow from the type annotation. + exists(TypeMention tm | result = tm.getTypeAt(path) | + tm = any(LetStmt let | identLetStmt(let, _, n)).getTypeRepr() + or + tm = any(ClosureExpr ce | n = ce.getBody()).getRetType().getTypeRepr() + or + tm = getReturnTypeMention(any(Function f | n = f.getBody())) + ) +} + /** * Holds if the type tree of `n1` at `prefix1` should be equal to the type tree * of `n2` at `prefix2`, but type information should only propagate from `n1` to @@ -1685,6 +1710,8 @@ private module AssocFunctionResolution { * 3. `AssocFunctionCallCallExpr`: a qualified function call, `Q::f(x)`; or * 4. `AssocFunctionCallOperation`: an operation expression, `x + y`, which is syntactic sugar * for `Add::add(x, y)`. + * 5. `ClosureMethodCall`: a call to a closure, `c(x)`, which is syntactic sugar for + * `c.call_once(x)`, `c.call_mut(x)`, or `c.call(x)`. * * Note that only in case 1 and 2 is auto-dereferencing and borrowing allowed. * @@ -1701,7 +1728,7 @@ private module AssocFunctionResolution { pragma[nomagic] abstract predicate hasNameAndArity(string name, int arity); - abstract Expr getNonReturnNodeAt(FunctionPosition pos); + abstract AstNode getNonReturnNodeAt(FunctionPosition pos); AstNode getNodeAt(FunctionPosition pos) { result = this.getNonReturnNodeAt(pos) @@ -2235,7 +2262,7 @@ private module AssocFunctionResolution { } } - private class AssocFunctionCallMethodCallExpr extends AssocFunctionCall instanceof MethodCallExpr { + private class MethodCallExprAssocFunctionCall extends AssocFunctionCall instanceof MethodCallExpr { override predicate hasNameAndArity(string name, int arity) { name = super.getIdentifier().getText() and arity = super.getNumberOfSyntacticArguments() @@ -2255,7 +2282,7 @@ private module AssocFunctionResolution { override Trait getTrait() { none() } } - private class AssocFunctionCallIndexExpr extends AssocFunctionCall, IndexExpr { + private class IndexExprAssocFunctionCall extends AssocFunctionCall, IndexExpr { private predicate isInMutableContext() { // todo: does not handle all cases yet VariableImpl::assignmentOperationDescendant(_, this) @@ -2285,8 +2312,8 @@ private module AssocFunctionResolution { } } - private class AssocFunctionCallCallExpr extends AssocFunctionCall, CallExpr { - AssocFunctionCallCallExpr() { + private class CallExprAssocFunctionCall extends AssocFunctionCall, CallExpr { + CallExprAssocFunctionCall() { exists(getCallExprPathQualifier(this)) and // even if a target cannot be resolved by path resolution, it may still // be possible to resolve a blanket implementation (so not `forex`) @@ -2318,7 +2345,7 @@ private module AssocFunctionResolution { override Trait getTrait() { result = getCallExprTraitQualifier(this) } } - final class AssocFunctionCallOperation extends AssocFunctionCall, Operation { + final class OperationAssocFunctionCall extends AssocFunctionCall, Operation { override predicate hasNameAndArity(string name, int arity) { this.isOverloaded(_, name, _) and arity = this.getNumberOfOperands() @@ -2376,6 +2403,29 @@ private module AssocFunctionResolution { override Trait getTrait() { this.isOverloaded(result, _, _) } } + private class DynamicAssocFunctionCall extends AssocFunctionCall instanceof CallExprImpl::DynamicCallExpr + { + pragma[nomagic] + override predicate hasNameAndArity(string name, int arity) { + name = "call_once" and // todo: handle call_mut and call + arity = 2 // args are passed in a tuple + } + + override predicate hasReceiver() { any() } + + override AstNode getNonReturnNodeAt(FunctionPosition pos) { + pos.asPosition() = 0 and + result = super.getFunction() + or + pos.asPosition() = 1 and + result = super.getArgList() + } + + override predicate supportsAutoDerefAndBorrow() { any() } + + override Trait getTrait() { result instanceof AnyFnTrait } + } + pragma[nomagic] private AssocFunctionDeclaration getAssocFunctionSuccessor( ImplOrTraitItemNode i, string name, int arity @@ -3239,7 +3289,7 @@ private module OperationMatchingInput implements MatchingInputSig { } } - class Access extends AssocFunctionResolution::AssocFunctionCallOperation { + class Access extends AssocFunctionResolution::OperationAssocFunctionCall { Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() } pragma[nomagic] @@ -3844,14 +3894,6 @@ private module InvokedClosureSatisfiesTypeInput implements SatisfiesTypeInputSig } } -private module InvokedClosureSatisfiesType = - SatisfiesType; - -/** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */ -private Type invokedClosureFnTypeAt(InvokedClosureExpr ce, TypePath path) { - InvokedClosureSatisfiesType::satisfiesConstraintType(ce, _, path, result) -} - /** * Gets the root type of a closure. * @@ -3878,73 +3920,39 @@ private TypePath closureParameterPath(int arity, int index) { TypePath::singleton(getTupleTypeParameter(arity, index))) } -/** Gets the path to the return type of the `FnOnce` trait. */ -private TypePath fnReturnPath() { - result = TypePath::singleton(getAssociatedTypeTypeParameter(any(FnOnceTrait t).getOutputType())) -} - -/** - * Gets the path to the parameter type of the `FnOnce` trait with arity `arity` - * and index `index`. - */ pragma[nomagic] -private TypePath fnParameterPath(int arity, int index) { - result = - TypePath::cons(TTypeParamTypeParameter(any(FnOnceTrait t).getTypeParam()), - TypePath::singleton(getTupleTypeParameter(arity, index))) -} - -pragma[nomagic] -private Type inferDynamicCallExprType(Expr n, TypePath path) { - exists(InvokedClosureExpr ce | - // Propagate the function's return type to the call expression - exists(TypePath path0 | result = invokedClosureFnTypeAt(ce, path0) | - n = ce.getCall() and - path = path0.stripPrefix(fnReturnPath()) +private Type inferClosureExprType(AstNode n, TypePath path) { + exists(ClosureExpr ce | + n = ce and + ( + path.isEmpty() and + result = closureRootType() + or + path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and + result.(TupleType).getArity() = ce.getNumberOfParams() or - // Propagate the function's parameter type to the arguments - exists(int index | - n = ce.getCall().getSyntacticPositionalArgument(index) and - path = - path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index)) + exists(TypePath path0 | + result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path0) and + path = closureReturnPath().append(path0) ) ) or - // _If_ the invoked expression has the type of a closure, then we propagate - // the surrounding types into the closure. - exists(int arity, TypePath path0 | ce.getTypeAt(TypePath::nil()) = closureRootType() | - // Propagate the type of arguments to the parameter types of closure - exists(int index, ArgList args | - n = ce and - args = ce.getCall().getArgList() and - arity = args.getNumberOfArgs() and - result = inferType(args.getArg(index), path0) and - path = closureParameterPath(arity, index).append(path0) - ) - or - // Propagate the type of the call expression to the return type of the closure - n = ce and - arity = ce.getCall().getArgList().getNumberOfArgs() and - result = inferType(ce.getCall(), path0) and - path = closureReturnPath().append(path0) + exists(Param p | + p = ce.getAParam() and + not p.hasTypeRepr() and + n = p.getPat() and + result = TUnknownType() and + path.isEmpty() ) ) } pragma[nomagic] -private Type inferClosureExprType(AstNode n, TypePath path) { - exists(ClosureExpr ce | - n = ce and - path.isEmpty() and - result = closureRootType() - or - n = ce and - path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and - result.(TupleType).getArity() = ce.getNumberOfParams() - or - // Propagate return type annotation to body - n = ce.getClosureBody() and - result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path) +private TupleType inferArgList(ArgList args, TypePath path) { + exists(CallExprImpl::DynamicCallExpr dce | + args = dce.getArgList() and + result.getArity() = dce.getNumberOfSyntacticArguments() and + path.isEmpty() ) } @@ -3992,7 +4000,8 @@ private module Cached { or i instanceof ImplItemNode and dispatch = false | - result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) + result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) and + not call instanceof CallExprImpl::DynamicCallExpr // todo ) } @@ -4101,13 +4110,15 @@ private module Cached { or result = inferForLoopExprType(n, path) or - result = inferDynamicCallExprType(n, path) - or result = inferClosureExprType(n, path) or + result = inferArgList(n, path) + or result = inferStructPatType(n, path) or result = inferTupleStructPatType(n, path) + or + result = inferUnknownTypeFromAnnotation(n, path) ) } } @@ -4124,8 +4135,8 @@ private module Debug { Locatable getRelevantLocatable() { exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and - filepath.matches("%/main.rs") and - startline = 103 + filepath.matches("%/regressions.rs") and + startline = 24 ) } diff --git a/rust/ql/test/library-tests/type-inference/closure.rs b/rust/ql/test/library-tests/type-inference/closure.rs index cbcf154563ad..fbef401bb083 100644 --- a/rust/ql/test/library-tests/type-inference/closure.rs +++ b/rust/ql/test/library-tests/type-inference/closure.rs @@ -63,7 +63,7 @@ mod fn_once_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -100,7 +100,7 @@ mod fn_mut_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -137,7 +137,7 @@ mod fn_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -183,25 +183,25 @@ mod closure_infer_param { } fn test() { - let f = |x| x; // $ MISSING: type=x:i64 + let f = |x| x; // $ type=x:i64 let _r = apply1(f, 1i64); // $ target=apply1 - let f = |x| x; // $ MISSING: type=x:i64 + let f = |x| x; // $ type=x:i64 let _r = apply2(f, 2i64); // $ target=apply2 - let f = |x| x; // $ MISSING: type=x:i64 + let f = |x| x; // $ type=x:i64 let _r = apply3(&f, 3i64); // $ target=apply3 - let f = |x| x; // $ MISSING: type=x:i64 + let f = |x| x; // $ type=x:i64 let _r = apply4(f, 4i64); // $ target=apply4 let mut f = |x| x; // $ MISSING: type=x:i64 let _r = apply5(&mut f, 5i64); // $ target=apply5 - let f = |x| x; // $ MISSING: type=x:i64 + let f = |x| x; // $ type=x:i64 let _r = apply6(f, 6i64); // $ target=apply6 - let f = |x| x; // $ MISSING: type=x:i64 + let f = |x| x; // $ type=x:i64 let _r = apply7(f, 7i64); // $ target=apply7 } } @@ -221,15 +221,15 @@ mod implicit_deref { pub fn test() { let x = 0i64; - let v = Default::default(); // $ MISSING: type=v:i64 target=default + let v = Default::default(); // $ type=v:i64 target=default let s = S(v); - let _ret = s(x); // $ MISSING: type=_ret:bool + let _ret = s(x); // $ type=_ret:bool let x = 0i32; - let v = Default::default(); // $ MISSING: type=v:i32 target=default + let v = Default::default(); // $ type=v:i32 target=default let s = S(v); let s_ref = &s; - let _ret = s_ref(x); // $ MISSING: type=_ret:bool + let _ret = s_ref(x); // $ type=_ret:bool // The call below is not an implicit deref, instead it will target // `impl FnOnce for &F` from diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 3e3d9f851080..ecb4816ebb01 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -2259,7 +2259,7 @@ mod loops { // for loops with arrays for i in [1, 2, 3] {} // $ type=i:i32 - for i in [1, 2, 3].map(|x| x + 1) {} // $ target=map MISSING: type=i:i32 + for i in [1, 2, 3].map(|x| x + 1) {} // $ target=map target=add type=i:i32 for i in [1, 2, 3].into_iter() {} // $ target=into_iter type=i:i32 let vals1 = [1u8, 2, 3]; // $ type=vals1:TArray.u8 @@ -2777,7 +2777,7 @@ mod arg_trait_bounds { } fn test() { - let v = Default::default(); // $ MISSING: type=v:i64 target=default + let v = Default::default(); // $ type=v:i64 target=default let g = Gen(v); let _ = my_get(&g); // $ target=my_get } diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index e42e3070218d..029f7873f2c3 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -545,6 +545,16 @@ inferCertainType | blanket_impl.rs:299:47:299:67 | "SELECT * FROM users" | | {EXTERNAL LOCATION} | & | | blanket_impl.rs:299:47:299:67 | "SELECT * FROM users" | TRef | {EXTERNAL LOCATION} | str | | closure.rs:4:19:31:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:6:13:6:22 | my_closure | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:6:13:6:22 | my_closure | dyn(Args) | {EXTERNAL LOCATION} | (T_2) | +| closure.rs:6:13:6:22 | my_closure | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:13:6:22 | my_closure | dyn(Args).T1 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:13:6:22 | my_closure | dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:6:26:6:38 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_2) | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args).T1 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:6:27:6:27 | a | | {EXTERNAL LOCATION} | bool | | closure.rs:6:30:6:30 | b | | {EXTERNAL LOCATION} | bool | | closure.rs:6:33:6:33 | a | | {EXTERNAL LOCATION} | bool | @@ -553,18 +563,38 @@ inferCertainType | closure.rs:8:13:8:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:8:22:8:25 | 1i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:9:31:9:34 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:10:25:10:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:10:25:10:27 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:26:10:26 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:13:14:20 | add_zero | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:14:13:14:20 | add_zero | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:14:13:14:20 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:13:14:20 | add_zero | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:24:14:33 | \|...\| n | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:14:24:14:33 | \|...\| n | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:14:24:14:33 | \|...\| n | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:24:14:33 | \|...\| n | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:14:25:14:25 | n | | {EXTERNAL LOCATION} | i64 | | closure.rs:14:33:14:33 | n | | {EXTERNAL LOCATION} | i64 | +| closure.rs:15:18:15:25 | add_zero | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:15:18:15:25 | add_zero | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:15:18:15:25 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:15:18:15:25 | add_zero | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:25:20:25:25 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:25:20:25:25 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:21:25:24 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:30:13:30:15 | _b2 | | {EXTERNAL LOCATION} | bool | | closure.rs:35:44:35:44 | f | | closure.rs:35:20:35:41 | F | | closure.rs:35:50:37:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:36:23:36:23 | f | | closure.rs:35:20:35:41 | F | +| closure.rs:36:24:36:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:36:24:36:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:36:25:36:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:39:45:39:45 | f | | closure.rs:39:28:39:42 | F | | closure.rs:39:51:41:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:40:23:40:23 | f | | closure.rs:39:28:39:42 | F | +| closure.rs:40:24:40:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:40:24:40:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:40:25:40:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:43:46:43:46 | f | | closure.rs:43:22:43:43 | F | | closure.rs:43:52:46:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -573,23 +603,38 @@ inferCertainType | closure.rs:48:45:48:45 | a | | closure.rs:48:14:48:14 | A | | closure.rs:48:56:50:5 | { ... } | | closure.rs:48:17:48:17 | B | | closure.rs:49:9:49:9 | f | | closure.rs:48:20:48:36 | F | +| closure.rs:49:10:49:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:49:10:49:12 | ArgList | T0 | closure.rs:48:14:48:14 | A | | closure.rs:49:11:49:11 | a | | closure.rs:48:14:48:14 | A | | closure.rs:52:18:52:18 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:52:53:54:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:53:9:53:9 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:56:15:68:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:57:13:57:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:57:13:57:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:57:13:57:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:57:17:63:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:57:17:63:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:57:17:63:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:57:18:57:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:58:16:58:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:64:24:64:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:64:24:64:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:64:24:64:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:64:27:64:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:67:13:67:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:19:67:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:72:47:72:47 | f | | closure.rs:72:20:72:40 | F | | closure.rs:72:53:74:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:73:23:73:23 | f | | closure.rs:72:20:72:40 | F | +| closure.rs:73:24:73:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:73:24:73:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:73:25:73:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:76:48:76:48 | f | | closure.rs:76:28:76:41 | F | | closure.rs:76:54:78:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:77:23:77:23 | f | | closure.rs:76:28:76:41 | F | +| closure.rs:77:24:77:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:77:24:77:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:77:25:77:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:80:49:80:49 | f | | closure.rs:80:22:80:42 | F | | closure.rs:80:55:83:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -598,23 +643,38 @@ inferCertainType | closure.rs:85:48:85:48 | a | | closure.rs:85:14:85:14 | A | | closure.rs:85:59:87:5 | { ... } | | closure.rs:85:17:85:17 | B | | closure.rs:86:9:86:9 | f | | closure.rs:85:20:85:35 | F | +| closure.rs:86:10:86:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:86:10:86:12 | ArgList | T0 | closure.rs:85:14:85:14 | A | | closure.rs:86:11:86:11 | a | | closure.rs:85:14:85:14 | A | | closure.rs:89:22:89:22 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:89:56:91:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:90:9:90:9 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:93:15:105:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:94:13:94:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:94:13:94:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:94:13:94:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:94:17:100:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:94:17:100:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:94:17:100:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:94:18:94:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:95:16:95:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:101:24:101:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:101:24:101:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:101:24:101:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:101:27:101:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:104:13:104:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:19:104:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:109:40:109:40 | f | | closure.rs:109:20:109:37 | F | | closure.rs:109:46:111:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:110:23:110:23 | f | | closure.rs:109:20:109:37 | F | +| closure.rs:110:24:110:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:110:24:110:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:110:25:110:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:113:41:113:41 | f | | closure.rs:113:28:113:38 | F | | closure.rs:113:47:115:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:114:23:114:23 | f | | closure.rs:113:28:113:38 | F | +| closure.rs:114:24:114:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:114:24:114:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:114:25:114:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:117:42:117:42 | f | | closure.rs:117:22:117:39 | F | | closure.rs:117:48:120:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -623,13 +683,24 @@ inferCertainType | closure.rs:122:41:122:41 | a | | closure.rs:122:14:122:14 | A | | closure.rs:122:52:124:5 | { ... } | | closure.rs:122:17:122:17 | B | | closure.rs:123:9:123:9 | f | | closure.rs:122:20:122:32 | F | +| closure.rs:123:10:123:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:123:10:123:12 | ArgList | T0 | closure.rs:122:14:122:14 | A | | closure.rs:123:11:123:11 | a | | closure.rs:122:14:122:14 | A | | closure.rs:126:18:126:18 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:126:49:128:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:127:9:127:9 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:130:15:142:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:131:13:131:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:131:13:131:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:131:13:131:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:131:17:137:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:131:17:137:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:131:17:137:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:131:18:131:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:132:16:132:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:138:24:138:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:138:24:138:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:138:24:138:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:138:27:138:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:141:13:141:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:19:141:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | @@ -641,6 +712,8 @@ inferCertainType | closure.rs:147:9:147:9 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:147:9:147:9 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:147:9:147:9 | f | T | closure.rs:146:26:146:51 | F | +| closure.rs:147:10:147:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:147:10:147:14 | ArgList | T0 | closure.rs:146:20:146:20 | A | | closure.rs:147:11:147:13 | arg | | closure.rs:146:20:146:20 | A | | closure.rs:150:30:150:30 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:150:30:150:30 | f | A | {EXTERNAL LOCATION} | Global | @@ -659,17 +732,25 @@ inferCertainType | closure.rs:151:34:151:36 | arg | | closure.rs:150:24:150:24 | A | | closure.rs:152:31:152:53 | ...::new(...) | | {EXTERNAL LOCATION} | Box | | closure.rs:152:31:152:53 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| closure.rs:152:40:152:52 | \|...\| true | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:152:40:152:52 | \|...\| true | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:152:40:152:52 | \|...\| true | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:152:40:152:52 | \|...\| true | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:152:41:152:41 | _ | | {EXTERNAL LOCATION} | i64 | | closure.rs:152:49:152:52 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:157:34:157:34 | f | | closure.rs:157:15:157:31 | F | | closure.rs:157:40:157:40 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:158:10:158:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:158:10:158:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | | closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:162:10:162:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:162:10:162:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | | closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | @@ -683,11 +764,15 @@ inferCertainType | closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:10:166:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:10:166:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | | closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:170:10:170:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:170:10:170:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | | closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | @@ -701,16 +786,22 @@ inferCertainType | closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:10:174:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:10:174:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | | closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | | closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:178:10:178:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:178:10:178:12 | ArgList | T0 | closure.rs:177:15:177:15 | T | | closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | | closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | | closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | | closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:182:10:182:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:182:10:182:12 | ArgList | T0 | closure.rs:181:15:181:15 | T | | closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | | closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | @@ -745,19 +836,27 @@ inferCertainType | closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | | closure.rs:217:42:219:9 | { ... } | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:218:13:218:22 | &... | | {EXTERNAL LOCATION} | & | +| closure.rs:218:14:218:22 | \|...\| false | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:218:18:218:22 | false | | {EXTERNAL LOCATION} | bool | | closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:21:226:23 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:226:21:226:23 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | | closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | | closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | | closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | | closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:232:25:232:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:232:25:232:27 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | | closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | | closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | +| closure.rs:239:13:239:15 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:13:239:15 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | @@ -6157,6 +6256,8 @@ inferType | closure.rs:10:18:10:24 | add_one | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:18:10:24 | add_one | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:10:18:10:27 | add_one(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:10:25:10:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:10:25:10:27 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:26:10:26 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:13:13:13:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:13:17:13:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | @@ -6176,6 +6277,8 @@ inferType | closure.rs:15:18:15:25 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:15:18:15:25 | add_zero | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:15:18:15:28 | add_zero(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:15:26:15:28 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:15:26:15:28 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:15:27:15:27 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:17:13:17:21 | _get_bool | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:17:13:17:21 | _get_bool | dyn(Args) | {EXTERNAL LOCATION} | () | @@ -6203,6 +6306,8 @@ inferType | closure.rs:25:18:25:19 | id | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:18:25:19 | id | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:25:18:25:25 | id(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:25:20:25:25 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:25:20:25:25 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:21:25:24 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:28:13:28:15 | id2 | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:28:13:28:15 | id2 | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | @@ -6222,18 +6327,24 @@ inferType | closure.rs:30:25:30:27 | id2 | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:30:25:30:27 | id2 | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:30:25:30:32 | id2(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:30:28:30:32 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:30:28:30:32 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:30:29:30:31 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:35:44:35:44 | f | | closure.rs:35:20:35:41 | F | | closure.rs:35:50:37:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:36:13:36:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:36:23:36:23 | f | | closure.rs:35:20:35:41 | F | | closure.rs:36:23:36:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:36:24:36:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:36:24:36:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:36:25:36:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:39:45:39:45 | f | | closure.rs:39:28:39:42 | F | | closure.rs:39:51:41:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:40:13:40:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:40:23:40:23 | f | | closure.rs:39:28:39:42 | F | | closure.rs:40:23:40:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:40:24:40:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:40:24:40:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:40:25:40:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:43:46:43:46 | f | | closure.rs:43:22:43:43 | F | | closure.rs:43:52:46:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6241,74 +6352,77 @@ inferType | closure.rs:44:19:44:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:45:9:45:9 | f | | closure.rs:43:22:43:43 | F | | closure.rs:45:9:45:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:45:10:45:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:45:10:45:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:45:11:45:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:48:39:48:39 | f | | closure.rs:48:20:48:36 | F | | closure.rs:48:45:48:45 | a | | closure.rs:48:14:48:14 | A | | closure.rs:48:56:50:5 | { ... } | | closure.rs:48:17:48:17 | B | | closure.rs:49:9:49:9 | f | | closure.rs:48:20:48:36 | F | | closure.rs:49:9:49:12 | f(...) | | closure.rs:48:17:48:17 | B | +| closure.rs:49:10:49:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:49:10:49:12 | ArgList | T0 | closure.rs:48:14:48:14 | A | | closure.rs:49:11:49:11 | a | | closure.rs:48:14:48:14 | A | | closure.rs:52:18:52:18 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:52:53:54:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:53:9:53:9 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:53:9:53:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:53:10:53:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:53:10:53:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:53:11:53:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:53:11:53:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:56:15:68:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:57:13:57:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:57:13:57:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:57:13:57:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:57:13:57:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:57:13:57:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:57:17:63:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:57:17:63:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:57:18:57:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:57:34:63:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:57:34:63:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:58:13:62:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:58:13:62:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:58:16:58:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:58:18:60:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:58:18:60:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:59:17:59:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:59:17:59:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:60:20:62:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:60:20:62:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:61:17:61:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:61:17:61:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:64:13:64:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:64:13:64:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:64:18:64:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:64:18:64:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:64:24:64:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:64:24:64:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:64:24:64:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:64:24:64:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:64:24:64:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:64:27:64:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:66:13:66:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:66:13:66:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:66:13:66:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:66:17:66:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:66:17:66:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:66:17:66:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:66:18:66:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:66:21:66:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:66:25:66:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:67:13:67:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:19:67:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:29:67:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:67:29:67:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:67:29:67:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:72:47:72:47 | f | | closure.rs:72:20:72:40 | F | | closure.rs:72:53:74:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:73:13:73:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:73:23:73:23 | f | | closure.rs:72:20:72:40 | F | | closure.rs:73:23:73:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:73:24:73:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:73:24:73:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:73:25:73:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:76:48:76:48 | f | | closure.rs:76:28:76:41 | F | | closure.rs:76:54:78:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:77:13:77:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:77:23:77:23 | f | | closure.rs:76:28:76:41 | F | | closure.rs:77:23:77:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:77:24:77:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:77:24:77:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:77:25:77:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:80:49:80:49 | f | | closure.rs:80:22:80:42 | F | | closure.rs:80:55:83:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6316,74 +6430,77 @@ inferType | closure.rs:81:19:81:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:82:9:82:9 | f | | closure.rs:80:22:80:42 | F | | closure.rs:82:9:82:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:82:10:82:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:82:10:82:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:82:11:82:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:85:42:85:42 | f | | closure.rs:85:20:85:35 | F | | closure.rs:85:48:85:48 | a | | closure.rs:85:14:85:14 | A | | closure.rs:85:59:87:5 | { ... } | | closure.rs:85:17:85:17 | B | | closure.rs:86:9:86:9 | f | | closure.rs:85:20:85:35 | F | | closure.rs:86:9:86:12 | f(...) | | closure.rs:85:17:85:17 | B | +| closure.rs:86:10:86:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:86:10:86:12 | ArgList | T0 | closure.rs:85:14:85:14 | A | | closure.rs:86:11:86:11 | a | | closure.rs:85:14:85:14 | A | | closure.rs:89:22:89:22 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:89:56:91:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:90:9:90:9 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:90:9:90:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:90:10:90:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:90:10:90:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:90:11:90:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:90:11:90:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:93:15:105:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:94:13:94:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:94:13:94:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:94:13:94:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:94:13:94:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:94:13:94:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:94:17:100:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:94:17:100:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:94:18:94:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:94:34:100:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:94:34:100:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:95:13:99:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:95:13:99:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:95:16:95:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:95:18:97:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:95:18:97:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:96:17:96:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:96:17:96:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:97:20:99:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:97:20:99:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:98:17:98:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:98:17:98:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:101:13:101:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:101:13:101:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:101:18:101:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:101:18:101:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:101:24:101:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:101:24:101:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:101:24:101:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:101:24:101:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:101:24:101:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:101:27:101:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:103:13:103:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:103:13:103:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:103:13:103:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:103:17:103:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:103:17:103:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:103:17:103:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:103:18:103:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:103:21:103:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:103:25:103:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:104:13:104:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:19:104:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:29:104:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:104:29:104:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:104:29:104:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:109:40:109:40 | f | | closure.rs:109:20:109:37 | F | | closure.rs:109:46:111:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:110:13:110:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:110:23:110:23 | f | | closure.rs:109:20:109:37 | F | | closure.rs:110:23:110:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:110:24:110:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:110:24:110:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:110:25:110:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:113:41:113:41 | f | | closure.rs:113:28:113:38 | F | | closure.rs:113:47:115:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:114:13:114:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:114:23:114:23 | f | | closure.rs:113:28:113:38 | F | | closure.rs:114:23:114:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:114:24:114:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:114:24:114:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:114:25:114:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:117:42:117:42 | f | | closure.rs:117:22:117:39 | F | | closure.rs:117:48:120:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6391,63 +6508,62 @@ inferType | closure.rs:118:19:118:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:119:9:119:9 | f | | closure.rs:117:22:117:39 | F | | closure.rs:119:9:119:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:119:10:119:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:119:10:119:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:119:11:119:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:122:35:122:35 | f | | closure.rs:122:20:122:32 | F | | closure.rs:122:41:122:41 | a | | closure.rs:122:14:122:14 | A | | closure.rs:122:52:124:5 | { ... } | | closure.rs:122:17:122:17 | B | | closure.rs:123:9:123:9 | f | | closure.rs:122:20:122:32 | F | | closure.rs:123:9:123:12 | f(...) | | closure.rs:122:17:122:17 | B | +| closure.rs:123:10:123:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:123:10:123:12 | ArgList | T0 | closure.rs:122:14:122:14 | A | | closure.rs:123:11:123:11 | a | | closure.rs:122:14:122:14 | A | | closure.rs:126:18:126:18 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:126:49:128:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:127:9:127:9 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:127:9:127:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:127:10:127:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:127:10:127:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:127:11:127:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:127:11:127:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:130:15:142:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:131:13:131:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:131:13:131:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:131:13:131:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:131:13:131:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:131:13:131:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:131:17:137:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:131:17:137:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:131:18:131:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:131:34:137:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:131:34:137:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:132:13:136:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:132:13:136:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:132:16:132:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:132:18:134:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:132:18:134:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:133:17:133:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:133:17:133:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:134:20:136:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:134:20:136:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:135:17:135:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:135:17:135:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:138:13:138:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:138:13:138:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:138:18:138:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:138:18:138:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:138:24:138:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:138:24:138:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:138:24:138:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:138:24:138:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:138:24:138:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:138:27:138:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:140:13:140:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:140:13:140:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:140:13:140:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:140:17:140:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:140:17:140:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:140:17:140:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:140:18:140:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:140:21:140:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:140:25:140:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:141:13:141:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:19:141:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:29:141:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:141:29:141:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:141:29:141:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:146:54:146:54 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:146:54:146:54 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:146:54:146:54 | f | T | closure.rs:146:26:146:51 | F | @@ -6457,7 +6573,8 @@ inferType | closure.rs:147:9:147:9 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:147:9:147:9 | f | T | closure.rs:146:26:146:51 | F | | closure.rs:147:9:147:14 | f(...) | | closure.rs:146:23:146:23 | B | -| closure.rs:147:9:147:14 | f(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:147:10:147:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:147:10:147:14 | ArgList | T0 | closure.rs:146:20:146:20 | A | | closure.rs:147:11:147:13 | arg | | closure.rs:146:20:146:20 | A | | closure.rs:150:30:150:30 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:150:30:150:30 | f | A | {EXTERNAL LOCATION} | Global | @@ -6496,12 +6613,16 @@ inferType | closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | | closure.rs:158:9:158:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:10:158:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:158:10:158:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | | closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | | closure.rs:162:9:162:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:10:162:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:162:10:162:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | | closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | @@ -6515,14 +6636,17 @@ inferType | closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | -| closure.rs:166:9:166:12 | f(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | | closure.rs:166:9:166:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:10:166:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:10:166:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | | closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | | closure.rs:170:9:170:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:10:170:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:170:10:170:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | | closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | @@ -6536,60 +6660,99 @@ inferType | closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | -| closure.rs:174:9:174:12 | f(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | | closure.rs:174:9:174:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:10:174:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:10:174:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | | closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | | closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | | closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | | closure.rs:178:9:178:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:10:178:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:178:10:178:12 | ArgList | T0 | closure.rs:177:15:177:15 | T | | closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | | closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | | closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | | closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | | closure.rs:182:9:182:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:10:182:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:182:10:182:12 | ArgList | T0 | closure.rs:181:15:181:15 | T | | closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | | closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:186:13:186:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:186:13:186:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:186:13:186:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:13:186:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:186:17:186:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:186:17:186:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:18:186:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:21:186:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | | closure.rs:187:18:187:32 | apply1(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:187:25:187:25 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:187:25:187:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:187:25:187:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:187:28:187:31 | 1i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:189:13:189:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:189:13:189:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:189:13:189:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:189:17:189:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:189:17:189:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:18:189:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:21:189:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:190:13:190:14 | _r | | {EXTERNAL LOCATION} | i64 | | closure.rs:190:18:190:32 | apply2(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:190:25:190:25 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:190:25:190:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:190:25:190:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:190:28:190:31 | 2i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:192:13:192:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:192:13:192:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:192:13:192:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:192:17:192:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:192:17:192:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:18:192:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:21:192:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:193:13:193:14 | _r | | {EXTERNAL LOCATION} | i64 | | closure.rs:193:18:193:33 | apply3(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:193:25:193:26 | &f | | {EXTERNAL LOCATION} | & | | closure.rs:193:25:193:26 | &f | TRef | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:193:25:193:26 | &f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:193:26:193:26 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:193:26:193:26 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:26:193:26 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:26:193:26 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:193:29:193:32 | 3i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:195:13:195:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:195:13:195:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:195:13:195:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:195:17:195:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:195:17:195:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:18:195:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:21:195:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:196:13:196:14 | _r | | {EXTERNAL LOCATION} | i64 | | closure.rs:196:18:196:32 | apply4(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:196:25:196:25 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:196:25:196:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:196:25:196:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:196:28:196:31 | 4i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:198:17:198:17 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:198:17:198:17 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | @@ -6605,21 +6768,37 @@ inferType | closure.rs:199:33:199:36 | 5i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:201:13:201:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:201:13:201:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:201:13:201:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:201:17:201:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:201:17:201:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:18:201:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:21:201:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:202:13:202:14 | _r | | {EXTERNAL LOCATION} | i64 | | closure.rs:202:18:202:32 | apply6(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:202:25:202:25 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:202:25:202:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:202:25:202:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:202:28:202:31 | 6i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:204:13:204:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:204:13:204:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:204:13:204:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:204:17:204:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:204:17:204:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:18:204:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:21:204:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:205:13:205:14 | _r | | {EXTERNAL LOCATION} | i64 | | closure.rs:205:18:205:32 | apply7(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:205:25:205:25 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:205:25:205:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:205:25:205:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:205:28:205:31 | 7i64 | | {EXTERNAL LOCATION} | i64 | | closure.rs:217:18:217:22 | SelfParam | | {EXTERNAL LOCATION} | & | | closure.rs:217:18:217:22 | SelfParam | TRef | closure.rs:212:5:212:19 | S | @@ -6643,37 +6822,72 @@ inferType | closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:224:13:224:13 | v | | {EXTERNAL LOCATION} | i64 | +| closure.rs:224:17:224:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:225:13:225:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:225:13:225:13 | s | T | {EXTERNAL LOCATION} | i64 | | closure.rs:225:17:225:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:225:17:225:20 | S(...) | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:19:225:19 | v | | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:13:226:16 | _ret | | {EXTERNAL LOCATION} | bool | | closure.rs:226:20:226:20 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:226:20:226:20 | s | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:20:226:23 | s(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:226:21:226:23 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:226:21:226:23 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | | closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:229:13:229:13 | v | | {EXTERNAL LOCATION} | i32 | +| closure.rs:229:17:229:34 | ...::default(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:230:13:230:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:230:13:230:13 | s | T | {EXTERNAL LOCATION} | i32 | | closure.rs:230:17:230:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:230:17:230:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:19:230:19 | v | | {EXTERNAL LOCATION} | i32 | | closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | | closure.rs:231:13:231:17 | s_ref | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:13:231:17 | s_ref | TRef.T | {EXTERNAL LOCATION} | i32 | | closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | | closure.rs:231:21:231:22 | &s | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:21:231:22 | &s | TRef.T | {EXTERNAL LOCATION} | i32 | | closure.rs:231:22:231:22 | s | | closure.rs:212:5:212:19 | S | -| closure.rs:232:13:232:16 | _ret | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:231:22:231:22 | s | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:13:232:16 | _ret | | {EXTERNAL LOCATION} | bool | | closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | | closure.rs:232:20:232:24 | s_ref | TRef | closure.rs:212:5:212:19 | S | -| closure.rs:232:20:232:27 | s_ref(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:232:20:232:24 | s_ref | TRef.T | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:20:232:27 | s_ref(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:232:25:232:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:232:25:232:27 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | | closure.rs:238:13:238:13 | c | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:238:13:238:13 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:238:13:238:13 | c | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:238:17:238:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:238:17:238:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:18:238:18 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:21:238:21 | x | | {EXTERNAL LOCATION} | i32 | | closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | | closure.rs:239:9:239:12 | (...) | TRef | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:239:9:239:12 | (...) | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | -| closure.rs:239:9:239:15 | ...(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:15 | ...(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | | closure.rs:239:10:239:11 | &c | TRef | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:239:10:239:11 | &c | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:239:11:239:11 | c | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:239:11:239:11 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:11:239:11 | c | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:11:239:11 | c | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:13:239:15 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:13:239:15 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | @@ -9748,14 +9962,21 @@ inferType | main.rs:1341:28:1341:41 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1341:28:1341:41 | ...::Ok(...) | T | main.rs:1317:5:1318:14 | S1 | | main.rs:1341:39:1341:40 | S1 | | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:13:1343:13 | y | | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:17 | x | | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:17 | x | T | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:17 | x | T.T | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:18 | TryExpr | | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:18 | TryExpr | T | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:29 | ... .map(...) | | {EXTERNAL LOCATION} | Result | +| main.rs:1343:17:1343:29 | ... .map(...) | T | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:17:1343:30 | TryExpr | | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:24:1343:28 | \|...\| s | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1343:24:1343:28 | \|...\| s | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:1343:24:1343:28 | \|...\| s | dyn(Args).T0 | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:24:1343:28 | \|...\| s | dyn(Output) | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:25:1343:25 | s | | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:28:1343:28 | s | | main.rs:1317:5:1318:14 | S1 | | main.rs:1344:9:1344:22 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1344:9:1344:22 | ...::Ok(...) | E | main.rs:1320:5:1321:14 | S2 | | main.rs:1344:9:1344:22 | ...::Ok(...) | T | main.rs:1317:5:1318:14 | S1 | @@ -9771,26 +9992,36 @@ inferType | main.rs:1350:21:1350:25 | input | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1350:21:1350:25 | input | T | main.rs:1349:20:1349:27 | T | | main.rs:1350:21:1350:26 | TryExpr | | main.rs:1349:20:1349:27 | T | +| main.rs:1351:13:1351:18 | mapped | | main.rs:1349:20:1349:27 | T | | main.rs:1351:22:1351:38 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1351:22:1351:38 | ...::Ok(...) | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1351:22:1351:38 | ...::Ok(...) | T | main.rs:1349:20:1349:27 | T | | main.rs:1351:22:1354:10 | ... .and_then(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1351:22:1354:10 | ... .and_then(...) | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:22:1354:10 | ... .and_then(...) | T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:22:1354:11 | TryExpr | | main.rs:1349:20:1349:27 | T | | main.rs:1351:33:1351:37 | value | | main.rs:1349:20:1349:27 | T | | main.rs:1351:49:1354:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:1351:49:1354:9 | \|...\| ... | dyn(Args).T0 | main.rs:1349:20:1349:27 | T | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | Result | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output).E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output).T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:50:1351:50 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1351:53:1354:9 | { ... } | | {EXTERNAL LOCATION} | Result | | main.rs:1351:53:1354:9 | { ... } | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:53:1354:9 | { ... } | T | main.rs:1349:20:1349:27 | T | | main.rs:1352:13:1352:31 | MacroExpr | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:27 | "{:?}\\n" | | {EXTERNAL LOCATION} | & | | main.rs:1352:22:1352:27 | "{:?}\\n" | TRef | {EXTERNAL LOCATION} | str | | main.rs:1352:22:1352:30 | ...::_print(...) | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:30 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:30 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:1352:30:1352:30 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | T | main.rs:1349:20:1349:27 | T | +| main.rs:1353:33:1353:33 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1355:9:1355:23 | ...::Err(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1355:9:1355:23 | ...::Err(...) | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1355:9:1355:23 | ...::Err(...) | T | main.rs:1349:20:1349:27 | T | @@ -11361,14 +11592,21 @@ inferType | main.rs:2261:25:2261:25 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2261:28:2261:29 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2262:9:2262:44 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2262:13:2262:13 | i | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:18:2262:26 | [...] | | {EXTERNAL LOCATION} | [;] | | main.rs:2262:18:2262:26 | [...] | TArray | {EXTERNAL LOCATION} | i32 | | main.rs:2262:18:2262:41 | ... .map(...) | | {EXTERNAL LOCATION} | [;] | +| main.rs:2262:18:2262:41 | ... .map(...) | TArray | {EXTERNAL LOCATION} | i32 | | main.rs:2262:19:2262:19 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:22:2262:22 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:25:2262:25 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:32:2262:40 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:2262:32:2262:40 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:2262:32:2262:40 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:32:2262:40 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:33:2262:33 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:36:2262:36 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:36:2262:40 | ... + ... | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:40:2262:40 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:43:2262:44 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2263:9:2263:41 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | @@ -12625,13 +12863,20 @@ inferType | main.rs:2775:13:2775:16 | self | TRef.T | main.rs:2773:10:2773:17 | GT | | main.rs:2775:13:2775:18 | self.0 | | main.rs:2773:10:2773:17 | GT | | main.rs:2779:15:2783:5 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2780:13:2780:13 | v | | {EXTERNAL LOCATION} | i64 | +| main.rs:2780:17:2780:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | | main.rs:2781:13:2781:13 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2781:13:2781:13 | g | T | {EXTERNAL LOCATION} | i64 | | main.rs:2781:17:2781:22 | Gen(...) | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2781:17:2781:22 | Gen(...) | T | {EXTERNAL LOCATION} | i64 | +| main.rs:2781:21:2781:21 | v | | {EXTERNAL LOCATION} | i64 | | main.rs:2782:13:2782:13 | _ | | {EXTERNAL LOCATION} | bool | | main.rs:2782:17:2782:26 | my_get(...) | | {EXTERNAL LOCATION} | bool | | main.rs:2782:24:2782:25 | &g | | {EXTERNAL LOCATION} | & | | main.rs:2782:24:2782:25 | &g | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:24:2782:25 | &g | TRef.T | {EXTERNAL LOCATION} | i64 | | main.rs:2782:25:2782:25 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:25:2782:25 | g | T | {EXTERNAL LOCATION} | i64 | | main.rs:2786:11:2821:1 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2787:5:2787:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | | main.rs:2788:5:2788:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 87f4e659d8c4..083875a978bc 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -1025,9 +1025,17 @@ module Make1 Input1> { pragma[inline] private predicate satisfiesConstraintTypeMentionInline( Term term, Constraint constraint, TypeAbstraction abs, TypePath path, - TypePath pathToTypeParamInSub + TypePath pathToTypeParamInSub, TypeParameter tp ) { - exists(TypeMention sub, TypeParameter tp | + exists(TypeMention sub | + // `impl From> for Option {` + // ^^^^^^^^^ sub + // ^^^^^^^^^^ constraintMention + // ^ tp + // `pathToTypeParamInSub` = `T_option`. + // `path` = `T_From.T_S`. + // `constraint` = `trait From`. + // satisfiesConstraintTypeMention1(term, constraint, abs, sub, path, tp) and tp = abs.getATypeParameter() and sub.getTypeAt(pathToTypeParamInSub) = tp @@ -1038,7 +1046,7 @@ module Make1 Input1> { private predicate satisfiesConstraintTypeMention( Term term, Constraint constraint, TypePath path, TypePath pathToTypeParamInSub ) { - satisfiesConstraintTypeMentionInline(term, constraint, _, path, pathToTypeParamInSub) + satisfiesConstraintTypeMentionInline(term, constraint, _, path, pathToTypeParamInSub, _) } pragma[nomagic] @@ -1046,7 +1054,7 @@ module Make1 Input1> { Term term, Constraint constraint, TypeAbstraction abs, TypePath path, TypePath pathToTypeParamInSub ) { - satisfiesConstraintTypeMentionInline(term, constraint, abs, path, pathToTypeParamInSub) + satisfiesConstraintTypeMentionInline(term, constraint, abs, path, pathToTypeParamInSub, _) } pragma[inline] @@ -1099,6 +1107,19 @@ module Make1 Input1> { ) } + pragma[nomagic] + predicate test( + // Term tt, TypePath pathToTypeParamInSub, TypeAbstraction abs, Type constraint, + // TypeParameter tp, TypePath path + Term term, Constraint constraint, TypeAbstraction abs, TypePath path, + TypePath pathToTypeParamInSub, TypeParameter tp + ) { + // Term term, Constraint constraint, TypeAbstraction abs, TypePath path, + // TypePath pathToTypeParamInSub, TypeParameter tp + satisfiesConstraintTypeMentionInline(term, constraint, abs, path, pathToTypeParamInSub, tp) + // satisfiesConstraintTypeMentionInline(tt, abs, constraint, path, pathToTypeParamInSub, tp) + } + /** * Holds if the type tree at `term` does _not_ satisfy the constraint `constraint`. * @@ -1379,8 +1400,19 @@ module Make1 Input1> { Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath path, TypeMention constraint ) { + // fn apply6(f: impl Fn(T) -> i64, a: T) -> i64 { + // + // apos = 0 + // constraint = trait Fn + // pathToTp = Args.T0 + // tp = T + // exists(TypePath pathToTp, TypeParameter tp | + // target = a.getTarget(e) and + // typeParameterConstraintHasTypeParameter(target, apos, path, constraint, pathToTp, tp) + // ) + // or target = a.getTarget(e) and - typeParameterConstraintHasTypeParameter(target, apos, path, constraint, _, _) + typeParameterConstraintHasAny(target, apos, _, path, constraint) } private newtype TRelevantAccess = @@ -1435,6 +1467,31 @@ module Make1 Input1> { constraint = ra.getConstraint(target) ) } + + predicate satisfiesConstraintTypeThrough( + Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, + TypeAbstraction abs, TypeMention constraint, TypePath path, Type t + ) { + exists(RelevantAccess ra | + ra = MkRelevantAccess(a, apos, e, prefix) and + SatisfiesConstraint::satisfiesConstraintTypeThrough(ra, + abs, constraint, path, t) and + constraint = ra.getConstraint(target) + ) + } + + predicate test( + Access a, TypePath pathToTypeParamInSub, AccessEnvironment e, Declaration target, + AccessPosition apos, TypePath prefix, TypeAbstraction abs, TypeMention constraint, + TypeParameter tp, TypePath path + ) { + exists(RelevantAccess ra | + ra = MkRelevantAccess(a, apos, e, prefix) and + SatisfiesConstraint::test(ra, + constraint, abs, path, pathToTypeParamInSub, tp) and + constraint = ra.getConstraint(target) + ) + } } /** @@ -1554,6 +1611,19 @@ module Make1 Input1> { ) } + pragma[nomagic] + private predicate typeParameterConstraintHasAny( + Declaration target, AccessPosition apos, TypeParameter constrainedTp, + TypePath pathToConstrained, TypeMention constraint + ) { + exists(DeclarationPosition dpos | + accessDeclarationPositionMatch(apos, dpos) and + constrainedTp = target.getTypeParameter(_) and + constrainedTp = target.getDeclaredType(dpos, pathToConstrained) and + constraint = getATypeParameterConstraint(constrainedTp) + ) + } + pragma[nomagic] private predicate typeConstraintBaseTypeMatch( Access a, AccessEnvironment e, Declaration target, TypePath path, Type t, TypeParameter tp @@ -1566,6 +1636,74 @@ module Make1 Input1> { ) } + pragma[nomagic] + private predicate test3( + Access a, AccessPosition apos, AccessEnvironment e, Declaration target, TypePath path, + Type t, TypeParameter tp + ) { + // not exists(getTypeArgument(a, target, tp, _)) and + exists( + TypeAbstraction abs, TypeMention constraint, TypePath pathToTypeParamInSub, + TypePath pathToTp, TypePath pathToTp2, TypePath suffix, TypeParameter tp2, TypePath path3, + TypePath path4, TypePath prefix //, TypeMention constraint2, AccessPosition apos2, + | + // TypePath pathToTp3, TypePath pathToTp4, TypeAbstraction abs2 + // a.getLocation().getStartLine() = 24 and + // tp = T + // pathToTp = Args.T0 + // pathToTp2 = "" + // constraint = trait Fn + // directTypeMatch(a, e, target, suffix, t, tp) and + // typeParameterConstraintHasTypeParameter(target, apos2, pathToTp4, constraint2, pathToTp3, + // tp) and + // AccessConstraint::satisfiesConstraintTypeThrough(a, e, target, apos2, pathToTp4, abs2, + // constraint2, pathToTp3.appendInverse(suffix), t) and + typeMatch(a, e, target, suffix, t, tp) and + // typeConstraintBaseTypeMatch(a, e, target, path, t, tp) and + typeParameterConstraintHasTypeParameter(target, apos, pathToTp2, constraint, pathToTp, tp) and + AccessConstraint::test(a, pathToTypeParamInSub, e, target, apos, prefix, abs, + /*TODO*/ constraint, tp2, path4) and + pathToTp = path4.appendInverse(path3) and + path = prefix.append(pathToTypeParamInSub.append(path3).append(suffix)) + // AccessConstraint::test(a, pathToTypeParamInSub, e, target, apos, _, /*TODO*/ constraint, + // tp) and + // path = pathToTypeParamInSub.append(suffix) + // satisfiesConstraintType(a, e, target, apos, pathToTp2, constraint, pathToTp.appendInverse(path), t) + ) + } + + pragma[nomagic] + private predicate test5( + Access a, AccessPosition apos, AccessEnvironment e, Declaration target, TypePath path, + Type t + ) { + // not exists(getTypeArgument(a, target, tp, _)) and + exists( + TypeMention constraint, TypePath pathToTypeParamInSub, TypePath pathToT, + TypeParameter tp2, TypePath path4, TypePath prefix, TypeParameter constrainedTp, + TypePath suffix + | + // tp2 = Args[Fn] + // pathToTypeParamInSub = dyn(Args) + // path4 = Args + // prefix = "" + // constraint = trait FnMut + AccessConstraint::test(a, pathToTypeParamInSub, e, target, apos, prefix, /*TODO*/ _, + constraint, tp2, path4) and + typeParameterConstraintHasAny(target, apos, constrainedTp, _, constraint) and + constraint = getATypeParameterConstraint(constrainedTp) and + t = constraint.getTypeAt(pathToT) and + // constraint = getATypeParameterConstraint(constrainedTp, TypePath::nil()) and + not t instanceof TypeParameter and + pathToT = path4.appendInverse(suffix) and + path = prefix.append(pathToTypeParamInSub.append(suffix)) + // AccessConstraint::test(a, pathToTypeParamInSub, e, target, apos, _, /*TODO*/ constraint, + // tp) and + // path = pathToTypeParamInSub.append(suffix) + // satisfiesConstraintType(a, e, target, apos, pathToTp2, constraint, pathToTp.appendInverse(path), t) + ) + } + pragma[inline] private predicate typeMatch( Access a, AccessEnvironment e, Declaration target, TypePath path, Type t, TypeParameter tp @@ -1639,6 +1777,10 @@ module Make1 Input1> { not result instanceof TypeParameter ) ) + or + test3(a, apos, e, _, path, result, _) + or + test5(a, apos, e, _, path, result) } }