]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_traits/src/implied_outlives_bounds.rs
Auto merge of #92268 - jswrenn:transmute, r=oli-obk
[rust.git] / compiler / rustc_traits / src / implied_outlives_bounds.rs
index 965324113d526edaa2b1c49adbbd601b0ae3c75d..4d4d55de5f45791f9bb3e864aa63f513c4e936f4 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_infer::traits::query::OutlivesBound;
 use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
@@ -44,9 +44,10 @@ fn compute_implied_outlives_bounds<'tcx>(
 
     // Sometimes when we ask what it takes for T: WF, we get back that
     // U: WF is required; in that case, we push U onto this stack and
-    // process it next. Currently (at least) these resulting
-    // predicates are always guaranteed to be a subset of the original
-    // type, so we need not fear non-termination.
+    // process it next. Because the resulting predicates aren't always
+    // guaranteed to be a subset of the original type, so we need to store the
+    // WF args we've computed in a set.
+    let mut checked_wf_args = rustc_data_structures::fx::FxHashSet::default();
     let mut wf_args = vec![ty.into()];
 
     let mut implied_bounds = vec![];
@@ -54,6 +55,10 @@ fn compute_implied_outlives_bounds<'tcx>(
     let mut fulfill_cx = FulfillmentContext::new();
 
     while let Some(arg) = wf_args.pop() {
+        if !checked_wf_args.insert(arg) {
+            continue;
+        }
+
         // Compute the obligations for `arg` to be well-formed. If `arg` is
         // an unresolved inference variable, just substituted an empty set
         // -- because the return type here is going to be things we *add*