@@ -33,7 +33,7 @@ use hir_def::{
3333 TraitId , TypeAliasId , VariantId ,
3434} ;
3535use hir_expand:: name:: { name, Name } ;
36- use la_arena:: ArenaMap ;
36+ use la_arena:: { ArenaMap , Entry } ;
3737use rustc_hash:: { FxHashMap , FxHashSet } ;
3838use stdx:: { always, never} ;
3939
@@ -676,36 +676,16 @@ impl<'a> InferenceContext<'a> {
676676 let return_ty = if let Some ( rpits) = self . db . return_type_impl_traits ( func) {
677677 // RPIT opaque types use substitution of their parent function.
678678 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
709689 } else {
710690 return_ty
711691 } ;
@@ -714,6 +694,50 @@ impl<'a> InferenceContext<'a> {
714694 self . return_coercion = Some ( CoerceMany :: new ( self . return_ty . clone ( ) ) ) ;
715695 }
716696
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+
717741 fn infer_body ( & mut self ) {
718742 match self . return_coercion {
719743 Some ( _) => self . infer_return ( self . body . body_expr ) ,
0 commit comments