diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 546001a25b299..85ebbb00c5f28 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -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 = @@ -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 = @@ -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 = diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index fb89b49faded5..a649526c1964a 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -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, } @@ -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()); @@ -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(self, _: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>) { @@ -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:?}")); } } diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index bb8c17cf7791d..e951a77611c21 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -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 }); + } } } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 38ad8cbf3a691..4acf4ed893c5e 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -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. diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 03717a4d654c7..2deb18484ec2e 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -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); } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 2beabc0835db1..28f850a50a0db 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -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![]); diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 66f448a451ee5..a1cdc794749c7 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -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. @@ -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 diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 13cc5cbed443f..7cb326ce696ab 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -358,11 +358,17 @@ pub fn suggest_constraining_type_params<'a>( // trait Foo {... } // - 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) 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 (``), 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; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f90703e61844e..5cf90e94907b0 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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 { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3376af986531e..149e4c2cb08ef 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -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); }; } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 7d95a0bc47821..49ae9f16c8e52 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -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, diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index 0fd27974dceca..ef4c65639eb4d 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -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(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(x: T, y: T) -> U; + /// Read a vector of pointers. /// /// `T` must be a vector. @@ -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 `::write` (e.g. aligned to the element /// type). @@ -468,4 +484,36 @@ extern "platform-intrinsic" { /// /// `T` must be a vector of integers. pub fn simd_cttz(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(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(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(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(x: T) -> T; + + /// Takes the square root of each element. + /// + /// `T` must be a vector of floats. + pub fn simd_fsqrt(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(x: T, y: T, z: T) -> T; } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index c0dd1e1208484..4c64850c0e04b 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -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); } diff --git a/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs b/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs new file mode 100644 index 0000000000000..7097aa0c43ae3 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.rs @@ -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 { + None, + Some(T), +} +use Option::*; + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn set_discriminant(ptr: &mut Option) { + 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> to the niched variant, but the value does not match + Return() + } + } +} + +pub fn main() { + let mut v = None; + set_discriminant(&mut v); +} diff --git a/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.stderr b/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.stderr new file mode 100644 index 0000000000000..a48a0a993daa1 --- /dev/null +++ b/src/tools/miri/tests/fail/enum-set-discriminant-niche-variant-wrong.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: trying to set discriminant of a Option> 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> 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 + diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir index 7df4eb492605b..21a9f6f8721e8 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir @@ -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: { diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir index 7df4eb492605b..21a9f6f8721e8 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir @@ -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: { diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir index 517b8d0dd883b..1cfb6c2f3ea82 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir @@ -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}; diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir index 517b8d0dd883b..1cfb6c2f3ea82 100644 --- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir @@ -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}; diff --git a/tests/ui/async-await/async-closures/is-not-fn.rs b/tests/ui/async-await/async-closures/is-not-fn.rs index 40b0febbf0692..81666cada31c6 100644 --- a/tests/ui/async-await/async-closures/is-not-fn.rs +++ b/tests/ui/async-await/async-closures/is-not-fn.rs @@ -5,5 +5,5 @@ fn main() { fn needs_fn(x: impl FnOnce()) {} needs_fn(async || {}); - //~^ ERROR expected `{coroutine-closure@is-not-fn.rs:7:14}` to be a closure that returns `()` + //~^ ERROR expected `{async closure@is-not-fn.rs:7:14}` to be a closure that returns `()` } diff --git a/tests/ui/async-await/async-closures/is-not-fn.stderr b/tests/ui/async-await/async-closures/is-not-fn.stderr index 6169cee85fd32..130746ece675f 100644 --- a/tests/ui/async-await/async-closures/is-not-fn.stderr +++ b/tests/ui/async-await/async-closures/is-not-fn.stderr @@ -1,4 +1,4 @@ -error[E0271]: expected `{coroutine-closure@is-not-fn.rs:7:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:7:23: 7:25}` +error[E0271]: expected `{async closure@is-not-fn.rs:7:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:7:23: 7:25}` --> $DIR/is-not-fn.rs:7:14 | LL | needs_fn(async || {}); diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.stderr b/tests/ui/async-await/async-closures/move-consuming-capture.stderr index 2c2a0d1162d17..45c1eac8f8f56 100644 --- a/tests/ui/async-await/async-closures/move-consuming-capture.stderr +++ b/tests/ui/async-await/async-closures/move-consuming-capture.stderr @@ -2,7 +2,7 @@ error[E0382]: use of moved value: `x` --> $DIR/move-consuming-capture.rs:17:9 | LL | let x = async move || { - | - move occurs because `x` has type `{coroutine-closure@$DIR/move-consuming-capture.rs:13:17: 13:30}`, which does not implement the `Copy` trait + | - move occurs because `x` has type `{async closure@$DIR/move-consuming-capture.rs:13:17: 13:30}`, which does not implement the `Copy` trait ... LL | x().await; | --- `x` moved due to this method call diff --git a/tests/ui/coercion/type-errors.rs b/tests/ui/coercion/type-errors.rs new file mode 100644 index 0000000000000..a2f0e55f1b931 --- /dev/null +++ b/tests/ui/coercion/type-errors.rs @@ -0,0 +1,15 @@ +// Regression test for an ICE: https://github.com/rust-lang/rust/issues/120884 +// We still need to properly go through coercions between types with errors instead of +// shortcutting and returning success, because we need the adjustments for building the MIR. + +pub fn has_error() -> TypeError {} +//~^ ERROR cannot find type `TypeError` in this scope + +pub fn cast() -> *const u8 { + // Casting a function item to a data pointer in valid in HIR, but invalid in MIR. + // We need an adjustment (ReifyFnPointer) to insert a cast from the function item + // to a function pointer as a separate MIR statement. + has_error as *const u8 +} + +fn main() {} diff --git a/tests/ui/coercion/type-errors.stderr b/tests/ui/coercion/type-errors.stderr new file mode 100644 index 0000000000000..489cd9ddf130e --- /dev/null +++ b/tests/ui/coercion/type-errors.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `TypeError` in this scope + --> $DIR/type-errors.rs:5:23 + | +LL | pub fn has_error() -> TypeError {} + | ^^^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/consts/miri_unleashed/extern-static.rs b/tests/ui/consts/miri_unleashed/extern-static.rs new file mode 100644 index 0000000000000..81176b3d4e997 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/extern-static.rs @@ -0,0 +1,24 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(thread_local)] +#![allow(static_mut_ref)] + +extern "C" { + static mut DATA: u8; +} + +// Make sure we catch accessing extern static. +static TEST_READ: () = { + unsafe { let _val = DATA; } + //~^ ERROR could not evaluate static initializer + //~| NOTE cannot access extern static +}; +static TEST_WRITE: () = { + unsafe { DATA = 0; } + //~^ ERROR could not evaluate static initializer + //~| NOTE cannot access extern static +}; + +// Just creating a reference is fine, as long as we are not reading or writing. +static TEST_REF: &u8 = unsafe { &DATA }; + +fn main() {} diff --git a/tests/ui/consts/miri_unleashed/extern-static.stderr b/tests/ui/consts/miri_unleashed/extern-static.stderr new file mode 100644 index 0000000000000..0979a5e4fb197 --- /dev/null +++ b/tests/ui/consts/miri_unleashed/extern-static.stderr @@ -0,0 +1,15 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/extern-static.rs:11:25 + | +LL | unsafe { let _val = DATA; } + | ^^^^ cannot access extern static (DefId(0:4 ~ extern_static[c41e]::{extern#0}::DATA)) + +error[E0080]: could not evaluate static initializer + --> $DIR/extern-static.rs:16:14 + | +LL | unsafe { DATA = 0; } + | ^^^^^^^^ cannot access extern static (DefId(0:4 ~ extern_static[c41e]::{extern#0}::DATA)) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/tls.rs b/tests/ui/consts/miri_unleashed/tls.rs index d06d7cf19f7ee..7319a5135d3a1 100644 --- a/tests/ui/consts/miri_unleashed/tls.rs +++ b/tests/ui/consts/miri_unleashed/tls.rs @@ -14,6 +14,8 @@ static TEST_BAD: () = { }; // Make sure we catch taking a reference to thread-local storage. +// The actual pointer depends on the thread, so even just taking a reference already does not make +// sense at compile-time. static TEST_BAD_REF: () = { unsafe { let _val = &A; } //~^ ERROR could not evaluate static initializer diff --git a/tests/ui/consts/miri_unleashed/tls.stderr b/tests/ui/consts/miri_unleashed/tls.stderr index ec24527d6c0e5..a00b7eb13128c 100644 --- a/tests/ui/consts/miri_unleashed/tls.stderr +++ b/tests/ui/consts/miri_unleashed/tls.stderr @@ -5,7 +5,7 @@ LL | unsafe { let _val = A; } | ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A)) error[E0080]: could not evaluate static initializer - --> $DIR/tls.rs:18:26 + --> $DIR/tls.rs:20:26 | LL | unsafe { let _val = &A; } | ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A)) @@ -18,7 +18,7 @@ help: skipping check that does not even have a feature gate LL | unsafe { let _val = A; } | ^ help: skipping check that does not even have a feature gate - --> $DIR/tls.rs:18:26 + --> $DIR/tls.rs:20:26 | LL | unsafe { let _val = &A; } | ^ diff --git a/tests/ui/error-codes/E0401.rs b/tests/ui/error-codes/E0401.rs index 8f8d6b87ef209..a120198b7284d 100644 --- a/tests/ui/error-codes/E0401.rs +++ b/tests/ui/error-codes/E0401.rs @@ -9,8 +9,6 @@ fn foo(x: T) { (y: T) { //~ ERROR E0401 } bfnr(x); - //~^ ERROR type annotations needed - //~| ERROR type annotations needed } diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index 754867061c7f8..5d6878620c89a 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -21,7 +21,7 @@ LL | (y: T) { | ^ use of generic parameter from outer item error[E0401]: can't use `Self` from outer item - --> $DIR/E0401.rs:24:25 + --> $DIR/E0401.rs:22:25 | LL | impl Iterator for A { | ---- `Self` type implicitly declared here, by this `impl` @@ -32,45 +32,6 @@ LL | fn helper(sel: &Self) -> u8 { | use of `Self` from outer item | refer to the type directly here instead -error[E0283]: type annotations needed - --> $DIR/E0401.rs:11:5 - | -LL | bfnr(x); - | ^^^^ cannot infer type of the type parameter `V` declared on the function `bfnr` - | - = note: cannot satisfy `_: Baz<_>` -note: required by a bound in `bfnr` - --> $DIR/E0401.rs:4:19 - | -LL | fn bfnr, W: Fn()>(y: T) { - | ^^^^^^ required by this bound in `bfnr` -help: consider specifying the generic arguments - | -LL | bfnr::(x); - | +++++++++++ - -error[E0283]: type annotations needed - --> $DIR/E0401.rs:11:5 - | -LL | bfnr(x); - | ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr` - | - = note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`: - - impl Fn for &F - where A: Tuple, F: Fn, F: ?Sized; - - impl Fn for Box - where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; -note: required by a bound in `bfnr` - --> $DIR/E0401.rs:4:30 - | -LL | fn bfnr, W: Fn()>(y: T) { - | ^^^^ required by this bound in `bfnr` -help: consider specifying the generic arguments - | -LL | bfnr::(x); - | +++++++++++ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0283, E0401. -For more information about an error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0401`. diff --git a/tests/ui/lint/large_assignments/box_rc_arc_allowed.rs b/tests/ui/lint/large_assignments/box_rc_arc_allowed.rs deleted file mode 100644 index 33113642023a2..0000000000000 --- a/tests/ui/lint/large_assignments/box_rc_arc_allowed.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![deny(large_assignments)] -#![feature(large_assignments)] -#![move_size_limit = "1000"] -// build-fail -// only-x86_64 - -// edition:2018 -// compile-flags: -Zmir-opt-level=0 - -use std::{sync::Arc, rc::Rc}; - -fn main() { - let _ = Arc::new([0; 9999]); // OK! - let _ = Box::new([0; 9999]); // OK! - let _ = Rc::new([0; 9999]); // OK! - let _ = NotBox::new([0; 9999]); //~ ERROR large_assignments -} - -struct NotBox { - data: [u8; 9999], -} - -impl NotBox { - fn new(data: [u8; 9999]) -> Self { - Self { - data, //~ ERROR large_assignments - } - } -} diff --git a/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs new file mode 100644 index 0000000000000..866a4d10ff5a4 --- /dev/null +++ b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs @@ -0,0 +1,38 @@ +#![deny(large_assignments)] +#![feature(large_assignments)] +#![move_size_limit = "1000"] +// build-fail +// only-64bit + +// edition:2018 +// compile-flags: -Zmir-opt-level=1 + +use std::{sync::Arc, rc::Rc}; + +fn main() { + let data = [0; 9999]; + + // Looking at --emit mir, we can see that all parameters below are passed by + // copy. But it requires at least mir-opt-level=1. + let _ = Arc::new(data); // OK! + let _ = Box::new(data); // OK! + let _ = Rc::new(data); // OK! + + // Looking at --emit llvm-ir, we can see that a memcpy is involved in the + // parameter passing. So we want the lint to trigger here. + let _ = NotBox::new(data); //~ ERROR large_assignments +} + +struct NotBox { + data: [u8; 9999], +} + +impl NotBox { + fn new(data: [u8; 9999]) -> Self { + // Looking at --emit llvm-ir, we can see that a memcpy is involved. + // So we want the lint to trigger here. + Self { //~ ERROR large_assignments + data, + } + } +} diff --git a/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.stderr similarity index 60% rename from tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr rename to tests/ui/lint/large_assignments/copy_into_box_rc_arc.stderr index fefb3a9621b54..6e42328a11133 100644 --- a/tests/ui/lint/large_assignments/box_rc_arc_allowed.stderr +++ b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.stderr @@ -1,21 +1,23 @@ error: moving 9999 bytes - --> $DIR/box_rc_arc_allowed.rs:16:25 + --> $DIR/copy_into_box_rc_arc.rs:23:25 | -LL | let _ = NotBox::new([0; 9999]); - | ^^^^^^^^^ value moved from here +LL | let _ = NotBox::new(data); + | ^^^^ value moved from here | = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` note: the lint level is defined here - --> $DIR/box_rc_arc_allowed.rs:1:9 + --> $DIR/copy_into_box_rc_arc.rs:1:9 | LL | #![deny(large_assignments)] | ^^^^^^^^^^^^^^^^^ error: moving 9999 bytes - --> $DIR/box_rc_arc_allowed.rs:26:13 + --> $DIR/copy_into_box_rc_arc.rs:34:9 | -LL | data, - | ^^^^ value moved from here +LL | / Self { +LL | | data, +LL | | } + | |_________^ value moved from here | = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` diff --git a/tests/ui/lint/large_assignments/large_future.rs b/tests/ui/lint/large_assignments/large_future.rs index 834746fa97e71..a69ff356c6b47 100644 --- a/tests/ui/lint/large_assignments/large_future.rs +++ b/tests/ui/lint/large_assignments/large_future.rs @@ -2,7 +2,7 @@ #![cfg_attr(attribute, feature(large_assignments))] #![cfg_attr(attribute, move_size_limit = "1000")] // build-fail -// only-x86_64 +// only-64bit // revisions: attribute option // [option]compile-flags: -Zmove-size-limit=1000 diff --git a/tests/ui/lint/large_assignments/move_into_box_rc_arc.rs b/tests/ui/lint/large_assignments/move_into_box_rc_arc.rs new file mode 100644 index 0000000000000..b7a70dfdda0e3 --- /dev/null +++ b/tests/ui/lint/large_assignments/move_into_box_rc_arc.rs @@ -0,0 +1,38 @@ +#![deny(large_assignments)] +#![feature(large_assignments)] +#![move_size_limit = "1000"] +// build-fail +// only-64bit + +// edition:2018 +// compile-flags: -Zmir-opt-level=0 + +use std::{sync::Arc, rc::Rc}; + +fn main() { + // Looking at --emit mir, we can see that all parameters below are passed + // by move. + let _ = Arc::new([0; 9999]); // OK! + let _ = Box::new([0; 9999]); // OK! + let _ = Rc::new([0; 9999]); // OK! + + // Looking at --emit llvm-ir, we can see that no memcpy is involved in the + // parameter passing. Instead, a pointer is passed. This is typically what + // we get when moving parameter into functions. So we don't want the lint to + // trigger here. + let _ = NotBox::new([0; 9999]); // OK (compare with copy_into_box_rc_arc.rs) +} + +struct NotBox { + data: [u8; 9999], +} + +impl NotBox { + fn new(data: [u8; 9999]) -> Self { + Self { + // Looking at --emit llvm-ir, we can see that a memcpy is involved. + // So we want the lint to trigger here. + data, //~ ERROR large_assignments + } + } +} diff --git a/tests/ui/lint/large_assignments/move_into_box_rc_arc.stderr b/tests/ui/lint/large_assignments/move_into_box_rc_arc.stderr new file mode 100644 index 0000000000000..a386de5e5e8e5 --- /dev/null +++ b/tests/ui/lint/large_assignments/move_into_box_rc_arc.stderr @@ -0,0 +1,15 @@ +error: moving 9999 bytes + --> $DIR/move_into_box_rc_arc.rs:35:13 + | +LL | data, + | ^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/move_into_box_rc_arc.rs:1:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/large_assignments/move_into_fn.rs b/tests/ui/lint/large_assignments/move_into_fn.rs new file mode 100644 index 0000000000000..359705bfc03ec --- /dev/null +++ b/tests/ui/lint/large_assignments/move_into_fn.rs @@ -0,0 +1,22 @@ +// build-fail + +#![feature(large_assignments)] +#![move_size_limit = "1000"] +#![deny(large_assignments)] +#![allow(unused)] + +// Note: This type does not implement Copy. +struct Data([u8; 9999]); + +fn main() { + // Looking at llvm-ir output, we can see a memcpy'd into Data, so we want + // the lint to trigger here. + let data = Data([100; 9999]); //~ ERROR large_assignments + + // Looking at llvm-ir output, we can see that there is no memcpy involved in + // this function call. Instead, just a pointer is passed to the function. So + // the lint shall not trigger here. + take_data(data); +} + +fn take_data(data: Data) {} diff --git a/tests/ui/lint/large_assignments/move_into_fn.stderr b/tests/ui/lint/large_assignments/move_into_fn.stderr new file mode 100644 index 0000000000000..92a0489e472f9 --- /dev/null +++ b/tests/ui/lint/large_assignments/move_into_fn.stderr @@ -0,0 +1,15 @@ +error: moving 9999 bytes + --> $DIR/move_into_fn.rs:14:16 + | +LL | let data = Data([100; 9999]); + | ^^^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/move_into_fn.rs:5:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/proc-macro/auxiliary/issue-118809.rs b/tests/ui/proc-macro/auxiliary/issue-118809.rs new file mode 100644 index 0000000000000..029b58c6d0c19 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/issue-118809.rs @@ -0,0 +1,20 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(Deserialize)] +pub fn deserialize_derive(input: TokenStream) -> TokenStream { + "impl Build { + fn deserialize() -> Option { + let x: Option = Some(0); + Some(x? + 1) + } + } + " + .parse() + .unwrap() +} diff --git a/tests/ui/proc-macro/issue-118809.rs b/tests/ui/proc-macro/issue-118809.rs new file mode 100644 index 0000000000000..732bf19c1736f --- /dev/null +++ b/tests/ui/proc-macro/issue-118809.rs @@ -0,0 +1,10 @@ +// aux-build: issue-118809.rs + +#[macro_use] +extern crate issue_118809; + +#[derive(Deserialize)] //~ ERROR mismatched types [E0308] +pub struct Build { +} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-118809.stderr b/tests/ui/proc-macro/issue-118809.stderr new file mode 100644 index 0000000000000..30b09fd4006bf --- /dev/null +++ b/tests/ui/proc-macro/issue-118809.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-118809.rs:6:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | | + | expected `u64`, found `u32` + | arguments to this enum variant are incorrect + | +help: the type constructed contains `u32` due to the type of the argument passed + --> $DIR/issue-118809.rs:6:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ this argument influences the type of `Some` +note: tuple variant defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index dc4ec5d3ee28b..ec9826819c0e5 100644 --- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -18,16 +18,16 @@ help: use parentheses to call this function LL | bar(foo()); | ++ -error[E0277]: `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future +error[E0277]: `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 | LL | bar(async_closure); - | --- ^^^^^^^^^^^^^ `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future + | --- ^^^^^^^^^^^^^ `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` - = note: {coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited + = help: the trait `Future` is not implemented for `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` + = note: {async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | diff --git a/tests/ui/trait-impl-bound-suggestions.fixed b/tests/ui/trait-impl-bound-suggestions.fixed index 744e7bef04e97..fb11286a175e5 100644 --- a/tests/ui/trait-impl-bound-suggestions.fixed +++ b/tests/ui/trait-impl-bound-suggestions.fixed @@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric where X: std::marker::Copy { } } +// Regression test for #120838 +#[allow(dead_code)] +trait InsufficientlyConstrainedGenericWithEmptyWhere where X: std::marker::Copy { + fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct { + //~^ ERROR the trait bound `X: Copy` is not satisfied + ConstrainedStruct { x } + } +} + pub fn main() { } diff --git a/tests/ui/trait-impl-bound-suggestions.rs b/tests/ui/trait-impl-bound-suggestions.rs index bf75175179efd..46130a5e76671 100644 --- a/tests/ui/trait-impl-bound-suggestions.rs +++ b/tests/ui/trait-impl-bound-suggestions.rs @@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric { } } +// Regression test for #120838 +#[allow(dead_code)] +trait InsufficientlyConstrainedGenericWithEmptyWhere where { + fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct { + //~^ ERROR the trait bound `X: Copy` is not satisfied + ConstrainedStruct { x } + } +} + pub fn main() { } diff --git a/tests/ui/trait-impl-bound-suggestions.stderr b/tests/ui/trait-impl-bound-suggestions.stderr index c1f31e2b32e27..9883c5bda017f 100644 --- a/tests/ui/trait-impl-bound-suggestions.stderr +++ b/tests/ui/trait-impl-bound-suggestions.stderr @@ -14,6 +14,22 @@ help: consider further restricting type parameter `X` LL | trait InsufficientlyConstrainedGeneric where X: std::marker::Copy { | ++++++++++++++++++++++++++ -error: aborting due to 1 previous error +error[E0277]: the trait bound `X: Copy` is not satisfied + --> $DIR/trait-impl-bound-suggestions.rs:23:52 + | +LL | fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct { + | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X` + | +note: required by a bound in `ConstrainedStruct` + --> $DIR/trait-impl-bound-suggestions.rs:8:29 + | +LL | struct ConstrainedStruct { + | ^^^^ required by this bound in `ConstrainedStruct` +help: consider further restricting type parameter `X` + | +LL | trait InsufficientlyConstrainedGenericWithEmptyWhere where X: std::marker::Copy { + | ++++++++++++++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/issue-104510-ice.rs b/tests/ui/typeck/issue-104510-ice.rs index 635cc8fad66f1..157bdf07e3826 100644 --- a/tests/ui/typeck/issue-104510-ice.rs +++ b/tests/ui/typeck/issue-104510-ice.rs @@ -6,7 +6,7 @@ struct W(Oops); unsafe fn test() { let j = W(()); - let pointer = &j as *const _; //~ ERROR type annotations needed + let pointer = &j as *const _; core::arch::asm!( "nop", in("eax") pointer, diff --git a/tests/ui/typeck/issue-104510-ice.stderr b/tests/ui/typeck/issue-104510-ice.stderr index 774e52681849f..143139b2c089c 100644 --- a/tests/ui/typeck/issue-104510-ice.stderr +++ b/tests/ui/typeck/issue-104510-ice.stderr @@ -4,18 +4,6 @@ error[E0412]: cannot find type `Oops` in this scope LL | struct W(Oops); | ^^^^ not found in this scope -error[E0282]: type annotations needed for `*const W` - --> $DIR/issue-104510-ice.rs:9:9 - | -LL | let pointer = &j as *const _; - | ^^^^^^^ - | -help: consider giving `pointer` an explicit type, where the type for type parameter `T` is specified - | -LL | let pointer: *const W = &j as *const _; - | +++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0282, E0412. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0412`.