1
- use rustc_ast:: { entry:: EntryPointType , Attribute } ;
1
+ use rustc_ast:: entry:: EntryPointType ;
2
2
use rustc_errors:: struct_span_err;
3
3
use rustc_hir:: def:: DefKind ;
4
4
use rustc_hir:: def_id:: { DefId , LocalDefId , CRATE_DEF_ID , LOCAL_CRATE } ;
5
5
use rustc_hir:: { ItemId , Node , CRATE_HIR_ID } ;
6
6
use rustc_middle:: ty:: query:: Providers ;
7
7
use rustc_middle:: ty:: { DefIdTree , TyCtxt } ;
8
- use rustc_session:: config:: { CrateType , EntryFnType } ;
8
+ use rustc_session:: config:: { sigpipe , CrateType , EntryFnType } ;
9
9
use rustc_session:: parse:: feature_err;
10
10
use rustc_span:: symbol:: sym;
11
11
use rustc_span:: { Span , Symbol , DUMMY_SP } ;
@@ -71,14 +71,12 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
71
71
}
72
72
}
73
73
74
- fn err_if_attr_found ( ctxt : & EntryContext < ' _ > , attrs : & [ Attribute ] , sym : Symbol ) {
74
+ fn err_if_attr_found ( ctxt : & EntryContext < ' _ > , id : ItemId , sym : Symbol , details : & str ) {
75
+ let attrs = ctxt. tcx . hir ( ) . attrs ( id. hir_id ( ) ) ;
75
76
if let Some ( attr) = ctxt. tcx . sess . find_by_name ( attrs, sym) {
76
77
ctxt. tcx
77
78
. sess
78
- . struct_span_err (
79
- attr. span ,
80
- & format ! ( "`{}` attribute can only be used on functions" , sym) ,
81
- )
79
+ . struct_span_err ( attr. span , & format ! ( "`{}` attribute {}" , sym, details) )
82
80
. emit ( ) ;
83
81
}
84
82
}
@@ -87,14 +85,16 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
87
85
let at_root = ctxt. tcx . opt_local_parent ( id. def_id ) == Some ( CRATE_DEF_ID ) ;
88
86
89
87
match entry_point_type ( ctxt, id, at_root) {
90
- EntryPointType :: None => ( ) ,
88
+ EntryPointType :: None => {
89
+ err_if_attr_found ( ctxt, id, sym:: unix_sigpipe, "can only be used on `fn main()`" ) ;
90
+ }
91
91
_ if !matches ! ( ctxt. tcx. def_kind( id. def_id) , DefKind :: Fn ) => {
92
- let attrs = ctxt. tcx . hir ( ) . attrs ( id. hir_id ( ) ) ;
93
- err_if_attr_found ( ctxt, attrs, sym:: start) ;
94
- err_if_attr_found ( ctxt, attrs, sym:: rustc_main) ;
92
+ err_if_attr_found ( ctxt, id, sym:: start, "can only be used on functions" ) ;
93
+ err_if_attr_found ( ctxt, id, sym:: rustc_main, "can only be used on functions" ) ;
95
94
}
96
95
EntryPointType :: MainNamed => ( ) ,
97
96
EntryPointType :: OtherMain => {
97
+ err_if_attr_found ( ctxt, id, sym:: unix_sigpipe, "can only be used on root `fn main()`" ) ;
98
98
ctxt. non_main_fns . push ( ctxt. tcx . def_span ( id. def_id ) ) ;
99
99
}
100
100
EntryPointType :: RustcMainAttr => {
@@ -116,6 +116,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
116
116
}
117
117
}
118
118
EntryPointType :: Start => {
119
+ err_if_attr_found ( ctxt, id, sym:: unix_sigpipe, "can only be used on `fn main()`" ) ;
119
120
if ctxt. start_fn . is_none ( ) {
120
121
ctxt. start_fn = Some ( ( id. def_id , ctxt. tcx . def_span ( id. def_id . to_def_id ( ) ) ) ) ;
121
122
} else {
@@ -136,8 +137,9 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
136
137
fn configure_main ( tcx : TyCtxt < ' _ > , visitor : & EntryContext < ' _ > ) -> Option < ( DefId , EntryFnType ) > {
137
138
if let Some ( ( def_id, _) ) = visitor. start_fn {
138
139
Some ( ( def_id. to_def_id ( ) , EntryFnType :: Start ) )
139
- } else if let Some ( ( def_id, _) ) = visitor. attr_main_fn {
140
- Some ( ( def_id. to_def_id ( ) , EntryFnType :: Main ) )
140
+ } else if let Some ( ( local_def_id, _) ) = visitor. attr_main_fn {
141
+ let def_id = local_def_id. to_def_id ( ) ;
142
+ Some ( ( def_id, EntryFnType :: Main { sigpipe : sigpipe ( tcx, def_id) } ) )
141
143
} else {
142
144
if let Some ( main_def) = tcx. resolutions ( ( ) ) . main_def && let Some ( def_id) = main_def. opt_fn_def_id ( ) {
143
145
// non-local main imports are handled below
@@ -161,13 +163,39 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
161
163
)
162
164
. emit ( ) ;
163
165
}
164
- return Some ( ( def_id, EntryFnType :: Main ) ) ;
166
+ return Some ( ( def_id, EntryFnType :: Main { sigpipe : sigpipe ( tcx , def_id ) } ) ) ;
165
167
}
166
168
no_main_err ( tcx, visitor) ;
167
169
None
168
170
}
169
171
}
170
172
173
+ fn sigpipe ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> u8 {
174
+ if let Some ( attr) = tcx. get_attr ( def_id, sym:: unix_sigpipe) {
175
+ match ( attr. value_str ( ) , attr. meta_item_list ( ) ) {
176
+ ( Some ( sym:: inherit) , None ) => sigpipe:: INHERIT ,
177
+ ( Some ( sym:: sig_ign) , None ) => sigpipe:: SIG_IGN ,
178
+ ( Some ( sym:: sig_dfl) , None ) => sigpipe:: SIG_DFL ,
179
+ ( _, Some ( _) ) => {
180
+ // Keep going so that `fn emit_malformed_attribute()` can print
181
+ // an excellent error message
182
+ sigpipe:: DEFAULT
183
+ }
184
+ _ => {
185
+ tcx. sess
186
+ . struct_span_err (
187
+ attr. span ,
188
+ "valid values for `#[unix_sigpipe = \" ...\" ]` are `inherit`, `sig_ign`, or `sig_dfl`" ,
189
+ )
190
+ . emit ( ) ;
191
+ sigpipe:: DEFAULT
192
+ }
193
+ }
194
+ } else {
195
+ sigpipe:: DEFAULT
196
+ }
197
+ }
198
+
171
199
fn no_main_err ( tcx : TyCtxt < ' _ > , visitor : & EntryContext < ' _ > ) {
172
200
let sp = tcx. def_span ( CRATE_DEF_ID ) ;
173
201
if * tcx. sess . parse_sess . reached_eof . borrow ( ) {
0 commit comments