Skip to content

Commit 454e2aa

Browse files
committed
Do not complain about missing fn main() in some cases
1 parent 053a095 commit 454e2aa

16 files changed

+50
-116
lines changed

src/librustc_metadata/cstore_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ impl cstore::CStore {
440440
let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);
441441
let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos);
442442
let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None);
443-
emit_unclosed_delims(&mut errors, &sess.diagnostic());
443+
emit_unclosed_delims(&mut errors, &sess.parse_sess);
444444

445445
// Mark the attrs as used
446446
let attrs = data.get_item_attrs(id.index, sess);

src/librustc_passes/entry.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
154154
}
155155

156156
fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
157+
let sp = tcx.hir().krate().span;
158+
if *tcx.sess.parse_sess.reached_eof.borrow() {
159+
// There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about
160+
// the missing `fn main()` then as it might have been hidden inside an unclosed block.
161+
tcx.sess.delay_span_bug(sp, "`main` not found, but expected unclosed brace error");
162+
return;
163+
}
164+
157165
// There is no main function.
158166
let mut err = struct_err!(tcx.sess, E0601,
159167
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
@@ -173,7 +181,6 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
173181
} else {
174182
String::from("consider adding a `main` function at the crate level")
175183
};
176-
let sp = tcx.hir().krate().span;
177184
// The file may be empty, which leads to the diagnostic machinery not emitting this
178185
// note. This is a relatively simple way to detect that case and emit a span-less
179186
// note instead.

src/libsyntax/parse/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub fn parse_stream_from_source_str(
108108
sess.source_map().new_source_file(name, source),
109109
override_span,
110110
);
111-
emit_unclosed_delims(&mut errors, &sess.span_diagnostic);
111+
emit_unclosed_delims(&mut errors, &sess);
112112
stream
113113
}
114114

@@ -242,7 +242,7 @@ pub fn maybe_file_to_stream(
242242
err.buffer(&mut buffer);
243243
// Not using `emit_unclosed_delims` to use `db.buffer`
244244
for unmatched in unmatched_braces {
245-
if let Some(err) = make_unclosed_delims_error(unmatched, &sess.span_diagnostic) {
245+
if let Some(err) = make_unclosed_delims_error(unmatched, &sess) {
246246
err.buffer(&mut buffer);
247247
}
248248
}

src/libsyntax/parse/parser.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,7 @@ pub struct Parser<'a> {
148148

149149
impl<'a> Drop for Parser<'a> {
150150
fn drop(&mut self) {
151-
let diag = self.diagnostic();
152-
emit_unclosed_delims(&mut self.unclosed_delims, diag);
151+
emit_unclosed_delims(&mut self.unclosed_delims, &self.sess);
153152
}
154153
}
155154

@@ -1372,12 +1371,12 @@ impl<'a> Parser<'a> {
13721371

13731372
crate fn make_unclosed_delims_error(
13741373
unmatched: UnmatchedBrace,
1375-
handler: &errors::Handler,
1374+
sess: &ParseSess,
13761375
) -> Option<DiagnosticBuilder<'_>> {
13771376
// `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
13781377
// `unmatched_braces` only for error recovery in the `Parser`.
13791378
let found_delim = unmatched.found_delim?;
1380-
let mut err = handler.struct_span_err(unmatched.found_span, &format!(
1379+
let mut err = sess.span_diagnostic.struct_span_err(unmatched.found_span, &format!(
13811380
"incorrect close delimiter: `{}`",
13821381
pprust::token_kind_to_string(&token::CloseDelim(found_delim)),
13831382
));
@@ -1391,8 +1390,10 @@ crate fn make_unclosed_delims_error(
13911390
Some(err)
13921391
}
13931392

1394-
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {
1393+
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, sess: &ParseSess) {
1394+
*sess.reached_eof.borrow_mut() |= unclosed_delims.iter()
1395+
.any(|unmatched_delim| unmatched_delim.found_delim.is_none());
13951396
for unmatched in unclosed_delims.drain(..) {
1396-
make_unclosed_delims_error(unmatched, handler).map(|mut e| e.emit());
1397+
make_unclosed_delims_error(unmatched, sess).map(|mut e| e.emit());
13971398
}
13981399
}

src/libsyntax/parse/parser/diagnostics.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,11 @@ impl<'a> Parser<'a> {
11411141
// Don't attempt to recover from this unclosed delimiter more than once.
11421142
let unmatched = self.unclosed_delims.remove(pos);
11431143
let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
1144+
if unmatched.found_delim.is_none() {
1145+
// We encountered `Eof`, set this fact here to avoid complaining about missing
1146+
// `fn main()` when we found place to suggest the closing brace.
1147+
*self.sess.reached_eof.borrow_mut() = true;
1148+
}
11441149

11451150
// We want to suggest the inclusion of the closing delimiter where it makes
11461151
// the most sense, which is immediately after the last token:

src/libsyntax/sess.rs

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ pub struct ParseSess {
7373
pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
7474
pub injected_crate_name: Once<Symbol>,
7575
crate gated_spans: GatedSpans,
76+
/// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors.
77+
pub reached_eof: Lock<bool>,
7678
}
7779

7880
impl ParseSess {
@@ -101,6 +103,7 @@ impl ParseSess {
101103
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
102104
injected_crate_name: Once::new(),
103105
gated_spans: GatedSpans::default(),
106+
reached_eof: Lock::new(false),
104107
}
105108
}
106109

src/test/ui/parser-recovery-1.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// Test that we can recover from missing braces in the parser.
44

55
trait Foo {
6-
//~^ ERROR `main` function not found
76
fn bar() {
87
let x = foo();
98
//~^ ERROR cannot find function `foo` in this scope

src/test/ui/parser-recovery-1.stderr

+6-20
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
error: this file contains an un-closed delimiter
2-
--> $DIR/parser-recovery-1.rs:16:55
2+
--> $DIR/parser-recovery-1.rs:15:55
33
|
44
LL | trait Foo {
55
| - un-closed delimiter
6-
LL |
76
LL | fn bar() {
87
| - this delimiter might not be properly closed...
98
...
@@ -14,36 +13,23 @@ LL | }
1413
| ^
1514

1615
error: unexpected token: `;`
17-
--> $DIR/parser-recovery-1.rs:13:15
16+
--> $DIR/parser-recovery-1.rs:12:15
1817
|
1918
LL | let x = y.;
2019
| ^
2120

2221
error[E0425]: cannot find function `foo` in this scope
23-
--> $DIR/parser-recovery-1.rs:8:17
22+
--> $DIR/parser-recovery-1.rs:7:17
2423
|
2524
LL | let x = foo();
2625
| ^^^ not found in this scope
2726

2827
error[E0425]: cannot find value `y` in this scope
29-
--> $DIR/parser-recovery-1.rs:13:13
28+
--> $DIR/parser-recovery-1.rs:12:13
3029
|
3130
LL | let x = y.;
3231
| ^ not found in this scope
3332

34-
error[E0601]: `main` function not found in crate `parser_recovery_1`
35-
--> $DIR/parser-recovery-1.rs:5:1
36-
|
37-
LL | / trait Foo {
38-
LL | |
39-
LL | | fn bar() {
40-
LL | | let x = foo();
41-
... |
42-
LL | |
43-
LL | | }
44-
| |______________________________________________________^ consider adding a `main` function to `$DIR/parser-recovery-1.rs`
45-
46-
error: aborting due to 5 previous errors
33+
error: aborting due to 4 previous errors
4734

48-
Some errors have detailed explanations: E0425, E0601.
49-
For more information about an error, try `rustc --explain E0425`.
35+
For more information about this error, try `rustc --explain E0425`.

src/test/ui/parser/issue-2354.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
fn foo() { //~ NOTE un-closed delimiter
2-
//~^ ERROR `main` function not found
3-
//~^^ NOTE main function must be defined
4-
//~^^^ NOTE you have one or more functions
52
match Some(10) {
63
//~^ NOTE this delimiter might not be properly closed...
74
Some(y) => { panic!(); }
@@ -14,5 +11,5 @@ fn bar() {
1411
while (i < 1000) {}
1512
}
1613

17-
fn main() {} //~ NOTE here is a function named `main`
18-
//~ ERROR this file contains an un-closed delimiter
14+
fn main() {}
15+
//~ ERROR this file contains an un-closed delimiter

src/test/ui/parser/issue-2354.stderr

+3-25
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,16 @@
11
error: this file contains an un-closed delimiter
2-
--> $DIR/issue-2354.rs:18:66
2+
--> $DIR/issue-2354.rs:15:53
33
|
44
LL | fn foo() {
55
| - un-closed delimiter
6-
...
76
LL | match Some(10) {
87
| - this delimiter might not be properly closed...
98
...
109
LL | }
1110
| - ...as it matches this but it has different indentation
1211
...
1312
LL |
14-
| ^
15-
16-
error[E0601]: `main` function not found in crate `issue_2354`
17-
--> $DIR/issue-2354.rs:1:1
18-
|
19-
LL | / fn foo() {
20-
LL | |
21-
LL | |
22-
LL | |
23-
... |
24-
LL | | fn main() {}
25-
LL | |
26-
| |_________________________________________________________________^ the main function must be defined at the crate level (in `$DIR/issue-2354.rs`)
27-
|
28-
note: here is a function named `main`
29-
--> $DIR/issue-2354.rs:17:1
30-
|
31-
LL | fn main() {}
32-
| ^^^^^^^^^^^^
33-
= note: you have one or more functions named `main` not defined at the crate level
34-
= help: either move the `main` function definitions or attach the `#[main]` attribute to one of them
13+
| ^
3514

36-
error: aborting due to 2 previous errors
15+
error: aborting due to previous error
3716

38-
For more information about this error, try `rustc --explain E0601`.

src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
impl T for () { //~ ERROR `main` function not found
2-
//~^ ERROR cannot find trait `T` in this scope
1+
impl T for () { //~ ERROR cannot find trait `T` in this scope
32

43
fn foo(&self) {}
54

Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
error: this file contains an un-closed delimiter
2-
--> $DIR/missing-close-brace-in-impl-trait.rs:13:53
2+
--> $DIR/missing-close-brace-in-impl-trait.rs:12:53
33
|
44
LL | impl T for () {
55
| - un-closed delimiter
66
...
77
LL |
88
| ^
99

10-
error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `trait`
11-
--> $DIR/missing-close-brace-in-impl-trait.rs:6:1
10+
error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `trait`
11+
--> $DIR/missing-close-brace-in-impl-trait.rs:5:1
1212
|
1313
LL | impl T for () {
1414
| - unclosed delimiter
15-
...
15+
LL |
1616
LL | fn foo(&self) {}
1717
| -
1818
| |
@@ -28,19 +28,6 @@ error[E0405]: cannot find trait `T` in this scope
2828
LL | impl T for () {
2929
| ^ not found in this scope
3030

31-
error[E0601]: `main` function not found in crate `missing_close_brace_in_impl_trait`
32-
--> $DIR/missing-close-brace-in-impl-trait.rs:1:1
33-
|
34-
LL | / impl T for () {
35-
LL | |
36-
LL | |
37-
LL | | fn foo(&self) {}
38-
... |
39-
LL | | fn main() {}
40-
LL | |
41-
| |____________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-impl-trait.rs`
42-
43-
error: aborting due to 4 previous errors
31+
error: aborting due to 3 previous errors
4432

45-
Some errors have detailed explanations: E0405, E0601.
46-
For more information about an error, try `rustc --explain E0405`.
33+
For more information about this error, try `rustc --explain E0405`.

src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub(crate) struct Bar<T> { //~ ERROR `main` function not found
1+
pub(crate) struct Bar<T> {
22
foo: T,
33

44
trait T { //~ ERROR expected identifier, found keyword `trait`

src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr

+1-14
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,5 @@ error: expected `:`, found `T`
2424
LL | trait T {
2525
| ^ expected `:`
2626

27-
error[E0601]: `main` function not found in crate `missing_close_brace_in_struct`
28-
--> $DIR/missing-close-brace-in-struct.rs:1:1
29-
|
30-
LL | / pub(crate) struct Bar<T> {
31-
LL | | foo: T,
32-
LL | |
33-
LL | | trait T {
34-
... |
35-
LL | |
36-
LL | | fn main() {}
37-
| |_________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-struct.rs`
38-
39-
error: aborting due to 4 previous errors
27+
error: aborting due to 3 previous errors
4028

41-
For more information about this error, try `rustc --explain E0601`.

src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
trait T {
2-
//~^ ERROR `main` function not found in crate `missing_close_brace_in_trait`
32
fn foo(&self);
43

54
pub(crate) struct Bar<T>(); //~ ERROR expected one of
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
error: this file contains an un-closed delimiter
2-
--> $DIR/missing-close-brace-in-trait.rs:11:66
2+
--> $DIR/missing-close-brace-in-trait.rs:10:66
33
|
44
LL | trait T {
55
| - un-closed delimiter
66
...
77
LL | fn main() {}
88
| ^
99

10-
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
11-
--> $DIR/missing-close-brace-in-trait.rs:5:1
10+
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found keyword `pub`
11+
--> $DIR/missing-close-brace-in-trait.rs:4:1
1212
|
1313
LL | trait T {
1414
| - unclosed delimiter
15-
LL |
1615
LL | fn foo(&self);
1716
| -
1817
| |
@@ -22,18 +21,5 @@ LL |
2221
LL | pub(crate) struct Bar<T>();
2322
| ^^^ unexpected token
2423

25-
error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
26-
--> $DIR/missing-close-brace-in-trait.rs:1:1
27-
|
28-
LL | / trait T {
29-
LL | |
30-
LL | | fn foo(&self);
31-
LL | |
32-
... |
33-
LL | |
34-
LL | | fn main() {}
35-
| |_________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-trait.rs`
36-
37-
error: aborting due to 3 previous errors
24+
error: aborting due to 2 previous errors
3825

39-
For more information about this error, try `rustc --explain E0601`.

0 commit comments

Comments
 (0)