Auto merge of #127014 - jhpratt:rollup-45ic8f5, r=jhpratt

Rollup of 6 pull requests

Successful merges:

 - #126571 (Less `maybe_whole_expr`, take 2)
 - #126721 (coverage: Make `#[coverage(..)]` apply recursively to nested functions)
 - #126928 (Some `Nonterminal` removal precursors)
 - #126929 (Remove `__rust_force_expr`.)
 - #126980 (set self.is_known_utf8 to false in extend_from_slice)
 - #126983 (Remove `f16` and `f128` ICE paths from smir)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-06-27 07:54:44 +00:00
commit 127fa2261b
37 changed files with 560 additions and 399 deletions

View File

@ -327,7 +327,8 @@ impl MetaItem {
I: Iterator<Item = &'a TokenTree>,
{
// FIXME: Share code with `parse_path`.
let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() {
let tt = tokens.next().map(|tt| TokenTree::uninterpolate(tt));
let path = match tt.as_deref() {
Some(&TokenTree::Token(
Token { kind: ref kind @ (token::Ident(..) | token::PathSep), span },
_,
@ -368,6 +369,12 @@ impl MetaItem {
token::Nonterminal::NtPath(path) => (**path).clone(),
_ => return None,
},
Some(TokenTree::Token(
Token { kind: token::OpenDelim(_) | token::CloseDelim(_), .. },
_,
)) => {
panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tt);
}
_ => return None,
};
let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi());

View File

@ -224,7 +224,7 @@ impl AttrTokenStream {
// Inner attributes are only supported on extern blocks, functions,
// impls, and modules. All of these have their inner attributes
// placed at the beginning of the rightmost outermost braced group:
// e.g. fn foo() { #![my_attr} }
// e.g. fn foo() { #![my_attr] }
//
// Therefore, we can insert them back into the right location
// without needing to do any extra position tracking.

View File

@ -124,22 +124,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
.emit();
}
}
sym::coverage => {
let inner = attr.meta_item_list();
match inner.as_deref() {
Some([item]) if item.has_name(sym::off) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
}
Some([item]) if item.has_name(sym::on) => {
// Allow #[coverage(on)] for being explicit, maybe also in future to enable
// coverage on a smaller scope within an excluded larger scope.
}
Some(_) | None => {
tcx.dcx()
.span_delayed_bug(attr.span, "unexpected value of coverage attribute");
}
}
}
sym::rustc_std_internal_symbol => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
}
@ -584,7 +568,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
codegen_fn_attrs.inline = InlineAttr::Never;
}

View File

@ -214,6 +214,12 @@ impl<'a> StripUnconfigured<'a> {
) => {
panic!("Nonterminal should have been flattened: {:?}", tree);
}
AttrTokenTree::Token(
Token { kind: TokenKind::OpenDelim(_) | TokenKind::CloseDelim(_), .. },
_,
) => {
panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tree);
}
AttrTokenTree::Token(token, spacing) => {
Some(AttrTokenTree::Token(token, spacing)).into_iter()
}

View File

@ -87,10 +87,7 @@ bitflags::bitflags! {
/// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a
/// function as an entry function from Non-Secure code.
const CMSE_NONSECURE_ENTRY = 1 << 13;
/// `#[coverage(off)]`: indicates that the function should be ignored by
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
/// during codegen.
const NO_COVERAGE = 1 << 14;
// (Bit 14 was used for `#[coverage(off)]`, but is now unused.)
/// `#[used(linker)]`:
/// indicates that neither LLVM nor the linker will eliminate this function.
const USED_LINKER = 1 << 15;

View File

@ -572,6 +572,15 @@ rustc_queries! {
separate_provide_extern
}
/// Checks for the nearest `#[coverage(off)]` or `#[coverage(on)]` on
/// this def and any enclosing defs, up to the crate root.
///
/// Returns `false` if `#[coverage(off)]` was found, or `true` if
/// either `#[coverage(on)]` or no coverage attribute was found.
query coverage_attr_on(key: LocalDefId) -> bool {
desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) }
}
/// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass
/// (for compiler option `-Cinstrument-coverage`), after MIR optimizations
/// have had a chance to potentially remove some of them.

View File

@ -6,11 +6,13 @@ use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::util::Providers;
use rustc_span::def_id::LocalDefId;
use rustc_span::sym;
/// Registers query/hook implementations related to coverage.
pub(crate) fn provide(providers: &mut Providers) {
providers.hooks.is_eligible_for_coverage =
|TyCtxtAt { tcx, .. }, def_id| is_eligible_for_coverage(tcx, def_id);
providers.queries.coverage_attr_on = coverage_attr_on;
providers.queries.coverage_ids_info = coverage_ids_info;
}
@ -38,7 +40,12 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
return false;
}
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_COVERAGE) {
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) {
trace!("InstrumentCoverage skipped for {def_id:?} (`#[naked]`)");
return false;
}
if !tcx.coverage_attr_on(def_id) {
trace!("InstrumentCoverage skipped for {def_id:?} (`#[coverage(off)]`)");
return false;
}
@ -46,6 +53,30 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
true
}
/// Query implementation for `coverage_attr_on`.
fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
// Check for annotations directly on this def.
if let Some(attr) = tcx.get_attr(def_id, sym::coverage) {
match attr.meta_item_list().as_deref() {
Some([item]) if item.has_name(sym::off) => return false,
Some([item]) if item.has_name(sym::on) => return true,
Some(_) | None => {
// Other possibilities should have been rejected by `rustc_parse::validate_attr`.
tcx.dcx().span_bug(attr.span, "unexpected value of coverage attribute");
}
}
}
match tcx.opt_local_parent(def_id) {
// Check the parent def (and so on recursively) until we find an
// enclosing attribute or reach the crate root.
Some(parent) => tcx.coverage_attr_on(parent),
// We reached the crate root without seeing a coverage attribute, so
// allow coverage instrumentation by default.
None => true,
}
}
/// Query implementation for `coverage_ids_info`.
fn coverage_ids_info<'tcx>(
tcx: TyCtxt<'tcx>,

View File

@ -39,36 +39,6 @@ use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span};
use thin_vec::{thin_vec, ThinVec};
use tracing::instrument;
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
/// dropped into the token stream, which happens while parsing the result of
/// macro expansion). Placement of these is not as complex as I feared it would
/// be. The important thing is to make sure that lookahead doesn't balk at
/// `token::Interpolated` tokens.
macro_rules! maybe_whole_expr {
($p:expr) => {
if let token::Interpolated(nt) = &$p.token.kind {
match &**nt {
token::NtExpr(e) | token::NtLiteral(e) => {
let e = e.clone();
$p.bump();
return Ok(e);
}
token::NtPath(path) => {
let path = (**path).clone();
$p.bump();
return Ok($p.mk_expr($p.prev_token.span, ExprKind::Path(None, path)));
}
token::NtBlock(block) => {
let block = block.clone();
$p.bump();
return Ok($p.mk_expr($p.prev_token.span, ExprKind::Block(block, None)));
}
_ => {}
};
}
};
}
#[derive(Debug)]
pub(super) enum LhsExpr {
// Already parsed just the outer attributes.
@ -1421,7 +1391,27 @@ impl<'a> Parser<'a> {
/// correctly if called from `parse_dot_or_call_expr()`.
fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
maybe_recover_from_interpolated_ty_qpath!(self, true);
maybe_whole_expr!(self);
if let token::Interpolated(nt) = &self.token.kind {
match &**nt {
token::NtExpr(e) | token::NtLiteral(e) => {
let e = e.clone();
self.bump();
return Ok(e);
}
token::NtPath(path) => {
let path = (**path).clone();
self.bump();
return Ok(self.mk_expr(self.prev_token.span, ExprKind::Path(None, path)));
}
token::NtBlock(block) => {
let block = block.clone();
self.bump();
return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None)));
}
_ => {}
};
}
// Outer attributes are already parsed and will be
// added to the return value after the fact.
@ -2190,7 +2180,26 @@ impl<'a> Parser<'a> {
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
maybe_whole_expr!(self);
if let token::Interpolated(nt) = &self.token.kind {
match &**nt {
// FIXME(nnethercote) The `NtExpr` case should only match if
// `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing
// an `UnOp::Neg` and an `ExprKind::Lit`, like how
// `can_begin_literal_maybe_minus` works. But this method has
// been over-accepting for a long time, and to make that change
// here requires also changing some `parse_literal_maybe_minus`
// call sites to accept additional expression kinds. E.g.
// `ExprKind::Path` must be accepted when parsing range
// patterns. That requires some care. So for now, we continue
// being less strict here than we should be.
token::NtExpr(e) | token::NtLiteral(e) => {
let e = e.clone();
self.bump();
return Ok(e);
}
_ => {}
};
}
let lo = self.token.span;
let minus_present = self.eat(&token::BinOp(token::Minus));

View File

@ -369,13 +369,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
/// Checks that `#[coverage(..)]` is applied to a function or closure.
/// Checks that `#[coverage(..)]` is applied to a function/closure/method,
/// or to an impl block or module.
fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) -> bool {
match target {
// #[coverage(..)] on function is fine
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
| Target::Impl
| Target::Mod => true,
_ => {
self.dcx().emit_err(errors::CoverageNotFnOrClosure {
attr_span: attr.span,

View File

@ -188,8 +188,10 @@ impl RustcInternal for FloatTy {
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
FloatTy::F16 => rustc_ty::FloatTy::F16,
FloatTy::F32 => rustc_ty::FloatTy::F32,
FloatTy::F64 => rustc_ty::FloatTy::F64,
FloatTy::F128 => rustc_ty::FloatTy::F128,
}
}
}

View File

@ -304,10 +304,10 @@ impl<'tcx> Stable<'tcx> for ty::FloatTy {
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::FloatTy::F16 => unimplemented!("f16_f128"),
ty::FloatTy::F16 => FloatTy::F16,
ty::FloatTy::F32 => FloatTy::F32,
ty::FloatTy::F64 => FloatTy::F64,
ty::FloatTy::F128 => unimplemented!("f16_f128"),
ty::FloatTy::F128 => FloatTy::F128,
}
}
}

View File

@ -608,8 +608,10 @@ impl UintTy {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FloatTy {
F16,
F32,
F64,
F128,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]

View File

@ -41,18 +41,18 @@
#[allow_internal_unstable(rustc_attrs, liballoc_internals)]
macro_rules! vec {
() => (
$crate::__rust_force_expr!($crate::vec::Vec::new())
$crate::vec::Vec::new()
);
($elem:expr; $n:expr) => (
$crate::__rust_force_expr!($crate::vec::from_elem($elem, $n))
$crate::vec::from_elem($elem, $n)
);
($($x:expr),+ $(,)?) => (
$crate::__rust_force_expr!(<[_]>::into_vec(
<[_]>::into_vec(
// This rustc_box is not required, but it produces a dramatic improvement in compile
// time when constructing arrays with many elements.
#[rustc_box]
$crate::boxed::Box::new([$($x),+])
))
)
);
}
@ -126,13 +126,3 @@ macro_rules! format {
res
}}
}
/// Force AST node to an expression to improve diagnostics in pattern position.
#[doc(hidden)]
#[macro_export]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
macro_rules! __rust_force_expr {
($e:expr) => {
$e
};
}

View File

@ -480,7 +480,7 @@ impl Wtf8Buf {
#[inline]
pub(crate) fn extend_from_slice(&mut self, other: &[u8]) {
self.bytes.extend_from_slice(other);
self.is_known_utf8 = self.is_known_utf8 || self.next_surrogate(0).is_none();
self.is_known_utf8 = false;
}
}

View File

@ -725,3 +725,27 @@ fn wtf8_utf8_boundary_between_surrogates() {
string.push(CodePoint::from_u32(0xD800).unwrap());
check_utf8_boundary(&string, 3);
}
#[test]
fn wobbled_wtf8_plus_bytes_isnt_utf8() {
let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
assert!(!string.is_known_utf8);
string.extend_from_slice(b"some utf-8");
assert!(!string.is_known_utf8);
}
#[test]
fn wobbled_wtf8_plus_str_isnt_utf8() {
let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
assert!(!string.is_known_utf8);
string.push_str("some utf-8");
assert!(!string.is_known_utf8);
}
#[test]
fn unwobbly_wtf8_plus_utf8_is_utf8() {
let mut string: Wtf8Buf = Wtf8Buf::from_str("hello world");
assert!(string.is_known_utf8);
string.push_str("some utf-8");
assert!(string.is_known_utf8);
}

View File

@ -0,0 +1,24 @@
Function name: <impl::MyStruct>::off_on (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 05, 00, 13]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 14, 5) to (start + 0, 19)
Function name: <impl::MyStruct>::on_inherit (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 05, 00, 17]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 22, 5) to (start + 0, 23)
Function name: <impl::MyStruct>::on_on (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 12]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 25, 5) to (start + 0, 18)

View File

@ -0,0 +1,42 @@
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2021
LL| |
LL| |// Checks that `#[coverage(..)]` can be applied to impl and impl-trait blocks,
LL| |// and is inherited by any enclosed functions.
LL| |
LL| |struct MyStruct;
LL| |
LL| |#[coverage(off)]
LL| |impl MyStruct {
LL| | fn off_inherit() {}
LL| |
LL| | #[coverage(on)]
LL| 0| fn off_on() {}
LL| |
LL| | #[coverage(off)]
LL| | fn off_off() {}
LL| |}
LL| |
LL| |#[coverage(on)]
LL| |impl MyStruct {
LL| 0| fn on_inherit() {}
LL| |
LL| | #[coverage(on)]
LL| 0| fn on_on() {}
LL| |
LL| | #[coverage(off)]
LL| | fn on_off() {}
LL| |}
LL| |
LL| |trait MyTrait {
LL| | fn method();
LL| |}
LL| |
LL| |#[coverage(off)]
LL| |impl MyTrait for MyStruct {
LL| | fn method() {}
LL| |}
LL| |
LL| |#[coverage(off)]
LL| |fn main() {}

View File

@ -0,0 +1,41 @@
#![feature(coverage_attribute)]
//@ edition: 2021
// Checks that `#[coverage(..)]` can be applied to impl and impl-trait blocks,
// and is inherited by any enclosed functions.
struct MyStruct;
#[coverage(off)]
impl MyStruct {
fn off_inherit() {}
#[coverage(on)]
fn off_on() {}
#[coverage(off)]
fn off_off() {}
}
#[coverage(on)]
impl MyStruct {
fn on_inherit() {}
#[coverage(on)]
fn on_on() {}
#[coverage(off)]
fn on_off() {}
}
trait MyTrait {
fn method();
}
#[coverage(off)]
impl MyTrait for MyStruct {
fn method() {}
}
#[coverage(off)]
fn main() {}

View File

@ -0,0 +1,24 @@
Function name: module::off::on (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 0c, 05, 00, 0f]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 12, 5) to (start + 0, 15)
Function name: module::on::inherit (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 14, 05, 00, 14]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 20, 5) to (start + 0, 20)
Function name: module::on::on (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 05, 00, 0f]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 23, 5) to (start + 0, 15)

View File

@ -0,0 +1,38 @@
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2021
LL| |
LL| |// Checks that `#[coverage(..)]` can be applied to modules, and is inherited
LL| |// by any enclosed functions.
LL| |
LL| |#[coverage(off)]
LL| |mod off {
LL| | fn inherit() {}
LL| |
LL| | #[coverage(on)]
LL| 0| fn on() {}
LL| |
LL| | #[coverage(off)]
LL| | fn off() {}
LL| |}
LL| |
LL| |#[coverage(on)]
LL| |mod on {
LL| 0| fn inherit() {}
LL| |
LL| | #[coverage(on)]
LL| 0| fn on() {}
LL| |
LL| | #[coverage(off)]
LL| | fn off() {}
LL| |}
LL| |
LL| |#[coverage(off)]
LL| |mod nested_a {
LL| | mod nested_b {
LL| | fn inner() {}
LL| | }
LL| |}
LL| |
LL| |#[coverage(off)]
LL| |fn main() {}

View File

@ -0,0 +1,37 @@
#![feature(coverage_attribute)]
//@ edition: 2021
// Checks that `#[coverage(..)]` can be applied to modules, and is inherited
// by any enclosed functions.
#[coverage(off)]
mod off {
fn inherit() {}
#[coverage(on)]
fn on() {}
#[coverage(off)]
fn off() {}
}
#[coverage(on)]
mod on {
fn inherit() {}
#[coverage(on)]
fn on() {}
#[coverage(off)]
fn off() {}
}
#[coverage(off)]
mod nested_a {
mod nested_b {
fn inner() {}
}
}
#[coverage(off)]
fn main() {}

View File

@ -1,35 +1,3 @@
Function name: <<<nested::MyOuter as nested::MyTrait>::trait_method::MyMiddle as nested::MyTrait>::trait_method::MyInner as nested::MyTrait>::trait_method (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 39, 15, 02, 16]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 57, 21) to (start + 2, 22)
Function name: <<<nested::MyOuter>::outer_method::MyMiddle>::middle_method::MyInner>::inner_method (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 23, 15, 02, 16]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 35, 21) to (start + 2, 22)
Function name: <<nested::MyOuter as nested::MyTrait>::trait_method::MyMiddle as nested::MyTrait>::trait_method (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 36, 0d, 08, 0e]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 54, 13) to (start + 8, 14)
Function name: <<nested::MyOuter>::outer_method::MyMiddle>::middle_method (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 20, 0d, 08, 0e]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 32, 13) to (start + 8, 14)
Function name: nested::closure_expr
Raw bytes (14): 0x[01, 01, 00, 02, 01, 44, 01, 01, 0f, 01, 0b, 05, 01, 02]
Number of files: 1
@ -39,23 +7,6 @@ Number of file 0 mappings: 2
- Code(Counter(0)) at (prev + 68, 1) to (start + 1, 15)
- Code(Counter(0)) at (prev + 11, 5) to (start + 1, 2)
Function name: nested::closure_expr::{closure#0}::{closure#0} (unused)
Raw bytes (14): 0x[01, 01, 00, 02, 00, 47, 1a, 01, 17, 00, 04, 0d, 01, 0a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
- Code(Zero) at (prev + 71, 26) to (start + 1, 23)
- Code(Zero) at (prev + 4, 13) to (start + 1, 10)
Function name: nested::closure_expr::{closure#0}::{closure#0}::{closure#0} (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 48, 1d, 02, 0e]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 72, 29) to (start + 2, 14)
Function name: nested::closure_tail
Raw bytes (14): 0x[01, 01, 00, 02, 01, 53, 01, 01, 0f, 01, 11, 05, 01, 02]
Number of files: 1
@ -65,36 +16,3 @@ Number of file 0 mappings: 2
- Code(Counter(0)) at (prev + 83, 1) to (start + 1, 15)
- Code(Counter(0)) at (prev + 17, 5) to (start + 1, 2)
Function name: nested::closure_tail::{closure#0}::{closure#0} (unused)
Raw bytes (14): 0x[01, 01, 00, 02, 00, 58, 14, 01, 1f, 00, 06, 15, 01, 12]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 2
- Code(Zero) at (prev + 88, 20) to (start + 1, 31)
- Code(Zero) at (prev + 6, 21) to (start + 1, 18)
Function name: nested::closure_tail::{closure#0}::{closure#0}::{closure#0} (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 1c, 02, 1a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 90, 28) to (start + 2, 26)
Function name: nested::outer_fn::middle_fn (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 05, 05, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 17, 5) to (start + 5, 6)
Function name: nested::outer_fn::middle_fn::inner_fn (unused)
Raw bytes (9): 0x[01, 01, 00, 01, 00, 12, 09, 02, 0a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Zero) at (prev + 18, 9) to (start + 2, 10)

View File

@ -14,12 +14,12 @@
LL| |
LL| |#[coverage(off)]
LL| |fn outer_fn() {
LL| 0| fn middle_fn() {
LL| 0| fn inner_fn() {
LL| 0| do_stuff();
LL| 0| }
LL| 0| do_stuff();
LL| 0| }
LL| | fn middle_fn() {
LL| | fn inner_fn() {
LL| | do_stuff();
LL| | }
LL| | do_stuff();
LL| | }
LL| | do_stuff();
LL| |}
LL| |
@ -29,15 +29,15 @@
LL| | fn outer_method(&self) {
LL| | struct MyMiddle;
LL| | impl MyMiddle {
LL| 0| fn middle_method(&self) {
LL| 0| struct MyInner;
LL| 0| impl MyInner {
LL| 0| fn inner_method(&self) {
LL| 0| do_stuff();
LL| 0| }
LL| 0| }
LL| 0| do_stuff();
LL| 0| }
LL| | fn middle_method(&self) {
LL| | struct MyInner;
LL| | impl MyInner {
LL| | fn inner_method(&self) {
LL| | do_stuff();
LL| | }
LL| | }
LL| | do_stuff();
LL| | }
LL| | }
LL| | do_stuff();
LL| | }
@ -51,15 +51,15 @@
LL| | fn trait_method(&self) {
LL| | struct MyMiddle;
LL| | impl MyTrait for MyMiddle {
LL| 0| fn trait_method(&self) {
LL| 0| struct MyInner;
LL| 0| impl MyTrait for MyInner {
LL| 0| fn trait_method(&self) {
LL| 0| do_stuff();
LL| 0| }
LL| 0| }
LL| 0| do_stuff();
LL| 0| }
LL| | fn trait_method(&self) {
LL| | struct MyInner;
LL| | impl MyTrait for MyInner {
LL| | fn trait_method(&self) {
LL| | do_stuff();
LL| | }
LL| | }
LL| | do_stuff();
LL| | }
LL| | }
LL| | do_stuff();
LL| | }
@ -68,12 +68,12 @@
LL| 1|fn closure_expr() {
LL| 1| let _outer = #[coverage(off)]
LL| | || {
LL| 0| let _middle = || {
LL| 0| let _inner = || {
LL| 0| do_stuff();
LL| 0| };
LL| 0| do_stuff();
LL| 0| };
LL| | let _middle = || {
LL| | let _inner = || {
LL| | do_stuff();
LL| | };
LL| | do_stuff();
LL| | };
LL| | do_stuff();
LL| | };
LL| 1| do_stuff();
@ -85,14 +85,14 @@
LL| | #[coverage(off)]
LL| | || {
LL| | let _middle = {
LL| 0| || {
LL| 0| let _inner = {
LL| 0| || {
LL| 0| do_stuff();
LL| 0| }
LL| | || {
LL| | let _inner = {
LL| | || {
LL| | do_stuff();
LL| | }
LL| | };
LL| 0| do_stuff();
LL| 0| }
LL| | do_stuff();
LL| | }
LL| | };
LL| | do_stuff();
LL| | }

View File

@ -6,14 +6,6 @@ Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 20, 5) to (start + 7, 6)
Function name: off_on_sandwich::sparse_a::sparse_b
Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 05, 10, 06]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
- Code(Counter(0)) at (prev + 34, 5) to (start + 16, 6)
Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c
Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 09, 0b, 0a]
Number of files: 1

View File

@ -31,10 +31,10 @@
LL| |fn sparse_a() {
LL| | sparse_b();
LL| | sparse_b();
LL| 2| fn sparse_b() {
LL| 2| sparse_c();
LL| 2| sparse_c();
LL| 2| #[coverage(on)]
LL| | fn sparse_b() {
LL| | sparse_c();
LL| | sparse_c();
LL| | #[coverage(on)]
LL| 4| fn sparse_c() {
LL| 4| sparse_d();
LL| 4| sparse_d();
@ -47,7 +47,7 @@
LL| 8| }
LL| 8| }
LL| 4| }
LL| 2| }
LL| | }
LL| |}
LL| |
LL| |#[coverage(off)]

View File

@ -59,16 +59,3 @@ Number of file 0 mappings: 4
= (c0 - c1)
- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10)
Function name: no_cov_crate::nested_fns::outer_not_covered::inner
Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 26, 09, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a]
Number of files: 1
- file 0 => global file 1
Number of expressions: 1
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 4
- Code(Counter(0)) at (prev + 38, 9) to (start + 1, 23)
- Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14)
- Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14)
= (c0 - c1)
- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10)

View File

@ -35,13 +35,13 @@
LL| |mod nested_fns {
LL| | #[coverage(off)]
LL| | pub fn outer_not_covered(is_true: bool) {
LL| 1| fn inner(is_true: bool) {
LL| 1| if is_true {
LL| 1| println!("called and covered");
LL| 1| } else {
LL| 0| println!("absolutely not covered");
LL| 0| }
LL| 1| }
LL| | fn inner(is_true: bool) {
LL| | if is_true {
LL| | println!("called and covered");
LL| | } else {
LL| | println!("absolutely not covered");
LL| | }
LL| | }
LL| | println!("called but not covered");
LL| | inner(is_true);
LL| | }

View File

@ -10,13 +10,11 @@
#[coverage = "off"]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
mod my_mod {}
mod my_mod_inner {
#![coverage = "off"]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
}
#[coverage = "off"]
@ -26,7 +24,6 @@ struct MyStruct;
#[coverage = "off"]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
impl MyStruct {
#[coverage = "off"]
//~^ ERROR malformed `coverage` attribute input
@ -51,7 +48,6 @@ trait MyTrait {
#[coverage = "off"]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
impl MyTrait for MyStruct {
#[coverage = "off"]
//~^ ERROR malformed `coverage` attribute input

View File

@ -12,7 +12,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:17:5
--> $DIR/name-value.rs:16:5
|
LL | #![coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^^
@ -25,7 +25,7 @@ LL | #![coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:22:1
--> $DIR/name-value.rs:20:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -38,7 +38,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:31:5
--> $DIR/name-value.rs:28:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -51,7 +51,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:27:1
--> $DIR/name-value.rs:25:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -64,7 +64,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:41:5
--> $DIR/name-value.rs:38:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -77,7 +77,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:46:5
--> $DIR/name-value.rs:43:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -90,7 +90,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:37:1
--> $DIR/name-value.rs:34:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -103,7 +103,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:56:5
--> $DIR/name-value.rs:52:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -116,7 +116,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:61:5
--> $DIR/name-value.rs:57:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -129,7 +129,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:52:1
--> $DIR/name-value.rs:49:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -142,7 +142,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/name-value.rs:67:1
--> $DIR/name-value.rs:63:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -155,27 +155,7 @@ LL | #[coverage(on)]
|
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:11:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
...
LL | mod my_mod {}
| ------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:17:5
|
LL | / mod my_mod_inner {
LL | | #![coverage = "off"]
| | ^^^^^^^^^^^^^^^^^^^^
LL | |
LL | |
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:22:1
--> $DIR/name-value.rs:20:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -184,21 +164,7 @@ LL | struct MyStruct;
| ---------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:27:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
...
LL | / impl MyStruct {
LL | | #[coverage = "off"]
LL | |
LL | |
LL | | const X: u32 = 7;
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:37:1
--> $DIR/name-value.rs:34:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -213,22 +179,7 @@ LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:52:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
...
LL | / impl MyTrait for MyStruct {
LL | | #[coverage = "off"]
LL | |
LL | |
... |
LL | | type T = ();
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:41:5
--> $DIR/name-value.rs:38:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -237,7 +188,7 @@ LL | const X: u32;
| ------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:46:5
--> $DIR/name-value.rs:43:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -246,7 +197,7 @@ LL | type T;
| ------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:31:5
--> $DIR/name-value.rs:28:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -255,7 +206,7 @@ LL | const X: u32 = 7;
| ----------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:56:5
--> $DIR/name-value.rs:52:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -264,7 +215,7 @@ LL | const X: u32 = 8;
| ----------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/name-value.rs:61:5
--> $DIR/name-value.rs:57:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
@ -272,6 +223,6 @@ LL | #[coverage = "off"]
LL | type T = ();
| ------------ not a function or closure
error: aborting due to 23 previous errors
error: aborting due to 19 previous errors
For more information about this error, try `rustc --explain E0788`.

View File

@ -2,7 +2,7 @@
#![feature(coverage_attribute)]
#![feature(impl_trait_in_assoc_type)]
#![warn(unused_attributes)]
#![coverage(off)] //~ ERROR attribute should be applied to a function definition or closure
#![coverage(off)]
#[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure
trait Trait {
@ -15,7 +15,7 @@ trait Trait {
type U;
}
#[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure
#[coverage(off)]
impl Trait for () {
const X: u32 = 0;

View File

@ -11,20 +11,6 @@ LL | | type U;
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/no-coverage.rs:18:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | / impl Trait for () {
LL | | const X: u32 = 0;
LL | |
LL | | #[coverage(off)]
... |
LL | | type U = impl Trait;
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/no-coverage.rs:39:5
|
@ -97,12 +83,6 @@ LL | #[coverage(off)]
LL | type T;
| ------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/no-coverage.rs:5:1
|
LL | #![coverage(off)]
| ^^^^^^^^^^^^^^^^^ not a function or closure
error: unconstrained opaque type
--> $DIR/no-coverage.rs:26:14
|
@ -111,6 +91,6 @@ LL | type U = impl Trait;
|
= note: `U` must be used in combination with a concrete type within the same impl
error: aborting due to 13 previous errors
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0788`.

View File

@ -10,13 +10,11 @@
#[coverage]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
mod my_mod {}
mod my_mod_inner {
#![coverage]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
}
#[coverage]
@ -26,7 +24,6 @@ struct MyStruct;
#[coverage]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
impl MyStruct {
#[coverage]
//~^ ERROR malformed `coverage` attribute input
@ -51,7 +48,6 @@ trait MyTrait {
#[coverage]
//~^ ERROR malformed `coverage` attribute input
//~| ERROR attribute should be applied to a function definition or closure
impl MyTrait for MyStruct {
#[coverage]
//~^ ERROR malformed `coverage` attribute input

View File

@ -12,7 +12,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:17:5
--> $DIR/word-only.rs:16:5
|
LL | #![coverage]
| ^^^^^^^^^^^^
@ -25,7 +25,7 @@ LL | #![coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:22:1
--> $DIR/word-only.rs:20:1
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -38,7 +38,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:31:5
--> $DIR/word-only.rs:28:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -51,7 +51,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:27:1
--> $DIR/word-only.rs:25:1
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -64,7 +64,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:41:5
--> $DIR/word-only.rs:38:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -77,7 +77,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:46:5
--> $DIR/word-only.rs:43:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -90,7 +90,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:37:1
--> $DIR/word-only.rs:34:1
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -103,7 +103,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:56:5
--> $DIR/word-only.rs:52:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -116,7 +116,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:61:5
--> $DIR/word-only.rs:57:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -129,7 +129,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:52:1
--> $DIR/word-only.rs:49:1
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -142,7 +142,7 @@ LL | #[coverage(on)]
|
error: malformed `coverage` attribute input
--> $DIR/word-only.rs:67:1
--> $DIR/word-only.rs:63:1
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -155,27 +155,7 @@ LL | #[coverage(on)]
|
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:11:1
|
LL | #[coverage]
| ^^^^^^^^^^^
...
LL | mod my_mod {}
| ------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:17:5
|
LL | / mod my_mod_inner {
LL | | #![coverage]
| | ^^^^^^^^^^^^
LL | |
LL | |
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:22:1
--> $DIR/word-only.rs:20:1
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -184,21 +164,7 @@ LL | struct MyStruct;
| ---------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:27:1
|
LL | #[coverage]
| ^^^^^^^^^^^
...
LL | / impl MyStruct {
LL | | #[coverage]
LL | |
LL | |
LL | | const X: u32 = 7;
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:37:1
--> $DIR/word-only.rs:34:1
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -213,22 +179,7 @@ LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:52:1
|
LL | #[coverage]
| ^^^^^^^^^^^
...
LL | / impl MyTrait for MyStruct {
LL | | #[coverage]
LL | |
LL | |
... |
LL | | type T = ();
LL | | }
| |_- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:41:5
--> $DIR/word-only.rs:38:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -237,7 +188,7 @@ LL | const X: u32;
| ------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:46:5
--> $DIR/word-only.rs:43:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -246,7 +197,7 @@ LL | type T;
| ------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:31:5
--> $DIR/word-only.rs:28:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -255,7 +206,7 @@ LL | const X: u32 = 7;
| ----------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:56:5
--> $DIR/word-only.rs:52:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -264,7 +215,7 @@ LL | const X: u32 = 8;
| ----------------- not a function or closure
error[E0788]: attribute should be applied to a function definition or closure
--> $DIR/word-only.rs:61:5
--> $DIR/word-only.rs:57:5
|
LL | #[coverage]
| ^^^^^^^^^^^
@ -272,6 +223,6 @@ LL | #[coverage]
LL | type T = ();
| ------------ not a function or closure
error: aborting due to 23 previous errors
error: aborting due to 19 previous errors
For more information about this error, try `rustc --explain E0788`.

View File

@ -23,4 +23,34 @@ simple_nonterminal!(a, 'a, (x, y, z)); // OK
complex_nonterminal!(enum E {});
// `ident`, `lifetime`, and `tt` all work. Other fragments do not. See
// https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment
macro_rules! foo {
(ident $x:ident) => { bar!(ident $x); };
(lifetime $x:lifetime) => { bar!(lifetime $x); };
(tt $x:tt) => { bar!(tt $x); };
(expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected the token `3`
(literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected the token `4`
(path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected the token `a::b::c`
(stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected the token `let abc = 0`
}
macro_rules! bar {
(ident abc) => {};
(lifetime 'abc) => {};
(tt 2) => {};
(expr 3) => {};
(literal 4) => {};
(path a::b::c) => {};
(stmt let abc = 0) => {};
}
foo!(ident abc);
foo!(lifetime 'abc);
foo!(tt 2);
foo!(expr 3);
foo!(literal 4);
foo!(path a::b::c);
foo!(stmt let abc = 0);
fn main() {}

View File

@ -23,5 +23,93 @@ LL | complex_nonterminal!(enum E {});
= help: try using `:tt` instead in the macro definition
= note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
error: no rules expected the token `3`
--> $DIR/nonterminal-matching.rs:32:35
|
LL | (expr $x:expr) => { bar!(expr $x); };
| ^^ no rules expected this token in macro call
...
LL | macro_rules! bar {
| ---------------- when calling this macro
...
LL | foo!(expr 3);
| ------------ in this macro invocation
|
note: while trying to match `3`
--> $DIR/nonterminal-matching.rs:42:11
|
LL | (expr 3) => {};
| ^
= note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens
= note: see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information
= help: try using `:tt` instead in the macro definition
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: no rules expected the token `4`
--> $DIR/nonterminal-matching.rs:33:44
|
LL | (literal $x:literal) => { bar!(literal $x); };
| ^^ no rules expected this token in macro call
...
LL | macro_rules! bar {
| ---------------- when calling this macro
...
LL | foo!(literal 4);
| --------------- in this macro invocation
|
note: while trying to match `4`
--> $DIR/nonterminal-matching.rs:43:14
|
LL | (literal 4) => {};
| ^
= note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens
= note: see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information
= help: try using `:tt` instead in the macro definition
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: no rules expected the token `a::b::c`
--> $DIR/nonterminal-matching.rs:34:35
|
LL | (path $x:path) => { bar!(path $x); };
| ^^ no rules expected this token in macro call
...
LL | macro_rules! bar {
| ---------------- when calling this macro
...
LL | foo!(path a::b::c);
| ------------------ in this macro invocation
|
note: while trying to match `a`
--> $DIR/nonterminal-matching.rs:44:11
|
LL | (path a::b::c) => {};
| ^
= note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens
= note: see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information
= help: try using `:tt` instead in the macro definition
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: no rules expected the token `let abc = 0`
--> $DIR/nonterminal-matching.rs:35:35
|
LL | (stmt $x:stmt) => { bar!(stmt $x); };
| ^^ no rules expected this token in macro call
...
LL | macro_rules! bar {
| ---------------- when calling this macro
...
LL | foo!(stmt let abc = 0);
| ---------------------- in this macro invocation
|
note: while trying to match `let`
--> $DIR/nonterminal-matching.rs:45:11
|
LL | (stmt let abc = 0) => {};
| ^^^
= note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens
= note: see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information
= help: try using `:tt` instead in the macro definition
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 5 previous errors

View File

@ -4,7 +4,7 @@
fn main() {
match Some(vec![42]) {
Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns
Some(vec![43]) => {} //~ ERROR expected pattern, found `#`
_ => {}
}
}

View File

@ -1,10 +1,13 @@
error: arbitrary expressions aren't allowed in patterns
error: expected pattern, found `#`
--> $DIR/vec-macro-in-pattern.rs:7:14
|
LL | Some(vec![43]) => {}
| ^^^^^^^^
| |
| expected pattern
| in this macro invocation
| this macro call doesn't expand to a pattern
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error