1
1
use rustc_ast:: entry:: EntryPointType ;
2
2
use rustc_errors:: struct_span_err;
3
+ use rustc_hir:: def:: DefKind ;
3
4
use rustc_hir:: def_id:: { DefId , LocalDefId , CRATE_DEF_ID , LOCAL_CRATE } ;
4
- use rustc_hir:: { Item , ItemKind , Node , CRATE_HIR_ID } ;
5
+ use rustc_hir:: { ItemId , Node , CRATE_HIR_ID } ;
5
6
use rustc_middle:: ty:: query:: Providers ;
6
7
use rustc_middle:: ty:: { DefIdTree , TyCtxt } ;
7
8
use rustc_session:: config:: { CrateType , EntryFnType } ;
@@ -40,30 +41,34 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
40
41
EntryContext { tcx, attr_main_fn : None , start_fn : None , non_main_fns : Vec :: new ( ) } ;
41
42
42
43
for id in tcx. hir ( ) . items ( ) {
43
- let item = tcx. hir ( ) . item ( id) ;
44
- find_item ( item, & mut ctxt) ;
44
+ find_item ( id, & mut ctxt) ;
45
45
}
46
46
47
47
configure_main ( tcx, & ctxt)
48
48
}
49
49
50
50
// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
51
51
// (with `ast::Item`), so make sure to keep them in sync.
52
- fn entry_point_type ( ctxt : & EntryContext < ' _ > , item : & Item < ' _ > , at_root : bool ) -> EntryPointType {
53
- let attrs = ctxt. tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
52
+ // A small optimization was added so that hir::Item is fetched only when needed.
53
+ // An equivalent optimization was not applied to the duplicated code in test_harness.rs.
54
+ fn entry_point_type ( ctxt : & EntryContext < ' _ > , id : ItemId , at_root : bool ) -> EntryPointType {
55
+ let attrs = ctxt. tcx . hir ( ) . attrs ( id. hir_id ( ) ) ;
54
56
if ctxt. tcx . sess . contains_name ( attrs, sym:: start) {
55
57
EntryPointType :: Start
56
58
} else if ctxt. tcx . sess . contains_name ( attrs, sym:: rustc_main) {
57
59
EntryPointType :: MainAttr
58
- } else if item. ident . name == sym:: main {
59
- if at_root {
60
- // This is a top-level function so can be `main`.
61
- EntryPointType :: MainNamed
60
+ } else {
61
+ let item = ctxt. tcx . hir ( ) . item ( id) ;
62
+ if item. ident . name == sym:: main {
63
+ if at_root {
64
+ // This is a top-level function so can be `main`.
65
+ EntryPointType :: MainNamed
66
+ } else {
67
+ EntryPointType :: OtherMain
68
+ }
62
69
} else {
63
- EntryPointType :: OtherMain
70
+ EntryPointType :: None
64
71
}
65
- } else {
66
- EntryPointType :: None
67
72
}
68
73
}
69
74
@@ -72,13 +77,13 @@ fn throw_attr_err(sess: &Session, span: Span, attr: &str) {
72
77
. emit ( ) ;
73
78
}
74
79
75
- fn find_item ( item : & Item < ' _ > , ctxt : & mut EntryContext < ' _ > ) {
76
- let at_root = ctxt. tcx . opt_local_parent ( item . def_id ) == Some ( CRATE_DEF_ID ) ;
80
+ fn find_item ( id : ItemId , ctxt : & mut EntryContext < ' _ > ) {
81
+ let at_root = ctxt. tcx . opt_local_parent ( id . def_id ) == Some ( CRATE_DEF_ID ) ;
77
82
78
- match entry_point_type ( ctxt, item , at_root) {
83
+ match entry_point_type ( ctxt, id , at_root) {
79
84
EntryPointType :: None => ( ) ,
80
- _ if !matches ! ( item . kind , ItemKind :: Fn ( .. ) ) => {
81
- let attrs = ctxt. tcx . hir ( ) . attrs ( item . hir_id ( ) ) ;
85
+ _ if !matches ! ( ctxt . tcx . hir ( ) . def_kind ( id . def_id ) , DefKind :: Fn ) => {
86
+ let attrs = ctxt. tcx . hir ( ) . attrs ( id . hir_id ( ) ) ;
82
87
if let Some ( attr) = ctxt. tcx . sess . find_by_name ( attrs, sym:: start) {
83
88
throw_attr_err ( & ctxt. tcx . sess , attr. span , "start" ) ;
84
89
}
@@ -88,31 +93,39 @@ fn find_item(item: &Item<'_>, ctxt: &mut EntryContext<'_>) {
88
93
}
89
94
EntryPointType :: MainNamed => ( ) ,
90
95
EntryPointType :: OtherMain => {
91
- ctxt. non_main_fns . push ( item . span ) ;
96
+ ctxt. non_main_fns . push ( ctxt . tcx . def_span ( id . def_id . to_def_id ( ) ) ) ;
92
97
}
93
98
EntryPointType :: MainAttr => {
94
99
if ctxt. attr_main_fn . is_none ( ) {
95
- ctxt. attr_main_fn = Some ( ( item . def_id , item . span ) ) ;
100
+ ctxt. attr_main_fn = Some ( ( id . def_id , ctxt . tcx . def_span ( id . def_id . to_def_id ( ) ) ) ) ;
96
101
} else {
97
102
struct_span_err ! (
98
103
ctxt. tcx. sess,
99
- item . span ,
104
+ ctxt . tcx . def_span ( id . def_id . to_def_id ( ) ) ,
100
105
E0137 ,
101
106
"multiple functions with a `#[main]` attribute"
102
107
)
103
- . span_label ( item. span , "additional `#[main]` function" )
108
+ . span_label (
109
+ ctxt. tcx . def_span ( id. def_id . to_def_id ( ) ) ,
110
+ "additional `#[main]` function" ,
111
+ )
104
112
. span_label ( ctxt. attr_main_fn . unwrap ( ) . 1 , "first `#[main]` function" )
105
113
. emit ( ) ;
106
114
}
107
115
}
108
116
EntryPointType :: Start => {
109
117
if ctxt. start_fn . is_none ( ) {
110
- ctxt. start_fn = Some ( ( item . def_id , item . span ) ) ;
118
+ ctxt. start_fn = Some ( ( id . def_id , ctxt . tcx . def_span ( id . def_id . to_def_id ( ) ) ) ) ;
111
119
} else {
112
- struct_span_err ! ( ctxt. tcx. sess, item. span, E0138 , "multiple `start` functions" )
113
- . span_label ( ctxt. start_fn . unwrap ( ) . 1 , "previous `#[start]` function here" )
114
- . span_label ( item. span , "multiple `start` functions" )
115
- . emit ( ) ;
120
+ struct_span_err ! (
121
+ ctxt. tcx. sess,
122
+ ctxt. tcx. def_span( id. def_id. to_def_id( ) ) ,
123
+ E0138 ,
124
+ "multiple `start` functions"
125
+ )
126
+ . span_label ( ctxt. start_fn . unwrap ( ) . 1 , "previous `#[start]` function here" )
127
+ . span_label ( ctxt. tcx . def_span ( id. def_id . to_def_id ( ) ) , "multiple `start` functions" )
128
+ . emit ( ) ;
116
129
}
117
130
}
118
131
}
0 commit comments