Skip to content

Commit

Permalink
Auto merge of #130390 - matthiaskrgr:rollup-evbfwe2, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #129195 (Stabilize `&mut` (and `*mut`) as well as `&Cell` (and `*const Cell`) in const)
 - #130118 (move Option::unwrap_unchecked into const_option feature gate)
 - #130295 (Fix target-cpu fpu features on Armv8-R.)
 - #130371 (Correctly account for niche-optimized tags in rustc_transmute)
 - #130381 (library: Compute Rust exception class from its string repr)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Sep 15, 2024
2 parents 1ae2688 + 729aa49 commit dde7d66
Show file tree
Hide file tree
Showing 181 changed files with 426 additions and 1,738 deletions.
10 changes: 0 additions & 10 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,6 @@ const_eval_incompatible_return_types =
const_eval_incompatible_types =
calling a function with argument of type {$callee_ty} passing data of type {$caller_ty}
const_eval_interior_mutability_borrow =
cannot borrow here, since the borrowed element may contain interior mutability
const_eval_interior_mutable_data_refer =
{const_eval_const_context}s cannot refer to interior mutable data
.label = this borrow of an interior mutable value may end up in the final value
Expand Down Expand Up @@ -230,9 +227,6 @@ const_eval_memory_exhausted =
const_eval_modified_global =
modifying a static's initial value from another static's initializer
const_eval_mut_deref =
mutation through a reference is not allowed in {const_eval_const_context}s
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
Expand Down Expand Up @@ -363,10 +357,6 @@ const_eval_too_generic =
const_eval_too_many_caller_args =
calling a function with more arguments than it expected
const_eval_transient_mut_borrow = mutable references are not allowed in {const_eval_const_context}s
const_eval_transient_mut_raw = raw mutable pointers are not allowed in {const_eval_const_context}s
const_eval_try_block_from_output_non_const =
`try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s
const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s
Expand Down
254 changes: 25 additions & 229 deletions compiler/rustc_const_eval/src/check_consts/check.rs

Large diffs are not rendered by default.

116 changes: 5 additions & 111 deletions compiler/rustc_const_eval/src/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir::{self, CallSource};
use rustc_middle::mir::CallSource;
use rustc_middle::span_bug;
use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _};
use rustc_middle::ty::{
Expand Down Expand Up @@ -391,27 +391,12 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
}
}

#[derive(Debug)]
/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow never escapes to
/// the final value of the constant.
pub(crate) struct TransientCellBorrow;
impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_refs_to_cell)
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.tcx
.sess
.create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
}
}

#[derive(Debug)]
/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow might escape to
/// the final value of the constant, and thus we cannot allow this (for now). We may allow
/// it in the future for static items.
pub(crate) struct CellBorrow;
impl<'tcx> NonConstOp<'tcx> for CellBorrow {
pub(crate) struct EscapingCellBorrow;
impl<'tcx> NonConstOp<'tcx> for EscapingCellBorrow {
fn importance(&self) -> DiagImportance {
// Most likely the code will try to do mutation with these borrows, which
// triggers its own errors. Only show this one if that does not happen.
Expand All @@ -431,9 +416,9 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
/// This op is for `&mut` borrows in the trailing expression of a constant
/// which uses the "enclosing scopes rule" to leak its locals into anonymous
/// static or const items.
pub(crate) struct MutBorrow(pub hir::BorrowKind);
pub(crate) struct EscapingMutBorrow(pub hir::BorrowKind);

impl<'tcx> NonConstOp<'tcx> for MutBorrow {
impl<'tcx> NonConstOp<'tcx> for EscapingMutBorrow {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
Status::Forbidden
}
Expand All @@ -460,49 +445,6 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
}
}

#[derive(Debug)]
pub(crate) struct TransientMutBorrow(pub hir::BorrowKind);

impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_mut_refs)
}

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
let kind = ccx.const_kind();
match self.0 {
hir::BorrowKind::Raw => ccx
.tcx
.sess
.create_feature_err(errors::TransientMutRawErr { span, kind }, sym::const_mut_refs),
hir::BorrowKind::Ref => ccx.tcx.sess.create_feature_err(
errors::TransientMutBorrowErr { span, kind },
sym::const_mut_refs,
),
}
}
}

#[derive(Debug)]
pub(crate) struct MutDeref;
impl<'tcx> NonConstOp<'tcx> for MutDeref {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_mut_refs)
}

fn importance(&self) -> DiagImportance {
// Usually a side-effect of a `TransientMutBorrow` somewhere.
DiagImportance::Secondary
}

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.tcx.sess.create_feature_err(
errors::MutDerefErr { span, kind: ccx.const_kind() },
sym::const_mut_refs,
)
}
}

/// A call to a `panic()` lang item where the first argument is _not_ a `&str`.
#[derive(Debug)]
pub(crate) struct PanicNonStr;
Expand All @@ -524,24 +466,6 @@ impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
}
}

#[derive(Debug)]
pub(crate) struct RawMutPtrDeref;
impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
Status::Unstable(sym::const_mut_refs)
}

#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
feature_err(
&ccx.tcx.sess,
sym::const_mut_refs,
span,
format!("dereferencing raw mutable pointers in {}s is unstable", ccx.const_kind(),),
)
}
}

/// Casting raw pointer or function pointer to an integer.
/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
/// allocation base addresses that are not known at compile-time.
Expand Down Expand Up @@ -588,33 +512,3 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
ccx.dcx().create_err(errors::ThreadLocalAccessErr { span })
}
}

/// Types that cannot appear in the signature or locals of a `const fn`.
pub(crate) mod mut_ref {
use super::*;

#[derive(Debug)]
pub(crate) struct MutRef(pub mir::LocalKind);
impl<'tcx> NonConstOp<'tcx> for MutRef {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_mut_refs)
}

fn importance(&self) -> DiagImportance {
match self.0 {
mir::LocalKind::Temp => DiagImportance::Secondary,
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => DiagImportance::Primary,
}
}

#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
feature_err(
&ccx.tcx.sess,
sym::const_mut_refs,
span,
format!("mutable references are not allowed in {}s", ccx.const_kind()),
)
}
}
}
31 changes: 0 additions & 31 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,30 +93,6 @@ pub(crate) struct PanicNonStrErr {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(const_eval_mut_deref, code = E0658)]
pub(crate) struct MutDerefErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}

#[derive(Diagnostic)]
#[diag(const_eval_transient_mut_borrow, code = E0658)]
pub(crate) struct TransientMutBorrowErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}

#[derive(Diagnostic)]
#[diag(const_eval_transient_mut_raw, code = E0658)]
pub(crate) struct TransientMutRawErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}

#[derive(Diagnostic)]
#[diag(const_eval_max_num_nodes_in_const)]
pub(crate) struct MaxNumNodesInConstErr {
Expand Down Expand Up @@ -217,13 +193,6 @@ pub(crate) struct InteriorMutableDataRefer {
pub teach: bool,
}

#[derive(Diagnostic)]
#[diag(const_eval_interior_mutability_borrow)]
pub(crate) struct InteriorMutabilityBorrow {
#[primary_span]
pub span: Span,
}

#[derive(LintDiagnostic)]
#[diag(const_eval_long_running)]
#[note]
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_error_codes/src/error_codes/E0764.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ A mutable reference was used in a constant.
Erroneous code example:

```compile_fail,E0764
#![feature(const_mut_refs)]
fn main() {
const OH_NO: &'static mut usize = &mut 1; // error!
}
Expand All @@ -26,8 +24,6 @@ Remember: you cannot use a function call inside a constant or static. However,
you can totally use it in constant functions:

```
#![feature(const_mut_refs)]
const fn foo(x: usize) -> usize {
let mut y = 1;
let z = &mut y;
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,14 @@ declare_features! (
(accepted, const_let, "1.33.0", Some(48821)),
/// Allows the use of `loop` and `while` in constants.
(accepted, const_loop, "1.46.0", Some(52000)),
/// Allows using `&mut` in constant functions.
(accepted, const_mut_refs, "CURRENT_RUSTC_VERSION", Some(57349)),
/// Allows panicking during const eval (producing compile-time errors).
(accepted, const_panic, "1.57.0", Some(51999)),
/// Allows dereferencing raw pointers during const eval.
(accepted, const_raw_ptr_deref, "1.58.0", Some(51911)),
/// Allows references to types with interior mutability within constants
(accepted, const_refs_to_cell, "CURRENT_RUSTC_VERSION", Some(80384)),
/// Allows implementing `Copy` for closures where possible (RFC 2132).
(accepted, copy_closures, "1.26.0", Some(44490)),
/// Allows `crate` in paths.
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,12 +403,8 @@ declare_features! (
(incomplete, const_closures, "1.68.0", Some(106003)),
/// Allows `for _ in _` loops in const contexts.
(unstable, const_for, "1.56.0", Some(87575)),
/// Allows using `&mut` in constant functions.
(unstable, const_mut_refs, "1.41.0", Some(57349)),
/// Be more precise when looking for live drops in a const context.
(unstable, const_precise_live_drops, "1.46.0", Some(73255)),
/// Allows references to types with interior mutability within constants
(unstable, const_refs_to_cell, "1.51.0", Some(80384)),
/// Allows creating pointers and references to `static` items in constants.
(unstable, const_refs_to_static, "1.78.0", Some(119618)),
/// Allows `impl const Trait for T` syntax.
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ pub(crate) fn target() -> Target {
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
// The Cortex-R52 has two variants with respect to floating-point support:
// 1. fp-armv8, SP-only, with 16 DP (32 SP) registers
// 2. neon-fp-armv8, SP+DP, with 32 DP registers
// Use the lesser of these two options as the default, as it will produce code
// compatible with either variant.
// Armv8-R requires a minimum set of floating-point features equivalent to:
// fp-armv8, SP-only, with 16 DP (32 SP) registers
// LLVM defines Armv8-R to include these features automatically.
//
// The Cortex-R52 supports these default features and optionally includes:
// neon-fp-armv8, SP+DP, with 32 DP registers
//
// Reference:
// Arm Cortex-R52 Processor Technical Reference Manual
// - Chapter 15 Advanced SIMD and floating-point support
features: "+fp-armv8,-fp64,-d32".into(),
max_atomic_width: Some(64),
emit_debug_gdb_scripts: false,
// GCC defaults to 8 for arm-none here.
Expand Down
35 changes: 25 additions & 10 deletions compiler/rustc_transmute/src/layout/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ pub(crate) mod rustc {
use rustc_middle::ty::{self, AdtDef, AdtKind, List, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::ErrorGuaranteed;
use rustc_target::abi::{
FieldIdx, FieldsShape, Layout, Size, TyAndLayout, VariantIdx, Variants,
FieldIdx, FieldsShape, Layout, Size, TagEncoding, TyAndLayout, VariantIdx, Variants,
};

use super::Tree;
Expand Down Expand Up @@ -319,11 +319,17 @@ pub(crate) mod rustc {
assert!(def.is_enum());

// Computes the variant of a given index.
let layout_of_variant = |index| {
let layout_of_variant = |index, encoding: Option<TagEncoding<VariantIdx>>| {
let tag = cx.tcx.tag_for_variant((cx.tcx.erase_regions(ty), index));
let variant_def = Def::Variant(def.variant(index));
let variant_layout = ty_variant(cx, (ty, layout), index);
Self::from_variant(variant_def, tag, (ty, variant_layout), layout.size, cx)
Self::from_variant(
variant_def,
tag.map(|tag| (tag, index, encoding.unwrap())),
(ty, variant_layout),
layout.size,
cx,
)
};

// We consider three kinds of enums, each demanding a different
Expand All @@ -345,9 +351,9 @@ pub(crate) mod rustc {
Variants::Single { index } => {
// `Variants::Single` on enums with variants denotes that
// the enum delegates its layout to the variant at `index`.
layout_of_variant(*index)
layout_of_variant(*index, None)
}
Variants::Multiple { tag_field, .. } => {
Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
// `Variants::Multiple` denotes an enum with multiple
// variants. The layout of such an enum is the disjunction
// of the layouts of its tagged variants.
Expand All @@ -359,7 +365,7 @@ pub(crate) mod rustc {
let variants = def.discriminants(cx.tcx()).try_fold(
Self::uninhabited(),
|variants, (idx, ref discriminant)| {
let variant = layout_of_variant(idx)?;
let variant = layout_of_variant(idx, Some(tag_encoding.clone()))?;
Result::<Self, Err>::Ok(variants.or(variant))
},
)?;
Expand All @@ -380,7 +386,7 @@ pub(crate) mod rustc {
/// `0`.
fn from_variant(
def: Def<'tcx>,
tag: Option<ScalarInt>,
tag: Option<(ScalarInt, VariantIdx, TagEncoding<VariantIdx>)>,
(ty, layout): (Ty<'tcx>, Layout<'tcx>),
total_size: Size,
cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
Expand All @@ -400,9 +406,18 @@ pub(crate) mod rustc {
let mut struct_tree = Self::def(def);

// If a `tag` is provided, place it at the start of the layout.
if let Some(tag) = tag {
size += tag.size();
struct_tree = struct_tree.then(Self::from_tag(tag, cx.tcx));
if let Some((tag, index, encoding)) = &tag {
match encoding {
TagEncoding::Direct => {
size += tag.size();
}
TagEncoding::Niche { niche_variants, .. } => {
if !niche_variants.contains(index) {
size += tag.size();
}
}
}
struct_tree = struct_tree.then(Self::from_tag(*tag, cx.tcx));
}

// Append the fields, in memory order, to the layout.
Expand Down
Loading

0 comments on commit dde7d66

Please sign in to comment.