Merge #1515
1515: Trait environment r=matklad a=flodiebold
This adds the environment, i.e. the set of `where` clauses in scope, when solving trait goals. That means that e.g. in
```rust
fn foo<T: SomeTrait>(t: T) {}
```
, we are able to complete methods of `SomeTrait` on the `t`. This affects the trait APIs quite a bit (since every method that needs to be able to solve for some trait needs to get this environment somehow), so I thought I'd do it rather sooner than later ;)
Co-authored-by: Florian Diebold <flodiebold@gmail.com>
This commit is contained in:
@@ -3003,6 +3003,85 @@ fn test(o: O<S>) {
|
||||
assert_eq!(t, "&str");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_param_env_1() {
|
||||
let t = type_at(
|
||||
r#"
|
||||
//- /main.rs
|
||||
trait Clone {}
|
||||
trait Trait { fn foo(self) -> u128; }
|
||||
struct S;
|
||||
impl Clone for S {}
|
||||
impl<T> Trait for T where T: Clone {}
|
||||
fn test<T: Clone>(t: T) { t.foo()<|>; }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(t, "u128");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_param_env_1_not_met() {
|
||||
let t = type_at(
|
||||
r#"
|
||||
//- /main.rs
|
||||
trait Clone {}
|
||||
trait Trait { fn foo(self) -> u128; }
|
||||
struct S;
|
||||
impl Clone for S {}
|
||||
impl<T> Trait for T where T: Clone {}
|
||||
fn test<T>(t: T) { t.foo()<|>; }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(t, "{unknown}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_param_env_2() {
|
||||
let t = type_at(
|
||||
r#"
|
||||
//- /main.rs
|
||||
trait Trait { fn foo(self) -> u128; }
|
||||
struct S;
|
||||
impl Trait for S {}
|
||||
fn test<T: Trait>(t: T) { t.foo()<|>; }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(t, "u128");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_param_env_2_not_met() {
|
||||
let t = type_at(
|
||||
r#"
|
||||
//- /main.rs
|
||||
trait Trait { fn foo(self) -> u128; }
|
||||
struct S;
|
||||
impl Trait for S {}
|
||||
fn test<T>(t: T) { t.foo()<|>; }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(t, "{unknown}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generic_param_env_deref() {
|
||||
let t = type_at(
|
||||
r#"
|
||||
//- /main.rs
|
||||
#[lang = "deref"]
|
||||
trait Deref {
|
||||
type Target;
|
||||
}
|
||||
trait Trait {}
|
||||
impl<T> Deref for T where T: Trait {
|
||||
type Target = i128;
|
||||
}
|
||||
fn test<T: Trait>(t: T) { (*t)<|>; }
|
||||
"#,
|
||||
);
|
||||
assert_eq!(t, "i128");
|
||||
}
|
||||
|
||||
fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
|
||||
let file = db.parse(pos.file_id).ok().unwrap();
|
||||
let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user