diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 86 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 10 |
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}; | |||
23 | use rustc_hash::FxHashMap; | 23 | use rustc_hash::FxHashMap; |
24 | 24 | ||
25 | use ra_arena::map::ArenaMap; | 25 | use ra_arena::map::ArenaMap; |
26 | use ra_prof::profile; | ||
26 | use test_utils::tested_by; | 27 | use test_utils::tested_by; |
27 | 28 | ||
28 | use crate::{ | 29 | use crate::{ |
@@ -51,7 +52,8 @@ use super::{ | |||
51 | mod unify; | 52 | mod unify; |
52 | 53 | ||
53 | /// The entry point of type inference. | 54 | /// The entry point of type inference. |
54 | pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { | 55 | pub 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; | |||
9 | use std::iter; | 9 | use std::iter; |
10 | 10 | ||
11 | use crate::{ | 11 | use 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 | }; |
24 | use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; | 25 | use 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 { | |||
274 | pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty { | 289 | pub(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 | ||
350 | pub(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 | |||
334 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | 365 | fn 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 { | |||
383 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | 414 | fn 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) | |||
411 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | 442 | fn 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 | ||
421 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 452 | fn 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 | |||
426 | fn 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 | ||
431 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | 457 | fn 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] |
1452 | fn infer_associated_method_generics_with_default_param() { | ||
1453 | assert_snapshot_matches!( | ||
1454 | infer(r#" | ||
1455 | struct Gen<T=u32> { | ||
1456 | val: T | ||
1457 | } | ||
1458 | |||
1459 | impl<T> Gen<T> { | ||
1460 | pub fn make() -> Gen<T> { | ||
1461 | loop { } | ||
1462 | } | ||
1463 | } | ||
1464 | |||
1465 | fn 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] | ||
1452 | fn infer_associated_method_generics_without_args() { | 1481 | fn 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}; | |||
4 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
5 | use log::debug; | 5 | use log::debug; |
6 | use chalk_ir::cast::Cast; | 6 | use chalk_ir::cast::Cast; |
7 | use ra_prof::profile; | ||
7 | 8 | ||
8 | use crate::{Crate, Trait, db::HirDatabase, ImplBlock}; | 9 | use crate::{Crate, Trait, db::HirDatabase, ImplBlock}; |
9 | use super::{TraitRef, Ty, Canonical}; | 10 | use super::{TraitRef, Ty, Canonical}; |
@@ -25,7 +26,7 @@ struct ChalkContext<'a, DB> { | |||
25 | krate: Crate, | 26 | krate: Crate, |
26 | } | 27 | } |
27 | 28 | ||
28 | pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { | 29 | pub(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`. |
36 | pub(crate) fn impls_for_trait( | 37 | pub(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. |
79 | pub(crate) fn implements( | 80 | pub(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(); |