expand: Resolve and expand inner attributes on out-of-line modules
This commit is contained in:
parent
84c08f82b4
commit
a4cc3cae04
12 changed files with 230 additions and 32 deletions
|
@ -1282,16 +1282,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
let (file_path, dir_path, dir_ownership) = match mod_kind {
|
||||
ModKind::Loaded(_, inline, _) => {
|
||||
// Inline `mod foo { ... }`, but we still need to push directories.
|
||||
assert!(
|
||||
*inline == Inline::Yes,
|
||||
"`mod` item is loaded from a file for the second time"
|
||||
);
|
||||
let (dir_path, dir_ownership) = mod_dir_path(
|
||||
&self.cx.sess,
|
||||
ident,
|
||||
&attrs,
|
||||
&self.cx.current_expansion.module,
|
||||
self.cx.current_expansion.dir_ownership,
|
||||
*inline,
|
||||
);
|
||||
item.attrs = attrs;
|
||||
(None, dir_path, dir_ownership)
|
||||
|
@ -1322,10 +1319,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
item.attrs = attrs;
|
||||
if item.attrs.len() > old_attrs_len {
|
||||
// If we loaded an out-of-line module and added some inner attributes,
|
||||
// then we need to re-configure it.
|
||||
// FIXME: Attributes also need to be recollected
|
||||
// for resolution and expansion.
|
||||
// then we need to re-configure it and re-collect attributes for
|
||||
// resolution and expansion.
|
||||
item = configure!(self, item);
|
||||
|
||||
if let Some(attr) = self.take_first_attr(&mut item) {
|
||||
return self
|
||||
.collect_attr(
|
||||
attr,
|
||||
Annotatable::Item(item),
|
||||
AstFragmentKind::Items,
|
||||
)
|
||||
.make_items();
|
||||
}
|
||||
}
|
||||
(Some(file_path), dir_path, dir_ownership)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::base::ModuleData;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{token, Attribute, Item};
|
||||
use rustc_ast::{token, Attribute, Inline, Item};
|
||||
use rustc_errors::{struct_span_err, DiagnosticBuilder};
|
||||
use rustc_parse::new_parser_from_file;
|
||||
use rustc_session::parse::ParseSess;
|
||||
|
@ -83,29 +83,49 @@ crate fn mod_dir_path(
|
|||
attrs: &[Attribute],
|
||||
module: &ModuleData,
|
||||
mut dir_ownership: DirOwnership,
|
||||
inline: Inline,
|
||||
) -> (PathBuf, DirOwnership) {
|
||||
if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
|
||||
// For inline modules file path from `#[path]` is actually the directory path
|
||||
// for historical reasons, so we don't pop the last segment here.
|
||||
return (file_path, DirOwnership::Owned { relative: None });
|
||||
}
|
||||
match inline {
|
||||
Inline::Yes => {
|
||||
if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
|
||||
// For inline modules file path from `#[path]` is actually the directory path
|
||||
// for historical reasons, so we don't pop the last segment here.
|
||||
return (file_path, DirOwnership::Owned { relative: None });
|
||||
}
|
||||
|
||||
// We have to push on the current module name in the case of relative
|
||||
// paths in order to ensure that any additional module paths from inline
|
||||
// `mod x { ... }` come after the relative extension.
|
||||
//
|
||||
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
|
||||
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
|
||||
let mut dir_path = module.dir_path.clone();
|
||||
if let DirOwnership::Owned { relative } = &mut dir_ownership {
|
||||
if let Some(ident) = relative.take() {
|
||||
// Remove the relative offset.
|
||||
// We have to push on the current module name in the case of relative
|
||||
// paths in order to ensure that any additional module paths from inline
|
||||
// `mod x { ... }` come after the relative extension.
|
||||
//
|
||||
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
|
||||
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
|
||||
let mut dir_path = module.dir_path.clone();
|
||||
if let DirOwnership::Owned { relative } = &mut dir_ownership {
|
||||
if let Some(ident) = relative.take() {
|
||||
// Remove the relative offset.
|
||||
dir_path.push(&*ident.as_str());
|
||||
}
|
||||
}
|
||||
dir_path.push(&*ident.as_str());
|
||||
|
||||
(dir_path, dir_ownership)
|
||||
}
|
||||
Inline::No => {
|
||||
// FIXME: This is a subset of `parse_external_mod` without actual parsing,
|
||||
// check whether the logic for unloaded, loaded and inline modules can be unified.
|
||||
let file_path = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)
|
||||
.map(|mp| {
|
||||
dir_ownership = mp.dir_ownership;
|
||||
mp.file_path
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
// Extract the directory path for submodules of the module.
|
||||
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
|
||||
|
||||
(dir_path, dir_ownership)
|
||||
}
|
||||
}
|
||||
dir_path.push(&*ident.as_str());
|
||||
|
||||
(dir_path, dir_ownership)
|
||||
}
|
||||
|
||||
fn mod_file_path<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue