@@ -67,6 +67,9 @@ pub struct OpaqueTypeDecl<'tcx> {
6767 /// the fn body). (Ultimately, writeback is responsible for this
6868 /// check.)
6969 pub has_required_region_bounds : bool ,
70+
71+ /// The origin of the existential type
72+ pub origin : hir:: ExistTyOrigin ,
7073}
7174
7275impl < ' a , ' gcx , ' tcx > InferCtxt < ' a , ' gcx , ' tcx > {
@@ -326,14 +329,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
326329 // There are two regions (`lr` and
327330 // `subst_arg`) which are not relatable. We can't
328331 // find a best choice.
329- self . tcx
332+ let context_name = match opaque_defn. origin {
333+ hir:: ExistTyOrigin :: ExistentialType => "existential type" ,
334+ hir:: ExistTyOrigin :: ReturnImplTrait => "impl Trait" ,
335+ hir:: ExistTyOrigin :: AsyncFn => "async fn" ,
336+ } ;
337+ let msg = format ! ( "ambiguous lifetime bound in `{}`" , context_name) ;
338+ let mut err = self . tcx
330339 . sess
331- . struct_span_err ( span, "ambiguous lifetime bound in `impl Trait`" )
332- . span_label (
333- span,
334- format ! ( "neither `{}` nor `{}` outlives the other" , lr, subst_arg) ,
335- )
336- . emit ( ) ;
340+ . struct_span_err ( span, & msg) ;
341+
342+ let lr_name = lr. to_string ( ) ;
343+ let subst_arg_name = subst_arg. to_string ( ) ;
344+ let label_owned;
345+ let label = match ( & * lr_name, & * subst_arg_name) {
346+ ( "'_" , "'_" ) => "the elided lifetimes here do not outlive one another" ,
347+ _ => {
348+ label_owned = format ! (
349+ "neither `{}` nor `{}` outlives the other" ,
350+ lr_name,
351+ subst_arg_name,
352+ ) ;
353+ & label_owned
354+ }
355+ } ;
356+ err. span_label ( span, label) ;
357+
358+ if let hir:: ExistTyOrigin :: AsyncFn = opaque_defn. origin {
359+ err. note ( "multiple unrelated lifetimes are not allowed in \
360+ `async fn`.") ;
361+ err. note ( "if you're using argument-position elided lifetimes, consider \
362+ switching to a single named lifetime.") ;
363+ }
364+ err. emit ( ) ;
337365
338366 least_region = Some ( self . tcx . mk_region ( ty:: ReEmpty ) ) ;
339367 break ;
@@ -692,39 +720,49 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
692720 parent_def_id == tcx. hir ( )
693721 . local_def_id_from_hir_id ( opaque_parent_hir_id)
694722 } ;
695- let in_definition_scope = match tcx. hir ( ) . find_by_hir_id ( opaque_hir_id) {
723+ let ( in_definition_scope, origin) =
724+ match tcx. hir ( ) . find_by_hir_id ( opaque_hir_id)
725+ {
696726 Some ( Node :: Item ( item) ) => match item. node {
697727 // impl trait
698728 hir:: ItemKind :: Existential ( hir:: ExistTy {
699729 impl_trait_fn : Some ( parent) ,
730+ origin,
700731 ..
701- } ) => parent == self . parent_def_id ,
732+ } ) => ( parent == self . parent_def_id , origin ) ,
702733 // named existential types
703734 hir:: ItemKind :: Existential ( hir:: ExistTy {
704735 impl_trait_fn : None ,
736+ origin,
705737 ..
706- } ) => may_define_existential_type (
707- tcx,
708- self . parent_def_id ,
709- opaque_hir_id,
738+ } ) => (
739+ may_define_existential_type (
740+ tcx,
741+ self . parent_def_id ,
742+ opaque_hir_id,
743+ ) ,
744+ origin,
710745 ) ,
711- _ => def_scope_default ( ) ,
746+ _ => ( def_scope_default ( ) , hir :: ExistTyOrigin :: ExistentialType ) ,
712747 } ,
713748 Some ( Node :: ImplItem ( item) ) => match item. node {
714- hir:: ImplItemKind :: Existential ( _) => may_define_existential_type (
715- tcx,
716- self . parent_def_id ,
717- opaque_hir_id,
749+ hir:: ImplItemKind :: Existential ( _) => (
750+ may_define_existential_type (
751+ tcx,
752+ self . parent_def_id ,
753+ opaque_hir_id,
754+ ) ,
755+ hir:: ExistTyOrigin :: ExistentialType ,
718756 ) ,
719- _ => def_scope_default ( ) ,
757+ _ => ( def_scope_default ( ) , hir :: ExistTyOrigin :: ExistentialType ) ,
720758 } ,
721759 _ => bug ! (
722760 "expected (impl) item, found {}" ,
723761 tcx. hir( ) . hir_to_string( opaque_hir_id) ,
724762 ) ,
725763 } ;
726764 if in_definition_scope {
727- return self . fold_opaque_ty ( ty, def_id, substs) ;
765+ return self . fold_opaque_ty ( ty, def_id, substs, origin ) ;
728766 }
729767
730768 debug ! (
@@ -746,6 +784,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
746784 ty : Ty < ' tcx > ,
747785 def_id : DefId ,
748786 substs : SubstsRef < ' tcx > ,
787+ origin : hir:: ExistTyOrigin ,
749788 ) -> Ty < ' tcx > {
750789 let infcx = self . infcx ;
751790 let tcx = infcx. tcx ;
@@ -795,6 +834,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
795834 substs,
796835 concrete_ty : ty_var,
797836 has_required_region_bounds : !required_region_bounds. is_empty ( ) ,
837+ origin,
798838 } ,
799839 ) ;
800840 debug ! ( "instantiate_opaque_types: ty_var={:?}" , ty_var) ;
0 commit comments