Skip to content
Open
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 compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
pub(crate) mod loop_match;
pub(crate) mod macro_attrs;
pub(crate) mod modules;
pub(crate) mod must_use;
pub(crate) mod no_implicit_prelude;
pub(crate) mod non_exhaustive;
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/modules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use super::prelude::*;

pub(crate) struct TransparentParser;
impl<S: Stage> NoArgsAttributeParser<S> for TransparentParser {
const PATH: &[Symbol] = &[sym::transparent];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]);
const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::Transparent(span);
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for a closure here

}
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::macro_attrs::{
AllowInternalUnsafeParser, MacroEscapeParser, MacroExportParser, MacroUseParser,
};
use crate::attributes::modules::TransparentParser;
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
Expand Down Expand Up @@ -241,6 +242,7 @@ attribute_parsers!(
Single<WithoutArgs<SpecializationTraitParser>>,
Single<WithoutArgs<StdInternalSymbolParser>>,
Single<WithoutArgs<TrackCallerParser>>,
Single<WithoutArgs<TransparentParser>>,
Single<WithoutArgs<TypeConstParser>>,
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
// tidy-alphabetical-end
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-track_caller-attribute"),
WarnFollowing, EncodeCrossCrate::Yes
),
gated!(
transparent, Normal,
template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-transparent-attribute"),
ErrorFollowing, EncodeCrossCrate::No, transparent_modules, experimental!(transparent)
),
ungated!(
instruction_set, Normal,
template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"),
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,8 @@ declare_features! (
(unstable, transmute_generic_consts, "1.70.0", Some(109929)),
/// Allows #[repr(transparent)] on unions (RFC 2645).
(unstable, transparent_unions, "1.37.0", Some(60405)),
/// Allows #[transparent] on modules to inherit lexical scopes.
(unstable, transparent_modules, "1.92.0", None),
/// Allows inconsistent bounds in where clauses.
(unstable, trivial_bounds, "1.28.0", Some(48214)),
/// Allows using `try {...}` expressions.
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,9 @@ pub enum AttributeKind {
/// Represents `#[track_caller]`
TrackCaller(Span),

/// Represents `#[transparent]` mod attribute
Transparent(Span),

/// Represents `#[type_const]`.
TypeConst(Span),

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ impl AttributeKind {
StdInternalSymbol(..) => No,
TargetFeature { .. } => No,
TrackCaller(..) => Yes,
Transparent(..) => No,
TypeConst(..) => Yes,
TypeLengthLimit { .. } => No,
UnsafeSpecializationMarker(..) => No,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::BodyStability { .. }
| AttributeKind::ConstStabilityIndirect
| AttributeKind::MacroTransparency(_)
| AttributeKind::Transparent(_)
| AttributeKind::Pointee(..)
| AttributeKind::Dummy
| AttributeKind::RustcBuiltinMacro { .. }
Expand Down
25 changes: 19 additions & 6 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let expn_id = self.cstore().expn_that_defined_untracked(def_id, self.tcx.sess);
return Some(self.new_extern_module(
parent,
ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))),
ModuleKind::Def(
def_kind,
def_id,
Some((self.tcx.item_name(def_id), false)),
),
expn_id,
self.def_span(def_id),
// FIXME: Account for `#[no_implicit_prelude]` attributes.
Expand Down Expand Up @@ -629,14 +633,14 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
// Disallow `use $crate;`
if source.ident.name == kw::DollarCrate && module_path.is_empty() {
let crate_root = self.r.resolve_crate_root(source.ident);
let crate_name = match crate_root.kind {
ModuleKind::Def(.., name) => name,
let crate_name_and_transparent = match crate_root.kind {
ModuleKind::Def(.., name_and_transparent) => name_and_transparent,
ModuleKind::Block => unreachable!(),
};
// HACK(eddyb) unclear how good this is, but keeping `$crate`
// in `source` breaks `tests/ui/imports/import-crate-var.rs`,
// while the current crate doesn't have a valid `crate_name`.
if let Some(crate_name) = crate_name {
if let Some((crate_name, _transparent)) = crate_name_and_transparent {
// `crate_name` should not be interpreted as relative.
module_path.push(Segment::from_ident_and_id(
Ident::new(kw::PathRoot, source.ident.span),
Expand Down Expand Up @@ -818,9 +822,18 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
{
self.r.mods_with_parse_errors.insert(def_id);
}
let transparent = AttributeParser::parse_limited(
self.r.tcx.sess,
&item.attrs,
sym::transparent,
item.span,
item.id,
None,
)
.is_some();
self.parent_scope.module = self.r.new_local_module(
Some(parent),
ModuleKind::Def(def_kind, def_id, Some(ident.name)),
ModuleKind::Def(def_kind, def_id, Some((ident.name, transparent))),
expansion.to_expn_id(),
item.span,
parent.no_implicit_prelude
Expand Down Expand Up @@ -852,7 +865,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {

self.parent_scope.module = self.r.new_local_module(
Some(parent),
ModuleKind::Def(def_kind, def_id, Some(ident.name)),
ModuleKind::Def(def_kind, def_id, Some((ident.name, false))),
expansion.to_expn_id(),
item.span,
parent.no_implicit_prelude,
Expand Down
33 changes: 23 additions & 10 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return Some((module.parent.unwrap().nearest_item_scope(), None));
}

if module.is_transparent() {
return Some((module.parent.unwrap().nearest_item_scope(), None));
}

// We need to support the next case under a deprecation warning
// ```
// struct MyStruct;
Expand All @@ -250,12 +254,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// So we have to fall back to the module's parent during lexical resolution in this case.
if derive_fallback_lint_id.is_some()
&& let Some(parent) = module.parent
// Inner module is inside the macro
&& module.expansion != parent.expansion
// Parent module is outside of the macro
&& module.expansion.is_descendant_of(parent.expansion)
// The macro is a proc macro derive
&& let Some(def_id) = module.expansion.expn_data().macro_def_id
// Inner module is inside the macro
&& module.expansion != parent.expansion
// Parent module is outside of the macro
&& module.expansion.is_descendant_of(parent.expansion)
// The macro is a proc macro derive
&& let Some(def_id) = module.expansion.expn_data().macro_def_id
Comment on lines +257 to +262
Copy link
Member Author

Choose a reason for hiding this comment

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

ill clean this up in the next pass, formatting got fked up in a few places >:[

{
let ext = &self.get_macro_by_def_id(def_id).ext;
if ext.builtin_name.is_none()
Expand Down Expand Up @@ -345,7 +349,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Encountered a module item, abandon ribs and look into that module and preludes.
let parent_scope = &ParentScope { module, ..*parent_scope };
let finalize = finalize.map(|f| Finalize { stage: Stage::Late, ..f });
return self
let binding = self
.cm()
.resolve_ident_in_scope_set(
orig_ident,
Expand All @@ -356,8 +360,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ignore_binding,
None,
)
.ok()
.map(LexicalScopeBinding::Item);
.ok();
match binding {
Some(binding) => {
return Some(LexicalScopeBinding::Item(binding));
}
None => {
if !module.is_transparent() {
return None;
}
}
}
}

if let RibKind::MacroDefinition(def) = rib.kind
Expand Down Expand Up @@ -690,7 +703,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
span_bug!(
orig_ident.span,
"ambiguous scoped macro resolutions with path-based \
scope resolution as first candidate"
scope resolution as first candidate"
Copy link
Member Author

Choose a reason for hiding this comment

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

todo: cleanup formatting

)
} else if innermost_binding.is_glob_import() {
Some(AmbiguityKind::GlobVsOuter)
Expand Down
15 changes: 12 additions & 3 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,17 +524,19 @@ enum ModuleKind {
/// * A normal module – either `mod from_file;` or `mod from_block { }` –
/// or the crate root (which is conceptually a top-level module).
/// The crate root will have `None` for the symbol.
/// * the bool in the tuple next to symbol represents whether the "transparent"
/// attribute is present on the module, only applies to named `mod` items.
/// * A trait or an enum (it implicitly contains associated types, methods and variant
/// constructors).
Def(DefKind, DefId, Option<Symbol>),
Def(DefKind, DefId, Option<(Symbol, bool)>),
Copy link
Member Author

Choose a reason for hiding this comment

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

This was the most obvious place to put this but it doesn't feel great, don't love all the places where I changed shit to name_and_transparent, open to suggestions for how to better thread this information through

}

impl ModuleKind {
/// Get name of the module.
fn name(&self) -> Option<Symbol> {
match *self {
ModuleKind::Block => None,
ModuleKind::Def(.., name) => name,
ModuleKind::Def(.., name_and_transparent) => name_and_transparent.map(|(name, _)| name),
}
}
}
Expand Down Expand Up @@ -759,6 +761,13 @@ impl<'ra> Module<'ra> {
}
}

fn is_transparent(self) -> bool {
match self.kind {
ModuleKind::Def(DefKind::Mod, _, Some((_, transparent))) => transparent,
_ => false,
}
}

fn is_ancestor_of(self, mut other: Self) -> bool {
while self != other {
if let Some(parent) = other.parent {
Expand Down Expand Up @@ -2449,7 +2458,7 @@ fn module_to_string(mut module: Module<'_>) -> Option<String> {
if let ModuleKind::Def(.., name) = module.kind {
if let Some(parent) = module.parent {
// `unwrap` is safe: the presence of a parent means it's not the crate root.
names.push(name.unwrap());
names.push(name.unwrap().0);
module = parent
} else {
break;
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,11 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
hygiene::update_dollar_crate_names(|ctxt| {
let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
match self.resolve_crate_root(ident).kind {
ModuleKind::Def(.., name) if let Some(name) = name => name,
ModuleKind::Def(.., name_and_transparent)
if let Some((name, _transparent)) = name_and_transparent =>
{
name
}
_ => kw::Crate,
}
});
Expand Down Expand Up @@ -1123,8 +1127,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
);
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
let location = match parent_scope.module.kind {
ModuleKind::Def(kind, def_id, name) => {
if let Some(name) = name {
ModuleKind::Def(kind, def_id, name_and_transparent) => {
if let Some((name, _transparent)) = name_and_transparent {
format!("{} `{name}`", kind.descr(def_id))
} else {
"the crate root".to_string()
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2230,6 +2230,7 @@ symbols! {
transmute_unchecked,
transparent,
Copy link
Member Author

Choose a reason for hiding this comment

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

I feel like I'm probably doing this part subtly wrong.

The transparent symbol already exists and I'm using it, I tried seeing if I could stay away from it and find a way to have all the compiler internal stuff talk about it with a unique symbol (transparent_modules) but have the actual ident of the attribute be transparent but it seemed like this was controlling that. If I got that wrong lmk.

transparent_enums,
transparent_modules,
transparent_unions,
trivial_bounds,
truncf16,
Expand Down
22 changes: 22 additions & 0 deletions tests/ui/modules/transparent-fail.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//@ check-fail
//@ edition:2018
mod y {
macro_rules! s {
() => {};
}

pub(crate) use s;
}

fn foo() {
struct S;
use y::s;
mod x {
// early resolution
s!(); //~ ERROR cannot find macro `s` in this scope
// late resolution
struct Y(S); //~ ERROR cannot find type `S` in this scope
}
}

fn main() {}
26 changes: 26 additions & 0 deletions tests/ui/modules/transparent-fail.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: cannot find macro `s` in this scope
--> $DIR/transparent-fail.rs:16:9
|
LL | s!();
| ^
|
= help: have you added the `#[macro_use]` on the module/import?
help: consider importing this macro through its public re-export
|
LL + use crate::y::s;
|

error[E0412]: cannot find type `S` in this scope
--> $DIR/transparent-fail.rs:18:18
|
LL | struct Y(S);
| ^ not found in this scope
|
help: you might be missing a type parameter
|
LL | struct Y<S>(S);
| +++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0412`.
27 changes: 27 additions & 0 deletions tests/ui/modules/transparent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//@ check-pass
//@ edition:2018
#![feature(transparent_modules)]

mod y {
macro_rules! s {
() => {};
}

pub(crate) use s;
}

fn foo() {
struct S;
use y::s;
#[transparent]
mod x {
// early resolution
s!();
// late resolution
struct Y(S);
}
}

pub fn main() {
foo();
}
Loading