Skip to content

Commit 257b494

Browse files
authored
Rollup merge of #137728 - Darksonn:no-tuple-unsize, r=oli-obk
Remove unsizing coercions for tuples See #42877 (comment) and below comments for justification. Tracking issue: #42877 Fixes: #135217
2 parents dac4ffd + 68df70d commit 257b494

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+56
-878
lines changed

compiler/rustc_feature/src/removed.rs

+2
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ declare_features! (
244244
/// Allows unnamed fields of struct and union type
245245
(removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")),
246246
(removed, unsafe_no_drop_flag, "1.0.0", None, None),
247+
(removed, unsized_tuple_coercion, "CURRENT_RUSTC_VERSION", Some(42877),
248+
Some("The feature restricts possible layouts for tuples, and this restriction is not worth it.")),
247249
/// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
248250
(removed, untagged_unions, "1.13.0", Some(55149),
249251
Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more")),

compiler/rustc_feature/src/unstable.rs

-2
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,6 @@ declare_features! (
659659
(internal, unsized_fn_params, "1.49.0", Some(48055)),
660660
/// Allows unsized rvalues at arguments and parameters.
661661
(incomplete, unsized_locals, "1.30.0", Some(48055)),
662-
/// Allows unsized tuple coercion.
663-
(unstable, unsized_tuple_coercion, "1.20.0", Some(42877)),
664662
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
665663
(unstable, used_with_arg, "1.60.0", Some(93798)),
666664
/// Allows use of attributes in `where` clauses.

compiler/rustc_hir_typeck/src/coercion.rs

+2-27
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,13 @@ use rustc_infer::traits::{
5151
PredicateObligations,
5252
};
5353
use rustc_middle::span_bug;
54-
use rustc_middle::traits::BuiltinImplSource;
5554
use rustc_middle::ty::adjustment::{
5655
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
5756
};
5857
use rustc_middle::ty::error::TypeError;
5958
use rustc_middle::ty::visit::TypeVisitableExt;
6059
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
61-
use rustc_session::parse::feature_err;
62-
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span, sym};
60+
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
6361
use rustc_trait_selection::infer::InferCtxtExt as _;
6462
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
6563
use rustc_trait_selection::traits::{
@@ -610,8 +608,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
610608
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
611609
)];
612610

613-
let mut has_unsized_tuple_coercion = false;
614-
615611
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
616612
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
617613
// inference might unify those two inner type variables later.
@@ -690,31 +686,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
690686
// be silent, as it causes a type mismatch later.
691687
}
692688

693-
Ok(Some(impl_source)) => {
694-
// Some builtin coercions are still unstable so we detect
695-
// these here and emit a feature error if coercion doesn't fail
696-
// due to another reason.
697-
match impl_source {
698-
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
699-
has_unsized_tuple_coercion = true;
700-
}
701-
_ => {}
702-
}
703-
queue.extend(impl_source.nested_obligations())
704-
}
689+
Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()),
705690
}
706691
}
707692

708-
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion() {
709-
feature_err(
710-
&self.tcx.sess,
711-
sym::unsized_tuple_coercion,
712-
self.cause.span,
713-
"unsized tuple coercion is not stable enough for use and is subject to change",
714-
)
715-
.emit();
716-
}
717-
718693
Ok(coercion)
719694
}
720695

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

-49
Original file line numberDiff line numberDiff line change
@@ -786,13 +786,6 @@ where
786786
)
787787
}
788788

789-
// `(A, B, T)` -> `(A, B, U)` where `T: Unsize<U>`
790-
(ty::Tuple(a_tys), ty::Tuple(b_tys))
791-
if a_tys.len() == b_tys.len() && !a_tys.is_empty() =>
792-
{
793-
result_to_single(ecx.consider_builtin_tuple_unsize(goal, a_tys, b_tys))
794-
}
795-
796789
_ => vec![],
797790
}
798791
})
@@ -1084,48 +1077,6 @@ where
10841077
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
10851078
}
10861079

1087-
/// We generate the following builtin impl for tuples of all sizes.
1088-
///
1089-
/// This impl is still unstable and we emit a feature error when it
1090-
/// when it is used by a coercion.
1091-
/// ```ignore (builtin impl example)
1092-
/// impl<T: ?Sized, U: ?Sized, V: ?Sized> Unsize<(T, V)> for (T, U)
1093-
/// where
1094-
/// U: Unsize<V>,
1095-
/// {}
1096-
/// ```
1097-
fn consider_builtin_tuple_unsize(
1098-
&mut self,
1099-
goal: Goal<I, (I::Ty, I::Ty)>,
1100-
a_tys: I::Tys,
1101-
b_tys: I::Tys,
1102-
) -> Result<Candidate<I>, NoSolution> {
1103-
let cx = self.cx();
1104-
let Goal { predicate: (_a_ty, b_ty), .. } = goal;
1105-
1106-
let (&a_last_ty, a_rest_tys) = a_tys.split_last().unwrap();
1107-
let b_last_ty = b_tys.last().unwrap();
1108-
1109-
// Instantiate just the tail field of B., and require that they're equal.
1110-
let unsized_a_ty = Ty::new_tup_from_iter(cx, a_rest_tys.iter().copied().chain([b_last_ty]));
1111-
self.eq(goal.param_env, unsized_a_ty, b_ty)?;
1112-
1113-
// Similar to ADTs, require that we can unsize the tail.
1114-
self.add_goal(
1115-
GoalSource::ImplWhereBound,
1116-
goal.with(
1117-
cx,
1118-
ty::TraitRef::new(
1119-
cx,
1120-
cx.require_lang_item(TraitSolverLangItem::Unsize),
1121-
[a_last_ty, b_last_ty],
1122-
),
1123-
),
1124-
);
1125-
self.probe_builtin_trait_candidate(BuiltinImplSource::TupleUnsizing)
1126-
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
1127-
}
1128-
11291080
// Return `Some` if there is an impl (built-in or user provided) that may
11301081
// hold for the self type of the goal, which for coherence and soundness
11311082
// purposes must disqualify the built-in auto impl assembled by considering

compiler/rustc_trait_selection/src/traits/project.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1232,8 +1232,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
12321232
// why we special case object types.
12331233
false
12341234
}
1235-
ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
1236-
| ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
1235+
ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => {
12371236
// These traits have no associated types.
12381237
selcx.tcx().dcx().span_delayed_bug(
12391238
obligation.cause.span,
@@ -1325,8 +1324,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
13251324
}
13261325
ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)
13271326
| ImplSource::Param(..)
1328-
| ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
1329-
| ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
1327+
| ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => {
13301328
// we don't create Select candidates with this kind of resolution
13311329
span_bug!(
13321330
obligation.cause.span,

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1017,13 +1017,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10171017
}
10181018
}
10191019

1020-
// `(.., T)` -> `(.., U)`
1021-
(&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
1022-
if tys_a.len() == tys_b.len() {
1023-
candidates.vec.push(BuiltinUnsizeCandidate);
1024-
}
1025-
}
1026-
10271020
_ => {}
10281021
};
10291022
}

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

-29
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
//! [rustc dev guide]:
88
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
99
10-
use std::iter;
1110
use std::ops::ControlFlow;
1211

1312
use rustc_ast::Mutability;
@@ -1315,34 +1314,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13151314
ImplSource::Builtin(BuiltinImplSource::Misc, nested)
13161315
}
13171316

1318-
// `(.., T)` -> `(.., U)`
1319-
(&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
1320-
assert_eq!(tys_a.len(), tys_b.len());
1321-
1322-
// The last field of the tuple has to exist.
1323-
let (&a_last, a_mid) = tys_a.split_last().ok_or(Unimplemented)?;
1324-
let &b_last = tys_b.last().unwrap();
1325-
1326-
// Check that the source tuple with the target's
1327-
// last element is equal to the target.
1328-
let new_tuple =
1329-
Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
1330-
let InferOk { mut obligations, .. } = self
1331-
.infcx
1332-
.at(&obligation.cause, obligation.param_env)
1333-
.eq(DefineOpaqueTypes::Yes, target, new_tuple)
1334-
.map_err(|_| Unimplemented)?;
1335-
1336-
// Add a nested `T: Unsize<U>` predicate.
1337-
let last_unsize_obligation = obligation.with(
1338-
tcx,
1339-
ty::TraitRef::new(tcx, obligation.predicate.def_id(), [a_last, b_last]),
1340-
);
1341-
obligations.push(last_unsize_obligation);
1342-
1343-
ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, obligations)
1344-
}
1345-
13461317
_ => bug!("source: {source}, target: {target}"),
13471318
})
13481319
}

compiler/rustc_ty_utils/src/instance.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,7 @@ fn resolve_associated_item<'tcx>(
381381
}
382382
}
383383
traits::ImplSource::Param(..)
384-
| traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _)
385-
| traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => None,
384+
| traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) => None,
386385
})
387386
}
388387

compiler/rustc_type_ir/src/solve/mod.rs

-5
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,6 @@ pub enum BuiltinImplSource {
189189
///
190190
/// The index is only used for winnowing.
191191
TraitUpcasting(usize),
192-
/// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`.
193-
///
194-
/// This can be removed when `feature(tuple_unsizing)` is stabilized, since we only
195-
/// use it to detect when unsizing tuples in hir typeck.
196-
TupleUnsizing,
197192
}
198193

199194
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]

library/coretests/tests/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787
#![feature(try_find)]
8888
#![feature(try_trait_v2)]
8989
#![feature(unsize)]
90-
#![feature(unsized_tuple_coercion)]
9190
#![feature(unwrap_infallible)]
9291
// tidy-alphabetical-end
9392
#![allow(internal_features)]

library/coretests/tests/ptr.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -525,31 +525,24 @@ fn ptr_metadata() {
525525
assert_eq!(metadata("foo"), 3_usize);
526526
assert_eq!(metadata(&[4, 7][..]), 2_usize);
527527

528-
let dst_tuple: &(bool, [u8]) = &(true, [0x66, 0x6F, 0x6F]);
529528
let dst_struct: &Pair<bool, [u8]> = &Pair(true, [0x66, 0x6F, 0x6F]);
530-
assert_eq!(metadata(dst_tuple), 3_usize);
531529
assert_eq!(metadata(dst_struct), 3_usize);
532530
unsafe {
533-
let dst_tuple: &(bool, str) = std::mem::transmute(dst_tuple);
534531
let dst_struct: &Pair<bool, str> = std::mem::transmute(dst_struct);
535-
assert_eq!(&dst_tuple.1, "foo");
536532
assert_eq!(&dst_struct.1, "foo");
537-
assert_eq!(metadata(dst_tuple), 3_usize);
538533
assert_eq!(metadata(dst_struct), 3_usize);
539534
}
540535

541536
let vtable_1: DynMetadata<dyn Debug> = metadata(&4_u16 as &dyn Debug);
542537
let vtable_2: DynMetadata<dyn Display> = metadata(&4_u16 as &dyn Display);
543538
let vtable_3: DynMetadata<dyn Display> = metadata(&4_u32 as &dyn Display);
544-
let vtable_4: DynMetadata<dyn Display> = metadata(&(true, 7_u32) as &(bool, dyn Display));
545-
let vtable_5: DynMetadata<dyn Display> =
539+
let vtable_4: DynMetadata<dyn Display> =
546540
metadata(&Pair(true, 7_u32) as &Pair<bool, dyn Display>);
547541
unsafe {
548542
let address_1: *const () = std::mem::transmute(vtable_1);
549543
let address_2: *const () = std::mem::transmute(vtable_2);
550544
let address_3: *const () = std::mem::transmute(vtable_3);
551545
let address_4: *const () = std::mem::transmute(vtable_4);
552-
let address_5: *const () = std::mem::transmute(vtable_5);
553546
// Different trait => different vtable pointer
554547
assert_ne!(address_1, address_2);
555548
// Different erased type => different vtable pointer
@@ -558,7 +551,6 @@ fn ptr_metadata() {
558551
// This is *not guaranteed*, so we skip it in Miri.
559552
if !cfg!(miri) {
560553
assert_eq!(address_3, address_4);
561-
assert_eq!(address_3, address_5);
562554
}
563555
}
564556
}

src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md

-27
This file was deleted.

src/tools/miri/tests/pass/unsized.rs

-15
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,8 @@
11
//@revisions: stack tree
22
//@[tree]compile-flags: -Zmiri-tree-borrows
3-
#![feature(unsized_tuple_coercion)]
43
#![feature(unsized_fn_params)]
54
#![feature(custom_mir, core_intrinsics)]
65

7-
use std::mem;
8-
9-
fn unsized_tuple() {
10-
let x: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
11-
let y: &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]);
12-
let mut a = [y, x];
13-
a.sort();
14-
assert_eq!(a, [x, y]);
15-
16-
assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
17-
assert_eq!(mem::size_of_val(x), 16);
18-
}
19-
206
fn unsized_params() {
217
pub fn f0(_f: dyn FnOnce()) {}
228
pub fn f1(_s: str) {}
@@ -56,7 +42,6 @@ fn unsized_field_projection() {
5642
}
5743

5844
fn main() {
59-
unsized_tuple();
6045
unsized_params();
6146
unsized_field_projection();
6247
}

src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs

-34
Original file line numberDiff line numberDiff line change
@@ -12311,40 +12311,6 @@ fn main() {
1231112311
```
1231212312

1231312313
will unnecessarily extend the stack frame.
12314-
"##,
12315-
default_severity: Severity::Allow,
12316-
warn_since: None,
12317-
deny_since: None,
12318-
},
12319-
Lint {
12320-
label: "unsized_tuple_coercion",
12321-
description: r##"# `unsized_tuple_coercion`
12322-
12323-
The tracking issue for this feature is: [#42877]
12324-
12325-
[#42877]: https://github.com/rust-lang/rust/issues/42877
12326-
12327-
------------------------
12328-
12329-
This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
12330-
12331-
```rust,ignore (partial-example)
12332-
impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
12333-
```
12334-
12335-
This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
12336-
12337-
```rust
12338-
#![feature(unsized_tuple_coercion)]
12339-
12340-
fn main() {
12341-
let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
12342-
let y : &([i32; 3], [i32]) = &x;
12343-
assert_eq!(y.1[0], 4);
12344-
}
12345-
```
12346-
12347-
[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
1234812314
"##,
1234912315
default_severity: Severity::Allow,
1235012316
warn_since: None,

0 commit comments

Comments
 (0)