Fix macro expansion expression parenthesis wrapping

This commit is contained in:
Lukas Wirth 2023-12-02 13:03:46 +01:00
parent efa67294ed
commit d2a31acda1
18 changed files with 218 additions and 64 deletions

View file

@ -1025,7 +1025,7 @@ impl ExprCollector<'_> {
let id = collector(self, Some(expansion.tree()));
self.ast_id_map = prev_ast_id_map;
self.expander.exit(self.db, mark);
self.expander.exit(mark);
id
}
None => collector(self, None),

View file

@ -2,6 +2,7 @@ mod block;
use base_db::{fixture::WithFixture, SourceDatabase};
use expect_test::{expect, Expect};
use hir_expand::db::ExpandDatabase;
use crate::{test_db::TestDB, ModuleDefId};
@ -143,7 +144,6 @@ mod m {
#[test]
fn desugar_builtin_format_args() {
// Regression test for a path resolution bug introduced with inner item handling.
let (db, body, def) = lower(
r#"
//- minicore: fmt
@ -221,3 +221,70 @@ fn main() {
}"#]]
.assert_eq(&body.pretty_print(&db, def))
}
#[test]
fn test_macro_hygiene() {
let (db, body, def) = lower(
r##"
//- minicore: fmt, from
//- /main.rs
mod error;
use crate::error::error;
fn main() {
// _ = forces body expansion instead of block def map expansion
_ = error!("Failed to resolve path `{}`", node.text());
}
//- /error.rs
macro_rules! _error {
($fmt:expr, $($arg:tt)+) => {$crate::error::intermediate!(format_args!($fmt, $($arg)+))}
}
pub(crate) use _error as error;
macro_rules! _intermediate {
($arg:expr) => {$crate::error::SsrError::new($arg)}
}
pub(crate) use _intermediate as intermediate;
pub struct SsrError(pub(crate) core::fmt::Arguments);
impl SsrError {
pub(crate) fn new(message: impl Into<core::fmt::Arguments>) -> SsrError {
SsrError(message.into())
}
}
"##,
);
println!("{}", db.dump_syntax_contexts());
assert_eq!(db.body_with_source_map(def.into()).1.diagnostics(), &[]);
expect![[r#"
fn main() {
_ = $crate::error::SsrError::new(
builtin#lang(Arguments::new_v1_formatted)(
&[
"\"Failed to resolve path `", "`\"",
],
&[
builtin#lang(Argument::new_display)(
&node.text(),
),
],
&[
builtin#lang(Placeholder::new)(
0usize,
' ',
builtin#lang(Alignment::Unknown),
0u32,
builtin#lang(Count::Implied),
builtin#lang(Count::Implied),
),
],
unsafe {
builtin#lang(UnsafeArg::new)()
},
),
);
}"#]]
.assert_eq(&body.pretty_print(&db, def))
}

View file

@ -794,7 +794,7 @@ impl<'a> AssocItemCollector<'a> {
self.collect(&item_tree, tree_id, &iter);
self.expander.exit(self.db, mark);
self.expander.exit(mark);
}
}

View file

@ -94,8 +94,8 @@ impl Expander {
ExpandResult { value: Some(InFile::new(macro_file.into(), value.0)), err: error.or(err) }
}
pub fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
self.span_map = db.span_map(mark.file_id);
pub fn exit(&mut self, mut mark: Mark) {
self.span_map = mark.span_map;
self.current_file_id = mark.file_id;
if self.recursion_depth == u32::MAX {
// Recursion limit has been reached somewhere in the macro expansion tree. Reset the
@ -174,10 +174,11 @@ impl Expander {
let parse = value.cast::<T>()?;
self.recursion_depth += 1;
self.span_map = db.span_map(file_id);
let old_span_map = std::mem::replace(&mut self.span_map, db.span_map(file_id));
let old_file_id = std::mem::replace(&mut self.current_file_id, file_id);
let mark = Mark {
file_id: old_file_id,
span_map: old_span_map,
bomb: DropBomb::new("expansion mark dropped"),
};
Some((mark, parse))
@ -190,5 +191,6 @@ impl Expander {
#[derive(Debug)]
pub struct Mark {
file_id: HirFileId,
span_map: SpanMap,
bomb: DropBomb,
}

View file

@ -439,7 +439,7 @@ impl GenericParams {
let ctx = expander.ctx(db);
let type_ref = TypeRef::from_ast(&ctx, expanded.tree());
self.fill_implicit_impl_trait_args(db, &mut *exp, &type_ref);
exp.1.exit(db, mark);
exp.1.exit(mark);
}
}
});

View file

@ -997,9 +997,9 @@ macro_rules! vec {
fn f() {
{
let mut v = Vec::new();
v.push((1));
v.push((2));
v.push((3));
v.push(1);
v.push(2);
v.push(3);
v
};
}
@ -1468,8 +1468,8 @@ macro_rules! matches {
};
}
fn main() {
match (0) {
0|1 if (true )=>true , _=>false
match 0 {
0|1 if true =>true , _=>false
};
}
"#]],

View file

@ -62,10 +62,10 @@ macro_rules !implement_methods {
struct Foo;
impl Foo {
fn alpha() -> &'static[u32] {
&[(1), (2), (3)]
&[1, 2, 3]
}
fn beta() -> &'static[u32] {
&[(1), (2), (3)]
&[1, 2, 3]
}
}
"#]],

View file

@ -39,8 +39,8 @@ fn main() {
};
{
let mut v = Vec::new();
v.push((1u32));
v.push((2));
v.push(1u32);
v.push(2);
v
};
}

View file

@ -192,9 +192,9 @@ macro_rules! constant {
($e:expr ;) => {$e};
}
const _: () = (0.0);
const _: () = (0.);
const _: () = (0e0);
const _: () = 0.0;
const _: () = 0.;
const _: () = 0e0;
"#]],
);
}