1 use crate::ImplTraitPosition
;
3 use super::errors
::{GenericTypeWithParentheses, UseAngleBrackets}
;
4 use super::ResolverAstLoweringExt
;
5 use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}
;
6 use super::{ImplTraitContext, LoweringContext, ParamMode}
;
8 use rustc_ast
::{self as ast, *}
;
10 use rustc_hir
::def
::{DefKind, PartialRes, Res}
;
11 use rustc_hir
::GenericArg
;
12 use rustc_span
::symbol
::{kw, Ident}
;
13 use rustc_span
::{BytePos, Span, DUMMY_SP}
;
15 use smallvec
::smallvec
;
17 impl<'a
, 'hir
> LoweringContext
<'a
, 'hir
> {
18 #[instrument(level = "trace", skip(self))]
19 pub(crate) fn lower_qpath(
22 qself
: &Option
<QSelf
>,
24 param_mode
: ParamMode
,
25 itctx
: &ImplTraitContext
,
26 ) -> hir
::QPath
<'hir
> {
27 let qself_position
= qself
.as_ref().map(|q
| q
.position
);
28 let qself
= qself
.as_ref().map(|q
| self.lower_ty(&q
.ty
, itctx
));
31 self.resolver
.get_partial_res(id
).unwrap_or_else(|| PartialRes
::new(Res
::Err
));
33 let path_span_lo
= p
.span
.shrink_to_lo();
34 let proj_start
= p
.segments
.len() - partial_res
.unresolved_segments();
35 let path
= self.arena
.alloc(hir
::Path
{
36 res
: self.lower_res(partial_res
.base_res()),
37 segments
: self.arena
.alloc_from_iter(p
.segments
[..proj_start
].iter().enumerate().map(
39 let param_mode
= match (qself_position
, param_mode
) {
40 (Some(j
), ParamMode
::Optional
) if i
< j
=> {
41 // This segment is part of the trait path in a
42 // qualified path - one of `a`, `b` or `Trait`
43 // in `<X as a::b::Trait>::T::U::method`.
49 let parenthesized_generic_args
= match partial_res
.base_res() {
50 // `a::b::Trait(Args)`
51 Res
::Def(DefKind
::Trait
, _
) if i
+ 1 == proj_start
=> {
52 ParenthesizedGenericArgs
::Ok
54 // `a::b::Trait(Args)::TraitItem`
55 Res
::Def(DefKind
::AssocFn
, _
)
56 | Res
::Def(DefKind
::AssocConst
, _
)
57 | Res
::Def(DefKind
::AssocTy
, _
)
58 if i
+ 2 == proj_start
=>
60 ParenthesizedGenericArgs
::Ok
62 // Avoid duplicated errors.
63 Res
::Err
=> ParenthesizedGenericArgs
::Ok
,
65 _
=> ParenthesizedGenericArgs
::Err
,
68 self.lower_path_segment(
72 parenthesized_generic_args
,
77 span
: self.lower_span(
78 p
.segments
[..proj_start
]
80 .map_or(path_span_lo
, |segment
| path_span_lo
.to(segment
.span())),
84 // Simple case, either no projections, or only fully-qualified.
85 // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
86 if partial_res
.unresolved_segments() == 0 {
87 return hir
::QPath
::Resolved(qself
, path
);
90 // Create the innermost type that we're projecting from.
91 let mut ty
= if path
.segments
.is_empty() {
92 // If the base path is empty that means there exists a
93 // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
94 qself
.expect("missing QSelf for <T>::...")
96 // Otherwise, the base path is an implicit `Self` type path,
97 // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
98 // `<I as Iterator>::Item::default`.
99 let new_id
= self.next_id();
100 self.arena
.alloc(self.ty_path(new_id
, path
.span
, hir
::QPath
::Resolved(qself
, path
)))
103 // Anything after the base path are associated "extensions",
104 // out of which all but the last one are associated types,
105 // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
106 // * base path is `std::vec::Vec<T>`
107 // * "extensions" are `IntoIter`, `Item` and `clone`
109 // 1. `std::vec::Vec<T>` (created above)
110 // 2. `<std::vec::Vec<T>>::IntoIter`
111 // 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
112 // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
113 for (i
, segment
) in p
.segments
.iter().enumerate().skip(proj_start
) {
114 let hir_segment
= self.arena
.alloc(self.lower_path_segment(
118 ParenthesizedGenericArgs
::Err
,
121 let qpath
= hir
::QPath
::TypeRelative(ty
, hir_segment
);
123 // It's finished, return the extension of the right node type.
124 if i
== p
.segments
.len() - 1 {
128 // Wrap the associated extension in another type node.
129 let new_id
= self.next_id();
130 ty
= self.arena
.alloc(self.ty_path(new_id
, path_span_lo
.to(segment
.span()), qpath
));
133 // We should've returned in the for loop above.
135 self.diagnostic().span_bug(
138 "lower_qpath: no final extension segment in {}..{}",
145 pub(crate) fn lower_path_extra(
149 param_mode
: ParamMode
,
150 ) -> &'hir hir
::Path
<'hir
> {
151 self.arena
.alloc(hir
::Path
{
153 segments
: self.arena
.alloc_from_iter(p
.segments
.iter().map(|segment
| {
154 self.lower_path_segment(
158 ParenthesizedGenericArgs
::Err
,
159 &ImplTraitContext
::Disallowed(ImplTraitPosition
::Path
),
162 span
: self.lower_span(p
.span
),
166 pub(crate) fn lower_path(
170 param_mode
: ParamMode
,
171 ) -> &'hir hir
::Path
<'hir
> {
172 let res
= self.expect_full_res(id
);
173 let res
= self.lower_res(res
);
174 self.lower_path_extra(res
, p
, param_mode
)
177 pub(crate) fn lower_path_segment(
180 segment
: &PathSegment
,
181 param_mode
: ParamMode
,
182 parenthesized_generic_args
: ParenthesizedGenericArgs
,
183 itctx
: &ImplTraitContext
,
184 ) -> hir
::PathSegment
<'hir
> {
185 debug
!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span
, segment
,);
186 let (mut generic_args
, infer_args
) = if let Some(ref generic_args
) = segment
.args
{
187 match **generic_args
{
188 GenericArgs
::AngleBracketed(ref data
) => {
189 self.lower_angle_bracketed_parameter_data(data
, param_mode
, itctx
)
191 GenericArgs
::Parenthesized(ref data
) => match parenthesized_generic_args
{
192 ParenthesizedGenericArgs
::Ok
=> self.lower_parenthesized_parameter_data(data
),
193 ParenthesizedGenericArgs
::Err
=> {
194 // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
195 let sub
= if !data
.inputs
.is_empty() {
196 // Start of the span to the 1st character of 1st argument
197 let open_param
= data
.inputs_span
.shrink_to_lo().to(data
203 // Last character position of last argument to the end of the span
204 let close_param
= data
210 .to(data
.inputs_span
.shrink_to_hi());
212 Some(UseAngleBrackets { open_param, close_param }
)
216 self.tcx
.sess
.emit_err(GenericTypeWithParentheses { span: data.span, sub }
);
218 self.lower_angle_bracketed_parameter_data(
219 &data
.as_angle_bracketed_args(),
232 args
: Default
::default(),
234 parenthesized
: false,
235 span
: path_span
.shrink_to_hi(),
237 param_mode
== ParamMode
::Optional
,
242 generic_args
.args
.iter().any(|arg
| matches
!(arg
, GenericArg
::Lifetime(_
)));
243 if !generic_args
.parenthesized
&& !has_lifetimes
{
244 self.maybe_insert_elided_lifetimes_in_path(
252 let res
= self.expect_full_res(segment
.id
);
253 let hir_id
= self.lower_node_id(segment
.id
);
255 "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
256 segment
.ident
, segment
.id
, hir_id
,
260 ident
: self.lower_ident(segment
.ident
),
262 res
: self.lower_res(res
),
264 args
: if generic_args
.is_empty() && generic_args
.span
.is_empty() {
267 Some(generic_args
.into_generic_args(self))
272 fn maybe_insert_elided_lifetimes_in_path(
276 segment_ident_span
: Span
,
277 generic_args
: &mut GenericArgsCtor
<'hir
>,
279 let (start
, end
) = match self.resolver
.get_lifetime_res(segment_id
) {
280 Some(LifetimeRes
::ElidedAnchor { start, end }
) => (start
, end
),
284 let expected_lifetimes
= end
.as_usize() - start
.as_usize();
285 debug
!(expected_lifetimes
);
287 // Note: these spans are used for diagnostics when they can't be inferred.
288 // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
289 let elided_lifetime_span
= if generic_args
.span
.is_empty() {
290 // If there are no brackets, use the identifier span.
291 // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
292 // originating from macros, since the segment's span might be from a macro arg.
293 segment_ident_span
.find_ancestor_inside(path_span
).unwrap_or(path_span
)
294 } else if generic_args
.is_empty() {
295 // If there are brackets, but not generic arguments, then use the opening bracket
296 generic_args
.span
.with_hi(generic_args
.span
.lo() + BytePos(1))
298 // Else use an empty span right after the opening bracket.
299 generic_args
.span
.with_lo(generic_args
.span
.lo() + BytePos(1)).shrink_to_lo()
302 generic_args
.args
.insert_many(
304 (start
.as_u32()..end
.as_u32()).map(|i
| {
305 let id
= NodeId
::from_u32(i
);
306 let l
= self.lower_lifetime(&Lifetime
{
308 ident
: Ident
::new(kw
::UnderscoreLifetime
, elided_lifetime_span
),
310 GenericArg
::Lifetime(l
)
315 pub(crate) fn lower_angle_bracketed_parameter_data(
317 data
: &AngleBracketedArgs
,
318 param_mode
: ParamMode
,
319 itctx
: &ImplTraitContext
,
320 ) -> (GenericArgsCtor
<'hir
>, bool
) {
321 let has_non_lt_args
= data
.args
.iter().any(|arg
| match arg
{
322 AngleBracketedArg
::Arg(ast
::GenericArg
::Lifetime(_
))
323 | AngleBracketedArg
::Constraint(_
) => false,
324 AngleBracketedArg
::Arg(ast
::GenericArg
::Type(_
) | ast
::GenericArg
::Const(_
)) => true,
329 .filter_map(|arg
| match arg
{
330 AngleBracketedArg
::Arg(arg
) => Some(self.lower_generic_arg(arg
, itctx
)),
331 AngleBracketedArg
::Constraint(_
) => None
,
334 let bindings
= self.arena
.alloc_from_iter(data
.args
.iter().filter_map(|arg
| match arg
{
335 AngleBracketedArg
::Constraint(c
) => Some(self.lower_assoc_ty_constraint(c
, itctx
)),
336 AngleBracketedArg
::Arg(_
) => None
,
338 let ctor
= GenericArgsCtor { args, bindings, parenthesized: false, span: data.span }
;
339 (ctor
, !has_non_lt_args
&& param_mode
== ParamMode
::Optional
)
342 fn lower_parenthesized_parameter_data(
344 data
: &ParenthesizedArgs
,
345 ) -> (GenericArgsCtor
<'hir
>, bool
) {
346 // Switch to `PassThrough` mode for anonymous lifetimes; this
347 // means that we permit things like `&Ref<T>`, where `Ref` has
348 // a hidden lifetime parameter. This is needed for backwards
349 // compatibility, even in contexts like an impl header where
350 // we generally don't permit such things (see #51008).
351 let ParenthesizedArgs { span, inputs, inputs_span, output }
= data
;
352 let inputs
= self.arena
.alloc_from_iter(inputs
.iter().map(|ty
| {
353 self.lower_ty_direct(ty
, &ImplTraitContext
::Disallowed(ImplTraitPosition
::FnTraitParam
))
355 let output_ty
= match output
{
357 self.lower_ty(&ty
, &ImplTraitContext
::Disallowed(ImplTraitPosition
::FnTraitReturn
))
359 FnRetTy
::Default(_
) => self.arena
.alloc(self.ty_tup(*span
, &[])),
361 let args
= smallvec
![GenericArg
::Type(self.arena
.alloc(self.ty_tup(*inputs_span
, inputs
)))];
362 let binding
= self.output_ty_binding(output_ty
.span
, output_ty
);
366 bindings
: arena_vec
![self; binding
],
368 span
: data
.inputs_span
,
374 /// An associated type binding `Output = $ty`.
375 pub(crate) fn output_ty_binding(
378 ty
: &'hir hir
::Ty
<'hir
>,
379 ) -> hir
::TypeBinding
<'hir
> {
380 let ident
= Ident
::with_dummy_span(hir
::FN_OUTPUT_NAME
);
381 let kind
= hir
::TypeBindingKind
::Equality { term: ty.into() }
;
382 let args
= arena_vec
![self;];
383 let bindings
= arena_vec
![self;];
384 let gen_args
= self.arena
.alloc(hir
::GenericArgs
{
387 parenthesized
: false,
391 hir_id
: self.next_id(),
393 span
: self.lower_span(span
),