Skip to content

Commit daeed4e

Browse files
committed
Rust: Add test with type inference inconsistency
1 parent a8a73eb commit daeed4e

File tree

4 files changed

+621
-514
lines changed

4 files changed

+621
-514
lines changed

rust/ql/lib/codeql/rust/internal/typeinference/TypeInferenceConsistency.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ query predicate illFormedTypeMention(TypeMention tm) {
3131
}
3232

3333
query predicate nonUniqueCertainType(AstNode n, TypePath path) {
34-
Consistency::nonUniqueCertainType(n, path, _)
34+
Consistency::nonUniqueCertainType(n, path, _) and
35+
n.fromSource() // Only include inconsistencies in the source.
3536
}
3637

3738
int getTypeInferenceInconsistencyCounts(string type) {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
nonUniqueCertainType
2+
| associated_types.rs:232:9:234:9 | { ... } | |

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

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,55 @@ mod concrete_type_access_associated_type {
192192
}
193193
}
194194

195+
// Tests a `<Type as Trait>::Assoc` type mention where the `Trait` type mention
196+
// contains a generic.
197+
//
198+
// In `convert` below the type of `<S as Trans<T>>::Output` depends on how
199+
// `convert` is called and thus the correct type cannot be determined when the
200+
// `TypeMention` is constructed.
201+
mod concrete_type_as_generic_access_associated_type {
202+
use super::*;
203+
204+
trait Trans<T> {
205+
type Output;
206+
fn through(t: T) -> Self::Output;
207+
}
208+
209+
impl Trans<bool> for S {
210+
type Output = i32;
211+
fn through(t: bool) -> Self::Output {
212+
if t {
213+
1
214+
} else {
215+
0
216+
}
217+
}
218+
}
219+
220+
impl Trans<i32> for S {
221+
type Output = bool;
222+
fn through(t: i32) -> Self::Output {
223+
t != 0 // $ target=ne
224+
}
225+
}
226+
227+
impl S {
228+
// S::convert
229+
fn convert<T>(&self, t: T) -> <S as Trans<T>>::Output
230+
where
231+
Self: Trans<T>,
232+
{
233+
S::through(t)
234+
}
235+
}
236+
237+
pub fn test() {
238+
let s = S;
239+
let _a = s.convert(true); // $ target=S::convert type=_a:i32 SPURIOUS: bool
240+
let _b = s.convert(42); // $ target=S::convert type=_b:bool SPURIOUS: i32
241+
}
242+
}
243+
195244
// Tests for signatures that access associated types on type parameters
196245
mod type_param_access_associated_type {
197246
use super::*;
@@ -468,6 +517,7 @@ mod dyn_trait {
468517
pub fn test() {
469518
default_method_using_associated_type::test(); // $ target=test
470519
concrete_type_access_associated_type::test(); // $ target=test
520+
concrete_type_as_generic_access_associated_type::test(); // $ target=test
471521
type_param_access_associated_type::test(); // $ target=test
472522
generic_associated_type::test(); // $ target=test
473523
multiple_associated_types::test(); // $ target=test

0 commit comments

Comments
 (0)