use crate::ImplTraitPosition;
+use super::ResolverAstLoweringExt;
use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
use super::{ImplTraitContext, LoweringContext, ParamMode};
use tracing::debug;
impl<'a, 'hir> LoweringContext<'a, 'hir> {
- crate fn lower_qpath(
+ #[instrument(level = "trace", skip(self))]
+ pub(crate) fn lower_qpath(
&mut self,
id: NodeId,
qself: &Option<QSelf>,
p: &Path,
param_mode: ParamMode,
- mut itctx: ImplTraitContext<'_, 'hir>,
+ itctx: ImplTraitContext,
) -> hir::QPath<'hir> {
- debug!("lower_qpath(id: {:?}, qself: {:?}, p: {:?})", id, qself, p);
let qself_position = qself.as_ref().map(|q| q.position);
- let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow()));
+ let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
let partial_res =
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
segment,
param_mode,
parenthesized_generic_args,
- itctx.reborrow(),
+ itctx,
)
},
)),
segment,
param_mode,
ParenthesizedGenericArgs::Err,
- itctx.reborrow(),
+ itctx,
));
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
);
}
- crate fn lower_path_extra(
+ pub(crate) fn lower_path_extra(
&mut self,
res: Res,
p: &Path,
})
}
- crate fn lower_path(
+ pub(crate) fn lower_path(
&mut self,
id: NodeId,
p: &Path,
self.lower_path_extra(res, p, param_mode)
}
- crate fn lower_path_segment(
+ pub(crate) fn lower_path_segment(
&mut self,
path_span: Span,
segment: &PathSegment,
param_mode: ParamMode,
parenthesized_generic_args: ParenthesizedGenericArgs,
- itctx: ImplTraitContext<'_, 'hir>,
+ itctx: ImplTraitContext,
) -> hir::PathSegment<'hir> {
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
}
GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args {
- ParenthesizedGenericArgs::Ok => {
- self.lower_parenthesized_parameter_data(segment.id, data)
- }
+ ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
ParenthesizedGenericArgs::Err => {
let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
err.span_label(data.span, "only `Fn` traits may use parentheses");
- if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
- // Do not suggest going from `Trait()` to `Trait<>`
- if !data.inputs.is_empty() {
- // Suggest replacing `(` and `)` with `<` and `>`
- // The snippet may be missing the closing `)`, skip that case
- if snippet.ends_with(')') {
- if let Some(split) = snippet.find('(') {
- let trait_name = &snippet[0..split];
- let args = &snippet[split + 1..snippet.len() - 1];
- err.span_suggestion(
- data.span,
- "use angle brackets instead",
- format!("{}<{}>", trait_name, args),
- Applicability::MaybeIncorrect,
- );
- }
- }
- }
- };
+ // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
+ if !data.inputs.is_empty() {
+ // Start of the span to the 1st character of 1st argument
+ let open_param = data.inputs_span.shrink_to_lo().to(data
+ .inputs
+ .first()
+ .unwrap()
+ .span
+ .shrink_to_lo());
+ // Last character position of last argument to the end of the span
+ let close_param = data
+ .inputs
+ .last()
+ .unwrap()
+ .span
+ .shrink_to_hi()
+ .to(data.inputs_span.shrink_to_hi());
+ err.multipart_suggestion(
+ &format!("use angle brackets instead",),
+ vec![
+ (open_param, String::from("<")),
+ (close_param, String::from(">")),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
err.emit();
(
self.lower_angle_bracketed_parameter_data(
&mut self,
data: &AngleBracketedArgs,
param_mode: ParamMode,
- mut itctx: ImplTraitContext<'_, 'hir>,
+ itctx: ImplTraitContext,
) -> (GenericArgsCtor<'hir>, bool) {
let has_non_lt_args = data.args.iter().any(|arg| match arg {
AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_))
.args
.iter()
.filter_map(|arg| match arg {
- AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx.reborrow())),
+ AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx)),
AngleBracketedArg::Constraint(_) => None,
})
.collect();
let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
- AngleBracketedArg::Constraint(c) => {
- Some(self.lower_assoc_ty_constraint(c, itctx.reborrow()))
- }
+ AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)),
AngleBracketedArg::Arg(_) => None,
}));
let ctor = GenericArgsCtor { args, bindings, parenthesized: false, span: data.span };
fn lower_parenthesized_parameter_data(
&mut self,
- id: NodeId,
data: &ParenthesizedArgs,
) -> (GenericArgsCtor<'hir>, bool) {
// Switch to `PassThrough` mode for anonymous lifetimes; this
// a hidden lifetime parameter. This is needed for backwards
// compatibility, even in contexts like an impl header where
// we generally don't permit such things (see #51008).
- self.with_lifetime_binder(id, |this| {
- let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
- let inputs = this.arena.alloc_from_iter(inputs.iter().map(|ty| {
- this.lower_ty_direct(
- ty,
- ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam),
- )
- }));
- let output_ty = match output {
- FnRetTy::Ty(ty) => this
- .lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)),
- FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(*span, &[])),
- };
- let args = smallvec![GenericArg::Type(this.ty_tup(*inputs_span, inputs))];
- let binding = this.output_ty_binding(output_ty.span, output_ty);
- (
- GenericArgsCtor {
- args,
- bindings: arena_vec![this; binding],
- parenthesized: true,
- span: data.inputs_span,
- },
- false,
- )
- })
+ let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
+ let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| {
+ self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
+ }));
+ let output_ty = match output {
+ FnRetTy::Ty(ty) => {
+ self.lower_ty(&ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
+ }
+ FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
+ };
+ let args = smallvec![GenericArg::Type(self.ty_tup(*inputs_span, inputs))];
+ let binding = self.output_ty_binding(output_ty.span, output_ty);
+ (
+ GenericArgsCtor {
+ args,
+ bindings: arena_vec![self; binding],
+ parenthesized: true,
+ span: data.inputs_span,
+ },
+ false,
+ )
}
/// An associated type binding `Output = $ty`.
- crate fn output_ty_binding(
+ pub(crate) fn output_ty_binding(
&mut self,
span: Span,
ty: &'hir hir::Ty<'hir>,