@@ -3,18 +3,19 @@ use rustc_ast::ptr::P;
3
3
use rustc_ast:: token;
4
4
use rustc_ast:: tokenstream:: TokenStream ;
5
5
use rustc_ast_pretty:: pprust;
6
+ use rustc_data_structures:: sync:: Lrc ;
6
7
use rustc_expand:: base:: {
7
- check_zero_tts, get_single_str_from_tts, parse_expr , resolve_path , DummyResult , ExtCtxt ,
8
- MacEager , MacResult ,
8
+ check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts , parse_expr ,
9
+ resolve_path , DummyResult , ExtCtxt , MacEager , MacResult ,
9
10
} ;
10
11
use rustc_expand:: module:: DirOwnership ;
11
12
use rustc_parse:: new_parser_from_file;
12
13
use rustc_parse:: parser:: { ForceCollect , Parser } ;
13
14
use rustc_session:: lint:: builtin:: INCOMPLETE_INCLUDE ;
14
15
use rustc_span:: symbol:: Symbol ;
15
16
use rustc_span:: { Pos , Span } ;
16
-
17
17
use smallvec:: SmallVec ;
18
+ use std:: path:: Path ;
18
19
use std:: rc:: Rc ;
19
20
20
21
// These macros all relate to the file system; they either return
@@ -180,32 +181,22 @@ pub fn expand_include_str(
180
181
tts : TokenStream ,
181
182
) -> Box < dyn MacResult + ' static > {
182
183
let sp = cx. with_def_site_ctxt ( sp) ;
183
- let file = match get_single_str_from_tts ( cx, sp, tts, "include_str!" ) {
184
- Ok ( file ) => file ,
184
+ let ( path , path_span ) = match get_single_str_spanned_from_tts ( cx, sp, tts, "include_str!" ) {
185
+ Ok ( res ) => res ,
185
186
Err ( guar) => return DummyResult :: any ( sp, guar) ,
186
187
} ;
187
- let file = match resolve_path ( & cx. sess , file. as_str ( ) , sp) {
188
- Ok ( f) => f,
189
- Err ( err) => {
190
- let guar = err. emit ( ) ;
191
- return DummyResult :: any ( sp, guar) ;
192
- }
193
- } ;
194
- match cx. source_map ( ) . load_binary_file ( & file) {
188
+ match load_binary_file ( cx, path. as_str ( ) , sp, path_span) {
195
189
Ok ( bytes) => match std:: str:: from_utf8 ( & bytes) {
196
190
Ok ( src) => {
197
191
let interned_src = Symbol :: intern ( src) ;
198
192
MacEager :: expr ( cx. expr_str ( sp, interned_src) )
199
193
}
200
194
Err ( _) => {
201
- let guar = cx. dcx ( ) . span_err ( sp, format ! ( "{} wasn't a utf-8 file" , file . display ( ) ) ) ;
195
+ let guar = cx. dcx ( ) . span_err ( sp, format ! ( "{path } wasn't a utf-8 file" ) ) ;
202
196
DummyResult :: any ( sp, guar)
203
197
}
204
198
} ,
205
- Err ( e) => {
206
- let guar = cx. dcx ( ) . span_err ( sp, format ! ( "couldn't read {}: {}" , file. display( ) , e) ) ;
207
- DummyResult :: any ( sp, guar)
208
- }
199
+ Err ( dummy) => dummy,
209
200
}
210
201
}
211
202
@@ -215,25 +206,57 @@ pub fn expand_include_bytes(
215
206
tts : TokenStream ,
216
207
) -> Box < dyn MacResult + ' static > {
217
208
let sp = cx. with_def_site_ctxt ( sp) ;
218
- let file = match get_single_str_from_tts ( cx, sp, tts, "include_bytes!" ) {
219
- Ok ( file ) => file ,
209
+ let ( path , path_span ) = match get_single_str_spanned_from_tts ( cx, sp, tts, "include_bytes!" ) {
210
+ Ok ( res ) => res ,
220
211
Err ( guar) => return DummyResult :: any ( sp, guar) ,
221
212
} ;
222
- let file = match resolve_path ( & cx. sess , file. as_str ( ) , sp) {
223
- Ok ( f) => f,
224
- Err ( err) => {
225
- let guar = err. emit ( ) ;
226
- return DummyResult :: any ( sp, guar) ;
227
- }
228
- } ;
229
- match cx. source_map ( ) . load_binary_file ( & file) {
213
+ match load_binary_file ( cx, path. as_str ( ) , sp, path_span) {
230
214
Ok ( bytes) => {
231
215
let expr = cx. expr ( sp, ast:: ExprKind :: IncludedBytes ( bytes) ) ;
232
216
MacEager :: expr ( expr)
233
217
}
234
- Err ( e) => {
235
- let guar = cx. dcx ( ) . span_err ( sp, format ! ( "couldn't read {}: {}" , file. display( ) , e) ) ;
236
- DummyResult :: any ( sp, guar)
218
+ Err ( dummy) => dummy,
219
+ }
220
+ }
221
+
222
+ fn load_binary_file (
223
+ cx : & mut ExtCtxt < ' _ > ,
224
+ original_path : & str ,
225
+ macro_span : Span ,
226
+ path_span : Span ,
227
+ ) -> Result < Lrc < [ u8 ] > , Box < dyn MacResult > > {
228
+ let resolved_path = match resolve_path ( & cx. sess , original_path, macro_span) {
229
+ Ok ( path) => path,
230
+ Err ( err) => {
231
+ let guar = err. emit ( ) ;
232
+ return Err ( DummyResult :: any ( macro_span, guar) ) ;
233
+ }
234
+ } ;
235
+ match cx. source_map ( ) . load_binary_file ( & resolved_path) {
236
+ Ok ( data) => Ok ( data) ,
237
+ Err ( io_err) => {
238
+ let mut err = cx. dcx ( ) . struct_span_err (
239
+ macro_span,
240
+ format ! ( "couldn't read {}: {io_err}" , resolved_path. display( ) ) ,
241
+ ) ;
242
+ if Path :: new ( original_path) . is_relative ( ) {
243
+ for prefix in [ ".." , "../.." ] {
244
+ let parent_path = Path :: new ( prefix) . join ( original_path) ;
245
+ if resolve_path ( & cx. sess , & parent_path, macro_span)
246
+ . map_or ( false , |p| p. exists ( ) )
247
+ {
248
+ err. span_suggestion (
249
+ path_span,
250
+ "it's in a parent directory" ,
251
+ format ! ( "\" {}\" " , parent_path. display( ) . to_string( ) . escape_debug( ) ) ,
252
+ rustc_lint_defs:: Applicability :: MachineApplicable ,
253
+ ) ;
254
+ break ;
255
+ }
256
+ }
257
+ }
258
+ let guar = err. emit ( ) ;
259
+ Err ( DummyResult :: any ( macro_span, guar) )
237
260
}
238
261
}
239
262
}
0 commit comments