Skip to content

Commit baab72e

Browse files
author
Jonas Schievink
committed
Reduce visibility of non-proc-macros
proc-macro crates only export proc-macros, but currently other items are also considered public (and show up in completion)
1 parent 0690450 commit baab72e

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

crates/hir_def/src/item_scope.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ use std::collections::hash_map::Entry;
55

66
use base_db::CrateId;
77
use hir_expand::name::Name;
8+
use hir_expand::MacroDefKind;
89
use once_cell::sync::Lazy;
910
use rustc_hash::{FxHashMap, FxHashSet};
1011
use test_utils::mark;
1112

13+
use crate::ModuleId;
1214
use crate::{
1315
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
1416
LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId,
@@ -265,6 +267,29 @@ impl ItemScope {
265267
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
266268
self.legacy_macros.clone()
267269
}
270+
271+
/// Marks everything that is not a procedural macro as private to `this_module`.
272+
pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) {
273+
for vis in self
274+
.types
275+
.values_mut()
276+
.chain(self.values.values_mut())
277+
.map(|(_, v)| v)
278+
.chain(self.unnamed_trait_imports.values_mut())
279+
{
280+
*vis = Visibility::Module(this_module);
281+
}
282+
283+
for (mac, vis) in self.macros.values_mut() {
284+
if let MacroDefKind::ProcMacro(_) = mac.kind {
285+
// FIXME: Technically this is insufficient since reexports of proc macros are also
286+
// forbidden. Practically nobody does that.
287+
continue;
288+
}
289+
290+
*vis = Visibility::Module(this_module);
291+
}
292+
}
268293
}
269294

270295
impl PerNs {

crates/hir_def/src/nameres/collector.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
8787
mod_dirs: FxHashMap::default(),
8888
cfg_options,
8989
proc_macros,
90+
exports_proc_macros: false,
9091
from_glob_import: Default::default(),
9192
};
9293
collector.collect();
@@ -203,6 +204,7 @@ struct DefCollector<'a> {
203204
mod_dirs: FxHashMap<LocalModuleId, ModDir>,
204205
cfg_options: &'a CfgOptions,
205206
proc_macros: Vec<(Name, ProcMacroExpander)>,
207+
exports_proc_macros: bool,
206208
from_glob_import: PerNsGlobImports,
207209
}
208210

@@ -260,9 +262,25 @@ impl DefCollector<'_> {
260262
self.record_resolved_import(directive)
261263
}
262264
self.unresolved_imports = unresolved_imports;
265+
266+
// FIXME: This condition should instead check if this is a `proc-macro` type crate.
267+
if self.exports_proc_macros {
268+
// A crate exporting procedural macros is not allowed to export anything else.
269+
//
270+
// Additionally, while the proc macro entry points must be `pub`, they are not publicly
271+
// exported in type/value namespace. This function reduces the visibility of all items
272+
// in the crate root that aren't proc macros.
273+
let root = self.def_map.root;
274+
let root = &mut self.def_map.modules[root];
275+
root.scope.censor_non_proc_macros(ModuleId {
276+
krate: self.def_map.krate,
277+
local_id: self.def_map.root,
278+
});
279+
}
263280
}
264281

265282
fn resolve_proc_macro(&mut self, name: &Name) {
283+
self.exports_proc_macros = true;
266284
let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) {
267285
Some((_, expander)) => MacroDefId {
268286
ast_id: None,
@@ -1310,6 +1328,7 @@ mod tests {
13101328
mod_dirs: FxHashMap::default(),
13111329
cfg_options: &CfgOptions::default(),
13121330
proc_macros: Default::default(),
1331+
exports_proc_macros: false,
13131332
from_glob_import: Default::default(),
13141333
};
13151334
collector.collect();

crates/hir_def/src/nameres/tests/macros.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,44 @@ fn resolves_proc_macros() {
699699
"#]],
700700
);
701701
}
702+
703+
#[test]
704+
fn proc_macro_censoring() {
705+
// Make sure that only proc macros are publicly exported from proc-macro crates.
706+
707+
check(
708+
r"
709+
//- /main.rs crate:main deps:macros
710+
pub use macros::*;
711+
712+
//- /macros.rs crate:macros
713+
pub struct TokenStream;
714+
715+
#[proc_macro]
716+
pub fn function_like_macro(args: TokenStream) -> TokenStream {
717+
args
718+
}
719+
720+
#[proc_macro_attribute]
721+
pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
722+
item
723+
}
724+
725+
#[proc_macro_derive(DummyTrait)]
726+
pub fn derive_macro(_item: TokenStream) -> TokenStream {
727+
TokenStream
728+
}
729+
730+
#[macro_export]
731+
macro_rules! mbe {
732+
() => {};
733+
}
734+
",
735+
expect![[r#"
736+
crate
737+
DummyTrait: m
738+
attribute_macro: m
739+
function_like_macro: m
740+
"#]],
741+
);
742+
}

0 commit comments

Comments
 (0)