Skip to content

Commit

Permalink
Auto merge of #127014 - jhpratt:rollup-45ic8f5, r=jhpratt
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Jun 27, 2024
2 parents 536235f + 73016dc commit 127fa22
Show file tree
Hide file tree
Showing 37 changed files with 560 additions and 399 deletions.
9 changes: 8 additions & 1 deletion compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
_,
Expand Down Expand Up @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
17 changes: 0 additions & 17 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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;
}

Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
33 changes: 32 additions & 1 deletion compiler/rustc_mir_transform/src/coverage/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -38,14 +40,43 @@ 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;
}

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>,
Expand Down
73 changes: 41 additions & 32 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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));
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_smir/src/rustc_internal/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_smir/src/rustc_smir/convert/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/stable_mir/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
18 changes: 4 additions & 14 deletions library/alloc/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),+])
))
)
);
}

Expand Down Expand Up @@ -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
};
}
2 changes: 1 addition & 1 deletion library/std/src/sys_common/wtf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
24 changes: 24 additions & 0 deletions library/std/src/sys_common/wtf8/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Loading

0 comments on commit 127fa22

Please sign in to comment.