Skip to content

Commit c2227d8

Browse files
committed
take care module name for suggesting surround the struct literal in parentheses
1 parent 3572d74 commit c2227d8

File tree

4 files changed

+99
-1
lines changed

4 files changed

+99
-1
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -751,10 +751,18 @@ impl<'a> Parser<'a> {
751751
tail.could_be_bare_literal = true;
752752
if maybe_struct_name.is_ident() && can_be_struct_literal {
753753
// Account for `if Example { a: one(), }.is_pos() {}`.
754+
// expand `before` so that we take care of module path such as:
755+
// `foo::Bar { ... } `
756+
// we expect to suggest `(foo::Bar { ... })` instead of `foo::(Bar { ... })`
757+
let sm = self.sess.source_map();
758+
let before = maybe_struct_name.span.shrink_to_lo();
759+
let extend_before = sm.span_extend_prev_while(before, |t| {
760+
t.is_alphanumeric() || t == ':' || t == '_'
761+
});
754762
Err(self.sess.create_err(StructLiteralNeedingParens {
755763
span: maybe_struct_name.span.to(expr.span),
756764
sugg: StructLiteralNeedingParensSugg {
757-
before: maybe_struct_name.span.shrink_to_lo(),
765+
before: extend_before.unwrap().shrink_to_lo(),
758766
after: expr.span.shrink_to_hi(),
759767
},
760768
}))

compiler/rustc_span/src/source_map.rs

+12
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,18 @@ impl SourceMap {
744744
})
745745
}
746746

747+
/// Extends the given `Span` to previous character while the previous character matches the predicate
748+
pub fn span_extend_prev_while(
749+
&self,
750+
span: Span,
751+
f: impl Fn(char) -> bool,
752+
) -> Result<Span, SpanSnippetError> {
753+
self.span_to_source(span, |s, start, _end| {
754+
let n = s[..start].char_indices().rfind(|&(_, c)| !f(c)).map_or(start, |(i, _)| start - i - 1);
755+
Ok(span.with_lo(span.lo() - BytePos(n as u32)))
756+
})
757+
}
758+
747759
/// Extends the given `Span` to just before the next occurrence of `c`.
748760
pub fn span_extend_to_next_char(&self, sp: Span, c: char, accept_newlines: bool) -> Span {
749761
if let Ok(next_source) = self.span_to_next_source(sp) {
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
mod module {
2+
#[derive(Eq, PartialEq)]
3+
pub struct Type {
4+
pub x: u8,
5+
pub y: u8,
6+
}
7+
8+
pub const C: u8 = 32u8;
9+
}
10+
11+
fn test(x: module::Type) {
12+
if x == module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
13+
}
14+
}
15+
16+
fn test2(x: module::Type) {
17+
if x ==module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
18+
}
19+
}
20+
21+
22+
fn test3(x: module::Type) {
23+
if x == Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
24+
}
25+
}
26+
27+
fn test4(x: module::Type) {
28+
if x == demo_module::Type { x: module::C, y: 1 } { //~ ERROR invalid struct literal
29+
}
30+
}
31+
32+
fn main() { }
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
error: invalid struct literal
2+
--> $DIR/issue-111692.rs:12:21
3+
|
4+
LL | if x == module::Type { x: module::C, y: 1 } {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
help: you might need to surround the struct literal in parentheses
8+
|
9+
LL | if x == (module::Type { x: module::C, y: 1 }) {
10+
| + +
11+
12+
error: invalid struct literal
13+
--> $DIR/issue-111692.rs:17:20
14+
|
15+
LL | if x ==module::Type { x: module::C, y: 1 } {
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
|
18+
help: you might need to surround the struct literal in parentheses
19+
|
20+
LL | if x ==(module::Type { x: module::C, y: 1 }) {
21+
| + +
22+
23+
error: invalid struct literal
24+
--> $DIR/issue-111692.rs:23:13
25+
|
26+
LL | if x == Type { x: module::C, y: 1 } {
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
28+
|
29+
help: you might need to surround the struct literal in parentheses
30+
|
31+
LL | if x == (Type { x: module::C, y: 1 }) {
32+
| + +
33+
34+
error: invalid struct literal
35+
--> $DIR/issue-111692.rs:28:26
36+
|
37+
LL | if x == demo_module::Type { x: module::C, y: 1 } {
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
|
40+
help: you might need to surround the struct literal in parentheses
41+
|
42+
LL | if x == (demo_module::Type { x: module::C, y: 1 }) {
43+
| + +
44+
45+
error: aborting due to 4 previous errors
46+

0 commit comments

Comments
 (0)