diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a83ac9bb63369..ab3950fb6f813 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -605,7 +605,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { ItemKind::Use(..) => { // don't suggest placing a use before the prelude // import or other generated ones - if item.span == DUMMY_SP { + if item.span.ctxt.outer().expn_info().is_none() { let mut span = item.span; span.hi = span.lo; self.span = Some(span); @@ -617,13 +617,26 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { ItemKind::ExternCrate(_) => {} // but place them before the first other item _ => if self.span.map_or(true, |span| item.span < span ) { - let mut span = item.span; - span.hi = span.lo; - self.span = Some(span); + if item.span.ctxt.outer().expn_info().is_none() { + // don't insert between attributes and an item + if item.attrs.is_empty() { + let mut span = item.span; + span.hi = span.lo; + self.span = Some(span); + } else { + // find the first attribute on the item + for attr in &item.attrs { + if self.span.map_or(true, |span| attr.span < span) { + let mut span = attr.span; + span.hi = span.lo; + self.span = Some(span); + } + } + } + } }, } } - assert!(self.span.is_some(), "a file can't have no items and emit suggestions"); } } @@ -3554,8 +3567,7 @@ impl<'a> Resolver<'a> { }; visit::walk_crate(&mut finder, krate); if !candidates.is_empty() { - let span = finder.span.expect("did not find module"); - show_candidates(&mut err, span, &candidates, better, finder.found_use); + show_candidates(&mut err, finder.span, &candidates, better, finder.found_use); } err.emit(); } @@ -3749,7 +3761,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St /// entities with that name in all crates. This method allows outputting the /// results of this search in a programmer-friendly way fn show_candidates(err: &mut DiagnosticBuilder, - span: Span, + // This is `None` if all placement locations are inside expansions + span: Option, candidates: &[ImportSuggestion], better: bool, found_use: bool) { @@ -3767,18 +3780,27 @@ fn show_candidates(err: &mut DiagnosticBuilder, }; let msg = format!("possible {}candidate{} into scope", better, msg_diff); - for candidate in &mut path_strings { - // produce an additional newline to separate the new use statement - // from the directly following item. - let additional_newline = if found_use { - "" - } else { - "\n" - }; - *candidate = format!("use {};\n{}", candidate, additional_newline); - } + if let Some(span) = span { + for candidate in &mut path_strings { + // produce an additional newline to separate the new use statement + // from the directly following item. + let additional_newline = if found_use { + "" + } else { + "\n" + }; + *candidate = format!("use {};\n{}", candidate, additional_newline); + } - err.span_suggestions(span, &msg, path_strings); + err.span_suggestions(span, &msg, path_strings); + } else { + let mut msg = msg; + msg.push(':'); + for candidate in path_strings { + msg.push('\n'); + msg.push_str(&candidate); + } + } } /// A somewhat inefficient routine to obtain the name of a module. diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index ee1481ec6f2b0..f7e5c602644cf 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -10,7 +10,7 @@ error[E0423]: expected value, found struct `Z` | help: possible better candidate is found in another module, you can import it into scope | -16 | use m::n::Z; +22 | use m::n::Z; | error[E0423]: expected value, found struct `S` @@ -24,7 +24,7 @@ error[E0423]: expected value, found struct `S` | help: possible better candidate is found in another module, you can import it into scope | -15 | use m::S; +32 | use m::S; | error[E0423]: expected value, found struct `xcrate::S` @@ -38,7 +38,7 @@ error[E0423]: expected value, found struct `xcrate::S` | help: possible better candidate is found in another module, you can import it into scope | -15 | use m::S; +32 | use m::S; | error[E0603]: tuple struct `Z` is private diff --git a/src/test/ui/resolve/use_suggestion_placement.rs b/src/test/ui/resolve/use_suggestion_placement.rs index e0027fed4d6f2..a43b8fc99df5f 100644 --- a/src/test/ui/resolve/use_suggestion_placement.rs +++ b/src/test/ui/resolve/use_suggestion_placement.rs @@ -16,6 +16,15 @@ mod m { pub const A: i32 = 0; } +mod foo { + #[derive(Debug)] + pub struct Foo; + + // test whether the use suggestion isn't + // placed into the expansion of `#[derive(Debug)] + type Bar = Path; +} + fn main() { y!(); let _ = A; diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr index 5c74d8bed6665..8a4dfdc80276a 100644 --- a/src/test/ui/resolve/use_suggestion_placement.stderr +++ b/src/test/ui/resolve/use_suggestion_placement.stderr @@ -1,7 +1,18 @@ +error[E0412]: cannot find type `Path` in this scope + --> $DIR/use_suggestion_placement.rs:25:16 + | +25 | type Bar = Path; + | ^^^^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | +21 | use std::path::Path; + | + error[E0425]: cannot find value `A` in this scope - --> $DIR/use_suggestion_placement.rs:21:13 + --> $DIR/use_suggestion_placement.rs:30:13 | -21 | let _ = A; +30 | let _ = A; | ^ not found in this scope | help: possible candidate is found in another module, you can import it into scope @@ -10,9 +21,9 @@ help: possible candidate is found in another module, you can import it into scop | error[E0412]: cannot find type `HashMap` in this scope - --> $DIR/use_suggestion_placement.rs:26:23 + --> $DIR/use_suggestion_placement.rs:35:23 | -26 | type Dict = HashMap; +35 | type Dict = HashMap; | ^^^^^^^ not found in this scope | help: possible candidates are found in other modules, you can import them into scope @@ -23,16 +34,16 @@ help: possible candidates are found in other modules, you can import them into s | error[E0091]: type parameter `K` is unused - --> $DIR/use_suggestion_placement.rs:26:15 + --> $DIR/use_suggestion_placement.rs:35:15 | -26 | type Dict = HashMap; +35 | type Dict = HashMap; | ^ unused type parameter error[E0091]: type parameter `V` is unused - --> $DIR/use_suggestion_placement.rs:26:18 + --> $DIR/use_suggestion_placement.rs:35:18 | -26 | type Dict = HashMap; +35 | type Dict = HashMap; | ^ unused type parameter -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr index 0cd7e1046f6cc..b57b58e3d2a6d 100644 --- a/src/test/ui/span/issue-35987.stderr +++ b/src/test/ui/span/issue-35987.stderr @@ -6,7 +6,7 @@ error[E0404]: expected trait, found type parameter `Add` | help: possible better candidate is found in another module, you can import it into scope | -11 | use std::ops::Add; +13 | use std::ops::Add; | error[E0601]: main function not found