diff options
-rw-r--r-- | crates/ra_hir_ty/src/db.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/coerce.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 56 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 15 |
8 files changed, 102 insertions, 63 deletions
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 9ce154593..222a36a9f 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -11,7 +11,7 @@ use ra_db::{salsa, CrateId}; | |||
11 | use crate::{ | 11 | use crate::{ |
12 | method_resolution::CrateImplBlocks, | 12 | method_resolution::CrateImplBlocks, |
13 | traits::{AssocTyValue, Impl}, | 13 | traits::{AssocTyValue, Impl}, |
14 | CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor, | 14 | CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, |
15 | ValueTyDefId, | 15 | ValueTyDefId, |
16 | }; | 16 | }; |
17 | 17 | ||
@@ -22,13 +22,18 @@ pub trait HirDatabase: DefDatabase { | |||
22 | fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>; | 22 | fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>; |
23 | 23 | ||
24 | #[salsa::invoke(crate::lower::ty_query)] | 24 | #[salsa::invoke(crate::lower::ty_query)] |
25 | #[salsa::cycle(crate::lower::ty_recover)] | ||
25 | fn ty(&self, def: TyDefId) -> Ty; | 26 | fn ty(&self, def: TyDefId) -> Ty; |
26 | 27 | ||
27 | #[salsa::invoke(crate::lower::value_ty_query)] | 28 | #[salsa::invoke(crate::lower::value_ty_query)] |
28 | fn value_ty(&self, def: ValueTyDefId) -> Ty; | 29 | fn value_ty(&self, def: ValueTyDefId) -> Ty; |
29 | 30 | ||
30 | #[salsa::invoke(crate::lower::impl_ty_query)] | 31 | #[salsa::invoke(crate::lower::impl_self_ty_query)] |
31 | fn impl_ty(&self, def: ImplId) -> ImplTy; | 32 | #[salsa::cycle(crate::lower::impl_self_ty_recover)] |
33 | fn impl_self_ty(&self, def: ImplId) -> Ty; | ||
34 | |||
35 | #[salsa::invoke(crate::lower::impl_trait_query)] | ||
36 | fn impl_trait(&self, def: ImplId) -> Option<TraitRef>; | ||
32 | 37 | ||
33 | #[salsa::invoke(crate::lower::field_types_query)] | 38 | #[salsa::invoke(crate::lower::field_types_query)] |
34 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; | 39 | fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; |
@@ -37,6 +42,7 @@ pub trait HirDatabase: DefDatabase { | |||
37 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; | 42 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; |
38 | 43 | ||
39 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 44 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
45 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | ||
40 | fn generic_predicates_for_param( | 46 | fn generic_predicates_for_param( |
41 | &self, | 47 | &self, |
42 | def: GenericDefId, | 48 | def: GenericDefId, |
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 719a0f395..064993d34 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs | |||
@@ -8,7 +8,7 @@ use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutabilit | |||
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
10 | 10 | ||
11 | use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk}; | 11 | use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk}; |
12 | 12 | ||
13 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; | 13 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; |
14 | 14 | ||
@@ -54,10 +54,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
54 | impls | 54 | impls |
55 | .iter() | 55 | .iter() |
56 | .filter_map(|&impl_id| { | 56 | .filter_map(|&impl_id| { |
57 | let trait_ref = match db.impl_ty(impl_id) { | 57 | let trait_ref = db.impl_trait(impl_id)?; |
58 | ImplTy::TraitRef(it) => it, | ||
59 | ImplTy::Inherent(_) => return None, | ||
60 | }; | ||
61 | 58 | ||
62 | // `CoerseUnsized` has one generic parameter for the target type. | 59 | // `CoerseUnsized` has one generic parameter for the target type. |
63 | let cur_from_ty = trait_ref.substs.0.get(0)?; | 60 | let cur_from_ty = trait_ref.substs.0.get(0)?; |
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 14be66836..bbf146418 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -244,7 +244,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
244 | ContainerId::ImplId(it) => it, | 244 | ContainerId::ImplId(it) => it, |
245 | _ => return None, | 245 | _ => return None, |
246 | }; | 246 | }; |
247 | let self_ty = self.db.impl_ty(impl_id).self_type().clone(); | 247 | let self_ty = self.db.impl_self_ty(impl_id).clone(); |
248 | let self_ty_substs = self_ty.substs()?; | 248 | let self_ty_substs = self_ty.substs()?; |
249 | let actual_substs = actual_def_ty.substs()?; | 249 | let actual_substs = actual_def_ty.substs()?; |
250 | 250 | ||
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index b45c8f82f..3c1f738df 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -486,21 +486,6 @@ impl TypeWalk for TraitRef { | |||
486 | } | 486 | } |
487 | } | 487 | } |
488 | 488 | ||
489 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
490 | pub enum ImplTy { | ||
491 | Inherent(Ty), | ||
492 | TraitRef(TraitRef), | ||
493 | } | ||
494 | |||
495 | impl ImplTy { | ||
496 | pub(crate) fn self_type(&self) -> &Ty { | ||
497 | match self { | ||
498 | ImplTy::Inherent(it) => it, | ||
499 | ImplTy::TraitRef(tr) => &tr.substs[0], | ||
500 | } | ||
501 | } | ||
502 | } | ||
503 | |||
504 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | 489 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the |
505 | /// parameters of a generic item. | 490 | /// parameters of a generic item. |
506 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 491 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 091c60f4f..32569ac66 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -27,8 +27,8 @@ use crate::{ | |||
27 | all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice, | 27 | all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice, |
28 | variant_data, | 28 | variant_data, |
29 | }, | 29 | }, |
30 | FnSig, GenericPredicate, ImplTy, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, | 30 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, |
31 | TraitRef, Ty, TypeCtor, TypeWalk, | 31 | Ty, TypeCtor, TypeWalk, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | impl Ty { | 34 | impl Ty { |
@@ -179,7 +179,7 @@ impl Ty { | |||
179 | let name = resolved_segment.name.clone(); | 179 | let name = resolved_segment.name.clone(); |
180 | Ty::Param { idx, name } | 180 | Ty::Param { idx, name } |
181 | } | 181 | } |
182 | TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(), | 182 | TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(), |
183 | TypeNs::AdtSelfType(adt) => db.ty(adt.into()), | 183 | TypeNs::AdtSelfType(adt) => db.ty(adt.into()), |
184 | 184 | ||
185 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), | 185 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), |
@@ -532,6 +532,15 @@ pub(crate) fn generic_predicates_for_param_query( | |||
532 | .collect() | 532 | .collect() |
533 | } | 533 | } |
534 | 534 | ||
535 | pub(crate) fn generic_predicates_for_param_recover( | ||
536 | _db: &impl HirDatabase, | ||
537 | _cycle: &[String], | ||
538 | _def: &GenericDefId, | ||
539 | _param_idx: &u32, | ||
540 | ) -> Arc<[GenericPredicate]> { | ||
541 | Arc::new([]) | ||
542 | } | ||
543 | |||
535 | impl TraitEnvironment { | 544 | impl TraitEnvironment { |
536 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { | 545 | pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { |
537 | let predicates = resolver | 546 | let predicates = resolver |
@@ -733,6 +742,11 @@ pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { | |||
733 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), | 742 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), |
734 | } | 743 | } |
735 | } | 744 | } |
745 | |||
746 | pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty { | ||
747 | Ty::Unknown | ||
748 | } | ||
749 | |||
736 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | 750 | pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { |
737 | match def { | 751 | match def { |
738 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), | 752 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), |
@@ -743,17 +757,24 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { | |||
743 | } | 757 | } |
744 | } | 758 | } |
745 | 759 | ||
746 | pub(crate) fn impl_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> ImplTy { | 760 | pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { |
747 | let impl_data = db.impl_data(impl_id); | 761 | let impl_data = db.impl_data(impl_id); |
748 | let resolver = impl_id.resolver(db); | 762 | let resolver = impl_id.resolver(db); |
749 | let self_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); | 763 | Ty::from_hir(db, &resolver, &impl_data.target_type) |
750 | match impl_data.target_trait.as_ref() { | 764 | } |
751 | Some(trait_ref) => { | 765 | |
752 | match TraitRef::from_hir(db, &resolver, trait_ref, Some(self_ty.clone())) { | 766 | pub(crate) fn impl_self_ty_recover( |
753 | Some(it) => ImplTy::TraitRef(it), | 767 | _db: &impl HirDatabase, |
754 | None => ImplTy::Inherent(self_ty), | 768 | _cycle: &[String], |
755 | } | 769 | _impl_id: &ImplId, |
756 | } | 770 | ) -> Ty { |
757 | None => ImplTy::Inherent(self_ty), | 771 | Ty::Unknown |
758 | } | 772 | } |
773 | |||
774 | pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { | ||
775 | let impl_data = db.impl_data(impl_id); | ||
776 | let resolver = impl_id.resolver(db); | ||
777 | let self_ty = db.impl_self_ty(impl_id); | ||
778 | let target_trait = impl_data.target_trait.as_ref()?; | ||
779 | TraitRef::from_hir(db, &resolver, target_trait, Some(self_ty.clone())) | ||
759 | } | 780 | } |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index ee1936b0e..2bded3dbd 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -19,7 +19,7 @@ use crate::{ | |||
19 | db::HirDatabase, | 19 | db::HirDatabase, |
20 | primitive::{FloatBitness, Uncertain}, | 20 | primitive::{FloatBitness, Uncertain}, |
21 | utils::all_super_traits, | 21 | utils::all_super_traits, |
22 | Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, | 22 | Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | /// This is used as a key for indexing impls. | 25 | /// This is used as a key for indexing impls. |
@@ -58,11 +58,12 @@ impl CrateImplBlocks { | |||
58 | let crate_def_map = db.crate_def_map(krate); | 58 | let crate_def_map = db.crate_def_map(krate); |
59 | for (_module_id, module_data) in crate_def_map.modules.iter() { | 59 | for (_module_id, module_data) in crate_def_map.modules.iter() { |
60 | for &impl_id in module_data.impls.iter() { | 60 | for &impl_id in module_data.impls.iter() { |
61 | match db.impl_ty(impl_id) { | 61 | match db.impl_trait(impl_id) { |
62 | ImplTy::TraitRef(tr) => { | 62 | Some(tr) => { |
63 | res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); | 63 | res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); |
64 | } | 64 | } |
65 | ImplTy::Inherent(self_ty) => { | 65 | None => { |
66 | let self_ty = db.impl_self_ty(impl_id); | ||
66 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) { | 67 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) { |
67 | res.impls.entry(self_ty_fp).or_default().push(impl_id); | 68 | res.impls.entry(self_ty_fp).or_default().push(impl_id); |
68 | } | 69 | } |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 4ba87e667..c856d6afd 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -2154,7 +2154,6 @@ fn test(x: Foo, y: Bar<&str>, z: Baz<i8, u8>) { | |||
2154 | } | 2154 | } |
2155 | 2155 | ||
2156 | #[test] | 2156 | #[test] |
2157 | #[should_panic] // we currently can't handle this | ||
2158 | fn recursive_type_alias() { | 2157 | fn recursive_type_alias() { |
2159 | assert_snapshot!( | 2158 | assert_snapshot!( |
2160 | infer(r#" | 2159 | infer(r#" |
@@ -2163,7 +2162,10 @@ type Foo = Foo; | |||
2163 | type Bar = A<Bar>; | 2162 | type Bar = A<Bar>; |
2164 | fn test(x: Foo) {} | 2163 | fn test(x: Foo) {} |
2165 | "#), | 2164 | "#), |
2166 | @"" | 2165 | @r###" |
2166 | [59; 60) 'x': {unknown} | ||
2167 | [67; 69) '{}': () | ||
2168 | "### | ||
2167 | ) | 2169 | ) |
2168 | } | 2170 | } |
2169 | 2171 | ||
@@ -4676,10 +4678,48 @@ fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { | |||
4676 | } | 4678 | } |
4677 | 4679 | ||
4678 | #[test] | 4680 | #[test] |
4679 | // FIXME this is currently a Salsa panic; it would be nicer if it just returned | 4681 | fn trait_impl_self_ty() { |
4680 | // in Unknown, and we should be able to do that once Salsa allows us to handle | 4682 | let t = type_at( |
4681 | // the cycle. But at least it doesn't overflow for now. | 4683 | r#" |
4682 | #[should_panic] | 4684 | //- /main.rs |
4685 | trait Trait<T> { | ||
4686 | fn foo(&self); | ||
4687 | } | ||
4688 | |||
4689 | struct S; | ||
4690 | |||
4691 | impl Trait<Self> for S {} | ||
4692 | |||
4693 | fn test() { | ||
4694 | S.foo()<|>; | ||
4695 | } | ||
4696 | "#, | ||
4697 | ); | ||
4698 | assert_eq!(t, "()"); | ||
4699 | } | ||
4700 | |||
4701 | #[test] | ||
4702 | fn trait_impl_self_ty_cycle() { | ||
4703 | let t = type_at( | ||
4704 | r#" | ||
4705 | //- /main.rs | ||
4706 | trait Trait { | ||
4707 | fn foo(&self); | ||
4708 | } | ||
4709 | |||
4710 | struct S<T>; | ||
4711 | |||
4712 | impl Trait for S<Self> {} | ||
4713 | |||
4714 | fn test() { | ||
4715 | S.foo()<|>; | ||
4716 | } | ||
4717 | "#, | ||
4718 | ); | ||
4719 | assert_eq!(t, "{unknown}"); | ||
4720 | } | ||
4721 | |||
4722 | #[test] | ||
4683 | fn unselected_projection_in_trait_env_cycle_1() { | 4723 | fn unselected_projection_in_trait_env_cycle_1() { |
4684 | let t = type_at( | 4724 | let t = type_at( |
4685 | r#" | 4725 | r#" |
@@ -4700,10 +4740,6 @@ fn test<T: Trait>() where T: Trait2<T::Item> { | |||
4700 | } | 4740 | } |
4701 | 4741 | ||
4702 | #[test] | 4742 | #[test] |
4703 | // FIXME this is currently a Salsa panic; it would be nicer if it just returned | ||
4704 | // in Unknown, and we should be able to do that once Salsa allows us to handle | ||
4705 | // the cycle. But at least it doesn't overflow for now. | ||
4706 | #[should_panic] | ||
4707 | fn unselected_projection_in_trait_env_cycle_2() { | 4743 | fn unselected_projection_in_trait_env_cycle_2() { |
4708 | let t = type_at( | 4744 | let t = type_at( |
4709 | r#" | 4745 | r#" |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 35de37e6b..104346ada 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -20,8 +20,8 @@ use ra_db::salsa::{InternId, InternKey}; | |||
20 | 20 | ||
21 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; | 21 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
22 | use crate::{ | 22 | use crate::{ |
23 | db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy, | 23 | db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, |
24 | Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 24 | TraitRef, Ty, TypeCtor, TypeWalk, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | /// This represents a trait whose name we could not resolve. | 27 | /// This represents a trait whose name we could not resolve. |
@@ -630,10 +630,7 @@ fn impl_block_datum( | |||
630 | chalk_id: chalk_ir::ImplId, | 630 | chalk_id: chalk_ir::ImplId, |
631 | impl_id: ImplId, | 631 | impl_id: ImplId, |
632 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { | 632 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
633 | let trait_ref = match db.impl_ty(impl_id) { | 633 | let trait_ref = db.impl_trait(impl_id)?; |
634 | ImplTy::TraitRef(it) => it, | ||
635 | ImplTy::Inherent(_) => return None, | ||
636 | }; | ||
637 | let impl_data = db.impl_data(impl_id); | 634 | let impl_data = db.impl_data(impl_id); |
638 | 635 | ||
639 | let generic_params = db.generic_params(impl_id.into()); | 636 | let generic_params = db.generic_params(impl_id.into()); |
@@ -787,11 +784,7 @@ fn type_alias_associated_ty_value( | |||
787 | _ => panic!("assoc ty value should be in impl"), | 784 | _ => panic!("assoc ty value should be in impl"), |
788 | }; | 785 | }; |
789 | 786 | ||
790 | let trait_ref = match db.impl_ty(impl_id) { | 787 | let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved |
791 | ImplTy::TraitRef(it) => it, | ||
792 | // we don't return any assoc ty values if the impl'd trait can't be resolved | ||
793 | ImplTy::Inherent(_) => panic!("assoc ty value should not exist"), | ||
794 | }; | ||
795 | 788 | ||
796 | let assoc_ty = db | 789 | let assoc_ty = db |
797 | .trait_data(trait_ref.trait_) | 790 | .trait_data(trait_ref.trait_) |