@@ -19,7 +19,7 @@ use std::sync::Arc;
19
19
use chalk_ir:: { cast:: Cast , ConstValue , DebruijnIndex , Mutability , Safety , Scalar , TypeFlags } ;
20
20
use hir_def:: {
21
21
body:: Body ,
22
- data:: { ConstData , FunctionData , StaticData } ,
22
+ data:: { ConstData , StaticData } ,
23
23
expr:: { BindingAnnotation , ExprId , PatId } ,
24
24
lang_item:: LangItemTarget ,
25
25
path:: { path, Path } ,
@@ -32,12 +32,13 @@ use hir_expand::name::{name, Name};
32
32
use itertools:: Either ;
33
33
use la_arena:: ArenaMap ;
34
34
use rustc_hash:: FxHashMap ;
35
- use stdx:: impl_from;
35
+ use stdx:: { always , impl_from} ;
36
36
37
37
use crate :: {
38
- db:: HirDatabase , fold_tys_and_consts, infer:: coerce:: CoerceMany , lower:: ImplTraitLoweringMode ,
39
- to_assoc_type_id, AliasEq , AliasTy , Const , DomainGoal , GenericArg , Goal , InEnvironment ,
40
- Interner , ProjectionTy , Substitution , TraitEnvironment , TraitRef , Ty , TyBuilder , TyExt , TyKind ,
38
+ db:: HirDatabase , fold_tys, fold_tys_and_consts, infer:: coerce:: CoerceMany ,
39
+ lower:: ImplTraitLoweringMode , to_assoc_type_id, AliasEq , AliasTy , Const , DomainGoal ,
40
+ GenericArg , Goal , ImplTraitId , InEnvironment , Interner , ProjectionTy , Substitution ,
41
+ TraitEnvironment , TraitRef , Ty , TyBuilder , TyExt , TyKind ,
41
42
} ;
42
43
43
44
// This lint has a false positive here. See the link below for details.
@@ -64,7 +65,7 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
64
65
65
66
match def {
66
67
DefWithBodyId :: ConstId ( c) => ctx. collect_const ( & db. const_data ( c) ) ,
67
- DefWithBodyId :: FunctionId ( f) => ctx. collect_fn ( & db . function_data ( f ) ) ,
68
+ DefWithBodyId :: FunctionId ( f) => ctx. collect_fn ( f ) ,
68
69
DefWithBodyId :: StaticId ( s) => ctx. collect_static ( & db. static_data ( s) ) ,
69
70
}
70
71
@@ -457,7 +458,8 @@ impl<'a> InferenceContext<'a> {
457
458
self . return_ty = self . make_ty ( & data. type_ref ) ;
458
459
}
459
460
460
- fn collect_fn ( & mut self , data : & FunctionData ) {
461
+ fn collect_fn ( & mut self , func : FunctionId ) {
462
+ let data = self . db . function_data ( func) ;
461
463
let ctx = crate :: lower:: TyLoweringContext :: new ( self . db , & self . resolver )
462
464
. with_impl_trait_mode ( ImplTraitLoweringMode :: Param ) ;
463
465
let param_tys =
@@ -474,8 +476,42 @@ impl<'a> InferenceContext<'a> {
474
476
} else {
475
477
& * data. ret_type
476
478
} ;
477
- let return_ty = self . make_ty_with_mode ( return_ty, ImplTraitLoweringMode :: Disallowed ) ; // FIXME implement RPIT
479
+ let return_ty = self . make_ty_with_mode ( return_ty, ImplTraitLoweringMode :: Opaque ) ;
478
480
self . return_ty = return_ty;
481
+
482
+ if let Some ( rpits) = self . db . return_type_impl_traits ( func) {
483
+ // RPIT opaque types use substitution of their parent function.
484
+ let fn_placeholders = TyBuilder :: placeholder_subst ( self . db , func) ;
485
+ self . return_ty = fold_tys (
486
+ self . return_ty . clone ( ) ,
487
+ |ty, _| {
488
+ let opaque_ty_id = match ty. kind ( Interner ) {
489
+ TyKind :: OpaqueType ( opaque_ty_id, _) => * opaque_ty_id,
490
+ _ => return ty,
491
+ } ;
492
+ let idx = match self . db . lookup_intern_impl_trait_id ( opaque_ty_id. into ( ) ) {
493
+ ImplTraitId :: ReturnTypeImplTrait ( _, idx) => idx,
494
+ _ => unreachable ! ( ) ,
495
+ } ;
496
+ let bounds = ( * rpits) . map_ref ( |rpits| {
497
+ rpits. impl_traits [ idx as usize ] . bounds . map_ref ( |it| it. into_iter ( ) )
498
+ } ) ;
499
+ let var = self . table . new_type_var ( ) ;
500
+ let var_subst = Substitution :: from1 ( Interner , var. clone ( ) ) ;
501
+ for bound in bounds {
502
+ let predicate =
503
+ bound. map ( |it| it. cloned ( ) ) . substitute ( Interner , & fn_placeholders) ;
504
+ let ( var_predicate, binders) = predicate
505
+ . substitute ( Interner , & var_subst)
506
+ . into_value_and_skipped_binders ( ) ;
507
+ always ! ( binders. len( Interner ) == 0 ) ; // quantified where clauses not yet handled
508
+ self . push_obligation ( var_predicate. cast ( Interner ) ) ;
509
+ }
510
+ var
511
+ } ,
512
+ DebruijnIndex :: INNERMOST ,
513
+ ) ;
514
+ }
479
515
}
480
516
481
517
fn infer_body ( & mut self ) {
0 commit comments