@@ -16,16 +16,16 @@ struct EntryContext<'a, 'tcx> {
16
16
17
17
map : & ' a hir_map:: Map < ' tcx > ,
18
18
19
- /// The top-level function called ' main' .
19
+ /// The top-level function called ` main` .
20
20
main_fn : Option < ( HirId , Span ) > ,
21
21
22
- /// The function that has attribute named ' main' .
22
+ /// The function that has attribute named ` main` .
23
23
attr_main_fn : Option < ( HirId , Span ) > ,
24
24
25
25
/// The function that has the attribute 'start' on it.
26
26
start_fn : Option < ( HirId , Span ) > ,
27
27
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.
29
29
/// main functions not defined at the top level. For diagnostics.
30
30
non_main_fns : Vec < ( HirId , Span ) > ,
31
31
}
@@ -88,7 +88,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
88
88
EntryPointType :: MainAttr
89
89
} else if item. ident . name == sym:: main {
90
90
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` .
92
92
EntryPointType :: MainNamed
93
93
} else {
94
94
EntryPointType :: OtherMain
@@ -109,7 +109,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
109
109
ctxt. main_fn = Some ( ( item. hir_id , item. span ) ) ;
110
110
} else {
111
111
span_err ! ( ctxt. session, item. span, E0136 ,
112
- "multiple ' main' functions" ) ;
112
+ "multiple ` main` functions" ) ;
113
113
}
114
114
} ,
115
115
EntryPointType :: OtherMain => {
@@ -130,7 +130,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
130
130
if ctxt. start_fn . is_none ( ) {
131
131
ctxt. start_fn = Some ( ( item. hir_id , item. span ) ) ;
132
132
} 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" )
134
134
. span_label ( ctxt. start_fn . unwrap ( ) . 1 , "previous `start` function here" )
135
135
. span_label ( item. span , "multiple `start` functions" )
136
136
. emit ( ) ;
@@ -148,34 +148,48 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De
148
148
} else if let Some ( ( hir_id, _) ) = visitor. main_fn {
149
149
Some ( ( tcx. hir ( ) . local_def_id ( hir_id) , EntryFnType :: Main ) )
150
150
} 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) ;
175
152
None
176
153
}
177
154
}
178
155
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
+
179
193
pub fn find_entry_point ( tcx : TyCtxt < ' _ > ) -> Option < ( DefId , EntryFnType ) > {
180
194
tcx. entry_fn ( LOCAL_CRATE )
181
195
}
0 commit comments