Skip to content

Commit 6219354

Browse files
committed
Rust: Add additional tests for associated types
1 parent fd5658d commit 6219354

File tree

2 files changed

+621
-392
lines changed

2 files changed

+621
-392
lines changed

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ trait GetSet {
2626
fn set(&self, _a: Self::Output) {}
2727
}
2828

29+
fn get<O, T: GetSet<Output = O> + ?Sized>(item: &T) -> O {
30+
item.get() // $ target=GetSet::get
31+
}
32+
2933
trait AnotherGet: GetSet {
3034
type AnotherOutput;
3135

@@ -124,6 +128,55 @@ mod type_param_access_associated_type {
124128
}
125129
}
126130

131+
// Tests for specifying associated types using equalities, e.g., `Trait<AssocType = Type>`
132+
mod equality_on_associated_type {
133+
use super::*;
134+
135+
fn _in_same_trait<T>(x: T)
136+
where
137+
T: GetSet<Output = char>,
138+
{
139+
let _a = x.get(); // $ target=GetSet::get type=_a:char
140+
}
141+
142+
// Here we specify `Output` from `GetSet` through the subtrait `AnotherGet`.
143+
fn _in_subtrait<T>(x: T)
144+
where
145+
T: AnotherGet<Output = i32, AnotherOutput = bool>,
146+
{
147+
let _a1 = x.get(); // $ target=GetSet::get MISSING: type=_a1:i32
148+
let _a2 = get(&x); // $ target=get MISSING: type=_a2:i32
149+
let _b = x.get_another(); // $ type=_b:bool target=AnotherGet::get_another
150+
}
151+
152+
// Here we specify the associated types as two separate trait bounds
153+
fn _two_bounds<T>(x: T)
154+
where
155+
T: AnotherGet<AnotherOutput = bool>,
156+
T: GetSet<Output = i32>,
157+
{
158+
let _a1 = x.get(); // $ target=GetSet::get type=_a1:i32
159+
let _a2 = get(&x); // $ target=get type=_a2:i32
160+
let _b = x.get_another(); // $ type=_b:bool target=AnotherGet::get_another
161+
}
162+
163+
trait AssocNameClash: GetSet {
164+
type Output; // This name clashes with GetSet::Output
165+
166+
// AssocNameClash::get2
167+
fn get2(&self) -> <Self as AssocNameClash>::Output;
168+
}
169+
170+
fn _two_bounds_name_clash<T>(x: T)
171+
where
172+
T: AssocNameClash<Output = char>,
173+
T: GetSet<Output = i32>,
174+
{
175+
let _a = x.get(); // $ type=_a:i32 target=GetSet::get
176+
let _b = x.get2(); // $ target=AssocNameClash::get2 MISSING: type=_b:char
177+
}
178+
}
179+
127180
mod generic_associated_type {
128181
use super::*;
129182

@@ -278,6 +331,29 @@ mod generic_associated_type_name_clash {
278331
}
279332
}
280333

334+
// Tests for associated types in `dyn` trait objects
335+
mod dyn_trait {
336+
use super::*;
337+
338+
fn _assoc_type_from_trait(t: &dyn GetSet<Output = i32>) {
339+
// Explicit deref
340+
let _a1 = (*t).get(); // $ target=deref target=GetSet::get type=_a1:i32
341+
342+
// Auto-deref
343+
let _a2 = t.get(); // $ target=GetSet::get type=_a2:i32
344+
345+
let _a3 = get(t); // $ target=get type=_a3:i32
346+
}
347+
348+
fn _assoc_type_from_supertrait(t: &dyn AnotherGet<Output = i32, AnotherOutput = bool>) {
349+
let _a1 = (*t).get(); // $ target=deref target=GetSet::get MISSING: type=_a1:i32
350+
let _a2 = t.get(); // $ target=GetSet::get MISSING: type=_a2:i32
351+
let _a3 = get(t); // $ target=get MISSING: type=_a3:i32
352+
let _b1 = (*t).get_another(); // $ target=deref target=AnotherGet::get_another type=_b1:bool
353+
let _b2 = t.get_another(); // $ target=AnotherGet::get_another type=_b2:bool
354+
}
355+
}
356+
281357
pub fn test() {
282358
default_method_using_associated_type::test(); // $ target=test
283359
type_param_access_associated_type::test(); // $ target=test

0 commit comments

Comments
 (0)