Skip to content

Commit c105f34

Browse files
authored
Rollup merge of rust-lang#59473 - estebank:borrow-sugg-inside-macro, r=davidtwco
Do not emit incorrect borrow suggestion involving macros and fix overlapping multiline spans Fix rust-lang#58298.
2 parents fda2066 + b5690c2 commit c105f34

File tree

7 files changed

+149
-20
lines changed

7 files changed

+149
-20
lines changed

src/librustc_errors/emitter.rs

+45-13
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ impl EmitterWriter {
243243
end_col: hi.col_display,
244244
is_primary: span_label.is_primary,
245245
label: span_label.label.clone(),
246+
overlaps_exactly: false,
246247
};
247248
multiline_annotations.push((lo.file.clone(), ml.clone()));
248249
AnnotationType::Multiline(ml)
@@ -258,10 +259,7 @@ impl EmitterWriter {
258259
};
259260

260261
if !ann.is_multiline() {
261-
add_annotation_to_file(&mut output,
262-
lo.file,
263-
lo.line,
264-
ann);
262+
add_annotation_to_file(&mut output, lo.file, lo.line, ann);
265263
}
266264
}
267265
}
@@ -274,10 +272,12 @@ impl EmitterWriter {
274272
let ref mut a = item.1;
275273
// Move all other multiline annotations overlapping with this one
276274
// one level to the right.
277-
if &ann != a &&
275+
if !(ann.same_span(a)) &&
278276
num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true)
279277
{
280278
a.increase_depth();
279+
} else if ann.same_span(a) && &ann != a {
280+
a.overlaps_exactly = true;
281281
} else {
282282
break;
283283
}
@@ -289,17 +289,49 @@ impl EmitterWriter {
289289
if ann.depth > max_depth {
290290
max_depth = ann.depth;
291291
}
292-
add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
293-
let middle = min(ann.line_start + 4, ann.line_end);
294-
for line in ann.line_start + 1..middle {
295-
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
296-
}
297-
if middle < ann.line_end - 1 {
298-
for line in ann.line_end - 1..ann.line_end {
292+
let mut end_ann = ann.as_end();
293+
if !ann.overlaps_exactly {
294+
// avoid output like
295+
//
296+
// | foo(
297+
// | _____^
298+
// | |_____|
299+
// | || bar,
300+
// | || );
301+
// | || ^
302+
// | ||______|
303+
// | |______foo
304+
// | baz
305+
//
306+
// and instead get
307+
//
308+
// | foo(
309+
// | _____^
310+
// | | bar,
311+
// | | );
312+
// | | ^
313+
// | | |
314+
// | |______foo
315+
// | baz
316+
add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
317+
// 4 is the minimum vertical length of a multiline span when presented: two lines
318+
// of code and two lines of underline. This is not true for the special case where
319+
// the beginning doesn't have an underline, but the current logic seems to be
320+
// working correctly.
321+
let middle = min(ann.line_start + 4, ann.line_end);
322+
for line in ann.line_start + 1..middle {
323+
// Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
299324
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
300325
}
326+
if middle < ann.line_end - 1 {
327+
for line in ann.line_end - 1..ann.line_end {
328+
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
329+
}
330+
}
331+
} else {
332+
end_ann.annotation_type = AnnotationType::Singleline;
301333
}
302-
add_annotation_to_file(&mut output, file, ann.line_end, ann.as_end());
334+
add_annotation_to_file(&mut output, file, ann.line_end, end_ann);
303335
}
304336
for file_vec in output.iter_mut() {
305337
file_vec.multiline_depth = max_depth;

src/librustc_errors/snippet.rs

+7
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,20 @@ pub struct MultilineAnnotation {
1818
pub end_col: usize,
1919
pub is_primary: bool,
2020
pub label: Option<String>,
21+
pub overlaps_exactly: bool,
2122
}
2223

2324
impl MultilineAnnotation {
2425
pub fn increase_depth(&mut self) {
2526
self.depth += 1;
2627
}
2728

29+
/// Compare two `MultilineAnnotation`s considering only the `Span` they cover.
30+
pub fn same_span(&self, other: &MultilineAnnotation) -> bool {
31+
self.line_start == other.line_start && self.line_end == other.line_end
32+
&& self.start_col == other.start_col && self.end_col == other.end_col
33+
}
34+
2835
pub fn as_start(&self) -> Annotation {
2936
Annotation {
3037
start_col: self.start_col,

src/librustc_typeck/check/demand.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc::hir::Node;
1010
use rustc::hir::{Item, ItemKind, print};
1111
use rustc::ty::{self, Ty, AssociatedItem};
1212
use rustc::ty::adjustment::AllowTwoPhase;
13-
use errors::{Applicability, DiagnosticBuilder, SourceMapper};
13+
use errors::{Applicability, DiagnosticBuilder};
1414

1515
use super::method::probe;
1616

@@ -292,9 +292,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
292292
expected: Ty<'tcx>)
293293
-> Option<(Span, &'static str, String)> {
294294
let cm = self.sess().source_map();
295-
// Use the callsite's span if this is a macro call. #41858
296-
let sp = cm.call_span_if_macro(expr.span);
295+
let sp = expr.span;
297296
if !cm.span_to_filename(sp).is_real() {
297+
// Ignore if span is from within a macro #41858, #58298. We previously used the macro
298+
// call span, but that breaks down when the type error comes from multiple calls down.
298299
return None;
299300
}
300301

src/libsyntax/test_snippet.rs

+60
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,66 @@ error: foo
374374
"#);
375375
}
376376

377+
#[test]
378+
fn triple_exact_overlap() {
379+
test_harness(r#"
380+
fn foo() {
381+
X0 Y0 Z0
382+
X1 Y1 Z1
383+
X2 Y2 Z2
384+
}
385+
"#,
386+
vec![
387+
SpanLabel {
388+
start: Position {
389+
string: "X0",
390+
count: 1,
391+
},
392+
end: Position {
393+
string: "X2",
394+
count: 1,
395+
},
396+
label: "`X` is a good letter",
397+
},
398+
SpanLabel {
399+
start: Position {
400+
string: "X0",
401+
count: 1,
402+
},
403+
end: Position {
404+
string: "X2",
405+
count: 1,
406+
},
407+
label: "`Y` is a good letter too",
408+
},
409+
SpanLabel {
410+
start: Position {
411+
string: "X0",
412+
count: 1,
413+
},
414+
end: Position {
415+
string: "X2",
416+
count: 1,
417+
},
418+
label: "`Z` label",
419+
},
420+
],
421+
r#"
422+
error: foo
423+
--> test.rs:3:3
424+
|
425+
3 | / X0 Y0 Z0
426+
4 | | X1 Y1 Z1
427+
5 | | X2 Y2 Z2
428+
| | ^
429+
| | |
430+
| | `X` is a good letter
431+
| |____`Y` is a good letter too
432+
| `Z` label
433+
434+
"#);
435+
}
436+
377437
#[test]
378438
fn minimum_depth() {
379439
test_harness(r#"

src/test/ui/span/coerce-suggestions.stderr

+1-4
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,7 @@ error[E0308]: mismatched types
5050
--> $DIR/coerce-suggestions.rs:21:9
5151
|
5252
LL | s = format!("foo");
53-
| ^^^^^^^^^^^^^^
54-
| |
55-
| expected mutable reference, found struct `std::string::String`
56-
| help: consider mutably borrowing here: `&mut format!("foo")`
53+
| ^^^^^^^^^^^^^^ expected mutable reference, found struct `std::string::String`
5754
|
5855
= note: expected type `&mut std::string::String`
5956
found type `std::string::String`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn warn(_: &str) {}
2+
3+
macro_rules! intrinsic_match {
4+
($intrinsic:expr) => {
5+
warn(format!("unsupported intrinsic {}", $intrinsic));
6+
//~^ ERROR mismatched types
7+
};
8+
}
9+
10+
fn main() {
11+
intrinsic_match! {
12+
"abc"
13+
};
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/dont-suggest-deref-inside-macro-issue-58298.rs:11:5
3+
|
4+
LL | / intrinsic_match! {
5+
LL | | "abc"
6+
LL | | };
7+
| | ^
8+
| | |
9+
| |______expected &str, found struct `std::string::String`
10+
| in this macro invocation
11+
|
12+
= note: expected type `&str`
13+
found type `std::string::String`
14+
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)