Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 2267c2c

Browse files
authored
Merge pull request rust-lang#3001 from scampi/issue2977
propagate errors about failing to rewrite a macro
2 parents 14fdf2e + 1befc93 commit 2267c2c

File tree

9 files changed

+236
-8
lines changed

9 files changed

+236
-8
lines changed

src/formatting.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> {
175175
}
176176

177177
self.handler
178-
.handle_formatted_file(path, visitor.buffer, &mut self.report)
178+
.handle_formatted_file(path, visitor.buffer.to_owned(), &mut self.report)
179179
}
180180
}
181181

src/macros.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl Rewrite for ast::Item {
6969
visitor.block_indent = shape.indent;
7070
visitor.last_pos = self.span().lo();
7171
visitor.visit_item(self);
72-
Some(visitor.buffer)
72+
Some(visitor.buffer.to_owned())
7373
}
7474
}
7575

@@ -406,7 +406,15 @@ pub fn rewrite_macro_def(
406406
";",
407407
|branch| branch.span.lo(),
408408
|branch| branch.span.hi(),
409-
|branch| branch.rewrite(context, arm_shape, multi_branch_style),
409+
|branch| match branch.rewrite(context, arm_shape, multi_branch_style) {
410+
Some(v) => Some(v),
411+
// if the rewrite returned None because a macro could not be rewritten, then return the
412+
// original body
413+
None if *context.macro_rewrite_failure.borrow() == true => {
414+
Some(context.snippet(branch.body).trim().to_string())
415+
}
416+
None => None,
417+
},
410418
context.snippet_provider.span_after(span, "{"),
411419
span.hi(),
412420
false,

src/visitor.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ impl<'a> SnippetProvider<'a> {
6060
}
6161

6262
pub struct FmtVisitor<'a> {
63+
parent_context: Option<&'a RewriteContext<'a>>,
6364
pub parse_session: &'a ParseSess,
6465
pub source_map: &'a SourceMap,
6566
pub buffer: String,
@@ -75,7 +76,21 @@ pub struct FmtVisitor<'a> {
7576
pub(crate) report: FormatReport,
7677
}
7778

79+
impl<'a> Drop for FmtVisitor<'a> {
80+
fn drop(&mut self) {
81+
if let Some(ctx) = self.parent_context {
82+
if self.macro_rewrite_failure {
83+
ctx.macro_rewrite_failure.replace(true);
84+
}
85+
}
86+
}
87+
}
88+
7889
impl<'b, 'a: 'b> FmtVisitor<'a> {
90+
fn set_parent_context(&mut self, context: &'a RewriteContext) {
91+
self.parent_context = Some(context);
92+
}
93+
7994
pub fn shape(&self) -> Shape {
8095
Shape::indented(self.block_indent, self.config)
8196
}
@@ -97,7 +112,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
97112
if contains_skip(get_attrs_from_stmt(stmt)) {
98113
self.push_skipped_with_span(stmt.span());
99114
} else {
100-
let rewrite = stmt.rewrite(&self.get_context(), self.shape());
115+
let shape = self.shape().clone();
116+
let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape));
101117
self.push_rewrite(stmt.span(), rewrite)
102118
}
103119
}
@@ -350,11 +366,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
350366
let where_span_end = snippet
351367
.find_uncommented("{")
352368
.map(|x| BytePos(x as u32) + source!(self, item.span).lo());
353-
let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end);
369+
let block_indent = self.block_indent.clone();
370+
let rw =
371+
self.with_context(|ctx| format_impl(&ctx, item, block_indent, where_span_end));
354372
self.push_rewrite(item.span, rw);
355373
}
356374
ast::ItemKind::Trait(..) => {
357-
let rw = format_trait(&self.get_context(), item, self.block_indent);
375+
let block_indent = self.block_indent.clone();
376+
let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent));
358377
self.push_rewrite(item.span, rw);
359378
}
360379
ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
@@ -575,12 +594,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
575594
}
576595

577596
pub fn from_context(ctx: &'a RewriteContext) -> FmtVisitor<'a> {
578-
FmtVisitor::from_source_map(
597+
let mut visitor = FmtVisitor::from_source_map(
579598
ctx.parse_session,
580599
ctx.config,
581600
ctx.snippet_provider,
582601
ctx.report.clone(),
583-
)
602+
);
603+
visitor.set_parent_context(ctx);
604+
visitor
584605
}
585606

586607
pub(crate) fn from_source_map(
@@ -590,6 +611,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
590611
report: FormatReport,
591612
) -> FmtVisitor<'a> {
592613
FmtVisitor {
614+
parent_context: None,
593615
parse_session,
594616
source_map: parse_session.source_map(),
595617
buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2),

tests/source/issue-2977/impl.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
macro_rules! atomic_bits {
2+
// the println macro cannot be rewritten because of the asm macro
3+
($type:ty, $ldrex:expr, $strex:expr) => {
4+
impl AtomicBits for $type {
5+
unsafe fn load_excl(address: usize) -> Self {
6+
let raw: $type;
7+
asm!($ldrex
8+
: "=r"(raw)
9+
: "r"(address)
10+
:
11+
: "volatile");
12+
raw
13+
}
14+
15+
unsafe fn store_excl(self, address: usize) -> bool {
16+
let status: $type;
17+
println!("{}",
18+
status);
19+
status == 0
20+
}
21+
}
22+
};
23+
24+
// the println macro should be rewritten here
25+
($type:ty) => {
26+
fn some_func(self) {
27+
let status: $type;
28+
println!("{}", status);
29+
}
30+
};
31+
32+
// unrewritale macro in func
33+
($type:ty, $ldrex:expr) => {
34+
unsafe fn load_excl(address: usize) -> Self {
35+
let raw: $type;
36+
asm!($ldrex
37+
: "=r"(raw)
38+
: "r"(address)
39+
:
40+
: "volatile");
41+
raw
42+
}
43+
}
44+
}

tests/source/issue-2977/trait.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
macro_rules! atomic_bits {
2+
// the println macro cannot be rewritten because of the asm macro
3+
($type:ty, $ldrex:expr, $strex:expr) => {
4+
trait $type {
5+
unsafe fn load_excl(address: usize) -> Self {
6+
let raw: $type;
7+
asm!($ldrex
8+
: "=r"(raw)
9+
: "r"(address)
10+
:
11+
: "volatile");
12+
raw
13+
}
14+
15+
unsafe fn store_excl(self, address: usize) -> bool {
16+
let status: $type;
17+
println!("{}",
18+
status);
19+
status == 0
20+
}
21+
}
22+
};
23+
24+
// the println macro should be rewritten here
25+
($type:ty) => {
26+
fn some_func(self) {
27+
let status: $type;
28+
println!("{}", status);
29+
}
30+
};
31+
32+
// unrewritale macro in func
33+
($type:ty, $ldrex:expr) => {
34+
unsafe fn load_excl(address: usize) -> Self {
35+
let raw: $type;
36+
asm!($ldrex
37+
: "=r"(raw)
38+
: "r"(address)
39+
:
40+
: "volatile");
41+
raw
42+
}
43+
}
44+
}

tests/target/issue-2977/block.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
macro_rules! atomic_bits {
2+
($ldrex:expr) => {
3+
execute(|| {
4+
asm!($ldrex
5+
: "=r"(raw)
6+
: "r"(address)
7+
:
8+
: "volatile");
9+
})
10+
};
11+
}

tests/target/issue-2977/impl.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
macro_rules! atomic_bits {
2+
// the println macro cannot be rewritten because of the asm macro
3+
($type:ty, $ldrex:expr, $strex:expr) => {
4+
impl AtomicBits for $type {
5+
unsafe fn load_excl(address: usize) -> Self {
6+
let raw: $type;
7+
asm!($ldrex
8+
: "=r"(raw)
9+
: "r"(address)
10+
:
11+
: "volatile");
12+
raw
13+
}
14+
15+
unsafe fn store_excl(self, address: usize) -> bool {
16+
let status: $type;
17+
println!("{}",
18+
status);
19+
status == 0
20+
}
21+
}
22+
};
23+
24+
// the println macro should be rewritten here
25+
($type:ty) => {
26+
fn some_func(self) {
27+
let status: $type;
28+
println!("{}", status);
29+
}
30+
};
31+
32+
// unrewritale macro in func
33+
($type:ty, $ldrex:expr) => {
34+
unsafe fn load_excl(address: usize) -> Self {
35+
let raw: $type;
36+
asm!($ldrex
37+
: "=r"(raw)
38+
: "r"(address)
39+
:
40+
: "volatile");
41+
raw
42+
}
43+
}
44+
}

tests/target/issue-2977/item.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
macro_rules! atomic_bits {
2+
($ldrex:expr) => {
3+
some_macro!(pub fn foo() {
4+
asm!($ldrex
5+
: "=r"(raw)
6+
: "r"(address)
7+
:
8+
: "volatile");
9+
})
10+
};
11+
}

tests/target/issue-2977/trait.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
macro_rules! atomic_bits {
2+
// the println macro cannot be rewritten because of the asm macro
3+
($type:ty, $ldrex:expr, $strex:expr) => {
4+
trait $type {
5+
unsafe fn load_excl(address: usize) -> Self {
6+
let raw: $type;
7+
asm!($ldrex
8+
: "=r"(raw)
9+
: "r"(address)
10+
:
11+
: "volatile");
12+
raw
13+
}
14+
15+
unsafe fn store_excl(self, address: usize) -> bool {
16+
let status: $type;
17+
println!("{}",
18+
status);
19+
status == 0
20+
}
21+
}
22+
};
23+
24+
// the println macro should be rewritten here
25+
($type:ty) => {
26+
fn some_func(self) {
27+
let status: $type;
28+
println!("{}", status);
29+
}
30+
};
31+
32+
// unrewritale macro in func
33+
($type:ty, $ldrex:expr) => {
34+
unsafe fn load_excl(address: usize) -> Self {
35+
let raw: $type;
36+
asm!($ldrex
37+
: "=r"(raw)
38+
: "r"(address)
39+
:
40+
: "volatile");
41+
raw
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)