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:
commit
127fa2261b
37 changed files with 560 additions and 399 deletions
|
@ -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());
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue