diff options
Diffstat (limited to 'compiler/rustc_expand/src/base.rs')
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index ae1b50a4176..2b30ec601a0 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -10,7 +10,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind}; use rustc_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult}; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS}; @@ -20,7 +20,7 @@ use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::{FileName, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::default::Default; @@ -1136,6 +1136,43 @@ impl<'a> ExtCtxt<'a> { } } +/// Resolves a `path` mentioned inside Rust code, returning an absolute path. +/// +/// This unifies the logic used for resolving `include_X!`. +pub fn resolve_path( + parse_sess: &ParseSess, + path: impl Into<PathBuf>, + span: Span, +) -> PResult<'_, PathBuf> { + let path = path.into(); + + // Relative paths are resolved relative to the file in which they are found + // after macro expansion (that is, they are unhygienic). + if !path.is_absolute() { + let callsite = span.source_callsite(); + let mut result = match parse_sess.source_map().span_to_filename(callsite) { + FileName::Real(name) => name + .into_local_path() + .expect("attempting to resolve a file path in an external file"), + FileName::DocTest(path, _) => path, + other => { + return Err(parse_sess.span_diagnostic.struct_span_err( + span, + &format!( + "cannot resolve relative path in non-file source `{}`", + parse_sess.source_map().filename_for_diagnostics(&other) + ), + )); + } + }; + result.pop(); + result.push(path); + Ok(result) + } else { + Ok(path) + } +} + /// Extracts a string literal from the macro expanded version of `expr`, /// returning a diagnostic error of `err_msg` if `expr` is not a string literal. /// The returned bool indicates whether an applicable suggestion has already been |
