aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-17 16:29:51 +0000
committerFlorian Diebold <[email protected]>2019-02-17 19:53:13 +0000
commitb82db684003b817d47c1bc8c0d3c6afc88be2663 (patch)
tree7ec419545aee3e4f7297c6792eec1efebba4eb24 /crates
parenta725dd4f7ac2b88541189f0f726ce86876c36add (diff)
Handle tuple structs / enum variants properly in type inference
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model_api.rs10
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/nameres.rs4
-rw-r--r--crates/ra_hir/src/ty.rs96
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap18
5 files changed, 95 insertions, 37 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 26ebc445b..9da8a482d 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -290,7 +290,11 @@ impl Struct {
290 } 290 }
291 291
292 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 292 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
293 db.type_for_def((*self).into()) 293 db.type_for_def((*self).into(), Namespace::Types)
294 }
295
296 pub fn constructor_ty(&self, db: &impl HirDatabase) -> Ty {
297 db.type_for_def((*self).into(), Namespace::Values)
294 } 298 }
295 299
296 // TODO move to a more general type 300 // TODO move to a more general type
@@ -350,7 +354,7 @@ impl Enum {
350 } 354 }
351 355
352 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 356 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
353 db.type_for_def((*self).into()) 357 db.type_for_def((*self).into(), Namespace::Types)
354 } 358 }
355 359
356 // TODO: move to a more general type 360 // TODO: move to a more general type
@@ -425,7 +429,7 @@ pub struct Function {
425 pub(crate) id: FunctionId, 429 pub(crate) id: FunctionId,
426} 430}
427 431
428pub use crate::expr::ScopeEntryWithSyntax; 432pub use crate::{ nameres::Namespace, expr::ScopeEntryWithSyntax};
429 433
430/// The declared signature of a function. 434/// The declared signature of a function.
431#[derive(Debug, Clone, PartialEq, Eq)] 435#[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 740a7be7a..fc0ee068c 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -15,7 +15,7 @@ use crate::{
15 adt::{StructData, EnumData}, 15 adt::{StructData, EnumData},
16 impl_block::{ModuleImplBlocks, ImplSourceMap}, 16 impl_block::{ModuleImplBlocks, ImplSourceMap},
17 generics::{GenericParams, GenericDef}, 17 generics::{GenericParams, GenericDef},
18 ids::SourceFileItemId, 18 ids::SourceFileItemId, nameres::Namespace
19}; 19};
20 20
21#[salsa::query_group(PersistentHirDatabaseStorage)] 21#[salsa::query_group(PersistentHirDatabaseStorage)]
@@ -88,7 +88,7 @@ pub trait HirDatabase: PersistentHirDatabase {
88 fn infer(&self, func: Function) -> Arc<InferenceResult>; 88 fn infer(&self, func: Function) -> Arc<InferenceResult>;
89 89
90 #[salsa::invoke(crate::ty::type_for_def)] 90 #[salsa::invoke(crate::ty::type_for_def)]
91 fn type_for_def(&self, def: TypableDef) -> Ty; 91 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty;
92 92
93 #[salsa::invoke(crate::ty::type_for_field)] 93 #[salsa::invoke(crate::ty::type_for_field)]
94 fn type_for_field(&self, field: StructField) -> Ty; 94 fn type_for_field(&self, field: StructField) -> Ty;
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index e35b4b129..bd920bfea 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -348,7 +348,7 @@ where
348 .into_iter() 348 .into_iter()
349 .filter_map(|variant| { 349 .filter_map(|variant| {
350 let res = Resolution { 350 let res = Resolution {
351 def: PerNs::both(variant.into(), e.into()), 351 def: PerNs::both(variant.into(), variant.into()),
352 import: Some(import_id), 352 import: Some(import_id),
353 }; 353 };
354 let name = variant.name(self.db)?; 354 let name = variant.name(self.db)?;
@@ -628,7 +628,7 @@ impl ItemMap {
628 // enum variant 628 // enum variant
629 tested_by!(item_map_enum_importing); 629 tested_by!(item_map_enum_importing);
630 match e.variant(db, &segment.name) { 630 match e.variant(db, &segment.name) {
631 Some(variant) => PerNs::both(variant.into(), (*e).into()), 631 Some(variant) => PerNs::both(variant.into(), variant.into()),
632 None => PerNs::none(), 632 None => PerNs::none(),
633 } 633 }
634 } 634 }
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 562ad1f49..fb98ac907 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -42,7 +42,7 @@ use crate::{
42 generics::GenericParams, 42 generics::GenericParams,
43 path::GenericArg, 43 path::GenericArg,
44 adt::VariantDef, 44 adt::VariantDef,
45 resolve::{Resolver, Resolution}, 45 resolve::{Resolver, Resolution}, nameres::Namespace
46}; 46};
47 47
48/// The ID of a type variable. 48/// The ID of a type variable.
@@ -226,6 +226,8 @@ pub enum Ty {
226 /// function has a unique type, which is output (for a function 226 /// function has a unique type, which is output (for a function
227 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. 227 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
228 /// 228 ///
229 /// This includes tuple struct / enum variant constructors as well.
230 ///
229 /// For example the type of `bar` here: 231 /// For example the type of `bar` here:
230 /// 232 ///
231 /// ```rust 233 /// ```rust
@@ -233,8 +235,8 @@ pub enum Ty {
233 /// let bar = foo; // bar: fn() -> i32 {foo} 235 /// let bar = foo; // bar: fn() -> i32 {foo}
234 /// ``` 236 /// ```
235 FnDef { 237 FnDef {
236 // Function definition 238 /// The definition of the function / constructor.
237 def: Function, 239 def: CallableDef,
238 /// For display 240 /// For display
239 name: Name, 241 name: Name,
240 /// Parameters and return type 242 /// Parameters and return type
@@ -396,7 +398,7 @@ impl Ty {
396 None => return Ty::Unknown, 398 None => return Ty::Unknown,
397 Some(it) => it, 399 Some(it) => it,
398 }; 400 };
399 let ty = db.type_for_def(typable); 401 let ty = db.type_for_def(typable, Namespace::Types);
400 let substs = Ty::substs_from_path(db, resolver, path, typable); 402 let substs = Ty::substs_from_path(db, resolver, path, typable);
401 ty.apply_substs(substs) 403 ty.apply_substs(substs)
402 } 404 }
@@ -673,7 +675,47 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
673 let output = Ty::from_hir(db, &resolver, signature.ret_type()); 675 let output = Ty::from_hir(db, &resolver, signature.ret_type());
674 let sig = Arc::new(FnSig { input, output }); 676 let sig = Arc::new(FnSig { input, output });
675 let substs = make_substs(&generics); 677 let substs = make_substs(&generics);
676 Ty::FnDef { def, sig, name, substs } 678 Ty::FnDef { def: def.into(), sig, name, substs }
679}
680
681/// Compute the type of a tuple struct constructor.
682fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
683 let var_data = def.variant_data(db);
684 let fields = match var_data.fields() {
685 Some(fields) => fields,
686 None => return type_for_struct(db, def), // Unit struct
687 };
688 let resolver = def.resolver(db);
689 let generics = def.generic_params(db);
690 let name = def.name(db).unwrap_or_else(Name::missing);
691 let input = fields
692 .iter()
693 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
694 .collect::<Vec<_>>();
695 let output = type_for_struct(db, def);
696 let sig = Arc::new(FnSig { input, output });
697 let substs = make_substs(&generics);
698 Ty::FnDef { def: def.into(), sig, name, substs }
699}
700
701/// Compute the type of a tuple enum variant constructor.
702fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
703 let var_data = def.variant_data(db);
704 let fields = match var_data.fields() {
705 Some(fields) => fields,
706 None => return type_for_enum(db, def.parent_enum(db)), // Unit variant
707 };
708 let resolver = def.parent_enum(db).resolver(db);
709 let generics = def.parent_enum(db).generic_params(db);
710 let name = def.name(db).unwrap_or_else(Name::missing);
711 let input = fields
712 .iter()
713 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
714 .collect::<Vec<_>>();
715 let output = type_for_enum(db, def.parent_enum(db));
716 let sig = Arc::new(FnSig { input, output });
717 let substs = make_substs(&generics);
718 Ty::FnDef { def: def.into(), sig, name, substs }
677} 719}
678 720
679fn make_substs(generics: &GenericParams) -> Substs { 721fn make_substs(generics: &GenericParams) -> Substs {
@@ -703,12 +745,6 @@ pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
703 } 745 }
704} 746}
705 747
706pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Ty {
707 let enum_parent = ev.parent_enum(db);
708
709 type_for_enum(db, enum_parent)
710}
711
712#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 748#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
713pub enum TypableDef { 749pub enum TypableDef {
714 Function(Function), 750 Function(Function),
@@ -735,12 +771,26 @@ impl From<ModuleDef> for Option<TypableDef> {
735 } 771 }
736} 772}
737 773
738pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { 774#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
739 match def { 775pub enum CallableDef {
740 TypableDef::Function(f) => type_for_fn(db, f), 776 Function(Function),
741 TypableDef::Struct(s) => type_for_struct(db, s), 777 Struct(Struct),
742 TypableDef::Enum(e) => type_for_enum(db, e), 778 EnumVariant(EnumVariant),
743 TypableDef::EnumVariant(v) => type_for_enum_variant(db, v), 779}
780impl_froms!(CallableDef: Function, Struct, EnumVariant);
781
782pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
783 match (def, ns) {
784 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
785 (TypableDef::Struct(s), Namespace::Types) => type_for_struct(db, s),
786 (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s),
787 (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e),
788 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
789
790 // 'error' cases:
791 (TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
792 (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown,
793 (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
744 } 794 }
745} 795}
746 796
@@ -1127,7 +1177,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1127 let typable: Option<TypableDef> = def.into(); 1177 let typable: Option<TypableDef> = def.into();
1128 let typable = typable?; 1178 let typable = typable?;
1129 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 1179 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
1130 let ty = self.db.type_for_def(typable).apply_substs(substs); 1180 let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs);
1131 let ty = self.insert_type_vars(ty); 1181 let ty = self.insert_type_vars(ty);
1132 Some(ty) 1182 Some(ty)
1133 } 1183 }
@@ -1178,12 +1228,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1178 let substs = Ty::substs_from_path(self.db, resolver, path, def); 1228 let substs = Ty::substs_from_path(self.db, resolver, path, def);
1179 match def { 1229 match def {
1180 TypableDef::Struct(s) => { 1230 TypableDef::Struct(s) => {
1181 let ty = type_for_struct(self.db, s); 1231 let ty = s.ty(self.db);
1182 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1232 let ty = self.insert_type_vars(ty.apply_substs(substs));
1183 (ty, Some(s.into())) 1233 (ty, Some(s.into()))
1184 } 1234 }
1185 TypableDef::EnumVariant(var) => { 1235 TypableDef::EnumVariant(var) => {
1186 let ty = type_for_enum_variant(self.db, var); 1236 let ty = var.parent_enum(self.db).ty(self.db);
1187 let ty = self.insert_type_vars(ty.apply_substs(substs)); 1237 let ty = self.insert_type_vars(ty.apply_substs(substs));
1188 (ty, Some(var.into())) 1238 (ty, Some(var.into()))
1189 } 1239 }
@@ -1384,7 +1434,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1384 let (derefed_receiver_ty, method_ty, def_generics) = match resolved { 1434 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
1385 Some((ty, func)) => { 1435 Some((ty, func)) => {
1386 self.write_method_resolution(tgt_expr, func); 1436 self.write_method_resolution(tgt_expr, func);
1387 (ty, self.db.type_for_def(func.into()), Some(func.generic_params(self.db))) 1437 (
1438 ty,
1439 self.db.type_for_def(func.into(), Namespace::Values),
1440 Some(func.generic_params(self.db)),
1441 )
1388 } 1442 }
1389 None => (Ty::Unknown, receiver_ty, None), 1443 None => (Ty::Unknown, receiver_ty, None),
1390 }; 1444 };
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
index 8747fae18..294186b06 100644
--- a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap
@@ -1,21 +1,21 @@
1--- 1---
2created: "2019-01-24T14:51:32.808861856+00:00" 2created: "2019-02-17T16:16:58.863630956Z"
3creator: [email protected] 3creator: [email protected]
4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs 4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6--- 6---
7[72; 154) '{ ...a.c; }': () 7[72; 154) '{ ...a.c; }': ()
8[82; 83) 'c': [unknown] 8[82; 83) 'c': C
9[86; 87) 'C': C 9[86; 87) 'C': fn C(usize) -> C
10[86; 90) 'C(1)': [unknown] 10[86; 90) 'C(1)': C
11[88; 89) '1': i32 11[88; 89) '1': usize
12[96; 97) 'B': B 12[96; 97) 'B': B
13[107; 108) 'a': A 13[107; 108) 'a': A
14[114; 133) 'A { b:...C(1) }': A 14[114; 133) 'A { b:...C(1) }': A
15[121; 122) 'B': B 15[121; 122) 'B': B
16[127; 128) 'C': C 16[127; 128) 'C': fn C(usize) -> C
17[127; 131) 'C(1)': C 17[127; 131) 'C(1)': C
18[129; 130) '1': i32 18[129; 130) '1': usize
19[139; 140) 'a': A 19[139; 140) 'a': A
20[139; 142) 'a.b': B 20[139; 142) 'a.b': B
21[148; 149) 'a': A 21[148; 149) 'a': A