diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_type_alias.snap | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 35 |
4 files changed, 84 insertions, 10 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 13080b5aa..29331bea5 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -477,7 +477,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
477 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 477 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
478 | (ty, Some(var.into())) | 478 | (ty, Some(var.into())) |
479 | } | 479 | } |
480 | TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None), | 480 | TypableDef::Type(_) | TypableDef::Function(_) | TypableDef::Enum(_) => { |
481 | (Ty::Unknown, None) | ||
482 | } | ||
481 | } | 483 | } |
482 | } | 484 | } |
483 | 485 | ||
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 63e13a30e..a11d964c8 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -10,7 +10,7 @@ use std::sync::Arc; | |||
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, | 12 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, |
13 | ModuleDef, | 13 | ModuleDef, Type, |
14 | HirDatabase, | 14 | HirDatabase, |
15 | type_ref::TypeRef, | 15 | type_ref::TypeRef, |
16 | name::KnownName, | 16 | name::KnownName, |
@@ -109,7 +109,7 @@ impl Ty { | |||
109 | }; | 109 | }; |
110 | let ty = db.type_for_def(typable, Namespace::Types); | 110 | let ty = db.type_for_def(typable, Namespace::Types); |
111 | let substs = Ty::substs_from_path(db, resolver, path, typable); | 111 | let substs = Ty::substs_from_path(db, resolver, path, typable); |
112 | ty.apply_substs(substs) | 112 | ty.subst(&substs) |
113 | } | 113 | } |
114 | 114 | ||
115 | pub(super) fn substs_from_path_segment( | 115 | pub(super) fn substs_from_path_segment( |
@@ -124,6 +124,7 @@ impl Ty { | |||
124 | TypableDef::Struct(s) => s.generic_params(db), | 124 | TypableDef::Struct(s) => s.generic_params(db), |
125 | TypableDef::Enum(e) => e.generic_params(db), | 125 | TypableDef::Enum(e) => e.generic_params(db), |
126 | TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), | 126 | TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), |
127 | TypableDef::Type(t) => t.generic_params(db), | ||
127 | }; | 128 | }; |
128 | let parent_param_count = def_generics.count_parent_params(); | 129 | let parent_param_count = def_generics.count_parent_params(); |
129 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); | 130 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); |
@@ -159,9 +160,10 @@ impl Ty { | |||
159 | ) -> Substs { | 160 | ) -> Substs { |
160 | let last = path.segments.last().expect("path should have at least one segment"); | 161 | let last = path.segments.last().expect("path should have at least one segment"); |
161 | let segment = match resolved { | 162 | let segment = match resolved { |
162 | TypableDef::Function(_) => last, | 163 | TypableDef::Function(_) |
163 | TypableDef::Struct(_) => last, | 164 | | TypableDef::Struct(_) |
164 | TypableDef::Enum(_) => last, | 165 | | TypableDef::Enum(_) |
166 | | TypableDef::Type(_) => last, | ||
165 | TypableDef::EnumVariant(_) => { | 167 | TypableDef::EnumVariant(_) => { |
166 | // the generic args for an enum variant may be either specified | 168 | // the generic args for an enum variant may be either specified |
167 | // on the segment referring to the enum, or on the segment | 169 | // on the segment referring to the enum, or on the segment |
@@ -194,11 +196,13 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace | |||
194 | (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), | 196 | (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), |
195 | (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), | 197 | (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), |
196 | (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), | 198 | (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), |
199 | (TypableDef::Type(t), Namespace::Types) => type_for_type_alias(db, t), | ||
197 | 200 | ||
198 | // 'error' cases: | 201 | // 'error' cases: |
199 | (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, | 202 | (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, |
200 | (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, | 203 | (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, |
201 | (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, | 204 | (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, |
205 | (TypableDef::Type(_), Namespace::Values) => Ty::Unknown, | ||
202 | } | 206 | } |
203 | } | 207 | } |
204 | 208 | ||
@@ -264,7 +268,7 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> | |||
264 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 268 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
265 | .collect::<Vec<_>>(); | 269 | .collect::<Vec<_>>(); |
266 | let substs = make_substs(&generics); | 270 | let substs = make_substs(&generics); |
267 | let output = type_for_enum(db, def.parent_enum(db)).apply_substs(substs.clone()); | 271 | let output = type_for_enum(db, def.parent_enum(db)).subst(&substs); |
268 | let sig = Arc::new(FnSig { input, output }); | 272 | let sig = Arc::new(FnSig { input, output }); |
269 | Ty::FnDef { def: def.into(), sig, name, substs } | 273 | Ty::FnDef { def: def.into(), sig, name, substs } |
270 | } | 274 | } |
@@ -298,14 +302,24 @@ fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | |||
298 | } | 302 | } |
299 | } | 303 | } |
300 | 304 | ||
305 | fn type_for_type_alias(db: &impl HirDatabase, t: Type) -> Ty { | ||
306 | let generics = t.generic_params(db); | ||
307 | let resolver = t.resolver(db); | ||
308 | let type_ref = t.type_ref(db); | ||
309 | let substs = make_substs(&generics); | ||
310 | let inner = Ty::from_hir(db, &resolver, &type_ref); | ||
311 | inner.subst(&substs) | ||
312 | } | ||
313 | |||
301 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 314 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
302 | pub enum TypableDef { | 315 | pub enum TypableDef { |
303 | Function(Function), | 316 | Function(Function), |
304 | Struct(Struct), | 317 | Struct(Struct), |
305 | Enum(Enum), | 318 | Enum(Enum), |
306 | EnumVariant(EnumVariant), | 319 | EnumVariant(EnumVariant), |
320 | Type(Type), | ||
307 | } | 321 | } |
308 | impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); | 322 | impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, Type); |
309 | 323 | ||
310 | impl From<ModuleDef> for Option<TypableDef> { | 324 | impl From<ModuleDef> for Option<TypableDef> { |
311 | fn from(def: ModuleDef) -> Option<TypableDef> { | 325 | fn from(def: ModuleDef) -> Option<TypableDef> { |
@@ -314,11 +328,11 @@ impl From<ModuleDef> for Option<TypableDef> { | |||
314 | ModuleDef::Struct(s) => s.into(), | 328 | ModuleDef::Struct(s) => s.into(), |
315 | ModuleDef::Enum(e) => e.into(), | 329 | ModuleDef::Enum(e) => e.into(), |
316 | ModuleDef::EnumVariant(v) => v.into(), | 330 | ModuleDef::EnumVariant(v) => v.into(), |
331 | ModuleDef::Type(t) => t.into(), | ||
317 | ModuleDef::Const(_) | 332 | ModuleDef::Const(_) |
318 | | ModuleDef::Static(_) | 333 | | ModuleDef::Static(_) |
319 | | ModuleDef::Module(_) | 334 | | ModuleDef::Module(_) |
320 | | ModuleDef::Trait(_) | 335 | | ModuleDef::Trait(_) => return None, |
321 | | ModuleDef::Type(_) => return None, | ||
322 | }; | 336 | }; |
323 | Some(res) | 337 | Some(res) |
324 | } | 338 | } |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_type_alias.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_type_alias.snap new file mode 100644 index 000000000..241c08353 --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_type_alias.snap | |||
@@ -0,0 +1,23 @@ | |||
1 | --- | ||
2 | created: "2019-02-24T16:13:47.561870283Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&result" | ||
6 | --- | ||
7 | [117; 118) 'x': A<u32, i128> | ||
8 | [125; 126) 'y': A<&str, u128> | ||
9 | [139; 140) 'z': A<u8, i8> | ||
10 | [155; 212) '{ ...z.y; }': () | ||
11 | [161; 162) 'x': A<u32, i128> | ||
12 | [161; 164) 'x.x': u32 | ||
13 | [170; 171) 'x': A<u32, i128> | ||
14 | [170; 173) 'x.y': i128 | ||
15 | [179; 180) 'y': A<&str, u128> | ||
16 | [179; 182) 'y.x': &str | ||
17 | [188; 189) 'y': A<&str, u128> | ||
18 | [188; 191) 'y.y': u128 | ||
19 | [197; 198) 'z': A<u8, i8> | ||
20 | [197; 200) 'z.x': u8 | ||
21 | [206; 207) 'z': A<u8, i8> | ||
22 | [206; 209) 'z.y': i8 | ||
23 | |||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index d0da34677..642259225 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -741,6 +741,41 @@ fn test() { | |||
741 | } | 741 | } |
742 | 742 | ||
743 | #[test] | 743 | #[test] |
744 | fn infer_type_alias() { | ||
745 | check_inference( | ||
746 | "infer_type_alias", | ||
747 | r#" | ||
748 | struct A<X, Y> { x: X, y: Y }; | ||
749 | type Foo = A<u32, i128>; | ||
750 | type Bar<T> = A<T, u128>; | ||
751 | type Baz<U, V> = A<V, U>; | ||
752 | fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) { | ||
753 | x.x; | ||
754 | x.y; | ||
755 | y.x; | ||
756 | y.y; | ||
757 | z.x; | ||
758 | z.y; | ||
759 | } | ||
760 | "#, | ||
761 | ) | ||
762 | } | ||
763 | |||
764 | #[test] | ||
765 | #[should_panic] // we currently can't handle this | ||
766 | fn recursive_type_alias() { | ||
767 | check_inference( | ||
768 | "recursive_type_alias", | ||
769 | r#" | ||
770 | struct A<X> {}; | ||
771 | type Foo = Foo; | ||
772 | type Bar = A<Bar>; | ||
773 | fn test(x: Foo) {} | ||
774 | "#, | ||
775 | ) | ||
776 | } | ||
777 | |||
778 | #[test] | ||
744 | fn no_panic_on_field_of_enum() { | 779 | fn no_panic_on_field_of_enum() { |
745 | check_inference( | 780 | check_inference( |
746 | "no_panic_on_field_of_enum", | 781 | "no_panic_on_field_of_enum", |