Skip to content

Commit

Permalink
Do not complain about missing fn main() in some cases
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Oct 30, 2019
1 parent 053a095 commit 454e2aa
Show file tree
Hide file tree
Showing 16 changed files with 50 additions and 116 deletions.
2 changes: 1 addition & 1 deletion src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ impl cstore::CStore {
let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);
let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos);
let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None);
emit_unclosed_delims(&mut errors, &sess.diagnostic());
emit_unclosed_delims(&mut errors, &sess.parse_sess);

// Mark the attrs as used
let attrs = data.get_item_attrs(id.index, sess);
Expand Down
9 changes: 8 additions & 1 deletion src/librustc_passes/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
}

fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
let sp = tcx.hir().krate().span;
if *tcx.sess.parse_sess.reached_eof.borrow() {
// There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about
// the missing `fn main()` then as it might have been hidden inside an unclosed block.
tcx.sess.delay_span_bug(sp, "`main` not found, but expected unclosed brace error");
return;
}

// There is no main function.
let mut err = struct_err!(tcx.sess, E0601,
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
Expand All @@ -173,7 +181,6 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
} else {
String::from("consider adding a `main` function at the crate level")
};
let sp = tcx.hir().krate().span;
// The file may be empty, which leads to the diagnostic machinery not emitting this
// note. This is a relatively simple way to detect that case and emit a span-less
// note instead.
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub fn parse_stream_from_source_str(
sess.source_map().new_source_file(name, source),
override_span,
);
emit_unclosed_delims(&mut errors, &sess.span_diagnostic);
emit_unclosed_delims(&mut errors, &sess);
stream
}

Expand Down Expand Up @@ -242,7 +242,7 @@ pub fn maybe_file_to_stream(
err.buffer(&mut buffer);
// Not using `emit_unclosed_delims` to use `db.buffer`
for unmatched in unmatched_braces {
if let Some(err) = make_unclosed_delims_error(unmatched, &sess.span_diagnostic) {
if let Some(err) = make_unclosed_delims_error(unmatched, &sess) {
err.buffer(&mut buffer);
}
}
Expand Down
13 changes: 7 additions & 6 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@ pub struct Parser<'a> {

impl<'a> Drop for Parser<'a> {
fn drop(&mut self) {
let diag = self.diagnostic();
emit_unclosed_delims(&mut self.unclosed_delims, diag);
emit_unclosed_delims(&mut self.unclosed_delims, &self.sess);
}
}

Expand Down Expand Up @@ -1372,12 +1371,12 @@ impl<'a> Parser<'a> {

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

pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, sess: &ParseSess) {
*sess.reached_eof.borrow_mut() |= unclosed_delims.iter()
.any(|unmatched_delim| unmatched_delim.found_delim.is_none());
for unmatched in unclosed_delims.drain(..) {
make_unclosed_delims_error(unmatched, handler).map(|mut e| e.emit());
make_unclosed_delims_error(unmatched, sess).map(|mut e| e.emit());
}
}
5 changes: 5 additions & 0 deletions src/libsyntax/parse/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,11 @@ impl<'a> Parser<'a> {
// Don't attempt to recover from this unclosed delimiter more than once.
let unmatched = self.unclosed_delims.remove(pos);
let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
if unmatched.found_delim.is_none() {
// We encountered `Eof`, set this fact here to avoid complaining about missing
// `fn main()` when we found place to suggest the closing brace.
*self.sess.reached_eof.borrow_mut() = true;
}

// We want to suggest the inclusion of the closing delimiter where it makes
// the most sense, which is immediately after the last token:
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/sess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub struct ParseSess {
pub ambiguous_block_expr_parse: Lock<FxHashMap<Span, Span>>,
pub injected_crate_name: Once<Symbol>,
crate gated_spans: GatedSpans,
/// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors.
pub reached_eof: Lock<bool>,
}

impl ParseSess {
Expand Down Expand Up @@ -101,6 +103,7 @@ impl ParseSess {
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
injected_crate_name: Once::new(),
gated_spans: GatedSpans::default(),
reached_eof: Lock::new(false),
}
}

Expand Down
1 change: 0 additions & 1 deletion src/test/ui/parser-recovery-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// Test that we can recover from missing braces in the parser.

trait Foo {
//~^ ERROR `main` function not found
fn bar() {
let x = foo();
//~^ ERROR cannot find function `foo` in this scope
Expand Down
26 changes: 6 additions & 20 deletions src/test/ui/parser-recovery-1.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
error: this file contains an un-closed delimiter
--> $DIR/parser-recovery-1.rs:16:55
--> $DIR/parser-recovery-1.rs:15:55
|
LL | trait Foo {
| - un-closed delimiter
LL |
LL | fn bar() {
| - this delimiter might not be properly closed...
...
Expand All @@ -14,36 +13,23 @@ LL | }
| ^

error: unexpected token: `;`
--> $DIR/parser-recovery-1.rs:13:15
--> $DIR/parser-recovery-1.rs:12:15
|
LL | let x = y.;
| ^

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

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

error[E0601]: `main` function not found in crate `parser_recovery_1`
--> $DIR/parser-recovery-1.rs:5:1
|
LL | / trait Foo {
LL | |
LL | | fn bar() {
LL | | let x = foo();
... |
LL | |
LL | | }
| |______________________________________________________^ consider adding a `main` function to `$DIR/parser-recovery-1.rs`

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

Some errors have detailed explanations: E0425, E0601.
For more information about an error, try `rustc --explain E0425`.
For more information about this error, try `rustc --explain E0425`.
7 changes: 2 additions & 5 deletions src/test/ui/parser/issue-2354.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
fn foo() { //~ NOTE un-closed delimiter
//~^ ERROR `main` function not found
//~^^ NOTE main function must be defined
//~^^^ NOTE you have one or more functions
match Some(10) {
//~^ NOTE this delimiter might not be properly closed...
Some(y) => { panic!(); }
Expand All @@ -14,5 +11,5 @@ fn bar() {
while (i < 1000) {}
}

fn main() {} //~ NOTE here is a function named `main`
//~ ERROR this file contains an un-closed delimiter
fn main() {}
//~ ERROR this file contains an un-closed delimiter
28 changes: 3 additions & 25 deletions src/test/ui/parser/issue-2354.stderr
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
error: this file contains an un-closed delimiter
--> $DIR/issue-2354.rs:18:66
--> $DIR/issue-2354.rs:15:53
|
LL | fn foo() {
| - un-closed delimiter
...
LL | match Some(10) {
| - this delimiter might not be properly closed...
...
LL | }
| - ...as it matches this but it has different indentation
...
LL |
| ^

error[E0601]: `main` function not found in crate `issue_2354`
--> $DIR/issue-2354.rs:1:1
|
LL | / fn foo() {
LL | |
LL | |
LL | |
... |
LL | | fn main() {}
LL | |
| |_________________________________________________________________^ the main function must be defined at the crate level (in `$DIR/issue-2354.rs`)
|
note: here is a function named `main`
--> $DIR/issue-2354.rs:17:1
|
LL | fn main() {}
| ^^^^^^^^^^^^
= note: you have one or more functions named `main` not defined at the crate level
= help: either move the `main` function definitions or attach the `#[main]` attribute to one of them
| ^

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0601`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
impl T for () { //~ ERROR `main` function not found
//~^ ERROR cannot find trait `T` in this scope
impl T for () { //~ ERROR cannot find trait `T` in this scope

fn foo(&self) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
error: this file contains an un-closed delimiter
--> $DIR/missing-close-brace-in-impl-trait.rs:13:53
--> $DIR/missing-close-brace-in-impl-trait.rs:12:53
|
LL | impl T for () {
| - un-closed delimiter
...
LL |
| ^

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

error[E0601]: `main` function not found in crate `missing_close_brace_in_impl_trait`
--> $DIR/missing-close-brace-in-impl-trait.rs:1:1
|
LL | / impl T for () {
LL | |
LL | |
LL | | fn foo(&self) {}
... |
LL | | fn main() {}
LL | |
| |____________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-impl-trait.rs`

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

Some errors have detailed explanations: E0405, E0601.
For more information about an error, try `rustc --explain E0405`.
For more information about this error, try `rustc --explain E0405`.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub(crate) struct Bar<T> { //~ ERROR `main` function not found
pub(crate) struct Bar<T> {
foo: T,

trait T { //~ ERROR expected identifier, found keyword `trait`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,5 @@ error: expected `:`, found `T`
LL | trait T {
| ^ expected `:`

error[E0601]: `main` function not found in crate `missing_close_brace_in_struct`
--> $DIR/missing-close-brace-in-struct.rs:1:1
|
LL | / pub(crate) struct Bar<T> {
LL | | foo: T,
LL | |
LL | | trait T {
... |
LL | |
LL | | fn main() {}
| |_________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-struct.rs`

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0601`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
trait T {
//~^ ERROR `main` function not found in crate `missing_close_brace_in_trait`
fn foo(&self);

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

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

error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
--> $DIR/missing-close-brace-in-trait.rs:1:1
|
LL | / trait T {
LL | |
LL | | fn foo(&self);
LL | |
... |
LL | |
LL | | fn main() {}
| |_________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-trait.rs`

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

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

0 comments on commit 454e2aa

Please sign in to comment.