Restore tuple unsizing feature gate
This commit is contained in:
parent
24eefd08e2
commit
c02d1a6553
7 changed files with 57 additions and 19 deletions
|
@ -622,6 +622,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
|
ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target])
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
let mut has_unsized_tuple_coercion = false;
|
||||||
let mut has_trait_upcasting_coercion = None;
|
let mut has_trait_upcasting_coercion = None;
|
||||||
|
|
||||||
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
|
||||||
|
@ -686,11 +687,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(impl_source)) => {
|
Ok(Some(impl_source)) => {
|
||||||
if matches!(impl_source, traits::ImplSource::TraitUpcasting(..)) {
|
match impl_source {
|
||||||
|
traits::ImplSource::TraitUpcasting(..) => {
|
||||||
has_trait_upcasting_coercion =
|
has_trait_upcasting_coercion =
|
||||||
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
|
Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
|
||||||
}
|
}
|
||||||
|
traits::ImplSource::TupleUnsizing(_) => {
|
||||||
|
has_unsized_tuple_coercion = true;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
queue.extend(impl_source.nested_obligations())
|
queue.extend(impl_source.nested_obligations())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -711,6 +717,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
|
||||||
|
feature_err(
|
||||||
|
&self.tcx.sess.parse_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)
|
Ok(coercion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -657,6 +657,9 @@ pub enum ImplSource<'tcx, N> {
|
||||||
/// Successful resolution for a builtin trait.
|
/// Successful resolution for a builtin trait.
|
||||||
Builtin(Vec<N>),
|
Builtin(Vec<N>),
|
||||||
|
|
||||||
|
// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`
|
||||||
|
TupleUnsizing(Vec<N>),
|
||||||
|
|
||||||
/// ImplSource for trait upcasting coercion
|
/// ImplSource for trait upcasting coercion
|
||||||
TraitUpcasting(ImplSourceTraitUpcastingData<N>),
|
TraitUpcasting(ImplSourceTraitUpcastingData<N>),
|
||||||
}
|
}
|
||||||
|
@ -665,7 +668,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||||
pub fn nested_obligations(self) -> Vec<N> {
|
pub fn nested_obligations(self) -> Vec<N> {
|
||||||
match self {
|
match self {
|
||||||
ImplSource::UserDefined(i) => i.nested,
|
ImplSource::UserDefined(i) => i.nested,
|
||||||
ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
|
ImplSource::Param(n, _) | ImplSource::Builtin(n) | ImplSource::TupleUnsizing(n) => n,
|
||||||
ImplSource::Object(d) => d.nested,
|
ImplSource::Object(d) => d.nested,
|
||||||
ImplSource::TraitUpcasting(d) => d.nested,
|
ImplSource::TraitUpcasting(d) => d.nested,
|
||||||
}
|
}
|
||||||
|
@ -674,7 +677,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||||
pub fn borrow_nested_obligations(&self) -> &[N] {
|
pub fn borrow_nested_obligations(&self) -> &[N] {
|
||||||
match self {
|
match self {
|
||||||
ImplSource::UserDefined(i) => &i.nested,
|
ImplSource::UserDefined(i) => &i.nested,
|
||||||
ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n,
|
ImplSource::Param(n, _) | ImplSource::Builtin(n) | ImplSource::TupleUnsizing(n) => &n,
|
||||||
ImplSource::Object(d) => &d.nested,
|
ImplSource::Object(d) => &d.nested,
|
||||||
ImplSource::TraitUpcasting(d) => &d.nested,
|
ImplSource::TraitUpcasting(d) => &d.nested,
|
||||||
}
|
}
|
||||||
|
@ -683,7 +686,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||||
pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
|
pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
|
||||||
match self {
|
match self {
|
||||||
ImplSource::UserDefined(i) => &mut i.nested,
|
ImplSource::UserDefined(i) => &mut i.nested,
|
||||||
ImplSource::Param(n, _) | ImplSource::Builtin(n) => n,
|
ImplSource::Param(n, _) | ImplSource::Builtin(n) | ImplSource::TupleUnsizing(n) => n,
|
||||||
ImplSource::Object(d) => &mut d.nested,
|
ImplSource::Object(d) => &mut d.nested,
|
||||||
ImplSource::TraitUpcasting(d) => &mut d.nested,
|
ImplSource::TraitUpcasting(d) => &mut d.nested,
|
||||||
}
|
}
|
||||||
|
@ -701,6 +704,9 @@ impl<'tcx, N> ImplSource<'tcx, N> {
|
||||||
}),
|
}),
|
||||||
ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
|
ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct),
|
||||||
ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()),
|
ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()),
|
||||||
|
ImplSource::TupleUnsizing(n) => {
|
||||||
|
ImplSource::TupleUnsizing(n.into_iter().map(f).collect())
|
||||||
|
}
|
||||||
ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData {
|
ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData {
|
||||||
vtable_base: o.vtable_base,
|
vtable_base: o.vtable_base,
|
||||||
nested: o.nested.into_iter().map(f).collect(),
|
nested: o.nested.into_iter().map(f).collect(),
|
||||||
|
|
|
@ -17,6 +17,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
|
||||||
write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
|
write!(f, "ImplSourceParamData({:?}, {:?})", n, ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super::ImplSource::TupleUnsizing(ref d) => write!(f, "{:?}", d),
|
||||||
|
|
||||||
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
|
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,6 +456,9 @@ fn rematch_unsize<'tcx>(
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
|
ty::TraitRef::new(tcx, goal.predicate.def_id(), [*a_last_ty, *b_last_ty]),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// We need to be able to detect tuple unsizing to require its feature gate.
|
||||||
|
return Ok(Some(ImplSource::TupleUnsizing(nested)));
|
||||||
}
|
}
|
||||||
// FIXME: We *could* ICE here if either:
|
// FIXME: We *could* ICE here if either:
|
||||||
// 1. the certainty is `Certainty::Yes`,
|
// 1. the certainty is `Certainty::Yes`,
|
||||||
|
|
|
@ -1925,7 +1925,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
// why we special case object types.
|
// why we special case object types.
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
| super::ImplSource::TraitUpcasting(_) => {
|
super::ImplSource::TraitUpcasting(_)
|
||||||
|
| super::ImplSource::TupleUnsizing(_) => {
|
||||||
// These traits have no associated types.
|
// These traits have no associated types.
|
||||||
selcx.tcx().sess.delay_span_bug(
|
selcx.tcx().sess.delay_span_bug(
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
|
@ -2005,7 +2006,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
|
||||||
}
|
}
|
||||||
super::ImplSource::Object(_)
|
super::ImplSource::Object(_)
|
||||||
| super::ImplSource::Param(..)
|
| super::ImplSource::Param(..)
|
||||||
| super::ImplSource::TraitUpcasting(_) => {
|
| super::ImplSource::TraitUpcasting(_)
|
||||||
|
| super::ImplSource::TupleUnsizing(_) => {
|
||||||
// we don't create Select candidates with this kind of resolution
|
// we don't create Select candidates with this kind of resolution
|
||||||
span_bug!(
|
span_bug!(
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
|
|
|
@ -114,9 +114,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
BuiltinUnsizeCandidate => {
|
BuiltinUnsizeCandidate => {
|
||||||
let data = self.confirm_builtin_unsize_candidate(obligation)?;
|
let source =
|
||||||
|
self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
|
||||||
|
let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
|
||||||
|
let target = self.infcx.shallow_resolve(target);
|
||||||
|
let data = self.confirm_builtin_unsize_candidate(obligation, source, target)?;
|
||||||
|
// If the source and target are both unsize goals, then we need to signify that
|
||||||
|
// this is tuple unsizing so that during unsized coercion we require the proper
|
||||||
|
// feature gate.
|
||||||
|
if matches!(source.kind(), ty::Tuple(..)) && matches!(target.kind(), ty::Tuple(..))
|
||||||
|
{
|
||||||
|
ImplSource::TupleUnsizing(data)
|
||||||
|
} else {
|
||||||
ImplSource::Builtin(data)
|
ImplSource::Builtin(data)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TraitUpcastingUnsizeCandidate(idx) => {
|
TraitUpcastingUnsizeCandidate(idx) => {
|
||||||
let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
|
let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
|
||||||
|
@ -1000,15 +1012,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
fn confirm_builtin_unsize_candidate(
|
fn confirm_builtin_unsize_candidate(
|
||||||
&mut self,
|
&mut self,
|
||||||
obligation: &PolyTraitObligation<'tcx>,
|
obligation: &PolyTraitObligation<'tcx>,
|
||||||
|
source: Ty<'tcx>,
|
||||||
|
target: Ty<'tcx>,
|
||||||
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
// `assemble_candidates_for_unsizing` should ensure there are no late-bound
|
|
||||||
// regions here. See the comment there for more details.
|
|
||||||
let source = self.infcx.shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
|
|
||||||
let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
|
|
||||||
let target = self.infcx.shallow_resolve(target);
|
|
||||||
|
|
||||||
debug!(?source, ?target, "confirm_builtin_unsize_candidate");
|
debug!(?source, ?target, "confirm_builtin_unsize_candidate");
|
||||||
|
|
||||||
let mut nested = vec![];
|
let mut nested = vec![];
|
||||||
|
|
|
@ -290,7 +290,9 @@ fn resolve_associated_item<'tcx>(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traits::ImplSource::Param(..) | traits::ImplSource::TraitUpcasting(_) => None,
|
traits::ImplSource::Param(..)
|
||||||
|
| traits::ImplSource::TraitUpcasting(_)
|
||||||
|
| traits::ImplSource::TupleUnsizing(_) => None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue