Skip to content

Commit a166af7

Browse files
committed
Auto merge of #120903 - matthiaskrgr:rollup-tmsuzth, r=matthiaskrgr
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
2 parents 980cf08 + 870435b commit a166af7

File tree

47 files changed

+491
-137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+491
-137
lines changed

compiler/rustc_const_eval/messages.ftl

+6-2
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ const_eval_error = {$error_kind ->
9898
const_eval_exact_div_has_remainder =
9999
exact_div: {$a} cannot be divided by {$b} without remainder
100100
101+
const_eval_extern_static =
102+
cannot access extern static ({$did})
101103
const_eval_fn_ptr_call =
102104
function pointers need an RFC before allowed to be called in {const_eval_const_context}s
103105
const_eval_for_loop_into_iter_non_const =
@@ -172,6 +174,10 @@ const_eval_invalid_meta =
172174
invalid metadata in wide pointer: total size is bigger than largest supported object
173175
const_eval_invalid_meta_slice =
174176
invalid metadata in wide pointer: slice is bigger than largest supported object
177+
178+
const_eval_invalid_niched_enum_variant_written =
179+
trying to set discriminant of a {$ty} to the niched variant, but the value does not match
180+
175181
const_eval_invalid_str =
176182
this string is not valid UTF-8: {$err}
177183
const_eval_invalid_tag =
@@ -298,8 +304,6 @@ const_eval_raw_ptr_to_int =
298304
.note = at compile-time, pointers do not have an integer value
299305
.note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
300306
301-
const_eval_read_extern_static =
302-
cannot read from extern static ({$did})
303307
const_eval_read_pointer_as_int =
304308
unable to turn pointer into integer
305309
const_eval_realloc_or_alloc_with_offset =

compiler/rustc_const_eval/src/errors.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
497497
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
498498
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
499499
UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
500+
InvalidNichedEnumVariantWritten { .. } => {
501+
const_eval_invalid_niched_enum_variant_written
502+
}
500503
AbiMismatchArgument { .. } => const_eval_incompatible_types,
501504
AbiMismatchReturn { .. } => const_eval_incompatible_return_types,
502505
}
@@ -585,6 +588,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
585588
builder.arg("target_size", info.target_size);
586589
builder.arg("data_size", info.data_size);
587590
}
591+
InvalidNichedEnumVariantWritten { enum_ty } => {
592+
builder.arg("ty", enum_ty.to_string());
593+
}
588594
AbiMismatchArgument { caller_ty, callee_ty }
589595
| AbiMismatchReturn { caller_ty, callee_ty } => {
590596
builder.arg("caller_ty", caller_ty.to_string());
@@ -793,7 +799,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
793799
UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
794800
UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
795801
UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
796-
UnsupportedOpInfo::ReadExternStatic(_) => const_eval_read_extern_static,
802+
UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static,
797803
}
798804
}
799805
fn add_args<G: EmissionGuarantee>(self, _: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>) {
@@ -812,7 +818,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
812818
OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
813819
builder.arg("ptr", ptr);
814820
}
815-
ThreadLocalStatic(did) | ReadExternStatic(did) => {
821+
ThreadLocalStatic(did) | ExternStatic(did) => {
816822
builder.arg("did", format!("{did:?}"));
817823
}
818824
}

compiler/rustc_const_eval/src/interpret/discriminant.rs

+8
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
8585
// Write result.
8686
let niche_dest = self.project_field(dest, tag_field)?;
8787
self.write_immediate(*tag_val, &niche_dest)?;
88+
} else {
89+
// The untagged variant is implicitly encoded simply by having a value that is
90+
// outside the niche variants. But what if the data stored here does not
91+
// actually encode this variant? That would be bad! So let's double-check...
92+
let actual_variant = self.read_discriminant(&dest.to_op(self)?)?;
93+
if actual_variant != variant_index {
94+
throw_ub!(InvalidNichedEnumVariantWritten { enum_ty: dest.layout().ty });
95+
}
8896
}
8997
}
9098
}

compiler/rustc_const_eval/src/interpret/memory.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
557557
if self.tcx.is_foreign_item(def_id) {
558558
// This is unreachable in Miri, but can happen in CTFE where we actually *do* support
559559
// referencing arbitrary (declared) extern statics.
560-
throw_unsup!(ReadExternStatic(def_id));
560+
throw_unsup!(ExternStatic(def_id));
561561
}
562562

563563
// We don't give a span -- statics don't need that, they cannot be generic or associated.

compiler/rustc_errors/src/diagnostic.rs

+11
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,17 @@ impl Diagnostic {
516516

517517
/// Helper for pushing to `self.suggestions`, if available (not disable).
518518
fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
519+
for subst in &suggestion.substitutions {
520+
for part in &subst.parts {
521+
let span = part.span;
522+
let call_site = span.ctxt().outer_expn_data().call_site;
523+
if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
524+
// Ignore if spans is from derive macro.
525+
return;
526+
}
527+
}
528+
}
529+
519530
if let Ok(suggestions) = &mut self.suggestions {
520531
suggestions.push(suggestion);
521532
}

compiler/rustc_hir_typeck/src/coercion.rs

-11
Original file line numberDiff line numberDiff line change
@@ -186,17 +186,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
186186
let b = self.shallow_resolve(b);
187187
debug!("Coerce.tys({:?} => {:?})", a, b);
188188

189-
// Just ignore error types.
190-
if let Err(guar) = (a, b).error_reported() {
191-
// Best-effort try to unify these types -- we're already on the error path,
192-
// so this will have the side-effect of making sure we have no ambiguities
193-
// due to `[type error]` and `_` not coercing together.
194-
let _ = self.commit_if_ok(|_| {
195-
self.at(&self.cause, self.param_env).eq(DefineOpaqueTypes::Yes, a, b)
196-
});
197-
return success(vec![], Ty::new_error(self.fcx.tcx, guar), vec![]);
198-
}
199-
200189
// Coercing from `!` to any type is allowed:
201190
if a.is_never() {
202191
return success(simple(Adjust::NeverToAny)(b), b, vec![]);

compiler/rustc_middle/src/mir/interpret/error.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
356356
UninhabitedEnumVariantWritten(VariantIdx),
357357
/// An uninhabited enum variant is projected.
358358
UninhabitedEnumVariantRead(VariantIdx),
359+
/// Trying to set discriminant to the niched variant, but the value does not match.
360+
InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
359361
/// ABI-incompatible argument types.
360362
AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
361363
/// ABI-incompatible return types.
@@ -468,7 +470,7 @@ pub enum UnsupportedOpInfo {
468470
/// Accessing thread local statics
469471
ThreadLocalStatic(DefId),
470472
/// Accessing an unsupported extern static.
471-
ReadExternStatic(DefId),
473+
ExternStatic(DefId),
472474
}
473475

474476
/// Error information for when the program exhausted the resources granted to it

compiler/rustc_middle/src/ty/diagnostics.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -358,11 +358,17 @@ pub fn suggest_constraining_type_params<'a>(
358358
// trait Foo<T=()> {... }
359359
// - insert: `where T: Zar`
360360
if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) {
361+
// If we are here and the where clause span is of non-zero length
362+
// it means we're dealing with an empty where clause like this:
363+
// fn foo<X>(x: X) where { ... }
364+
// In that case we don't want to add another "where" (Fixes #120838)
365+
let where_prefix = if generics.where_clause_span.is_empty() { " where" } else { "" };
366+
361367
// Suggest a bound, but there is no existing `where` clause *and* the type param has a
362368
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
363369
suggestions.push((
364370
generics.tail_span_for_predicate_suggestion(),
365-
format!(" where {param_name}: {constraint}"),
371+
format!("{where_prefix} {param_name}: {constraint}"),
366372
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
367373
));
368374
continue;

compiler/rustc_middle/src/ty/print/pretty.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,24 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
877877
ty::CoroutineClosure(did, args) => {
878878
p!(write("{{"));
879879
if !self.should_print_verbose() {
880-
p!(write("coroutine-closure"));
880+
match self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(did)).unwrap()
881+
{
882+
hir::CoroutineKind::Desugared(
883+
hir::CoroutineDesugaring::Async,
884+
hir::CoroutineSource::Closure,
885+
) => p!("async closure"),
886+
hir::CoroutineKind::Desugared(
887+
hir::CoroutineDesugaring::AsyncGen,
888+
hir::CoroutineSource::Closure,
889+
) => p!("async gen closure"),
890+
hir::CoroutineKind::Desugared(
891+
hir::CoroutineDesugaring::Gen,
892+
hir::CoroutineSource::Closure,
893+
) => p!("gen closure"),
894+
_ => unreachable!(
895+
"coroutine from coroutine-closure should have CoroutineSource::Closure"
896+
),
897+
}
881898
// FIXME(eddyb) should use `def_span`.
882899
if let Some(did) = did.as_local() {
883900
if self.tcx().sess.opts.unstable_opts.span_free_formats {

compiler/rustc_monomorphize/src/collector.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,15 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
666666
debug!(?def_id, ?fn_span);
667667

668668
for arg in args {
669-
if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node) {
669+
// Moving args into functions is typically implemented with pointer
670+
// passing at the llvm-ir level and not by memcpy's. So always allow
671+
// moving args into functions.
672+
let operand: &mir::Operand<'tcx> = &arg.node;
673+
if let mir::Operand::Move(_) = operand {
674+
continue;
675+
}
676+
677+
if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) {
670678
self.lint_large_assignment(limit.0, too_large_size, location, arg.span);
671679
};
672680
}

compiler/rustc_span/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,13 @@ impl Span {
625625
span.lo < other.hi && other.lo < span.hi
626626
}
627627

628+
/// Returns `true` if `self` touches or adjoins `other`.
629+
pub fn overlaps_or_adjacent(self, other: Span) -> bool {
630+
let span = self.data();
631+
let other = other.data();
632+
span.lo <= other.hi && other.lo <= span.hi
633+
}
634+
628635
/// Returns `true` if the spans are equal with regards to the source text.
629636
///
630637
/// Use this instead of `==` when either span could be generated code,

library/core/src/intrinsics/simd.rs

+51-3
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,27 @@ extern "platform-intrinsic" {
190190
///
191191
/// `T` must be a vector.
192192
///
193-
/// `U` must be a const array of `i32`s.
193+
/// `U` must be a **const** array of `i32`s. This means it must either refer to a named
194+
/// const or be given as an inline const expression (`const { ... }`).
194195
///
195196
/// `V` must be a vector with the same element type as `T` and the same length as `U`.
196197
///
197-
/// Concatenates `x` and `y`, then returns a new vector such that each element is selected from
198-
/// the concatenation by the matching index in `idx`.
198+
/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy`
199+
/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds
200+
/// of `xy`.
199201
pub fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
200202

203+
/// Shuffle two vectors by const indices.
204+
///
205+
/// `T` must be a vector.
206+
///
207+
/// `U` must be a vector with the same element type as `T` and the same length as `IDX`.
208+
///
209+
/// Returns a new vector such that element `i` is selected from `xy[IDX[i]]`, where `xy`
210+
/// is the concatenation of `x` and `y`. It is a compile-time error if `IDX[i]` is out-of-bounds
211+
/// of `xy`.
212+
pub fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
213+
201214
/// Read a vector of pointers.
202215
///
203216
/// `T` must be a vector.
@@ -232,6 +245,9 @@ extern "platform-intrinsic" {
232245
/// corresponding value in `val` to the pointer.
233246
/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
234247
///
248+
/// The stores happen in left-to-right order.
249+
/// (This is relevant in case two of the stores overlap.)
250+
///
235251
/// # Safety
236252
/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element
237253
/// type).
@@ -468,4 +484,36 @@ extern "platform-intrinsic" {
468484
///
469485
/// `T` must be a vector of integers.
470486
pub fn simd_cttz<T>(x: T) -> T;
487+
488+
/// Round up each element to the next highest integer-valued float.
489+
///
490+
/// `T` must be a vector of floats.
491+
pub fn simd_ceil<T>(x: T) -> T;
492+
493+
/// Round down each element to the next lowest integer-valued float.
494+
///
495+
/// `T` must be a vector of floats.
496+
pub fn simd_floor<T>(x: T) -> T;
497+
498+
/// Round each element to the closest integer-valued float.
499+
/// Ties are resolved by rounding away from 0.
500+
///
501+
/// `T` must be a vector of floats.
502+
pub fn simd_round<T>(x: T) -> T;
503+
504+
/// Return the integer part of each element as an integer-valued float.
505+
/// In other words, non-integer values are truncated towards zero.
506+
///
507+
/// `T` must be a vector of floats.
508+
pub fn simd_trunc<T>(x: T) -> T;
509+
510+
/// Takes the square root of each element.
511+
///
512+
/// `T` must be a vector of floats.
513+
pub fn simd_fsqrt<T>(x: T) -> T;
514+
515+
/// Computes `(x*y) + z` for each element, but without any intermediate rounding.
516+
///
517+
/// `T` must be a vector of floats.
518+
pub fn simd_fma<T>(x: T, y: T, z: T) -> T;
471519
}

src/bootstrap/src/core/config/config.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1810,10 +1810,9 @@ impl Config {
18101810
target.llvm_config = Some(config.src.join(s));
18111811
}
18121812
if let Some(patches) = cfg.llvm_has_rust_patches {
1813-
assert_eq!(
1814-
config.submodules,
1815-
Some(false),
1816-
"cannot set `llvm-has-rust-patches` for a managed submodule (set `build.submodules = false` if you want to apply patches)"
1813+
assert!(
1814+
config.submodules == Some(false) || cfg.llvm_config.is_some(),
1815+
"use of `llvm-has-rust-patches` is restricted to cases where either submodules are disabled or llvm-config been provided"
18171816
);
18181817
target.llvm_has_rust_patches = Some(patches);
18191818
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![feature(core_intrinsics)]
2+
#![feature(custom_mir)]
3+
4+
use std::intrinsics::mir::*;
5+
use std::num::NonZeroI32;
6+
7+
// We define our own option type so that we can control the varian indices.
8+
#[allow(unused)]
9+
enum Option<T> {
10+
None,
11+
Some(T),
12+
}
13+
use Option::*;
14+
15+
#[custom_mir(dialect = "runtime", phase = "optimized")]
16+
fn set_discriminant(ptr: &mut Option<NonZeroI32>) {
17+
mir! {
18+
{
19+
// We set the discriminant to `Some`, which is a NOP since this is the niched variant.
20+
// However, the enum is actually encoding `None` currently! That's not good...
21+
SetDiscriminant(*ptr, 1);
22+
//~^ ERROR: trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
23+
Return()
24+
}
25+
}
26+
}
27+
28+
pub fn main() {
29+
let mut v = None;
30+
set_discriminant(&mut v);
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
2+
--> $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
3+
|
4+
LL | SetDiscriminant(*ptr, 1);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^ trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `set_discriminant` at $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
11+
note: inside `main`
12+
--> $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
13+
|
14+
LL | set_discriminant(&mut v);
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to 1 previous error
20+

tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir

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

3-
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} {
3+
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} {
44
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
55

66
bb0: {

tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir

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

3-
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} {
3+
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} {
44
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
55

66
bb0: {

tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut
22

3-
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} {
3+
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} {
44
debug a => _2;
55
debug b => ((*_1).0: i32);
66
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};

tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut
22

3-
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} {
3+
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} {
44
debug a => _2;
55
debug b => ((*_1).0: i32);
66
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};

0 commit comments

Comments
 (0)