From 6f318e3ceff807a1f2e63a0b73aa5c1a4a27519a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Campinas?= Date: Fri, 7 Sep 2018 14:48:52 +0200 Subject: [PATCH] propagate errors about failing to rewrite a macro --- src/expr.rs | 3 +++ src/items.rs | 8 ++++++ src/macros.rs | 13 +++++++++- src/visitor.rs | 10 +++++--- tests/source/issue-2977/impl.rs | 44 ++++++++++++++++++++++++++++++++ tests/source/issue-2977/trait.rs | 44 ++++++++++++++++++++++++++++++++ tests/target/issue-2977/block.rs | 11 ++++++++ tests/target/issue-2977/impl.rs | 44 ++++++++++++++++++++++++++++++++ tests/target/issue-2977/item.rs | 11 ++++++++ tests/target/issue-2977/trait.rs | 44 ++++++++++++++++++++++++++++++++ 10 files changed, 228 insertions(+), 4 deletions(-) create mode 100644 tests/source/issue-2977/impl.rs create mode 100644 tests/source/issue-2977/trait.rs create mode 100644 tests/target/issue-2977/block.rs create mode 100644 tests/target/issue-2977/impl.rs create mode 100644 tests/target/issue-2977/item.rs create mode 100644 tests/target/issue-2977/trait.rs diff --git a/src/expr.rs b/src/expr.rs index 329081f5d704..722898b81504 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -522,6 +522,9 @@ pub fn rewrite_block_with_visitor( let inner_attrs = attrs.map(inner_attributes); let label_str = rewrite_label(label); visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } Some(format!("{}{}{}", prefix, label_str, visitor.buffer)) } diff --git a/src/items.rs b/src/items.rs index 7f8980dd1506..9dfc4c584cd6 100644 --- a/src/items.rs +++ b/src/items.rs @@ -747,6 +747,10 @@ pub fn format_impl( visitor.format_missing(item.span.hi() - BytePos(1)); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } + let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config); @@ -1106,6 +1110,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) visitor.format_missing(item.span.hi() - BytePos(1)); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } + let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config); diff --git a/src/macros.rs b/src/macros.rs index 6aae1b23f0c6..6e52b63363d4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -69,6 +69,9 @@ impl Rewrite for ast::Item { visitor.block_indent = shape.indent; visitor.last_pos = self.span().lo(); visitor.visit_item(self); + if visitor.macro_rewrite_failure { + context.macro_rewrite_failure.replace(true); + } Some(visitor.buffer) } } @@ -406,7 +409,15 @@ pub fn rewrite_macro_def( ";", |branch| branch.span.lo(), |branch| branch.span.hi(), - |branch| branch.rewrite(context, arm_shape, multi_branch_style), + |branch| match branch.rewrite(context, arm_shape, multi_branch_style) { + Some(v) => Some(v), + // if the rewrite returned None because a macro could not be rewritten, then return the + // original body + None if *context.macro_rewrite_failure.borrow() == true => { + Some(context.snippet(branch.body).trim().to_string()) + } + None => None, + }, context.snippet_provider.span_after(span, "{"), span.hi(), false, diff --git a/src/visitor.rs b/src/visitor.rs index e6ef7f23da04..c622de6ef489 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -97,7 +97,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { if contains_skip(get_attrs_from_stmt(stmt)) { self.push_skipped_with_span(stmt.span()); } else { - let rewrite = stmt.rewrite(&self.get_context(), self.shape()); + let shape = self.shape().clone(); + let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); self.push_rewrite(stmt.span(), rewrite) } } @@ -350,11 +351,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let where_span_end = snippet .find_uncommented("{") .map(|x| BytePos(x as u32) + source!(self, item.span).lo()); - let rw = format_impl(&self.get_context(), item, self.block_indent, where_span_end); + let block_indent = self.block_indent.clone(); + let rw = + self.with_context(|ctx| format_impl(&ctx, item, block_indent, where_span_end)); self.push_rewrite(item.span, rw); } ast::ItemKind::Trait(..) => { - let rw = format_trait(&self.get_context(), item, self.block_indent); + let block_indent = self.block_indent.clone(); + let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent)); self.push_rewrite(item.span, rw); } ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => { diff --git a/tests/source/issue-2977/impl.rs b/tests/source/issue-2977/impl.rs new file mode 100644 index 000000000000..8d7bb9414eb7 --- /dev/null +++ b/tests/source/issue-2977/impl.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + impl AtomicBits for $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +} diff --git a/tests/source/issue-2977/trait.rs b/tests/source/issue-2977/trait.rs new file mode 100644 index 000000000000..ae20668cd75f --- /dev/null +++ b/tests/source/issue-2977/trait.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + trait $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +} diff --git a/tests/target/issue-2977/block.rs b/tests/target/issue-2977/block.rs new file mode 100644 index 000000000000..d376e370c72e --- /dev/null +++ b/tests/target/issue-2977/block.rs @@ -0,0 +1,11 @@ +macro_rules! atomic_bits { + ($ldrex:expr) => { + execute(|| { + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + }) + }; +} diff --git a/tests/target/issue-2977/impl.rs b/tests/target/issue-2977/impl.rs new file mode 100644 index 000000000000..8d7bb9414eb7 --- /dev/null +++ b/tests/target/issue-2977/impl.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + impl AtomicBits for $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +} diff --git a/tests/target/issue-2977/item.rs b/tests/target/issue-2977/item.rs new file mode 100644 index 000000000000..857065ca93f7 --- /dev/null +++ b/tests/target/issue-2977/item.rs @@ -0,0 +1,11 @@ +macro_rules! atomic_bits { + ($ldrex:expr) => { + some_macro!(pub fn foo() { + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + }) + }; +} diff --git a/tests/target/issue-2977/trait.rs b/tests/target/issue-2977/trait.rs new file mode 100644 index 000000000000..ae20668cd75f --- /dev/null +++ b/tests/target/issue-2977/trait.rs @@ -0,0 +1,44 @@ +macro_rules! atomic_bits { + // the println macro cannot be rewritten because of the asm macro + ($type:ty, $ldrex:expr, $strex:expr) => { + trait $type { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + + unsafe fn store_excl(self, address: usize) -> bool { + let status: $type; + println!("{}", + status); + status == 0 + } + } + }; + + // the println macro should be rewritten here + ($type:ty) => { + fn some_func(self) { + let status: $type; + println!("{}", status); + } + }; + + // unrewritale macro in func + ($type:ty, $ldrex:expr) => { + unsafe fn load_excl(address: usize) -> Self { + let raw: $type; + asm!($ldrex + : "=r"(raw) + : "r"(address) + : + : "volatile"); + raw + } + } +}