Delete tuple unsizing
This commit is contained in:
parent
2af87eab3b
commit
44cccae02a
47 changed files with 55 additions and 879 deletions
|
@ -655,8 +655,6 @@ declare_features! (
|
|||
(internal, unsized_fn_params, "1.49.0", Some(48055)),
|
||||
/// Allows unsized rvalues at arguments and parameters.
|
||||
(incomplete, unsized_locals, "1.30.0", Some(48055)),
|
||||
/// Allows unsized tuple coercion.
|
||||
(unstable, unsized_tuple_coercion, "1.20.0", Some(42877)),
|
||||
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
|
||||
(unstable, used_with_arg, "1.60.0", Some(93798)),
|
||||
/// Allows use of x86 `AMX` target-feature attributes and intrinsics
|
||||
|
|
|
@ -51,15 +51,13 @@ use rustc_infer::traits::{
|
|||
PredicateObligations,
|
||||
};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::traits::BuiltinImplSource;
|
||||
use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
|
||||
};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span, sym};
|
||||
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
|
@ -610,8 +608,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
|
||||
)];
|
||||
|
||||
let mut has_unsized_tuple_coercion = false;
|
||||
|
||||
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
||||
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
|
||||
// inference might unify those two inner type variables later.
|
||||
|
@ -690,31 +686,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
// be silent, as it causes a type mismatch later.
|
||||
}
|
||||
|
||||
Ok(Some(impl_source)) => {
|
||||
// Some builtin coercions are still unstable so we detect
|
||||
// these here and emit a feature error if coercion doesn't fail
|
||||
// due to another reason.
|
||||
match impl_source {
|
||||
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
|
||||
has_unsized_tuple_coercion = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
queue.extend(impl_source.nested_obligations())
|
||||
}
|
||||
Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()),
|
||||
}
|
||||
}
|
||||
|
||||
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion() {
|
||||
feature_err(
|
||||
&self.tcx.sess,
|
||||
sym::unsized_tuple_coercion,
|
||||
self.cause.span,
|
||||
"unsized tuple coercion is not stable enough for use and is subject to change",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
Ok(coercion)
|
||||
}
|
||||
|
||||
|
|
|
@ -787,13 +787,6 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
// `(A, B, T)` -> `(A, B, U)` where `T: Unsize<U>`
|
||||
(ty::Tuple(a_tys), ty::Tuple(b_tys))
|
||||
if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
|
||||
{
|
||||
result_to_single(ecx.consider_builtin_tuple_unsize(goal, a_tys, b_tys))
|
||||
}
|
||||
|
||||
_ => vec![],
|
||||
}
|
||||
})
|
||||
|
@ -1085,48 +1078,6 @@ where
|
|||
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
|
||||
}
|
||||
|
||||
/// We generate the following builtin impl for tuples of all sizes.
|
||||
///
|
||||
/// This impl is still unstable and we emit a feature error when it
|
||||
/// when it is used by a coercion.
|
||||
/// ```ignore (builtin impl example)
|
||||
/// impl<T: ?Sized, U: ?Sized, V: ?Sized> Unsize<(T, V)> for (T, U)
|
||||
/// where
|
||||
/// U: Unsize<V>,
|
||||
/// {}
|
||||
/// ```
|
||||
fn consider_builtin_tuple_unsize(
|
||||
&mut self,
|
||||
goal: Goal<I, (I::Ty, I::Ty)>,
|
||||
a_tys: I::Tys,
|
||||
b_tys: I::Tys,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
let cx = self.cx();
|
||||
let Goal { predicate: (_a_ty, b_ty), .. } = goal;
|
||||
|
||||
let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
|
||||
let b_last_ty = b_tys.last().unwrap();
|
||||
|
||||
// Instantiate just the tail field of B., and require that they're equal.
|
||||
let unsized_a_ty = Ty::new_tup_from_iter(cx, a_rest_tys.iter().copied().chain([b_last_ty]));
|
||||
self.eq(goal.param_env, unsized_a_ty, b_ty)?;
|
||||
|
||||
// Similar to ADTs, require that we can unsize the tail.
|
||||
self.add_goal(
|
||||
GoalSource::ImplWhereBound,
|
||||
goal.with(
|
||||
cx,
|
||||
ty::TraitRef::new(
|
||||
cx,
|
||||
cx.require_lang_item(TraitSolverLangItem::Unsize),
|
||||
[a_last_ty, b_last_ty],
|
||||
),
|
||||
),
|
||||
);
|
||||
self.probe_builtin_trait_candidate(BuiltinImplSource::TupleUnsizing)
|
||||
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
|
||||
}
|
||||
|
||||
// Return `Some` if there is an impl (built-in or user provided) that may
|
||||
// hold for the self type of the goal, which for coherence and soundness
|
||||
// purposes must disqualify the built-in auto impl assembled by considering
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//! An "interner" is a data structure that associates values with usize tags and
|
||||
//! allows bidirectional lookup; i.e., given a value, one can easily find the
|
||||
//! An "interner" is a data structure that associates values with usize tags and allows bidirectional lookup; i.e., given a value, one can easily find the
|
||||
//! type, and vice versa.
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -2165,7 +2164,6 @@ symbols! {
|
|||
unsized_const_params,
|
||||
unsized_fn_params,
|
||||
unsized_locals,
|
||||
unsized_tuple_coercion,
|
||||
unstable,
|
||||
unstable_location_reason_default: "this crate is being loaded from the sysroot, an \
|
||||
unstable location; did you mean to load this crate \
|
||||
|
|
|
@ -1232,8 +1232,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|||
// why we special case object types.
|
||||
false
|
||||
}
|
||||
ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
|
||||
| ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
|
||||
ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => {
|
||||
// These traits have no associated types.
|
||||
selcx.tcx().dcx().span_delayed_bug(
|
||||
obligation.cause.span,
|
||||
|
@ -1325,8 +1324,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
|
|||
}
|
||||
ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)
|
||||
| ImplSource::Param(..)
|
||||
| ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
|
||||
| ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
|
||||
| ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => {
|
||||
// we don't create Select candidates with this kind of resolution
|
||||
span_bug!(
|
||||
obligation.cause.span,
|
||||
|
|
|
@ -1017,13 +1017,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// `(.., T)` -> `(.., U)`
|
||||
(&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
|
||||
if tys_a.len() == tys_b.len() {
|
||||
candidates.vec.push(BuiltinUnsizeCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
//! [rustc dev guide]:
|
||||
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
|
||||
|
||||
use std::iter;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
|
@ -1320,34 +1319,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ImplSource::Builtin(BuiltinImplSource::Misc, nested)
|
||||
}
|
||||
|
||||
// `(.., T)` -> `(.., U)`
|
||||
(&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
|
||||
assert_eq!(tys_a.len(), tys_b.len());
|
||||
|
||||
// The last field of the tuple has to exist.
|
||||
let (&a_last, a_mid) = tys_a.split_last().ok_or(Unimplemented)?;
|
||||
let &b_last = tys_b.last().unwrap();
|
||||
|
||||
// Check that the source tuple with the target's
|
||||
// last element is equal to the target.
|
||||
let new_tuple =
|
||||
Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
|
||||
let InferOk { mut obligations, .. } = self
|
||||
.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, target, new_tuple)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
|
||||
// Add a nested `T: Unsize<U>` predicate.
|
||||
let last_unsize_obligation = obligation.with(
|
||||
tcx,
|
||||
ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]),
|
||||
);
|
||||
obligations.push(last_unsize_obligation);
|
||||
|
||||
ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations)
|
||||
}
|
||||
|
||||
_ => bug!("source: {source}, target: {target}"),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -381,8 +381,7 @@ fn resolve_associated_item<'tcx>(
|
|||
}
|
||||
}
|
||||
traits::ImplSource::Param(..)
|
||||
| traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
|
||||
| traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => None,
|
||||
| traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => None,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -181,11 +181,6 @@ pub enum BuiltinImplSource {
|
|||
///
|
||||
/// The index is only used for winnowing.
|
||||
TraitUpcasting(usize),
|
||||
/// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`.
|
||||
///
|
||||
/// This can be removed when `feature(tuple_unsizing)` is stabilized, since we only
|
||||
/// use it to detect when unsizing tuples in hir typeck.
|
||||
TupleUnsizing,
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
|
||||
|
|
|
@ -88,7 +88,6 @@
|
|||
#![feature(try_find)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(unsize)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
#![feature(unwrap_infallible)]
|
||||
// tidy-alphabetical-end
|
||||
#![allow(internal_features)]
|
||||
|
|
|
@ -525,31 +525,24 @@ fn ptr_metadata() {
|
|||
assert_eq!(metadata("foo"), 3_usize);
|
||||
assert_eq!(metadata(&[4, 7][..]), 2_usize);
|
||||
|
||||
let dst_tuple: &(bool, [u8]) = &(true, [0x66, 0x6F, 0x6F]);
|
||||
let dst_struct: &Pair<bool, [u8]> = &Pair(true, [0x66, 0x6F, 0x6F]);
|
||||
assert_eq!(metadata(dst_tuple), 3_usize);
|
||||
assert_eq!(metadata(dst_struct), 3_usize);
|
||||
unsafe {
|
||||
let dst_tuple: &(bool, str) = std::mem::transmute(dst_tuple);
|
||||
let dst_struct: &Pair<bool, str> = std::mem::transmute(dst_struct);
|
||||
assert_eq!(&dst_tuple.1, "foo");
|
||||
assert_eq!(&dst_struct.1, "foo");
|
||||
assert_eq!(metadata(dst_tuple), 3_usize);
|
||||
assert_eq!(metadata(dst_struct), 3_usize);
|
||||
}
|
||||
|
||||
let vtable_1: DynMetadata<dyn Debug> = metadata(&4_u16 as &dyn Debug);
|
||||
let vtable_2: DynMetadata<dyn Display> = metadata(&4_u16 as &dyn Display);
|
||||
let vtable_3: DynMetadata<dyn Display> = metadata(&4_u32 as &dyn Display);
|
||||
let vtable_4: DynMetadata<dyn Display> = metadata(&(true, 7_u32) as &(bool, dyn Display));
|
||||
let vtable_5: DynMetadata<dyn Display> =
|
||||
let vtable_4: DynMetadata<dyn Display> =
|
||||
metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>);
|
||||
unsafe {
|
||||
let address_1: *const () = std::mem::transmute(vtable_1);
|
||||
let address_2: *const () = std::mem::transmute(vtable_2);
|
||||
let address_3: *const () = std::mem::transmute(vtable_3);
|
||||
let address_4: *const () = std::mem::transmute(vtable_4);
|
||||
let address_5: *const () = std::mem::transmute(vtable_5);
|
||||
// Different trait => different vtable pointer
|
||||
assert_ne!(address_1, address_2);
|
||||
// Different erased type => different vtable pointer
|
||||
|
@ -558,7 +551,6 @@ fn ptr_metadata() {
|
|||
// This is *not guaranteed*, so we skip it in Miri.
|
||||
if !cfg!(miri) {
|
||||
assert_eq!(address_3, address_4);
|
||||
assert_eq!(address_3, address_5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
# `unsized_tuple_coercion`
|
||||
|
||||
The tracking issue for this feature is: [#42877]
|
||||
|
||||
[#42877]: https://github.com/rust-lang/rust/issues/42877
|
||||
|
||||
------------------------
|
||||
|
||||
This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
|
||||
|
||||
```rust,ignore (partial-example)
|
||||
impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
|
||||
```
|
||||
|
||||
This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
|
||||
|
||||
```rust
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
fn main() {
|
||||
let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
|
||||
let y : &([i32; 3], [i32]) = &x;
|
||||
assert_eq!(y.1[0], 4);
|
||||
}
|
||||
```
|
||||
|
||||
[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
|
@ -1,22 +1,10 @@
|
|||
//@revisions: stack tree
|
||||
//@[tree]compile-flags: -Zmiri-tree-borrows
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
#![feature(unsized_fn_params)]
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
use std::mem;
|
||||
|
||||
fn unsized_tuple() {
|
||||
let x: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
|
||||
let y: &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]);
|
||||
let mut a = [y, x];
|
||||
a.sort();
|
||||
assert_eq!(a, [x, y]);
|
||||
|
||||
assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
|
||||
assert_eq!(mem::size_of_val(x), 16);
|
||||
}
|
||||
|
||||
fn unsized_params() {
|
||||
pub fn f0(_f: dyn FnOnce()) {}
|
||||
pub fn f1(_s: str) {}
|
||||
|
@ -56,7 +44,6 @@ fn unsized_field_projection() {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
unsized_tuple();
|
||||
unsized_params();
|
||||
unsized_field_projection();
|
||||
}
|
||||
|
|
|
@ -12311,40 +12311,6 @@ fn main() {
|
|||
```
|
||||
|
||||
will unnecessarily extend the stack frame.
|
||||
"##,
|
||||
default_severity: Severity::Allow,
|
||||
warn_since: None,
|
||||
deny_since: None,
|
||||
},
|
||||
Lint {
|
||||
label: "unsized_tuple_coercion",
|
||||
description: r##"# `unsized_tuple_coercion`
|
||||
|
||||
The tracking issue for this feature is: [#42877]
|
||||
|
||||
[#42877]: https://github.com/rust-lang/rust/issues/42877
|
||||
|
||||
------------------------
|
||||
|
||||
This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
|
||||
|
||||
```rust,ignore (partial-example)
|
||||
impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
|
||||
```
|
||||
|
||||
This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
|
||||
|
||||
```rust
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
fn main() {
|
||||
let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
|
||||
let y : &([i32; 3], [i32]) = &x;
|
||||
assert_eq!(y.1[0], 4);
|
||||
}
|
||||
```
|
||||
|
||||
[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||
"##,
|
||||
default_severity: Severity::Allow,
|
||||
warn_since: None,
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
// gdb-command:print _box
|
||||
// gdb-check:$4 = alloc::boxed::Box<unsized::Foo<dyn core::fmt::Debug>, alloc::alloc::Global> {pointer: [...], vtable: [...]}
|
||||
|
||||
// gdb-command:print tuple_slice
|
||||
// gdb-check:$5 = &(i32, i32, [i32]) {data_ptr: [...], length: 2}
|
||||
|
||||
// gdb-command:print tuple_dyn
|
||||
// gdb-check:$6 = &(i32, i32, dyn core::fmt::Debug) {pointer: [...], vtable: [...]}
|
||||
|
||||
// === CDB TESTS ===================================================================================
|
||||
|
||||
// cdb-command: g
|
||||
|
@ -48,17 +42,6 @@
|
|||
// cdb-check:[+0x000] pointer : 0x[...] [Type: unsized::Foo<dyn$<core::fmt::Debug> > *]
|
||||
// cdb-check:[...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[4]]
|
||||
|
||||
// cdb-command:dx tuple_slice
|
||||
// cdb-check:tuple_slice [Type: ref$<tuple$<i32,i32,slice2$<i32> > >]
|
||||
// cdb-check: [+0x000] data_ptr : 0x[...] [Type: tuple$<i32,i32,slice2$<i32> > *]
|
||||
// cdb-check: [...] length : 0x2 [Type: unsigned [...]int[...]
|
||||
|
||||
// cdb-command:dx tuple_dyn
|
||||
// cdb-check:tuple_dyn [Type: ref$<tuple$<i32,i32,dyn$<core::fmt::Debug> > >]
|
||||
// cdb-check: [+0x000] pointer : 0x[...] [Type: tuple$<i32,i32,dyn$<core::fmt::Debug> > *]
|
||||
// cdb-check: [...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[4]]
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
#![feature(omit_gdb_pretty_printer_section)]
|
||||
#![omit_gdb_pretty_printer_section]
|
||||
|
||||
|
@ -77,10 +60,6 @@ fn main() {
|
|||
let c: &Foo<dyn std::fmt::Debug> = &Foo { value: 7i32 };
|
||||
let _box: Box<Foo<dyn std::fmt::Debug>> = Box::new(Foo { value: 8i32 });
|
||||
|
||||
// Also check unsized tuples
|
||||
let tuple_slice: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
|
||||
let tuple_dyn: &(i32, i32, dyn std::fmt::Debug) = &(0, 1, &3u64);
|
||||
|
||||
zzz(); // #break
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
//@ check-pass
|
||||
#![allow(improper_ctypes_definitions)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
#![feature(unsized_fn_params)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
struct Fat<T: ?Sized>(T);
|
||||
|
||||
// Check that computing the fn abi for `bad`, with a external ABI fn ptr that is not FFI-safe, does
|
||||
// not ICE.
|
||||
|
||||
|
@ -19,12 +20,12 @@ pub extern "C" fn declare_bad(_x: str) {}
|
|||
pub extern "system" fn declare_more_bad(f: dyn FnOnce()) {
|
||||
}
|
||||
|
||||
fn make_bad() -> extern "C" fn(([u8],)) {
|
||||
fn make_bad() -> extern "C" fn(Fat<[u8]>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn call_bad() {
|
||||
let f = make_bad();
|
||||
let slice: Box<([u8],)> = Box::new(([1; 8],));
|
||||
let slice: Box<Fat<[u8]>> = Box::new(Fat([1; 8]));
|
||||
f(*slice);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// Check that you can cast between different pointers to trait objects
|
||||
// whose vtable have the same kind (both lengths, or both trait pointers).
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
trait Bar { //~ WARN trait `Bar` is never used
|
||||
fn bar(&self) { println!("Bar!"); }
|
||||
}
|
||||
|
@ -19,10 +17,6 @@ fn foo_to_bar<T:?Sized>(u: *const FooS<T>) -> *const BarS<T> {
|
|||
u as *const BarS<T>
|
||||
}
|
||||
|
||||
fn tuple_i32_to_u32<T:?Sized>(u: *const (i32, T)) -> *const (u32, T) {
|
||||
u as *const (u32, T)
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let s = FooS([0,1,2]);
|
||||
|
@ -31,14 +25,4 @@ fn main() {
|
|||
let bar_ref : *const BarS<[u32]> = foo_to_bar(u);
|
||||
let z : &BarS<[u32]> = unsafe{&*bar_ref};
|
||||
assert_eq!(&z.0, &[0,1,2]);
|
||||
|
||||
// this assumes that tuple reprs for (i32, _) and (u32, _) are
|
||||
// the same.
|
||||
let s = (0i32, [0, 1, 2]);
|
||||
let u: &(i32, [u8]) = &s;
|
||||
let u: *const (i32, [u8]) = u;
|
||||
let u_u32 : *const (u32, [u8]) = tuple_i32_to_u32(u);
|
||||
unsafe {
|
||||
assert_eq!(&(*u_u32).1, &[0, 1, 2]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
warning: trait `Bar` is never used
|
||||
--> $DIR/cast-rfc0401-vtable-kinds.rs:7:7
|
||||
--> $DIR/cast-rfc0401-vtable-kinds.rs:5:7
|
||||
|
|
||||
LL | trait Bar {
|
||||
| ^^^
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Forbid assignment into a dynamically sized type.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
type Fat<T> = (isize, &'static str, T);
|
||||
struct Fat<T: ?Sized>(isize, &'static str, T);
|
||||
|
||||
#[derive(PartialEq,Eq)]
|
||||
struct Bar;
|
||||
|
@ -28,7 +26,7 @@ impl ToBar for Bar1 {
|
|||
|
||||
pub fn main() {
|
||||
// Assignment.
|
||||
let f5: &mut Fat<dyn ToBar> = &mut (5, "some str", Bar1 {f :42});
|
||||
let f5: &mut Fat<dyn ToBar> = &mut Fat(5, "some str", Bar1 {f :42});
|
||||
let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
|
||||
f5.2 = Bar1 {f: 36};
|
||||
//~^ ERROR mismatched types
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/dst-bad-assign-3.rs:33:12
|
||||
--> $DIR/dst-bad-assign-3.rs:31:12
|
||||
|
|
||||
LL | f5.2 = Bar1 {f: 36};
|
||||
| ---- ^^^^^^^^^^^^ expected `dyn ToBar`, found `Bar1`
|
||||
|
@ -11,7 +11,7 @@ LL | f5.2 = Bar1 {f: 36};
|
|||
= help: `Bar1` implements `ToBar` so you could box the found value and coerce it to the trait object `Box<dyn ToBar>`, you will have to change the expected type as well
|
||||
|
||||
error[E0277]: the size for values of type `dyn ToBar` cannot be known at compilation time
|
||||
--> $DIR/dst-bad-assign-3.rs:33:5
|
||||
--> $DIR/dst-bad-assign-3.rs:31:5
|
||||
|
|
||||
LL | f5.2 = Bar1 {f: 36};
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Attempt to change the type as well as unsizing.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
struct Fat<T: ?Sized> {
|
||||
ptr: T
|
||||
}
|
||||
|
@ -21,16 +19,4 @@ pub fn main() {
|
|||
let f2: &Fat<Foo> = &f1;
|
||||
let f3: &Fat<dyn Bar> = f2;
|
||||
//~^ ERROR `Foo: Bar` is not satisfied
|
||||
|
||||
// Tuple with a vec of isize.
|
||||
let f1 = ([1, 2, 3],);
|
||||
let f2: &([isize; 3],) = &f1;
|
||||
let f3: &([usize],) = f2;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
// Tuple with a trait.
|
||||
let f1 = (Foo,);
|
||||
let f2: &(Foo,) = &f1;
|
||||
let f3: &(dyn Bar,) = f2;
|
||||
//~^ ERROR `Foo: Bar` is not satisfied
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/dst-bad-coerce1.rs:16:29
|
||||
--> $DIR/dst-bad-coerce1.rs:14:29
|
||||
|
|
||||
LL | let f3: &Fat<[usize]> = f2;
|
||||
| ------------- ^^ expected `&Fat<[usize]>`, found `&Fat<[isize; 3]>`
|
||||
|
@ -10,43 +10,19 @@ LL | let f3: &Fat<[usize]> = f2;
|
|||
found reference `&Fat<[isize; 3]>`
|
||||
|
||||
error[E0277]: the trait bound `Foo: Bar` is not satisfied
|
||||
--> $DIR/dst-bad-coerce1.rs:22:29
|
||||
--> $DIR/dst-bad-coerce1.rs:20:29
|
||||
|
|
||||
LL | let f3: &Fat<dyn Bar> = f2;
|
||||
| ^^ the trait `Bar` is not implemented for `Foo`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/dst-bad-coerce1.rs:10:1
|
||||
--> $DIR/dst-bad-coerce1.rs:8:1
|
||||
|
|
||||
LL | trait Bar { fn bar(&self) {} }
|
||||
| ^^^^^^^^^
|
||||
= note: required for the cast from `&Fat<Foo>` to `&Fat<dyn Bar>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dst-bad-coerce1.rs:28:27
|
||||
|
|
||||
LL | let f3: &([usize],) = f2;
|
||||
| ----------- ^^ expected `&([usize],)`, found `&([isize; 3],)`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&([usize],)`
|
||||
found reference `&([isize; 3],)`
|
||||
|
||||
error[E0277]: the trait bound `Foo: Bar` is not satisfied
|
||||
--> $DIR/dst-bad-coerce1.rs:34:27
|
||||
|
|
||||
LL | let f3: &(dyn Bar,) = f2;
|
||||
| ^^ the trait `Bar` is not implemented for `Foo`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/dst-bad-coerce1.rs:10:1
|
||||
|
|
||||
LL | trait Bar { fn bar(&self) {} }
|
||||
| ^^^^^^^^^
|
||||
= note: required for the cast from `&(Foo,)` to `&(dyn Bar,)`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Attempt to extend the lifetime as well as unsizing.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
struct Fat<T: ?Sized> {
|
||||
ptr: T
|
||||
}
|
||||
|
@ -20,16 +18,6 @@ fn baz<'a>() {
|
|||
let f1 = Fat { ptr: Foo };
|
||||
let f2: &Fat<Foo> = &f1; //~ ERROR `f1` does not live long enough
|
||||
let f3: &'a Fat<dyn Bar> = f2;
|
||||
|
||||
// Tuple with a vec of ints.
|
||||
let f1 = ([1, 2, 3],);
|
||||
let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough
|
||||
let f3: &'a ([isize],) = f2;
|
||||
|
||||
// Tuple with a trait.
|
||||
let f1 = (Foo,);
|
||||
let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough
|
||||
let f3: &'a (dyn Bar,) = f2;
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0597]: `f1` does not live long enough
|
||||
--> $DIR/dst-bad-coerce3.rs:16:32
|
||||
--> $DIR/dst-bad-coerce3.rs:14:32
|
||||
|
|
||||
LL | fn baz<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
|
@ -15,7 +15,7 @@ LL | }
|
|||
| - `f1` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `f1` does not live long enough
|
||||
--> $DIR/dst-bad-coerce3.rs:21:25
|
||||
--> $DIR/dst-bad-coerce3.rs:19:25
|
||||
|
|
||||
LL | fn baz<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
|
@ -26,41 +26,9 @@ LL | let f2: &Fat<Foo> = &f1;
|
|||
| ^^^ borrowed value does not live long enough
|
||||
LL | let f3: &'a Fat<dyn Bar> = f2;
|
||||
| ---------------- type annotation requires that `f1` is borrowed for `'a`
|
||||
...
|
||||
LL | }
|
||||
| - `f1` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `f1` does not live long enough
|
||||
--> $DIR/dst-bad-coerce3.rs:26:30
|
||||
|
|
||||
LL | fn baz<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | let f1 = ([1, 2, 3],);
|
||||
| -- binding `f1` declared here
|
||||
LL | let f2: &([isize; 3],) = &f1;
|
||||
| ^^^ borrowed value does not live long enough
|
||||
LL | let f3: &'a ([isize],) = f2;
|
||||
| -------------- type annotation requires that `f1` is borrowed for `'a`
|
||||
...
|
||||
LL | }
|
||||
| - `f1` dropped here while still borrowed
|
||||
|
||||
error[E0597]: `f1` does not live long enough
|
||||
--> $DIR/dst-bad-coerce3.rs:31:23
|
||||
|
|
||||
LL | fn baz<'a>() {
|
||||
| -- lifetime `'a` defined here
|
||||
...
|
||||
LL | let f1 = (Foo,);
|
||||
| -- binding `f1` declared here
|
||||
LL | let f2: &(Foo,) = &f1;
|
||||
| ^^^ borrowed value does not live long enough
|
||||
LL | let f3: &'a (dyn Bar,) = f2;
|
||||
| -------------- type annotation requires that `f1` is borrowed for `'a`
|
||||
LL | }
|
||||
| - `f1` dropped here while still borrowed
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0597`.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// Attempt to coerce from unsized to sized.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
struct Fat<T: ?Sized> {
|
||||
ptr: T
|
||||
}
|
||||
|
@ -14,12 +12,4 @@ pub fn main() {
|
|||
//~| expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
|
||||
//~| expected reference `&Fat<[isize; 3]>`
|
||||
//~| found reference `&Fat<[isize]>`
|
||||
|
||||
// Tuple with a vec of isizes.
|
||||
let f1: &([isize],) = &([1, 2, 3],);
|
||||
let f2: &([isize; 3],) = f1;
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `&([isize; 3],)`, found `&([isize],)`
|
||||
//~| expected reference `&([isize; 3],)`
|
||||
//~| found reference `&([isize],)`
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/dst-bad-coerce4.rs:12:32
|
||||
--> $DIR/dst-bad-coerce4.rs:10:32
|
||||
|
|
||||
LL | let f2: &Fat<[isize; 3]> = f1;
|
||||
| ---------------- ^^ expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
|
||||
|
@ -9,17 +9,6 @@ LL | let f2: &Fat<[isize; 3]> = f1;
|
|||
= note: expected reference `&Fat<[isize; 3]>`
|
||||
found reference `&Fat<[isize]>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dst-bad-coerce4.rs:20:30
|
||||
|
|
||||
LL | let f2: &([isize; 3],) = f1;
|
||||
| -------------- ^^ expected `&([isize; 3],)`, found `&([isize],)`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&([isize; 3],)`
|
||||
found reference `&([isize],)`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
// because it would require stack allocation of an unsized temporary (*g in the
|
||||
// test).
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
struct Fat<T: ?Sized>(T);
|
||||
|
||||
pub fn main() {
|
||||
let f: ([isize; 3],) = ([5, 6, 7],);
|
||||
let g: &([isize],) = &f;
|
||||
let h: &(([isize],),) = &(*g,);
|
||||
let f: Fat<[isize; 3]> = Fat([5, 6, 7]);
|
||||
let g: &Fat<[isize]> = &f;
|
||||
let h: &Fat<Fat<[isize]>> = &Fat(*g);
|
||||
//~^ ERROR the size for values of type
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
error[E0277]: the size for values of type `[isize]` cannot be known at compilation time
|
||||
--> $DIR/dst-bad-deep-2.rs:11:30
|
||||
--> $DIR/dst-bad-deep-2.rs:11:38
|
||||
|
|
||||
LL | let h: &(([isize],),) = &(*g,);
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
LL | let h: &Fat<Fat<[isize]>> = &Fat(*g);
|
||||
| ^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]`
|
||||
= note: required because it appears within the type `([isize],)`
|
||||
= note: required because it appears within the type `(([isize],),)`
|
||||
= note: tuples must have a statically known size to be initialized
|
||||
= help: within `Fat<[isize]>`, the trait `Sized` is not implemented for `[isize]`
|
||||
note: required because it appears within the type `Fat<[isize]>`
|
||||
--> $DIR/dst-bad-deep-2.rs:6:8
|
||||
|
|
||||
LL | struct Fat<T: ?Sized>(T);
|
||||
| ^^^
|
||||
= note: all function arguments must have a statically known size
|
||||
= help: unsized fn params are gated as an unstable feature
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//@ run-pass
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
struct Test<T: ?Sized>(T);
|
||||
|
||||
|
@ -14,14 +13,4 @@ fn main() {
|
|||
let slice = &[1,2,3];
|
||||
let x = Test(&slice);
|
||||
let Test(&_slice) = x;
|
||||
|
||||
|
||||
let x = (10, [1,2,3]);
|
||||
let x : &(i32, [i32]) = &x;
|
||||
|
||||
let & ref _y = x;
|
||||
|
||||
let slice = &[1,2,3];
|
||||
let x = (10, &slice);
|
||||
let (_, &_slice) = x;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
//@ run-pass
|
||||
// Test DST raw pointers
|
||||
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
trait Trait {
|
||||
fn foo(&self) -> isize;
|
||||
}
|
||||
|
@ -38,14 +35,6 @@ pub fn main() {
|
|||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
// raw DST tuple
|
||||
let p = (A { f: 42 },);
|
||||
let o: *const (dyn Trait,) = &p;
|
||||
let r = unsafe {
|
||||
(&*o).0.foo()
|
||||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
// raw slice
|
||||
let a: *const [_] = &[1, 2, 3];
|
||||
unsafe {
|
||||
|
@ -73,15 +62,6 @@ pub fn main() {
|
|||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
// raw DST tuple with slice
|
||||
let c: *const ([_],) = &([1, 2, 3],);
|
||||
unsafe {
|
||||
let b = (&*c).0[0];
|
||||
assert_eq!(b, 1);
|
||||
let len = (&*c).0.len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
// all of the above with *mut
|
||||
let mut x = A { f: 42 };
|
||||
let z: *mut dyn Trait = &mut x;
|
||||
|
@ -97,13 +77,6 @@ pub fn main() {
|
|||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
let mut p = (A { f: 42 },);
|
||||
let o: *mut (dyn Trait,) = &mut p;
|
||||
let r = unsafe {
|
||||
(&*o).0.foo()
|
||||
};
|
||||
assert_eq!(r, 42);
|
||||
|
||||
let a: *mut [_] = &mut [1, 2, 3];
|
||||
unsafe {
|
||||
let b = (*a)[2];
|
||||
|
@ -127,12 +100,4 @@ pub fn main() {
|
|||
let len = (&*c).f.len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
|
||||
let c: *mut ([_],) = &mut ([1, 2, 3],);
|
||||
unsafe {
|
||||
let b = (&*c).0[0];
|
||||
assert_eq!(b, 1);
|
||||
let len = (&*c).0.len();
|
||||
assert_eq!(len, 3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
//@ run-pass
|
||||
#![allow(type_alias_bounds)]
|
||||
|
||||
#![allow(unused_features)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
type Fat<T: ?Sized> = (isize, &'static str, T);
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
struct Bar;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
struct Bar1 {
|
||||
f: isize
|
||||
}
|
||||
|
||||
trait ToBar {
|
||||
fn to_bar(&self) -> Bar;
|
||||
fn to_val(&self) -> isize;
|
||||
}
|
||||
|
||||
impl ToBar for Bar {
|
||||
fn to_bar(&self) -> Bar {
|
||||
*self
|
||||
}
|
||||
fn to_val(&self) -> isize {
|
||||
0
|
||||
}
|
||||
}
|
||||
impl ToBar for Bar1 {
|
||||
fn to_bar(&self) -> Bar {
|
||||
Bar
|
||||
}
|
||||
fn to_val(&self) -> isize {
|
||||
self.f
|
||||
}
|
||||
}
|
||||
|
||||
// x is a fat pointer
|
||||
fn foo(x: &Fat<dyn ToBar>) {
|
||||
assert_eq!(x.0, 5);
|
||||
assert_eq!(x.1, "some str");
|
||||
assert_eq!(x.2.to_bar(), Bar);
|
||||
assert_eq!(x.2.to_val(), 42);
|
||||
|
||||
let y = &x.2;
|
||||
assert_eq!(y.to_bar(), Bar);
|
||||
assert_eq!(y.to_val(), 42);
|
||||
}
|
||||
|
||||
fn bar(x: &dyn ToBar) {
|
||||
assert_eq!(x.to_bar(), Bar);
|
||||
assert_eq!(x.to_val(), 42);
|
||||
}
|
||||
|
||||
fn baz(x: &Fat<Fat<dyn ToBar>>) {
|
||||
assert_eq!(x.0, 5);
|
||||
assert_eq!(x.1, "some str");
|
||||
assert_eq!((x.2).0, 8);
|
||||
assert_eq!((x.2).1, "deep str");
|
||||
assert_eq!((x.2).2.to_bar(), Bar);
|
||||
assert_eq!((x.2).2.to_val(), 42);
|
||||
|
||||
let y = &(x.2).2;
|
||||
assert_eq!(y.to_bar(), Bar);
|
||||
assert_eq!(y.to_val(), 42);
|
||||
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let f1 = (5, "some str", Bar1 {f :42});
|
||||
foo(&f1);
|
||||
let f2 = &f1;
|
||||
foo(f2);
|
||||
let f3: &Fat<dyn ToBar> = f2;
|
||||
foo(f3);
|
||||
let f4: &Fat<dyn ToBar> = &f1;
|
||||
foo(f4);
|
||||
let f5: &Fat<dyn ToBar> = &(5, "some str", Bar1 {f :42});
|
||||
foo(f5);
|
||||
|
||||
// Zero size object.
|
||||
let f6: &Fat<dyn ToBar> = &(5, "some str", Bar);
|
||||
assert_eq!(f6.2.to_bar(), Bar);
|
||||
|
||||
// &*
|
||||
//
|
||||
let f7: Box<dyn ToBar> = Box::new(Bar1 {f :42});
|
||||
bar(&*f7);
|
||||
|
||||
// Deep nesting
|
||||
let f1 = (5, "some str", (8, "deep str", Bar1 {f :42}));
|
||||
baz(&f1);
|
||||
let f2 = &f1;
|
||||
baz(f2);
|
||||
let f3: &Fat<Fat<dyn ToBar>> = f2;
|
||||
baz(f3);
|
||||
let f4: &Fat<Fat<dyn ToBar>> = &f1;
|
||||
baz(f4);
|
||||
let f5: &Fat<Fat<dyn ToBar>> = &(5, "some str", (8, "deep str", Bar1 {f :42}));
|
||||
baz(f5);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
// Ensure that unsizable fields that might be accessed don't get reordered
|
||||
|
||||
fn nonzero_size() {
|
||||
let sized: (u8, [u32; 2]) = (123, [456, 789]);
|
||||
let unsize: &(u8, [u32]) = &sized;
|
||||
assert_eq!(unsize.0, 123);
|
||||
assert_eq!(unsize.1.len(), 2);
|
||||
assert_eq!(unsize.1[0], 456);
|
||||
assert_eq!(unsize.1[1], 789);
|
||||
}
|
||||
|
||||
fn zst() {
|
||||
let sized: (u8, [u32; 0]) = (123, []);
|
||||
let unsize: &(u8, [u32]) = &sized;
|
||||
assert_eq!(unsize.0, 123);
|
||||
assert_eq!(unsize.1.len(), 0);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
nonzero_size();
|
||||
zst();
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
//@ run-pass
|
||||
#![allow(stable_features)]
|
||||
#![allow(type_alias_bounds)]
|
||||
|
||||
// As dst-tuple.rs, but the unsized field is the only field in the tuple.
|
||||
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
type Fat<T: ?Sized> = (T,);
|
||||
|
||||
// x is a fat pointer
|
||||
fn foo(x: &Fat<[isize]>) {
|
||||
let y = &x.0;
|
||||
assert_eq!(x.0.len(), 3);
|
||||
assert_eq!(y[0], 1);
|
||||
assert_eq!(x.0[1], 2);
|
||||
}
|
||||
|
||||
fn foo2<T:ToBar>(x: &Fat<[T]>) {
|
||||
let y = &x.0;
|
||||
let bar = Bar;
|
||||
assert_eq!(x.0.len(), 3);
|
||||
assert_eq!(y[0].to_bar(), bar);
|
||||
assert_eq!(x.0[1].to_bar(), bar);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
struct Bar;
|
||||
|
||||
trait ToBar {
|
||||
fn to_bar(&self) -> Bar;
|
||||
}
|
||||
|
||||
impl ToBar for Bar {
|
||||
fn to_bar(&self) -> Bar {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// With a vec of ints.
|
||||
let f1 = ([1, 2, 3],);
|
||||
foo(&f1);
|
||||
let f2 = &f1;
|
||||
foo(f2);
|
||||
let f3: &Fat<[isize]> = f2;
|
||||
foo(f3);
|
||||
let f4: &Fat<[isize]> = &f1;
|
||||
foo(f4);
|
||||
let f5: &Fat<[isize]> = &([1, 2, 3],);
|
||||
foo(f5);
|
||||
|
||||
// With a vec of Bars.
|
||||
let bar = Bar;
|
||||
let f1 = ([bar, bar, bar],);
|
||||
foo2(&f1);
|
||||
let f2 = &f1;
|
||||
foo2(f2);
|
||||
let f3: &Fat<[Bar]> = f2;
|
||||
foo2(f3);
|
||||
let f4: &Fat<[Bar]> = &f1;
|
||||
foo2(f4);
|
||||
let f5: &Fat<[Bar]> = &([bar, bar, bar],);
|
||||
foo2(f5);
|
||||
|
||||
// Assignment.
|
||||
let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],);
|
||||
f5.0[1] = 34;
|
||||
assert_eq!(f5.0[0], 1);
|
||||
assert_eq!(f5.0[1], 34);
|
||||
assert_eq!(f5.0[2], 3);
|
||||
|
||||
// Zero size vec.
|
||||
let f5: &Fat<[isize]> = &([],);
|
||||
assert!(f5.0.is_empty());
|
||||
let f5: &Fat<[Bar]> = &([],);
|
||||
assert!(f5.0.is_empty());
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
// Check that we do not change the offsets of ZST fields when unsizing
|
||||
|
||||
fn scalar_layout() {
|
||||
let sized: &(u8, [(); 13]) = &(123, [(); 13]);
|
||||
let unsize: &(u8, [()]) = sized;
|
||||
assert_eq!(sized.1.as_ptr(), unsize.1.as_ptr());
|
||||
}
|
||||
|
||||
fn scalarpair_layout() {
|
||||
let sized: &(u8, u16, [(); 13]) = &(123, 456, [(); 13]);
|
||||
let unsize: &(u8, u16, [()]) = sized;
|
||||
assert_eq!(sized.2.as_ptr(), unsize.2.as_ptr());
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
scalar_layout();
|
||||
scalarpair_layout();
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
//@ run-pass
|
||||
#![allow(type_alias_bounds)]
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
type Fat<T: ?Sized> = (isize, &'static str, T);
|
||||
|
||||
// x is a fat pointer
|
||||
fn foo(x: &Fat<[isize]>) {
|
||||
let y = &x.2;
|
||||
assert_eq!(x.2.len(), 3);
|
||||
assert_eq!(y[0], 1);
|
||||
assert_eq!(x.2[1], 2);
|
||||
assert_eq!(x.0, 5);
|
||||
assert_eq!(x.1, "some str");
|
||||
}
|
||||
|
||||
fn foo2<T:ToBar>(x: &Fat<[T]>) {
|
||||
let y = &x.2;
|
||||
let bar = Bar;
|
||||
assert_eq!(x.2.len(), 3);
|
||||
assert_eq!(y[0].to_bar(), bar);
|
||||
assert_eq!(x.2[1].to_bar(), bar);
|
||||
assert_eq!(x.0, 5);
|
||||
assert_eq!(x.1, "some str");
|
||||
}
|
||||
|
||||
fn foo3(x: &Fat<Fat<[isize]>>) {
|
||||
let y = &(x.2).2;
|
||||
assert_eq!(x.0, 5);
|
||||
assert_eq!(x.1, "some str");
|
||||
assert_eq!((x.2).0, 8);
|
||||
assert_eq!((x.2).1, "deep str");
|
||||
assert_eq!((x.2).2.len(), 3);
|
||||
assert_eq!(y[0], 1);
|
||||
assert_eq!((x.2).2[1], 2);
|
||||
}
|
||||
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
struct Bar;
|
||||
|
||||
trait ToBar {
|
||||
fn to_bar(&self) -> Bar;
|
||||
}
|
||||
|
||||
impl ToBar for Bar {
|
||||
fn to_bar(&self) -> Bar {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
// With a vec of ints.
|
||||
let f1 = (5, "some str", [1, 2, 3]);
|
||||
foo(&f1);
|
||||
let f2 = &f1;
|
||||
foo(f2);
|
||||
let f3: &Fat<[isize]> = f2;
|
||||
foo(f3);
|
||||
let f4: &Fat<[isize]> = &f1;
|
||||
foo(f4);
|
||||
let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]);
|
||||
foo(f5);
|
||||
|
||||
// With a vec of Bars.
|
||||
let bar = Bar;
|
||||
let f1 = (5, "some str", [bar, bar, bar]);
|
||||
foo2(&f1);
|
||||
let f2 = &f1;
|
||||
foo2(f2);
|
||||
let f3: &Fat<[Bar]> = f2;
|
||||
foo2(f3);
|
||||
let f4: &Fat<[Bar]> = &f1;
|
||||
foo2(f4);
|
||||
let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]);
|
||||
foo2(f5);
|
||||
|
||||
// Assignment.
|
||||
let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]);
|
||||
f5.2[1] = 34;
|
||||
assert_eq!(f5.2[0], 1);
|
||||
assert_eq!(f5.2[1], 34);
|
||||
assert_eq!(f5.2[2], 3);
|
||||
|
||||
// Zero size vec.
|
||||
let f5: &Fat<[isize]> = &(5, "some str", []);
|
||||
assert!(f5.2.is_empty());
|
||||
let f5: &Fat<[Bar]> = &(5, "some str", []);
|
||||
assert!(f5.2.is_empty());
|
||||
|
||||
// Deeply nested.
|
||||
let f1 = (5, "some str", (8, "deep str", [1, 2, 3]));
|
||||
foo3(&f1);
|
||||
let f2 = &f1;
|
||||
foo3(f2);
|
||||
let f3: &Fat<Fat<[isize]>> = f2;
|
||||
foo3(f3);
|
||||
let f4: &Fat<Fat<[isize]>> = &f1;
|
||||
foo3(f4);
|
||||
let f5: &Fat<Fat<[isize]>> = &(5, "some str", (8, "deep str", [1, 2, 3]));
|
||||
foo3(f5);
|
||||
|
||||
// Box.
|
||||
let f1 = Box::new([1, 2, 3]);
|
||||
assert_eq!((*f1)[1], 2);
|
||||
let f2: Box<[isize]> = f1;
|
||||
assert_eq!((*f2)[1], 2);
|
||||
|
||||
// Nested Box.
|
||||
let f1 : Box<Fat<[isize; 3]>> = Box::new((5, "some str", [1, 2, 3]));
|
||||
foo(&*f1);
|
||||
let f2 : Box<Fat<[isize]>> = f1;
|
||||
foo(&*f2);
|
||||
|
||||
let f3 : Box<Fat<[isize]>> =
|
||||
Box::<Fat<[_; 3]>>::new((5, "some str", [1, 2, 3]));
|
||||
foo(&*f3);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
fn main() {
|
||||
let _ : &(dyn Send,) = &((),);
|
||||
//~^ ERROR unsized tuple coercion is not stable enough
|
||||
//~^ ERROR 2:28: 2:34: mismatched types [E0308]
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
error[E0658]: unsized tuple coercion is not stable enough for use and is subject to change
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-unsized_tuple_coercion.rs:2:28
|
||||
|
|
||||
LL | let _ : &(dyn Send,) = &((),);
|
||||
| ^^^^^^
|
||||
| ------------ ^^^^^^ expected `&(dyn Send,)`, found `&((),)`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: see issue #42877 <https://github.com/rust-lang/rust/issues/42877> for more information
|
||||
= help: add `#![feature(unsized_tuple_coercion)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
= note: expected reference `&(dyn Send,)`
|
||||
found reference `&((),)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
//! Test that we allow unsizing `([Opaque; N],)` to `([Concrete],)`.
|
||||
|
||||
//@check-pass
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
fn hello() -> ([impl Sized; 2],) {
|
||||
if false {
|
||||
let x = hello();
|
||||
let _: &([i32],) = &x;
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,8 +1,6 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
trait Foo {}
|
||||
|
||||
impl Foo for i32 {}
|
||||
|
@ -15,10 +13,6 @@ fn main() {
|
|||
let y = [1, 2, 3];
|
||||
let _: &[i32] = &y;
|
||||
|
||||
// Tuple unsizing
|
||||
let hi = (1i32,);
|
||||
let _: &(dyn Foo,) = &hi;
|
||||
|
||||
// Dropping auto traits
|
||||
let a: &(dyn Foo + Send) = &1;
|
||||
let _: &dyn Foo = a;
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#![feature(unsized_tuple_coercion)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unsized_fn_params)]
|
||||
|
||||
fn bad() -> extern "rust-call" fn(([u8],)) { todo!() }
|
||||
|
||||
fn main() {
|
||||
let f = bad();
|
||||
let slice: Box<([u8],)> = Box::new(([1; 8],));
|
||||
f(*slice);
|
||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/rust-call.rs:10:7
|
||||
|
|
||||
LL | f(*slice);
|
||||
| ^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]`
|
||||
= note: required because it appears within the type `([u8],)`
|
||||
= note: argument required to be sized due to `extern "rust-call"` ABI
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,6 +1,6 @@
|
|||
//@ run-pass
|
||||
#![allow(incomplete_features, unused_braces, unused_parens)]
|
||||
#![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
|
||||
#![feature(unsized_locals, unsized_fn_params)]
|
||||
|
||||
struct A<X: ?Sized>(#[allow(dead_code)] X);
|
||||
|
||||
|
@ -8,9 +8,6 @@ fn udrop<T: ?Sized>(_x: T) {}
|
|||
fn foo() -> Box<[u8]> {
|
||||
Box::new(*b"foo")
|
||||
}
|
||||
fn tfoo() -> Box<(i32, [u8])> {
|
||||
Box::new((42, *b"foo"))
|
||||
}
|
||||
fn afoo() -> Box<A<[u8]>> {
|
||||
Box::new(A(*b"foo"))
|
||||
}
|
||||
|
@ -27,7 +24,6 @@ fn main() {
|
|||
udrop::<[u8]>(if true { *foo() } else { *foo() });
|
||||
udrop::<[u8]>({ *foo() });
|
||||
udrop::<[u8]>((*foo()));
|
||||
udrop::<[u8]>((*tfoo()).1);
|
||||
*afoo() + 42;
|
||||
udrop as fn([u8]);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(unsized_tuple_coercion, unsized_fn_params)]
|
||||
#![feature(unsized_fn_params)]
|
||||
|
||||
struct A<X: ?Sized>(X);
|
||||
|
||||
|
@ -6,9 +6,6 @@ fn udrop<T: ?Sized>(_x: T) {}
|
|||
fn foo() -> Box<[u8]> {
|
||||
Box::new(*b"foo")
|
||||
}
|
||||
fn tfoo() -> Box<(i32, [u8])> {
|
||||
Box::new((42, *b"foo"))
|
||||
}
|
||||
fn afoo() -> Box<A<[u8]>> {
|
||||
Box::new(A(*b"foo"))
|
||||
}
|
||||
|
@ -19,8 +16,6 @@ impl std::ops::Add<i32> for A<[u8]> {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
udrop::<(i32, [u8])>((42, *foo()));
|
||||
//~^ERROR E0277
|
||||
udrop::<A<[u8]>>(A { 0: *foo() });
|
||||
//~^ERROR E0277
|
||||
udrop::<A<[u8]>>(A(*foo()));
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-exprs.rs:22:26
|
||||
|
|
||||
LL | udrop::<(i32, [u8])>((42, *foo()));
|
||||
| ^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]`
|
||||
= note: required because it appears within the type `({integer}, [u8])`
|
||||
= note: tuples must have a statically known size to be initialized
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-exprs.rs:24:22
|
||||
--> $DIR/unsized-exprs.rs:19:22
|
||||
|
|
||||
LL | udrop::<A<[u8]>>(A { 0: *foo() });
|
||||
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
@ -23,7 +13,7 @@ LL | struct A<X: ?Sized>(X);
|
|||
= note: structs must have a statically known size to be initialized
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-exprs.rs:26:22
|
||||
--> $DIR/unsized-exprs.rs:21:22
|
||||
|
|
||||
LL | udrop::<A<[u8]>>(A(*foo()));
|
||||
| ^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
@ -36,6 +26,6 @@ LL | struct A<X: ?Sized>(X);
|
|||
| ^
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(unsized_tuple_coercion, unsized_fn_params)]
|
||||
#![feature(unsized_fn_params)]
|
||||
|
||||
struct A<X: ?Sized>(X);
|
||||
|
||||
|
@ -6,9 +6,6 @@ fn udrop<T: ?Sized>(_x: T) {}
|
|||
fn foo() -> Box<[u8]> {
|
||||
Box::new(*b"foo")
|
||||
}
|
||||
fn tfoo() -> Box<(i32, [u8])> {
|
||||
Box::new((42, *b"foo"))
|
||||
}
|
||||
fn afoo() -> Box<A<[u8]>> {
|
||||
Box::new(A(*b"foo"))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0508]: cannot move out of type `[u8]`, a non-copy slice
|
||||
--> $DIR/unsized-exprs2.rs:22:5
|
||||
--> $DIR/unsized-exprs2.rs:19:5
|
||||
|
|
||||
LL | udrop::<[u8]>(foo()[..]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
fn main() {
|
||||
let x : &(i32, i32, [i32]) = &(0, 1, [2, 3]);
|
||||
let y : &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]);
|
||||
let mut a = [y, x];
|
||||
a.sort();
|
||||
assert_eq!(a, [x, y]);
|
||||
|
||||
assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
|
||||
|
||||
let mut h = HashSet::new();
|
||||
h.insert(x);
|
||||
h.insert(y);
|
||||
assert!(h.contains(x));
|
||||
assert!(h.contains(y));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue