aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
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/infer/unify.rs7
-rw-r--r--crates/ra_hir/src/ty/lower.rs86
-rw-r--r--crates/ra_hir/src/ty/tests.rs29
-rw-r--r--crates/ra_hir/src/ty/traits.rs10
5 files changed, 100 insertions, 36 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 1e7d97f51..a48272981 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -23,6 +23,7 @@ use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError};
23use rustc_hash::FxHashMap; 23use rustc_hash::FxHashMap;
24 24
25use ra_arena::map::ArenaMap; 25use ra_arena::map::ArenaMap;
26use ra_prof::profile;
26use test_utils::tested_by; 27use test_utils::tested_by;
27 28
28use crate::{ 29use crate::{
@@ -51,7 +52,8 @@ use super::{
51mod unify; 52mod unify;
52 53
53/// The entry point of type inference. 54/// The entry point of type inference.
54pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 55pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
56 let _p = profile("infer_query");
55 db.check_canceled(); 57 db.check_canceled();
56 let body = def.body(db); 58 let body = def.body(db);
57 let resolver = def.resolver(db); 59 let resolver = def.resolver(db);
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index 8ca7e957d..bc9719725 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -56,7 +56,12 @@ where
56 self.var_stack.pop(); 56 self.var_stack.pop();
57 result 57 result
58 } else { 58 } else {
59 let free_var = InferTy::TypeVar(self.ctx.var_unification_table.find(inner)); 59 let root = self.ctx.var_unification_table.find(inner);
60 let free_var = match tv {
61 InferTy::TypeVar(_) => InferTy::TypeVar(root),
62 InferTy::IntVar(_) => InferTy::IntVar(root),
63 InferTy::FloatVar(_) => InferTy::FloatVar(root),
64 };
60 let position = self.add(free_var); 65 let position = self.add(free_var);
61 Ty::Bound(position as u32) 66 Ty::Bound(position as u32)
62 } 67 }
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 09d26ce5a..a1a2d0f6b 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -9,17 +9,18 @@ use std::sync::Arc;
9use std::iter; 9use std::iter;
10 10
11use crate::{ 11use crate::{
12 Function, Struct, StructField, Enum, EnumVariant, Path, 12 Function, Struct, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static,
13 ModuleDef, TypeAlias,
14 Const, Static,
15 HirDatabase, 13 HirDatabase,
16 type_ref::TypeRef, 14 type_ref::TypeRef,
17 name::KnownName, 15 name::KnownName,
18 nameres::Namespace, 16 nameres::Namespace,
19 resolve::{Resolver, Resolution}, 17 resolve::{Resolver, Resolution},
20 path::{PathSegment, GenericArg}, 18 path::{PathSegment, GenericArg},
21 generics::{GenericParams, HasGenericParams}, 19 generics::{HasGenericParams},
22 adt::VariantDef, Trait, generics::{ WherePredicate, GenericDef} 20 adt::VariantDef,
21 Trait,
22 generics::{WherePredicate, GenericDef},
23 ty::AdtDef,
23}; 24};
24use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; 25use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate};
25 26
@@ -120,15 +121,15 @@ impl Ty {
120 segment: &PathSegment, 121 segment: &PathSegment,
121 resolved: TypableDef, 122 resolved: TypableDef,
122 ) -> Substs { 123 ) -> Substs {
123 let def_generics = match resolved { 124 let def_generic: Option<GenericDef> = match resolved {
124 TypableDef::Function(func) => func.generic_params(db), 125 TypableDef::Function(func) => Some(func.into()),
125 TypableDef::Struct(s) => s.generic_params(db), 126 TypableDef::Struct(s) => Some(s.into()),
126 TypableDef::Enum(e) => e.generic_params(db), 127 TypableDef::Enum(e) => Some(e.into()),
127 TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), 128 TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()),
128 TypableDef::TypeAlias(t) => t.generic_params(db), 129 TypableDef::TypeAlias(t) => Some(t.into()),
129 TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), 130 TypableDef::Const(_) | TypableDef::Static(_) => None,
130 }; 131 };
131 substs_from_path_segment(db, resolver, segment, &def_generics, false) 132 substs_from_path_segment(db, resolver, segment, def_generic, false)
132 } 133 }
133 134
134 /// Collect generic arguments from a path into a `Substs`. See also 135 /// Collect generic arguments from a path into a `Substs`. See also
@@ -172,10 +173,12 @@ pub(super) fn substs_from_path_segment(
172 db: &impl HirDatabase, 173 db: &impl HirDatabase,
173 resolver: &Resolver, 174 resolver: &Resolver,
174 segment: &PathSegment, 175 segment: &PathSegment,
175 def_generics: &GenericParams, 176 def_generic: Option<GenericDef>,
176 add_self_param: bool, 177 add_self_param: bool,
177) -> Substs { 178) -> Substs {
178 let mut substs = Vec::new(); 179 let mut substs = Vec::new();
180 let def_generics = def_generic.map(|def| def.generic_params(db)).unwrap_or_default();
181
179 let parent_param_count = def_generics.count_parent_params(); 182 let parent_param_count = def_generics.count_parent_params();
180 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); 183 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count));
181 if add_self_param { 184 if add_self_param {
@@ -199,12 +202,24 @@ pub(super) fn substs_from_path_segment(
199 } 202 }
200 } 203 }
201 // add placeholders for args that were not provided 204 // add placeholders for args that were not provided
202 // FIXME: handle defaults
203 let supplied_params = substs.len(); 205 let supplied_params = substs.len();
204 for _ in supplied_params..def_generics.count_params_including_parent() { 206 for _ in supplied_params..def_generics.count_params_including_parent() {
205 substs.push(Ty::Unknown); 207 substs.push(Ty::Unknown);
206 } 208 }
207 assert_eq!(substs.len(), def_generics.count_params_including_parent()); 209 assert_eq!(substs.len(), def_generics.count_params_including_parent());
210
211 // handle defaults
212 if let Some(def_generic) = def_generic {
213 let default_substs = db.generic_defaults(def_generic);
214 assert_eq!(substs.len(), default_substs.len());
215
216 for (i, default_ty) in default_substs.iter().enumerate() {
217 if substs[i] == Ty::Unknown {
218 substs[i] = default_ty.clone();
219 }
220 }
221 }
222
208 Substs(substs.into()) 223 Substs(substs.into())
209} 224}
210 225
@@ -249,7 +264,7 @@ impl TraitRef {
249 resolved: Trait, 264 resolved: Trait,
250 ) -> Substs { 265 ) -> Substs {
251 let segment = path.segments.last().expect("path should have at least one segment"); 266 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) 267 substs_from_path_segment(db, resolver, segment, Some(resolved.into()), true)
253 } 268 }
254 269
255 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { 270 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef {
@@ -274,9 +289,9 @@ impl TraitRef {
274pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty { 289pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
275 match (def, ns) { 290 match (def, ns) {
276 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f), 291 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
277 (TypableDef::Struct(s), Namespace::Types) => type_for_struct(db, s), 292 (TypableDef::Struct(s), Namespace::Types) => type_for_adt(db, s),
278 (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), 293 (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s),
279 (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), 294 (TypableDef::Enum(e), Namespace::Types) => type_for_adt(db, e),
280 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), 295 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
281 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t), 296 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
282 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c), 297 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c),
@@ -331,6 +346,22 @@ pub(crate) fn generic_predicates(
331 predicates.into() 346 predicates.into()
332} 347}
333 348
349/// Resolve the default type params from generics
350pub(crate) fn generic_defaults(db: &impl HirDatabase, def: GenericDef) -> Substs {
351 let resolver = def.resolver(db);
352 let generic_params = def.generic_params(db);
353
354 let defaults = generic_params
355 .params_including_parent()
356 .into_iter()
357 .map(|p| {
358 p.default.as_ref().map_or(Ty::Unknown, |path| Ty::from_hir_path(db, &resolver, path))
359 })
360 .collect::<Vec<_>>();
361
362 Substs(defaults.into())
363}
364
334fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { 365fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
335 let signature = def.signature(db); 366 let signature = def.signature(db);
336 let resolver = def.resolver(db); 367 let resolver = def.resolver(db);
@@ -375,7 +406,7 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
375 .iter() 406 .iter()
376 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 407 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
377 .collect::<Vec<_>>(); 408 .collect::<Vec<_>>();
378 let ret = type_for_struct(db, def); 409 let ret = type_for_adt(db, def);
379 FnSig::from_params_and_return(params, ret) 410 FnSig::from_params_and_return(params, ret)
380} 411}
381 412
@@ -383,7 +414,7 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
383fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 414fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
384 let var_data = def.variant_data(db); 415 let var_data = def.variant_data(db);
385 if var_data.fields().is_none() { 416 if var_data.fields().is_none() {
386 return type_for_struct(db, def); // Unit struct 417 return type_for_adt(db, def); // Unit struct
387 } 418 }
388 let generics = def.generic_params(db); 419 let generics = def.generic_params(db);
389 let substs = Substs::identity(&generics); 420 let substs = Substs::identity(&generics);
@@ -403,7 +434,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant)
403 .collect::<Vec<_>>(); 434 .collect::<Vec<_>>();
404 let generics = def.parent_enum(db).generic_params(db); 435 let generics = def.parent_enum(db).generic_params(db);
405 let substs = Substs::identity(&generics); 436 let substs = Substs::identity(&generics);
406 let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs); 437 let ret = type_for_adt(db, def.parent_enum(db)).subst(&substs);
407 FnSig::from_params_and_return(params, ret) 438 FnSig::from_params_and_return(params, ret)
408} 439}
409 440
@@ -411,21 +442,16 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant)
411fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { 442fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
412 let var_data = def.variant_data(db); 443 let var_data = def.variant_data(db);
413 if var_data.fields().is_none() { 444 if var_data.fields().is_none() {
414 return type_for_enum(db, def.parent_enum(db)); // Unit variant 445 return type_for_adt(db, def.parent_enum(db)); // Unit variant
415 } 446 }
416 let generics = def.parent_enum(db).generic_params(db); 447 let generics = def.parent_enum(db).generic_params(db);
417 let substs = Substs::identity(&generics); 448 let substs = Substs::identity(&generics);
418 Ty::apply(TypeCtor::FnDef(def.into()), substs) 449 Ty::apply(TypeCtor::FnDef(def.into()), substs)
419} 450}
420 451
421fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 452fn type_for_adt(db: &impl HirDatabase, adt: impl Into<AdtDef> + HasGenericParams) -> Ty {
422 let generics = s.generic_params(db); 453 let generics = adt.generic_params(db);
423 Ty::apply(TypeCtor::Adt(s.into()), Substs::identity(&generics)) 454 Ty::apply(TypeCtor::Adt(adt.into()), Substs::identity(&generics))
424}
425
426fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
427 let generics = s.generic_params(db);
428 Ty::apply(TypeCtor::Adt(s.into()), Substs::identity(&generics))
429} 455}
430 456
431fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 457fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty {
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#"
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 7de04c044..e6c78c0d4 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -4,6 +4,7 @@ use std::sync::{Arc, Mutex};
4use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
5use log::debug; 5use log::debug;
6use chalk_ir::cast::Cast; 6use chalk_ir::cast::Cast;
7use ra_prof::profile;
7 8
8use crate::{Crate, Trait, db::HirDatabase, ImplBlock}; 9use crate::{Crate, Trait, db::HirDatabase, ImplBlock};
9use super::{TraitRef, Ty, Canonical}; 10use super::{TraitRef, Ty, Canonical};
@@ -25,7 +26,7 @@ struct ChalkContext<'a, DB> {
25 krate: Crate, 26 krate: Crate,
26} 27}
27 28
28pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { 29pub(crate) fn solver_query(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> {
29 // krate parameter is just so we cache a unique solver per crate 30 // krate parameter is just so we cache a unique solver per crate
30 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE }; 31 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
31 debug!("Creating new solver for crate {:?}", _krate); 32 debug!("Creating new solver for crate {:?}", _krate);
@@ -33,7 +34,7 @@ pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>
33} 34}
34 35
35/// Collects impls for the given trait in the whole dependency tree of `krate`. 36/// Collects impls for the given trait in the whole dependency tree of `krate`.
36pub(crate) fn impls_for_trait( 37pub(crate) fn impls_for_trait_query(
37 db: &impl HirDatabase, 38 db: &impl HirDatabase,
38 krate: Crate, 39 krate: Crate,
39 trait_: Trait, 40 trait_: Trait,
@@ -60,7 +61,7 @@ fn solve(
60 let context = ChalkContext { db, krate }; 61 let context = ChalkContext { db, krate };
61 let solver = db.solver(krate); 62 let solver = db.solver(krate);
62 debug!("solve goal: {:?}", goal); 63 debug!("solve goal: {:?}", goal);
63 let solution = solver.lock().unwrap().solve(&context, goal); 64 let solution = solver.lock().unwrap().solve_with_fuel(&context, goal, Some(1000));
64 debug!("solve({:?}) => {:?}", goal, solution); 65 debug!("solve({:?}) => {:?}", goal, solution);
65 solution 66 solution
66} 67}
@@ -76,11 +77,12 @@ pub enum Obligation {
76} 77}
77 78
78/// Check using Chalk whether trait is implemented for given parameters including `Self` type. 79/// Check using Chalk whether trait is implemented for given parameters including `Self` type.
79pub(crate) fn implements( 80pub(crate) fn implements_query(
80 db: &impl HirDatabase, 81 db: &impl HirDatabase,
81 krate: Crate, 82 krate: Crate,
82 trait_ref: Canonical<TraitRef>, 83 trait_ref: Canonical<TraitRef>,
83) -> Option<Solution> { 84) -> Option<Solution> {
85 let _p = profile("implements_query");
84 let goal: chalk_ir::Goal = trait_ref.value.to_chalk(db).cast(); 86 let goal: chalk_ir::Goal = trait_ref.value.to_chalk(db).cast();
85 debug!("goal: {:?}", goal); 87 debug!("goal: {:?}", goal);
86 let env = chalk_ir::Environment::new(); 88 let env = chalk_ir::Environment::new();