Rollup merge of #100367 - fmease:fix-100365, r=compiler-errors

Suggest the path separator when a dot is used on a trait

Fixes #100365.

`@rustbot` label A-diagnostics
r? diagnostics
This commit is contained in:
Michael Goulet 2022-08-13 21:06:49 -07:00 committed by GitHub
commit e248c7f9ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 394 additions and 53 deletions

View file

@ -985,27 +985,45 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let ns = source.namespace();
let is_expected = &|res| source.is_expected(res);
let path_sep = |err: &mut Diagnostic, expr: &Expr| match expr.kind {
ExprKind::Field(_, ident) => {
let path_sep = |err: &mut Diagnostic, expr: &Expr, kind: DefKind| {
const MESSAGE: &str = "use the path separator to refer to an item";
let (lhs_span, rhs_span) = match &expr.kind {
ExprKind::Field(base, ident) => (base.span, ident.span),
ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
_ => return false,
};
if lhs_span.eq_ctxt(rhs_span) {
err.span_suggestion(
expr.span,
"use the path separator to refer to an item",
format!("{}::{}", path_str, ident),
lhs_span.between(rhs_span),
MESSAGE,
"::",
Applicability::MaybeIncorrect,
);
true
}
ExprKind::MethodCall(ref segment, ..) => {
let span = expr.span.with_hi(segment.ident.span.hi());
err.span_suggestion(
span,
"use the path separator to refer to an item",
format!("{}::{}", path_str, segment.ident),
} else if kind == DefKind::Struct
&& let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
&& let Ok(snippet) = self.r.session.source_map().span_to_snippet(lhs_source_span)
{
// The LHS is a type that originates from a macro call.
// We have to add angle brackets around it.
err.span_suggestion_verbose(
lhs_source_span.until(rhs_span),
MESSAGE,
format!("<{snippet}>::"),
Applicability::MaybeIncorrect,
);
true
} else {
// Either we were unable to obtain the source span / the snippet or
// the LHS originates from a macro call and it is not a type and thus
// there is no way to replace `.` with `::` and still somehow suggest
// valid Rust code.
false
}
_ => false,
};
let find_span = |source: &PathSource<'_>, err: &mut Diagnostic| {
@ -1027,7 +1045,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
match source {
PathSource::Expr(Some(
parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
)) if path_sep(err, &parent) => {}
)) if path_sep(err, &parent, DefKind::Struct) => {}
PathSource::Expr(
None
| Some(Expr {
@ -1143,8 +1161,11 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
}
(Res::Def(DefKind::Mod, _), PathSource::Expr(Some(parent))) => {
if !path_sep(err, &parent) {
(
Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
PathSource::Expr(Some(parent)),
) => {
if !path_sep(err, &parent, kind) {
return false;
}
}