diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 0de1fcd7c3a9b..b207244349d8f 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -12,7 +12,7 @@ use rustc_hir::find_attr; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; -use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, FnAbi}; use tracing::field::Empty; use tracing::{info, instrument, trace}; @@ -284,7 +284,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { 'tcx: 'y, { assert_eq!(callee_ty, callee_abi.layout.ty); - if callee_abi.mode == PassMode::Ignore { + if callee_abi.is_ignore() { // This one is skipped. Still must be made live though! if !already_live { self.storage_live(callee_arg.as_local().unwrap())?; @@ -450,7 +450,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let mut caller_args = args .iter() .zip(caller_fn_abi.args.iter()) - .filter(|arg_and_abi| !matches!(arg_and_abi.1.mode, PassMode::Ignore)); + .filter(|arg_and_abi| !arg_and_abi.1.is_ignore()); // Now we have to spread them out across the callee's locals, // taking into account the `spread_arg`. If we could write @@ -480,7 +480,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Consume the remaining arguments by putting them into the variable argument // list. - let varargs = self.allocate_varargs(&mut caller_args, &mut callee_args_abis)?; + let varargs = self.allocate_varargs( + &mut caller_args, + // "Ignored" arguments aren't actually passed, so the callee should also + // ignore them. (`pass_argument` does this for regular arguments.) + (&mut callee_args_abis).filter(|(_, abi)| !abi.is_ignore()), + )?; // When the frame is dropped, these variable arguments are deallocated. self.frame_mut().va_list = varargs.clone(); let key = self.va_list_ptr(varargs.into()); diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 6da6ed2ec757a..b0f34264ad841 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -631,8 +631,8 @@ impl<'a, 'tcx: 'a, M: Machine<'tcx>> InterpCx<'tcx, M> { /// of variadic arguments. Return a list of the places that hold those arguments. pub(crate) fn allocate_varargs( &mut self, - caller_args: &mut I, - callee_abis: &mut J, + caller_args: I, + mut callee_abis: J, ) -> InterpResult<'tcx, Vec>> where I: Iterator, &'a ArgAbi<'tcx, Ty<'tcx>>)>, diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 2cf490350e907..b72927f455c76 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -7,6 +7,7 @@ use std::borrow::Cow; use std::fmt::Write; use std::hash::Hash; +use std::mem; use std::num::NonZero; use either::{Left, Right}; @@ -288,6 +289,8 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> { /// If this is `Some`, then `reset_provenance_and_padding` must be true (but not vice versa: /// we might not track data vs padding bytes if the operand isn't stored in memory anyway). data_bytes: Option, + /// True if we are inside of `MaybeDangling`. This disables pointer access checks. + may_dangle: bool, } impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { @@ -489,7 +492,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta(), place.layout)?; } - // Make sure this is dereferenceable and all. + + // Determine size and alignment of pointee. let size_and_align = try_validation!( self.ecx.size_and_align_of_val(&place), self.path, @@ -503,27 +507,33 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // alignment and size determined by the layout (size will be 0, // alignment should take attributes into account). .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); - // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. - try_validation!( - self.ecx.check_ptr_access( - place.ptr(), - size, - CheckInAllocMsg::Dereferenceable, // will anyway be replaced by validity message - ), - self.path, - Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind, maybe: false }, - Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance { - ptr_kind, - // FIXME this says "null pointer" when null but we need translate - pointer: format!("{}", Pointer::>::without_provenance(i)) - }, - Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds { - ptr_kind - }, - Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree { - ptr_kind, - }, - ); + + if !self.may_dangle { + // Make sure this is dereferenceable and all. + + // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. + // Call `check_ptr_access` to avoid checking alignment here. + try_validation!( + self.ecx.check_ptr_access( + place.ptr(), + size, + CheckInAllocMsg::Dereferenceable, // will anyway be replaced by validity message + ), + self.path, + Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind, maybe: false }, + Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance { + ptr_kind, + pointer: format!("{}", Pointer::>::without_provenance(i)) + }, + Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds { + ptr_kind + }, + Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree { + ptr_kind, + }, + ); + } + try_validation!( self.ecx.check_ptr_align( place.ptr(), @@ -536,8 +546,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { found_bytes: has.bytes() }, ); - // Make sure this is non-null. We checked dereferenceability above, but if `size` is zero - // that does not imply non-null. + + // Make sure this is non-null. This is obviously needed when `may_dangle` is set, + // but even if we did check dereferenceability above that would still allow null + // pointers if `size` is zero. let scalar = Scalar::from_maybe_pointer(place.ptr(), self.ecx); if self.ecx.scalar_may_be_null(scalar)? { let maybe = !M::Provenance::OFFSET_IS_ADDR && matches!(scalar, Scalar::Ptr(..)); @@ -1265,6 +1277,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, ty::PatternKind::Or(_patterns) => {} } } + ty::Adt(adt, _) if adt.is_maybe_dangling() => { + let old_may_dangle = mem::replace(&mut self.may_dangle, true); + + let inner = self.ecx.project_field(val, FieldIdx::ZERO)?; + self.visit_value(&inner)?; + + self.may_dangle = old_may_dangle; + } _ => { // default handler try_validation!( @@ -1350,6 +1370,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ecx, reset_provenance_and_padding, data_bytes: reset_padding.then_some(RangeSet(Vec::new())), + may_dangle: false, }; v.visit_value(val)?; v.reset_padding(val)?; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index c2d7b0e21a7fd..39e886227d946 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -465,7 +465,7 @@ declare_features! ( /// Allows having using `suggestion` in the `#[deprecated]` attribute. (unstable, deprecated_suggestion, "1.61.0", Some(94785)), /// Allows deref patterns. - (incomplete, deref_patterns, "1.79.0", Some(87121)), + (unstable, deref_patterns, "1.79.0", Some(87121)), /// Allows deriving the From trait on single-field structs. (unstable, derive_from, "1.91.0", Some(144889)), /// Allows giving non-const impls custom diagnostic messages if attempted to be used as const diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2de101a1e4522..e45d1cf8b5e3b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1792,27 +1792,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_tuple( &self, - elts: &'tcx [hir::Expr<'tcx>], + elements: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { - let flds = expected.only_has_type(self).and_then(|ty| { - let ty = self.try_structurally_resolve_type(expr.span, ty); - match ty.kind() { - ty::Tuple(flds) => Some(&flds[..]), - _ => None, - } + let mut expectations = expected + .only_has_type(self) + .and_then(|ty| self.try_structurally_resolve_type(expr.span, ty).opt_tuple_fields()) + .unwrap_or_default() + .iter(); + + let elements = elements.iter().map(|e| { + let ty = expectations.next().unwrap_or_else(|| self.next_ty_var(e.span)); + self.check_expr_coercible_to_type(e, ty, None); + ty }); - let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { - Some(fs) if i < fs.len() => { - let ety = fs[i]; - self.check_expr_coercible_to_type(e, ety, None); - ety - } - _ => self.check_expr_with_expectation(e, NoExpectation), - }); - let tuple = Ty::new_tup_from_iter(self.tcx, elt_ts_iter); + let tuple = Ty::new_tup_from_iter(self.tcx, elements); + if let Err(guar) = tuple.error_reported() { Ty::new_error(self.tcx, guar) } else { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d0d8fad4b120b..2acc58422902b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1592,7 +1592,8 @@ impl<'tcx> Ty<'tcx> { } } - /// Iterates over tuple fields. + /// Returns a list of tuple type arguments. + /// /// Panics when called on anything but a tuple. #[inline] pub fn tuple_fields(self) -> &'tcx List> { @@ -1602,6 +1603,15 @@ impl<'tcx> Ty<'tcx> { } } + /// Returns a list of tuple type arguments, or `None` if `self` isn't a tuple. + #[inline] + pub fn opt_tuple_fields(self) -> Option<&'tcx List>> { + match self.kind() { + Tuple(args) => Some(args), + _ => None, + } + } + /// If the type contains variants, returns the valid range of variant indices. // // FIXME: This requires the optimized MIR in the case of coroutines. diff --git a/src/doc/unstable-book/src/language-features/deref-patterns.md b/src/doc/unstable-book/src/language-features/deref-patterns.md index 23c2dc688400b..a0c9a7e30277e 100644 --- a/src/doc/unstable-book/src/language-features/deref-patterns.md +++ b/src/doc/unstable-book/src/language-features/deref-patterns.md @@ -6,8 +6,7 @@ The tracking issue for this feature is: [#87121] ------------------------ -> **Note**: This feature is incomplete. In the future, it is meant to supersede -> [`box_patterns`]. +> **Note**: This feature supersedes [`box_patterns`]. This feature permits pattern matching on [smart pointers in the standard library] through their `Deref` target types, either implicitly or with explicit `deref!(_)` patterns (the syntax of which @@ -15,7 +14,6 @@ is currently a placeholder). ```rust #![feature(deref_patterns)] -#![allow(incomplete_features)] let mut v = vec![Box::new(Some(0))]; @@ -58,7 +56,6 @@ Like [`box_patterns`], deref patterns may move out of boxes: ```rust # #![feature(deref_patterns)] -# #![allow(incomplete_features)] struct NoCopy; let deref!(x) = Box::new(NoCopy); drop::(x); @@ -69,7 +66,6 @@ allowing then to be used in deref patterns: ```rust # #![feature(deref_patterns)] -# #![allow(incomplete_features)] match ("test".to_string(), Box::from("test"), b"test".to_vec()) { ("test", "test", b"test") => {} _ => panic!(), diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 617b619a7df90..66e804d972b76 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -917,6 +917,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { RetagInfo { cause: self.retag_cause, in_field: self.in_field }, )?; self.ecx.write_immediate(*val, place)?; + interp_ok(()) } } @@ -964,6 +965,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // even if field retagging is not enabled. *shrug*) self.walk_value(place)?; } + ty::Adt(adt, _) if adt.is_maybe_dangling() => { + // Skip traversing for everything inside of `MaybeDangling` + } _ => { // Not a reference/pointer/box. Recurse. let in_field = mem::replace(&mut self.in_field, true); // remember and restore old value diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 1a7c0af2988a3..a205502327307 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -523,6 +523,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // even if field retagging is not enabled. *shrug*) self.walk_value(place)?; } + ty::Adt(adt, _) if adt.is_maybe_dangling() => { + // Skip traversing for everything inside of `MaybeDangling` + } _ => { // Not a reference/pointer/box. Recurse. self.walk_value(place)?; diff --git a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs new file mode 100644 index 0000000000000..92917c88b7312 --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs @@ -0,0 +1,15 @@ +// Test that an unaligned `MaybeDangling<&u8>` is still detected as UB. +// +//@compile-flags: -Zmiri-disable-stacked-borrows +#![feature(maybe_dangling)] + +use std::mem::{MaybeDangling, transmute}; + +fn main() { + let a = [1u16, 0u16]; + unsafe { + let unaligned = MaybeDangling::new(a.as_ptr().byte_add(1)); + transmute::, MaybeDangling<&u16>>(unaligned) + //~^ ERROR: Undefined Behavior: constructing invalid value: encountered an unaligned reference + }; +} diff --git a/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr new file mode 100644 index 0000000000000..9a50a031cf96e --- /dev/null +++ b/src/tools/miri/tests/fail/unaligned_pointers/maybe_dangling_unalighed.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN) + --> tests/fail/unaligned_pointers/maybe_dangling_unalighed.rs:LL:CC + | +LL | transmute::, MaybeDangling<&u16>>(unaligned) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = 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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_null.rs b/src/tools/miri/tests/fail/validity/maybe_dangling_null.rs new file mode 100644 index 0000000000000..21dba864a3f12 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/maybe_dangling_null.rs @@ -0,0 +1,13 @@ +// Test that a null `MaybeDangling<&u8>` is still detected as UB. +// +//@compile-flags: -Zmiri-disable-stacked-borrows +#![feature(maybe_dangling)] + +use std::mem::{MaybeDangling, transmute}; +use std::ptr::null; + +fn main() { + let null = MaybeDangling::new(null()); + unsafe { transmute::, MaybeDangling<&u8>>(null) }; + //~^ ERROR: Undefined Behavior: constructing invalid value: encountered a null reference +} diff --git a/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr new file mode 100644 index 0000000000000..650234777ccf4 --- /dev/null +++ b/src/tools/miri/tests/fail/validity/maybe_dangling_null.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: constructing invalid value: encountered a null reference + --> tests/fail/validity/maybe_dangling_null.rs:LL:CC + | +LL | unsafe { transmute::, MaybeDangling<&u8>>(null) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = 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: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs new file mode 100644 index 0000000000000..fe2b526d94b19 --- /dev/null +++ b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs @@ -0,0 +1,59 @@ +// Check that `MaybeDangling` actually prevents UB when it wraps dangling +// boxes and references +// +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows +#![feature(maybe_dangling)] + +use std::mem::{self, MaybeDangling}; +use std::ptr::drop_in_place; + +fn main() { + boxy(); + reference(); + write_through_shared_ref(); +} + +fn boxy() { + let mut x = MaybeDangling::new(Box::new(1)); + + // make the box dangle + unsafe { drop_in_place(x.as_mut()) }; + + // move the dangling box (without `MaybeDangling` this causes UB) + let x: MaybeDangling> = x; + + mem::forget(x); +} + +fn reference() { + let x = { + let local = 0; + + // erase the lifetime to make a dangling reference + unsafe { + mem::transmute::, MaybeDangling<&u32>>(MaybeDangling::new(&local)) + } + }; + + // move the dangling reference (without `MaybeDangling` this causes UB) + let _x: MaybeDangling<&u32> = x; +} + +fn write_through_shared_ref() { + // Under the current models, we do not forbid writing through + // `MaybeDangling<&i32>`. That's not yet finally decided, but meanwhile + // ensure we document this and notice when it changes. + + unsafe { + let mutref = &mut 0; + write_through_shr(mem::transmute(mutref)); + } + + fn write_through_shr(x: MaybeDangling<&i32>) { + unsafe { + let y: *mut i32 = mem::transmute(x); + y.write(1); + } + } +} diff --git a/src/tools/miri/tests/pass/c-variadic-ignored-argument.rs b/src/tools/miri/tests/pass/c-variadic-ignored-argument.rs new file mode 100644 index 0000000000000..b41e1b0f076af --- /dev/null +++ b/src/tools/miri/tests/pass/c-variadic-ignored-argument.rs @@ -0,0 +1,21 @@ +//@ ignore-target: windows # does not ignore ZST arguments +//@ ignore-target: powerpc # does not ignore ZST arguments +//@ ignore-target: s390x # does not ignore ZST arguments +//@ ignore-target: sparc # does not ignore ZST arguments +#![feature(c_variadic)] + +// Some platforms ignore ZSTs, meaning that the argument is not passed, even though it is part +// of the callee's ABI. Test that this doesn't trip any asserts. +// +// NOTE: this test only succeeds when the `()` argument uses `Passmode::Ignore`. For some targets, +// notably msvc, such arguments are not ignored, which would cause UB when attempting to read the +// second `i32` argument while the next item in the variable argument list is `()`. + +fn main() { + unsafe extern "C" fn variadic(mut ap: ...) { + ap.arg::(); + ap.arg::(); + } + + unsafe { variadic(0i32, (), 1i32) } +} diff --git a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout index de7da309271da..296339e738455 100644 --- a/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout +++ b/src/tools/miri/tests/pass/stacked_borrows/stack-printing.stdout @@ -1,6 +1,6 @@ 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite ] 0..1: [ SharedReadWrite ] -0..1: [ SharedReadWrite Unique Unique Unique Unique Unique Unique Unique Unique Unique Unique Unique ] -0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled Disabled Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] +0..1: [ SharedReadWrite Unique Unique Unique Unique Unique Unique Unique ] +0..1: [ SharedReadWrite Disabled Disabled Disabled Disabled Disabled Disabled Disabled SharedReadOnly ] 0..1: [ unknown-bottom(..) ] diff --git a/tests/mir-opt/building/match/deref-patterns/string.rs b/tests/mir-opt/building/match/deref-patterns/string.rs index 1f8d6fbb0bd25..92232c7df79dc 100644 --- a/tests/mir-opt/building/match/deref-patterns/string.rs +++ b/tests/mir-opt/building/match/deref-patterns/string.rs @@ -2,7 +2,6 @@ //@ compile-flags: -Z mir-opt-level=0 -C panic=abort #![feature(deref_patterns)] -#![expect(incomplete_features)] #![crate_type = "lib"] // EMIT_MIR string.foo.PreCodegen.after.mir diff --git a/tests/ui/consts/const-eval/c-variadic-ignored-argument.rs b/tests/ui/consts/const-eval/c-variadic-ignored-argument.rs new file mode 100644 index 0000000000000..fe700eea186e0 --- /dev/null +++ b/tests/ui/consts/const-eval/c-variadic-ignored-argument.rs @@ -0,0 +1,18 @@ +//@ build-pass +//@ compile-flags: --emit=obj +#![feature(c_variadic)] +#![feature(const_c_variadic)] +#![feature(const_destruct)] +#![crate_type = "lib"] + +// Regression test for when a c-variadic argument is `PassMode::Ignore`. The caller won't pass the +// argument, but the callee ABI does have the argument. Ensure that const-eval is able to handle +// this case without tripping any asserts. + +const unsafe extern "C" fn read_n(_: ...) {} + +unsafe fn read_too_many() { + const { read_n::<0>((), 1i32) } +} + +fn read_as() -> () {} diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr index 3b9735510bd7e..8810d16ca5986 100644 --- a/tests/ui/loops/loop-break-value.stderr +++ b/tests/ui/loops/loop-break-value.stderr @@ -232,10 +232,10 @@ LL | break (break, break); | || | | || expected because of this `break` | |expected because of this `break` - | expected `()`, found `(!, !)` + | expected `()`, found `(_, _)` | = note: expected unit type `()` - found tuple `(!, !)` + found tuple `(_, _)` error[E0308]: mismatched types --> $DIR/loop-break-value.rs:89:15 diff --git a/tests/ui/never_type/regress/divergent-block-with-tail.stderr b/tests/ui/never_type/regress/divergent-block-with-tail.stderr index 1f205e8967880..94cf5e5fa915f 100644 --- a/tests/ui/never_type/regress/divergent-block-with-tail.stderr +++ b/tests/ui/never_type/regress/divergent-block-with-tail.stderr @@ -22,10 +22,10 @@ error[E0308]: mismatched types LL | fn f() -> isize { | ----- expected `isize` because of return type LL | (return 1, return 2) - | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)` + | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(_, _)` | = note: expected type `isize` - found tuple `(!, !)` + found tuple `(_, _)` error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/deref-patterns/basic.rs b/tests/ui/pattern/deref-patterns/basic.rs index dee4521e1f95c..0cb80b43944d1 100644 --- a/tests/ui/pattern/deref-patterns/basic.rs +++ b/tests/ui/pattern/deref-patterns/basic.rs @@ -1,7 +1,6 @@ //@ run-pass //@ check-run-results #![feature(deref_patterns)] -#![expect(incomplete_features)] fn main() { test(Some(String::from("42"))); diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs index 92c01d737bac6..c3165ebf6cef5 100644 --- a/tests/ui/pattern/deref-patterns/bindings.rs +++ b/tests/ui/pattern/deref-patterns/bindings.rs @@ -1,7 +1,6 @@ //@ revisions: explicit implicit //@ run-pass #![feature(deref_patterns)] -#![allow(incomplete_features)] use std::rc::Rc; diff --git a/tests/ui/pattern/deref-patterns/branch.rs b/tests/ui/pattern/deref-patterns/branch.rs index 9d72b35fd2f1c..5b87742eb319b 100644 --- a/tests/ui/pattern/deref-patterns/branch.rs +++ b/tests/ui/pattern/deref-patterns/branch.rs @@ -2,7 +2,6 @@ //@ run-pass // Test the execution of deref patterns. #![feature(deref_patterns)] -#![allow(incomplete_features)] #[cfg(explicit)] fn branch(vec: Vec) -> u32 { diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs index fdcc6cb461114..633044a597725 100644 --- a/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs +++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.rs @@ -5,7 +5,6 @@ //@ dont-require-annotations: NOTE #![feature(deref_patterns)] -#![expect(incomplete_features)] fn main() { // Baseline 1: under normal circumstances, byte string literal patterns have type `&[u8; N]`, diff --git a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr index 046682004be7e..531d5ba292c43 100644 --- a/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr +++ b/tests/ui/pattern/deref-patterns/byte-string-type-errors.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:13:12 + --> $DIR/byte-string-type-errors.rs:12:12 | LL | if let b"test" = () {} | ^^^^^^^ -- this expression has type `()` @@ -7,7 +7,7 @@ LL | if let b"test" = () {} | expected `()`, found `&[u8; 4]` error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:20:12 + --> $DIR/byte-string-type-errors.rs:19:12 | LL | if let b"test" = &[] as &[i8] {} | ^^^^^^^ ------------ this expression has type `&[i8]` @@ -18,7 +18,7 @@ LL | if let b"test" = &[] as &[i8] {} found reference `&'static [u8]` error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:25:12 + --> $DIR/byte-string-type-errors.rs:24:12 | LL | if let b"test" = *(&[] as &[i8]) {} | ^^^^^^^ --------------- this expression has type `[i8]` @@ -29,7 +29,7 @@ LL | if let b"test" = *(&[] as &[i8]) {} found slice `[u8]` error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:30:12 + --> $DIR/byte-string-type-errors.rs:29:12 | LL | if let b"test" = [()] {} | ^^^^^^^ ---- this expression has type `[(); 1]` @@ -40,7 +40,7 @@ LL | if let b"test" = [()] {} found array `[u8; 4]` error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:33:12 + --> $DIR/byte-string-type-errors.rs:32:12 | LL | if let b"test" = *b"this array is too long" {} | ^^^^^^^ -------------------------- this expression has type `[u8; 22]` @@ -48,7 +48,7 @@ LL | if let b"test" = *b"this array is too long" {} | expected an array with a size of 22, found one with a size of 4 error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:39:12 + --> $DIR/byte-string-type-errors.rs:38:12 | LL | if let b"test" = &mut () {} | ^^^^^^^ ------- this expression has type `&mut ()` @@ -56,7 +56,7 @@ LL | if let b"test" = &mut () {} | expected `()`, found `&[u8; 4]` error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:44:12 + --> $DIR/byte-string-type-errors.rs:43:12 | LL | if let b"test" = &mut [] as &mut [i8] {} | ^^^^^^^ -------------------- this expression has type `&mut [i8]` @@ -67,7 +67,7 @@ LL | if let b"test" = &mut [] as &mut [i8] {} found slice `[u8]` error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:48:12 + --> $DIR/byte-string-type-errors.rs:47:12 | LL | if let b"test" = &mut [()] {} | ^^^^^^^ --------- this expression has type `&mut [(); 1]` @@ -78,7 +78,7 @@ LL | if let b"test" = &mut [()] {} found array `[u8; 4]` error[E0308]: mismatched types - --> $DIR/byte-string-type-errors.rs:52:12 + --> $DIR/byte-string-type-errors.rs:51:12 | LL | if let b"test" = &mut *b"this array is too long" {} | ^^^^^^^ ------------------------------- this expression has type `&mut [u8; 22]` diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs index 2b4746e33e678..36d9ae70efddc 100644 --- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs +++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs @@ -1,5 +1,4 @@ #![feature(deref_patterns)] -#![allow(incomplete_features)] use std::rc::Rc; diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr index a548ac5909a8c..532dd496b235f 100644 --- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr +++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr @@ -1,5 +1,5 @@ error[E0508]: cannot move out of type `[Struct]`, a non-copy slice - --> $DIR/cant_move_out_of_pattern.rs:9:11 + --> $DIR/cant_move_out_of_pattern.rs:8:11 | LL | match b { | ^ cannot move out of here @@ -16,7 +16,7 @@ LL | deref!([ref x]) => x, | +++ error[E0507]: cannot move out of a shared reference - --> $DIR/cant_move_out_of_pattern.rs:17:11 + --> $DIR/cant_move_out_of_pattern.rs:16:11 | LL | match rc { | ^^ @@ -33,7 +33,7 @@ LL | deref!(ref x) => x, | +++ error[E0508]: cannot move out of type `[Struct]`, a non-copy slice - --> $DIR/cant_move_out_of_pattern.rs:25:11 + --> $DIR/cant_move_out_of_pattern.rs:24:11 | LL | match b { | ^ cannot move out of here @@ -50,7 +50,7 @@ LL | [ref x] => x, | +++ error[E0507]: cannot move out of a shared reference - --> $DIR/cant_move_out_of_pattern.rs:35:11 + --> $DIR/cant_move_out_of_pattern.rs:34:11 | LL | match rc { | ^^ diff --git a/tests/ui/pattern/deref-patterns/closure_capture.rs b/tests/ui/pattern/deref-patterns/closure_capture.rs index 497ec622b0cf8..c02c82e9ea0cd 100644 --- a/tests/ui/pattern/deref-patterns/closure_capture.rs +++ b/tests/ui/pattern/deref-patterns/closure_capture.rs @@ -1,6 +1,5 @@ //@ run-pass #![feature(deref_patterns)] -#![allow(incomplete_features)] use std::rc::Rc; diff --git a/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.rs b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.rs index 3a2531f4b95e6..08dec4885846a 100644 --- a/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.rs +++ b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.rs @@ -8,7 +8,6 @@ //! we'd get without `deref_patterns` enabled. #![cfg_attr(deref_patterns, feature(deref_patterns))] -#![cfg_attr(deref_patterns, expect(incomplete_features))] fn uninferred() -> T { unimplemented!() } diff --git a/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.stable.stderr b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.stable.stderr index 61079718c5d5a..0770569e0406e 100644 --- a/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.stable.stderr +++ b/tests/ui/pattern/deref-patterns/const-pats-do-not-mislead-inference.stable.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/const-pats-do-not-mislead-inference.rs:33:12 + --> $DIR/const-pats-do-not-mislead-inference.rs:32:12 | LL | if let b"..." = &&x {} | ^^^^^^ --- this expression has type `&&_` @@ -10,7 +10,7 @@ LL | if let b"..." = &&x {} found reference `&'static [u8; 3]` error[E0308]: mismatched types - --> $DIR/const-pats-do-not-mislead-inference.rs:39:12 + --> $DIR/const-pats-do-not-mislead-inference.rs:38:12 | LL | if let "..." = &Box::new(x) {} | ^^^^^ ------------ this expression has type `&Box<_>` @@ -25,7 +25,7 @@ LL | if let "..." = &*Box::new(x) {} | + error[E0308]: mismatched types - --> $DIR/const-pats-do-not-mislead-inference.rs:45:12 + --> $DIR/const-pats-do-not-mislead-inference.rs:44:12 | LL | if let b"..." = Box::new(&x) {} | ^^^^^^ ------------ this expression has type `Box<&_>` @@ -40,7 +40,7 @@ LL | if let b"..." = *Box::new(&x) {} | + error[E0308]: mismatched types - --> $DIR/const-pats-do-not-mislead-inference.rs:51:12 + --> $DIR/const-pats-do-not-mislead-inference.rs:50:12 | LL | if let "..." = &mut x {} | ^^^^^ ------ this expression has type `&mut _` diff --git a/tests/ui/pattern/deref-patterns/default-infer.rs b/tests/ui/pattern/deref-patterns/default-infer.rs index fb0b2add132a3..38c8793a9b44a 100644 --- a/tests/ui/pattern/deref-patterns/default-infer.rs +++ b/tests/ui/pattern/deref-patterns/default-infer.rs @@ -1,6 +1,5 @@ //@ check-pass #![feature(deref_patterns)] -#![expect(incomplete_features)] fn main() { match <_ as Default>::default() { diff --git a/tests/ui/pattern/deref-patterns/deref-box.rs b/tests/ui/pattern/deref-patterns/deref-box.rs index 39b23dcab51e7..1af13f82f3f97 100644 --- a/tests/ui/pattern/deref-patterns/deref-box.rs +++ b/tests/ui/pattern/deref-patterns/deref-box.rs @@ -3,7 +3,6 @@ //! and `DerefMut::deref_mut`. Test that they work as expected. #![feature(deref_patterns)] -#![expect(incomplete_features)] fn unbox_1(b: Box) -> T { let deref!(x) = b; diff --git a/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs b/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs index e1a37b9c65f4b..e656ef9a43809 100644 --- a/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs +++ b/tests/ui/pattern/deref-patterns/dont-ice-on-slice-in-deref-pat-in-closure.rs @@ -3,7 +3,6 @@ //! inside a deref pattern inside a closure: rust-lang/rust#125059 #![feature(deref_patterns)] -#![allow(incomplete_features, unused)] fn simple_vec(vec: Vec) -> u32 { (|| match Vec::::new() { diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.rs b/tests/ui/pattern/deref-patterns/fake_borrows.rs index fba2873fd02a3..74292fe25d8ce 100644 --- a/tests/ui/pattern/deref-patterns/fake_borrows.rs +++ b/tests/ui/pattern/deref-patterns/fake_borrows.rs @@ -1,5 +1,4 @@ #![feature(deref_patterns)] -#![allow(incomplete_features)] #[rustfmt::skip] fn main() { diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.stderr b/tests/ui/pattern/deref-patterns/fake_borrows.stderr index 7dc3001739e67..312de4760a453 100644 --- a/tests/ui/pattern/deref-patterns/fake_borrows.stderr +++ b/tests/ui/pattern/deref-patterns/fake_borrows.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable - --> $DIR/fake_borrows.rs:9:16 + --> $DIR/fake_borrows.rs:8:16 | LL | match v { | - immutable borrow occurs here @@ -10,7 +10,7 @@ LL | _ if { v[0] = true; false } => {} | mutable borrow occurs here error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable - --> $DIR/fake_borrows.rs:16:16 + --> $DIR/fake_borrows.rs:15:16 | LL | match v { | - immutable borrow occurs here @@ -21,7 +21,7 @@ LL | _ if { v[0] = true; false } => {} | mutable borrow occurs here error[E0510]: cannot assign `*b` in match guard - --> $DIR/fake_borrows.rs:26:16 + --> $DIR/fake_borrows.rs:25:16 | LL | match b { | - value is immutable in match guard @@ -30,7 +30,7 @@ LL | _ if { *b = true; false } => {} | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `*b` in match guard - --> $DIR/fake_borrows.rs:33:16 + --> $DIR/fake_borrows.rs:32:16 | LL | match b { | - value is immutable in match guard diff --git a/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.rs b/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.rs index fbc742aa84774..b775cb3ac756a 100644 --- a/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.rs +++ b/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.rs @@ -1,5 +1,4 @@ #![feature(deref_patterns)] -#![expect(incomplete_features)] fn main() { let vec![const { vec![] }]: Vec = vec![]; diff --git a/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.stderr b/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.stderr index 48728acbc2916..d18ca2589bbc5 100644 --- a/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.stderr +++ b/tests/ui/pattern/deref-patterns/ice-adjust-mode-unimplemented-for-constblock.stderr @@ -1,5 +1,5 @@ error[E0532]: expected a pattern, found a function call - --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:9 + --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:4:9 | LL | let vec![const { vec![] }]: Vec = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant @@ -7,7 +7,7 @@ LL | let vec![const { vec![] }]: Vec = vec![]; = note: function calls are not allowed in patterns: error[E0532]: expected a pattern, found a function call - --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:9 + --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:4:9 | LL | let vec![const { vec![] }]: Vec = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant @@ -15,7 +15,7 @@ LL | let vec![const { vec![] }]: Vec = vec![]; = note: function calls are not allowed in patterns: error: arbitrary expressions aren't allowed in patterns - --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:14 + --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:4:14 | LL | let vec![const { vec![] }]: Vec = vec![]; | ^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | let vec![const { vec![] }]: Vec = vec![]; = help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead error[E0164]: expected tuple struct or tuple variant, found associated function `::alloc::boxed::Box::new_uninit` - --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:9 + --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:4:9 | LL | let vec![const { vec![] }]: Vec = vec![]; | ^^^^^^^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.rs b/tests/ui/pattern/deref-patterns/implicit-const-deref.rs index 70f89629bc228..4aa5695c7399c 100644 --- a/tests/ui/pattern/deref-patterns/implicit-const-deref.rs +++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.rs @@ -4,7 +4,6 @@ //! scrutinee and end up with a type error; this would prevent us from reporting that only constants //! supporting structural equality can be used as patterns. #![feature(deref_patterns)] -#![allow(incomplete_features)] const EMPTY: Vec<()> = Vec::new(); diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr index 6d43018462873..a75542ffd4ad6 100644 --- a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr +++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr @@ -1,5 +1,5 @@ error: constant of non-structural type `Vec<()>` in a pattern - --> $DIR/implicit-const-deref.rs:15:9 + --> $DIR/implicit-const-deref.rs:14:9 | LL | const EMPTY: Vec<()> = Vec::new(); | -------------------- constant defined here diff --git a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs index 24770261edc53..107ae12f3b74b 100644 --- a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs +++ b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs @@ -1,7 +1,6 @@ //@ run-pass //! Test that implicit deref patterns interact as expected with `Cow` constructor patterns. #![feature(deref_patterns)] -#![allow(incomplete_features)] use std::borrow::Cow; use std::rc::Rc; diff --git a/tests/ui/pattern/deref-patterns/recursion-limit.rs b/tests/ui/pattern/deref-patterns/recursion-limit.rs index c5fe520f6f1ab..75c64cb1f539e 100644 --- a/tests/ui/pattern/deref-patterns/recursion-limit.rs +++ b/tests/ui/pattern/deref-patterns/recursion-limit.rs @@ -1,6 +1,5 @@ //! Test that implicit deref patterns respect the recursion limit #![feature(deref_patterns)] -#![allow(incomplete_features)] #![recursion_limit = "8"] use std::ops::Deref; diff --git a/tests/ui/pattern/deref-patterns/recursion-limit.stderr b/tests/ui/pattern/deref-patterns/recursion-limit.stderr index 7c140e4493e7b..e7f6a272432eb 100644 --- a/tests/ui/pattern/deref-patterns/recursion-limit.stderr +++ b/tests/ui/pattern/deref-patterns/recursion-limit.stderr @@ -1,5 +1,5 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Cyclic` - --> $DIR/recursion-limit.rs:18:9 + --> $DIR/recursion-limit.rs:17:9 | LL | () => {} | ^^ deref recursion limit reached @@ -7,13 +7,13 @@ LL | () => {} = help: consider increasing the recursion limit by adding a `#![recursion_limit = "16"]` attribute to your crate (`recursion_limit`) error[E0277]: the trait bound `Cyclic: DerefPure` is not satisfied - --> $DIR/recursion-limit.rs:18:9 + --> $DIR/recursion-limit.rs:17:9 | LL | () => {} | ^^ unsatisfied trait bound | help: the nightly-only, unstable trait `DerefPure` is not implemented for `Cyclic` - --> $DIR/recursion-limit.rs:8:1 + --> $DIR/recursion-limit.rs:7:1 | LL | struct Cyclic; | ^^^^^^^^^^^^^ diff --git a/tests/ui/pattern/deref-patterns/ref-mut.rs b/tests/ui/pattern/deref-patterns/ref-mut.rs index 43738671346d3..7751a13565e84 100644 --- a/tests/ui/pattern/deref-patterns/ref-mut.rs +++ b/tests/ui/pattern/deref-patterns/ref-mut.rs @@ -1,5 +1,4 @@ #![feature(deref_patterns)] -//~^ WARN the feature `deref_patterns` is incomplete use std::rc::Rc; diff --git a/tests/ui/pattern/deref-patterns/ref-mut.stderr b/tests/ui/pattern/deref-patterns/ref-mut.stderr index 24a35b418e95c..1359410de827c 100644 --- a/tests/ui/pattern/deref-patterns/ref-mut.stderr +++ b/tests/ui/pattern/deref-patterns/ref-mut.stderr @@ -1,14 +1,5 @@ -warning: the feature `deref_patterns` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/ref-mut.rs:1:12 - | -LL | #![feature(deref_patterns)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #87121 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the trait bound `Rc<{integer}>: DerefMut` is not satisfied - --> $DIR/ref-mut.rs:17:9 + --> $DIR/ref-mut.rs:16:9 | LL | deref!(x) => {} | ^^^^^^^^^ the trait `DerefMut` is not implemented for `Rc<{integer}>` @@ -16,11 +7,11 @@ LL | deref!(x) => {} = note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Rc<({integer},)>: DerefMut` is not satisfied - --> $DIR/ref-mut.rs:22:9 + --> $DIR/ref-mut.rs:21:9 | LL | (x,) => {} | ^^^^ the trait `DerefMut` is not implemented for `Rc<({integer},)>` -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/pattern/deref-patterns/refs.rs b/tests/ui/pattern/deref-patterns/refs.rs index 51826225856bd..13566510e7a52 100644 --- a/tests/ui/pattern/deref-patterns/refs.rs +++ b/tests/ui/pattern/deref-patterns/refs.rs @@ -1,6 +1,5 @@ //@ check-pass #![feature(deref_patterns)] -#![expect(incomplete_features)] fn foo(s: &String) -> i32 { match *s { diff --git a/tests/ui/pattern/deref-patterns/strings.rs b/tests/ui/pattern/deref-patterns/strings.rs index fac15a9aee3de..5b6cfb9425d67 100644 --- a/tests/ui/pattern/deref-patterns/strings.rs +++ b/tests/ui/pattern/deref-patterns/strings.rs @@ -2,7 +2,6 @@ //! Test deref patterns using string and bytestring literals. #![feature(deref_patterns)] -#![allow(incomplete_features)] fn main() { for (test_in, test_expect) in [("zero", 0), ("one", 1), ("two", 2)] { diff --git a/tests/ui/pattern/deref-patterns/typeck.rs b/tests/ui/pattern/deref-patterns/typeck.rs index 3a7ce9d1deb3d..a1a055d5f0e79 100644 --- a/tests/ui/pattern/deref-patterns/typeck.rs +++ b/tests/ui/pattern/deref-patterns/typeck.rs @@ -1,6 +1,5 @@ //@ check-pass #![feature(deref_patterns)] -#![allow(incomplete_features)] use std::rc::Rc; diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs index 6ae87bb7bc362..14ddb670e57ff 100644 --- a/tests/ui/pattern/deref-patterns/typeck_fail.rs +++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs @@ -1,5 +1,4 @@ #![feature(deref_patterns)] -#![allow(incomplete_features)] fn main() { // Make sure we don't try implicitly dereferncing any ADT. diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr index fc29caac56301..6e81e9f6a0645 100644 --- a/tests/ui/pattern/deref-patterns/typeck_fail.stderr +++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/typeck_fail.rs:7:9 + --> $DIR/typeck_fail.rs:6:9 | LL | match Some(0) { | ------- this expression has type `Option<{integer}>` diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs index 9e95f4ec40962..db76e6fb7f943 100644 --- a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs +++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs @@ -1,5 +1,4 @@ #![feature(deref_patterns)] -#![allow(incomplete_features)] struct MyPointer; diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr index 3ee6efefe6973..3b680b4238a03 100644 --- a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr +++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `MyPointer: DerefPure` is not satisfied - --> $DIR/unsatisfied-bounds.rs:17:9 + --> $DIR/unsatisfied-bounds.rs:16:9 | LL | () => {} | ^^ unsatisfied trait bound | help: the nightly-only, unstable trait `DerefPure` is not implemented for `MyPointer` - --> $DIR/unsatisfied-bounds.rs:4:1 + --> $DIR/unsatisfied-bounds.rs:3:1 | LL | struct MyPointer; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs b/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs index 03419030e72fd..17de653801697 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs +++ b/tests/ui/pattern/deref-patterns/usefulness/empty-types.rs @@ -4,7 +4,6 @@ // FIXME(deref_patterns): On stabilization, cases for deref patterns could be worked into that file // to keep the tests for empty types in one place and test more thoroughly. #![feature(deref_patterns)] -#![expect(incomplete_features)] #![deny(unreachable_patterns)] enum Void {} diff --git a/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr b/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr index e32477085661c..4eb49b54b83bc 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr +++ b/tests/ui/pattern/deref-patterns/usefulness/empty-types.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `deref!(Some(_))` not covered - --> $DIR/empty-types.rs:21:11 + --> $DIR/empty-types.rs:20:11 | LL | match box_opt_void { | ^^^^^^^^^^^^ pattern `deref!(Some(_))` not covered @@ -15,7 +15,7 @@ LL + deref!(Some(_)) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:35:11 + --> $DIR/empty-types.rs:34:11 | LL | match *box_opt_void { | ^^^^^^^^^^^^^ pattern `Some(_)` not covered diff --git a/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.rs b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.rs index f567dc07bb592..8858f628217c1 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.rs +++ b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.rs @@ -2,7 +2,6 @@ //! doesn't support this, so make sure we catch it beforehand. As a consequence, it takes priority //! over non-exhaustive match and unreachable pattern errors. #![feature(deref_patterns)] -#![expect(incomplete_features)] #![deny(unreachable_patterns)] use std::borrow::Cow; diff --git a/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.stderr b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.stderr index 5ad24164b9850..3d036afc9e90a 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.stderr +++ b/tests/ui/pattern/deref-patterns/usefulness/mixed-constructors.stderr @@ -1,5 +1,5 @@ error: mix of deref patterns and normal constructors - --> $DIR/mixed-constructors.rs:16:9 + --> $DIR/mixed-constructors.rs:15:9 | LL | false => {} | ^^^^^ matches on the result of dereferencing `Cow<'_, bool>` @@ -7,7 +7,7 @@ LL | Cow::Borrowed(_) => {} | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` error: mix of deref patterns and normal constructors - --> $DIR/mixed-constructors.rs:22:9 + --> $DIR/mixed-constructors.rs:21:9 | LL | Cow::Borrowed(_) => {} | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` @@ -15,7 +15,7 @@ LL | true => {} | ^^^^ matches on the result of dereferencing `Cow<'_, bool>` error: mix of deref patterns and normal constructors - --> $DIR/mixed-constructors.rs:29:9 + --> $DIR/mixed-constructors.rs:28:9 | LL | Cow::Owned(_) => {} | ^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` @@ -23,7 +23,7 @@ LL | false => {} | ^^^^^ matches on the result of dereferencing `Cow<'_, bool>` error: mix of deref patterns and normal constructors - --> $DIR/mixed-constructors.rs:36:10 + --> $DIR/mixed-constructors.rs:35:10 | LL | (Cow::Borrowed(_), 0) => {} | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` @@ -31,7 +31,7 @@ LL | (true, 0) => {} | ^^^^ matches on the result of dereferencing `Cow<'_, bool>` error: mix of deref patterns and normal constructors - --> $DIR/mixed-constructors.rs:43:13 + --> $DIR/mixed-constructors.rs:42:13 | LL | (0, Cow::Borrowed(_)) => {} | ^^^^^^^^^^^^^^^^ matches directly on `Cow<'_, bool>` diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs index bab6308223e50..64f5f14f199a9 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs +++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs @@ -1,6 +1,5 @@ //! Test non-exhaustive matches involving deref patterns. #![feature(deref_patterns)] -#![expect(incomplete_features)] #![deny(unreachable_patterns)] fn main() { diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr index a1abd5f0e3f4b..75c8b1864c785 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr +++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `deref!(true)` not covered - --> $DIR/non-exhaustive.rs:7:11 + --> $DIR/non-exhaustive.rs:6:11 | LL | match Box::new(false) { | ^^^^^^^^^^^^^^^ pattern `deref!(true)` not covered @@ -14,7 +14,7 @@ LL + deref!(true) => todo!() | error[E0004]: non-exhaustive patterns: `deref!(deref!(false))` not covered - --> $DIR/non-exhaustive.rs:12:11 + --> $DIR/non-exhaustive.rs:11:11 | LL | match Box::new(Box::new(false)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `deref!(deref!(false))` not covered @@ -29,7 +29,7 @@ LL + deref!(deref!(false)) => todo!() | error[E0004]: non-exhaustive patterns: `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered - --> $DIR/non-exhaustive.rs:17:11 + --> $DIR/non-exhaustive.rs:16:11 | LL | match Box::new((true, Box::new(false))) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered @@ -44,7 +44,7 @@ LL + deref!((true, deref!(true))) | deref!((false, deref!(false))) => to | error[E0004]: non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered - --> $DIR/non-exhaustive.rs:24:11 + --> $DIR/non-exhaustive.rs:23:11 | LL | match Box::new((Box::new(T::A), Box::new(T::A))) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `deref!((deref!(T::C), _))` not covered diff --git a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs index 2677fc54dedc2..5559ee8f55661 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs +++ b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.rs @@ -1,6 +1,5 @@ //! Test unreachable patterns involving deref patterns. #![feature(deref_patterns)] -#![expect(incomplete_features)] #![deny(unreachable_patterns)] fn main() { diff --git a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr index 045e11be31966..88ac7b2351a78 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr +++ b/tests/ui/pattern/deref-patterns/usefulness/unreachable-patterns.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/unreachable-patterns.rs:10:9 + --> $DIR/unreachable-patterns.rs:9:9 | LL | false => {} | ----- matches all the relevant values @@ -7,13 +7,13 @@ LL | false => {} | ^^^^^ no value can reach this | note: the lint level is defined here - --> $DIR/unreachable-patterns.rs:4:9 + --> $DIR/unreachable-patterns.rs:3:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/unreachable-patterns.rs:16:9 + --> $DIR/unreachable-patterns.rs:15:9 | LL | true => {} | ---- matches all the relevant values @@ -22,13 +22,13 @@ LL | true => {} | ^^^^ no value can reach this error: unreachable pattern - --> $DIR/unreachable-patterns.rs:23:9 + --> $DIR/unreachable-patterns.rs:22:9 | LL | _ => {} | ^ no value can reach this | note: multiple earlier patterns match some of the same values - --> $DIR/unreachable-patterns.rs:23:9 + --> $DIR/unreachable-patterns.rs:22:9 | LL | (true, _) => {} | --------- matches some of the same values @@ -40,7 +40,7 @@ LL | _ => {} | ^ collectively making this unreachable error: unreachable pattern - --> $DIR/unreachable-patterns.rs:29:9 + --> $DIR/unreachable-patterns.rs:28:9 | LL | (T::A | T::B, T::A | T::C) => {} | -------------------------- matches all the relevant values @@ -48,7 +48,7 @@ LL | (T::A, T::C) => {} | ^^^^^^^^^^^^ no value can reach this error: unreachable pattern - --> $DIR/unreachable-patterns.rs:30:9 + --> $DIR/unreachable-patterns.rs:29:9 | LL | (T::A | T::B, T::A | T::C) => {} | -------------------------- matches all the relevant values diff --git a/tests/ui/tuple/array-diagnostics.rs b/tests/ui/tuple/array-diagnostics.rs index 1929dab073169..0a88e9cc3a51d 100644 --- a/tests/ui/tuple/array-diagnostics.rs +++ b/tests/ui/tuple/array-diagnostics.rs @@ -1,7 +1,7 @@ fn main() { let _tmp = [ ("C200B40A82", 3), - ("C200B40A83", 4) //~ ERROR: expected function, found `(&'static str, {integer})` [E0618] + ("C200B40A83", 4) //~ ERROR: expected function, found `(&str, {integer})` [E0618] ("C200B40A8537", 5), ]; } diff --git a/tests/ui/tuple/array-diagnostics.stderr b/tests/ui/tuple/array-diagnostics.stderr index 629ca2b37fa5a..b8f7840ea4b6c 100644 --- a/tests/ui/tuple/array-diagnostics.stderr +++ b/tests/ui/tuple/array-diagnostics.stderr @@ -1,4 +1,4 @@ -error[E0618]: expected function, found `(&'static str, {integer})` +error[E0618]: expected function, found `(&str, {integer})` --> $DIR/array-diagnostics.rs:4:9 | LL | ("C200B40A83", 4) diff --git a/tests/ui/tuple/coercion-never.rs b/tests/ui/tuple/coercion-never.rs new file mode 100644 index 0000000000000..3e4c4480c6f1f --- /dev/null +++ b/tests/ui/tuple/coercion-never.rs @@ -0,0 +1,16 @@ +// This test checks if tuple elements are a coercion site or not. +// Note that the code here is a degenerate case, but you can get similar effects in real code, when +// unifying match arms, for example. +// +// See also coercion-slice.rs +// +//@ check-pass + +fn main() { + let _: ((),) = (loop {},); + + ((),) = (loop {},); + + let x = (loop {},); + let _: ((),) = x; +} diff --git a/tests/ui/tuple/coercion-slice.rs b/tests/ui/tuple/coercion-slice.rs new file mode 100644 index 0000000000000..250265f28ff08 --- /dev/null +++ b/tests/ui/tuple/coercion-slice.rs @@ -0,0 +1,12 @@ +// This test checks if tuple elements are a coercion site or not. +// Note that the code here is a degenerate case, but you can get similar effects in real code, when +// unifying match arms, for example. +// +// See also: coercion-never.rs + +fn main() { + let _: (&[u8],) = (&[],); + + let y = (&[],); + let _: (&[u8],) = y; //~ error: mismatched types +} diff --git a/tests/ui/tuple/coercion-slice.stderr b/tests/ui/tuple/coercion-slice.stderr new file mode 100644 index 0000000000000..a8ae7db4490cb --- /dev/null +++ b/tests/ui/tuple/coercion-slice.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/coercion-slice.rs:11:23 + | +LL | let _: (&[u8],) = y; + | -------- ^ expected `(&[u8],)`, found `(&[_; 0],)` + | | + | expected due to this + | + = note: expected tuple `(&[u8],)` + found tuple `(&[_; 0],)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`.