@@ -93,6 +93,18 @@ pub struct OpaqueTypeDecl<'tcx> {
9393 pub origin : hir:: OpaqueTyOrigin ,
9494}
9595
96+ /// Whether member constraints should be generated for all opaque types
97+ pub enum GenerateMemberConstraints {
98+ /// The default, used by typeck
99+ WhenRequired ,
100+ /// The borrow checker needs member constraints in any case where we don't
101+ /// have a `'static` bound. This is because the borrow checker has more
102+ /// flexibility in the values of regions. For example, given `f<'a, 'b>`
103+ /// the borrow checker can have an inference variable outlive `'a` and `'b`,
104+ /// but not be equal to `'static`.
105+ IfNoStaticBound ,
106+ }
107+
96108impl < ' a , ' tcx > InferCtxt < ' a , ' tcx > {
97109 /// Replaces all opaque types in `value` with fresh inference variables
98110 /// and creates appropriate obligations. For example, given the input:
@@ -315,7 +327,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
315327 debug ! ( "constrain_opaque_types()" ) ;
316328
317329 for ( & def_id, opaque_defn) in opaque_types {
318- self . constrain_opaque_type ( def_id, opaque_defn, free_region_relations) ;
330+ self . constrain_opaque_type (
331+ def_id,
332+ opaque_defn,
333+ GenerateMemberConstraints :: WhenRequired ,
334+ free_region_relations,
335+ ) ;
319336 }
320337 }
321338
@@ -324,6 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
324341 & self ,
325342 def_id : DefId ,
326343 opaque_defn : & OpaqueTypeDecl < ' tcx > ,
344+ mode : GenerateMemberConstraints ,
327345 free_region_relations : & FRR ,
328346 ) {
329347 debug ! ( "constrain_opaque_type()" ) ;
@@ -358,6 +376,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
358376 op : |r| self . sub_regions ( infer:: CallReturn ( span) , required_region, r) ,
359377 } ) ;
360378 }
379+ if let GenerateMemberConstraints :: IfNoStaticBound = mode {
380+ self . generate_member_constraint (
381+ concrete_ty,
382+ opaque_type_generics,
383+ opaque_defn,
384+ def_id,
385+ ) ;
386+ }
361387 return ;
362388 }
363389
@@ -398,13 +424,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
398424 // we will create a "in bound" like `'r in
399425 // ['a, 'b, 'c]`, where `'a..'c` are the
400426 // regions that appear in the impl trait.
427+
428+ // For now, enforce a feature gate outside of async functions.
429+ self . member_constraint_feature_gate ( opaque_defn, def_id, lr, subst_arg) ;
430+
401431 return self . generate_member_constraint (
402432 concrete_ty,
403433 opaque_type_generics,
404434 opaque_defn,
405435 def_id,
406- lr,
407- subst_arg,
408436 ) ;
409437 }
410438 }
@@ -414,6 +442,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
414442 let least_region = least_region. unwrap_or ( tcx. lifetimes . re_static ) ;
415443 debug ! ( "constrain_opaque_types: least_region={:?}" , least_region) ;
416444
445+ if let GenerateMemberConstraints :: IfNoStaticBound = mode {
446+ if least_region != tcx. lifetimes . re_static {
447+ self . generate_member_constraint (
448+ concrete_ty,
449+ opaque_type_generics,
450+ opaque_defn,
451+ def_id,
452+ ) ;
453+ }
454+ }
417455 concrete_ty. visit_with ( & mut ConstrainOpaqueTypeRegionVisitor {
418456 tcx : self . tcx ,
419457 op : |r| self . sub_regions ( infer:: CallReturn ( span) , least_region, r) ,
@@ -434,19 +472,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
434472 opaque_type_generics : & ty:: Generics ,
435473 opaque_defn : & OpaqueTypeDecl < ' tcx > ,
436474 opaque_type_def_id : DefId ,
437- conflict1 : ty:: Region < ' tcx > ,
438- conflict2 : ty:: Region < ' tcx > ,
439475 ) {
440- // For now, enforce a feature gate outside of async functions.
441- if self . member_constraint_feature_gate (
442- opaque_defn,
443- opaque_type_def_id,
444- conflict1,
445- conflict2,
446- ) {
447- return ;
448- }
449-
450476 // Create the set of choice regions: each region in the hidden
451477 // type can be equal to any of the region parameters of the
452478 // opaque type definition.
@@ -500,8 +526,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
500526 hir:: OpaqueTyOrigin :: AsyncFn => return false ,
501527
502528 // Otherwise, generate the label we'll use in the error message.
503- hir:: OpaqueTyOrigin :: TypeAlias => "impl Trait" ,
504- hir:: OpaqueTyOrigin :: FnReturn => "impl Trait" ,
529+ hir:: OpaqueTyOrigin :: TypeAlias
530+ | hir:: OpaqueTyOrigin :: FnReturn
531+ | hir:: OpaqueTyOrigin :: Misc => "impl Trait" ,
505532 } ;
506533 let msg = format ! ( "ambiguous lifetime bound in `{}`" , context_name) ;
507534 let mut err = self . tcx . sess . struct_span_err ( span, & msg) ;
@@ -549,13 +576,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
549576 /// # Parameters
550577 ///
551578 /// - `def_id`, the `impl Trait` type
552- /// - `opaque_defn `, the opaque definition created in `instantiate_opaque_types`
579+ /// - `substs `, the substs used to instantiate this opaque type
553580 /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
554581 /// `opaque_defn.concrete_ty`
555582 pub fn infer_opaque_definition_from_instantiation (
556583 & self ,
557584 def_id : DefId ,
558- opaque_defn : & OpaqueTypeDecl < ' tcx > ,
585+ substs : SubstsRef < ' tcx > ,
559586 instantiated_ty : Ty < ' tcx > ,
560587 span : Span ,
561588 ) -> Ty < ' tcx > {
@@ -571,12 +598,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
571598 // `impl Trait` return type, resulting in the parameters
572599 // shifting.
573600 let id_substs = InternalSubsts :: identity_for_item ( self . tcx , def_id) ;
574- let map: FxHashMap < GenericArg < ' tcx > , GenericArg < ' tcx > > = opaque_defn
575- . substs
576- . iter ( )
577- . enumerate ( )
578- . map ( |( index, subst) | ( * subst, id_substs[ index] ) )
579- . collect ( ) ;
601+ let map: FxHashMap < GenericArg < ' tcx > , GenericArg < ' tcx > > =
602+ substs. iter ( ) . enumerate ( ) . map ( |( index, subst) | ( * subst, id_substs[ index] ) ) . collect ( ) ;
580603
581604 // Convert the type from the function into a type valid outside
582605 // the function, by replacing invalid regions with 'static,
@@ -598,11 +621,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
598621pub fn unexpected_hidden_region_diagnostic (
599622 tcx : TyCtxt < ' tcx > ,
600623 region_scope_tree : Option < & region:: ScopeTree > ,
601- opaque_type_def_id : DefId ,
624+ span : Span ,
602625 hidden_ty : Ty < ' tcx > ,
603626 hidden_region : ty:: Region < ' tcx > ,
604627) -> DiagnosticBuilder < ' tcx > {
605- let span = tcx. def_span ( opaque_type_def_id) ;
606628 let mut err = struct_span_err ! (
607629 tcx. sess,
608630 span,
@@ -817,32 +839,48 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
817839
818840 fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
819841 match r {
820- // ignore bound regions that appear in the type (e.g., this
821- // would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
822- ty:: ReLateBound ( ..) |
823-
824- // ignore `'static`, as that can appear anywhere
825- ty:: ReStatic => return r,
826-
827- _ => { }
842+ // Ignore bound regions and `'static` regions that appear in the
843+ // type, we only need to remap regions that reference lifetimes
844+ // from the function declaraion.
845+ // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
846+ ty:: ReLateBound ( ..) | ty:: ReStatic => return r,
847+
848+ // If regions have been erased (by writeback), don't try to unerase
849+ // them.
850+ ty:: ReErased => return r,
851+
852+ // The regions that we expect from borrow checking.
853+ ty:: ReEarlyBound ( _) | ty:: ReFree ( _) | ty:: ReEmpty ( ty:: UniverseIndex :: ROOT ) => { }
854+
855+ ty:: ReEmpty ( _)
856+ | ty:: RePlaceholder ( _)
857+ | ty:: ReVar ( _)
858+ | ty:: ReScope ( _)
859+ | ty:: ReClosureBound ( _) => {
860+ // All of the regions in the type should either have been
861+ // erased by writeback, or mapped back to named regions by
862+ // borrow checking.
863+ bug ! ( "unexpected region kind in opaque type: {:?}" , r) ;
864+ }
828865 }
829866
830867 let generics = self . tcx ( ) . generics_of ( self . opaque_type_def_id ) ;
831868 match self . map . get ( & r. into ( ) ) . map ( |k| k. unpack ( ) ) {
832869 Some ( GenericArgKind :: Lifetime ( r1) ) => r1,
833870 Some ( u) => panic ! ( "region mapped to unexpected kind: {:?}" , u) ,
871+ None if self . map_missing_regions_to_empty || self . tainted_by_errors => {
872+ self . tcx . lifetimes . re_root_empty
873+ }
834874 None if generics. parent . is_some ( ) => {
835- if !self . map_missing_regions_to_empty && !self . tainted_by_errors {
836- if let Some ( hidden_ty) = self . hidden_ty . take ( ) {
837- unexpected_hidden_region_diagnostic (
838- self . tcx ,
839- None ,
840- self . opaque_type_def_id ,
841- hidden_ty,
842- r,
843- )
844- . emit ( ) ;
845- }
875+ if let Some ( hidden_ty) = self . hidden_ty . take ( ) {
876+ unexpected_hidden_region_diagnostic (
877+ self . tcx ,
878+ None ,
879+ self . tcx . def_span ( self . opaque_type_def_id ) ,
880+ hidden_ty,
881+ r,
882+ )
883+ . emit ( ) ;
846884 }
847885 self . tcx . lifetimes . re_root_empty
848886 }
@@ -860,7 +898,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
860898 )
861899 . emit ( ) ;
862900
863- self . tcx ( ) . mk_region ( ty :: ReStatic )
901+ self . tcx ( ) . lifetimes . re_static
864902 }
865903 }
866904 }
0 commit comments