Skip to content

Commit c02d1a6

Browse files
Restore tuple unsizing feature gate
1 parent 24eefd0 commit c02d1a6

File tree

7 files changed

+57
-19
lines changed

7 files changed

+57
-19
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
622622
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
623623
)];
624624

625+
let mut has_unsized_tuple_coercion = false;
625626
let mut has_trait_upcasting_coercion = None;
626627

627628
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
@@ -686,11 +687,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
686687
}
687688

688689
Ok(Some(impl_source)) => {
689-
if matches!(impl_source, traits::ImplSource::TraitUpcasting(..)) {
690-
has_trait_upcasting_coercion =
691-
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
690+
match impl_source {
691+
traits::ImplSource::TraitUpcasting(..) => {
692+
has_trait_upcasting_coercion =
693+
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
694+
}
695+
traits::ImplSource::TupleUnsizing(_) => {
696+
has_unsized_tuple_coercion = true;
697+
}
698+
_ => {}
692699
}
693-
694700
queue.extend(impl_source.nested_obligations())
695701
}
696702
}
@@ -711,6 +717,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
711717
err.emit();
712718
}
713719

720+
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
721+
feature_err(
722+
&self.tcx.sess.parse_sess,
723+
sym::unsized_tuple_coercion,
724+
self.cause.span,
725+
"unsized tuple coercion is not stable enough for use and is subject to change",
726+
)
727+
.emit();
728+
}
729+
714730
Ok(coercion)
715731
}
716732

compiler/rustc_middle/src/traits/mod.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,9 @@ pub enum ImplSource<'tcx, N> {
657657
/// Successful resolution for a builtin trait.
658658
Builtin(Vec<N>),
659659

660+
// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`
661+
TupleUnsizing(Vec<N>),
662+
660663
/// ImplSource for trait upcasting coercion
661664
TraitUpcasting(ImplSourceTraitUpcastingData<N>),
662665
}
@@ -665,7 +668,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
665668
pub fn nested_obligations(self) -> Vec<N> {
666669
match self {
667670
ImplSource::UserDefined(i) => i.nested,
668-
ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
671+
ImplSource::Param(n, _) | ImplSource::Builtin(n) | ImplSource::TupleUnsizing(n) => n,
669672
ImplSource::Object(d) => d.nested,
670673
ImplSource::TraitUpcasting(d) => d.nested,
671674
}
@@ -674,7 +677,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
674677
pub fn borrow_nested_obligations(&self) -> &[N] {
675678
match self {
676679
ImplSource::UserDefined(i) => &i.nested,
677-
ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n,
680+
ImplSource::Param(n, _) | ImplSource::Builtin(n) | ImplSource::TupleUnsizing(n) => &n,
678681
ImplSource::Object(d) => &d.nested,
679682
ImplSource::TraitUpcasting(d) => &d.nested,
680683
}
@@ -683,7 +686,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
683686
pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
684687
match self {
685688
ImplSource::UserDefined(i) => &mut i.nested,
686-
ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
689+
ImplSource::Param(n, _) | ImplSource::Builtin(n) | ImplSource::TupleUnsizing(n) => n,
687690
ImplSource::Object(d) => &mut d.nested,
688691
ImplSource::TraitUpcasting(d) => &mut d.nested,
689692
}
@@ -701,6 +704,9 @@ impl<'tcx, N> ImplSource<'tcx, N> {
701704
}),
702705
ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
703706
ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()),
707+
ImplSource::TupleUnsizing(n) => {
708+
ImplSource::TupleUnsizing(n.into_iter().map(f).collect())
709+
}
704710
ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData {
705711
vtable_base: o.vtable_base,
706712
nested: o.nested.into_iter().map(f).collect(),

compiler/rustc_middle/src/traits/structural_impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
1717
write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
1818
}
1919

20+
super::ImplSource::TupleUnsizing(ref d) => write!(f, "{:?}", d),
21+
2022
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
2123
}
2224
}

compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs

+3
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,9 @@ fn rematch_unsize<'tcx>(
456456
goal.param_env,
457457
ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
458458
));
459+
460+
// We need to be able to detect tuple unsizing to require its feature gate.
461+
return Ok(Some(ImplSource::TupleUnsizing(nested)));
459462
}
460463
// FIXME: We *could* ICE here if either:
461464
// 1. the certainty is `Certainty::Yes`,

compiler/rustc_trait_selection/src/traits/project.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1925,7 +1925,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
19251925
// why we special case object types.
19261926
false
19271927
}
1928-
| super::ImplSource::TraitUpcasting(_) => {
1928+
super::ImplSource::TraitUpcasting(_)
1929+
| super::ImplSource::TupleUnsizing(_) => {
19291930
// These traits have no associated types.
19301931
selcx.tcx().sess.delay_span_bug(
19311932
obligation.cause.span,
@@ -2005,7 +2006,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
20052006
}
20062007
super::ImplSource::Object(_)
20072008
| super::ImplSource::Param(..)
2008-
| super::ImplSource::TraitUpcasting(_) => {
2009+
| super::ImplSource::TraitUpcasting(_)
2010+
| super::ImplSource::TupleUnsizing(_) => {
20092011
// we don't create Select candidates with this kind of resolution
20102012
span_bug!(
20112013
obligation.cause.span,

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

+16-9
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
114114
}
115115

116116
BuiltinUnsizeCandidate => {
117-
let data = self.confirm_builtin_unsize_candidate(obligation)?;
118-
ImplSource::Builtin(data)
117+
let source =
118+
self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
119+
let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
120+
let target = self.infcx.shallow_resolve(target);
121+
let data = self.confirm_builtin_unsize_candidate(obligation, source, target)?;
122+
// If the source and target are both unsize goals, then we need to signify that
123+
// this is tuple unsizing so that during unsized coercion we require the proper
124+
// feature gate.
125+
if matches!(source.kind(), ty::Tuple(..)) && matches!(target.kind(), ty::Tuple(..))
126+
{
127+
ImplSource::TupleUnsizing(data)
128+
} else {
129+
ImplSource::Builtin(data)
130+
}
119131
}
120132

121133
TraitUpcastingUnsizeCandidate(idx) => {
@@ -1000,15 +1012,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10001012
fn confirm_builtin_unsize_candidate(
10011013
&mut self,
10021014
obligation: &PolyTraitObligation<'tcx>,
1015+
source: Ty<'tcx>,
1016+
target: Ty<'tcx>,
10031017
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
10041018
let tcx = self.tcx();
1005-
1006-
// `assemble_candidates_for_unsizing` should ensure there are no late-bound
1007-
// regions here. See the comment there for more details.
1008-
let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
1009-
let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
1010-
let target = self.infcx.shallow_resolve(target);
1011-
10121019
debug!(?source, ?target, "confirm_builtin_unsize_candidate");
10131020

10141021
let mut nested = vec![];

compiler/rustc_ty_utils/src/instance.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ fn resolve_associated_item<'tcx>(
290290
None
291291
}
292292
}
293-
traits::ImplSource::Param(..) | traits::ImplSource::TraitUpcasting(_) => None,
293+
traits::ImplSource::Param(..)
294+
| traits::ImplSource::TraitUpcasting(_)
295+
| traits::ImplSource::TupleUnsizing(_) => None,
294296
})
295297
}
296298

0 commit comments

Comments
 (0)