1
Fork 0

Delete tuple unsizing

This commit is contained in:
Alice Ryhl 2025-02-27 08:21:47 +00:00
parent 2af87eab3b
commit 44cccae02a
47 changed files with 55 additions and 879 deletions

View file

@ -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

View file

@ -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)
}

View file

@ -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

View file

@ -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 \

View file

@ -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,

View file

@ -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);
}
}
_ => {}
};
}

View file

@ -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}"),
})
}

View file

@ -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,
})
}

View file

@ -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)]

View file

@ -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)]

View file

@ -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);
}
}
}

View file

@ -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

View file

@ -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();
}

View file

@ -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,

View file

@ -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
}

View file

@ -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);
}

View file

@ -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]);
}
}

View file

@ -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 {
| ^^^

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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`.

View file

@ -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() {

View file

@ -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`.

View file

@ -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],)`
}

View file

@ -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`.

View file

@ -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
}

View file

@ -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

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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());
}

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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]
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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;

View file

@ -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
}

View file

@ -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`.

View file

@ -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]);
}

View file

@ -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()));

View file

@ -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`.

View file

@ -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"))
}

View file

@ -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()[..]);
| ^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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));
}