@@ -33,7 +33,7 @@ use hir_def::{
33
33
TraitId , TypeAliasId , VariantId ,
34
34
} ;
35
35
use hir_expand:: name:: { name, Name } ;
36
- use la_arena:: ArenaMap ;
36
+ use la_arena:: { ArenaMap , Entry } ;
37
37
use rustc_hash:: { FxHashMap , FxHashSet } ;
38
38
use stdx:: { always, never} ;
39
39
@@ -676,36 +676,16 @@ impl<'a> InferenceContext<'a> {
676
676
let return_ty = if let Some ( rpits) = self . db . return_type_impl_traits ( func) {
677
677
// RPIT opaque types use substitution of their parent function.
678
678
let fn_placeholders = TyBuilder :: placeholder_subst ( self . db , func) ;
679
- fold_tys (
680
- return_ty,
681
- |ty, _| {
682
- let opaque_ty_id = match ty. kind ( Interner ) {
683
- TyKind :: OpaqueType ( opaque_ty_id, _) => * opaque_ty_id,
684
- _ => return ty,
685
- } ;
686
- let idx = match self . db . lookup_intern_impl_trait_id ( opaque_ty_id. into ( ) ) {
687
- ImplTraitId :: ReturnTypeImplTrait ( _, idx) => idx,
688
- _ => unreachable ! ( ) ,
689
- } ;
690
- let bounds = ( * rpits) . map_ref ( |rpits| {
691
- rpits. impl_traits [ idx] . bounds . map_ref ( |it| it. into_iter ( ) )
692
- } ) ;
693
- let var = self . table . new_type_var ( ) ;
694
- let var_subst = Substitution :: from1 ( Interner , var. clone ( ) ) ;
695
- for bound in bounds {
696
- let predicate =
697
- bound. map ( |it| it. cloned ( ) ) . substitute ( Interner , & fn_placeholders) ;
698
- let ( var_predicate, binders) = predicate
699
- . substitute ( Interner , & var_subst)
700
- . into_value_and_skipped_binders ( ) ;
701
- always ! ( binders. is_empty( Interner ) ) ; // quantified where clauses not yet handled
702
- self . push_obligation ( var_predicate. cast ( Interner ) ) ;
703
- }
704
- self . result . type_of_rpit . insert ( idx, var. clone ( ) ) ;
705
- var
706
- } ,
707
- DebruijnIndex :: INNERMOST ,
708
- )
679
+ let result =
680
+ self . insert_inference_vars_for_rpit ( return_ty, rpits. clone ( ) , fn_placeholders) ;
681
+ let rpits = rpits. skip_binders ( ) ;
682
+ for ( id, _) in rpits. impl_traits . iter ( ) {
683
+ if let Entry :: Vacant ( e) = self . result . type_of_rpit . entry ( id) {
684
+ never ! ( "Missed RPIT in `insert_inference_vars_for_rpit`" ) ;
685
+ e. insert ( TyKind :: Error . intern ( Interner ) ) ;
686
+ }
687
+ }
688
+ result
709
689
} else {
710
690
return_ty
711
691
} ;
@@ -714,6 +694,50 @@ impl<'a> InferenceContext<'a> {
714
694
self . return_coercion = Some ( CoerceMany :: new ( self . return_ty . clone ( ) ) ) ;
715
695
}
716
696
697
+ fn insert_inference_vars_for_rpit < T > (
698
+ & mut self ,
699
+ t : T ,
700
+ rpits : Arc < chalk_ir:: Binders < crate :: ReturnTypeImplTraits > > ,
701
+ fn_placeholders : Substitution ,
702
+ ) -> T
703
+ where
704
+ T : crate :: HasInterner < Interner = Interner > + crate :: TypeFoldable < Interner > ,
705
+ {
706
+ fold_tys (
707
+ t,
708
+ |ty, _| {
709
+ let opaque_ty_id = match ty. kind ( Interner ) {
710
+ TyKind :: OpaqueType ( opaque_ty_id, _) => * opaque_ty_id,
711
+ _ => return ty,
712
+ } ;
713
+ let idx = match self . db . lookup_intern_impl_trait_id ( opaque_ty_id. into ( ) ) {
714
+ ImplTraitId :: ReturnTypeImplTrait ( _, idx) => idx,
715
+ _ => unreachable ! ( ) ,
716
+ } ;
717
+ let bounds = ( * rpits)
718
+ . map_ref ( |rpits| rpits. impl_traits [ idx] . bounds . map_ref ( |it| it. into_iter ( ) ) ) ;
719
+ let var = self . table . new_type_var ( ) ;
720
+ let var_subst = Substitution :: from1 ( Interner , var. clone ( ) ) ;
721
+ for bound in bounds {
722
+ let predicate =
723
+ bound. map ( |it| it. cloned ( ) ) . substitute ( Interner , & fn_placeholders) ;
724
+ let ( var_predicate, binders) =
725
+ predicate. substitute ( Interner , & var_subst) . into_value_and_skipped_binders ( ) ;
726
+ always ! ( binders. is_empty( Interner ) ) ; // quantified where clauses not yet handled
727
+ let var_predicate = self . insert_inference_vars_for_rpit (
728
+ var_predicate,
729
+ rpits. clone ( ) ,
730
+ fn_placeholders. clone ( ) ,
731
+ ) ;
732
+ self . push_obligation ( var_predicate. cast ( Interner ) ) ;
733
+ }
734
+ self . result . type_of_rpit . insert ( idx, var. clone ( ) ) ;
735
+ var
736
+ } ,
737
+ DebruijnIndex :: INNERMOST ,
738
+ )
739
+ }
740
+
717
741
fn infer_body ( & mut self ) {
718
742
match self . return_coercion {
719
743
Some ( _) => self . infer_return ( self . body . body_expr ) ,
0 commit comments