diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 214 |
1 files changed, 168 insertions, 46 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 35ac86a46..42713928f 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -21,8 +21,10 @@ use hir_def::{ | |||
21 | HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, | 21 | HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, |
22 | UnionId, VariantId, | 22 | UnionId, VariantId, |
23 | }; | 23 | }; |
24 | use hir_expand::name::Name; | ||
24 | use ra_arena::map::ArenaMap; | 25 | use ra_arena::map::ArenaMap; |
25 | use ra_db::CrateId; | 26 | use ra_db::CrateId; |
27 | use test_utils::mark; | ||
26 | 28 | ||
27 | use crate::{ | 29 | use crate::{ |
28 | db::HirDatabase, | 30 | db::HirDatabase, |
@@ -31,10 +33,10 @@ use crate::{ | |||
31 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, | 33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, |
32 | make_mut_slice, variant_data, | 34 | make_mut_slice, variant_data, |
33 | }, | 35 | }, |
34 | Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, | 36 | Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, OpaqueTy, OpaqueTyId, PolyFnSig, |
35 | ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | 37 | ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substs, |
38 | TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, | ||
36 | }; | 39 | }; |
37 | use hir_expand::name::Name; | ||
38 | 40 | ||
39 | #[derive(Debug)] | 41 | #[derive(Debug)] |
40 | pub struct TyLoweringContext<'a> { | 42 | pub struct TyLoweringContext<'a> { |
@@ -47,7 +49,16 @@ pub struct TyLoweringContext<'a> { | |||
47 | /// possible currently, so this should be fine for now. | 49 | /// possible currently, so this should be fine for now. |
48 | pub type_param_mode: TypeParamLoweringMode, | 50 | pub type_param_mode: TypeParamLoweringMode, |
49 | pub impl_trait_mode: ImplTraitLoweringMode, | 51 | pub impl_trait_mode: ImplTraitLoweringMode, |
50 | pub impl_trait_counter: std::cell::Cell<u16>, | 52 | impl_trait_counter: std::cell::Cell<u16>, |
53 | /// When turning `impl Trait` into opaque types, we have to collect the | ||
54 | /// bounds at the same time to get the IDs correct (without becoming too | ||
55 | /// complicated). I don't like using interior mutability (as for the | ||
56 | /// counter), but I've tried and failed to make the lifetimes work for | ||
57 | /// passing around a `&mut TyLoweringContext`. The core problem is that | ||
58 | /// we're grouping the mutable data (the counter and this field) together | ||
59 | /// with the immutable context (the references to the DB and resolver). | ||
60 | /// Splitting this up would be a possible fix. | ||
61 | opaque_type_data: std::cell::RefCell<Vec<ReturnTypeImplTrait>>, | ||
51 | } | 62 | } |
52 | 63 | ||
53 | impl<'a> TyLoweringContext<'a> { | 64 | impl<'a> TyLoweringContext<'a> { |
@@ -56,26 +67,42 @@ impl<'a> TyLoweringContext<'a> { | |||
56 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; | 67 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; |
57 | let type_param_mode = TypeParamLoweringMode::Placeholder; | 68 | let type_param_mode = TypeParamLoweringMode::Placeholder; |
58 | let in_binders = DebruijnIndex::INNERMOST; | 69 | let in_binders = DebruijnIndex::INNERMOST; |
59 | Self { db, resolver, in_binders, impl_trait_mode, impl_trait_counter, type_param_mode } | 70 | let opaque_type_data = std::cell::RefCell::new(Vec::new()); |
71 | Self { | ||
72 | db, | ||
73 | resolver, | ||
74 | in_binders, | ||
75 | impl_trait_mode, | ||
76 | impl_trait_counter, | ||
77 | type_param_mode, | ||
78 | opaque_type_data, | ||
79 | } | ||
60 | } | 80 | } |
61 | 81 | ||
62 | pub fn with_shifted_in<T>( | 82 | pub fn with_debruijn<T>( |
63 | &self, | 83 | &self, |
64 | debruijn: DebruijnIndex, | 84 | debruijn: DebruijnIndex, |
65 | f: impl FnOnce(&TyLoweringContext) -> T, | 85 | f: impl FnOnce(&TyLoweringContext) -> T, |
66 | ) -> T { | 86 | ) -> T { |
87 | let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new()); | ||
67 | let new_ctx = Self { | 88 | let new_ctx = Self { |
68 | in_binders: self.in_binders.shifted_in_from(debruijn), | 89 | in_binders: debruijn, |
69 | impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), | 90 | impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), |
91 | opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec), | ||
70 | ..*self | 92 | ..*self |
71 | }; | 93 | }; |
72 | let result = f(&new_ctx); | 94 | let result = f(&new_ctx); |
73 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); | 95 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); |
96 | self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner()); | ||
74 | result | 97 | result |
75 | } | 98 | } |
76 | 99 | ||
77 | pub fn shifted_in(self, debruijn: DebruijnIndex) -> Self { | 100 | pub fn with_shifted_in<T>( |
78 | Self { in_binders: self.in_binders.shifted_in_from(debruijn), ..self } | 101 | &self, |
102 | debruijn: DebruijnIndex, | ||
103 | f: impl FnOnce(&TyLoweringContext) -> T, | ||
104 | ) -> T { | ||
105 | self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f) | ||
79 | } | 106 | } |
80 | 107 | ||
81 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | 108 | pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { |
@@ -167,20 +194,44 @@ impl Ty { | |||
167 | TypeRef::ImplTrait(bounds) => { | 194 | TypeRef::ImplTrait(bounds) => { |
168 | match ctx.impl_trait_mode { | 195 | match ctx.impl_trait_mode { |
169 | ImplTraitLoweringMode::Opaque => { | 196 | ImplTraitLoweringMode::Opaque => { |
170 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | 197 | let idx = ctx.impl_trait_counter.get(); |
171 | let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 198 | ctx.impl_trait_counter.set(idx + 1); |
172 | bounds | 199 | |
173 | .iter() | 200 | assert!(idx as usize == ctx.opaque_type_data.borrow().len()); |
174 | .flat_map(|b| { | 201 | // this dance is to make sure the data is in the right |
175 | GenericPredicate::from_type_bound(ctx, b, self_ty.clone()) | 202 | // place even if we encounter more opaque types while |
176 | }) | 203 | // lowering the bounds |
177 | .collect() | 204 | ctx.opaque_type_data |
178 | }); | 205 | .borrow_mut() |
179 | Ty::Opaque(predicates) | 206 | .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) }); |
207 | // We don't want to lower the bounds inside the binders | ||
208 | // we're currently in, because they don't end up inside | ||
209 | // those binders. E.g. when we have `impl Trait<impl | ||
210 | // OtherTrait<T>>`, the `impl OtherTrait<T>` can't refer | ||
211 | // to the self parameter from `impl Trait`, and the | ||
212 | // bounds aren't actually stored nested within each | ||
213 | // other, but separately. So if the `T` refers to a type | ||
214 | // parameter of the outer function, it's just one binder | ||
215 | // away instead of two. | ||
216 | let actual_opaque_type_data = ctx | ||
217 | .with_debruijn(DebruijnIndex::INNERMOST, |ctx| { | ||
218 | ReturnTypeImplTrait::from_hir(ctx, &bounds) | ||
219 | }); | ||
220 | ctx.opaque_type_data.borrow_mut()[idx as usize] = actual_opaque_type_data; | ||
221 | |||
222 | let func = match ctx.resolver.generic_def() { | ||
223 | Some(GenericDefId::FunctionId(f)) => f, | ||
224 | _ => panic!("opaque impl trait lowering in non-function"), | ||
225 | }; | ||
226 | let impl_trait_id = OpaqueTyId::ReturnTypeImplTrait(func, idx); | ||
227 | let generics = generics(ctx.db.upcast(), func.into()); | ||
228 | let parameters = Substs::bound_vars(&generics, ctx.in_binders); | ||
229 | Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters }) | ||
180 | } | 230 | } |
181 | ImplTraitLoweringMode::Param => { | 231 | ImplTraitLoweringMode::Param => { |
182 | let idx = ctx.impl_trait_counter.get(); | 232 | let idx = ctx.impl_trait_counter.get(); |
183 | ctx.impl_trait_counter.set(idx + 1); | 233 | // FIXME we're probably doing something wrong here |
234 | ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); | ||
184 | if let Some(def) = ctx.resolver.generic_def() { | 235 | if let Some(def) = ctx.resolver.generic_def() { |
185 | let generics = generics(ctx.db.upcast(), def); | 236 | let generics = generics(ctx.db.upcast(), def); |
186 | let param = generics | 237 | let param = generics |
@@ -197,7 +248,8 @@ impl Ty { | |||
197 | } | 248 | } |
198 | ImplTraitLoweringMode::Variable => { | 249 | ImplTraitLoweringMode::Variable => { |
199 | let idx = ctx.impl_trait_counter.get(); | 250 | let idx = ctx.impl_trait_counter.get(); |
200 | ctx.impl_trait_counter.set(idx + 1); | 251 | // FIXME we're probably doing something wrong here |
252 | ctx.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16); | ||
201 | let (parent_params, self_params, list_params, _impl_trait_params) = | 253 | let (parent_params, self_params, list_params, _impl_trait_params) = |
202 | if let Some(def) = ctx.resolver.generic_def() { | 254 | if let Some(def) = ctx.resolver.generic_def() { |
203 | let generics = generics(ctx.db.upcast(), def); | 255 | let generics = generics(ctx.db.upcast(), def); |
@@ -271,6 +323,7 @@ impl Ty { | |||
271 | resolution: TypeNs, | 323 | resolution: TypeNs, |
272 | resolved_segment: PathSegment<'_>, | 324 | resolved_segment: PathSegment<'_>, |
273 | remaining_segments: PathSegments<'_>, | 325 | remaining_segments: PathSegments<'_>, |
326 | infer_args: bool, | ||
274 | ) -> (Ty, Option<TypeNs>) { | 327 | ) -> (Ty, Option<TypeNs>) { |
275 | let ty = match resolution { | 328 | let ty = match resolution { |
276 | TypeNs::TraitId(trait_) => { | 329 | TypeNs::TraitId(trait_) => { |
@@ -348,9 +401,15 @@ impl Ty { | |||
348 | ctx.db.ty(adt.into()).subst(&substs) | 401 | ctx.db.ty(adt.into()).subst(&substs) |
349 | } | 402 | } |
350 | 403 | ||
351 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 404 | TypeNs::AdtId(it) => { |
352 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 405 | Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) |
353 | TypeNs::TypeAliasId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 406 | } |
407 | TypeNs::BuiltinType(it) => { | ||
408 | Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) | ||
409 | } | ||
410 | TypeNs::TypeAliasId(it) => { | ||
411 | Ty::from_hir_path_inner(ctx, resolved_segment, it.into(), infer_args) | ||
412 | } | ||
354 | // FIXME: report error | 413 | // FIXME: report error |
355 | TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), | 414 | TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), |
356 | }; | 415 | }; |
@@ -376,7 +435,13 @@ impl Ty { | |||
376 | ), | 435 | ), |
377 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), | 436 | Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), |
378 | }; | 437 | }; |
379 | Ty::from_partly_resolved_hir_path(ctx, resolution, resolved_segment, remaining_segments) | 438 | Ty::from_partly_resolved_hir_path( |
439 | ctx, | ||
440 | resolution, | ||
441 | resolved_segment, | ||
442 | remaining_segments, | ||
443 | false, | ||
444 | ) | ||
380 | } | 445 | } |
381 | 446 | ||
382 | fn select_associated_type( | 447 | fn select_associated_type( |
@@ -422,13 +487,14 @@ impl Ty { | |||
422 | ctx: &TyLoweringContext<'_>, | 487 | ctx: &TyLoweringContext<'_>, |
423 | segment: PathSegment<'_>, | 488 | segment: PathSegment<'_>, |
424 | typable: TyDefId, | 489 | typable: TyDefId, |
490 | infer_args: bool, | ||
425 | ) -> Ty { | 491 | ) -> Ty { |
426 | let generic_def = match typable { | 492 | let generic_def = match typable { |
427 | TyDefId::BuiltinType(_) => None, | 493 | TyDefId::BuiltinType(_) => None, |
428 | TyDefId::AdtId(it) => Some(it.into()), | 494 | TyDefId::AdtId(it) => Some(it.into()), |
429 | TyDefId::TypeAliasId(it) => Some(it.into()), | 495 | TyDefId::TypeAliasId(it) => Some(it.into()), |
430 | }; | 496 | }; |
431 | let substs = substs_from_path_segment(ctx, segment, generic_def, false); | 497 | let substs = substs_from_path_segment(ctx, segment, generic_def, infer_args); |
432 | ctx.db.ty(typable).subst(&substs) | 498 | ctx.db.ty(typable).subst(&substs) |
433 | } | 499 | } |
434 | 500 | ||
@@ -441,6 +507,7 @@ impl Ty { | |||
441 | // `ValueTyDefId` is just a convenient way to pass generics and | 507 | // `ValueTyDefId` is just a convenient way to pass generics and |
442 | // special-case enum variants | 508 | // special-case enum variants |
443 | resolved: ValueTyDefId, | 509 | resolved: ValueTyDefId, |
510 | infer_args: bool, | ||
444 | ) -> Substs { | 511 | ) -> Substs { |
445 | let last = path.segments().last().expect("path should have at least one segment"); | 512 | let last = path.segments().last().expect("path should have at least one segment"); |
446 | let (segment, generic_def) = match resolved { | 513 | let (segment, generic_def) = match resolved { |
@@ -463,22 +530,27 @@ impl Ty { | |||
463 | (segment, Some(var.parent.into())) | 530 | (segment, Some(var.parent.into())) |
464 | } | 531 | } |
465 | }; | 532 | }; |
466 | substs_from_path_segment(ctx, segment, generic_def, false) | 533 | substs_from_path_segment(ctx, segment, generic_def, infer_args) |
467 | } | 534 | } |
468 | } | 535 | } |
469 | 536 | ||
470 | pub(super) fn substs_from_path_segment( | 537 | fn substs_from_path_segment( |
471 | ctx: &TyLoweringContext<'_>, | 538 | ctx: &TyLoweringContext<'_>, |
472 | segment: PathSegment<'_>, | 539 | segment: PathSegment<'_>, |
473 | def_generic: Option<GenericDefId>, | 540 | def_generic: Option<GenericDefId>, |
474 | _add_self_param: bool, | 541 | infer_args: bool, |
475 | ) -> Substs { | 542 | ) -> Substs { |
476 | let mut substs = Vec::new(); | 543 | let mut substs = Vec::new(); |
477 | let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); | 544 | let def_generics = def_generic.map(|def| generics(ctx.db.upcast(), def)); |
478 | 545 | ||
479 | let (parent_params, self_params, type_params, impl_trait_params) = | 546 | let (parent_params, self_params, type_params, impl_trait_params) = |
480 | def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); | 547 | def_generics.map_or((0, 0, 0, 0), |g| g.provenance_split()); |
548 | let total_len = parent_params + self_params + type_params + impl_trait_params; | ||
549 | |||
481 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); | 550 | substs.extend(iter::repeat(Ty::Unknown).take(parent_params)); |
551 | |||
552 | let mut had_explicit_args = false; | ||
553 | |||
482 | if let Some(generic_args) = &segment.args_and_bindings { | 554 | if let Some(generic_args) = &segment.args_and_bindings { |
483 | if !generic_args.has_self_type { | 555 | if !generic_args.has_self_type { |
484 | substs.extend(iter::repeat(Ty::Unknown).take(self_params)); | 556 | substs.extend(iter::repeat(Ty::Unknown).take(self_params)); |
@@ -490,31 +562,35 @@ pub(super) fn substs_from_path_segment( | |||
490 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { | 562 | for arg in generic_args.args.iter().skip(skip).take(expected_num) { |
491 | match arg { | 563 | match arg { |
492 | GenericArg::Type(type_ref) => { | 564 | GenericArg::Type(type_ref) => { |
565 | had_explicit_args = true; | ||
493 | let ty = Ty::from_hir(ctx, type_ref); | 566 | let ty = Ty::from_hir(ctx, type_ref); |
494 | substs.push(ty); | 567 | substs.push(ty); |
495 | } | 568 | } |
496 | } | 569 | } |
497 | } | 570 | } |
498 | } | 571 | } |
499 | let total_len = parent_params + self_params + type_params + impl_trait_params; | ||
500 | // add placeholders for args that were not provided | ||
501 | for _ in substs.len()..total_len { | ||
502 | substs.push(Ty::Unknown); | ||
503 | } | ||
504 | assert_eq!(substs.len(), total_len); | ||
505 | 572 | ||
506 | // handle defaults | 573 | // handle defaults. In expression or pattern path segments without |
507 | if let Some(def_generic) = def_generic { | 574 | // explicitly specified type arguments, missing type arguments are inferred |
508 | let default_substs = ctx.db.generic_defaults(def_generic); | 575 | // (i.e. defaults aren't used). |
509 | assert_eq!(substs.len(), default_substs.len()); | 576 | if !infer_args || had_explicit_args { |
577 | if let Some(def_generic) = def_generic { | ||
578 | let default_substs = ctx.db.generic_defaults(def_generic); | ||
579 | assert_eq!(total_len, default_substs.len()); | ||
510 | 580 | ||
511 | for (i, default_ty) in default_substs.iter().enumerate() { | 581 | for default_ty in default_substs.iter().skip(substs.len()) { |
512 | if substs[i] == Ty::Unknown { | 582 | substs.push(default_ty.clone()); |
513 | substs[i] = default_ty.clone(); | ||
514 | } | 583 | } |
515 | } | 584 | } |
516 | } | 585 | } |
517 | 586 | ||
587 | // add placeholders for args that were not provided | ||
588 | // FIXME: emit diagnostics in contexts where this is not allowed | ||
589 | for _ in substs.len()..total_len { | ||
590 | substs.push(Ty::Unknown); | ||
591 | } | ||
592 | assert_eq!(substs.len(), total_len); | ||
593 | |||
518 | Substs(substs.into()) | 594 | Substs(substs.into()) |
519 | } | 595 | } |
520 | 596 | ||
@@ -563,9 +639,7 @@ impl TraitRef { | |||
563 | segment: PathSegment<'_>, | 639 | segment: PathSegment<'_>, |
564 | resolved: TraitId, | 640 | resolved: TraitId, |
565 | ) -> Substs { | 641 | ) -> Substs { |
566 | let has_self_param = | 642 | substs_from_path_segment(ctx, segment, Some(resolved.into()), false) |
567 | segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); | ||
568 | substs_from_path_segment(ctx, segment, Some(resolved.into()), !has_self_param) | ||
569 | } | 643 | } |
570 | 644 | ||
571 | pub(crate) fn from_type_bound( | 645 | pub(crate) fn from_type_bound( |
@@ -663,6 +737,30 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
663 | }) | 737 | }) |
664 | } | 738 | } |
665 | 739 | ||
740 | impl ReturnTypeImplTrait { | ||
741 | fn from_hir(ctx: &TyLoweringContext, bounds: &[TypeBound]) -> Self { | ||
742 | mark::hit!(lower_rpit); | ||
743 | let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); | ||
744 | let predicates = ctx.with_shifted_in(DebruijnIndex::ONE, |ctx| { | ||
745 | bounds | ||
746 | .iter() | ||
747 | .flat_map(|b| GenericPredicate::from_type_bound(ctx, b, self_ty.clone())) | ||
748 | .collect() | ||
749 | }); | ||
750 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } | ||
751 | } | ||
752 | } | ||
753 | |||
754 | fn count_impl_traits(type_ref: &TypeRef) -> usize { | ||
755 | let mut count = 0; | ||
756 | type_ref.walk(&mut |type_ref| { | ||
757 | if matches!(type_ref, TypeRef::ImplTrait(_)) { | ||
758 | count += 1; | ||
759 | } | ||
760 | }); | ||
761 | count | ||
762 | } | ||
763 | |||
666 | /// Build the signature of a callable item (function, struct or enum variant). | 764 | /// Build the signature of a callable item (function, struct or enum variant). |
667 | pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig { | 765 | pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig { |
668 | match def { | 766 | match def { |
@@ -864,7 +962,9 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { | |||
864 | .with_impl_trait_mode(ImplTraitLoweringMode::Variable) | 962 | .with_impl_trait_mode(ImplTraitLoweringMode::Variable) |
865 | .with_type_param_mode(TypeParamLoweringMode::Variable); | 963 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
866 | let params = data.params.iter().map(|tr| Ty::from_hir(&ctx_params, tr)).collect::<Vec<_>>(); | 964 | 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); | 965 | let ctx_ret = TyLoweringContext::new(db, &resolver) |
966 | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) | ||
967 | .with_type_param_mode(TypeParamLoweringMode::Variable); | ||
868 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); | 968 | let ret = Ty::from_hir(&ctx_ret, &data.ret_type); |
869 | let generics = generics(db.upcast(), def.into()); | 969 | let generics = generics(db.upcast(), def.into()); |
870 | let num_binders = generics.len(); | 970 | let num_binders = generics.len(); |
@@ -1084,3 +1184,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))?, | 1184 | TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value))?, |
1085 | )) | 1185 | )) |
1086 | } | 1186 | } |
1187 | |||
1188 | pub(crate) fn return_type_impl_traits( | ||
1189 | db: &impl HirDatabase, | ||
1190 | def: hir_def::FunctionId, | ||
1191 | ) -> Option<Arc<Binders<ReturnTypeImplTraits>>> { | ||
1192 | // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe | ||
1193 | let data = db.function_data(def); | ||
1194 | let resolver = def.resolver(db.upcast()); | ||
1195 | let ctx_ret = TyLoweringContext::new(db, &resolver) | ||
1196 | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) | ||
1197 | .with_type_param_mode(TypeParamLoweringMode::Variable); | ||
1198 | let _ret = Ty::from_hir(&ctx_ret, &data.ret_type); | ||
1199 | let generics = generics(db.upcast(), def.into()); | ||
1200 | let num_binders = generics.len(); | ||
1201 | let return_type_impl_traits = | ||
1202 | ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() }; | ||
1203 | if return_type_impl_traits.impl_traits.is_empty() { | ||
1204 | None | ||
1205 | } else { | ||
1206 | Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) | ||
1207 | } | ||
1208 | } | ||