about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs74
1 files changed, 43 insertions, 31 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 54b6c22b2d8..47bccb9588e 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -15,12 +15,13 @@ use tracing::{debug, instrument, trace};
 
 use crate::infer::InferCtxt;
 use crate::traits;
+
 /// Returns the set of obligations needed to make `arg` well-formed.
 /// If `arg` contains unresolved inference variables, this may include
 /// further WF obligations. However, if `arg` IS an unresolved
 /// inference variable, returns `None`, because we are not able to
-/// make any progress at all. This is to prevent "livelock" where we
-/// say "$0 is WF if $0 is WF".
+/// make any progress at all. This is to prevent cycles where we
+/// say "?0 is WF if ?0 is WF".
 pub fn obligations<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -29,14 +30,14 @@ pub fn obligations<'tcx>(
     arg: GenericArg<'tcx>,
     span: Span,
 ) -> Option<PredicateObligations<'tcx>> {
-    // Handle the "livelock" case (see comment above) by bailing out if necessary.
+    // Handle the "cycle" case (see comment above) by bailing out if necessary.
     let arg = match arg.unpack() {
         GenericArgKind::Type(ty) => {
             match ty.kind() {
                 ty::Infer(ty::TyVar(_)) => {
                     let resolved_ty = infcx.shallow_resolve(ty);
                     if resolved_ty == ty {
-                        // No progress, bail out to prevent "livelock".
+                        // No progress, bail out to prevent cycles.
                         return None;
                     } else {
                         resolved_ty
@@ -51,7 +52,7 @@ pub fn obligations<'tcx>(
                 ty::ConstKind::Infer(_) => {
                     let resolved = infcx.shallow_resolve_const(ct);
                     if resolved == ct {
-                        // No progress.
+                        // No progress, bail out to prevent cycles.
                         return None;
                     } else {
                         resolved
@@ -74,7 +75,7 @@ pub fn obligations<'tcx>(
         recursion_depth,
         item: None,
     };
-    wf.compute(arg);
+    wf.add_wf_preds_for_generic_arg(arg);
     debug!("wf::obligations({:?}, body_id={:?}) = {:?}", arg, body_id, wf.out);
 
     let result = wf.normalize(infcx);
@@ -97,7 +98,7 @@ pub fn unnormalized_obligations<'tcx>(
 
     // However, if `arg` IS an unresolved inference variable, returns `None`,
     // because we are not able to make any progress at all. This is to prevent
-    // "livelock" where we say "$0 is WF if $0 is WF".
+    // cycles where we say "?0 is WF if ?0 is WF".
     if arg.is_non_region_infer() {
         return None;
     }
@@ -115,7 +116,7 @@ pub fn unnormalized_obligations<'tcx>(
         recursion_depth: 0,
         item: None,
     };
-    wf.compute(arg);
+    wf.add_wf_preds_for_generic_arg(arg);
     Some(wf.out)
 }
 
@@ -140,7 +141,7 @@ pub fn trait_obligations<'tcx>(
         recursion_depth: 0,
         item: Some(item),
     };
-    wf.compute_trait_pred(trait_pred, Elaborate::All);
+    wf.add_wf_preds_for_trait_pred(trait_pred, Elaborate::All);
     debug!(obligations = ?wf.out);
     wf.normalize(infcx)
 }
@@ -171,7 +172,7 @@ pub fn clause_obligations<'tcx>(
     // It's ok to skip the binder here because wf code is prepared for it
     match clause.kind().skip_binder() {
         ty::ClauseKind::Trait(t) => {
-            wf.compute_trait_pred(t, Elaborate::None);
+            wf.add_wf_preds_for_trait_pred(t, Elaborate::None);
         }
         ty::ClauseKind::HostEffect(..) => {
             // Technically the well-formedness of this predicate is implied by
@@ -179,22 +180,22 @@ pub fn clause_obligations<'tcx>(
         }
         ty::ClauseKind::RegionOutlives(..) => {}
         ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
-            wf.compute(ty.into());
+            wf.add_wf_preds_for_generic_arg(ty.into());
         }
         ty::ClauseKind::Projection(t) => {
-            wf.compute_alias_term(t.projection_term);
-            wf.compute(t.term.into_arg());
+            wf.add_wf_preds_for_alias_term(t.projection_term);
+            wf.add_wf_preds_for_generic_arg(t.term.into_arg());
         }
         ty::ClauseKind::ConstArgHasType(ct, ty) => {
-            wf.compute(ct.into());
-            wf.compute(ty.into());
+            wf.add_wf_preds_for_generic_arg(ct.into());
+            wf.add_wf_preds_for_generic_arg(ty.into());
         }
         ty::ClauseKind::WellFormed(arg) => {
-            wf.compute(arg);
+            wf.add_wf_preds_for_generic_arg(arg);
         }
 
         ty::ClauseKind::ConstEvaluatable(ct) => {
-            wf.compute(ct.into());
+            wf.add_wf_preds_for_generic_arg(ct.into());
         }
     }
 
@@ -372,14 +373,18 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
     }
 
     /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
-    fn compute_trait_pred(&mut self, trait_pred: ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
+    fn add_wf_preds_for_trait_pred(
+        &mut self,
+        trait_pred: ty::TraitPredicate<'tcx>,
+        elaborate: Elaborate,
+    ) {
         let tcx = self.tcx();
         let trait_ref = trait_pred.trait_ref;
 
         // Negative trait predicates don't require supertraits to hold, just
         // that their args are WF.
         if trait_pred.polarity == ty::PredicatePolarity::Negative {
-            self.compute_negative_trait_pred(trait_ref);
+            self.add_wf_preds_for_negative_trait_pred(trait_ref);
             return;
         }
 
@@ -445,15 +450,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
     // Compute the obligations that are required for `trait_ref` to be WF,
     // given that it is a *negative* trait predicate.
-    fn compute_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
+    fn add_wf_preds_for_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
         for arg in trait_ref.args {
-            self.compute(arg);
+            self.add_wf_preds_for_generic_arg(arg);
         }
     }
 
     /// Pushes the obligations required for an alias (except inherent) to be WF
     /// into `self.out`.
-    fn compute_alias_term(&mut self, data: ty::AliasTerm<'tcx>) {
+    fn add_wf_preds_for_alias_term(&mut self, data: ty::AliasTerm<'tcx>) {
         // A projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -478,13 +483,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         let obligations = self.nominal_obligations(data.def_id, data.args);
         self.out.extend(obligations);
 
-        self.compute_projection_args(data.args);
+        self.add_wf_preds_for_projection_args(data.args);
     }
 
     /// Pushes the obligations required for an inherent alias to be WF
     /// into `self.out`.
     // FIXME(inherent_associated_types): Merge this function with `fn compute_alias`.
-    fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
+    fn add_wf_preds_for_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) {
         // An inherent projection is well-formed if
         //
         // (a) its predicates hold (*)
@@ -511,7 +516,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
         data.args.visit_with(self);
     }
 
-    fn compute_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
+    fn add_wf_preds_for_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
         let tcx = self.tcx();
         let cause = self.cause(ObligationCauseCode::WellFormed(None));
         let param_env = self.param_env;
@@ -557,7 +562,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
 
     /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
     #[instrument(level = "debug", skip(self))]
-    fn compute(&mut self, arg: GenericArg<'tcx>) {
+    fn add_wf_preds_for_generic_arg(&mut self, arg: GenericArg<'tcx>) {
         arg.visit_with(self);
         debug!(?self.out);
     }
@@ -596,7 +601,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
             .collect()
     }
 
-    fn from_object_ty(
+    fn add_wf_preds_for_dyn_ty(
         &mut self,
         ty: Ty<'tcx>,
         data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
@@ -651,6 +656,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                     outlives,
                 ));
             }
+
+            // We don't add any wf predicates corresponding to the trait ref's generic arguments
+            // which allows code like this to compile:
+            // ```rust
+            // trait Trait<T: Sized> {}
+            // fn foo(_: &dyn Trait<[u32]>) {}
+            // ```
         }
     }
 }
@@ -761,7 +773,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 self.out.extend(obligations);
             }
             ty::Alias(ty::Inherent, data) => {
-                self.compute_inherent_projection(data);
+                self.add_wf_preds_for_inherent_projection(data);
                 return; // Subtree handled by compute_inherent_projection.
             }
 
@@ -895,7 +907,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 //
                 // Here, we defer WF checking due to higher-ranked
                 // regions. This is perhaps not ideal.
-                self.from_object_ty(t, data, r);
+                self.add_wf_preds_for_dyn_ty(t, data, r);
 
                 // FIXME(#27579) RFC also considers adding trait
                 // obligations that don't refer to Self and
@@ -917,11 +929,11 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
             // 1. Check if they have been resolved, and if so proceed with
             //    THAT type.
             // 2. If not, we've at least simplified things (e.g., we went
-            //    from `Vec<$0>: WF` to `$0: WF`), so we can
+            //    from `Vec?0>: WF` to `?0: WF`), so we can
             //    register a pending obligation and keep
             //    moving. (Goal is that an "inductive hypothesis"
             //    is satisfied to ensure termination.)
-            // See also the comment on `fn obligations`, describing "livelock"
+            // See also the comment on `fn obligations`, describing cycle
             // prevention, which happens before this can be reached.
             ty::Infer(_) => {
                 let cause = self.cause(ObligationCauseCode::WellFormed(None));