mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Auto merge of #153617 - JonathanBrouwer:rollup-udG4Tzr, r=JonathanBrouwer
Rollup of 4 pull requests Successful merges: - rust-lang/rust#147834 (Always make tuple elements a coercion site) - rust-lang/rust#150446 (miri/const eval: support `MaybeDangling`) - rust-lang/rust#153053 (stop marking `deref_patterns` as an incomplete feature) - rust-lang/rust#153398 (fix ICE in `const_c_variadic` when passing ZSTs)
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
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 @@ fn pass_argument<'x, 'y>(
|
||||
'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 @@ pub fn init_stack_frame(
|
||||
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 @@ pub fn init_stack_frame(
|
||||
|
||||
// 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());
|
||||
|
||||
@@ -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<I, J>(
|
||||
&mut self,
|
||||
caller_args: &mut I,
|
||||
callee_abis: &mut J,
|
||||
caller_args: I,
|
||||
mut callee_abis: J,
|
||||
) -> InterpResult<'tcx, Vec<MPlaceTy<'tcx, M::Provenance>>>
|
||||
where
|
||||
I: Iterator<Item = (&'a FnArg<'tcx, M::Provenance>, &'a ArgAbi<'tcx, Ty<'tcx>>)>,
|
||||
|
||||
@@ -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<RangeSet>,
|
||||
/// 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 @@ fn check_safe_pointer(
|
||||
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 @@ fn check_safe_pointer(
|
||||
// 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::<Option<AllocId>>::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::<Option<AllocId>>::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 @@ fn check_safe_pointer(
|
||||
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 @@ fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'t
|
||||
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 @@ fn validate_operand_internal(
|
||||
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)?;
|
||||
|
||||
@@ -465,7 +465,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
/// 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
|
||||
|
||||
@@ -1792,27 +1792,24 @@ fn check_expr_repeat(
|
||||
|
||||
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 {
|
||||
|
||||
@@ -1592,7 +1592,8 @@ pub fn ty_adt_def(self) -> Option<AdtDef<'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<Ty<'tcx>> {
|
||||
@@ -1602,6 +1603,15 @@ pub fn tuple_fields(self) -> &'tcx List<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<Ty<'tcx>>> {
|
||||
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.
|
||||
|
||||
@@ -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::<NoCopy>(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!(),
|
||||
|
||||
@@ -917,6 +917,7 @@ fn retag_ptr_inplace(
|
||||
RetagInfo { cause: self.retag_cause, in_field: self.in_field },
|
||||
)?;
|
||||
self.ecx.write_immediate(*val, place)?;
|
||||
|
||||
interp_ok(())
|
||||
}
|
||||
}
|
||||
@@ -964,6 +965,9 @@ fn visit_value(&mut self, place: &PlaceTy<'tcx>) -> InterpResult<'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
|
||||
|
||||
@@ -523,6 +523,9 @@ fn visit_value(&mut self, place: &PlaceTy<'tcx>) -> InterpResult<'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)?;
|
||||
|
||||
@@ -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<*const u16>, MaybeDangling<&u16>>(unaligned)
|
||||
//~^ ERROR: Undefined Behavior: constructing invalid value: encountered an unaligned reference
|
||||
};
|
||||
}
|
||||
@@ -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<*const u16>, 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
|
||||
|
||||
@@ -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<*const u8>, MaybeDangling<&u8>>(null) };
|
||||
//~^ ERROR: Undefined Behavior: constructing invalid value: encountered a null reference
|
||||
}
|
||||
@@ -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<*const u8>, 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
|
||||
|
||||
@@ -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<Box<u32>> = 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<&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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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::<i32>();
|
||||
ap.arg::<i32>();
|
||||
}
|
||||
|
||||
unsafe { variadic(0i32, (), 1i32) }
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
0..1: [ SharedReadWrite<TAG> ]
|
||||
0..1: [ SharedReadWrite<TAG> ]
|
||||
0..1: [ SharedReadWrite<TAG> ]
|
||||
0..1: [ SharedReadWrite<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> ]
|
||||
0..1: [ SharedReadWrite<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> SharedReadOnly<TAG> ]
|
||||
0..1: [ SharedReadWrite<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> Unique<TAG> ]
|
||||
0..1: [ SharedReadWrite<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> Disabled<TAG> SharedReadOnly<TAG> ]
|
||||
0..1: [ unknown-bottom(..<TAG>) ]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<const N: usize>(_: ...) {}
|
||||
|
||||
unsafe fn read_too_many() {
|
||||
const { read_n::<0>((), 1i32) }
|
||||
}
|
||||
|
||||
fn read_as<T>() -> () {}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//@ run-pass
|
||||
//@ check-run-results
|
||||
#![feature(deref_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
fn main() {
|
||||
test(Some(String::from("42")));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//@ revisions: explicit implicit
|
||||
//@ run-pass
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
@@ -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>) -> u32 {
|
||||
|
||||
@@ -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]`,
|
||||
|
||||
@@ -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]`
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
| ^^
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//@ run-pass
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
@@ -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>() -> T { unimplemented!() }
|
||||
|
||||
|
||||
@@ -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 _`
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//@ check-pass
|
||||
#![feature(deref_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
fn main() {
|
||||
match <_ as Default>::default() {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
//! and `DerefMut::deref_mut`. Test that they work as expected.
|
||||
|
||||
#![feature(deref_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
fn unbox_1<T>(b: Box<T>) -> T {
|
||||
let deref!(x) = b;
|
||||
|
||||
@@ -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>) -> u32 {
|
||||
(|| match Vec::<u32>::new() {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#[rustfmt::skip]
|
||||
fn main() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![feature(deref_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
fn main() {
|
||||
let vec![const { vec![] }]: Vec<usize> = vec![];
|
||||
|
||||
@@ -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<usize> = vec![];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
||||
@@ -7,7 +7,7 @@ LL | let vec![const { vec![] }]: Vec<usize> = vec![];
|
||||
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
|
||||
|
||||
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<usize> = vec![];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
||||
@@ -15,7 +15,7 @@ LL | let vec![const { vec![] }]: Vec<usize> = vec![];
|
||||
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
|
||||
|
||||
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<usize> = vec![];
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@@ -23,7 +23,7 @@ LL | let vec![const { vec![] }]: Vec<usize> = 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<usize> = vec![];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![feature(deref_patterns)]
|
||||
//~^ WARN the feature `deref_patterns` is incomplete
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
@@ -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 <https://github.com/rust-lang/rust/issues/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`.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//@ check-pass
|
||||
#![feature(deref_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
fn foo(s: &String) -> i32 {
|
||||
match *s {
|
||||
|
||||
@@ -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)] {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//@ check-pass
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn main() {
|
||||
// Make sure we don't try implicitly dereferncing any ADT.
|
||||
|
||||
@@ -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}>`
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#![feature(deref_patterns)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct MyPointer;
|
||||
|
||||
|
||||
@@ -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;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>`
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//! Test non-exhaustive matches involving deref patterns.
|
||||
#![feature(deref_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//! Test unreachable patterns involving deref patterns.
|
||||
#![feature(deref_patterns)]
|
||||
#![expect(incomplete_features)]
|
||||
#![deny(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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`.
|
||||
Reference in New Issue
Block a user