Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

overhaul "missing main" diagnostic #79086

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 16 additions & 32 deletions compiler/rustc_passes/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc_ast::entry::EntryPointType;
use rustc_errors::struct_span_err;
use rustc_errors::{struct_span_err, Applicability};
use rustc_hir::def_id::{CrateNum, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem};
Expand All @@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::config::{CrateType, EntryFnType};
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::{Span, DUMMY_SP};
use rustc_span::{MultiSpan, Span};

struct EntryContext<'a, 'tcx> {
session: &'a Session,
Expand Down Expand Up @@ -174,49 +174,33 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
return;
}

// There is no main function.
let mut err = struct_span_err!(
tcx.sess,
DUMMY_SP,
sp.shrink_to_lo(),
E0601,
"`main` function not found in crate `{}`",
tcx.crate_name(LOCAL_CRATE)
);
let filename = &tcx.sess.local_crate_source_file;
let note = if !visitor.non_main_fns.is_empty() {
for &(_, span) in &visitor.non_main_fns {
err.span_note(span, "here is a function named `main`");
}
err.note("you have one or more functions named `main` not defined at the crate level");
err.help(
"either move the `main` function definitions or attach the `#[main]` attribute \
to one of them",
);
// There were some functions named `main` though. Try to give the user a hint.
format!(
"the main function must be defined at the crate level{}",
filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default()
)
} else if let Some(filename) = filename {
format!("consider adding a `main` function to `{}`", filename.display())
} else {
String::from("consider adding a `main` function at the crate level")
};
// 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.
if tcx.sess.source_map().lookup_line(sp.lo()).is_ok() {
err.set_span(sp);
err.span_label(sp, &note);
} else {
err.note(&note);

if !visitor.non_main_fns.is_empty() {
let span = MultiSpan::from_spans(visitor.non_main_fns.iter().map(|(_, sp)| *sp).collect());
err.span_help(span, "consider moving one of these function definitions to the crate root");
Comment on lines +186 to +187
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't being tested, is it? Found the test.

Also, I wonder if a span_label per "non main fns" might look better.

The message doesn't account for a single fn being found (use pluralize!()).

}

err.span_suggestion(
sp.shrink_to_lo(),
"define a function named `main` at the crate root",
String::from("fn main() {}\n"),
Applicability::MaybeIncorrect,
);
Comment on lines +190 to +195
Copy link
Member

@jyn514 jyn514 Nov 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another hint that would be helpful is to pass --crate-type lib if you didn't mean for this to be a binary. I run into that a lot testing out things for rustdoc (really I want rust-lang/rust-playground#489, but in the meantime ...)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a help with this info might be warranted.


if tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"If you don't know the basics of Rust, you can go look to the Rust Book \
to get started: https://doc.rust-lang.org/book/",
);
}

err.emit();
}

Expand Down
10 changes: 7 additions & 3 deletions src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
error[E0601]: `main` function not found in crate `cfg_attr_cfg_2`
--> $DIR/cfg-attr-cfg-2.rs:8:1
|
LL | / #[cfg_attr(foo, cfg(bar))]
LL | | fn main() { }
| |_____________^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
LL | #[cfg_attr(foo, cfg(bar))]
| ^
|
help: define a function named `main` at the crate root
|
LL | fn main() {}
|

error: aborting due to previous error

Expand Down
7 changes: 6 additions & 1 deletion src/test/ui/conditional-compilation/cfg-in-crate-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1`
--> $DIR/cfg-in-crate-1.rs:3:1
|
LL | #![cfg(bar)]
| ^^^^^^^^^^^^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
| ^
|
help: define a function named `main` at the crate root
|
LL | fn main() {}
|

error: aborting due to previous error

Expand Down
13 changes: 4 additions & 9 deletions src/test/ui/continue-after-missing-main.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
error[E0601]: `main` function not found in crate `continue_after_missing_main`
--> $DIR/continue-after-missing-main.rs:1:1
|
LL | / #![allow(dead_code)]
LL | |
LL | | struct Tableau<'a, MP> {
LL | | provider: &'a MP,
... |
LL | |
LL | | }
| |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
help: define a function named `main` at the crate root
Comment on lines 1 to +3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple of cases now where the main diagnostic doesn't have a primary span. We should have a span pointing to the first char at least. I wonder if it is because of the code deleted between 205 and 212.

|
LL | fn main() {}
|

error[E0623]: lifetime mismatch
--> $DIR/continue-after-missing-main.rs:28:56
Expand Down
11 changes: 7 additions & 4 deletions src/test/ui/elided-test.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
error[E0601]: `main` function not found in crate `elided_test`
--> $DIR/elided-test.rs:5:1
|
LL | / #[test]
LL | | fn main() {
LL | | }
| |_^ consider adding a `main` function to `$DIR/elided-test.rs`
LL | #[test]
| ^
|
help: define a function named `main` at the crate root
|
LL | fn main() {}
|

error: aborting due to previous error

Expand Down
7 changes: 6 additions & 1 deletion src/test/ui/error-codes/E0601.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ error[E0601]: `main` function not found in crate `E0601`
--> $DIR/E0601.rs:1:37
|
LL |
| ^ consider adding a `main` function to `$DIR/E0601.rs`
| ^
|
help: define a function named `main` at the crate root
|
LL |
| ^^^^^^^^^^^^

error: aborting due to previous error

Expand Down
9 changes: 4 additions & 5 deletions src/test/ui/issues/issue-49040.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ LL | #![allow(unused_variables)];
| ^ help: remove this semicolon

error[E0601]: `main` function not found in crate `issue_49040`
--> $DIR/issue-49040.rs:1:1
|
LL | / #![allow(unused_variables)];
LL | |
LL | | fn foo() {}
| |__^ consider adding a `main` function to `$DIR/issue-49040.rs`
help: define a function named `main` at the crate root
|
LL | fn main() {}
|

error: aborting due to 2 previous errors

Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/json-short.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ If you don't know the basics of Rust, you can look at the
[Rust Book][rust-book] to get started.

[rust-book]: https://doc.rust-lang.org/book/
"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":62,"byte_end":62,"line_start":1,"line_end":1,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:63: error[E0601]: `main` function not found in crate `json_short`
"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":62,"byte_end":62,"line_start":1,"line_end":1,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"define a function named `main` at the crate root","code":null,"level":"help","spans":[{"file_name":"$DIR/json-short.rs","byte_start":62,"byte_end":62,"line_start":1,"line_end":1,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":null,"suggested_replacement":"fn main() {}
","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-short.rs:1:63: error[E0601]: `main` function not found in crate `json_short`
"}
{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
"}
17 changes: 5 additions & 12 deletions src/test/ui/main-wrong-location.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
error[E0601]: `main` function not found in crate `main_wrong_location`
--> $DIR/main-wrong-location.rs:1:1
|
LL | / mod m {
LL | |
LL | | // An inferred main entry point (that doesn't use #[main])
LL | | // must appear at the top of the crate
LL | | fn main() { }
LL | | }
| |_^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`)
|
note: here is a function named `main`
help: consider moving one of these function definitions to the crate root
--> $DIR/main-wrong-location.rs:5:5
|
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
help: define a function named `main` at the crate root
|
LL | fn main() {}
|

error: aborting due to previous error

Expand Down
7 changes: 6 additions & 1 deletion src/test/ui/missing/missing-main.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ error[E0601]: `main` function not found in crate `missing_main`
--> $DIR/missing-main.rs:2:1
|
LL | fn mian() { }
| ^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/missing-main.rs`
| ^
|
help: define a function named `main` at the crate root
|
LL | fn main() {}
|

error: aborting due to previous error

Expand Down
11 changes: 7 additions & 4 deletions src/test/ui/proc-macro/issue-59191-replace-root-with-fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ LL | #![issue_59191::no_main]
error[E0601]: `main` function not found in crate `issue_59191_replace_root_with_fn`
--> $DIR/issue-59191-replace-root-with-fn.rs:5:1
|
LL | / #![feature(custom_inner_attributes)]
LL | |
LL | | #![issue_59191::no_main]
| |________________________^ consider adding a `main` function to `$DIR/issue-59191-replace-root-with-fn.rs`
LL | #![feature(custom_inner_attributes)]
| ^
|
help: define a function named `main` at the crate root
|
LL | fn main() {}
|

error: aborting due to 2 previous errors

Expand Down