about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs25
2 files changed, 20 insertions, 11 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a39fc1f1771..18470d520f7 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1925,7 +1925,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                 // why we special case object types.
                 false
             }
-            | super::ImplSource::TraitUpcasting(_) => {
+            super::ImplSource::TraitUpcasting(_)
+            | super::ImplSource::TupleUnsizing(_) => {
                 // These traits have no associated types.
                 selcx.tcx().sess.delay_span_bug(
                     obligation.cause.span,
@@ -2005,7 +2006,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
         }
         super::ImplSource::Object(_)
         | super::ImplSource::Param(..)
-        | super::ImplSource::TraitUpcasting(_) => {
+        | super::ImplSource::TraitUpcasting(_)
+        | super::ImplSource::TupleUnsizing(_) => {
             // we don't create Select candidates with this kind of resolution
             span_bug!(
                 obligation.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 2cb2895b476..f423d40b994 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -114,8 +114,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             BuiltinUnsizeCandidate => {
-                let data = self.confirm_builtin_unsize_candidate(obligation)?;
-                ImplSource::Builtin(data)
+                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)
+                }
             }
 
             TraitUpcastingUnsizeCandidate(idx) => {
@@ -1000,15 +1012,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn confirm_builtin_unsize_candidate(
         &mut self,
         obligation: &PolyTraitObligation<'tcx>,
+        source: Ty<'tcx>,
+        target: Ty<'tcx>,
     ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'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");
 
         let mut nested = vec![];