Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement module_path macro #17936

Merged
merged 2 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/base-db/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ impl ReleaseChannel {
}
}

#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CrateData {
pub root_file_id: FileId,
Expand Down
3 changes: 2 additions & 1 deletion crates/hir-def/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,8 +748,9 @@ impl<'a> AssocItemCollector<'a> {
&AstIdWithPath::new(file_id, ast_id, Clone::clone(path)),
ctxt,
expand_to,
self.expander.krate(),
self.expander.module,
resolver,
|module| module.def_map(self.db).path_for_module(self.db, module),
) {
Ok(Some(call_id)) => {
let res =
Expand Down
9 changes: 6 additions & 3 deletions crates/hir-def/src/expander.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ impl Expander {

let result = self.within_limit(db, |this| {
let macro_call = this.in_file(&macro_call);
match macro_call.as_call_id_with_errors(db.upcast(), this.module.krate(), |path| {
resolver(path).map(|it| db.macro_def(it))
}) {
match macro_call.as_call_id(
db.upcast(),
this.module,
|path| resolver(path).map(|it| db.macro_def(it)),
|module| this.module.def_map(db).path_for_module(db, module),
) {
Ok(call_id) => call_id,
Err(resolve_err) => {
unresolved_macro_err = Some(resolve_err);
Expand Down
44 changes: 25 additions & 19 deletions crates/hir-def/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ use base_db::{
use hir_expand::{
builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
db::ExpandDatabase,
eager::expand_eager_macro_input,
eager::{expand_eager_macro_input, expand_module_path_as_eager},
impl_intern_lookup,
name::Name,
proc_macro::{CustomProcMacroExpander, ProcMacroKind},
Expand Down Expand Up @@ -1400,26 +1400,19 @@ pub trait AsMacroCall {
fn as_call_id(
&self,
db: &dyn ExpandDatabase,
krate: CrateId,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Option<MacroCallId> {
self.as_call_id_with_errors(db, krate, resolver).ok()?.value
}

fn as_call_id_with_errors(
&self,
db: &dyn ExpandDatabase,
krate: CrateId,
module: ModuleId,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
mod_path: impl FnOnce(ModuleId) -> String,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
}

impl AsMacroCall for InFile<&ast::MacroCall> {
fn as_call_id_with_errors(
fn as_call_id(
&self,
db: &dyn ExpandDatabase,
krate: CrateId,
module: ModuleId,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
mod_path: impl FnOnce(ModuleId) -> String,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
Expand All @@ -1446,9 +1439,10 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
&path,
call_site.ctx,
expands_to,
krate,
module,
resolver,
resolver,
mod_path,
)
}
}
Expand All @@ -1475,18 +1469,20 @@ fn macro_call_as_call_id(
call: &AstIdWithPath<ast::MacroCall>,
call_site: SyntaxContextId,
expand_to: ExpandTo,
krate: CrateId,
module: ModuleId,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
mod_path: impl FnOnce(ModuleId) -> String,
) -> Result<Option<MacroCallId>, UnresolvedMacro> {
macro_call_as_call_id_with_eager(
db,
call.ast_id,
&call.path,
call_site,
expand_to,
krate,
module,
resolver,
resolver,
mod_path,
)
.map(|res| res.value)
}
Expand All @@ -1497,16 +1493,26 @@ fn macro_call_as_call_id_with_eager(
path: &path::ModPath,
call_site: SyntaxContextId,
expand_to: ExpandTo,
krate: CrateId,
module: ModuleId,
resolver: impl FnOnce(&path::ModPath) -> Option<MacroDefId>,
eager_resolver: impl Fn(&path::ModPath) -> Option<MacroDefId>,
mod_path: impl FnOnce(ModuleId) -> String,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
let def = resolver(path).ok_or_else(|| UnresolvedMacro { path: path.clone() })?;

let res = match def.kind {
MacroDefKind::BuiltInEager(_, EagerExpander::ModulePath) => expand_module_path_as_eager(
db,
module.krate,
mod_path(module),
&ast_id.to_node(db),
ast_id,
def,
call_site,
),
MacroDefKind::BuiltInEager(..) => expand_eager_macro_input(
db,
krate,
module.krate,
&ast_id.to_node(db),
ast_id,
def,
Expand All @@ -1516,7 +1522,7 @@ fn macro_call_as_call_id_with_eager(
_ if def.is_fn_like() => ExpandResult {
value: Some(def.make_call(
db,
krate,
module.krate,
MacroCallKind::FnLike { ast_id, expand_to, eager: None },
call_site,
)),
Expand Down
15 changes: 10 additions & 5 deletions crates/hir-def/src/macro_expansion_tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,16 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
let macro_call = InFile::new(source.file_id, &macro_call);
let res = macro_call
.as_call_id_with_errors(&db, krate, |path| {
resolver
.resolve_path_as_macro(&db, path, Some(MacroSubNs::Bang))
.map(|(it, _)| db.macro_def(it))
})
.as_call_id(
&db,
resolver.module(),
|path| {
resolver
.resolve_path_as_macro(&db, path, Some(MacroSubNs::Bang))
.map(|(it, _)| db.macro_def(it))
},
|module| def_map.path_for_module(&db, module),
)
.unwrap();
let macro_call_id = res.value.unwrap();
let macro_file = MacroFileId { macro_call_id };
Expand Down
27 changes: 26 additions & 1 deletion crates/hir-def/src/nameres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use base_db::CrateId;
use hir_expand::{
name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId,
};
use intern::Symbol;
use intern::{sym, Symbol};
use itertools::Itertools;
use la_arena::Arena;
use rustc_hash::{FxHashMap, FxHashSet};
Expand Down Expand Up @@ -139,6 +139,7 @@ pub struct DefMap {
/// Data that belongs to a crate which is shared between a crate's def map and all its block def maps.
#[derive(Clone, Debug, PartialEq, Eq)]
struct DefMapCrateData {
crate_name: Option<Symbol>,
/// The extern prelude which contains all root modules of external crates that are in scope.
extern_prelude: FxIndexMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,

Expand All @@ -164,6 +165,7 @@ struct DefMapCrateData {
impl DefMapCrateData {
fn new(edition: Edition) -> Self {
Self {
crate_name: None,
extern_prelude: FxIndexMap::default(),
exported_derives: FxHashMap::default(),
fn_proc_macro_mapping: FxHashMap::default(),
Expand All @@ -186,6 +188,7 @@ impl DefMapCrateData {
registered_attrs,
registered_tools,
unstable_features,
crate_name: _,
rustc_coherence_is_core: _,
no_core: _,
no_std: _,
Expand Down Expand Up @@ -443,6 +446,28 @@ impl DefMap {
self.modules.iter()
}

pub fn path_for_module(&self, db: &dyn DefDatabase, mut module: ModuleId) -> String {
debug_assert!(module.krate == self.krate && module.block == self.block.map(|b| b.block));
let mut parts = vec![];
if let Some(name) = module.name(db) {
parts.push(name.symbol().clone());
}
while let Some(parent) = module.def_map(db).containing_module(module.local_id) {
module = parent;
if let Some(name) = module.name(db) {
parts.push(name.symbol().clone());
}
if parts.len() > 10 {
break;
}
}
parts.push(match &self.data.crate_name {
Some(name) => name.clone(),
None => sym::crate_.clone(),
});
parts.into_iter().rev().format("::").to_string()
}

pub fn derive_helpers_in_scope(
&self,
id: AstId<ast::Adt>,
Expand Down
27 changes: 20 additions & 7 deletions crates/hir-def/src/nameres/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,18 +247,23 @@ impl DefCollector<'_> {
let _p = tracing::info_span!("seed_with_top_level").entered();

let crate_graph = self.db.crate_graph();
let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
crate_data.crate_name = crate_graph[self.def_map.krate]
.display_name
.as_ref()
.map(|it| it.crate_name().symbol().clone());

let file_id = crate_graph[self.def_map.krate].root_file_id();
let item_tree = self.db.file_item_tree(file_id.into());
let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();

let mut process = true;
let mut crate_cged_out = false;

// Process other crate-level attributes.
for attr in &*attrs {
if let Some(cfg) = attr.cfg() {
if self.cfg_options.check(&cfg) == Some(false) {
process = false;
crate_cged_out = true;
break;
}
}
Expand All @@ -272,6 +277,11 @@ impl DefCollector<'_> {
}
}
}
() if *attr_name == sym::crate_name.clone() => {
if let Some(name) = attr.string_value().cloned() {
crate_data.crate_name = Some(name);
}
}
() if *attr_name == sym::crate_type.clone() => {
if attr.string_value() == Some(&sym::proc_dash_macro) {
self.is_proc_macro = true;
Expand Down Expand Up @@ -337,7 +347,7 @@ impl DefCollector<'_> {

self.inject_prelude();

if !process {
if crate_cged_out {
return;
}

Expand Down Expand Up @@ -1207,8 +1217,9 @@ impl DefCollector<'_> {
ast_id,
*call_site,
*expand_to,
self.def_map.krate,
self.def_map.module_id(directive.module_id),
resolver_def_id,
|module| self.def_map.path_for_module(self.db, module),
);
if let Ok(Some(call_id)) = call_id {
self.def_map.modules[directive.module_id]
Expand Down Expand Up @@ -1486,7 +1497,7 @@ impl DefCollector<'_> {
ast_id,
*call_site,
*expand_to,
self.def_map.krate,
self.def_map.module_id(directive.module_id),
|path| {
let resolved_res = self.def_map.resolve_path_fp_with_macro(
self.db,
Expand All @@ -1498,6 +1509,7 @@ impl DefCollector<'_> {
);
resolved_res.resolved_def.take_macros().map(|it| self.db.macro_def(it))
},
|module| self.def_map.path_for_module(self.db, module),
);
if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
Expand Down Expand Up @@ -2351,7 +2363,7 @@ impl ModCollector<'_, '_> {
&ast_id.path,
ctxt,
expand_to,
self.def_collector.def_map.krate,
self.def_collector.def_map.module_id(self.module_id),
|path| {
path.as_ident().and_then(|name| {
let def_map = &self.def_collector.def_map;
Expand Down Expand Up @@ -2381,6 +2393,7 @@ impl ModCollector<'_, '_> {
);
resolved_res.resolved_def.take_macros().map(|it| db.macro_def(it))
},
|module| self.def_collector.def_map.path_for_module(self.def_collector.db, module),
) {
// FIXME: if there were errors, this might've been in the eager expansion from an
// unresolved macro, so we need to push this into late macro resolution. see fixme above
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-expand/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Builtin macros and attributes
#[macro_use]
mod quote;
pub(crate) mod quote;

mod attr_macro;
mod derive_macro;
Expand Down
30 changes: 16 additions & 14 deletions crates/hir-expand/src/builtin/fn_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ register_builtin! {
(column, Column) => line_expand,
(file, File) => file_expand,
(line, Line) => line_expand,
(module_path, ModulePath) => module_path_expand,
(assert, Assert) => assert_expand,
(stringify, Stringify) => stringify_expand,
(llvm_asm, LlvmAsm) => asm_expand,
Expand All @@ -142,7 +141,10 @@ register_builtin! {
(include_bytes, IncludeBytes) => include_bytes_expand,
(include_str, IncludeStr) => include_str_expand,
(env, Env) => env_expand,
(option_env, OptionEnv) => option_env_expand
(option_env, OptionEnv) => option_env_expand,
// This isn't really eager, we have no inputs, but we abuse the fact how eager macros are
// handled in r-a to be able to thread the module path through.
(module_path, ModulePath) => module_path_expand
Comment on lines +145 to +147
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The magic that makes things work despite our crate split (I hate this hack)

}

fn mk_pound(span: Span) -> tt::Subtree {
Expand All @@ -157,18 +159,6 @@ fn mk_pound(span: Span) -> tt::Subtree {
)
}

fn module_path_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
_tt: &tt::Subtree,
span: Span,
) -> ExpandResult<tt::Subtree> {
// Just return a dummy result.
ExpandResult::ok(quote! {span =>
"module::path"
})
}

fn line_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
Expand Down Expand Up @@ -904,6 +894,18 @@ fn option_env_expand(
ExpandResult::ok(expanded)
}

fn module_path_expand(
_db: &dyn ExpandDatabase,
_id: MacroCallId,
tt: &tt::Subtree,
span: Span,
) -> ExpandResult<tt::Subtree> {
// Note: The actual implementation of this is in crates\hir-expand\src\eager.rs
ExpandResult::ok(quote! {span =>
#tt
})
}

fn quote_expand(
_db: &dyn ExpandDatabase,
_arg_id: MacroCallId,
Expand Down
Loading