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:
bors[bot]
2019-07-09 07:50:18 +00:00
11 changed files with 286 additions and 119 deletions

View File

@@ -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();