@@ -6,12 +6,14 @@ use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
66use super :: { ImplTraitContext , LoweringContext , ParamMode } ;
77
88use rustc_ast:: { self as ast, * } ;
9+ use rustc_data_structures:: sync:: Lrc ;
910use rustc_hir as hir;
1011use rustc_hir:: def:: { DefKind , PartialRes , Res } ;
12+ use rustc_hir:: def_id:: DefId ;
1113use rustc_hir:: GenericArg ;
1214use rustc_middle:: span_bug;
1315use rustc_span:: symbol:: { kw, sym, Ident } ;
14- use rustc_span:: { BytePos , Span , DUMMY_SP } ;
16+ use rustc_span:: { BytePos , DesugaringKind , Span , Symbol , DUMMY_SP } ;
1517
1618use smallvec:: { smallvec, SmallVec } ;
1719
@@ -24,8 +26,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2426 p : & Path ,
2527 param_mode : ParamMode ,
2628 itctx : & ImplTraitContext ,
27- // constness of the impl/bound if this is a trait path
28- constness : Option < ast:: BoundConstness > ,
29+ // modifiers of the impl/bound if this is a trait path
30+ modifiers : Option < ast:: TraitBoundModifiers > ,
2931 ) -> hir:: QPath < ' hir > {
3032 let qself_position = qself. as_ref ( ) . map ( |q| q. position ) ;
3133 let qself = qself. as_ref ( ) . map ( |q| self . lower_ty ( & q. ty , itctx) ) ;
@@ -35,10 +37,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
3537 let base_res = partial_res. base_res ( ) ;
3638 let unresolved_segments = partial_res. unresolved_segments ( ) ;
3739
40+ let mut res = self . lower_res ( base_res) ;
41+
42+ // When we have an `async` kw on a bound, map the trait it resolves to.
43+ let mut bound_modifier_allowed_features = None ;
44+ if let Some ( TraitBoundModifiers { asyncness : BoundAsyncness :: Async ( _) , .. } ) = modifiers {
45+ if let Res :: Def ( DefKind :: Trait , def_id) = res {
46+ if let Some ( ( async_def_id, features) ) = self . map_trait_to_async_trait ( def_id) {
47+ res = Res :: Def ( DefKind :: Trait , async_def_id) ;
48+ bound_modifier_allowed_features = Some ( features) ;
49+ } else {
50+ panic ! ( ) ;
51+ }
52+ } else {
53+ panic ! ( ) ;
54+ }
55+ }
56+
3857 let path_span_lo = p. span . shrink_to_lo ( ) ;
3958 let proj_start = p. segments . len ( ) - unresolved_segments;
4059 let path = self . arena . alloc ( hir:: Path {
41- res : self . lower_res ( base_res ) ,
60+ res,
4261 segments : self . arena . alloc_from_iter ( p. segments [ ..proj_start] . iter ( ) . enumerate ( ) . map (
4362 |( i, segment) | {
4463 let param_mode = match ( qself_position, param_mode) {
@@ -77,7 +96,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
7796 parenthesized_generic_args,
7897 itctx,
7998 // if this is the last segment, add constness to the trait path
80- if i == proj_start - 1 { constness } else { None } ,
99+ if i == proj_start - 1 { modifiers. map ( |m| m. constness ) } else { None } ,
100+ bound_modifier_allowed_features. clone ( ) ,
81101 )
82102 } ,
83103 ) ) ,
@@ -88,6 +108,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
88108 ) ,
89109 } ) ;
90110
111+ if let Some ( bound_modifier_allowed_features) = bound_modifier_allowed_features {
112+ path. span = self . mark_span_with_reason (
113+ DesugaringKind :: BoundModifier ,
114+ path. span ,
115+ Some ( bound_modifier_allowed_features) ,
116+ ) ;
117+ }
118+
91119 // Simple case, either no projections, or only fully-qualified.
92120 // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
93121 if unresolved_segments == 0 {
@@ -125,6 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
125153 ParenthesizedGenericArgs :: Err ,
126154 itctx,
127155 None ,
156+ None ,
128157 ) ) ;
129158 let qpath = hir:: QPath :: TypeRelative ( ty, hir_segment) ;
130159
@@ -166,6 +195,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
166195 ParenthesizedGenericArgs :: Err ,
167196 & ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
168197 None ,
198+ None ,
169199 )
170200 } ) ) ,
171201 span : self . lower_span ( p. span ) ,
@@ -180,6 +210,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
180210 parenthesized_generic_args : ParenthesizedGenericArgs ,
181211 itctx : & ImplTraitContext ,
182212 constness : Option < ast:: BoundConstness > ,
213+ // Additional features ungated with a bound modifier like `async`.
214+ // This is passed down to the implicit associated type binding in
215+ // parenthesized bounds.
216+ bound_modifier_allowed_features : Option < Lrc < [ Symbol ] > > ,
183217 ) -> hir:: PathSegment < ' hir > {
184218 debug ! ( "path_span: {:?}, lower_path_segment(segment: {:?})" , path_span, segment) ;
185219 let ( mut generic_args, infer_args) = if let Some ( generic_args) = segment. args . as_deref ( ) {
@@ -188,9 +222,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
188222 self . lower_angle_bracketed_parameter_data ( data, param_mode, itctx)
189223 }
190224 GenericArgs :: Parenthesized ( data) => match parenthesized_generic_args {
191- ParenthesizedGenericArgs :: ParenSugar => {
192- self . lower_parenthesized_parameter_data ( data, itctx)
193- }
225+ ParenthesizedGenericArgs :: ParenSugar => self
226+ . lower_parenthesized_parameter_data (
227+ data,
228+ itctx,
229+ bound_modifier_allowed_features,
230+ ) ,
194231 ParenthesizedGenericArgs :: Err => {
195232 // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
196233 let sub = if !data. inputs . is_empty ( ) {
@@ -357,6 +394,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
357394 & mut self ,
358395 data : & ParenthesizedArgs ,
359396 itctx : & ImplTraitContext ,
397+ bound_modifier_allowed_features : Option < Lrc < [ Symbol ] > > ,
360398 ) -> ( GenericArgsCtor < ' hir > , bool ) {
361399 // Switch to `PassThrough` mode for anonymous lifetimes; this
362400 // means that we permit things like `&Ref<T>`, where `Ref` has
@@ -392,7 +430,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
392430 FnRetTy :: Default ( _) => self . arena . alloc ( self . ty_tup ( * span, & [ ] ) ) ,
393431 } ;
394432 let args = smallvec ! [ GenericArg :: Type ( self . arena. alloc( self . ty_tup( * inputs_span, inputs) ) ) ] ;
395- let binding = self . assoc_ty_binding ( sym:: Output , output_ty. span , output_ty) ;
433+
434+ // If we have a bound like `async Fn() -> T`, make sure that we mark the
435+ // `Output = T` associated type bound with the right feature gates.
436+ let mut output_span = output_ty. span ;
437+ if let Some ( bound_modifier_allowed_features) = bound_modifier_allowed_features {
438+ output_span = self . mark_span_with_reason (
439+ DesugaringKind :: BoundModifier ,
440+ output_span,
441+ Some ( bound_modifier_allowed_features) ,
442+ ) ;
443+ }
444+ let binding = self . assoc_ty_binding ( sym:: Output , output_span, output_ty) ;
445+
396446 (
397447 GenericArgsCtor {
398448 args,
@@ -429,4 +479,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
429479 kind,
430480 }
431481 }
482+
483+ /// When a bound is annotated with `async`, it signals to lowering that the trait
484+ /// that the bound refers to should be mapped to the "async" flavor of the trait.
485+ ///
486+ /// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one
487+ /// that is generic over `async`ness, if that's ever possible, or modify the
488+ /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
489+ fn map_trait_to_async_trait ( & self , def_id : DefId ) -> Option < ( DefId , Lrc < [ Symbol ] > ) > {
490+ let lang_items = self . tcx . lang_items ( ) ;
491+ if Some ( def_id) == lang_items. fn_trait ( ) {
492+ Some ( ( lang_items. async_fn_trait ( ) ?, self . allow_async_fn_traits . clone ( ) ) )
493+ } else if Some ( def_id) == lang_items. fn_mut_trait ( ) {
494+ Some ( ( lang_items. async_fn_mut_trait ( ) ?, self . allow_async_fn_traits . clone ( ) ) )
495+ } else if Some ( def_id) == lang_items. fn_once_trait ( ) {
496+ Some ( ( lang_items. async_fn_once_trait ( ) ?, self . allow_async_fn_traits . clone ( ) ) )
497+ } else {
498+ None
499+ }
500+ }
432501}
0 commit comments