]>
Commit | Line | Data |
---|---|---|
5099ac24 FG |
1 | use crate::ImplTraitPosition; |
2 | ||
c620b35d FG |
3 | use super::errors::{ |
4 | AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, GenericTypeWithParentheses, UseAngleBrackets, | |
5 | }; | |
923072b8 | 6 | use super::ResolverAstLoweringExt; |
04454e1e FG |
7 | use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; |
8 | use super::{ImplTraitContext, LoweringContext, ParamMode}; | |
dfeec247 | 9 | |
3dfed10e | 10 | use rustc_ast::{self as ast, *}; |
c620b35d | 11 | use rustc_data_structures::sync::Lrc; |
dfeec247 XL |
12 | use rustc_hir as hir; |
13 | use rustc_hir::def::{DefKind, PartialRes, Res}; | |
c620b35d | 14 | use rustc_hir::def_id::DefId; |
dfeec247 | 15 | use rustc_hir::GenericArg; |
4b012472 | 16 | use rustc_middle::span_bug; |
487cf647 | 17 | use rustc_span::symbol::{kw, sym, Ident}; |
c620b35d | 18 | use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP}; |
dfeec247 | 19 | |
487cf647 | 20 | use smallvec::{smallvec, SmallVec}; |
31ef2f64 | 21 | use tracing::{debug, instrument}; |
dfeec247 XL |
22 | |
23 | impl<'a, 'hir> LoweringContext<'a, 'hir> { | |
923072b8 FG |
24 | #[instrument(level = "trace", skip(self))] |
25 | pub(crate) fn lower_qpath( | |
dfeec247 XL |
26 | &mut self, |
27 | id: NodeId, | |
487cf647 | 28 | qself: &Option<ptr::P<QSelf>>, |
dfeec247 XL |
29 | p: &Path, |
30 | param_mode: ParamMode, | |
c620b35d FG |
31 | itctx: ImplTraitContext, |
32 | // modifiers of the impl/bound if this is a trait path | |
33 | modifiers: Option<ast::TraitBoundModifiers>, | |
dfeec247 XL |
34 | ) -> hir::QPath<'hir> { |
35 | let qself_position = qself.as_ref().map(|q| q.position); | |
923072b8 | 36 | let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); |
dfeec247 XL |
37 | |
38 | let partial_res = | |
39 | self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); | |
2b03887a FG |
40 | let base_res = partial_res.base_res(); |
41 | let unresolved_segments = partial_res.unresolved_segments(); | |
dfeec247 | 42 | |
c620b35d FG |
43 | let mut res = self.lower_res(base_res); |
44 | ||
45 | // When we have an `async` kw on a bound, map the trait it resolves to. | |
46 | let mut bound_modifier_allowed_features = None; | |
47 | if let Some(TraitBoundModifiers { asyncness: BoundAsyncness::Async(_), .. }) = modifiers { | |
48 | match res { | |
49 | Res::Def(DefKind::Trait, def_id) => { | |
50 | if let Some((async_def_id, features)) = self.map_trait_to_async_trait(def_id) { | |
51 | res = Res::Def(DefKind::Trait, async_def_id); | |
52 | bound_modifier_allowed_features = Some(features); | |
53 | } else { | |
54 | self.dcx().emit_err(AsyncBoundOnlyForFnTraits { span: p.span }); | |
55 | } | |
56 | } | |
57 | Res::Err => { | |
58 | // No additional error. | |
59 | } | |
60 | _ => { | |
61 | // This error isn't actually emitted AFAICT, but it's best to keep | |
62 | // it around in case the resolver doesn't always check the defkind | |
63 | // of an item or something. | |
64 | self.dcx().emit_err(AsyncBoundNotOnTrait { span: p.span, descr: res.descr() }); | |
65 | } | |
66 | } | |
67 | } | |
68 | ||
6a06907d | 69 | let path_span_lo = p.span.shrink_to_lo(); |
2b03887a | 70 | let proj_start = p.segments.len() - unresolved_segments; |
dfeec247 | 71 | let path = self.arena.alloc(hir::Path { |
c620b35d | 72 | res, |
dfeec247 XL |
73 | segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map( |
74 | |(i, segment)| { | |
75 | let param_mode = match (qself_position, param_mode) { | |
76 | (Some(j), ParamMode::Optional) if i < j => { | |
77 | // This segment is part of the trait path in a | |
78 | // qualified path - one of `a`, `b` or `Trait` | |
79 | // in `<X as a::b::Trait>::T::U::method`. | |
80 | ParamMode::Explicit | |
81 | } | |
82 | _ => param_mode, | |
83 | }; | |
84 | ||
2b03887a | 85 | let parenthesized_generic_args = match base_res { |
dfeec247 XL |
86 | // `a::b::Trait(Args)` |
87 | Res::Def(DefKind::Trait, _) if i + 1 == proj_start => { | |
353b0b11 | 88 | ParenthesizedGenericArgs::ParenSugar |
dfeec247 XL |
89 | } |
90 | // `a::b::Trait(Args)::TraitItem` | |
ba9703b0 | 91 | Res::Def(DefKind::AssocFn, _) |
dfeec247 XL |
92 | | Res::Def(DefKind::AssocConst, _) |
93 | | Res::Def(DefKind::AssocTy, _) | |
94 | if i + 2 == proj_start => | |
95 | { | |
353b0b11 | 96 | ParenthesizedGenericArgs::ParenSugar |
dfeec247 XL |
97 | } |
98 | // Avoid duplicated errors. | |
353b0b11 | 99 | Res::Err => ParenthesizedGenericArgs::ParenSugar, |
dfeec247 XL |
100 | // An error |
101 | _ => ParenthesizedGenericArgs::Err, | |
102 | }; | |
103 | ||
dfeec247 XL |
104 | self.lower_path_segment( |
105 | p.span, | |
106 | segment, | |
107 | param_mode, | |
dfeec247 | 108 | parenthesized_generic_args, |
923072b8 | 109 | itctx, |
add651ee | 110 | // if this is the last segment, add constness to the trait path |
c620b35d FG |
111 | if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None }, |
112 | bound_modifier_allowed_features.clone(), | |
dfeec247 XL |
113 | ) |
114 | }, | |
115 | )), | |
94222f64 XL |
116 | span: self.lower_span( |
117 | p.segments[..proj_start] | |
118 | .last() | |
119 | .map_or(path_span_lo, |segment| path_span_lo.to(segment.span())), | |
120 | ), | |
dfeec247 XL |
121 | }); |
122 | ||
c620b35d FG |
123 | if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features { |
124 | path.span = self.mark_span_with_reason( | |
125 | DesugaringKind::BoundModifier, | |
126 | path.span, | |
127 | Some(bound_modifier_allowed_features), | |
128 | ); | |
129 | } | |
130 | ||
dfeec247 XL |
131 | // Simple case, either no projections, or only fully-qualified. |
132 | // E.g., `std::mem::size_of` or `<I as Iterator>::Item`. | |
2b03887a | 133 | if unresolved_segments == 0 { |
dfeec247 XL |
134 | return hir::QPath::Resolved(qself, path); |
135 | } | |
136 | ||
137 | // Create the innermost type that we're projecting from. | |
138 | let mut ty = if path.segments.is_empty() { | |
139 | // If the base path is empty that means there exists a | |
140 | // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`. | |
141 | qself.expect("missing QSelf for <T>::...") | |
142 | } else { | |
143 | // Otherwise, the base path is an implicit `Self` type path, | |
144 | // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in | |
145 | // `<I as Iterator>::Item::default`. | |
146 | let new_id = self.next_id(); | |
6a06907d | 147 | self.arena.alloc(self.ty_path(new_id, path.span, hir::QPath::Resolved(qself, path))) |
dfeec247 XL |
148 | }; |
149 | ||
150 | // Anything after the base path are associated "extensions", | |
151 | // out of which all but the last one are associated types, | |
152 | // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`: | |
153 | // * base path is `std::vec::Vec<T>` | |
154 | // * "extensions" are `IntoIter`, `Item` and `clone` | |
155 | // * type nodes are: | |
156 | // 1. `std::vec::Vec<T>` (created above) | |
157 | // 2. `<std::vec::Vec<T>>::IntoIter` | |
158 | // 3. `<<std::vec::Vec<T>>::IntoIter>::Item` | |
159 | // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone` | |
160 | for (i, segment) in p.segments.iter().enumerate().skip(proj_start) { | |
6a06907d | 161 | let hir_segment = self.arena.alloc(self.lower_path_segment( |
dfeec247 XL |
162 | p.span, |
163 | segment, | |
164 | param_mode, | |
dfeec247 | 165 | ParenthesizedGenericArgs::Err, |
923072b8 | 166 | itctx, |
add651ee | 167 | None, |
c620b35d | 168 | None, |
dfeec247 | 169 | )); |
6a06907d | 170 | let qpath = hir::QPath::TypeRelative(ty, hir_segment); |
dfeec247 XL |
171 | |
172 | // It's finished, return the extension of the right node type. | |
173 | if i == p.segments.len() - 1 { | |
174 | return qpath; | |
175 | } | |
176 | ||
177 | // Wrap the associated extension in another type node. | |
178 | let new_id = self.next_id(); | |
6a06907d | 179 | ty = self.arena.alloc(self.ty_path(new_id, path_span_lo.to(segment.span()), qpath)); |
dfeec247 XL |
180 | } |
181 | ||
182 | // We should've returned in the for loop above. | |
ba9703b0 | 183 | |
c0240ec0 | 184 | self.dcx().span_bug( |
dfeec247 | 185 | p.span, |
49aad941 | 186 | format!( |
ba9703b0 XL |
187 | "lower_qpath: no final extension segment in {}..{}", |
188 | proj_start, | |
189 | p.segments.len() | |
190 | ), | |
191 | ); | |
dfeec247 XL |
192 | } |
193 | ||
487cf647 | 194 | pub(crate) fn lower_use_path( |
dfeec247 | 195 | &mut self, |
487cf647 | 196 | res: SmallVec<[Res; 3]>, |
dfeec247 XL |
197 | p: &Path, |
198 | param_mode: ParamMode, | |
487cf647 | 199 | ) -> &'hir hir::UsePath<'hir> { |
c620b35d | 200 | assert!((1..=3).contains(&res.len())); |
487cf647 | 201 | self.arena.alloc(hir::UsePath { |
dfeec247 XL |
202 | res, |
203 | segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { | |
204 | self.lower_path_segment( | |
205 | p.span, | |
206 | segment, | |
207 | param_mode, | |
dfeec247 | 208 | ParenthesizedGenericArgs::Err, |
c620b35d FG |
209 | ImplTraitContext::Disallowed(ImplTraitPosition::Path), |
210 | None, | |
add651ee | 211 | None, |
dfeec247 XL |
212 | ) |
213 | })), | |
94222f64 | 214 | span: self.lower_span(p.span), |
dfeec247 XL |
215 | }) |
216 | } | |
217 | ||
923072b8 | 218 | pub(crate) fn lower_path_segment( |
dfeec247 XL |
219 | &mut self, |
220 | path_span: Span, | |
221 | segment: &PathSegment, | |
222 | param_mode: ParamMode, | |
dfeec247 | 223 | parenthesized_generic_args: ParenthesizedGenericArgs, |
c620b35d | 224 | itctx: ImplTraitContext, |
c0240ec0 | 225 | constness: Option<ast::BoundConstness>, |
c620b35d FG |
226 | // Additional features ungated with a bound modifier like `async`. |
227 | // This is passed down to the implicit associated type binding in | |
228 | // parenthesized bounds. | |
229 | bound_modifier_allowed_features: Option<Lrc<[Symbol]>>, | |
dfeec247 | 230 | ) -> hir::PathSegment<'hir> { |
add651ee | 231 | debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment); |
487cf647 FG |
232 | let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() { |
233 | match generic_args { | |
234 | GenericArgs::AngleBracketed(data) => { | |
dfeec247 XL |
235 | self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) |
236 | } | |
487cf647 | 237 | GenericArgs::Parenthesized(data) => match parenthesized_generic_args { |
c620b35d FG |
238 | ParenthesizedGenericArgs::ParenSugar => self |
239 | .lower_parenthesized_parameter_data( | |
240 | data, | |
241 | itctx, | |
242 | bound_modifier_allowed_features, | |
243 | ), | |
dfeec247 | 244 | ParenthesizedGenericArgs::Err => { |
923072b8 | 245 | // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` |
f2b60f7d | 246 | let sub = if !data.inputs.is_empty() { |
923072b8 FG |
247 | // Start of the span to the 1st character of 1st argument |
248 | let open_param = data.inputs_span.shrink_to_lo().to(data | |
249 | .inputs | |
250 | .first() | |
251 | .unwrap() | |
252 | .span | |
253 | .shrink_to_lo()); | |
254 | // Last character position of last argument to the end of the span | |
255 | let close_param = data | |
256 | .inputs | |
257 | .last() | |
258 | .unwrap() | |
259 | .span | |
260 | .shrink_to_hi() | |
261 | .to(data.inputs_span.shrink_to_hi()); | |
f2b60f7d FG |
262 | |
263 | Some(UseAngleBrackets { open_param, close_param }) | |
264 | } else { | |
265 | None | |
266 | }; | |
c0240ec0 | 267 | self.dcx().emit_err(GenericTypeWithParentheses { span: data.span, sub }); |
dfeec247 XL |
268 | ( |
269 | self.lower_angle_bracketed_parameter_data( | |
270 | &data.as_angle_bracketed_args(), | |
271 | param_mode, | |
272 | itctx, | |
273 | ) | |
274 | .0, | |
275 | false, | |
276 | ) | |
277 | } | |
278 | }, | |
279 | } | |
280 | } else { | |
17df50a5 XL |
281 | ( |
282 | GenericArgsCtor { | |
283 | args: Default::default(), | |
31ef2f64 | 284 | constraints: &[], |
353b0b11 | 285 | parenthesized: hir::GenericArgsParentheses::No, |
17df50a5 XL |
286 | span: path_span.shrink_to_hi(), |
287 | }, | |
288 | param_mode == ParamMode::Optional, | |
289 | ) | |
dfeec247 XL |
290 | }; |
291 | ||
add651ee FG |
292 | if let Some(constness) = constness { |
293 | generic_args.push_constness(self, constness); | |
294 | } | |
295 | ||
29967ef6 XL |
296 | let has_lifetimes = |
297 | generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); | |
353b0b11 FG |
298 | |
299 | // FIXME(return_type_notation): Is this correct? I think so. | |
300 | if generic_args.parenthesized != hir::GenericArgsParentheses::ParenSugar && !has_lifetimes { | |
04454e1e FG |
301 | self.maybe_insert_elided_lifetimes_in_path( |
302 | path_span, | |
303 | segment.id, | |
304 | segment.ident.span, | |
305 | &mut generic_args, | |
306 | ); | |
dfeec247 XL |
307 | } |
308 | ||
309 | let res = self.expect_full_res(segment.id); | |
f2b60f7d | 310 | let hir_id = self.lower_node_id(segment.id); |
dfeec247 XL |
311 | debug!( |
312 | "lower_path_segment: ident={:?} original-id={:?} new-id={:?}", | |
f2b60f7d | 313 | segment.ident, segment.id, hir_id, |
dfeec247 XL |
314 | ); |
315 | ||
316 | hir::PathSegment { | |
94222f64 | 317 | ident: self.lower_ident(segment.ident), |
f2b60f7d FG |
318 | hir_id, |
319 | res: self.lower_res(res), | |
dfeec247 | 320 | infer_args, |
17df50a5 | 321 | args: if generic_args.is_empty() && generic_args.span.is_empty() { |
dfeec247 XL |
322 | None |
323 | } else { | |
94222f64 | 324 | Some(generic_args.into_generic_args(self)) |
dfeec247 XL |
325 | }, |
326 | } | |
327 | } | |
328 | ||
04454e1e FG |
329 | fn maybe_insert_elided_lifetimes_in_path( |
330 | &mut self, | |
331 | path_span: Span, | |
332 | segment_id: NodeId, | |
333 | segment_ident_span: Span, | |
334 | generic_args: &mut GenericArgsCtor<'hir>, | |
335 | ) { | |
336 | let (start, end) = match self.resolver.get_lifetime_res(segment_id) { | |
337 | Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end), | |
338 | None => return, | |
4b012472 FG |
339 | Some(res) => { |
340 | span_bug!(path_span, "expected an elided lifetime to insert. found {res:?}") | |
341 | } | |
04454e1e FG |
342 | }; |
343 | let expected_lifetimes = end.as_usize() - start.as_usize(); | |
344 | debug!(expected_lifetimes); | |
345 | ||
346 | // Note: these spans are used for diagnostics when they can't be inferred. | |
347 | // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label | |
348 | let elided_lifetime_span = if generic_args.span.is_empty() { | |
349 | // If there are no brackets, use the identifier span. | |
350 | // HACK: we use find_ancestor_inside to properly suggest elided spans in paths | |
351 | // originating from macros, since the segment's span might be from a macro arg. | |
352 | segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span) | |
353 | } else if generic_args.is_empty() { | |
354 | // If there are brackets, but not generic arguments, then use the opening bracket | |
355 | generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)) | |
356 | } else { | |
357 | // Else use an empty span right after the opening bracket. | |
358 | generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo() | |
359 | }; | |
360 | ||
361 | generic_args.args.insert_many( | |
362 | 0, | |
363 | (start.as_u32()..end.as_u32()).map(|i| { | |
364 | let id = NodeId::from_u32(i); | |
365 | let l = self.lower_lifetime(&Lifetime { | |
366 | id, | |
487cf647 | 367 | ident: Ident::new(kw::Empty, elided_lifetime_span), |
04454e1e FG |
368 | }); |
369 | GenericArg::Lifetime(l) | |
370 | }), | |
371 | ); | |
372 | } | |
373 | ||
5869c6ff | 374 | pub(crate) fn lower_angle_bracketed_parameter_data( |
dfeec247 XL |
375 | &mut self, |
376 | data: &AngleBracketedArgs, | |
377 | param_mode: ParamMode, | |
c620b35d | 378 | itctx: ImplTraitContext, |
dfeec247 | 379 | ) -> (GenericArgsCtor<'hir>, bool) { |
ba9703b0 XL |
380 | let has_non_lt_args = data.args.iter().any(|arg| match arg { |
381 | AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) | |
382 | | AngleBracketedArg::Constraint(_) => false, | |
383 | AngleBracketedArg::Arg(ast::GenericArg::Type(_) | ast::GenericArg::Const(_)) => true, | |
dfeec247 | 384 | }); |
ba9703b0 XL |
385 | let args = data |
386 | .args | |
387 | .iter() | |
388 | .filter_map(|arg| match arg { | |
923072b8 | 389 | AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx)), |
ba9703b0 XL |
390 | AngleBracketedArg::Constraint(_) => None, |
391 | }) | |
392 | .collect(); | |
31ef2f64 FG |
393 | let constraints = |
394 | self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg { | |
395 | AngleBracketedArg::Constraint(c) => { | |
396 | Some(self.lower_assoc_item_constraint(c, itctx)) | |
397 | } | |
398 | AngleBracketedArg::Arg(_) => None, | |
399 | })); | |
353b0b11 FG |
400 | let ctor = GenericArgsCtor { |
401 | args, | |
31ef2f64 | 402 | constraints, |
353b0b11 FG |
403 | parenthesized: hir::GenericArgsParentheses::No, |
404 | span: data.span, | |
405 | }; | |
ba9703b0 | 406 | (ctor, !has_non_lt_args && param_mode == ParamMode::Optional) |
dfeec247 XL |
407 | } |
408 | ||
409 | fn lower_parenthesized_parameter_data( | |
410 | &mut self, | |
411 | data: &ParenthesizedArgs, | |
c620b35d FG |
412 | itctx: ImplTraitContext, |
413 | bound_modifier_allowed_features: Option<Lrc<[Symbol]>>, | |
dfeec247 XL |
414 | ) -> (GenericArgsCtor<'hir>, bool) { |
415 | // Switch to `PassThrough` mode for anonymous lifetimes; this | |
416 | // means that we permit things like `&Ref<T>`, where `Ref` has | |
417 | // a hidden lifetime parameter. This is needed for backwards | |
418 | // compatibility, even in contexts like an impl header where | |
419 | // we generally don't permit such things (see #51008). | |
923072b8 FG |
420 | let ParenthesizedArgs { span, inputs, inputs_span, output } = data; |
421 | let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { | |
c620b35d | 422 | self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) |
923072b8 FG |
423 | })); |
424 | let output_ty = match output { | |
487cf647 FG |
425 | // Only allow `impl Trait` in return position. i.e.: |
426 | // ```rust | |
427 | // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug | |
428 | // // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^ | |
429 | // ``` | |
c620b35d | 430 | FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::OpaqueTy { .. }) => { |
487cf647 | 431 | if self.tcx.features().impl_trait_in_fn_trait_return { |
4b012472 | 432 | self.lower_ty(ty, itctx) |
487cf647 FG |
433 | } else { |
434 | self.lower_ty( | |
4b012472 | 435 | ty, |
c620b35d | 436 | ImplTraitContext::FeatureGated( |
487cf647 FG |
437 | ImplTraitPosition::FnTraitReturn, |
438 | sym::impl_trait_in_fn_trait_return, | |
439 | ), | |
440 | ) | |
441 | } | |
442 | } | |
923072b8 | 443 | FnRetTy::Ty(ty) => { |
c620b35d | 444 | self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) |
923072b8 FG |
445 | } |
446 | FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), | |
447 | }; | |
f2b60f7d | 448 | let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; |
c620b35d FG |
449 | |
450 | // If we have a bound like `async Fn() -> T`, make sure that we mark the | |
451 | // `Output = T` associated type bound with the right feature gates. | |
452 | let mut output_span = output_ty.span; | |
453 | if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features { | |
454 | output_span = self.mark_span_with_reason( | |
455 | DesugaringKind::BoundModifier, | |
456 | output_span, | |
457 | Some(bound_modifier_allowed_features), | |
458 | ); | |
459 | } | |
31ef2f64 | 460 | let constraint = self.assoc_ty_binding(sym::Output, output_span, output_ty); |
c620b35d | 461 | |
923072b8 FG |
462 | ( |
463 | GenericArgsCtor { | |
464 | args, | |
31ef2f64 | 465 | constraints: arena_vec![self; constraint], |
353b0b11 | 466 | parenthesized: hir::GenericArgsParentheses::ParenSugar, |
923072b8 FG |
467 | span: data.inputs_span, |
468 | }, | |
469 | false, | |
470 | ) | |
dfeec247 XL |
471 | } |
472 | ||
31ef2f64 | 473 | /// An associated type binding (i.e., associated type equality constraint). |
4b012472 | 474 | pub(crate) fn assoc_ty_binding( |
dfeec247 | 475 | &mut self, |
4b012472 | 476 | assoc_ty_name: rustc_span::Symbol, |
dfeec247 XL |
477 | span: Span, |
478 | ty: &'hir hir::Ty<'hir>, | |
31ef2f64 | 479 | ) -> hir::AssocItemConstraint<'hir> { |
4b012472 | 480 | let ident = Ident::with_dummy_span(assoc_ty_name); |
31ef2f64 | 481 | let kind = hir::AssocItemConstraintKind::Equality { term: ty.into() }; |
5869c6ff | 482 | let args = arena_vec![self;]; |
31ef2f64 | 483 | let constraints = arena_vec![self;]; |
17df50a5 XL |
484 | let gen_args = self.arena.alloc(hir::GenericArgs { |
485 | args, | |
31ef2f64 | 486 | constraints, |
353b0b11 | 487 | parenthesized: hir::GenericArgsParentheses::No, |
17df50a5 XL |
488 | span_ext: DUMMY_SP, |
489 | }); | |
31ef2f64 | 490 | hir::AssocItemConstraint { |
94222f64 XL |
491 | hir_id: self.next_id(), |
492 | gen_args, | |
493 | span: self.lower_span(span), | |
494 | ident, | |
495 | kind, | |
496 | } | |
dfeec247 | 497 | } |
c620b35d FG |
498 | |
499 | /// When a bound is annotated with `async`, it signals to lowering that the trait | |
500 | /// that the bound refers to should be mapped to the "async" flavor of the trait. | |
501 | /// | |
502 | /// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one | |
503 | /// that is generic over `async`ness, if that's ever possible, or modify the | |
504 | /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`. | |
505 | fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<(DefId, Lrc<[Symbol]>)> { | |
506 | let lang_items = self.tcx.lang_items(); | |
507 | if Some(def_id) == lang_items.fn_trait() { | |
508 | Some((lang_items.async_fn_trait()?, self.allow_async_fn_traits.clone())) | |
509 | } else if Some(def_id) == lang_items.fn_mut_trait() { | |
510 | Some((lang_items.async_fn_mut_trait()?, self.allow_async_fn_traits.clone())) | |
511 | } else if Some(def_id) == lang_items.fn_once_trait() { | |
512 | Some((lang_items.async_fn_once_trait()?, self.allow_async_fn_traits.clone())) | |
513 | } else { | |
514 | None | |
515 | } | |
516 | } | |
dfeec247 | 517 | } |