Add a bunch of tests for type inference involving traits

None of them works correctly yet, of course.
This commit is contained in:
Florian Diebold 2019-03-02 14:53:26 +01:00
parent 00b09bcd8c
commit b7fdad8448
13 changed files with 403 additions and 0 deletions

View file

@ -0,0 +1,10 @@
---
created: "2019-03-02T13:52:02.767222917Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[67; 100) '{ ...own; }': ()
[77; 78) 'y': [unknown]
[90; 97) 'unknown': [unknown]

View file

@ -0,0 +1,11 @@
---
created: "2019-03-02T13:49:53.509955706Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[59; 60) 't': T
[65; 84) '{ ...d(); }': ()
[71; 72) 't': T
[71; 81) 't.method()': [unknown]

View file

@ -0,0 +1,11 @@
---
created: "2019-03-02T13:49:53.477633667Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[66; 67) 't': T
[72; 91) '{ ...d(); }': ()
[78; 79) 't': T
[78; 88) 't.method()': [unknown]

View file

@ -0,0 +1,17 @@
---
created: "2019-03-02T13:49:53.558635265Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[86; 87) 't': T
[92; 94) '{}': ()
[105; 144) '{ ...(s); }': ()
[115; 116) 's': S<[unknown]>
[119; 120) 'S': S<[unknown]>(T) -> S<T>
[119; 129) 'S(unknown)': S<[unknown]>
[121; 128) 'unknown': [unknown]
[135; 138) 'foo': fn foo<S<[unknown]>>(T) -> ()
[135; 141) 'foo(s)': ()
[139; 140) 's': S<[unknown]>

View file

@ -0,0 +1,18 @@
---
created: "2019-03-02T13:49:53.572131028Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[87; 88) 't': T
[98; 100) '{}': ()
[111; 163) '{ ...(s); }': ()
[121; 122) 's': S<[unknown]>
[125; 126) 'S': S<[unknown]>(T) -> S<T>
[125; 135) 'S(unknown)': S<[unknown]>
[127; 134) 'unknown': [unknown]
[145; 146) 'x': u32
[154; 157) 'foo': fn foo<u32, S<[unknown]>>(T) -> U
[154; 160) 'foo(s)': u32
[158; 159) 's': S<[unknown]>

View file

@ -0,0 +1,12 @@
---
created: "2019-03-02T13:49:53.680954394Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[108; 181) '{ ...ter; }': ()
[118; 119) 'x': i32
[145; 146) '1': i32
[156; 157) 'y': [unknown]
[169; 178) 'no_matter': [unknown]

View file

@ -0,0 +1,17 @@
---
created: "2019-03-02T13:49:53.756157395Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[87; 193) '{ ...t(); }': ()
[97; 99) 's1': S
[105; 121) 'Defaul...efault': [unknown]
[105; 123) 'Defaul...ault()': S
[133; 135) 's2': [unknown]
[138; 148) 'S::default': [unknown]
[138; 150) 'S::default()': [unknown]
[160; 162) 's3': [unknown]
[165; 188) '<S as ...efault': [unknown]
[165; 190) '<S as ...ault()': [unknown]

View file

@ -0,0 +1,11 @@
---
created: "2019-03-02T13:49:53.771466423Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[33; 37) 'self': &[unknown]
[92; 111) '{ ...d(); }': ()
[98; 99) 'S': S
[98; 108) 'S.method()': [unknown]

View file

@ -0,0 +1,13 @@
---
created: "2019-03-02T13:49:53.765202736Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[33; 37) 'self': &[unknown]
[102; 127) '{ ...d(); }': ()
[108; 109) 'S': S<u32>(T) -> S<T>
[108; 115) 'S(1u32)': S<u32>
[108; 124) 'S(1u32...thod()': [unknown]
[110; 114) '1u32': u32

View file

@ -0,0 +1,15 @@
---
created: "2019-03-02T15:41:07.568155273Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[63; 67) 'self': &[unknown]
[169; 173) 'self': &[unknown]
[300; 337) '{ ... }': ()
[310; 311) 'S': S
[310; 320) 'S.method()': [unknown]
[416; 454) '{ ... }': ()
[426; 427) 'S': S
[426; 436) 'S.method()': [unknown]

View file

@ -0,0 +1,14 @@
---
created: "2019-03-02T15:41:07.562949721Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[31; 35) 'self': &[unknown]
[110; 114) 'self': &[unknown]
[170; 228) '{ ...i128 }': ()
[176; 178) 'S1': S1
[176; 187) 'S1.method()': [unknown]
[203; 205) 'S2': S2
[203; 214) 'S2.method()': [unknown]

View file

@ -0,0 +1,19 @@
---
created: "2019-03-02T13:49:53.860659428Z"
creator: insta@0.6.3
source: crates/ra_hir/src/ty/tests.rs
expression: "&result"
---
[29; 33) 'self': [unknown]
[107; 198) '{ ...(S); }': ()
[117; 118) 'x': u32
[126; 127) 'S': S
[126; 134) 'S.into()': u32
[144; 145) 'y': u64
[153; 154) 'S': S
[153; 161) 'S.into()': u64
[171; 172) 'z': [unknown]
[175; 192) 'Into::...::into': [unknown]
[175; 195) 'Into::...nto(S)': [unknown]
[193; 194) 'S': S

View file

@ -1043,6 +1043,241 @@ fn test() {
); );
} }
#[test]
fn infer_trait_method_simple() {
// the trait implementation is intentionally incomplete -- it shouldn't matter
check_inference(
"infer_trait_method_simple",
r#"
trait Trait1 {
fn method(&self) -> u32;
}
struct S1;
impl Trait1 for S1 {}
trait Trait2 {
fn method(&self) -> i128;
}
struct S2;
impl Trait2 for S2 {}
fn test() {
S1.method(); // -> u32
S2.method(); // -> i128
}
"#,
);
}
#[test]
fn infer_trait_method_scoped() {
// the trait implementation is intentionally incomplete -- it shouldn't matter
check_inference(
"infer_trait_method_scoped",
r#"
struct S;
mod foo {
pub trait Trait1 {
fn method(&self) -> u32;
}
impl Trait1 for super::S {}
}
mod bar {
pub trait Trait2 {
fn method(&self) -> i128;
}
impl Trait2 for super::S {}
}
mod foo_test {
use super::S;
use super::foo::Trait1;
fn test() {
S.method(); // -> u32
}
}
mod bar_test {
use super::S;
use super::bar::Trait2;
fn test() {
S.method(); // -> i128
}
}
"#,
);
}
#[test]
fn infer_trait_method_generic_1() {
// the trait implementation is intentionally incomplete -- it shouldn't matter
check_inference(
"infer_trait_method_generic_1",
r#"
trait Trait<T> {
fn method(&self) -> T;
}
struct S;
impl Trait<u32> for S {}
fn test() {
S.method();
}
"#,
);
}
#[test]
fn infer_trait_method_generic_2() {
// the trait implementation is intentionally incomplete -- it shouldn't matter
check_inference(
"infer_trait_method_generic_2",
r#"
trait Trait<T> {
fn method(&self) -> T;
}
struct S<T>(T);
impl<U> Trait<U> for S<U> {}
fn test() {
S(1u32).method();
}
"#,
);
}
#[test]
fn infer_trait_assoc_method() {
check_inference(
"infer_trait_assoc_method",
r#"
trait Default {
fn default() -> Self;
}
struct S;
impl Default for S {}
fn test() {
let s1: S = Default::default();
let s2 = S::default();
let s3 = <S as Default>::default();
}
"#,
);
}
#[test]
fn infer_from_bound_1() {
check_inference(
"infer_from_bound_1",
r#"
trait Trait<T> {}
struct S<T>(T);
impl<U> Trait<U> for S<U> {}
fn foo<T: Trait<u32>>(t: T) {}
fn test() {
let s = S(unknown);
foo(s);
}
"#,
);
}
#[test]
fn infer_from_bound_2() {
check_inference(
"infer_from_bound_2",
r#"
trait Trait<T> {}
struct S<T>(T);
impl<U> Trait<U> for S<U> {}
fn foo<U, T: Trait<U>>(t: T) -> U {}
fn test() {
let s = S(unknown);
let x: u32 = foo(s);
}
"#,
);
}
#[test]
fn infer_call_trait_method_on_generic_param_1() {
check_inference(
"infer_call_trait_method_on_generic_param_1",
r#"
trait Trait {
fn method() -> u32;
}
fn test<T: Trait>(t: T) {
t.method();
}
"#,
);
}
#[test]
fn infer_call_trait_method_on_generic_param_2() {
check_inference(
"infer_call_trait_method_on_generic_param_2",
r#"
trait Trait<T> {
fn method() -> T;
}
fn test<U, T: Trait<U>>(t: T) {
t.method();
}
"#,
);
}
#[test]
fn infer_with_multiple_trait_impls() {
check_inference(
"infer_with_multiple_trait_impls",
r#"
trait Into<T> {
fn into(self) -> T;
}
struct S;
impl Into<u32> for S;
impl Into<u64> for S;
fn test() {
let x: u32 = S.into();
let y: u64 = S.into();
let z = Into::<u64>::into(S);
}
"#,
);
}
#[test]
fn infer_project_associated_type() {
check_inference(
"infer_project_associated_type",
r#"
trait Iterable {
type Item;
}
struct S;
impl Iterable for S { type Item = u32; }
fn test<T: Iterable>() {
let x: <S as Iterable>::Item = 1;
let y: T::Item = no_matter;
}
"#,
);
}
#[test]
fn infer_associated_type_bound() {
check_inference(
"infer_associated_type_bound",
r#"
trait Iterable {
type Item;
}
fn test<T: Iterable<Item=u32>>() {
let y: T::Item = unknown;
}
"#,
);
}
fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
let func = source_binder::function_from_position(db, pos).unwrap(); let func = source_binder::function_from_position(db, pos).unwrap();
let body_source_map = func.body_source_map(db); let body_source_map = func.body_source_map(db);