Skip to content

Commit

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

Successful merges:

 - #119213 (simd intrinsics: add simd_shuffle_generic and other missing intrinsics)
 - #120272 (Suppress suggestions in derive macro)
 - #120773 (large_assignments: Allow moves into functions)
 - #120874 (Take empty `where` bounds into account when suggesting predicates)
 - #120882 (interpret/write_discriminant: when encoding niched variant, ensure the stored value matches)
 - #120883 (interpret: rename ReadExternStatic → ExternStatic)
 - #120890 (Adapt `llvm-has-rust-patches` validation to take `llvm-config` into account.)
 - #120895 (don't skip coercions for types with errors)
 - #120896 (Print kind of coroutine closure)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Feb 11, 2024
2 parents 980cf08 + 870435b commit a166af7
Show file tree
Hide file tree
Showing 47 changed files with 491 additions and 137 deletions.
8 changes: 6 additions & 2 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ const_eval_error = {$error_kind ->
const_eval_exact_div_has_remainder =
exact_div: {$a} cannot be divided by {$b} without remainder
const_eval_extern_static =
cannot access extern static ({$did})
const_eval_fn_ptr_call =
function pointers need an RFC before allowed to be called in {const_eval_const_context}s
const_eval_for_loop_into_iter_non_const =
Expand Down Expand Up @@ -172,6 +174,10 @@ const_eval_invalid_meta =
invalid metadata in wide pointer: total size is bigger than largest supported object
const_eval_invalid_meta_slice =
invalid metadata in wide pointer: slice is bigger than largest supported object
const_eval_invalid_niched_enum_variant_written =
trying to set discriminant of a {$ty} to the niched variant, but the value does not match
const_eval_invalid_str =
this string is not valid UTF-8: {$err}
const_eval_invalid_tag =
Expand Down Expand Up @@ -298,8 +304,6 @@ const_eval_raw_ptr_to_int =
.note = at compile-time, pointers do not have an integer value
.note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
const_eval_read_extern_static =
cannot read from extern static ({$did})
const_eval_read_pointer_as_int =
unable to turn pointer into integer
const_eval_realloc_or_alloc_with_offset =
Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
InvalidNichedEnumVariantWritten { .. } => {
const_eval_invalid_niched_enum_variant_written
}
AbiMismatchArgument { .. } => const_eval_incompatible_types,
AbiMismatchReturn { .. } => const_eval_incompatible_return_types,
}
Expand Down Expand Up @@ -585,6 +588,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
builder.arg("target_size", info.target_size);
builder.arg("data_size", info.data_size);
}
InvalidNichedEnumVariantWritten { enum_ty } => {
builder.arg("ty", enum_ty.to_string());
}
AbiMismatchArgument { caller_ty, callee_ty }
| AbiMismatchReturn { caller_ty, callee_ty } => {
builder.arg("caller_ty", caller_ty.to_string());
Expand Down Expand Up @@ -793,7 +799,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
UnsupportedOpInfo::ReadExternStatic(_) => const_eval_read_extern_static,
UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static,
}
}
fn add_args<G: EmissionGuarantee>(self, _: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>) {
Expand All @@ -812,7 +818,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
builder.arg("ptr", ptr);
}
ThreadLocalStatic(did) | ReadExternStatic(did) => {
ThreadLocalStatic(did) | ExternStatic(did) => {
builder.arg("did", format!("{did:?}"));
}
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_const_eval/src/interpret/discriminant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Write result.
let niche_dest = self.project_field(dest, tag_field)?;
self.write_immediate(*tag_val, &niche_dest)?;
} else {
// The untagged variant is implicitly encoded simply by having a value that is
// outside the niche variants. But what if the data stored here does not
// actually encode this variant? That would be bad! So let's double-check...
let actual_variant = self.read_discriminant(&dest.to_op(self)?)?;
if actual_variant != variant_index {
throw_ub!(InvalidNichedEnumVariantWritten { enum_ty: dest.layout().ty });
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
if self.tcx.is_foreign_item(def_id) {
// This is unreachable in Miri, but can happen in CTFE where we actually *do* support
// referencing arbitrary (declared) extern statics.
throw_unsup!(ReadExternStatic(def_id));
throw_unsup!(ExternStatic(def_id));
}

// We don't give a span -- statics don't need that, they cannot be generic or associated.
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,17 @@ impl Diagnostic {

/// Helper for pushing to `self.suggestions`, if available (not disable).
fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
for subst in &suggestion.substitutions {
for part in &subst.parts {
let span = part.span;
let call_site = span.ctxt().outer_expn_data().call_site;
if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
// Ignore if spans is from derive macro.
return;
}
}
}

if let Ok(suggestions) = &mut self.suggestions {
suggestions.push(suggestion);
}
Expand Down
11 changes: 0 additions & 11 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let b = self.shallow_resolve(b);
debug!("Coerce.tys({:?} => {:?})", a, b);

// Just ignore error types.
if let Err(guar) = (a, b).error_reported() {
// Best-effort try to unify these types -- we're already on the error path,
// so this will have the side-effect of making sure we have no ambiguities
// due to `[type error]` and `_` not coercing together.
let _ = self.commit_if_ok(|_| {
self.at(&self.cause, self.param_env).eq(DefineOpaqueTypes::Yes, a, b)
});
return success(vec![], Ty::new_error(self.fcx.tcx, guar), vec![]);
}

// Coercing from `!` to any type is allowed:
if a.is_never() {
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
UninhabitedEnumVariantWritten(VariantIdx),
/// An uninhabited enum variant is projected.
UninhabitedEnumVariantRead(VariantIdx),
/// Trying to set discriminant to the niched variant, but the value does not match.
InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
/// ABI-incompatible argument types.
AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
/// ABI-incompatible return types.
Expand Down Expand Up @@ -468,7 +470,7 @@ pub enum UnsupportedOpInfo {
/// Accessing thread local statics
ThreadLocalStatic(DefId),
/// Accessing an unsupported extern static.
ReadExternStatic(DefId),
ExternStatic(DefId),
}

/// Error information for when the program exhausted the resources granted to it
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,17 @@ pub fn suggest_constraining_type_params<'a>(
// trait Foo<T=()> {... }
// - insert: `where T: Zar`
if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) {
// If we are here and the where clause span is of non-zero length
// it means we're dealing with an empty where clause like this:
// fn foo<X>(x: X) where { ... }
// In that case we don't want to add another "where" (Fixes #120838)
let where_prefix = if generics.where_clause_span.is_empty() { " where" } else { "" };

// Suggest a bound, but there is no existing `where` clause *and* the type param has a
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
suggestions.push((
generics.tail_span_for_predicate_suggestion(),
format!(" where {param_name}: {constraint}"),
format!("{where_prefix} {param_name}: {constraint}"),
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
));
continue;
Expand Down
19 changes: 18 additions & 1 deletion compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,24 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
ty::CoroutineClosure(did, args) => {
p!(write("{{"));
if !self.should_print_verbose() {
p!(write("coroutine-closure"));
match self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(did)).unwrap()
{
hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineSource::Closure,
) => p!("async closure"),
hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::AsyncGen,
hir::CoroutineSource::Closure,
) => p!("async gen closure"),
hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Gen,
hir::CoroutineSource::Closure,
) => p!("gen closure"),
_ => unreachable!(
"coroutine from coroutine-closure should have CoroutineSource::Closure"
),
}
// FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() {
if self.tcx().sess.opts.unstable_opts.span_free_formats {
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,15 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
debug!(?def_id, ?fn_span);

for arg in args {
if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node) {
// Moving args into functions is typically implemented with pointer
// passing at the llvm-ir level and not by memcpy's. So always allow
// moving args into functions.
let operand: &mir::Operand<'tcx> = &arg.node;
if let mir::Operand::Move(_) = operand {
continue;
}

if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) {
self.lint_large_assignment(limit.0, too_large_size, location, arg.span);
};
}
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,13 @@ impl Span {
span.lo < other.hi && other.lo < span.hi
}

/// Returns `true` if `self` touches or adjoins `other`.
pub fn overlaps_or_adjacent(self, other: Span) -> bool {
let span = self.data();
let other = other.data();
span.lo <= other.hi && other.lo <= span.hi
}

/// Returns `true` if the spans are equal with regards to the source text.
///
/// Use this instead of `==` when either span could be generated code,
Expand Down
54 changes: 51 additions & 3 deletions library/core/src/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,27 @@ extern "platform-intrinsic" {
///
/// `T` must be a vector.
///
/// `U` must be a const array of `i32`s.
/// `U` must be a **const** array of `i32`s. This means it must either refer to a named
/// const or be given as an inline const expression (`const { ... }`).
///
/// `V` must be a vector with the same element type as `T` and the same length as `U`.
///
/// Concatenates `x` and `y`, then returns a new vector such that each element is selected from
/// the concatenation by the matching index in `idx`.
/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy`
/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds
/// of `xy`.
pub fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;

/// Shuffle two vectors by const indices.
///
/// `T` must be a vector.
///
/// `U` must be a vector with the same element type as `T` and the same length as `IDX`.
///
/// Returns a new vector such that element `i` is selected from `xy[IDX[i]]`, where `xy`
/// is the concatenation of `x` and `y`. It is a compile-time error if `IDX[i]` is out-of-bounds
/// of `xy`.
pub fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;

/// Read a vector of pointers.
///
/// `T` must be a vector.
Expand Down Expand Up @@ -232,6 +245,9 @@ extern "platform-intrinsic" {
/// corresponding value in `val` to the pointer.
/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
///
/// The stores happen in left-to-right order.
/// (This is relevant in case two of the stores overlap.)
///
/// # Safety
/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element
/// type).
Expand Down Expand Up @@ -468,4 +484,36 @@ extern "platform-intrinsic" {
///
/// `T` must be a vector of integers.
pub fn simd_cttz<T>(x: T) -> T;

/// Round up each element to the next highest integer-valued float.
///
/// `T` must be a vector of floats.
pub fn simd_ceil<T>(x: T) -> T;

/// Round down each element to the next lowest integer-valued float.
///
/// `T` must be a vector of floats.
pub fn simd_floor<T>(x: T) -> T;

/// Round each element to the closest integer-valued float.
/// Ties are resolved by rounding away from 0.
///
/// `T` must be a vector of floats.
pub fn simd_round<T>(x: T) -> T;

/// Return the integer part of each element as an integer-valued float.
/// In other words, non-integer values are truncated towards zero.
///
/// `T` must be a vector of floats.
pub fn simd_trunc<T>(x: T) -> T;

/// Takes the square root of each element.
///
/// `T` must be a vector of floats.
pub fn simd_fsqrt<T>(x: T) -> T;

/// Computes `(x*y) + z` for each element, but without any intermediate rounding.
///
/// `T` must be a vector of floats.
pub fn simd_fma<T>(x: T, y: T, z: T) -> T;
}
7 changes: 3 additions & 4 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1810,10 +1810,9 @@ impl Config {
target.llvm_config = Some(config.src.join(s));
}
if let Some(patches) = cfg.llvm_has_rust_patches {
assert_eq!(
config.submodules,
Some(false),
"cannot set `llvm-has-rust-patches` for a managed submodule (set `build.submodules = false` if you want to apply patches)"
assert!(
config.submodules == Some(false) || cfg.llvm_config.is_some(),
"use of `llvm-has-rust-patches` is restricted to cases where either submodules are disabled or llvm-config been provided"
);
target.llvm_has_rust_patches = Some(patches);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#![feature(core_intrinsics)]
#![feature(custom_mir)]

use std::intrinsics::mir::*;
use std::num::NonZeroI32;

// We define our own option type so that we can control the varian indices.
#[allow(unused)]
enum Option<T> {
None,
Some(T),
}
use Option::*;

#[custom_mir(dialect = "runtime", phase = "optimized")]
fn set_discriminant(ptr: &mut Option<NonZeroI32>) {
mir! {
{
// We set the discriminant to `Some`, which is a NOP since this is the niched variant.
// However, the enum is actually encoding `None` currently! That's not good...
SetDiscriminant(*ptr, 1);
//~^ ERROR: trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
Return()
}
}
}

pub fn main() {
let mut v = None;
set_discriminant(&mut v);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: Undefined Behavior: trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
--> $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
|
LL | SetDiscriminant(*ptr, 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^ trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `set_discriminant` at $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
note: inside `main`
--> $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
|
LL | set_discriminant(&mut v);
| ^^^^^^^^^^^^^^^^^^^^^^^^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move

fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};

bb0: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move

fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};

bb0: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut

fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
fn main::{closure#0}::{closure#0}(_1: &mut {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
debug a => _2;
debug b => ((*_1).0: i32);
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut

fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
fn main::{closure#0}::{closure#0}(_1: &mut {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
debug a => _2;
debug b => ((*_1).0: i32);
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
Expand Down
Loading

0 comments on commit a166af7

Please sign in to comment.