Skip to content

Commit bb4cdf8

Browse files
committed
Auto merge of #82399 - petrochenkov:modin2, r=Aaron1011
expand: Resolve and expand inner attributes on out-of-line modules Fixes #81661 r? `@Aaron1011`
2 parents 9320b12 + a4cc3ca commit bb4cdf8

File tree

12 files changed

+230
-32
lines changed

12 files changed

+230
-32
lines changed

Cargo.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -4774,7 +4774,7 @@ version = "0.11.0"
47744774
source = "registry+https://github.com./rust-lang/crates.io-index"
47754775
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
47764776
dependencies = [
4777-
"semver-parser 0.10.1",
4777+
"semver-parser 0.10.2",
47784778
"serde",
47794779
]
47804780

@@ -4786,9 +4786,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
47864786

47874787
[[package]]
47884788
name = "semver-parser"
4789-
version = "0.10.1"
4789+
version = "0.10.2"
47904790
source = "registry+https://github.com./rust-lang/crates.io-index"
4791-
checksum = "42ef146c2ad5e5f4b037cd6ce2ebb775401729b19a82040c1beac9d36c7d1428"
4791+
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
47924792
dependencies = [
47934793
"pest",
47944794
]

compiler/rustc_ast/src/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2297,7 +2297,7 @@ impl FnRetTy {
22972297
}
22982298
}
22992299

2300-
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
2300+
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
23012301
pub enum Inline {
23022302
Yes,
23032303
No,

compiler/rustc_expand/src/expand.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -1282,16 +1282,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12821282
let (file_path, dir_path, dir_ownership) = match mod_kind {
12831283
ModKind::Loaded(_, inline, _) => {
12841284
// Inline `mod foo { ... }`, but we still need to push directories.
1285-
assert!(
1286-
*inline == Inline::Yes,
1287-
"`mod` item is loaded from a file for the second time"
1288-
);
12891285
let (dir_path, dir_ownership) = mod_dir_path(
12901286
&self.cx.sess,
12911287
ident,
12921288
&attrs,
12931289
&self.cx.current_expansion.module,
12941290
self.cx.current_expansion.dir_ownership,
1291+
*inline,
12951292
);
12961293
item.attrs = attrs;
12971294
(None, dir_path, dir_ownership)
@@ -1322,10 +1319,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13221319
item.attrs = attrs;
13231320
if item.attrs.len() > old_attrs_len {
13241321
// If we loaded an out-of-line module and added some inner attributes,
1325-
// then we need to re-configure it.
1326-
// FIXME: Attributes also need to be recollected
1327-
// for resolution and expansion.
1322+
// then we need to re-configure it and re-collect attributes for
1323+
// resolution and expansion.
13281324
item = configure!(self, item);
1325+
1326+
if let Some(attr) = self.take_first_attr(&mut item) {
1327+
return self
1328+
.collect_attr(
1329+
attr,
1330+
Annotatable::Item(item),
1331+
AstFragmentKind::Items,
1332+
)
1333+
.make_items();
1334+
}
13291335
}
13301336
(Some(file_path), dir_path, dir_ownership)
13311337
}

compiler/rustc_expand/src/module.rs

+39-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::base::ModuleData;
22
use rustc_ast::ptr::P;
3-
use rustc_ast::{token, Attribute, Item};
3+
use rustc_ast::{token, Attribute, Inline, Item};
44
use rustc_errors::{struct_span_err, DiagnosticBuilder};
55
use rustc_parse::new_parser_from_file;
66
use rustc_session::parse::ParseSess;
@@ -83,29 +83,49 @@ crate fn mod_dir_path(
8383
attrs: &[Attribute],
8484
module: &ModuleData,
8585
mut dir_ownership: DirOwnership,
86+
inline: Inline,
8687
) -> (PathBuf, DirOwnership) {
87-
if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
88-
// For inline modules file path from `#[path]` is actually the directory path
89-
// for historical reasons, so we don't pop the last segment here.
90-
return (file_path, DirOwnership::Owned { relative: None });
91-
}
88+
match inline {
89+
Inline::Yes => {
90+
if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
91+
// For inline modules file path from `#[path]` is actually the directory path
92+
// for historical reasons, so we don't pop the last segment here.
93+
return (file_path, DirOwnership::Owned { relative: None });
94+
}
9295

93-
// We have to push on the current module name in the case of relative
94-
// paths in order to ensure that any additional module paths from inline
95-
// `mod x { ... }` come after the relative extension.
96-
//
97-
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
98-
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
99-
let mut dir_path = module.dir_path.clone();
100-
if let DirOwnership::Owned { relative } = &mut dir_ownership {
101-
if let Some(ident) = relative.take() {
102-
// Remove the relative offset.
96+
// We have to push on the current module name in the case of relative
97+
// paths in order to ensure that any additional module paths from inline
98+
// `mod x { ... }` come after the relative extension.
99+
//
100+
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
101+
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
102+
let mut dir_path = module.dir_path.clone();
103+
if let DirOwnership::Owned { relative } = &mut dir_ownership {
104+
if let Some(ident) = relative.take() {
105+
// Remove the relative offset.
106+
dir_path.push(&*ident.as_str());
107+
}
108+
}
103109
dir_path.push(&*ident.as_str());
110+
111+
(dir_path, dir_ownership)
104112
}
105-
}
106-
dir_path.push(&*ident.as_str());
113+
Inline::No => {
114+
// FIXME: This is a subset of `parse_external_mod` without actual parsing,
115+
// check whether the logic for unloaded, loaded and inline modules can be unified.
116+
let file_path = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)
117+
.map(|mp| {
118+
dir_ownership = mp.dir_ownership;
119+
mp.file_path
120+
})
121+
.unwrap_or_default();
122+
123+
// Extract the directory path for submodules of the module.
124+
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
107125

108-
(dir_path, dir_ownership)
126+
(dir_path, dir_ownership)
127+
}
128+
}
109129
}
110130

111131
fn mod_file_path<'a>(

compiler/rustc_resolve/src/macros.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ use crate::Namespace::*;
66
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BuiltinMacroState, Determinacy};
77
use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
88
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
9-
use rustc_ast::{self as ast, NodeId};
9+
use rustc_ast::{self as ast, Inline, ItemKind, ModKind, NodeId};
1010
use rustc_ast_lowering::ResolverAstLowering;
1111
use rustc_ast_pretty::pprust;
1212
use rustc_attr::StabilityLevel;
1313
use rustc_data_structures::fx::FxHashSet;
1414
use rustc_data_structures::ptr_key::PtrKey;
1515
use rustc_data_structures::sync::Lrc;
1616
use rustc_errors::struct_span_err;
17+
use rustc_expand::base::Annotatable;
1718
use rustc_expand::base::{Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind};
1819
use rustc_expand::compile_declarative_macro;
1920
use rustc_expand::expand::{AstFragment, Invocation, InvocationKind};
@@ -153,6 +154,26 @@ crate fn registered_attrs_and_tools(
153154
(registered_attrs, registered_tools)
154155
}
155156

157+
// Some feature gates for inner attributes are reported as lints for backward compatibility.
158+
fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bool {
159+
match &path.segments[..] {
160+
// `#![test]`
161+
[seg] if seg.ident.name == sym::test => return true,
162+
// `#![rustfmt::skip]` on out-of-line modules
163+
[seg1, seg2] if seg1.ident.name == sym::rustfmt && seg2.ident.name == sym::skip => {
164+
if let InvocationKind::Attr { item, .. } = &invoc.kind {
165+
if let Annotatable::Item(item) = item {
166+
if let ItemKind::Mod(_, ModKind::Loaded(_, Inline::No, _)) = item.kind {
167+
return true;
168+
}
169+
}
170+
}
171+
}
172+
_ => {}
173+
}
174+
false
175+
}
176+
156177
impl<'a> ResolverExpand for Resolver<'a> {
157178
fn next_node_id(&mut self) -> NodeId {
158179
self.next_node_id()
@@ -267,6 +288,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
267288
parent_scope,
268289
node_id,
269290
force,
291+
soft_custom_inner_attributes_gate(path, invoc),
270292
)?;
271293

272294
let span = invoc.span();
@@ -440,6 +462,7 @@ impl<'a> Resolver<'a> {
440462
parent_scope: &ParentScope<'a>,
441463
node_id: NodeId,
442464
force: bool,
465+
soft_custom_inner_attributes_gate: bool,
443466
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
444467
let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force)
445468
{
@@ -507,7 +530,7 @@ impl<'a> Resolver<'a> {
507530
Res::NonMacroAttr(..) => "custom inner attributes are unstable",
508531
_ => unreachable!(),
509532
};
510-
if path == &sym::test {
533+
if soft_custom_inner_attributes_gate {
511534
self.session.parse_sess.buffer_lint(SOFT_UNSTABLE, path.span, node_id, msg);
512535
} else {
513536
feature_err(&self.session.parse_sess, sym::custom_inner_attributes, path.span, msg)

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,7 @@ symbols! {
11111111
size_of,
11121112
size_of_val,
11131113
sized,
1114+
skip,
11141115
slice,
11151116
slice_alloc,
11161117
slice_patterns,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// check-pass
2+
3+
mod module_with_cfg;
4+
5+
mod module_with_cfg {} // Ok, the module above is configured away by an inner attribute.
6+
7+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// ignore-test
2+
3+
#![cfg_attr(all(), cfg(FALSE))]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// compile-flags: -Z span-debug
2+
// error-pattern:custom inner attributes are unstable
3+
// error-pattern:inner macro attributes are unstable
4+
// error-pattern:this was previously accepted
5+
// aux-build:test-macros.rs
6+
7+
#![no_std] // Don't load unnecessary hygiene information from std
8+
extern crate std;
9+
10+
#[macro_use]
11+
extern crate test_macros;
12+
13+
#[deny(unused_attributes)]
14+
mod module_with_attrs;
15+
//~^ ERROR non-inline modules in proc macro input are unstable
16+
//~| ERROR custom inner attributes are unstable
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
error[E0658]: inner macro attributes are unstable
2+
--> $DIR/module_with_attrs.rs:4:4
3+
|
4+
LL | #![print_attr]
5+
| ^^^^^^^^^^
6+
|
7+
= note: see issue #54726 <https://github.com./rust-lang/rust/issues/54726> for more information
8+
= help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
9+
10+
error[E0658]: non-inline modules in proc macro input are unstable
11+
--> $DIR/inner-attr-non-inline-mod.rs:14:1
12+
|
13+
LL | mod module_with_attrs;
14+
| ^^^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #54727 <https://github.com./rust-lang/rust/issues/54727> for more information
17+
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
18+
19+
error[E0658]: custom inner attributes are unstable
20+
--> $DIR/inner-attr-non-inline-mod.rs:14:1
21+
|
22+
LL | mod module_with_attrs;
23+
| ^^^^^^^^^^^^^^^^^^^^^^
24+
|
25+
= note: see issue #54726 <https://github.com./rust-lang/rust/issues/54726> for more information
26+
= help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable
27+
28+
error: custom inner attributes are unstable
29+
--> $DIR/module_with_attrs.rs:3:4
30+
|
31+
LL | #![rustfmt::skip]
32+
| ^^^^^^^^^^^^^
33+
|
34+
= note: `#[deny(soft_unstable)]` on by default
35+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
36+
= note: for more information, see issue #64266 <https://github.com./rust-lang/rust/issues/64266>
37+
38+
error: aborting due to 4 previous errors
39+
40+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { # ! [rustfmt :: skip] }
2+
PRINT-ATTR INPUT (DEBUG): TokenStream [
3+
Punct {
4+
ch: '#',
5+
spacing: Alone,
6+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
7+
},
8+
Group {
9+
delimiter: Bracket,
10+
stream: TokenStream [
11+
Ident {
12+
ident: "deny",
13+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
14+
},
15+
Group {
16+
delimiter: Parenthesis,
17+
stream: TokenStream [
18+
Ident {
19+
ident: "unused_attributes",
20+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
21+
},
22+
],
23+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
24+
},
25+
],
26+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
27+
},
28+
Ident {
29+
ident: "mod",
30+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
31+
},
32+
Ident {
33+
ident: "module_with_attrs",
34+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
35+
},
36+
Group {
37+
delimiter: Brace,
38+
stream: TokenStream [
39+
Punct {
40+
ch: '#',
41+
spacing: Joint,
42+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
43+
},
44+
Punct {
45+
ch: '!',
46+
spacing: Alone,
47+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
48+
},
49+
Group {
50+
delimiter: Bracket,
51+
stream: TokenStream [
52+
Ident {
53+
ident: "rustfmt",
54+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
55+
},
56+
Punct {
57+
ch: ':',
58+
spacing: Joint,
59+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
60+
},
61+
Punct {
62+
ch: ':',
63+
spacing: Alone,
64+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
65+
},
66+
Ident {
67+
ident: "skip",
68+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
69+
},
70+
],
71+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
72+
},
73+
],
74+
span: $DIR/inner-attr-non-inline-mod.rs:14:1: 14:23 (#0),
75+
},
76+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// ignore-test
2+
3+
#![rustfmt::skip]
4+
#![print_attr]

0 commit comments

Comments
 (0)