aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs4
-rw-r--r--crates/ra_hir_ty/src/traits.rs4
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs49
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs156
4 files changed, 126 insertions, 87 deletions
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index 45164c9e9..ce9a06fde 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -865,7 +865,7 @@ mod foo {
865 865
866#[test] 866#[test]
867fn method_resolution_where_clause_for_unknown_trait() { 867fn method_resolution_where_clause_for_unknown_trait() {
868 // The blanket impl shouldn't apply because we can't even resolve UnknownTrait 868 // The blanket impl currently applies because we ignore the unresolved where clause
869 let t = type_at( 869 let t = type_at(
870 r#" 870 r#"
871//- /main.rs 871//- /main.rs
@@ -875,7 +875,7 @@ impl<T> Trait for T where T: UnknownTrait {}
875fn test() { (&S).foo()<|>; } 875fn test() { (&S).foo()<|>; }
876"#, 876"#,
877 ); 877 );
878 assert_eq!(t, "{unknown}"); 878 assert_eq!(t, "u128");
879} 879}
880 880
881#[test] 881#[test]
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs
index fbab60925..c4dc857bc 100644
--- a/crates/ra_hir_ty/src/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -291,7 +291,7 @@ impl FnTrait {
291 } 291 }
292} 292}
293 293
294#[derive(Debug, Clone, PartialEq, Eq, Hash)] 294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
295pub struct ClosureFnTraitImplData { 295pub struct ClosureFnTraitImplData {
296 def: DefWithBodyId, 296 def: DefWithBodyId,
297 expr: ExprId, 297 expr: ExprId,
@@ -300,7 +300,7 @@ pub struct ClosureFnTraitImplData {
300 300
301/// An impl. Usually this comes from an impl block, but some built-in types get 301/// An impl. Usually this comes from an impl block, but some built-in types get
302/// synthetic impls. 302/// synthetic impls.
303#[derive(Debug, Clone, PartialEq, Eq, Hash)] 303#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
304pub enum Impl { 304pub enum Impl {
305 /// A normal impl from an impl block. 305 /// A normal impl from an impl block.
306 ImplBlock(ImplId), 306 ImplBlock(ImplId),
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index cd587a338..dd41176f0 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -28,24 +28,24 @@ pub(super) fn get_builtin_impls(
28 trait_: TraitId, 28 trait_: TraitId,
29 mut callback: impl FnMut(Impl), 29 mut callback: impl FnMut(Impl),
30) { 30) {
31 // Note: since impl_datum needs to be infallible, we need to make sure here
32 // that we have all prerequisites to build the respective impls.
31 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { 33 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
32 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() 34 for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
33 { 35 {
34 if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { 36 if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) {
35 if trait_ == actual_trait { 37 if trait_ == actual_trait {
36 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; 38 let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
37 callback(Impl::ClosureFnTraitImpl(impl_)); 39 if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
40 callback(Impl::ClosureFnTraitImpl(impl_));
41 }
38 } 42 }
39 } 43 }
40 } 44 }
41 } 45 }
42} 46}
43 47
44pub(super) fn impl_datum( 48pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData {
45 db: &impl HirDatabase,
46 krate: CrateId,
47 impl_: Impl,
48) -> Option<BuiltinImplData> {
49 match impl_ { 49 match impl_ {
50 Impl::ImplBlock(_) => unreachable!(), 50 Impl::ImplBlock(_) => unreachable!(),
51 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), 51 Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data),
@@ -65,21 +65,38 @@ pub(super) fn associated_ty_value(
65 } 65 }
66} 66}
67 67
68fn check_closure_fn_trait_impl_prerequisites(
69 db: &impl HirDatabase,
70 krate: CrateId,
71 data: super::ClosureFnTraitImplData,
72) -> bool {
73 // the respective Fn/FnOnce/FnMut trait needs to exist
74 if get_fn_trait(db, krate, data.fn_trait).is_none() {
75 return false;
76 }
77
78 // FIXME: there are more assumptions that we should probably check here:
79 // the traits having no type params, FnOnce being a supertrait
80
81 // the FnOnce trait needs to exist and have an assoc type named Output
82 let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) {
83 Some(t) => t,
84 None => return false,
85 };
86 db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some()
87}
88
68fn closure_fn_trait_impl_datum( 89fn closure_fn_trait_impl_datum(
69 db: &impl HirDatabase, 90 db: &impl HirDatabase,
70 krate: CrateId, 91 krate: CrateId,
71 data: super::ClosureFnTraitImplData, 92 data: super::ClosureFnTraitImplData,
72) -> Option<BuiltinImplData> { 93) -> BuiltinImplData {
73 // for some closure |X, Y| -> Z: 94 // for some closure |X, Y| -> Z:
74 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } 95 // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
75 96
76 let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait 97 let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait
77 98 // the existence of the Fn trait has been checked before
78 // validate FnOnce trait, since we need it in the assoc ty value definition 99 .expect("fn trait for closure impl missing");
79 // and don't want to return a valid value only to find out later that FnOnce
80 // is broken
81 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
82 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
83 100
84 let num_args: u16 = match &db.body(data.def.into())[data.expr] { 101 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
85 Expr::Lambda { args, .. } => args.len() as u16, 102 Expr::Lambda { args, .. } => args.len() as u16,
@@ -107,12 +124,12 @@ fn closure_fn_trait_impl_datum(
107 124
108 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); 125 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone());
109 126
110 Some(BuiltinImplData { 127 BuiltinImplData {
111 num_vars: num_args as usize + 1, 128 num_vars: num_args as usize + 1,
112 trait_ref, 129 trait_ref,
113 where_clauses: Vec::new(), 130 where_clauses: Vec::new(),
114 assoc_ty_values: vec![output_ty_id], 131 assoc_ty_values: vec![output_ty_id],
115 }) 132 }
116} 133}
117 134
118fn closure_fn_trait_output_assoc_ty_value( 135fn closure_fn_trait_output_assoc_ty_value(
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index d53d3fdeb..9e38337e5 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -1,5 +1,5 @@
1//! Conversion code from/to Chalk. 1//! Conversion code from/to Chalk.
2use std::sync::Arc; 2use std::{fmt, sync::Arc};
3 3
4use log::debug; 4use log::debug;
5 5
@@ -17,7 +17,73 @@ use crate::{
17 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 17 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
18}; 18};
19 19
20pub type TypeFamily = chalk_ir::family::ChalkIr; 20#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
21pub struct TypeFamily {}
22
23impl chalk_ir::family::TypeFamily for TypeFamily {
24 type InternedType = Box<chalk_ir::TyData<Self>>;
25 type InternedLifetime = chalk_ir::LifetimeData<Self>;
26 type InternedParameter = chalk_ir::ParameterData<Self>;
27 type DefId = InternId;
28
29 // FIXME: implement these
30 fn debug_struct_id(
31 _type_kind_id: chalk_ir::StructId<Self>,
32 _fmt: &mut fmt::Formatter<'_>,
33 ) -> Option<fmt::Result> {
34 None
35 }
36
37 fn debug_trait_id(
38 _type_kind_id: chalk_ir::TraitId<Self>,
39 _fmt: &mut fmt::Formatter<'_>,
40 ) -> Option<fmt::Result> {
41 None
42 }
43
44 fn debug_assoc_type_id(
45 _id: chalk_ir::AssocTypeId<Self>,
46 _fmt: &mut fmt::Formatter<'_>,
47 ) -> Option<fmt::Result> {
48 None
49 }
50
51 fn debug_projection(
52 _projection: &chalk_ir::ProjectionTy<Self>,
53 _fmt: &mut fmt::Formatter<'_>,
54 ) -> Option<fmt::Result> {
55 None
56 }
57
58 fn intern_ty(ty: chalk_ir::TyData<Self>) -> Box<chalk_ir::TyData<Self>> {
59 Box::new(ty)
60 }
61
62 fn ty_data(ty: &Box<chalk_ir::TyData<Self>>) -> &chalk_ir::TyData<Self> {
63 ty
64 }
65
66 fn intern_lifetime(lifetime: chalk_ir::LifetimeData<Self>) -> chalk_ir::LifetimeData<Self> {
67 lifetime
68 }
69
70 fn lifetime_data(lifetime: &chalk_ir::LifetimeData<Self>) -> &chalk_ir::LifetimeData<Self> {
71 lifetime
72 }
73
74 fn intern_parameter(parameter: chalk_ir::ParameterData<Self>) -> chalk_ir::ParameterData<Self> {
75 parameter
76 }
77
78 fn parameter_data(parameter: &chalk_ir::ParameterData<Self>) -> &chalk_ir::ParameterData<Self> {
79 parameter
80 }
81}
82
83impl chalk_ir::family::HasTypeFamily for TypeFamily {
84 type TypeFamily = Self;
85}
86
21pub type AssocTypeId = chalk_ir::AssocTypeId<TypeFamily>; 87pub type AssocTypeId = chalk_ir::AssocTypeId<TypeFamily>;
22pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<TypeFamily>; 88pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum<TypeFamily>;
23pub type TraitId = chalk_ir::TraitId<TypeFamily>; 89pub type TraitId = chalk_ir::TraitId<TypeFamily>;
@@ -29,9 +95,6 @@ pub type ImplDatum = chalk_rust_ir::ImplDatum<TypeFamily>;
29pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; 95pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId;
30pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<TypeFamily>; 96pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue<TypeFamily>;
31 97
32/// This represents a trait whose name we could not resolve.
33const UNKNOWN_TRAIT: TraitId = chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() });
34
35pub(super) trait ToChalk { 98pub(super) trait ToChalk {
36 type Chalk; 99 type Chalk;
37 fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; 100 fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk;
@@ -162,11 +225,11 @@ impl ToChalk for hir_def::TraitId {
162 type Chalk = TraitId; 225 type Chalk = TraitId;
163 226
164 fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { 227 fn to_chalk(self, _db: &impl HirDatabase) -> TraitId {
165 chalk_ir::TraitId(id_to_chalk(self)) 228 chalk_ir::TraitId(self.as_intern_id())
166 } 229 }
167 230
168 fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { 231 fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId {
169 id_from_chalk(trait_id.0) 232 InternKey::from_intern_id(trait_id.0)
170 } 233 }
171} 234}
172 235
@@ -215,11 +278,11 @@ impl ToChalk for TypeAliasId {
215 type Chalk = AssocTypeId; 278 type Chalk = AssocTypeId;
216 279
217 fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { 280 fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId {
218 chalk_ir::AssocTypeId(id_to_chalk(self)) 281 chalk_ir::AssocTypeId(self.as_intern_id())
219 } 282 }
220 283
221 fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { 284 fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId {
222 id_from_chalk(type_alias_id.0) 285 InternKey::from_intern_id(type_alias_id.0)
223 } 286 }
224} 287}
225 288
@@ -250,13 +313,7 @@ impl ToChalk for GenericPredicate {
250 }), 313 }),
251 0, 314 0,
252 ), 315 ),
253 GenericPredicate::Error => { 316 GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
254 let impossible_trait_ref = chalk_ir::TraitRef {
255 trait_id: UNKNOWN_TRAIT,
256 parameters: vec![Ty::Unknown.to_chalk(db).cast()],
257 };
258 make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0)
259 }
260 } 317 }
261 } 318 }
262 319
@@ -266,10 +323,6 @@ impl ToChalk for GenericPredicate {
266 ) -> GenericPredicate { 323 ) -> GenericPredicate {
267 match where_clause.value { 324 match where_clause.value {
268 chalk_ir::WhereClause::Implemented(tr) => { 325 chalk_ir::WhereClause::Implemented(tr) => {
269 if tr.trait_id == UNKNOWN_TRAIT {
270 // FIXME we need an Error enum on the Chalk side to avoid this
271 return GenericPredicate::Error;
272 }
273 GenericPredicate::Implemented(from_chalk(db, tr)) 326 GenericPredicate::Implemented(from_chalk(db, tr))
274 } 327 }
275 chalk_ir::WhereClause::ProjectionEq(projection_eq) => { 328 chalk_ir::WhereClause::ProjectionEq(projection_eq) => {
@@ -460,9 +513,8 @@ fn convert_where_clauses(
460 let mut result = Vec::with_capacity(generic_predicates.len()); 513 let mut result = Vec::with_capacity(generic_predicates.len());
461 for pred in generic_predicates.iter() { 514 for pred in generic_predicates.iter() {
462 if pred.is_error() { 515 if pred.is_error() {
463 // HACK: Return just the single predicate (which is always false 516 // skip errored predicates completely
464 // anyway), otherwise Chalk can easily get into slow situations 517 continue;
465 return vec![pred.clone().subst(substs).to_chalk(db)];
466 } 518 }
467 result.push(pred.clone().subst(substs).to_chalk(db)); 519 result.push(pred.clone().subst(substs).to_chalk(db));
468 } 520 }
@@ -491,10 +543,11 @@ where
491 parameters: &[Parameter<TypeFamily>], 543 parameters: &[Parameter<TypeFamily>],
492 ) -> Vec<ImplId> { 544 ) -> Vec<ImplId> {
493 debug!("impls_for_trait {:?}", trait_id); 545 debug!("impls_for_trait {:?}", trait_id);
494 if trait_id == UNKNOWN_TRAIT {
495 return Vec::new();
496 }
497 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); 546 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id);
547
548 // Note: Since we're using impls_for_trait, only impls where the trait
549 // can be resolved should ever reach Chalk. `impl_datum` relies on that
550 // and will panic if the trait can't be resolved.
498 let mut result: Vec<_> = self 551 let mut result: Vec<_> = self
499 .db 552 .db
500 .impls_for_trait(self.krate, trait_.into()) 553 .impls_for_trait(self.krate, trait_.into())
@@ -566,24 +619,6 @@ pub(crate) fn trait_datum_query(
566 trait_id: TraitId, 619 trait_id: TraitId,
567) -> Arc<TraitDatum> { 620) -> Arc<TraitDatum> {
568 debug!("trait_datum {:?}", trait_id); 621 debug!("trait_datum {:?}", trait_id);
569 if trait_id == UNKNOWN_TRAIT {
570 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() };
571
572 let flags = chalk_rust_ir::TraitFlags {
573 auto: false,
574 marker: false,
575 upstream: true,
576 fundamental: false,
577 non_enumerable: true,
578 coinductive: false,
579 };
580 return Arc::new(TraitDatum {
581 id: trait_id,
582 binders: make_binders(trait_datum_bound, 1),
583 flags,
584 associated_ty_ids: vec![],
585 });
586 }
587 let trait_: hir_def::TraitId = from_chalk(db, trait_id); 622 let trait_: hir_def::TraitId = from_chalk(db, trait_id);
588 let trait_data = db.trait_data(trait_); 623 let trait_data = db.trait_data(trait_);
589 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 624 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
@@ -653,9 +688,8 @@ pub(crate) fn impl_datum_query(
653 let impl_: Impl = from_chalk(db, impl_id); 688 let impl_: Impl = from_chalk(db, impl_id);
654 match impl_ { 689 match impl_ {
655 Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), 690 Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block),
656 _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), 691 _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)),
657 } 692 }
658 .unwrap_or_else(invalid_impl_datum)
659} 693}
660 694
661fn impl_block_datum( 695fn impl_block_datum(
@@ -663,8 +697,11 @@ fn impl_block_datum(
663 krate: CrateId, 697 krate: CrateId,
664 chalk_id: ImplId, 698 chalk_id: ImplId,
665 impl_id: hir_def::ImplId, 699 impl_id: hir_def::ImplId,
666) -> Option<Arc<ImplDatum>> { 700) -> Arc<ImplDatum> {
667 let trait_ref = db.impl_trait(impl_id)?; 701 let trait_ref = db
702 .impl_trait(impl_id)
703 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
704 .expect("invalid impl passed to Chalk");
668 let impl_data = db.impl_data(impl_id); 705 let impl_data = db.impl_data(impl_id);
669 706
670 let generic_params = generics(db, impl_id.into()); 707 let generic_params = generics(db, impl_id.into());
@@ -716,21 +753,6 @@ fn impl_block_datum(
716 polarity, 753 polarity,
717 associated_ty_value_ids, 754 associated_ty_value_ids,
718 }; 755 };
719 Some(Arc::new(impl_datum))
720}
721
722fn invalid_impl_datum() -> Arc<ImplDatum> {
723 let trait_ref = chalk_ir::TraitRef {
724 trait_id: UNKNOWN_TRAIT,
725 parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()],
726 };
727 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() };
728 let impl_datum = ImplDatum {
729 binders: make_binders(impl_datum_bound, 1),
730 impl_type: chalk_rust_ir::ImplType::External,
731 polarity: chalk_rust_ir::Polarity::Positive,
732 associated_ty_value_ids: Vec::new(),
733 };
734 Arc::new(impl_datum) 756 Arc::new(impl_datum)
735} 757}
736 758
@@ -786,25 +808,25 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
786 808
787impl From<StructId> for crate::TypeCtorId { 809impl From<StructId> for crate::TypeCtorId {
788 fn from(struct_id: StructId) -> Self { 810 fn from(struct_id: StructId) -> Self {
789 id_from_chalk(struct_id.0) 811 InternKey::from_intern_id(struct_id.0)
790 } 812 }
791} 813}
792 814
793impl From<crate::TypeCtorId> for StructId { 815impl From<crate::TypeCtorId> for StructId {
794 fn from(type_ctor_id: crate::TypeCtorId) -> Self { 816 fn from(type_ctor_id: crate::TypeCtorId) -> Self {
795 chalk_ir::StructId(id_to_chalk(type_ctor_id)) 817 chalk_ir::StructId(type_ctor_id.as_intern_id())
796 } 818 }
797} 819}
798 820
799impl From<ImplId> for crate::traits::GlobalImplId { 821impl From<ImplId> for crate::traits::GlobalImplId {
800 fn from(impl_id: ImplId) -> Self { 822 fn from(impl_id: ImplId) -> Self {
801 id_from_chalk(impl_id.0) 823 InternKey::from_intern_id(impl_id.0)
802 } 824 }
803} 825}
804 826
805impl From<crate::traits::GlobalImplId> for ImplId { 827impl From<crate::traits::GlobalImplId> for ImplId {
806 fn from(impl_id: crate::traits::GlobalImplId) -> Self { 828 fn from(impl_id: crate::traits::GlobalImplId) -> Self {
807 chalk_ir::ImplId(id_to_chalk(impl_id)) 829 chalk_ir::ImplId(impl_id.as_intern_id())
808 } 830 }
809} 831}
810 832