11use crate :: ImplTraitPosition ;
22
3- use super :: errors:: { GenericTypeWithParentheses , UseAngleBrackets } ;
3+ use super :: errors:: {
4+ AsyncBoundNotOnTrait , AsyncBoundOnlyForFnTraits , GenericTypeWithParentheses , UseAngleBrackets ,
5+ } ;
46use super :: ResolverAstLoweringExt ;
57use super :: { GenericArgsCtor , LifetimeRes , ParenthesizedGenericArgs } ;
68use super :: { ImplTraitContext , LoweringContext , ParamMode } ;
79
810use rustc_ast:: { self as ast, * } ;
11+ use rustc_data_structures:: sync:: Lrc ;
912use rustc_hir as hir;
1013use rustc_hir:: def:: { DefKind , PartialRes , Res } ;
14+ use rustc_hir:: def_id:: DefId ;
1115use rustc_hir:: GenericArg ;
1216use rustc_middle:: span_bug;
1317use rustc_span:: symbol:: { kw, sym, Ident } ;
14- use rustc_span:: { BytePos , Span , DUMMY_SP } ;
18+ use rustc_span:: { BytePos , DesugaringKind , Span , Symbol , DUMMY_SP } ;
1519
1620use smallvec:: { smallvec, SmallVec } ;
1721
@@ -24,8 +28,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2428 p : & Path ,
2529 param_mode : ParamMode ,
2630 itctx : & ImplTraitContext ,
27- // constness of the impl/bound if this is a trait path
28- constness : Option < ast:: BoundConstness > ,
31+ // modifiers of the impl/bound if this is a trait path
32+ modifiers : Option < ast:: TraitBoundModifiers > ,
2933 ) -> hir:: QPath < ' hir > {
3034 let qself_position = qself. as_ref ( ) . map ( |q| q. position ) ;
3135 let qself = qself. as_ref ( ) . map ( |q| self . lower_ty ( & q. ty , itctx) ) ;
@@ -35,10 +39,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
3539 let base_res = partial_res. base_res ( ) ;
3640 let unresolved_segments = partial_res. unresolved_segments ( ) ;
3741
42+ let mut res = self . lower_res ( base_res) ;
43+
44+ // When we have an `async` kw on a bound, map the trait it resolves to.
45+ let mut bound_modifier_allowed_features = None ;
46+ if let Some ( TraitBoundModifiers { asyncness : BoundAsyncness :: Async ( _) , .. } ) = modifiers {
47+ match res {
48+ Res :: Def ( DefKind :: Trait , def_id) => {
49+ if let Some ( ( async_def_id, features) ) = self . map_trait_to_async_trait ( def_id) {
50+ res = Res :: Def ( DefKind :: Trait , async_def_id) ;
51+ bound_modifier_allowed_features = Some ( features) ;
52+ } else {
53+ self . dcx ( ) . emit_err ( AsyncBoundOnlyForFnTraits { span : p. span } ) ;
54+ }
55+ }
56+ Res :: Err => {
57+ // No additional error.
58+ }
59+ _ => {
60+ // This error isn't actually emitted AFAICT, but it's best to keep
61+ // it around in case the resolver doesn't always check the defkind
62+ // of an item or something.
63+ self . dcx ( ) . emit_err ( AsyncBoundNotOnTrait { span : p. span , descr : res. descr ( ) } ) ;
64+ }
65+ }
66+ }
67+
3868 let path_span_lo = p. span . shrink_to_lo ( ) ;
3969 let proj_start = p. segments . len ( ) - unresolved_segments;
4070 let path = self . arena . alloc ( hir:: Path {
41- res : self . lower_res ( base_res ) ,
71+ res,
4272 segments : self . arena . alloc_from_iter ( p. segments [ ..proj_start] . iter ( ) . enumerate ( ) . map (
4373 |( i, segment) | {
4474 let param_mode = match ( qself_position, param_mode) {
@@ -77,7 +107,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
77107 parenthesized_generic_args,
78108 itctx,
79109 // if this is the last segment, add constness to the trait path
80- if i == proj_start - 1 { constness } else { None } ,
110+ if i == proj_start - 1 { modifiers. map ( |m| m. constness ) } else { None } ,
111+ bound_modifier_allowed_features. clone ( ) ,
81112 )
82113 } ,
83114 ) ) ,
@@ -88,6 +119,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
88119 ) ,
89120 } ) ;
90121
122+ if let Some ( bound_modifier_allowed_features) = bound_modifier_allowed_features {
123+ path. span = self . mark_span_with_reason (
124+ DesugaringKind :: BoundModifier ,
125+ path. span ,
126+ Some ( bound_modifier_allowed_features) ,
127+ ) ;
128+ }
129+
91130 // Simple case, either no projections, or only fully-qualified.
92131 // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
93132 if unresolved_segments == 0 {
@@ -125,6 +164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
125164 ParenthesizedGenericArgs :: Err ,
126165 itctx,
127166 None ,
167+ None ,
128168 ) ) ;
129169 let qpath = hir:: QPath :: TypeRelative ( ty, hir_segment) ;
130170
@@ -166,6 +206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
166206 ParenthesizedGenericArgs :: Err ,
167207 & ImplTraitContext :: Disallowed ( ImplTraitPosition :: Path ) ,
168208 None ,
209+ None ,
169210 )
170211 } ) ) ,
171212 span : self . lower_span ( p. span ) ,
@@ -180,6 +221,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
180221 parenthesized_generic_args : ParenthesizedGenericArgs ,
181222 itctx : & ImplTraitContext ,
182223 constness : Option < ast:: BoundConstness > ,
224+ // Additional features ungated with a bound modifier like `async`.
225+ // This is passed down to the implicit associated type binding in
226+ // parenthesized bounds.
227+ bound_modifier_allowed_features : Option < Lrc < [ Symbol ] > > ,
183228 ) -> hir:: PathSegment < ' hir > {
184229 debug ! ( "path_span: {:?}, lower_path_segment(segment: {:?})" , path_span, segment) ;
185230 let ( mut generic_args, infer_args) = if let Some ( generic_args) = segment. args . as_deref ( ) {
@@ -188,9 +233,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
188233 self . lower_angle_bracketed_parameter_data ( data, param_mode, itctx)
189234 }
190235 GenericArgs :: Parenthesized ( data) => match parenthesized_generic_args {
191- ParenthesizedGenericArgs :: ParenSugar => {
192- self . lower_parenthesized_parameter_data ( data, itctx)
193- }
236+ ParenthesizedGenericArgs :: ParenSugar => self
237+ . lower_parenthesized_parameter_data (
238+ data,
239+ itctx,
240+ bound_modifier_allowed_features,
241+ ) ,
194242 ParenthesizedGenericArgs :: Err => {
195243 // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
196244 let sub = if !data. inputs . is_empty ( ) {
@@ -357,6 +405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
357405 & mut self ,
358406 data : & ParenthesizedArgs ,
359407 itctx : & ImplTraitContext ,
408+ bound_modifier_allowed_features : Option < Lrc < [ Symbol ] > > ,
360409 ) -> ( GenericArgsCtor < ' hir > , bool ) {
361410 // Switch to `PassThrough` mode for anonymous lifetimes; this
362411 // means that we permit things like `&Ref<T>`, where `Ref` has
@@ -392,7 +441,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
392441 FnRetTy :: Default ( _) => self . arena . alloc ( self . ty_tup ( * span, & [ ] ) ) ,
393442 } ;
394443 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) ;
444+
445+ // If we have a bound like `async Fn() -> T`, make sure that we mark the
446+ // `Output = T` associated type bound with the right feature gates.
447+ let mut output_span = output_ty. span ;
448+ if let Some ( bound_modifier_allowed_features) = bound_modifier_allowed_features {
449+ output_span = self . mark_span_with_reason (
450+ DesugaringKind :: BoundModifier ,
451+ output_span,
452+ Some ( bound_modifier_allowed_features) ,
453+ ) ;
454+ }
455+ let binding = self . assoc_ty_binding ( sym:: Output , output_span, output_ty) ;
456+
396457 (
397458 GenericArgsCtor {
398459 args,
@@ -429,4 +490,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
429490 kind,
430491 }
431492 }
493+
494+ /// When a bound is annotated with `async`, it signals to lowering that the trait
495+ /// that the bound refers to should be mapped to the "async" flavor of the trait.
496+ ///
497+ /// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one
498+ /// that is generic over `async`ness, if that's ever possible, or modify the
499+ /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
500+ fn map_trait_to_async_trait ( & self , def_id : DefId ) -> Option < ( DefId , Lrc < [ Symbol ] > ) > {
501+ let lang_items = self . tcx . lang_items ( ) ;
502+ if Some ( def_id) == lang_items. fn_trait ( ) {
503+ Some ( ( lang_items. async_fn_trait ( ) ?, self . allow_async_fn_traits . clone ( ) ) )
504+ } else if Some ( def_id) == lang_items. fn_mut_trait ( ) {
505+ Some ( ( lang_items. async_fn_mut_trait ( ) ?, self . allow_async_fn_traits . clone ( ) ) )
506+ } else if Some ( def_id) == lang_items. fn_once_trait ( ) {
507+ Some ( ( lang_items. async_fn_once_trait ( ) ?, self . allow_async_fn_traits . clone ( ) ) )
508+ } else {
509+ None
510+ }
511+ }
432512}
0 commit comments