@@ -10,7 +10,7 @@ use rustc_ast::{self as ast, Attribute, HasAttrs, Item, NodeId, PatKind};
10
10
use rustc_attr:: { self as attr, Deprecation , Stability } ;
11
11
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
12
12
use rustc_data_structures:: sync:: { self , Lrc } ;
13
- use rustc_errors:: { Applicability , DiagnosticBuilder , ErrorGuaranteed , MultiSpan } ;
13
+ use rustc_errors:: { Applicability , DiagnosticBuilder , ErrorGuaranteed , MultiSpan , PResult } ;
14
14
use rustc_lint_defs:: builtin:: PROC_MACRO_BACK_COMPAT ;
15
15
use rustc_lint_defs:: BuiltinLintDiagnostics ;
16
16
use rustc_parse:: { self , parser, to_token_stream, MACRO_ARGUMENTS } ;
@@ -20,7 +20,7 @@ use rustc_span::edition::Edition;
20
20
use rustc_span:: hygiene:: { AstPass , ExpnData , ExpnKind , LocalExpnId } ;
21
21
use rustc_span:: source_map:: SourceMap ;
22
22
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
23
- use rustc_span:: { Span , DUMMY_SP } ;
23
+ use rustc_span:: { FileName , Span , DUMMY_SP } ;
24
24
use smallvec:: { smallvec, SmallVec } ;
25
25
26
26
use std:: default:: Default ;
@@ -1137,6 +1137,43 @@ impl<'a> ExtCtxt<'a> {
1137
1137
}
1138
1138
}
1139
1139
1140
+ /// Resolves a `path` mentioned inside Rust code, returning an absolute path.
1141
+ ///
1142
+ /// This unifies the logic used for resolving `include_X!`.
1143
+ pub fn resolve_path (
1144
+ parse_sess : & ParseSess ,
1145
+ path : impl Into < PathBuf > ,
1146
+ span : Span ,
1147
+ ) -> PResult < ' _ , PathBuf > {
1148
+ let path = path. into ( ) ;
1149
+
1150
+ // Relative paths are resolved relative to the file in which they are found
1151
+ // after macro expansion (that is, they are unhygienic).
1152
+ if !path. is_absolute ( ) {
1153
+ let callsite = span. source_callsite ( ) ;
1154
+ let mut result = match parse_sess. source_map ( ) . span_to_filename ( callsite) {
1155
+ FileName :: Real ( name) => name
1156
+ . into_local_path ( )
1157
+ . expect ( "attempting to resolve a file path in an external file" ) ,
1158
+ FileName :: DocTest ( path, _) => path,
1159
+ other => {
1160
+ return Err ( parse_sess. span_diagnostic . struct_span_err (
1161
+ span,
1162
+ & format ! (
1163
+ "cannot resolve relative path in non-file source `{}`" ,
1164
+ parse_sess. source_map( ) . filename_for_diagnostics( & other)
1165
+ ) ,
1166
+ ) ) ;
1167
+ }
1168
+ } ;
1169
+ result. pop ( ) ;
1170
+ result. push ( path) ;
1171
+ Ok ( result)
1172
+ } else {
1173
+ Ok ( path)
1174
+ }
1175
+ }
1176
+
1140
1177
/// Extracts a string literal from the macro expanded version of `expr`,
1141
1178
/// returning a diagnostic error of `err_msg` if `expr` is not a string literal.
1142
1179
/// The returned bool indicates whether an applicable suggestion has already been
0 commit comments