Auto merge of #85014 - Dylan-DPC:rollup-jzpbkdu, r=Dylan-DPC
Rollup of 11 pull requests Successful merges: - #84409 (Ensure TLS destructors run before thread joins in SGX) - #84500 (Add --run flag to compiletest) - #84728 (Add test for suggestion to borrow unsized function parameters) - #84734 (Add `needs-unwind` and beginning of support for testing `panic=abort` std to compiletest) - #84755 (Allow using `core::` in intra-doc links within core itself) - #84871 (Disallows `#![feature(no_coverage)]` on stable and beta (using standard crate-level gating)) - #84872 (Wire up tidy dependency checks for cg_clif) - #84896 (Handle incorrect placement of parentheses in trait bounds more gracefully) - #84905 (CTFE engine: rename copy → copy_intrinsic, move to intrinsics.rs) - #84953 (Remove unneeded call to with_default_session_globals in rustdoc highlight) - #84987 (small nits) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1773f14a24
50 changed files with 763 additions and 258 deletions
|
@ -15,20 +15,12 @@ pub fn expand_deriving_eq(
|
|||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
) {
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let no_coverage_ident =
|
||||
rustc_ast::attr::mk_nested_word_item(Ident::new(sym::no_coverage, span));
|
||||
let no_coverage_feature =
|
||||
rustc_ast::attr::mk_list_item(Ident::new(sym::feature, span), vec![no_coverage_ident]);
|
||||
let no_coverage = cx.meta_word(span, sym::no_coverage);
|
||||
let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
|
||||
let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
|
||||
let attrs = vec![
|
||||
cx.attribute(inline),
|
||||
cx.attribute(no_coverage_feature),
|
||||
cx.attribute(no_coverage),
|
||||
cx.attribute(doc),
|
||||
];
|
||||
let no_coverage = cx.meta_word(span, sym::no_coverage);
|
||||
let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)];
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
|
|
|
@ -273,13 +273,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
template!(List: "address, memory, thread"),
|
||||
experimental!(no_sanitize)
|
||||
),
|
||||
ungated!(
|
||||
// Not exclusively gated at the crate level (though crate-level is
|
||||
// supported). The feature can alternatively be enabled on individual
|
||||
// functions.
|
||||
no_coverage, AssumedUsed,
|
||||
template!(Word),
|
||||
),
|
||||
gated!(no_coverage, AssumedUsed, template!(Word), experimental!(no_coverage)),
|
||||
|
||||
// FIXME: #14408 assume docs are used since rustdoc looks at them.
|
||||
ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")),
|
||||
|
|
|
@ -2398,9 +2398,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
self.tcx.associated_item(def_id).ident
|
||||
),
|
||||
infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{}`", name),
|
||||
infer::BoundRegionInCoherence(name) => {
|
||||
format!(" for lifetime parameter `{}` in coherence check", name)
|
||||
}
|
||||
infer::UpvarRegion(ref upvar_id, _) => {
|
||||
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
|
||||
format!(" for capture of `{}` by closure", var_name)
|
||||
|
|
|
@ -453,8 +453,6 @@ pub enum RegionVariableOrigin {
|
|||
|
||||
UpvarRegion(ty::UpvarId, Span),
|
||||
|
||||
BoundRegionInCoherence(Symbol),
|
||||
|
||||
/// This origin is used for the inference variables that we create
|
||||
/// during NLL region processing.
|
||||
Nll(NllRegionVariableOrigin),
|
||||
|
@ -1749,7 +1747,6 @@ impl RegionVariableOrigin {
|
|||
| EarlyBoundRegion(a, ..)
|
||||
| LateBoundRegion(a, ..)
|
||||
| UpvarRegion(_, a) => a,
|
||||
BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
|
||||
Nll(..) => bug!("NLL variable used with `span`"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -323,7 +323,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.write_scalar(result, dest)?;
|
||||
}
|
||||
sym::copy => {
|
||||
self.copy(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
|
||||
self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
|
||||
}
|
||||
sym::offset => {
|
||||
let ptr = self.read_scalar(&args[0])?.check_init()?;
|
||||
|
@ -530,4 +530,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
)?;
|
||||
Ok(offset_ptr)
|
||||
}
|
||||
|
||||
/// Copy `count*size_of::<T>()` many bytes from `*src` to `*dst`.
|
||||
pub(crate) fn copy_intrinsic(
|
||||
&mut self,
|
||||
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
nonoverlapping: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let (size, align) = (layout.size, layout.align.abi);
|
||||
let size = size.checked_mul(count, self).ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"overflow computing total size of `{}`",
|
||||
if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
|
||||
)
|
||||
})?;
|
||||
|
||||
// Make sure we check both pointers for an access of the total size and aligment,
|
||||
// *even if* the total size is 0.
|
||||
let src =
|
||||
self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?;
|
||||
|
||||
let dst =
|
||||
self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?;
|
||||
|
||||
if let (Some(src), Some(dst)) = (src, dst) {
|
||||
self.memory.copy(src, dst, size, nonoverlapping)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//!
|
||||
//! The main entry point is the `step` method.
|
||||
|
||||
use crate::interpret::OpTy;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
||||
use rustc_target::abi::LayoutOf;
|
||||
|
@ -119,7 +118,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
let src = self.eval_operand(src, None)?;
|
||||
let dst = self.eval_operand(dst, None)?;
|
||||
let count = self.eval_operand(count, None)?;
|
||||
self.copy(&src, &dst, &count, /* nonoverlapping */ true)?;
|
||||
self.copy_intrinsic(&src, &dst, &count, /* nonoverlapping */ true)?;
|
||||
}
|
||||
|
||||
// Statements we do not track.
|
||||
|
@ -149,37 +148,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn copy(
|
||||
&mut self,
|
||||
src: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
dst: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::PointerTag>,
|
||||
nonoverlapping: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let (size, align) = (layout.size, layout.align.abi);
|
||||
let size = size.checked_mul(count, self).ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"overflow computing total size of `{}`",
|
||||
if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
|
||||
)
|
||||
})?;
|
||||
|
||||
// Make sure we check both pointers for an access of the total size and aligment,
|
||||
// *even if* the total size is 0.
|
||||
let src =
|
||||
self.memory.check_ptr_access(self.read_scalar(&src)?.check_init()?, size, align)?;
|
||||
|
||||
let dst =
|
||||
self.memory.check_ptr_access(self.read_scalar(&dst)?.check_init()?, size, align)?;
|
||||
|
||||
if let (Some(src), Some(dst)) = (src, dst) {
|
||||
self.memory.copy(src, dst, size, nonoverlapping)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Evaluate an assignment statement.
|
||||
///
|
||||
/// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
|
||||
|
|
|
@ -470,7 +470,7 @@ impl<'a> Parser<'a> {
|
|||
/// Is a `dyn B0 + ... + Bn` type allowed here?
|
||||
fn is_explicit_dyn_type(&mut self) -> bool {
|
||||
self.check_keyword(kw::Dyn)
|
||||
&& (self.token.uninterpolated_span().rust_2018()
|
||||
&& (!self.token.uninterpolated_span().rust_2015()
|
||||
|| self.look_ahead(1, |t| {
|
||||
t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)
|
||||
}))
|
||||
|
@ -539,7 +539,21 @@ impl<'a> Parser<'a> {
|
|||
) -> PResult<'a, GenericBounds> {
|
||||
let mut bounds = Vec::new();
|
||||
let mut negative_bounds = Vec::new();
|
||||
while self.can_begin_bound() {
|
||||
|
||||
while self.can_begin_bound() || self.token.is_keyword(kw::Dyn) {
|
||||
if self.token.is_keyword(kw::Dyn) {
|
||||
// Account for `&dyn Trait + dyn Other`.
|
||||
self.struct_span_err(self.token.span, "invalid `dyn` keyword")
|
||||
.help("`dyn` is only needed at the start of a trait `+`-separated list")
|
||||
.span_suggestion(
|
||||
self.token.span,
|
||||
"remove this keyword",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
self.bump();
|
||||
}
|
||||
match self.parse_generic_bound()? {
|
||||
Ok(bound) => bounds.push(bound),
|
||||
Err(neg_sp) => negative_bounds.push(neg_sp),
|
||||
|
@ -721,7 +735,26 @@ impl<'a> Parser<'a> {
|
|||
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
||||
let path = self.parse_path(PathStyle::Type)?;
|
||||
if has_parens {
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
if self.token.is_like_plus() {
|
||||
// Someone has written something like `&dyn (Trait + Other)`. The correct code
|
||||
// would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
|
||||
// span to suggest that. When written as `&dyn Trait + Other`, an appropriate
|
||||
// suggestion is given.
|
||||
let bounds = vec![];
|
||||
self.parse_remaining_bounds(bounds, true)?;
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
let sp = vec![lo, self.prev_token.span];
|
||||
let sugg: Vec<_> = sp.iter().map(|sp| (*sp, String::new())).collect();
|
||||
self.struct_span_err(sp, "incorrect braces around trait bounds")
|
||||
.multipart_suggestion(
|
||||
"remove the parentheses",
|
||||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
self.expect(&token::CloseDelim(token::Paren))?;
|
||||
}
|
||||
}
|
||||
|
||||
let modifier = modifiers.to_trait_bound_modifier();
|
||||
|
|
|
@ -1044,8 +1044,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
/// Returns `true` if the global caches can be used.
|
||||
/// Do note that if the type itself is not in the
|
||||
/// global tcx, the local caches will be used.
|
||||
fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
|
||||
// If there are any inference variables in the `ParamEnv`, then we
|
||||
// always use a cache local to this particular scope. Otherwise, we
|
||||
|
|
|
@ -2661,8 +2661,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
|||
let mut inline_span = None;
|
||||
let mut link_ordinal_span = None;
|
||||
let mut no_sanitize_span = None;
|
||||
let mut no_coverage_feature_enabled = false;
|
||||
let mut no_coverage_attr = None;
|
||||
for attr in attrs.iter() {
|
||||
if tcx.sess.check_name(attr, sym::cold) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
|
||||
|
@ -2726,15 +2724,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
|||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
|
||||
} else if tcx.sess.check_name(attr, sym::no_mangle) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
||||
} else if attr.has_name(sym::feature) {
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
if list.iter().any(|nested_meta_item| nested_meta_item.has_name(sym::no_coverage)) {
|
||||
tcx.sess.mark_attr_used(attr);
|
||||
no_coverage_feature_enabled = true;
|
||||
}
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::no_coverage) {
|
||||
no_coverage_attr = Some(attr);
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
|
||||
} else if tcx.sess.check_name(attr, sym::rustc_std_internal_symbol) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||
} else if tcx.sess.check_name(attr, sym::used) {
|
||||
|
@ -2945,23 +2936,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(no_coverage_attr) = no_coverage_attr {
|
||||
if tcx.sess.features_untracked().no_coverage || no_coverage_feature_enabled {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE
|
||||
} else {
|
||||
let mut err = feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::no_coverage,
|
||||
no_coverage_attr.span,
|
||||
"the `#[no_coverage]` attribute is an experimental feature",
|
||||
);
|
||||
if tcx.sess.parse_sess.unstable_features.is_nightly_build() {
|
||||
err.help("or, alternatively, add `#[feature(no_coverage)]` to the function");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
|
||||
if !attr.has_name(sym::inline) {
|
||||
return ia;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue