Skip to content

Clean up errors in typeck and resolve #74005

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 11, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -942,17 +942,6 @@ impl<'a> Resolver<'a> {
Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
Some(suggestion) => suggestion,
};
let msg = format!(
"{} {} with a similar name exists",
suggestion.res.article(),
suggestion.res.descr()
);
err.span_suggestion(
span,
&msg,
suggestion.candidate.to_string(),
Applicability::MaybeIncorrect,
);
let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate {
LOCAL_CRATE => self.opt_span(def_id),
_ => Some(
@@ -961,16 +950,48 @@ impl<'a> Resolver<'a> {
.guess_head_span(self.cstore().get_span_untracked(def_id, self.session)),
),
});
if let Some(span) = def_span {
if let Some(def_span) = def_span {
if span.overlaps(def_span) {
// Don't suggest typo suggestion for itself like in the followoing:
// error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
// --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
// |
// LL | struct X {}
// | ----------- `X` defined here
// LL |
// LL | const Y: X = X("ö");
// | -------------^^^^^^- similarly named constant `Y` defined here
// |
// help: use struct literal syntax instead
// |
// LL | const Y: X = X {};
// | ^^^^
// help: a constant with a similar name exists
// |
// LL | const Y: X = Y("ö");
// | ^
return false;
}
err.span_label(
self.session.source_map().guess_head_span(span),
self.session.source_map().guess_head_span(def_span),
&format!(
"similarly named {} `{}` defined here",
suggestion.res.descr(),
suggestion.candidate.as_str(),
),
);
}
let msg = format!(
"{} {} with a similar name exists",
suggestion.res.article(),
suggestion.res.descr()
);
err.span_suggestion(
span,
&msg,
suggestion.candidate.to_string(),
Applicability::MaybeIncorrect,
);
true
}

42 changes: 31 additions & 11 deletions src/librustc_resolve/late/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}
use rustc_hir as hir;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::PrimTy;
use rustc_session::config::nightly_options;
use rustc_span::hygiene::MacroKind;
@@ -88,6 +88,18 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str
}

impl<'a> LateResolutionVisitor<'a, '_, '_> {
fn def_span(&self, def_id: DefId) -> Option<Span> {
match def_id.krate {
LOCAL_CRATE => self.r.opt_span(def_id),
_ => Some(
self.r
.session
.source_map()
.guess_head_span(self.r.cstore().get_span_untracked(def_id, self.r.session)),
),
}
}

/// Handles error reporting for `smart_resolve_path_fragment` function.
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
pub(crate) fn smart_resolve_report_errors(
@@ -339,8 +351,6 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {

// Try Levenshtein algorithm.
let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected, span);
let levenshtein_worked = self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);

// Try context-dependent help if relaxed lookup didn't work.
if let Some(res) = res {
if self.smart_resolve_context_dependent_help(
@@ -351,14 +361,18 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
&path_str,
&fallback_label,
) {
// We do this to avoid losing a secondary span when we override the main error span.
self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);
return (err, candidates);
}
}

// Fallback label.
if !levenshtein_worked {
if !self.type_ascription_suggestion(&mut err, base_span)
&& !self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span)
{
// Fallback label.
err.span_label(base_span, fallback_label);
self.type_ascription_suggestion(&mut err, base_span);

match self.diagnostic_metadata.current_let_binding {
Some((pat_sp, Some(ty_sp), None)) if ty_sp.contains(base_span) && could_be_expr => {
err.span_suggestion_short(
@@ -518,6 +532,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
}),
) if followed_by_brace => {
if let Some(sp) = closing_brace {
err.span_label(span, fallback_label);
err.multipart_suggestion(
"surround the struct literal with parentheses",
vec![
@@ -550,7 +565,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
}
_ => span,
};
if let Some(span) = self.r.opt_span(def_id) {
if let Some(span) = self.def_span(def_id) {
err.span_label(span, &format!("`{}` defined here", path_str));
}
let (tail, descr, applicability) = match source {
@@ -581,12 +596,15 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
applicability,
);
}
_ => {}
_ => {
err.span_label(span, fallback_label);
}
}
};

match (res, source) {
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
err.span_label(span, fallback_label);
err.span_suggestion_verbose(
span.shrink_to_hi(),
"use `!` to invoke the macro",
@@ -602,7 +620,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
if nightly_options::is_nightly_build() {
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
`type` alias";
if let Some(span) = self.r.opt_span(def_id) {
if let Some(span) = self.def_span(def_id) {
err.span_help(span, msg);
} else {
err.help(msg);
@@ -680,7 +698,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
bad_struct_syntax_suggestion(def_id);
}
(Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => {
if let Some(span) = self.r.opt_span(def_id) {
if let Some(span) = self.def_span(def_id) {
err.span_label(span, &format!("`{}` defined here", path_str));
}
err.span_label(span, format!("did you mean `{}( /* fields */ )`?", path_str));
@@ -869,7 +887,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
start.to(sm.next_point(start))
}

fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) {
fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) -> bool {
let sm = self.r.session.source_map();
let base_snippet = sm.span_to_snippet(base_span);
if let Some(&sp) = self.diagnostic_metadata.current_type_ascription.last() {
@@ -939,9 +957,11 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
"expecting a type here because of type ascription",
);
}
return show_label;
}
}
}
false
}

fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
Original file line number Diff line number Diff line change
@@ -2,10 +2,7 @@ error[E0573]: expected type, found const parameter `C`
--> $DIR/struct-with-invalid-const-param.rs:4:23
|
LL | struct S<const C: u8>(C);
| ----------------------^--
| | |
| | help: a struct with a similar name exists: `S`
| similarly named struct `S` defined here
| ^ not a type

warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/struct-with-invalid-const-param.rs:1:12
44 changes: 29 additions & 15 deletions src/test/ui/empty/empty-struct-braces-expr.stderr
Original file line number Diff line number Diff line change
@@ -12,14 +12,14 @@ LL | let e1 = Empty1;
LL | pub struct XEmpty2;
| ------------------- similarly named unit struct `XEmpty2` defined here
|
help: a unit struct with a similar name exists
|
LL | let e1 = XEmpty2;
| ^^^^^^^
help: use struct literal syntax instead
|
LL | let e1 = Empty1 {};
| ^^^^^^^^^
help: a unit struct with a similar name exists
|
LL | let e1 = XEmpty2;
| ^^^^^^^

error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
--> $DIR/empty-struct-braces-expr.rs:16:14
@@ -29,15 +29,20 @@ LL | struct Empty1 {}
...
LL | let e1 = Empty1();
| ^^^^^^^^
|
::: $DIR/auxiliary/empty-struct.rs:2:1
|
help: a unit struct with a similar name exists
LL | pub struct XEmpty2;
| ------------------- similarly named unit struct `XEmpty2` defined here
|
LL | let e1 = XEmpty2();
| ^^^^^^^
help: use struct literal syntax instead
|
LL | let e1 = Empty1 {};
| ^^^^^^^^^
help: a unit struct with a similar name exists
|
LL | let e1 = XEmpty2();
| ^^^^^^^

error[E0423]: expected value, found struct variant `E::Empty3`
--> $DIR/empty-struct-braces-expr.rs:18:14
@@ -63,34 +68,43 @@ error[E0423]: expected value, found struct `XEmpty1`
LL | let xe1 = XEmpty1;
| ^^^^^^^
|
::: $DIR/auxiliary/empty-struct.rs:2:1
::: $DIR/auxiliary/empty-struct.rs:1:1
|
LL | pub struct XEmpty1 {}
| ------------------ `XEmpty1` defined here
LL | pub struct XEmpty2;
| ------------------- similarly named unit struct `XEmpty2` defined here
|
help: a unit struct with a similar name exists
|
LL | let xe1 = XEmpty2;
| ^^^^^^^
help: use struct literal syntax instead
|
LL | let xe1 = XEmpty1 {};
| ^^^^^^^^^^
help: a unit struct with a similar name exists
|
LL | let xe1 = XEmpty2;
| ^^^^^^^

error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
--> $DIR/empty-struct-braces-expr.rs:23:15
|
LL | let xe1 = XEmpty1();
| ^^^^^^^^^
|
::: $DIR/auxiliary/empty-struct.rs:1:1
|
help: a unit struct with a similar name exists
LL | pub struct XEmpty1 {}
| ------------------ `XEmpty1` defined here
LL | pub struct XEmpty2;
| ------------------- similarly named unit struct `XEmpty2` defined here
|
LL | let xe1 = XEmpty2();
| ^^^^^^^
help: use struct literal syntax instead
|
LL | let xe1 = XEmpty1 {};
| ^^^^^^^^^^
help: a unit struct with a similar name exists
|
LL | let xe1 = XEmpty2();
| ^^^^^^^

error[E0599]: no variant or associated item named `Empty3` found for enum `empty_struct::XE` in the current scope
--> $DIR/empty-struct-braces-expr.rs:25:19
12 changes: 7 additions & 5 deletions src/test/ui/empty/empty-struct-braces-pat-1.stderr
Original file line number Diff line number Diff line change
@@ -13,19 +13,21 @@ error[E0532]: expected unit struct, unit variant or constant, found struct varia
LL | XE::XEmpty3 => ()
| ^^^^^^^^^^^
|
::: $DIR/auxiliary/empty-struct.rs:7:5
::: $DIR/auxiliary/empty-struct.rs:6:5
|
LL | XEmpty3 {},
| ------- `XE::XEmpty3` defined here
LL | XEmpty4,
| ------- similarly named unit variant `XEmpty4` defined here
|
help: a unit variant with a similar name exists
|
LL | XE::XEmpty4 => ()
| ^^^^^^^
help: use struct pattern syntax instead
|
LL | XE::XEmpty3 { /* fields */ } => ()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: a unit variant with a similar name exists
|
LL | XE::XEmpty4 => ()
| ^^^^^^^

error: aborting due to 2 previous errors

Loading