Skip to content
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
13 changes: 9 additions & 4 deletions crates/hir_def/src/nameres/mod_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,26 @@ impl ModDir {
name: &Name,
attr_path: Option<&SmolStr>,
) -> Result<(FileId, bool, ModDir), String> {
let file_id = file_id.original_file(db.upcast());
let orig_file_id = file_id.original_file(db.upcast());

let mut candidate_files = Vec::new();
match attr_path {
Some(attr_path) => {
candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
}
None => {
candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
if file_id.is_include_macro(db.upcast()) {
candidate_files.push(format!("{}.rs", name));
candidate_files.push(format!("{}/mod.rs", name));
} else {
candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
}
}
};

for candidate in candidate_files.iter() {
let path = AnchoredPath { anchor: file_id, path: candidate.as_str() };
let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() };
if let Some(file_id) = db.resolve_path(path) {
let is_mod_rs = candidate.ends_with("/mod.rs");

Expand Down
66 changes: 44 additions & 22 deletions crates/hir_expand/src/builtin_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ macro_rules! register_builtin {
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let expander = match *self {
$( EagerExpander::$e_kind => $e_expand, )*
};
Expand All @@ -61,6 +61,20 @@ macro_rules! register_builtin {
};
}

#[derive(Debug)]
pub struct ExpandedEager {
pub(crate) subtree: tt::Subtree,
pub(crate) fragment: FragmentKind,
/// The included file ID of the include macro.
pub(crate) included_file: Option<FileId>,
}

impl ExpandedEager {
fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self {
ExpandedEager { subtree, fragment, included_file: None }
}
}

pub fn find_builtin_macro(
ident: &name::Name,
krate: CrateId,
Expand Down Expand Up @@ -280,7 +294,7 @@ fn compile_error_expand(
_db: &dyn AstDatabase,
_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let err = match &*tt.token_trees {
[tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => {
let text = it.text.as_str();
Expand All @@ -294,14 +308,14 @@ fn compile_error_expand(
_ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()),
};

ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) }
ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) }
}

fn concat_expand(
_db: &dyn AstDatabase,
_arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let mut err = None;
let mut text = String::new();
for (i, t) in tt.token_trees.iter().enumerate() {
Expand All @@ -325,7 +339,7 @@ fn concat_expand(
}
}
}
ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err }
ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err }
}

fn relative_file(
Expand Down Expand Up @@ -361,21 +375,27 @@ fn include_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let res = (|| {
let path = parse_string(tt)?;
let file_id = relative_file(db, arg_id.into(), &path, false)?;

Ok(parse_to_token_tree(&db.file_text(file_id))
let subtree = parse_to_token_tree(&db.file_text(file_id))
.ok_or_else(|| mbe::ExpandError::ConversionError)?
.0)
.0;
Ok((subtree, file_id))
})();

match res {
Ok(res) => {
Ok((subtree, file_id)) => {
// FIXME:
// Handle include as expression
ExpandResult::ok(Some((res, FragmentKind::Items)))

ExpandResult::ok(Some(ExpandedEager {
subtree,
fragment: FragmentKind::Items,
included_file: Some(file_id),
}))
}
Err(e) => ExpandResult::only_err(e),
}
Expand All @@ -385,7 +405,7 @@ fn include_bytes_expand(
_db: &dyn AstDatabase,
_arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
if let Err(e) = parse_string(tt) {
return ExpandResult::only_err(e);
}
Expand All @@ -398,14 +418,14 @@ fn include_bytes_expand(
id: tt::TokenId::unspecified(),
}))],
};
ExpandResult::ok(Some((res, FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr)))
}

fn include_str_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let path = match parse_string(tt) {
Ok(it) => it,
Err(e) => return ExpandResult::only_err(e),
Expand All @@ -418,14 +438,14 @@ fn include_str_expand(
let file_id = match relative_file(db, arg_id.into(), &path, true) {
Ok(file_id) => file_id,
Err(_) => {
return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr)));
return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr)));
}
};

let text = db.file_text(file_id);
let text = &*text;

ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)))
}

fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
Expand All @@ -437,7 +457,7 @@ fn env_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let key = match parse_string(tt) {
Ok(it) => it,
Err(e) => return ExpandResult::only_err(e),
Expand All @@ -461,14 +481,14 @@ fn env_expand(
});
let expanded = quote! { #s };

ExpandResult { value: Some((expanded, FragmentKind::Expr)), err }
ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err }
}

fn option_env_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let key = match parse_string(tt) {
Ok(it) => it,
Err(e) => return ExpandResult::only_err(e),
Expand All @@ -479,7 +499,7 @@ fn option_env_expand(
Some(s) => quote! { std::option::Some(#s) },
};

ExpandResult::ok(Some((expanded, FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr)))
}

#[cfg(test)]
Expand Down Expand Up @@ -553,16 +573,18 @@ mod tests {
subtree: Arc::new(parsed_args.clone()),
krate,
call: call_id,
included_file: None,
}
});

let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
let eager = EagerCallLoc {
def,
fragment,
subtree: Arc::new(subtree),
fragment: expanded.fragment,
subtree: Arc::new(expanded.subtree),
krate,
call: call_id,
included_file: expanded.included_file,
};

let id: MacroCallId = db.intern_eager_expansion(eager).into();
Expand Down
13 changes: 10 additions & 3 deletions crates/hir_expand/src/eager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ pub fn expand_eager_macro(
subtree: Arc::new(parsed_args.clone()),
krate,
call: call_id,
included_file: None,
}
});
let arg_file_id: MacroCallId = arg_id.into();
Expand All @@ -143,9 +144,15 @@ pub fn expand_eager_macro(
if let MacroDefKind::BuiltInEager(eager, _) = def.kind {
let res = eager.expand(db, arg_id, &subtree);

let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?;
let eager =
EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id };
let expanded = diagnostic_sink.expand_result_option(res)?;
let eager = EagerCallLoc {
def,
fragment: expanded.fragment,
subtree: Arc::new(expanded.subtree),
krate,
call: call_id,
included_file: expanded.included_file,
};

Ok(db.intern_eager_expansion(eager))
} else {
Expand Down
23 changes: 22 additions & 1 deletion crates/hir_expand/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ impl HirFileId {
}
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
loc.call.file_id
if let Some(included_file) = loc.included_file {
return included_file;
} else {
loc.call.file_id
}
}
};
file_id.original_file(db)
Expand Down Expand Up @@ -188,6 +192,21 @@ impl HirFileId {
}
}
}

/// Return whether this file is an include macro
pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool {
match self.0 {
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
return loc.included_file.is_some();
}
_ => {}
},
_ => {}
}
false
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -315,6 +334,8 @@ pub struct EagerCallLoc {
pub(crate) subtree: Arc<tt::Subtree>,
pub(crate) krate: CrateId,
pub(crate) call: AstId<ast::MacroCall>,
// The included file ID of the include macro.
pub(crate) included_file: Option<FileId>,
}

/// ExpansionInfo mainly describes how to map text range between src and expanded macro
Expand Down
23 changes: 23 additions & 0 deletions crates/hir_ty/src/tests/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,29 @@ fn bar() -> u32 {0}
);
}

#[test]
fn infer_builtin_macros_include_child_mod() {
check_types(
r#"
//- /main.rs
#[rustc_builtin_macro]
macro_rules! include {() => {}}

include!("f/foo.rs");

fn main() {
bar::bar();
} //^ u32

//- /f/foo.rs
pub mod bar;

//- /f/bar.rs
pub fn bar() -> u32 {0}
"#,
);
}

#[test]
fn infer_builtin_macros_include_str() {
check_types(
Expand Down