1 use crate::ImplTraitPosition
;
3 use super::ResolverAstLoweringExt
;
4 use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}
;
5 use super::{ImplTraitContext, LoweringContext, ParamMode}
;
7 use rustc_ast
::{self as ast, *}
;
8 use rustc_errors
::{struct_span_err, Applicability}
;
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
;
18 impl<'a
, 'hir
> LoweringContext
<'a
, 'hir
> {
19 #[instrument(level = "trace", skip(self))]
20 pub(crate) fn lower_qpath(
23 qself
: &Option
<QSelf
>,
25 param_mode
: ParamMode
,
26 itctx
: ImplTraitContext
,
27 ) -> hir
::QPath
<'hir
> {
28 let qself_position
= qself
.as_ref().map(|q
| q
.position
);
29 let qself
= qself
.as_ref().map(|q
| self.lower_ty(&q
.ty
, itctx
));
32 self.resolver
.get_partial_res(id
).unwrap_or_else(|| PartialRes
::new(Res
::Err
));
34 let path_span_lo
= p
.span
.shrink_to_lo();
35 let proj_start
= p
.segments
.len() - partial_res
.unresolved_segments();
36 let path
= self.arena
.alloc(hir
::Path
{
37 res
: self.lower_res(partial_res
.base_res()),
38 segments
: self.arena
.alloc_from_iter(p
.segments
[..proj_start
].iter().enumerate().map(
40 let param_mode
= match (qself_position
, param_mode
) {
41 (Some(j
), ParamMode
::Optional
) if i
< j
=> {
42 // This segment is part of the trait path in a
43 // qualified path - one of `a`, `b` or `Trait`
44 // in `<X as a::b::Trait>::T::U::method`.
50 let parenthesized_generic_args
= match partial_res
.base_res() {
51 // `a::b::Trait(Args)`
52 Res
::Def(DefKind
::Trait
, _
) if i
+ 1 == proj_start
=> {
53 ParenthesizedGenericArgs
::Ok
55 // `a::b::Trait(Args)::TraitItem`
56 Res
::Def(DefKind
::AssocFn
, _
)
57 | Res
::Def(DefKind
::AssocConst
, _
)
58 | Res
::Def(DefKind
::AssocTy
, _
)
59 if i
+ 2 == proj_start
=>
61 ParenthesizedGenericArgs
::Ok
63 // Avoid duplicated errors.
64 Res
::Err
=> ParenthesizedGenericArgs
::Ok
,
66 _
=> ParenthesizedGenericArgs
::Err
,
69 self.lower_path_segment(
73 parenthesized_generic_args
,
78 span
: self.lower_span(
79 p
.segments
[..proj_start
]
81 .map_or(path_span_lo
, |segment
| path_span_lo
.to(segment
.span())),
85 // Simple case, either no projections, or only fully-qualified.
86 // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
87 if partial_res
.unresolved_segments() == 0 {
88 return hir
::QPath
::Resolved(qself
, path
);
91 // Create the innermost type that we're projecting from.
92 let mut ty
= if path
.segments
.is_empty() {
93 // If the base path is empty that means there exists a
94 // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
95 qself
.expect("missing QSelf for <T>::...")
97 // Otherwise, the base path is an implicit `Self` type path,
98 // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
99 // `<I as Iterator>::Item::default`.
100 let new_id
= self.next_id();
101 self.arena
.alloc(self.ty_path(new_id
, path
.span
, hir
::QPath
::Resolved(qself
, path
)))
104 // Anything after the base path are associated "extensions",
105 // out of which all but the last one are associated types,
106 // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
107 // * base path is `std::vec::Vec<T>`
108 // * "extensions" are `IntoIter`, `Item` and `clone`
110 // 1. `std::vec::Vec<T>` (created above)
111 // 2. `<std::vec::Vec<T>>::IntoIter`
112 // 3. `<<std::vec::Vec<T>>::IntoIter>::Item`
113 // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
114 for (i
, segment
) in p
.segments
.iter().enumerate().skip(proj_start
) {
115 let hir_segment
= self.arena
.alloc(self.lower_path_segment(
119 ParenthesizedGenericArgs
::Err
,
122 let qpath
= hir
::QPath
::TypeRelative(ty
, hir_segment
);
124 // It's finished, return the extension of the right node type.
125 if i
== p
.segments
.len() - 1 {
129 // Wrap the associated extension in another type node.
130 let new_id
= self.next_id();
131 ty
= self.arena
.alloc(self.ty_path(new_id
, path_span_lo
.to(segment
.span()), qpath
));
134 // We should've returned in the for loop above.
136 self.sess
.diagnostic().span_bug(
139 "lower_qpath: no final extension segment in {}..{}",
146 pub(crate) fn lower_path_extra(
150 param_mode
: ParamMode
,
151 ) -> &'hir hir
::Path
<'hir
> {
152 self.arena
.alloc(hir
::Path
{
154 segments
: self.arena
.alloc_from_iter(p
.segments
.iter().map(|segment
| {
155 self.lower_path_segment(
159 ParenthesizedGenericArgs
::Err
,
160 ImplTraitContext
::Disallowed(ImplTraitPosition
::Path
),
163 span
: self.lower_span(p
.span
),
167 pub(crate) fn lower_path(
171 param_mode
: ParamMode
,
172 ) -> &'hir hir
::Path
<'hir
> {
173 let res
= self.expect_full_res(id
);
174 let res
= self.lower_res(res
);
175 self.lower_path_extra(res
, p
, param_mode
)
178 pub(crate) fn lower_path_segment(
181 segment
: &PathSegment
,
182 param_mode
: ParamMode
,
183 parenthesized_generic_args
: ParenthesizedGenericArgs
,
184 itctx
: ImplTraitContext
,
185 ) -> hir
::PathSegment
<'hir
> {
186 debug
!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span
, segment
,);
187 let (mut generic_args
, infer_args
) = if let Some(ref generic_args
) = segment
.args
{
188 let msg
= "parenthesized type parameters may only be used with a `Fn` trait";
189 match **generic_args
{
190 GenericArgs
::AngleBracketed(ref data
) => {
191 self.lower_angle_bracketed_parameter_data(data
, param_mode
, itctx
)
193 GenericArgs
::Parenthesized(ref data
) => match parenthesized_generic_args
{
194 ParenthesizedGenericArgs
::Ok
=> self.lower_parenthesized_parameter_data(data
),
195 ParenthesizedGenericArgs
::Err
=> {
196 let mut err
= struct_span_err
!(self.sess
, data
.span
, E0214
, "{}", msg
);
197 err
.span_label(data
.span
, "only `Fn` traits may use parentheses");
198 // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
199 if !data
.inputs
.is_empty() {
200 // Start of the span to the 1st character of 1st argument
201 let open_param
= data
.inputs_span
.shrink_to_lo().to(data
207 // Last character position of last argument to the end of the span
208 let close_param
= data
214 .to(data
.inputs_span
.shrink_to_hi());
215 err
.multipart_suggestion(
216 &format
!("use angle brackets instead",),
218 (open_param
, String
::from("<")),
219 (close_param
, String
::from(">")),
221 Applicability
::MaybeIncorrect
,
226 self.lower_angle_bracketed_parameter_data(
227 &data
.as_angle_bracketed_args(),
240 args
: Default
::default(),
242 parenthesized
: false,
243 span
: path_span
.shrink_to_hi(),
245 param_mode
== ParamMode
::Optional
,
250 generic_args
.args
.iter().any(|arg
| matches
!(arg
, GenericArg
::Lifetime(_
)));
251 if !generic_args
.parenthesized
&& !has_lifetimes
{
252 self.maybe_insert_elided_lifetimes_in_path(
260 let res
= self.expect_full_res(segment
.id
);
261 let id
= self.lower_node_id(segment
.id
);
263 "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
264 segment
.ident
, segment
.id
, id
,
268 ident
: self.lower_ident(segment
.ident
),
270 res
: Some(self.lower_res(res
)),
272 args
: if generic_args
.is_empty() && generic_args
.span
.is_empty() {
275 Some(generic_args
.into_generic_args(self))
280 fn maybe_insert_elided_lifetimes_in_path(
284 segment_ident_span
: Span
,
285 generic_args
: &mut GenericArgsCtor
<'hir
>,
287 let (start
, end
) = match self.resolver
.get_lifetime_res(segment_id
) {
288 Some(LifetimeRes
::ElidedAnchor { start, end }
) => (start
, end
),
292 let expected_lifetimes
= end
.as_usize() - start
.as_usize();
293 debug
!(expected_lifetimes
);
295 // Note: these spans are used for diagnostics when they can't be inferred.
296 // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
297 let elided_lifetime_span
= if generic_args
.span
.is_empty() {
298 // If there are no brackets, use the identifier span.
299 // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
300 // originating from macros, since the segment's span might be from a macro arg.
301 segment_ident_span
.find_ancestor_inside(path_span
).unwrap_or(path_span
)
302 } else if generic_args
.is_empty() {
303 // If there are brackets, but not generic arguments, then use the opening bracket
304 generic_args
.span
.with_hi(generic_args
.span
.lo() + BytePos(1))
306 // Else use an empty span right after the opening bracket.
307 generic_args
.span
.with_lo(generic_args
.span
.lo() + BytePos(1)).shrink_to_lo()
310 generic_args
.args
.insert_many(
312 (start
.as_u32()..end
.as_u32()).map(|i
| {
313 let id
= NodeId
::from_u32(i
);
314 let l
= self.lower_lifetime(&Lifetime
{
316 ident
: Ident
::new(kw
::UnderscoreLifetime
, elided_lifetime_span
),
318 GenericArg
::Lifetime(l
)
323 pub(crate) fn lower_angle_bracketed_parameter_data(
325 data
: &AngleBracketedArgs
,
326 param_mode
: ParamMode
,
327 itctx
: ImplTraitContext
,
328 ) -> (GenericArgsCtor
<'hir
>, bool
) {
329 let has_non_lt_args
= data
.args
.iter().any(|arg
| match arg
{
330 AngleBracketedArg
::Arg(ast
::GenericArg
::Lifetime(_
))
331 | AngleBracketedArg
::Constraint(_
) => false,
332 AngleBracketedArg
::Arg(ast
::GenericArg
::Type(_
) | ast
::GenericArg
::Const(_
)) => true,
337 .filter_map(|arg
| match arg
{
338 AngleBracketedArg
::Arg(arg
) => Some(self.lower_generic_arg(arg
, itctx
)),
339 AngleBracketedArg
::Constraint(_
) => None
,
342 let bindings
= self.arena
.alloc_from_iter(data
.args
.iter().filter_map(|arg
| match arg
{
343 AngleBracketedArg
::Constraint(c
) => Some(self.lower_assoc_ty_constraint(c
, itctx
)),
344 AngleBracketedArg
::Arg(_
) => None
,
346 let ctor
= GenericArgsCtor { args, bindings, parenthesized: false, span: data.span }
;
347 (ctor
, !has_non_lt_args
&& param_mode
== ParamMode
::Optional
)
350 fn lower_parenthesized_parameter_data(
352 data
: &ParenthesizedArgs
,
353 ) -> (GenericArgsCtor
<'hir
>, bool
) {
354 // Switch to `PassThrough` mode for anonymous lifetimes; this
355 // means that we permit things like `&Ref<T>`, where `Ref` has
356 // a hidden lifetime parameter. This is needed for backwards
357 // compatibility, even in contexts like an impl header where
358 // we generally don't permit such things (see #51008).
359 let ParenthesizedArgs { span, inputs, inputs_span, output }
= data
;
360 let inputs
= self.arena
.alloc_from_iter(inputs
.iter().map(|ty
| {
361 self.lower_ty_direct(ty
, ImplTraitContext
::Disallowed(ImplTraitPosition
::FnTraitParam
))
363 let output_ty
= match output
{
365 self.lower_ty(&ty
, ImplTraitContext
::Disallowed(ImplTraitPosition
::FnTraitReturn
))
367 FnRetTy
::Default(_
) => self.arena
.alloc(self.ty_tup(*span
, &[])),
369 let args
= smallvec
![GenericArg
::Type(self.ty_tup(*inputs_span
, inputs
))];
370 let binding
= self.output_ty_binding(output_ty
.span
, output_ty
);
374 bindings
: arena_vec
![self; binding
],
376 span
: data
.inputs_span
,
382 /// An associated type binding `Output = $ty`.
383 pub(crate) fn output_ty_binding(
386 ty
: &'hir hir
::Ty
<'hir
>,
387 ) -> hir
::TypeBinding
<'hir
> {
388 let ident
= Ident
::with_dummy_span(hir
::FN_OUTPUT_NAME
);
389 let kind
= hir
::TypeBindingKind
::Equality { term: ty.into() }
;
390 let args
= arena_vec
![self;];
391 let bindings
= arena_vec
![self;];
392 let gen_args
= self.arena
.alloc(hir
::GenericArgs
{
395 parenthesized
: false,
399 hir_id
: self.next_id(),
401 span
: self.lower_span(span
),