1
1
use hir:: map as hir_map;
2
- use hir:: def_id:: { CRATE_DEF_INDEX } ;
2
+ use hir:: def_id:: { CrateNum , CRATE_DEF_INDEX , DefId , LOCAL_CRATE } ;
3
3
use session:: { config, Session } ;
4
4
use session:: config:: EntryFnType ;
5
5
use syntax:: ast:: NodeId ;
@@ -8,6 +8,8 @@ use syntax::entry::EntryPointType;
8
8
use syntax_pos:: Span ;
9
9
use hir:: { Item , ItemKind , ImplItem , TraitItem } ;
10
10
use hir:: itemlikevisit:: ItemLikeVisitor ;
11
+ use ty:: TyCtxt ;
12
+ use ty:: query:: Providers ;
11
13
12
14
struct EntryContext < ' a , ' tcx : ' a > {
13
15
session : & ' a Session ,
@@ -45,36 +47,34 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
45
47
}
46
48
}
47
49
48
- pub fn find_entry_point ( session : & Session ,
49
- hir_map : & hir_map :: Map < ' _ > ,
50
- crate_name : & str ) {
51
- let any_exe = session . crate_types . borrow ( ) . iter ( ) . any ( |ty| {
50
+ fn entry_fn ( tcx : TyCtxt < ' _ , ' _ , ' _ > , cnum : CrateNum ) -> Option < ( DefId , EntryFnType ) > {
51
+ assert_eq ! ( cnum , LOCAL_CRATE ) ;
52
+
53
+ let any_exe = tcx . sess . crate_types . borrow ( ) . iter ( ) . any ( |ty| {
52
54
* ty == config:: CrateType :: Executable
53
55
} ) ;
54
56
if !any_exe {
55
57
// No need to find a main function
56
- session. entry_fn . set ( None ) ;
57
- return
58
+ return None ;
58
59
}
59
60
60
61
// If the user wants no main function at all, then stop here.
61
- if attr:: contains_name ( & hir_map. krate ( ) . attrs , "no_main" ) {
62
- session. entry_fn . set ( None ) ;
63
- return
62
+ if attr:: contains_name ( & tcx. hir ( ) . krate ( ) . attrs , "no_main" ) {
63
+ return None ;
64
64
}
65
65
66
66
let mut ctxt = EntryContext {
67
- session,
68
- map : hir_map ,
67
+ session : tcx . sess ,
68
+ map : tcx . hir ( ) ,
69
69
main_fn : None ,
70
70
attr_main_fn : None ,
71
71
start_fn : None ,
72
72
non_main_fns : Vec :: new ( ) ,
73
73
} ;
74
74
75
- hir_map . krate ( ) . visit_all_item_likes ( & mut ctxt) ;
75
+ tcx . hir ( ) . krate ( ) . visit_all_item_likes ( & mut ctxt) ;
76
76
77
- configure_main ( & mut ctxt , crate_name ) ;
77
+ configure_main ( tcx , & ctxt )
78
78
}
79
79
80
80
// Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep
@@ -135,43 +135,58 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
135
135
. span_label ( item. span , "multiple `start` functions" )
136
136
. emit ( ) ;
137
137
}
138
- } ,
139
- EntryPointType :: None => ( )
138
+ }
139
+ EntryPointType :: None => ( ) ,
140
140
}
141
141
}
142
142
143
- fn configure_main ( this : & mut EntryContext < ' _ , ' _ > , crate_name : & str ) {
144
- if let Some ( ( node_id, span) ) = this. start_fn {
145
- this. session . entry_fn . set ( Some ( ( node_id, span, EntryFnType :: Start ) ) ) ;
146
- } else if let Some ( ( node_id, span) ) = this. attr_main_fn {
147
- this. session . entry_fn . set ( Some ( ( node_id, span, EntryFnType :: Main ) ) ) ;
148
- } else if let Some ( ( node_id, span) ) = this. main_fn {
149
- this. session . entry_fn . set ( Some ( ( node_id, span, EntryFnType :: Main ) ) ) ;
143
+ fn configure_main (
144
+ tcx : TyCtxt < ' _ , ' _ , ' _ > ,
145
+ visitor : & EntryContext < ' _ , ' _ > ,
146
+ ) -> Option < ( DefId , EntryFnType ) > {
147
+ if let Some ( ( node_id, _) ) = visitor. start_fn {
148
+ Some ( ( tcx. hir ( ) . local_def_id ( node_id) , EntryFnType :: Start ) )
149
+ } else if let Some ( ( node_id, _) ) = visitor. attr_main_fn {
150
+ Some ( ( tcx. hir ( ) . local_def_id ( node_id) , EntryFnType :: Main ) )
151
+ } else if let Some ( ( node_id, _) ) = visitor. main_fn {
152
+ Some ( ( tcx. hir ( ) . local_def_id ( node_id) , EntryFnType :: Main ) )
150
153
} else {
151
154
// No main function
152
- this. session . entry_fn . set ( None ) ;
153
- let mut err = struct_err ! ( this. session, E0601 ,
154
- "`main` function not found in crate `{}`" , crate_name) ;
155
- if !this. non_main_fns . is_empty ( ) {
155
+ let mut err = struct_err ! ( tcx. sess, E0601 ,
156
+ "`main` function not found in crate `{}`" , tcx. crate_name( LOCAL_CRATE ) ) ;
157
+ if !visitor. non_main_fns . is_empty ( ) {
156
158
// There were some functions named 'main' though. Try to give the user a hint.
157
159
err. note ( "the main function must be defined at the crate level \
158
160
but you have one or more functions named 'main' that are not \
159
161
defined at the crate level. Either move the definition or \
160
162
attach the `#[main]` attribute to override this behavior.") ;
161
- for & ( _, span) in & this . non_main_fns {
163
+ for & ( _, span) in & visitor . non_main_fns {
162
164
err. span_note ( span, "here is a function named 'main'" ) ;
163
165
}
164
166
err. emit ( ) ;
165
- this . session . abort_if_errors ( ) ;
167
+ tcx . sess . abort_if_errors ( ) ;
166
168
} else {
167
- if let Some ( ref filename) = this . session . local_crate_source_file {
169
+ if let Some ( ref filename) = tcx . sess . local_crate_source_file {
168
170
err. note ( & format ! ( "consider adding a `main` function to `{}`" , filename. display( ) ) ) ;
169
171
}
170
- if this . session . teach ( & err. get_code ( ) . unwrap ( ) ) {
172
+ if tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
171
173
err. note ( "If you don't know the basics of Rust, you can go look to the Rust Book \
172
174
to get started: https://doc.rust-lang.org/book/") ;
173
175
}
174
176
err. emit ( ) ;
175
177
}
178
+
179
+ None
176
180
}
177
181
}
182
+
183
+ pub fn find_entry_point ( tcx : TyCtxt < ' _ , ' _ , ' _ > ) -> Option < ( DefId , EntryFnType ) > {
184
+ tcx. entry_fn ( LOCAL_CRATE )
185
+ }
186
+
187
+ pub fn provide ( providers : & mut Providers < ' _ > ) {
188
+ * providers = Providers {
189
+ entry_fn,
190
+ ..* providers
191
+ } ;
192
+ }
0 commit comments