aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-24 16:25:41 +0000
committerFlorian Diebold <[email protected]>2019-02-24 19:54:04 +0000
commit5d72b96988587699e0a1c62c08bd76d2a7fed100 (patch)
treecfc5c55e0d2ba5fcea6b508c20e23cb43b7f9956 /crates/ra_hir/src/ty
parent5a684099e9aa3482b408002030fafe1dcd0fa9a9 (diff)
Implement support for type aliases
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs4
-rw-r--r--crates/ra_hir/src/ty/lower.rs32
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_type_alias.snap23
-rw-r--r--crates/ra_hir/src/ty/tests.rs21
4 files changed, 70 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
11use crate::{ 11use 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
305fn 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)]
302pub enum TypableDef { 315pub 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}
308impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); 322impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, Type);
309 323
310impl From<ModuleDef> for Option<TypableDef> { 324impl 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---
2created: "2019-02-24T16:13:47.561870283Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&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..490c087f9 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -741,6 +741,27 @@ fn test() {
741} 741}
742 742
743#[test] 743#[test]
744fn infer_type_alias() {
745 check_inference(
746 "infer_type_alias",
747 r#"
748struct A<X, Y> { x: X, y: Y };
749type Foo = A<u32, i128>;
750type Bar<T> = A<T, u128>;
751type Baz<U, V> = A<V, U>;
752fn 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]
744fn no_panic_on_field_of_enum() { 765fn no_panic_on_field_of_enum() {
745 check_inference( 766 check_inference(
746 "no_panic_on_field_of_enum", 767 "no_panic_on_field_of_enum",