From 5d72b96988587699e0a1c62c08bd76d2a7fed100 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 24 Feb 2019 17:25:41 +0100 Subject: Implement support for type aliases --- crates/ra_hir/src/ty/infer.rs | 4 ++- crates/ra_hir/src/ty/lower.rs | 32 ++++++++++++++++------ .../src/ty/snapshots/tests__infer_type_alias.snap | 23 ++++++++++++++++ crates/ra_hir/src/ty/tests.rs | 21 ++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 crates/ra_hir/src/ty/snapshots/tests__infer_type_alias.snap (limited to 'crates/ra_hir/src/ty') 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> { let ty = self.insert_type_vars(ty.apply_substs(substs)); (ty, Some(var.into())) } - TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None), + TypableDef::Type(_) | TypableDef::Function(_) | TypableDef::Enum(_) => { + (Ty::Unknown, None) + } } } 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; use crate::{ Function, Struct, StructField, Enum, EnumVariant, Path, Name, - ModuleDef, + ModuleDef, Type, HirDatabase, type_ref::TypeRef, name::KnownName, @@ -109,7 +109,7 @@ impl Ty { }; let ty = db.type_for_def(typable, Namespace::Types); let substs = Ty::substs_from_path(db, resolver, path, typable); - ty.apply_substs(substs) + ty.subst(&substs) } pub(super) fn substs_from_path_segment( @@ -124,6 +124,7 @@ impl Ty { TypableDef::Struct(s) => s.generic_params(db), TypableDef::Enum(e) => e.generic_params(db), TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), + TypableDef::Type(t) => t.generic_params(db), }; let parent_param_count = def_generics.count_parent_params(); substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); @@ -159,9 +160,10 @@ impl Ty { ) -> Substs { let last = path.segments.last().expect("path should have at least one segment"); let segment = match resolved { - TypableDef::Function(_) => last, - TypableDef::Struct(_) => last, - TypableDef::Enum(_) => last, + TypableDef::Function(_) + | TypableDef::Struct(_) + | TypableDef::Enum(_) + | TypableDef::Type(_) => last, TypableDef::EnumVariant(_) => { // the generic args for an enum variant may be either specified // 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 (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), + (TypableDef::Type(t), Namespace::Types) => type_for_type_alias(db, t), // 'error' cases: (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, + (TypableDef::Type(_), Namespace::Values) => Ty::Unknown, } } @@ -264,7 +268,7 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) .collect::>(); let substs = make_substs(&generics); - let output = type_for_enum(db, def.parent_enum(db)).apply_substs(substs.clone()); + let output = type_for_enum(db, def.parent_enum(db)).subst(&substs); let sig = Arc::new(FnSig { input, output }); Ty::FnDef { def: def.into(), sig, name, substs } } @@ -298,14 +302,24 @@ fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { } } +fn type_for_type_alias(db: &impl HirDatabase, t: Type) -> Ty { + let generics = t.generic_params(db); + let resolver = t.resolver(db); + let type_ref = t.type_ref(db); + let substs = make_substs(&generics); + let inner = Ty::from_hir(db, &resolver, &type_ref); + inner.subst(&substs) +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum TypableDef { Function(Function), Struct(Struct), Enum(Enum), EnumVariant(EnumVariant), + Type(Type), } -impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); +impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, Type); impl From for Option { fn from(def: ModuleDef) -> Option { @@ -314,11 +328,11 @@ impl From for Option { ModuleDef::Struct(s) => s.into(), ModuleDef::Enum(e) => e.into(), ModuleDef::EnumVariant(v) => v.into(), + ModuleDef::Type(t) => t.into(), ModuleDef::Const(_) | ModuleDef::Static(_) | ModuleDef::Module(_) - | ModuleDef::Trait(_) - | ModuleDef::Type(_) => return None, + | ModuleDef::Trait(_) => return None, }; Some(res) } 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 @@ +--- +created: "2019-02-24T16:13:47.561870283Z" +creator: insta@0.6.3 +source: crates/ra_hir/src/ty/tests.rs +expression: "&result" +--- +[117; 118) 'x': A +[125; 126) 'y': A<&str, u128> +[139; 140) 'z': A +[155; 212) '{ ...z.y; }': () +[161; 162) 'x': A +[161; 164) 'x.x': u32 +[170; 171) 'x': A +[170; 173) 'x.y': i128 +[179; 180) 'y': A<&str, u128> +[179; 182) 'y.x': &str +[188; 189) 'y': A<&str, u128> +[188; 191) 'y.y': u128 +[197; 198) 'z': A +[197; 200) 'z.x': u8 +[206; 207) 'z': A +[206; 209) 'z.y': i8 + 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 @@ -740,6 +740,27 @@ fn test() { ); } +#[test] +fn infer_type_alias() { + check_inference( + "infer_type_alias", + r#" +struct A { x: X, y: Y }; +type Foo = A; +type Bar = A; +type Baz = A; +fn test(x: Foo, y: Bar<&str>, z: Baz) { + x.x; + x.y; + y.x; + y.y; + z.x; + z.y; +} +"#, + ) +} + #[test] fn no_panic_on_field_of_enum() { check_inference( -- cgit v1.2.3