Skip to content

Commit 2834212

Browse files
authored
Rollup merge of rust-lang#64290 - Mark-Simulacrum:span-no-main, r=estebank
Provide a span if main function is not present in crate Unfortunately, the diagnostic machinery does not cope well with an empty span which can happen if the crate is empty, in which case we merely set a spanless note. Tests are already updated for this change, so a dedicated test is not added. Resolves rust-lang#36561.
2 parents 47af328 + 6dc1483 commit 2834212

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+167
-125
lines changed

src/librustc/middle/entry.rs

+44-30
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ struct EntryContext<'a, 'tcx> {
1616

1717
map: &'a hir_map::Map<'tcx>,
1818

19-
/// The top-level function called 'main'.
19+
/// The top-level function called `main`.
2020
main_fn: Option<(HirId, Span)>,
2121

22-
/// The function that has attribute named 'main'.
22+
/// The function that has attribute named `main`.
2323
attr_main_fn: Option<(HirId, Span)>,
2424

2525
/// The function that has the attribute 'start' on it.
2626
start_fn: Option<(HirId, Span)>,
2727

28-
/// The functions that one might think are 'main' but aren't, e.g.
28+
/// The functions that one might think are `main` but aren't, e.g.
2929
/// main functions not defined at the top level. For diagnostics.
3030
non_main_fns: Vec<(HirId, Span)> ,
3131
}
@@ -88,7 +88,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
8888
EntryPointType::MainAttr
8989
} else if item.ident.name == sym::main {
9090
if at_root {
91-
// This is a top-level function so can be 'main'.
91+
// This is a top-level function so can be `main`.
9292
EntryPointType::MainNamed
9393
} else {
9494
EntryPointType::OtherMain
@@ -109,7 +109,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
109109
ctxt.main_fn = Some((item.hir_id, item.span));
110110
} else {
111111
span_err!(ctxt.session, item.span, E0136,
112-
"multiple 'main' functions");
112+
"multiple `main` functions");
113113
}
114114
},
115115
EntryPointType::OtherMain => {
@@ -130,7 +130,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
130130
if ctxt.start_fn.is_none() {
131131
ctxt.start_fn = Some((item.hir_id, item.span));
132132
} else {
133-
struct_span_err!(ctxt.session, item.span, E0138, "multiple 'start' functions")
133+
struct_span_err!(ctxt.session, item.span, E0138, "multiple `start` functions")
134134
.span_label(ctxt.start_fn.unwrap().1, "previous `start` function here")
135135
.span_label(item.span, "multiple `start` functions")
136136
.emit();
@@ -148,34 +148,48 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
148148
} else if let Some((hir_id, _)) = visitor.main_fn {
149149
Some((tcx.hir().local_def_id(hir_id), EntryFnType::Main))
150150
} else {
151-
// There is no main function.
152-
let mut err = struct_err!(tcx.sess, E0601,
153-
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
154-
if !visitor.non_main_fns.is_empty() {
155-
// There were some functions named 'main' though. Try to give the user a hint.
156-
err.note("the main function must be defined at the crate level \
157-
but you have one or more functions named 'main' that are not \
158-
defined at the crate level. Either move the definition or \
159-
attach the `#[main]` attribute to override this behavior.");
160-
for &(_, span) in &visitor.non_main_fns {
161-
err.span_note(span, "here is a function named 'main'");
162-
}
163-
err.emit();
164-
} else {
165-
if let Some(ref filename) = tcx.sess.local_crate_source_file {
166-
err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
167-
}
168-
if tcx.sess.teach(&err.get_code().unwrap()) {
169-
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
170-
to get started: https://doc.rust-lang.org/book/");
171-
}
172-
err.emit();
173-
}
174-
151+
no_main_err(tcx, visitor);
175152
None
176153
}
177154
}
178155

156+
fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) {
157+
// There is no main function.
158+
let mut err = struct_err!(tcx.sess, E0601,
159+
"`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
160+
let filename = &tcx.sess.local_crate_source_file;
161+
let note = if !visitor.non_main_fns.is_empty() {
162+
for &(_, span) in &visitor.non_main_fns {
163+
err.span_note(span, "here is a function named `main`");
164+
}
165+
err.note("you have one or more functions named `main` not defined at the crate level");
166+
err.help("either move the `main` function definitions or attach the `#[main]` attribute \
167+
to one of them");
168+
// There were some functions named `main` though. Try to give the user a hint.
169+
format!("the main function must be defined at the crate level{}",
170+
filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default())
171+
} else if let Some(filename) = filename {
172+
format!("consider adding a `main` function to `{}`", filename.display())
173+
} else {
174+
String::from("consider adding a `main` function at the crate level")
175+
};
176+
let sp = tcx.hir().krate().span;
177+
// The file may be empty, which leads to the diagnostic machinery not emitting this
178+
// note. This is a relatively simple way to detect that case and emit a span-less
179+
// note instead.
180+
if let Ok(_) = tcx.sess.source_map().lookup_line(sp.lo()) {
181+
err.set_span(sp);
182+
err.span_label(sp, &note);
183+
} else {
184+
err.note(&note);
185+
}
186+
if tcx.sess.teach(&err.get_code().unwrap()) {
187+
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
188+
to get started: https://doc.rust-lang.org/book/");
189+
}
190+
err.emit();
191+
}
192+
179193
pub fn find_entry_point(tcx: TyCtxt<'_>) -> Option<(DefId, EntryFnType)> {
180194
tcx.entry_fn(LOCAL_CRATE)
181195
}

src/test/ui-fulldeps/hash-stable-is-unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ use rustc_macros::HashStable;
1313
#[derive(HashStable)]
1414
//~^ use of unstable library feature 'rustc_private'
1515
struct Test;
16+
17+
fn main() {}

src/test/ui-fulldeps/hash-stable-is-unstable.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
error[E0601]: `main` function not found in crate `hash_stable_is_unstable`
2-
|
3-
= note: consider adding a `main` function to `$DIR/hash-stable-is-unstable.rs`
4-
51
error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
62
--> $DIR/hash-stable-is-unstable.rs:3:1
73
|
@@ -47,7 +43,6 @@ LL | #[derive(HashStable)]
4743
= note: for more information, see https://github.com/rust-lang/rust/issues/27812
4844
= help: add `#![feature(rustc_private)]` to the crate attributes to enable
4945

50-
error: aborting due to 6 previous errors
46+
error: aborting due to 5 previous errors
5147

52-
Some errors have detailed explanations: E0601, E0658.
53-
For more information about an error, try `rustc --explain E0601`.
48+
For more information about this error, try `rustc --explain E0658`.

src/test/ui/associated-type-bounds/inside-adt.rs

+2
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,5 @@ union U2 { f: Box<dyn Iterator<Item: Copy>> }
3131
union U3 { f: dyn Iterator<Item: 'static> }
3232
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
3333
//~| ERROR could not find defining uses
34+
35+
fn main() {}

src/test/ui/associated-type-bounds/inside-adt.stderr

+1-6
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ error: associated type bounds are not allowed within structs, enums, or unions
5252
LL | union U3 { f: dyn Iterator<Item: 'static> }
5353
| ^^^^^^^^^^^^^
5454

55-
error[E0601]: `main` function not found in crate `inside_adt`
56-
|
57-
= note: consider adding a `main` function to `$DIR/inside-adt.rs`
58-
5955
error: could not find defining uses
6056
--> $DIR/inside-adt.rs:5:29
6157
|
@@ -110,6 +106,5 @@ error: could not find defining uses
110106
LL | union U3 { f: dyn Iterator<Item: 'static> }
111107
| ^^^^^^^^^^^^^
112108

113-
error: aborting due to 19 previous errors
109+
error: aborting due to 18 previous errors
114110

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

src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0601]: `main` function not found in crate `cfg_attr_cfg_2`
2+
--> $DIR/cfg-attr-cfg-2.rs:8:1
23
|
3-
= note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
4+
LL | / #[cfg_attr(foo, cfg(bar))]
5+
LL | | fn main() { }
6+
| |_____________^ consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs`
47

58
error: aborting due to previous error
69

src/test/ui/conditional-compilation/cfg-in-crate-1.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0601]: `main` function not found in crate `cfg_in_crate_1`
2+
--> $DIR/cfg-in-crate-1.rs:3:1
23
|
3-
= note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
4+
LL | #![cfg(bar)]
5+
| ^^^^^^^^^^^^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs`
46

57
error: aborting due to previous error
68

src/test/ui/continue-after-missing-main.stderr

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
error[E0601]: `main` function not found in crate `continue_after_missing_main`
2+
--> $DIR/continue-after-missing-main.rs:1:1
23
|
3-
= note: consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
4+
LL | / #![allow(dead_code)]
5+
LL | |
6+
LL | | // error-pattern:`main` function not found in crate
7+
LL | |
8+
... |
9+
LL | |
10+
LL | | }
11+
| |_^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs`
412

513
error[E0623]: lifetime mismatch
614
--> $DIR/continue-after-missing-main.rs:30:56

src/test/ui/elided-test.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
error[E0601]: `main` function not found in crate `elided_test`
2+
--> $DIR/elided-test.rs:5:1
23
|
3-
= note: consider adding a `main` function to `$DIR/elided-test.rs`
4+
LL | / #[test]
5+
LL | | fn main() {
6+
LL | | }
7+
| |_^ consider adding a `main` function to `$DIR/elided-test.rs`
48

59
error: aborting due to previous error
610

src/test/ui/error-codes/E0138.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0138]: multiple 'start' functions
1+
error[E0138]: multiple `start` functions
22
--> $DIR/E0138.rs:7:1
33
|
44
LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 }

src/test/ui/error-codes/E0601.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
// Test for main function not found.
1+
//~ ERROR `main` function not found

src/test/ui/error-codes/E0601.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0601]: `main` function not found in crate `E0601`
2+
--> $DIR/E0601.rs:1:37
23
|
3-
= note: consider adding a `main` function to `$DIR/E0601.rs`
4+
LL |
5+
| ^ consider adding a `main` function to `$DIR/E0601.rs`
46

57
error: aborting due to previous error
68

src/test/ui/issues/issue-46101.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
trait Foo {}
33
#[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
44
struct S;
5+
6+
fn main() {}

src/test/ui/issues/issue-46101.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@ error[E0433]: failed to resolve: partially resolved path in a derive macro
44
LL | #[derive(Foo::Anything)]
55
| ^^^^^^^^^^^^^ partially resolved path in a derive macro
66

7-
error[E0601]: `main` function not found in crate `issue_46101`
8-
|
9-
= note: consider adding a `main` function to `$DIR/issue-46101.rs`
10-
11-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
128

13-
Some errors have detailed explanations: E0433, E0601.
14-
For more information about an error, try `rustc --explain E0433`.
9+
For more information about this error, try `rustc --explain E0433`.

src/test/ui/issues/issue-49040.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
#![allow(unused_variables)]; //~ ERROR expected item, found `;`
2+
//~^ ERROR `main` function
23
fn foo() {}

src/test/ui/issues/issue-49040.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ LL | #![allow(unused_variables)];
55
| ^ help: remove this semicolon
66

77
error[E0601]: `main` function not found in crate `issue_49040`
8+
--> $DIR/issue-49040.rs:1:1
89
|
9-
= note: consider adding a `main` function to `$DIR/issue-49040.rs`
10+
LL | / #![allow(unused_variables)];
11+
LL | |
12+
LL | | fn foo() {}
13+
| |__^ consider adding a `main` function to `$DIR/issue-49040.rs`
1014

1115
error: aborting due to 2 previous errors
1216

src/test/ui/issues/issue-60057.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ impl A {
1515
}
1616
}
1717
}
18+
19+
fn main() {}

src/test/ui/issues/issue-60057.stderr

+2-7
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@ error[E0425]: cannot find value `banana` in this scope
1010
LL | banana: banana
1111
| ^^^^^^ help: you might have meant to use the available field: `self.banana`
1212

13-
error[E0601]: `main` function not found in crate `issue_60057`
14-
|
15-
= note: consider adding a `main` function to `$DIR/issue-60057.rs`
16-
17-
error: aborting due to 3 previous errors
13+
error: aborting due to 2 previous errors
1814

19-
Some errors have detailed explanations: E0425, E0601.
20-
For more information about an error, try `rustc --explain E0425`.
15+
For more information about this error, try `rustc --explain E0425`.

src/test/ui/json-short.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn main() {
1111

1212
If you don't know the basics of Rust, you can go look to the Rust Book to get
1313
started: https://doc.rust-lang.org/book/
14-
"},"level":"error","spans":[],"children":[{"message":"consider adding a `main` function to `$DIR/json-short.rs`","code":null,"level":"note","spans":[],"children":[],"rendered":null}],"rendered":"error[E0601]: `main` function not found in crate `json_short`
14+
"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":76,"byte_end":76,"line_start":2,"line_end":2,"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:2:63: error[E0601]: `main` function not found in crate `json_short`
1515
"}
1616
{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
1717
"}

src/test/ui/lifetime-before-type-params.rs

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ fn third<T, U, 'a>() {}
77
//~^ ERROR lifetime parameters must be declared prior to type parameters
88
fn fourth<'a, T, 'b, U, 'c, V>() {}
99
//~^ ERROR lifetime parameters must be declared prior to type parameters
10+
11+
fn main() {}

src/test/ui/lifetime-before-type-params.stderr

+1-6
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,5 @@ error: lifetime parameters must be declared prior to type parameters
2222
LL | fn fourth<'a, T, 'b, U, 'c, V>() {}
2323
| --------^^-----^^---- help: reorder the parameters: lifetimes, then types: `<'a, 'b, 'c, T, U, V>`
2424

25-
error[E0601]: `main` function not found in crate `lifetime_before_type_params`
26-
|
27-
= note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs`
28-
29-
error: aborting due to 5 previous errors
25+
error: aborting due to 4 previous errors
3026

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

src/test/ui/main-wrong-location.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod m {
2+
//~^ ERROR `main` function not found
23
// An inferred main entry point (that doesn't use #[main])
34
// must appear at the top of the crate
45
fn main() { }

src/test/ui/main-wrong-location.stderr

+13-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
error[E0601]: `main` function not found in crate `main_wrong_location`
2+
--> $DIR/main-wrong-location.rs:1:1
23
|
3-
= note: the main function must be defined at the crate level but you have one or more functions named 'main' that are not defined at the crate level. Either move the definition or attach the `#[main]` attribute to override this behavior.
4-
note: here is a function named 'main'
5-
--> $DIR/main-wrong-location.rs:4:5
4+
LL | / mod m {
5+
LL | |
6+
LL | | // An inferred main entry point (that doesn't use #[main])
7+
LL | | // must appear at the top of the crate
8+
LL | | fn main() { }
9+
LL | | }
10+
| |_^ the main function must be defined at the crate level (in `$DIR/main-wrong-location.rs`)
11+
|
12+
note: here is a function named `main`
13+
--> $DIR/main-wrong-location.rs:5:5
614
|
715
LL | fn main() { }
816
| ^^^^^^^^^^^^^
17+
= note: you have one or more functions named `main` not defined at the crate level
18+
= help: either move the `main` function definitions or attach the `#[main]` attribute to one of them
919

1020
error: aborting due to previous error
1121

src/test/ui/missing/missing-main.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
error[E0601]: `main` function not found in crate `missing_main`
2+
--> $DIR/missing-main.rs:2:1
23
|
3-
= note: consider adding a `main` function to `$DIR/missing-main.rs`
4+
LL | fn mian() { }
5+
| ^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/missing-main.rs`
46

57
error: aborting due to previous error
68

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

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

55
trait Foo {
6+
//~^ ERROR `main` function not found
67
fn bar() {
78
let x = foo();
89
//~^ ERROR cannot find function `foo` in this scope

0 commit comments

Comments
 (0)