@@ -31,7 +31,7 @@ use smallvec::{smallvec, SmallVec};
31
31
32
32
use rustc_span:: source_map:: { respan, Spanned } ;
33
33
use std:: collections:: { hash_map:: Entry , BTreeSet } ;
34
- use std:: mem:: { replace, take} ;
34
+ use std:: mem:: { replace, take, swap } ;
35
35
36
36
mod diagnostics;
37
37
@@ -3334,10 +3334,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
3334
3334
let ( mut err, candidates) =
3335
3335
this. smart_resolve_report_errors ( path, path_span, PathSource :: Type , None ) ;
3336
3336
3337
- if candidates. is_empty ( ) {
3338
- err. cancel ( ) ;
3339
- return Some ( parent_err) ;
3340
- }
3341
3337
3342
3338
// There are two different error messages user might receive at
3343
3339
// this point:
@@ -3348,37 +3344,62 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
3348
3344
// latter one - for paths in expression-position.
3349
3345
//
3350
3346
// 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
3352
3348
// `parent_err`), but we want *hints* from E0412 (so `err`).
3353
3349
//
3354
3350
// And that's what happens below - we're just mixing both messages
3355
3351
// into a single one.
3356
3352
let mut parent_err = this. r . into_struct_error ( parent_err. span , parent_err. node ) ;
3357
3353
3354
+ // overwrite all properties with the parent's error message
3358
3355
err. message = take ( & mut parent_err. message ) ;
3359
3356
err. code = take ( & mut parent_err. code ) ;
3357
+ swap ( & mut err. span , & mut parent_err. span ) ;
3360
3358
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 ( ) ) ;
3361
3373
3362
3374
parent_err. cancel ( ) ;
3363
3375
3364
3376
let def_id = this. parent_scope . module . nearest_parent_mod ( ) ;
3365
3377
3366
3378
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
+ }
3376
3397
} else {
3377
3398
err. cancel ( ) ;
3378
3399
}
3379
3400
3380
3401
// 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
3382
3403
None
3383
3404
} ;
3384
3405
0 commit comments