Skip to content

Commit c0472a5

Browse files
committed
Fix E0433 diagnostics ignoring typo suggestions and outputing wrong message
1 parent 1898c34 commit c0472a5

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

compiler/rustc_resolve/src/late.rs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use smallvec::{smallvec, SmallVec};
3131

3232
use rustc_span::source_map::{respan, Spanned};
3333
use std::collections::{hash_map::Entry, BTreeSet};
34-
use std::mem::{replace, take};
34+
use std::mem::{replace, take, swap};
3535

3636
mod diagnostics;
3737

@@ -3334,10 +3334,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
33343334
let (mut err, candidates) =
33353335
this.smart_resolve_report_errors(path, path_span, PathSource::Type, None);
33363336

3337-
if candidates.is_empty() {
3338-
err.cancel();
3339-
return Some(parent_err);
3340-
}
33413337

33423338
// There are two different error messages user might receive at
33433339
// this point:
@@ -3348,37 +3344,62 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
33483344
// latter one - for paths in expression-position.
33493345
//
33503346
// Thus (since we're in expression-position at this point), not to
3351-
// confuse the user, we want to keep the *message* from E0432 (so
3347+
// confuse the user, we want to keep the *message* from E0433 (so
33523348
// `parent_err`), but we want *hints* from E0412 (so `err`).
33533349
//
33543350
// And that's what happens below - we're just mixing both messages
33553351
// into a single one.
33563352
let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node);
33573353

3354+
// overwrite all properties with the parent's error message
33583355
err.message = take(&mut parent_err.message);
33593356
err.code = take(&mut parent_err.code);
3357+
swap(&mut err.span, &mut parent_err.span);
33603358
err.children = take(&mut parent_err.children);
3359+
err.sort_span = parent_err.sort_span;
3360+
err.is_lint = parent_err.is_lint;
3361+
3362+
// merge the parent's suggestions with the typo suggestions
3363+
fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) {
3364+
match res1 {
3365+
Ok(vec1) => match res2 {
3366+
Ok(mut vec2) => { vec1.append(&mut vec2); },
3367+
Err(e) => { *res1 = Err(e) },
3368+
},
3369+
Err(_) => (),
3370+
};
3371+
}
3372+
append_result(&mut err.suggestions, parent_err.suggestions.clone());
33613373

33623374
parent_err.cancel();
33633375

33643376
let def_id = this.parent_scope.module.nearest_parent_mod();
33653377

33663378
if this.should_report_errs() {
3367-
this.r.use_injections.push(UseError {
3368-
err,
3369-
candidates,
3370-
def_id,
3371-
instead: false,
3372-
suggestion: None,
3373-
path: path.into(),
3374-
is_call: source.is_call(),
3375-
});
3379+
if candidates.is_empty() {
3380+
// When there is no suggested imports, we can just emit the error
3381+
// and suggestions immediately. Note that we bypass the usually error
3382+
// reporting routine (ie via `self.r.report_error`) because we need
3383+
// to post-process the `ResolutionError` above.
3384+
err.emit();
3385+
} else {
3386+
// If there are suggested imports, the error reporting is delayed
3387+
this.r.use_injections.push(UseError {
3388+
err,
3389+
candidates,
3390+
def_id,
3391+
instead: false,
3392+
suggestion: None,
3393+
path: path.into(),
3394+
is_call: source.is_call(),
3395+
});
3396+
}
33763397
} else {
33773398
err.cancel();
33783399
}
33793400

33803401
// We don't return `Some(parent_err)` here, because the error will
3381-
// be already printed as part of the `use` injections
3402+
// be already printed either immediately or as part of the `use` injections
33823403
None
33833404
};
33843405

0 commit comments

Comments
 (0)