-use crate::utils::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
use if_chain::if_chain;
use rustc_ast::ast::{BindingMode, Lifetime, Mutability, Param, PatKind, Path, TyKind};
use rustc_errors::Applicability;
if let [segment] = &path.segments[..];
if segment.ident.name == kw::SelfUpper;
then {
+ // In case we have a named lifetime, we check if the name comes from expansion.
+ // If it does, at this point we know the rest of the parameter was written by the user,
+ // so let them decide what the name of the lifetime should be.
+ // See #6089 for more details.
+ let mut applicability = Applicability::MachineApplicable;
let self_param = match (binding_mode, mutbl) {
(Mode::Ref(None), Mutability::Mut) => "&mut self".to_string(),
- (Mode::Ref(Some(lifetime)), Mutability::Mut) => format!("&{} mut self", &lifetime.ident.name),
+ (Mode::Ref(Some(lifetime)), Mutability::Mut) => {
+ if in_macro(lifetime.ident.span) {
+ applicability = Applicability::HasPlaceholders;
+ "&'_ mut self".to_string()
+ } else {
+ format!("&{} mut self", &lifetime.ident.name)
+ }
+ },
(Mode::Ref(None), Mutability::Not) => "&self".to_string(),
- (Mode::Ref(Some(lifetime)), Mutability::Not) => format!("&{} self", &lifetime.ident.name),
+ (Mode::Ref(Some(lifetime)), Mutability::Not) => {
+ if in_macro(lifetime.ident.span) {
+ applicability = Applicability::HasPlaceholders;
+ "&'_ self".to_string()
+ } else {
+ format!("&{} self", &lifetime.ident.name)
+ }
+ },
(Mode::Value, Mutability::Mut) => "mut self".to_string(),
(Mode::Value, Mutability::Not) => "self".to_string(),
};
"the type of the `self` parameter does not need to be arbitrary",
"consider to change this parameter to",
self_param,
- Applicability::MachineApplicable,
+ applicability,
)
}
}
impl EarlyLintPass for NeedlessArbitrarySelfType {
fn check_param(&mut self, cx: &EarlyContext<'_>, p: &Param) {
- if !p.is_self() {
+ // Bail out if the parameter it's not a receiver or was not written by the user
+ if !p.is_self() || in_macro(p.span) {
return;
}
match &p.ty.kind {
TyKind::Path(None, path) => {
if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind {
- check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl)
+ check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
}
},
TyKind::Rptr(lifetime, mut_ty) => {
if let TyKind::Path(None, path) = &mut_ty.ty.kind;
if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind;
then {
- check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl)
+ check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
}
}
},