aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-03-04 22:00:44 +0000
committerFlorian Diebold <[email protected]>2020-06-05 16:08:27 +0100
commit02962b374ecefd6f2a75956f4fb18806531d1d51 (patch)
tree7c807d6a09db7e485ea39c3e67331b99829a364c /crates/ra_hir_ty
parent9c52f527a1cef7d39c2b1c55b49dc5459d392a4d (diff)
Implement return position impl trait / opaque type support
This is working, but I'm not that happy with how the lowering works. We might need an additional representation between `TypeRef` and `Ty` where names are resolved and `impl Trait` bounds are separated out, but things like inference variables don't exist and `impl Trait` is always represented the same way. Also note that this doesn't implement correct handling of RPIT *inside* the function (which involves turning the `impl Trait`s into variables and creating obligations for them). That intermediate representation might help there as well.
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/db.rs20
-rw-r--r--crates/ra_hir_ty/src/display.rs37
-rw-r--r--crates/ra_hir_ty/src/infer.rs23
-rw-r--r--crates/ra_hir_ty/src/lib.rs98
-rw-r--r--crates/ra_hir_ty/src/lower.rs143
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs47
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs52
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/interner.rs2
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs45
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs5
10 files changed, 395 insertions, 77 deletions
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
index 0a8bb24ac..bf71d38d6 100644
--- a/crates/ra_hir_ty/src/db.rs
+++ b/crates/ra_hir_ty/src/db.rs
@@ -3,8 +3,8 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{ 5use hir_def::{
6 db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalFieldId, TraitId, TypeParamId, 6 db::DefDatabase, DefWithBodyId, FunctionId, GenericDefId, ImplId, LocalFieldId, TraitId,
7 VariantId, 7 TypeParamId, VariantId,
8}; 8};
9use ra_arena::map::ArenaMap; 9use ra_arena::map::ArenaMap;
10use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; 10use ra_db::{impl_intern_key, salsa, CrateId, Upcast};
@@ -13,8 +13,8 @@ use ra_prof::profile;
13use crate::{ 13use crate::{
14 method_resolution::{CrateImplDefs, TyFingerprint}, 14 method_resolution::{CrateImplDefs, TyFingerprint},
15 traits::{chalk, AssocTyValue, Impl}, 15 traits::{chalk, AssocTyValue, Impl},
16 Binders, CallableDef, GenericPredicate, InferenceResult, PolyFnSig, Substs, TraitRef, Ty, 16 Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig,
17 TyDefId, TypeCtor, ValueTyDefId, 17 ReturnTypeImplTraits, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId,
18}; 18};
19use hir_expand::name::Name; 19use hir_expand::name::Name;
20 20
@@ -48,6 +48,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
48 #[salsa::invoke(crate::callable_item_sig)] 48 #[salsa::invoke(crate::callable_item_sig)]
49 fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig; 49 fn callable_item_signature(&self, def: CallableDef) -> PolyFnSig;
50 50
51 #[salsa::invoke(crate::lower::return_type_impl_traits)]
52 fn return_type_impl_traits(
53 &self,
54 def: FunctionId,
55 ) -> Option<Arc<Binders<ReturnTypeImplTraits>>>;
56
51 #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] 57 #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
52 #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] 58 #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
53 fn generic_predicates_for_param( 59 fn generic_predicates_for_param(
@@ -80,6 +86,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
80 #[salsa::interned] 86 #[salsa::interned]
81 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId; 87 fn intern_type_param_id(&self, param_id: TypeParamId) -> GlobalTypeParamId;
82 #[salsa::interned] 88 #[salsa::interned]
89 fn intern_impl_trait_id(&self, id: OpaqueTyId) -> InternedOpaqueTyId;
90 #[salsa::interned]
83 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId; 91 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
84 #[salsa::interned] 92 #[salsa::interned]
85 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; 93 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
@@ -142,3 +150,7 @@ fn hir_database_is_object_safe() {
142#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 150#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
143pub struct GlobalTypeParamId(salsa::InternId); 151pub struct GlobalTypeParamId(salsa::InternId);
144impl_intern_key!(GlobalTypeParamId); 152impl_intern_key!(GlobalTypeParamId);
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
155pub struct InternedOpaqueTyId(salsa::InternId);
156impl_intern_key!(InternedOpaqueTyId);
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index b9c4d2e89..3e63a2415 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -359,6 +359,21 @@ impl HirDisplay for ApplicationTy {
359 write!(f, ">")?; 359 write!(f, ">")?;
360 } 360 }
361 } 361 }
362 TypeCtor::OpaqueType(opaque_ty_id) => {
363 let bounds = match opaque_ty_id {
364 crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
365 let datas =
366 f.db.return_type_impl_traits(func).expect("impl trait id without data");
367 let data = (*datas)
368 .as_ref()
369 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
370 data.clone().subst(&self.parameters)
371 }
372 };
373 write!(f, "impl ")?;
374 write_bounds_like_dyn_trait(&bounds.value, f)?;
375 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
376 }
362 TypeCtor::Closure { .. } => { 377 TypeCtor::Closure { .. } => {
363 let sig = self.parameters[0].callable_sig(f.db); 378 let sig = self.parameters[0].callable_sig(f.db);
364 if let Some(sig) = sig { 379 if let Some(sig) = sig {
@@ -427,14 +442,24 @@ impl HirDisplay for Ty {
427 } 442 }
428 } 443 }
429 Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 444 Ty::Bound(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
430 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 445 Ty::Dyn(predicates) => {
431 match self { 446 write!(f, "dyn ")?;
432 Ty::Dyn(_) => write!(f, "dyn ")?,
433 Ty::Opaque(_) => write!(f, "impl ")?,
434 _ => unreachable!(),
435 };
436 write_bounds_like_dyn_trait(predicates, f)?; 447 write_bounds_like_dyn_trait(predicates, f)?;
437 } 448 }
449 Ty::Opaque(opaque_ty) => {
450 let bounds = match opaque_ty.opaque_ty_id {
451 crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
452 let datas =
453 f.db.return_type_impl_traits(func).expect("impl trait id without data");
454 let data = (*datas)
455 .as_ref()
456 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
457 data.clone().subst(&opaque_ty.parameters)
458 }
459 };
460 write!(f, "impl ")?;
461 write_bounds_like_dyn_trait(&bounds.value, f)?;
462 }
438 Ty::Unknown => write!(f, "{{unknown}}")?, 463 Ty::Unknown => write!(f, "{{unknown}}")?,
439 Ty::Infer(..) => write!(f, "_")?, 464 Ty::Infer(..) => write!(f, "_")?,
440 } 465 }
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index dc77e88e5..d9bf3c2f0 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -39,8 +39,8 @@ use ra_syntax::SmolStr;
39use super::{ 39use super::{
40 primitive::{FloatTy, IntTy}, 40 primitive::{FloatTy, IntTy},
41 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 41 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
42 ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, 42 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
43 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, 43 TypeWalk, Uncertain,
44}; 44};
45use crate::{ 45use crate::{
46 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 46 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
@@ -383,25 +383,6 @@ impl<'a> InferenceContext<'a> {
383 ) -> Ty { 383 ) -> Ty {
384 match assoc_ty { 384 match assoc_ty {
385 Some(res_assoc_ty) => { 385 Some(res_assoc_ty) => {
386 // FIXME:
387 // Check if inner_ty is is `impl Trait` and contained input TypeAlias id
388 // this is a workaround while Chalk assoc type projection doesn't always work yet,
389 // but once that is fixed I don't think we should keep this
390 // (we'll probably change how associated types are resolved anyway)
391 if let Ty::Opaque(ref predicates) = inner_ty {
392 for p in predicates.iter() {
393 if let GenericPredicate::Projection(projection) = p {
394 if projection.projection_ty.associated_ty == res_assoc_ty {
395 if let ty_app!(_, params) = &projection.ty {
396 if params.len() == 0 {
397 return projection.ty.clone();
398 }
399 }
400 }
401 }
402 }
403 }
404
405 let ty = self.table.new_type_var(); 386 let ty = self.table.new_type_var();
406 let builder = Substs::build_for_def(self.db, res_assoc_ty) 387 let builder = Substs::build_for_def(self.db, res_assoc_ty)
407 .push(inner_ty) 388 .push(inner_ty)
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 9fa8d3bdc..135976fcd 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -147,6 +147,12 @@ pub enum TypeCtor {
147 /// an **application type** like `(Iterator::Item)<T>`. 147 /// an **application type** like `(Iterator::Item)<T>`.
148 AssociatedType(TypeAliasId), 148 AssociatedType(TypeAliasId),
149 149
150 /// This represents a placeholder for an opaque type in situations where we
151 /// don't know the hidden type (i.e. currently almost always). This is
152 /// analogous to the `AssociatedType` type constructor. As with that one,
153 /// these are only produced by Chalk.
154 OpaqueType(OpaqueTyId),
155
150 /// The type of a specific closure. 156 /// The type of a specific closure.
151 /// 157 ///
152 /// The closure signature is stored in a `FnPtr` type in the first type 158 /// The closure signature is stored in a `FnPtr` type in the first type
@@ -194,6 +200,14 @@ impl TypeCtor {
194 let generic_params = generics(db.upcast(), type_alias.into()); 200 let generic_params = generics(db.upcast(), type_alias.into());
195 generic_params.len() 201 generic_params.len()
196 } 202 }
203 TypeCtor::OpaqueType(opaque_ty_id) => {
204 match opaque_ty_id {
205 OpaqueTyId::ReturnTypeImplTrait(func, _) => {
206 let generic_params = generics(db.upcast(), func.into());
207 generic_params.len()
208 }
209 }
210 }
197 TypeCtor::FnPtr { num_args } => num_args as usize + 1, 211 TypeCtor::FnPtr { num_args } => num_args as usize + 1,
198 TypeCtor::Tuple { cardinality } => cardinality as usize, 212 TypeCtor::Tuple { cardinality } => cardinality as usize,
199 } 213 }
@@ -220,6 +234,11 @@ impl TypeCtor {
220 TypeCtor::AssociatedType(type_alias) => { 234 TypeCtor::AssociatedType(type_alias) => {
221 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate) 235 Some(type_alias.lookup(db.upcast()).module(db.upcast()).krate)
222 } 236 }
237 TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id {
238 OpaqueTyId::ReturnTypeImplTrait(func, _) => {
239 Some(func.lookup(db.upcast()).module(db.upcast()).krate)
240 }
241 },
223 } 242 }
224 } 243 }
225 244
@@ -241,6 +260,7 @@ impl TypeCtor {
241 TypeCtor::Adt(adt) => Some(adt.into()), 260 TypeCtor::Adt(adt) => Some(adt.into()),
242 TypeCtor::FnDef(callable) => Some(callable.into()), 261 TypeCtor::FnDef(callable) => Some(callable.into()),
243 TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()), 262 TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()),
263 TypeCtor::OpaqueType(_impl_trait_id) => None,
244 } 264 }
245 } 265 }
246} 266}
@@ -254,6 +274,12 @@ pub struct ApplicationTy {
254 pub parameters: Substs, 274 pub parameters: Substs,
255} 275}
256 276
277#[derive(Clone, PartialEq, Eq, Debug, Hash)]
278pub struct OpaqueTy {
279 pub opaque_ty_id: OpaqueTyId,
280 pub parameters: Substs,
281}
282
257/// A "projection" type corresponds to an (unnormalized) 283/// A "projection" type corresponds to an (unnormalized)
258/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the 284/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
259/// trait and all its parameters are fully known. 285/// trait and all its parameters are fully known.
@@ -308,6 +334,12 @@ pub enum Ty {
308 /// trait and all its parameters are fully known. 334 /// trait and all its parameters are fully known.
309 Projection(ProjectionTy), 335 Projection(ProjectionTy),
310 336
337 /// An opaque type (`impl Trait`).
338 ///
339 /// This is currently only used for return type impl trait; each instance of
340 /// `impl Trait` in a return type gets its own ID.
341 Opaque(OpaqueTy),
342
311 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) 343 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
312 /// {}` when we're type-checking the body of that function. In this 344 /// {}` when we're type-checking the body of that function. In this
313 /// situation, we know this stands for *some* type, but don't know the exact 345 /// situation, we know this stands for *some* type, but don't know the exact
@@ -332,12 +364,6 @@ pub enum Ty {
332 /// didn't seem worth the overhead yet. 364 /// didn't seem worth the overhead yet.
333 Dyn(Arc<[GenericPredicate]>), 365 Dyn(Arc<[GenericPredicate]>),
334 366
335 /// An opaque type (`impl Trait`).
336 ///
337 /// The predicates are quantified over the `Self` type; see `Ty::Dyn` for
338 /// more.
339 Opaque(Arc<[GenericPredicate]>),
340
341 /// A placeholder for a type which could not be computed; this is propagated 367 /// A placeholder for a type which could not be computed; this is propagated
342 /// to avoid useless error messages. Doubles as a placeholder where type 368 /// to avoid useless error messages. Doubles as a placeholder where type
343 /// variables are inserted before type checking, since we want to try to 369 /// variables are inserted before type checking, since we want to try to
@@ -490,7 +516,7 @@ impl Deref for Substs {
490 } 516 }
491} 517}
492 518
493#[derive(Copy, Clone, PartialEq, Eq, Debug)] 519#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
494pub struct Binders<T> { 520pub struct Binders<T> {
495 pub num_binders: usize, 521 pub num_binders: usize,
496 pub value: T, 522 pub value: T,
@@ -534,6 +560,20 @@ impl<T: TypeWalk> Binders<T> {
534 } 560 }
535} 561}
536 562
563impl<T: TypeWalk> TypeWalk for Binders<T> {
564 fn walk(&self, f: &mut impl FnMut(&Ty)) {
565 self.value.walk(f);
566 }
567
568 fn walk_mut_binders(
569 &mut self,
570 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
571 binders: DebruijnIndex,
572 ) {
573 self.value.walk_mut_binders(f, binders.shifted_in())
574 }
575}
576
537/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. 577/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
538/// Name to be bikeshedded: TraitBound? TraitImplements? 578/// Name to be bikeshedded: TraitBound? TraitImplements?
539#[derive(Clone, PartialEq, Eq, Debug, Hash)] 579#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -947,11 +987,16 @@ impl TypeWalk for Ty {
947 t.walk(f); 987 t.walk(f);
948 } 988 }
949 } 989 }
950 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 990 Ty::Dyn(predicates) => {
951 for p in predicates.iter() { 991 for p in predicates.iter() {
952 p.walk(f); 992 p.walk(f);
953 } 993 }
954 } 994 }
995 Ty::Opaque(o_ty) => {
996 for t in o_ty.parameters.iter() {
997 t.walk(f);
998 }
999 }
955 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 1000 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
956 } 1001 }
957 f(self); 1002 f(self);
@@ -969,13 +1014,48 @@ impl TypeWalk for Ty {
969 Ty::Projection(p_ty) => { 1014 Ty::Projection(p_ty) => {
970 p_ty.parameters.walk_mut_binders(f, binders); 1015 p_ty.parameters.walk_mut_binders(f, binders);
971 } 1016 }
972 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 1017 Ty::Dyn(predicates) => {
973 for p in make_mut_slice(predicates) { 1018 for p in make_mut_slice(predicates) {
974 p.walk_mut_binders(f, binders.shifted_in()); 1019 p.walk_mut_binders(f, binders.shifted_in());
975 } 1020 }
976 } 1021 }
1022 Ty::Opaque(o_ty) => {
1023 o_ty.parameters.walk_mut_binders(f, binders);
1024 }
977 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} 1025 Ty::Placeholder { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
978 } 1026 }
979 f(self, binders); 1027 f(self, binders);
980 } 1028 }
981} 1029}
1030
1031impl<T: TypeWalk> TypeWalk for Vec<T> {
1032 fn walk(&self, f: &mut impl FnMut(&Ty)) {
1033 for t in self {
1034 t.walk(f);
1035 }
1036 }
1037 fn walk_mut_binders(
1038 &mut self,
1039 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
1040 binders: DebruijnIndex,
1041 ) {
1042 for t in self {
1043 t.walk_mut_binders(f, binders);
1044 }
1045 }
1046}
1047
1048#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
1049pub enum OpaqueTyId {
1050 ReturnTypeImplTrait(hir_def::FunctionId, u16),
1051}
1052
1053#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1054pub struct ReturnTypeImplTraits {
1055 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
1056}
1057
1058#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1059pub(crate) struct ReturnTypeImplTrait {
1060 pub(crate) bounds: Binders<Vec<GenericPredicate>>,
1061}
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 35ac86a46..dfc018b0b 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -31,8 +31,9 @@ use crate::{
31 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 31 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
32 make_mut_slice, variant_data, 32 make_mut_slice, variant_data,
33 }, 33 },
34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, 34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig,
35 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 35 ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs,
36 TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
36}; 37};
37use hir_expand::name::Name; 38use hir_expand::name::Name;
38 39
@@ -47,7 +48,16 @@ pub struct TyLoweringContext<'a> {
47 /// possible currently, so this should be fine for now. 48 /// possible currently, so this should be fine for now.
48 pub type_param_mode: TypeParamLoweringMode, 49 pub type_param_mode: TypeParamLoweringMode,
49 pub impl_trait_mode: ImplTraitLoweringMode, 50 pub impl_trait_mode: ImplTraitLoweringMode,
50 pub impl_trait_counter: std::cell::Cell<u16>, 51 impl_trait_counter: std::cell::Cell<u16>,
52 /// When turning `impl Trait` into opaque types, we have to collect the
53 /// bounds at the same time to get the IDs correct (without becoming too
54 /// complicated). I don't like using interior mutability (as for the
55 /// counter), but I've tried and failed to make the lifetimes work for
56 /// passing around a `&mut TyLoweringContext`. The core problem is that
57 /// we're grouping the mutable data (the counter and this field) together
58 /// with the immutable context (the references to the DB and resolver).
59 /// Splitting this up would be a possible fix.
60 opaque_type_data: std::cell::RefCell<Vec<ReturnTypeImplTrait>>,
51} 61}
52 62
53impl<'a> TyLoweringContext<'a> { 63impl<'a> TyLoweringContext<'a> {
@@ -56,26 +66,42 @@ impl<'a> TyLoweringContext<'a> {
56 let impl_trait_mode = ImplTraitLoweringMode::Disallowed; 66 let impl_trait_mode = ImplTraitLoweringMode::Disallowed;
57 let type_param_mode = TypeParamLoweringMode::Placeholder; 67 let type_param_mode = TypeParamLoweringMode::Placeholder;
58 let in_binders = DebruijnIndex::INNERMOST; 68 let in_binders = DebruijnIndex::INNERMOST;
59 Self { db, resolver, in_binders, impl_trait_mode, impl_trait_counter, type_param_mode } 69 let opaque_type_data = std::cell::RefCell::new(Vec::new());
70 Self {
71 db,
72 resolver,
73 in_binders,
74 impl_trait_mode,
75 impl_trait_counter,
76 type_param_mode,
77 opaque_type_data,
78 }
60 } 79 }
61 80
62 pub fn with_shifted_in<T>( 81 pub fn with_debruijn<T>(
63 &self, 82 &self,
64 debruijn: DebruijnIndex, 83 debruijn: DebruijnIndex,
65 f: impl FnOnce(&TyLoweringContext) -> T, 84 f: impl FnOnce(&TyLoweringContext) -> T,
66 ) -> T { 85 ) -> T {
86 let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new());
67 let new_ctx = Self { 87 let new_ctx = Self {
68 in_binders: self.in_binders.shifted_in_from(debruijn), 88 in_binders: debruijn,
69 impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), 89 impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()),
90 opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec),
70 ..*self 91 ..*self
71 }; 92 };
72 let result = f(&new_ctx); 93 let result = f(&new_ctx);
73 self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); 94 self.impl_trait_counter.set(new_ctx.impl_trait_counter.get());
95 self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner());
74 result 96 result
75 } 97 }
76 98
77 pub fn shifted_in(self, debruijn: DebruijnIndex) -> Self { 99 pub fn with_shifted_in<T>(
78 Self { in_binders: self.in_binders.shifted_in_from(debruijn), ..self } 100 &self,
101 debruijn: DebruijnIndex,
102 f: impl FnOnce(&TyLoweringContext) -> T,
103 ) -> T {
104 self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f)
79 } 105 }
80 106
81 pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { 107 pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
@@ -167,20 +193,47 @@ impl Ty {
167 TypeRef::ImplTrait(bounds) => { 193 TypeRef::ImplTrait(bounds) => {
168 match ctx.impl_trait_mode { 194 match ctx.impl_trait_mode {
169 ImplTraitLoweringMode::Opaque => { 195 ImplTraitLoweringMode::Opaque => {
170 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 196 let idx = ctx.impl_trait_counter.get();
171 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { 197 ctx.impl_trait_counter.set(idx + 1);
172 bounds 198
173 .iter() 199 assert!(idx as usize == ctx.opaque_type_data.borrow().len());
174 .flat_map(|b| { 200 // this dance is to make sure the data is in the right
175 GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) 201 // place even if we encounter more opaque types while
176 }) 202 // lowering the bounds
177 .collect() 203 ctx.opaque_type_data
178 }); 204 .borrow_mut()
179 Ty::Opaque(predicates) 205 .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) });
206 // We don't want to lower the bounds inside the binders
207 // we're currently in, because they don't end up inside
208 // those binders. E.g. when we have `impl Trait<impl
209 // OtherTrait<T>>`, the `impl OtherTrait<T>` can't refer
210 // to the self parameter from `impl Trait`, and the
211 // bounds aren't actually stored nested within each
212 // other, but separately. So if the `T` refers to a type
213 // parameter of the outer function, it's just one binder
214 // away instead of two.
215 let actual_opaque_type_data = ctx
216 .with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
217 ReturnTypeImplTrait::from_hir(ctx, &bounds)
218 });
219 ctx.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data;
220
221 let func = match ctx.resolver.generic_def() {
222 Some(GenericDefId::FunctionId(f)) => f,
223 _ => {
224 // this shouldn't happen
225 return (Ty::Unknown, None);
226 }
227 };
228 let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx);
229 let generics = generics(ctx.db.upcast(), func.into());
230 let parameters = Substs::bound_vars(&generics, ctx.in_binders);
231 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })
180 } 232 }
181 ImplTraitLoweringMode::Param => { 233 ImplTraitLoweringMode::Param => {
182 let idx = ctx.impl_trait_counter.get(); 234 let idx = ctx.impl_trait_counter.get();
183 ctx.impl_trait_counter.set(idx + 1); 235 // FIXME we're probably doing something wrong here
236 ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
184 if let Some(def) = ctx.resolver.generic_def() { 237 if let Some(def) = ctx.resolver.generic_def() {
185 let generics = generics(ctx.db.upcast(), def); 238 let generics = generics(ctx.db.upcast(), def);
186 let param = generics 239 let param = generics
@@ -197,7 +250,8 @@ impl Ty {
197 } 250 }
198 ImplTraitLoweringMode::Variable => { 251 ImplTraitLoweringMode::Variable => {
199 let idx = ctx.impl_trait_counter.get(); 252 let idx = ctx.impl_trait_counter.get();
200 ctx.impl_trait_counter.set(idx + 1); 253 // FIXME we're probably doing something wrong here
254 ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
201 let (parent_params, self_params, list_params, _impl_trait_params) = 255 let (parent_params, self_params, list_params, _impl_trait_params) =
202 if let Some(def) = ctx.resolver.generic_def() { 256 if let Some(def) = ctx.resolver.generic_def() {
203 let generics = generics(ctx.db.upcast(), def); 257 let generics = generics(ctx.db.upcast(), def);
@@ -663,6 +717,29 @@ fn assoc_type_bindings_from_type_bound<'a>(
663 }) 717 })
664} 718}
665 719
720impl ReturnTypeImplTrait {
721 fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self {
722 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
723 let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| {
724 bounds
725 .iter()
726 .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone()))
727 .collect()
728 });
729 ReturnTypeImplTrait { bounds: Binders::new(1, predicates) }
730 }
731}
732
733fn count_impl_traits(type_ref: &TypeRef) -> usize {
734 let mut count = 0;
735 type_ref.walk(&mut |type_ref| {
736 if matches!(type_ref, TypeRef::ImplTrait(_)) {
737 count += 1;
738 }
739 });
740 count
741}
742
666/// Build the signature of a callable item (function, struct or enum variant). 743/// Build the signature of a callable item (function, struct or enum variant).
667pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig { 744pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig {
668 match def { 745 match def {
@@ -864,7 +941,9 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
864 .with_impl_trait_mode(ImplTraitLoweringMode::Variable) 941 .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
865 .with_type_param_mode(TypeParamLoweringMode::Variable); 942 .with_type_param_mode(TypeParamLoweringMode::Variable);
866 let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); 943 let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>();
867 let ctx_ret = ctx_params.with_impl_trait_mode(ImplTraitLoweringMode::Opaque); 944 let ctx_ret = TyLoweringContext::new(db, &resolver)
945 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
946 .with_type_param_mode(TypeParamLoweringMode::Variable);
868 let ret = Ty::from_hir(&ctx_ret, &data.ret_type); 947 let ret = Ty::from_hir(&ctx_ret, &data.ret_type);
869 let generics = generics(db.upcast(), def.into()); 948 let generics = generics(db.upcast(), def.into());
870 let num_binders = generics.len(); 949 let num_binders = generics.len();
@@ -1084,3 +1163,25 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
1084 TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?, 1163 TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?,
1085 )) 1164 ))
1086} 1165}
1166
1167pub(crate) fn return_type_impl_traits(
1168 db: &impl HirDatabase,
1169 def: hir_def::FunctionId,
1170) -> Option<Arc<Binders<ReturnTypeImplTraits>>> {
1171 // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
1172 let data = db.function_data(def);
1173 let resolver = def.resolver(db.upcast());
1174 let ctx_ret = TyLoweringContext::new(db, &resolver)
1175 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1176 .with_type_param_mode(TypeParamLoweringMode::Variable);
1177 let _ret = Ty::from_hir(&ctx_ret, &data.ret_type);
1178 let generics = generics(db.upcast(), def.into());
1179 let num_binders = generics.len();
1180 let return_type_impl_traits =
1181 ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() };
1182 if return_type_impl_traits.impl_traits.is_empty() {
1183 None
1184 } else {
1185 Some(Arc::new(Binders::new(num_binders, return_type_impl_traits)))
1186 }
1187}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index e8778d419..d83dc6d79 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1110,7 +1110,6 @@ fn test() {
1110} 1110}
1111 1111
1112#[test] 1112#[test]
1113#[ignore]
1114fn impl_trait() { 1113fn impl_trait() {
1115 assert_snapshot!( 1114 assert_snapshot!(
1116 infer(r#" 1115 infer(r#"
@@ -1161,6 +1160,52 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
1161} 1160}
1162 1161
1163#[test] 1162#[test]
1163fn return_pos_impl_trait() {
1164 assert_snapshot!(
1165 infer(r#"
1166trait Iterator {
1167 type Item;
1168 fn next(&mut self) -> Self::Item;
1169}
1170trait Trait<T> {
1171 fn foo(&self) -> T;
1172}
1173fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} }
1174fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} }
1175
1176fn test() {
1177 // let (a, b) = bar();
1178 // a.next().foo();
1179 // b.foo();
1180 let (c, d) = baz(1u128);
1181 c.next();//.foo();
1182 // d.foo();
1183}
1184"#),
1185 @r###"
1186 50..54 'self': &mut Self
1187 102..106 'self': &Self
1188 185..196 '{ loop {} }': ({unknown}, {unknown})
1189 187..194 'loop {}': !
1190 192..194 '{}': ()
1191 207..208 't': T
1192 269..280 '{ loop {} }': ({unknown}, {unknown})
1193 271..278 'loop {}': !
1194 276..278 '{}': ()
1195 292..429 '{ ...o(); }': ()
1196 368..374 '(c, d)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
1197 369..370 'c': impl Iterator<Item = impl Trait<u128>>
1198 372..373 'd': impl Trait<u128>
1199 377..380 'baz': fn baz<u128>(u128) -> (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
1200 377..387 'baz(1u128)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
1201 381..386 '1u128': u128
1202 393..394 'c': impl Iterator<Item = impl Trait<u128>>
1203 393..401 'c.next()': impl Trait<u128>
1204 "###
1205 );
1206}
1207
1208#[test]
1164fn dyn_trait() { 1209fn dyn_trait() {
1165 assert_snapshot!( 1210 assert_snapshot!(
1166 infer(r#" 1211 infer(r#"
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 61de3cc30..a72a82f5a 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -4,7 +4,7 @@ use std::sync::Arc;
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{fold::shift::Shift, GenericArg, TypeName}; 6use chalk_ir::{fold::shift::Shift, GenericArg, TypeName};
7use chalk_solve::rust_ir::{self, WellKnownTrait}; 7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 8
9use hir_def::{ 9use hir_def::{
10 lang_item::{lang_attr, LangItemTarget}, 10 lang_item::{lang_attr, LangItemTarget},
@@ -100,6 +100,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
100 fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> { 100 fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc<AssociatedTyValue> {
101 self.db.associated_ty_value(self.krate, id) 101 self.db.associated_ty_value(self.krate, id)
102 } 102 }
103
103 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<Interner>> { 104 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<Interner>> {
104 vec![] 105 vec![]
105 } 106 }
@@ -130,11 +131,34 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
130 self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) 131 self.db.program_clauses_for_chalk_env(self.krate, environment.clone())
131 } 132 }
132 133
133 fn opaque_ty_data( 134 fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatum> {
134 &self, 135 let interned_id = crate::db::InternedOpaqueTyId::from(id);
135 _id: chalk_ir::OpaqueTyId<Interner>, 136 let full_id = self.db.lookup_intern_impl_trait_id(interned_id);
136 ) -> Arc<rust_ir::OpaqueTyDatum<Interner>> { 137 let (func, idx) = match full_id {
137 unimplemented!() 138 crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => (func, idx),
139 };
140 let datas =
141 self.db.return_type_impl_traits(func).expect("impl trait id without impl traits");
142 let data = &datas.value.impl_traits[idx as usize];
143 let bound = OpaqueTyDatumBound {
144 bounds: make_binders(
145 data.bounds
146 .value
147 .iter()
148 .cloned()
149 .filter(|b| !b.is_error())
150 .map(|b| b.to_chalk(self.db))
151 .collect(),
152 1,
153 ),
154 };
155 let num_vars = datas.num_binders;
156 Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) })
157 }
158
159 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
160 // FIXME: actually provide the hidden type; it is relevant for auto traits
161 Ty::Unknown.to_chalk(self.db)
138 } 162 }
139 163
140 fn force_impl_for( 164 fn force_impl_for(
@@ -150,10 +174,6 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
150 // FIXME: implement actual object safety 174 // FIXME: implement actual object safety
151 true 175 true
152 } 176 }
153
154 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
155 Ty::Unknown.to_chalk(self.db)
156 }
157} 177}
158 178
159pub(crate) fn program_clauses_for_chalk_env_query( 179pub(crate) fn program_clauses_for_chalk_env_query(
@@ -460,6 +480,18 @@ impl From<crate::traits::GlobalImplId> for ImplId {
460 } 480 }
461} 481}
462 482
483impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
484 fn from(id: OpaqueTyId) -> Self {
485 InternKey::from_intern_id(id.0)
486 }
487}
488
489impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
490 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
491 chalk_ir::OpaqueTyId(id.as_intern_id())
492 }
493}
494
463impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId { 495impl From<rust_ir::AssociatedTyValueId<Interner>> for crate::traits::AssocTyValueId {
464 fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self { 496 fn from(id: rust_ir::AssociatedTyValueId<Interner>) -> Self {
465 Self::from_intern_id(id.0) 497 Self::from_intern_id(id.0)
diff --git a/crates/ra_hir_ty/src/traits/chalk/interner.rs b/crates/ra_hir_ty/src/traits/chalk/interner.rs
index e27074ba6..56aab640c 100644
--- a/crates/ra_hir_ty/src/traits/chalk/interner.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/interner.rs
@@ -22,6 +22,8 @@ pub type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interne
22pub type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; 22pub type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
23pub type FnDefId = chalk_ir::FnDefId<Interner>; 23pub type FnDefId = chalk_ir::FnDefId<Interner>;
24pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; 24pub type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
25pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
26pub type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
25 27
26impl chalk_ir::interner::Interner for Interner { 28impl chalk_ir::interner::Interner for Interner {
27 type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc? 29 type InternedType = Box<chalk_ir::TyData<Self>>; // FIXME use Arc?
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
index 5f6daf842..834360430 100644
--- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
@@ -16,8 +16,8 @@ use crate::{
16 db::HirDatabase, 16 db::HirDatabase,
17 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, 17 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain},
18 traits::{builtin, AssocTyValue, Canonical, Impl, Obligation}, 18 traits::{builtin, AssocTyValue, Canonical, Impl, Obligation},
19 ApplicationTy, CallableDef, GenericPredicate, InEnvironment, ProjectionPredicate, ProjectionTy, 19 ApplicationTy, CallableDef, GenericPredicate, InEnvironment, OpaqueTy, OpaqueTyId,
20 Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, 20 ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
21}; 21};
22 22
23use super::interner::*; 23use super::interner::*;
@@ -68,7 +68,16 @@ impl ToChalk for Ty {
68 let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) }; 68 let bounded_ty = chalk_ir::DynTy { bounds: make_binders(where_clauses, 1) };
69 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner) 69 chalk_ir::TyData::Dyn(bounded_ty).intern(&Interner)
70 } 70 }
71 Ty::Opaque(_) | Ty::Unknown => { 71 Ty::Opaque(opaque_ty) => {
72 let opaque_ty_id = opaque_ty.opaque_ty_id.to_chalk(db);
73 let substitution = opaque_ty.parameters.to_chalk(db);
74 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
75 opaque_ty_id,
76 substitution,
77 }))
78 .intern(&Interner)
79 }
80 Ty::Unknown => {
72 let substitution = chalk_ir::Substitution::empty(&Interner); 81 let substitution = chalk_ir::Substitution::empty(&Interner);
73 let name = TypeName::Error; 82 let name = TypeName::Error;
74 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner) 83 chalk_ir::ApplicationTy { name, substitution }.cast(&Interner).intern(&Interner)
@@ -98,7 +107,11 @@ impl ToChalk for Ty {
98 let parameters = from_chalk(db, proj.substitution); 107 let parameters = from_chalk(db, proj.substitution);
99 Ty::Projection(ProjectionTy { associated_ty, parameters }) 108 Ty::Projection(ProjectionTy { associated_ty, parameters })
100 } 109 }
101 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), 110 chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
111 let impl_trait_id = from_chalk(db, opaque_ty.opaque_ty_id);
112 let parameters = from_chalk(db, opaque_ty.substitution);
113 Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })
114 }
102 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => { 115 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: _, substitution }) => {
103 let parameters: Substs = from_chalk(db, substitution); 116 let parameters: Substs = from_chalk(db, substitution);
104 Ty::Apply(ApplicationTy { 117 Ty::Apply(ApplicationTy {
@@ -204,6 +217,21 @@ impl ToChalk for hir_def::TraitId {
204 } 217 }
205} 218}
206 219
220impl ToChalk for OpaqueTyId {
221 type Chalk = chalk_ir::OpaqueTyId<Interner>;
222
223 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::OpaqueTyId<Interner> {
224 db.intern_impl_trait_id(self).into()
225 }
226
227 fn from_chalk(
228 db: &dyn HirDatabase,
229 opaque_ty_id: chalk_ir::OpaqueTyId<Interner>,
230 ) -> OpaqueTyId {
231 db.lookup_intern_impl_trait_id(opaque_ty_id.into())
232 }
233}
234
207impl ToChalk for TypeCtor { 235impl ToChalk for TypeCtor {
208 type Chalk = TypeName<Interner>; 236 type Chalk = TypeName<Interner>;
209 237
@@ -214,6 +242,11 @@ impl ToChalk for TypeCtor {
214 TypeName::AssociatedType(type_id) 242 TypeName::AssociatedType(type_id)
215 } 243 }
216 244
245 TypeCtor::OpaqueType(impl_trait_id) => {
246 let id = impl_trait_id.to_chalk(db);
247 TypeName::OpaqueType(id)
248 }
249
217 TypeCtor::Bool => TypeName::Scalar(Scalar::Bool), 250 TypeCtor::Bool => TypeName::Scalar(Scalar::Bool),
218 TypeCtor::Char => TypeName::Scalar(Scalar::Char), 251 TypeCtor::Char => TypeName::Scalar(Scalar::Char),
219 TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)), 252 TypeCtor::Int(Uncertain::Known(int_ty)) => TypeName::Scalar(int_ty_to_chalk(int_ty)),
@@ -252,7 +285,9 @@ impl ToChalk for TypeCtor {
252 match type_name { 285 match type_name {
253 TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), 286 TypeName::Adt(struct_id) => db.lookup_intern_type_ctor(struct_id.into()),
254 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), 287 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)),
255 TypeName::OpaqueType(_) => unreachable!(), 288 TypeName::OpaqueType(opaque_type_id) => {
289 TypeCtor::OpaqueType(from_chalk(db, opaque_type_id))
290 }
256 291
257 TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool, 292 TypeName::Scalar(Scalar::Bool) => TypeCtor::Bool,
258 TypeName::Scalar(Scalar::Char) => TypeCtor::Char, 293 TypeName::Scalar(Scalar::Char) => TypeCtor::Char,
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs
index d88828c7c..556af7098 100644
--- a/crates/ra_hir_ty/src/traits/chalk/tls.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs
@@ -69,6 +69,11 @@ impl DebugContext<'_> {
69 let name = self.0.type_alias_data(type_alias).name.clone(); 69 let name = self.0.type_alias_data(type_alias).name.clone();
70 write!(f, "{}::{}", trait_name, name)?; 70 write!(f, "{}::{}", trait_name, name)?;
71 } 71 }
72 TypeCtor::OpaqueType(opaque_ty_id) => match opaque_ty_id {
73 crate::OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
74 write!(f, "{{impl trait {} of {:?}}}", idx, func)?;
75 }
76 },
72 TypeCtor::Closure { def, expr } => { 77 TypeCtor::Closure { def, expr } => {
73 write!(f, "{{closure {:?} in ", expr.into_raw())?; 78 write!(f, "{{closure {:?} in ", expr.into_raw())?;
74 match def { 79 match def {