Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b30022a

Browse files
authoredNov 29, 2016
Auto merge of #37369 - estebank:multiline-span, r=nikomatsakis
Show multiline spans in full if short enough When dealing with multiline spans that span few lines, show the complete span instead of restricting to the first character of the first line. For example, instead of: ``` % ./rustc file2.rs error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied --> file2.rs:13:9 | 13 | foo(1 + bar(x, | ^ trait `{integer}: std::ops::Add<()>` not satisfied | ``` show ``` % ./rustc file2.rs error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied --> file2.rs:13:9 | 13 | foo(1 + bar(x, | ________^ starting here... 14 | | y), | |_____________^ ...ending here: trait `{integer}: std::ops::Add<()>` not satisfied | ``` The [proposal in internals](https://internals.rust-lang.org/t/proposal-for-multiline-span-comments/4242/6) outlines the reasoning behind this.
2 parents f50dbd5 + b7982bb commit b30022a

15 files changed

+1158
-144
lines changed
 

‎src/librustc_errors/emitter.rs

Lines changed: 353 additions & 105 deletions
Large diffs are not rendered by default.

‎src/librustc_errors/snippet.rs

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,86 @@ pub struct Line {
4141
pub annotations: Vec<Annotation>,
4242
}
4343

44+
45+
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
46+
pub struct MultilineAnnotation {
47+
pub depth: usize,
48+
pub line_start: usize,
49+
pub line_end: usize,
50+
pub start_col: usize,
51+
pub end_col: usize,
52+
pub is_primary: bool,
53+
pub label: Option<String>,
54+
}
55+
56+
impl MultilineAnnotation {
57+
pub fn increase_depth(&mut self) {
58+
self.depth += 1;
59+
}
60+
61+
pub fn as_start(&self) -> Annotation {
62+
Annotation {
63+
start_col: self.start_col,
64+
end_col: self.start_col + 1,
65+
is_primary: self.is_primary,
66+
label: Some("starting here...".to_owned()),
67+
annotation_type: AnnotationType::MultilineStart(self.depth)
68+
}
69+
}
70+
71+
pub fn as_end(&self) -> Annotation {
72+
Annotation {
73+
start_col: self.end_col - 1,
74+
end_col: self.end_col,
75+
is_primary: self.is_primary,
76+
label: match self.label {
77+
Some(ref label) => Some(format!("...ending here: {}", label)),
78+
None => Some("...ending here".to_owned()),
79+
},
80+
annotation_type: AnnotationType::MultilineEnd(self.depth)
81+
}
82+
}
83+
84+
pub fn as_line(&self) -> Annotation {
85+
Annotation {
86+
start_col: 0,
87+
end_col: 0,
88+
is_primary: self.is_primary,
89+
label: None,
90+
annotation_type: AnnotationType::MultilineLine(self.depth)
91+
}
92+
}
93+
}
94+
95+
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
96+
pub enum AnnotationType {
97+
/// Annotation under a single line of code
98+
Singleline,
99+
100+
/// Annotation under the first character of a multiline span
101+
Minimized,
102+
103+
/// Annotation enclosing the first and last character of a multiline span
104+
Multiline(MultilineAnnotation),
105+
106+
// The Multiline type above is replaced with the following three in order
107+
// to reuse the current label drawing code.
108+
//
109+
// Each of these corresponds to one part of the following diagram:
110+
//
111+
// x | foo(1 + bar(x,
112+
// | _________^ starting here... < MultilineStart
113+
// x | | y), < MultilineLine
114+
// | |______________^ ...ending here: label < MultilineEnd
115+
// x | z);
116+
/// Annotation marking the first character of a fully shown multiline span
117+
MultilineStart(usize),
118+
/// Annotation marking the last character of a fully shown multiline span
119+
MultilineEnd(usize),
120+
/// Line at the left enclosing the lines of a fully shown multiline span
121+
MultilineLine(usize),
122+
}
123+
44124
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
45125
pub struct Annotation {
46126
/// Start column, 0-based indexing -- counting *characters*, not
@@ -55,11 +135,32 @@ pub struct Annotation {
55135
/// Is this annotation derived from primary span
56136
pub is_primary: bool,
57137

58-
/// Is this a large span minimized down to a smaller span
59-
pub is_minimized: bool,
60-
61138
/// Optional label to display adjacent to the annotation.
62139
pub label: Option<String>,
140+
141+
/// Is this a single line, multiline or multiline span minimized down to a
142+
/// smaller span.
143+
pub annotation_type: AnnotationType,
144+
}
145+
146+
impl Annotation {
147+
pub fn is_minimized(&self) -> bool {
148+
match self.annotation_type {
149+
AnnotationType::Minimized => true,
150+
_ => false,
151+
}
152+
}
153+
154+
pub fn is_multiline(&self) -> bool {
155+
match self.annotation_type {
156+
AnnotationType::Multiline(_) |
157+
AnnotationType::MultilineStart(_) |
158+
AnnotationType::MultilineLine(_) |
159+
AnnotationType::MultilineEnd(_) => true,
160+
_ => false,
161+
}
162+
}
163+
63164
}
64165

65166
#[derive(Debug)]

‎src/libsyntax/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,7 @@ pub mod ext {
145145
}
146146
}
147147

148+
#[cfg(test)]
149+
mod test_snippet;
150+
148151
// __build_diagnostic_array! { libsyntax, DIAGNOSTICS }

‎src/libsyntax/test_snippet.rs

Lines changed: 546 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
error[E0276]: impl has stricter requirements than trait
22
--> $DIR/region-extra-2.rs:19:5
33
|
4-
15 | fn renew<'b: 'a>(self) -> &'b mut [T];
5-
| -------------------------------------- definition of `renew` from trait
4+
15 | fn renew<'b: 'a>(self) -> &'b mut [T];
5+
| -------------------------------------- definition of `renew` from trait
66
...
7-
19 | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
8-
| ^ impl has extra requirement `'a: 'b`
7+
19 | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
8+
| _____^ starting here...
9+
20 | | //~^ ERROR E0276
10+
21 | | &mut self[..]
11+
22 | | }
12+
| |_____^ ...ending here: impl has extra requirement `'a: 'b`
913

1014
error: aborting due to previous error
1115

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
error[E0276]: impl has stricter requirements than trait
22
--> $DIR/traits-misc-mismatch-2.rs:23:5
33
|
4-
19 | fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
5-
| ------------------------------------------------------------------ definition of `zip` from trait
4+
19 | fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
5+
| ------------------------------------------------------------------ definition of `zip` from trait
66
...
7-
23 | fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
8-
| ^ impl has extra requirement `U: Iterator<B>`
7+
23 | fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
8+
| _____^ starting here...
9+
24 | | //~^ ERROR E0276
10+
25 | | ZipIterator{a: self, b: other}
11+
26 | | }
12+
| |_____^ ...ending here: impl has extra requirement `U: Iterator<B>`
913

1014
error: aborting due to previous error
1115

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
22
--> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:32:1
33
|
4-
32 | impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
5-
| ^
4+
32 | impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
5+
| _^ starting here...
6+
33 | | //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
7+
34 | |
8+
35 | | // (unsafe to access self.1 due to #[may_dangle] on A)
9+
36 | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
10+
37 | | }
11+
| |_^ ...ending here
612

713
error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
814
--> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:38:1
915
|
10-
38 | impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
11-
| ^
16+
38 | impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
17+
| _^ starting here...
18+
39 | | //~^ ERROR requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
19+
40 | |
20+
41 | | // (unsafe to access self.1 due to #[may_dangle] on 'a)
21+
42 | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
22+
43 | | }
23+
| |_^ ...ending here
1224

1325
error: aborting due to 2 previous errors
1426

‎src/test/ui/lifetimes/consider-using-explicit-lifetime.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen
1515
help: consider using an explicit lifetime parameter as shown: fn from_str(path: &'a str) -> Result<Self, ()>
1616
--> $DIR/consider-using-explicit-lifetime.rs:25:5
1717
|
18-
25 | fn from_str(path: &str) -> Result<Self, ()> {
19-
| ^
18+
25 | fn from_str(path: &str) -> Result<Self, ()> {
19+
| _____^ starting here...
20+
26 | | Ok(Foo { field: path })
21+
27 | | }
22+
| |_____^ ...ending here
2023

2124
error: aborting due to 2 previous errors
2225

‎src/test/ui/mismatched_types/main.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
error[E0308]: mismatched types
22
--> $DIR/main.rs:12:18
33
|
4-
12 | let x: u32 = (
5-
| ^ expected u32, found ()
4+
12 | let x: u32 = (
5+
| __________________^ starting here...
6+
13 | | );
7+
| |_____^ ...ending here: expected u32, found ()
68
|
79
= note: expected type `u32`
810
= note: found type `()`

‎src/test/ui/missing-items/m2.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ error: main function not found
33
error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`
44
--> $DIR/m2.rs:20:1
55
|
6-
20 | impl m1::X for X {
7-
| ^ missing `CONSTANT`, `Type`, `method` in implementation
6+
20 | impl m1::X for X {
7+
| _^ starting here...
8+
21 | | }
9+
| |_^ ...ending here: missing `CONSTANT`, `Type`, `method` in implementation
810
|
911
= note: `CONSTANT` from trait: `const CONSTANT: u32;`
1012
= note: `Type` from trait: `type Type;`

‎src/test/ui/span/impl-wrong-item-for-trait.stderr

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,19 @@ error[E0323]: item `bar` is an associated const, which doesn't match its trait `
1010
error[E0046]: not all trait items implemented, missing: `bar`
1111
--> $DIR/impl-wrong-item-for-trait.rs:22:1
1212
|
13-
16 | fn bar(&self);
14-
| -------------- `bar` from trait
13+
16 | fn bar(&self);
14+
| -------------- `bar` from trait
1515
...
16-
22 | impl Foo for FooConstForMethod {
17-
| ^ missing `bar` in implementation
16+
22 | impl Foo for FooConstForMethod {
17+
| _^ starting here...
18+
23 | | //~^ ERROR E0046
19+
24 | | //~| NOTE missing `bar` in implementation
20+
25 | | const bar: u64 = 1;
21+
26 | | //~^ ERROR E0323
22+
27 | | //~| NOTE does not match trait
23+
28 | | const MY_CONST: u32 = 1;
24+
29 | | }
25+
| |_^ ...ending here: missing `bar` in implementation
1826

1927
error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `<FooMethodForConst as Foo>`
2028
--> $DIR/impl-wrong-item-for-trait.rs:37:5
@@ -28,11 +36,19 @@ error[E0324]: item `MY_CONST` is an associated method, which doesn't match its t
2836
error[E0046]: not all trait items implemented, missing: `MY_CONST`
2937
--> $DIR/impl-wrong-item-for-trait.rs:33:1
3038
|
31-
17 | const MY_CONST: u32;
32-
| -------------------- `MY_CONST` from trait
39+
17 | const MY_CONST: u32;
40+
| -------------------- `MY_CONST` from trait
3341
...
34-
33 | impl Foo for FooMethodForConst {
35-
| ^ missing `MY_CONST` in implementation
42+
33 | impl Foo for FooMethodForConst {
43+
| _^ starting here...
44+
34 | | //~^ ERROR E0046
45+
35 | | //~| NOTE missing `MY_CONST` in implementation
46+
36 | | fn bar(&self) {}
47+
37 | | fn MY_CONST() {}
48+
38 | | //~^ ERROR E0324
49+
39 | | //~| NOTE does not match trait
50+
40 | | }
51+
| |_^ ...ending here: missing `MY_CONST` in implementation
3652

3753
error[E0325]: item `bar` is an associated type, which doesn't match its trait `<FooTypeForMethod as Foo>`
3854
--> $DIR/impl-wrong-item-for-trait.rs:47:5
@@ -46,17 +62,27 @@ error[E0325]: item `bar` is an associated type, which doesn't match its trait `<
4662
error[E0046]: not all trait items implemented, missing: `bar`
4763
--> $DIR/impl-wrong-item-for-trait.rs:44:1
4864
|
49-
16 | fn bar(&self);
50-
| -------------- `bar` from trait
65+
16 | fn bar(&self);
66+
| -------------- `bar` from trait
5167
...
52-
44 | impl Foo for FooTypeForMethod {
53-
| ^ missing `bar` in implementation
68+
44 | impl Foo for FooTypeForMethod {
69+
| _^ starting here...
70+
45 | | //~^ ERROR E0046
71+
46 | | //~| NOTE missing `bar` in implementation
72+
47 | | type bar = u64;
73+
48 | | //~^ ERROR E0325
74+
49 | | //~| NOTE does not match trait
75+
50 | | const MY_CONST: u32 = 1;
76+
51 | | }
77+
| |_^ ...ending here: missing `bar` in implementation
5478

5579
error[E0046]: not all trait items implemented, missing: `fmt`
5680
--> $DIR/impl-wrong-item-for-trait.rs:53:1
5781
|
58-
53 | impl Debug for FooTypeForMethod {
59-
| ^ missing `fmt` in implementation
82+
53 | impl Debug for FooTypeForMethod {
83+
| _^ starting here...
84+
54 | | }
85+
| |_^ ...ending here: missing `fmt` in implementation
6086
|
6187
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
6288

‎src/test/ui/span/issue-23827.stderr

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
error[E0046]: not all trait items implemented, missing: `Output`
22
--> $DIR/issue-23827.rs:36:1
33
|
4-
36 | impl<C: Component> FnOnce<(C,)> for Prototype {
5-
| ^ missing `Output` in implementation
4+
36 | impl<C: Component> FnOnce<(C,)> for Prototype {
5+
| _^ starting here...
6+
37 | | //~^ ERROR E0046
7+
38 | | //~| NOTE missing `Output` in implementation
8+
39 | | //~| NOTE `Output` from trait: `type Output;`
9+
40 | | extern "rust-call" fn call_once(self, (comp,): (C,)) -> Prototype {
10+
41 | | Fn::call(&self, (comp,))
11+
42 | | }
12+
43 | | }
13+
| |_^ ...ending here: missing `Output` in implementation
614
|
715
= note: `Output` from trait: `type Output;`
816

‎src/test/ui/span/issue-24356.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
error[E0046]: not all trait items implemented, missing: `Target`
22
--> $DIR/issue-24356.rs:30:9
33
|
4-
30 | impl Deref for Thing {
5-
| ^ missing `Target` in implementation
4+
30 | impl Deref for Thing {
5+
| _________^ starting here...
6+
31 | | //~^ ERROR E0046
7+
32 | | //~| NOTE missing `Target` in implementation
8+
33 | | //~| NOTE `Target` from trait: `type Target;`
9+
34 | | fn deref(&self) -> i8 { self.0 }
10+
35 | | }
11+
| |_________^ ...ending here: missing `Target` in implementation
612
|
713
= note: `Target` from trait: `type Target;`
814

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn foo(a: u32, b: u32) {
12+
a + b;
13+
}
14+
15+
fn bar(a: u32, b: u32) {
16+
a + b;
17+
}
18+
19+
fn main() {
20+
let x = 1;
21+
let y = 2;
22+
let z = 3;
23+
foo(1 as u32 +
24+
25+
bar(x,
26+
27+
y),
28+
29+
z)
30+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied
2+
--> $DIR/multiline-span-simple.rs:23:9
3+
|
4+
23 | foo(1 as u32 +
5+
| _________^ starting here...
6+
24 | |
7+
25 | | bar(x,
8+
26 | |
9+
27 | | y),
10+
| |______________^ ...ending here: the trait `std::ops::Add<()>` is not implemented for `u32`
11+
|
12+
= help: the following implementations were found:
13+
= help: <u32 as std::ops::Add>
14+
= help: <&'a u32 as std::ops::Add<u32>>
15+
= help: <u32 as std::ops::Add<&'a u32>>
16+
= help: <&'b u32 as std::ops::Add<&'a u32>>
17+
18+
error: aborting due to previous error
19+

0 commit comments

Comments
 (0)
Please sign in to comment.