aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-05-20 10:52:15 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-05-20 10:52:15 +0100
commit3894eb77d8c06acda68f6c267315063b1c9960e8 (patch)
treed6f33d4f6647cea3ec63b48e3b14b7897890db94 /crates
parent5edddae523184462d779d5a347ca1c5be5832044 (diff)
parent3fc344b9f16ad481e87198da72052dd7ddfc88be (diff)
Merge #1286
1286: Add infer for generic default type r=flodiebold a=edwin0cheng This PR add infer support for generic default type: ``` struct Gen<T=u32> { val: T } ``` * add the (unresolved) defaults from the definition to GenericParams * add a query generic_defaults that resolves those defaults to types and returns a Substs * add the missing type in `substs_from_path_segment` * add tests based on the idea in this [comment](https://github.com/rust-analyzer/rust-analyzer/issues/1099#issuecomment-484206279) Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/db.rs5
-rw-r--r--crates/ra_hir/src/generics.rs13
-rw-r--r--crates/ra_hir/src/ty.rs2
-rw-r--r--crates/ra_hir/src/ty/lower.rs54
-rw-r--r--crates/ra_hir/src/ty/tests.rs29
5 files changed, 86 insertions, 17 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 8e827d4f5..bda02d3cc 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -11,7 +11,7 @@ use crate::{
11 DefWithBody, Trait, 11 DefWithBody, Trait,
12 ids, 12 ids,
13 nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap}, 13 nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap},
14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig, TypeCtor, GenericPredicate}, 14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig, TypeCtor, GenericPredicate, Substs},
15 adt::{StructData, EnumData}, 15 adt::{StructData, EnumData},
16 impl_block::{ModuleImplBlocks, ImplSourceMap, ImplBlock}, 16 impl_block::{ModuleImplBlocks, ImplSourceMap, ImplBlock},
17 generics::{GenericParams, GenericDef}, 17 generics::{GenericParams, GenericDef},
@@ -141,6 +141,9 @@ pub trait HirDatabase: DefDatabase {
141 #[salsa::invoke(crate::ty::generic_predicates)] 141 #[salsa::invoke(crate::ty::generic_predicates)]
142 fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>; 142 fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>;
143 143
144 #[salsa::invoke(crate::ty::generic_defaults)]
145 fn generic_defaults(&self, def: GenericDef) -> Substs;
146
144 #[salsa::invoke(crate::expr::body_with_source_map_query)] 147 #[salsa::invoke(crate::expr::body_with_source_map_query)]
145 fn body_with_source_map( 148 fn body_with_source_map(
146 &self, 149 &self,
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index c29b96f50..a635c7184 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -5,7 +5,7 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner, DefaultTypeParamOwner};
9 9
10use crate::{ 10use crate::{
11 db::{ HirDatabase, DefDatabase}, 11 db::{ HirDatabase, DefDatabase},
@@ -18,6 +18,7 @@ pub struct GenericParam {
18 // FIXME: give generic params proper IDs 18 // FIXME: give generic params proper IDs
19 pub(crate) idx: u32, 19 pub(crate) idx: u32,
20 pub(crate) name: Name, 20 pub(crate) name: Name,
21 pub(crate) default: Option<Path>,
21} 22}
22 23
23/// Data about the generic parameters of a function, struct, impl, etc. 24/// Data about the generic parameters of a function, struct, impl, etc.
@@ -68,7 +69,11 @@ impl GenericParams {
68 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), 69 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
69 GenericDef::Trait(it) => { 70 GenericDef::Trait(it) => {
70 // traits get the Self type as an implicit first type parameter 71 // traits get the Self type as an implicit first type parameter
71 generics.params.push(GenericParam { idx: start, name: Name::self_type() }); 72 generics.params.push(GenericParam {
73 idx: start,
74 name: Name::self_type(),
75 default: None,
76 });
72 generics.fill(&*it.source(db).1, start + 1); 77 generics.fill(&*it.source(db).1, start + 1);
73 } 78 }
74 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), 79 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start),
@@ -90,7 +95,9 @@ impl GenericParams {
90 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { 95 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
91 for (idx, type_param) in params.type_params().enumerate() { 96 for (idx, type_param) in params.type_params().enumerate() {
92 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); 97 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
93 let param = GenericParam { idx: idx as u32 + start, name: name.clone() }; 98 let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast);
99
100 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
94 self.params.push(param); 101 self.params.push(param);
95 102
96 let type_ref = TypeRef::Path(name.into()); 103 let type_ref = TypeRef::Path(name.into());
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index cfe07156b..9a65bf567 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -19,7 +19,7 @@ use std::{fmt, mem};
19use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams}; 19use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams};
20use display::{HirDisplay, HirFormatter}; 20use display::{HirDisplay, HirFormatter};
21 21
22pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig, generic_predicates}; 22pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig, generic_predicates, generic_defaults};
23pub(crate) use infer::{infer, InferenceResult, InferTy}; 23pub(crate) use infer::{infer, InferenceResult, InferTy};
24pub use lower::CallableDef; 24pub use lower::CallableDef;
25 25
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 09d26ce5a..8a8cc2a24 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -18,7 +18,7 @@ use crate::{
18 nameres::Namespace, 18 nameres::Namespace,
19 resolve::{Resolver, Resolution}, 19 resolve::{Resolver, Resolution},
20 path::{PathSegment, GenericArg}, 20 path::{PathSegment, GenericArg},
21 generics::{GenericParams, HasGenericParams}, 21 generics::{HasGenericParams},
22 adt::VariantDef, Trait, generics::{ WherePredicate, GenericDef} 22 adt::VariantDef, Trait, generics::{ WherePredicate, GenericDef}
23}; 23};
24use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; 24use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate};
@@ -120,15 +120,15 @@ impl Ty {
120 segment: &PathSegment, 120 segment: &PathSegment,
121 resolved: TypableDef, 121 resolved: TypableDef,
122 ) -> Substs { 122 ) -> Substs {
123 let def_generics = match resolved { 123 let def_generic: Option<GenericDef> = match resolved {
124 TypableDef::Function(func) => func.generic_params(db), 124 TypableDef::Function(func) => Some(func.into()),
125 TypableDef::Struct(s) => s.generic_params(db), 125 TypableDef::Struct(s) => Some(s.into()),
126 TypableDef::Enum(e) => e.generic_params(db), 126 TypableDef::Enum(e) => Some(e.into()),
127 TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), 127 TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()),
128 TypableDef::TypeAlias(t) => t.generic_params(db), 128 TypableDef::TypeAlias(t) => Some(t.into()),
129 TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), 129 TypableDef::Const(_) | TypableDef::Static(_) => None,
130 }; 130 };
131 substs_from_path_segment(db, resolver, segment, &def_generics, false) 131 substs_from_path_segment(db, resolver, segment, def_generic, false)
132 } 132 }
133 133
134 /// Collect generic arguments from a path into a `Substs`. See also 134 /// Collect generic arguments from a path into a `Substs`. See also
@@ -172,10 +172,12 @@ pub(super) fn substs_from_path_segment(
172 db: &impl HirDatabase, 172 db: &impl HirDatabase,
173 resolver: &Resolver, 173 resolver: &Resolver,
174 segment: &PathSegment, 174 segment: &PathSegment,
175 def_generics: &GenericParams, 175 def_generic: Option<GenericDef>,
176 add_self_param: bool, 176 add_self_param: bool,
177) -> Substs { 177) -> Substs {
178 let mut substs = Vec::new(); 178 let mut substs = Vec::new();
179 let def_generics = def_generic.map(|def| def.generic_params(db)).unwrap_or_default();
180
179 let parent_param_count = def_generics.count_parent_params(); 181 let parent_param_count = def_generics.count_parent_params();
180 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); 182 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count));
181 if add_self_param { 183 if add_self_param {
@@ -199,12 +201,24 @@ pub(super) fn substs_from_path_segment(
199 } 201 }
200 } 202 }
201 // add placeholders for args that were not provided 203 // add placeholders for args that were not provided
202 // FIXME: handle defaults
203 let supplied_params = substs.len(); 204 let supplied_params = substs.len();
204 for _ in supplied_params..def_generics.count_params_including_parent() { 205 for _ in supplied_params..def_generics.count_params_including_parent() {
205 substs.push(Ty::Unknown); 206 substs.push(Ty::Unknown);
206 } 207 }
207 assert_eq!(substs.len(), def_generics.count_params_including_parent()); 208 assert_eq!(substs.len(), def_generics.count_params_including_parent());
209
210 // handle defaults
211 if let Some(def_generic) = def_generic {
212 let default_substs = db.generic_defaults(def_generic);
213 assert_eq!(substs.len(), default_substs.len());
214
215 for (i, default_ty) in default_substs.iter().enumerate() {
216 if substs[i] == Ty::Unknown {
217 substs[i] = default_ty.clone();
218 }
219 }
220 }
221
208 Substs(substs.into()) 222 Substs(substs.into())
209} 223}
210 224
@@ -249,7 +263,7 @@ impl TraitRef {
249 resolved: Trait, 263 resolved: Trait,
250 ) -> Substs { 264 ) -> Substs {
251 let segment = path.segments.last().expect("path should have at least one segment"); 265 let segment = path.segments.last().expect("path should have at least one segment");
252 substs_from_path_segment(db, resolver, segment, &resolved.generic_params(db), true) 266 substs_from_path_segment(db, resolver, segment, Some(resolved.into()), true)
253 } 267 }
254 268
255 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { 269 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef {
@@ -331,6 +345,22 @@ pub(crate) fn generic_predicates(
331 predicates.into() 345 predicates.into()
332} 346}
333 347
348/// Resolve the default type params from generics
349pub(crate) fn generic_defaults(db: &impl HirDatabase, def: GenericDef) -> Substs {
350 let resolver = def.resolver(db);
351 let generic_params = def.generic_params(db);
352
353 let defaults = generic_params
354 .params_including_parent()
355 .into_iter()
356 .map(|p| {
357 p.default.as_ref().map_or(Ty::Unknown, |path| Ty::from_hir_path(db, &resolver, path))
358 })
359 .collect::<Vec<_>>();
360
361 Substs(defaults.into())
362}
363
334fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { 364fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
335 let signature = def.signature(db); 365 let signature = def.signature(db);
336 let resolver = def.resolver(db); 366 let resolver = def.resolver(db);
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f8364203d..cd24faba5 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1449,6 +1449,35 @@ fn test() {
1449} 1449}
1450 1450
1451#[test] 1451#[test]
1452fn infer_associated_method_generics_with_default_param() {
1453 assert_snapshot_matches!(
1454 infer(r#"
1455struct Gen<T=u32> {
1456 val: T
1457}
1458
1459impl<T> Gen<T> {
1460 pub fn make() -> Gen<T> {
1461 loop { }
1462 }
1463}
1464
1465fn test() {
1466 let a = Gen::make();
1467}
1468"#),
1469 @r###"
1470[80; 104) '{ ... }': !
1471[90; 98) 'loop { }': !
1472[95; 98) '{ }': ()
1473[118; 146) '{ ...e(); }': ()
1474[128; 129) 'a': Gen<u32>
1475[132; 141) 'Gen::make': fn make<u32>() -> Gen<T>
1476[132; 143) 'Gen::make()': Gen<u32>"###
1477 );
1478}
1479
1480#[test]
1452fn infer_associated_method_generics_without_args() { 1481fn infer_associated_method_generics_without_args() {
1453 assert_snapshot_matches!( 1482 assert_snapshot_matches!(
1454 infer(r#" 1483 infer(r#"