about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-02-12 13:30:30 -0800
committerMichael Goulet <michael@errs.io>2022-02-14 20:01:52 -0800
commit879e4f8131b71050b00407befd6f1669389fe9ed (patch)
tree2dfeb88034a1045b9c8effa799a209088751a23e
parent784c7a6cadf218b518734c4f21690334401ff83a (diff)
downloadrust-879e4f8131b71050b00407befd6f1669389fe9ed.tar.gz
rust-879e4f8131b71050b00407befd6f1669389fe9ed.zip
use an enum in matches_projection_projection
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs37
2 files changed, 28 insertions, 16 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a8d15d98eea..584e412b8a2 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -19,6 +19,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
 use crate::traits::error_reporting::InferCtxtExt as _;
+use crate::traits::select::ProjectionMatchesProjection;
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorReported;
@@ -1248,7 +1249,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
             });
 
             match is_match {
-                Some(true) => {
+                ProjectionMatchesProjection::Yes => {
                     candidate_set.push_candidate(ctor(data));
 
                     if potentially_unnormalized_candidates
@@ -1260,10 +1261,10 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
                         return;
                     }
                 }
-                Some(false) => {}
-                None => {
+                ProjectionMatchesProjection::Ambiguous => {
                     candidate_set.mark_ambiguous();
                 }
+                ProjectionMatchesProjection::No => {}
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4ca60a65485..2f85417a5b6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1508,15 +1508,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })
     }
 
-    /// Return Some(true) if the obligation's predicate type applies to the env_predicate, and
-    /// Some(false) if it does not. Returns None in the case that the projection type is a GAT,
+    /// Return `Yes` if the obligation's predicate type applies to the env_predicate, and
+    /// `No` if it does not. Return `Ambiguous` in the case that the projection type is a GAT,
     /// and applying this env_predicate constrains any of the obligation's GAT substitutions.
+    ///
+    /// This behavior is a somewhat of a hack to prevent overconstraining inference variables
+    /// in cases like #91762.
     pub(super) fn match_projection_projections(
         &mut self,
         obligation: &ProjectionTyObligation<'tcx>,
         env_predicate: PolyProjectionPredicate<'tcx>,
         potentially_unnormalized_candidates: bool,
-    ) -> Option<bool> {
+    ) -> ProjectionMatchesProjection {
         let mut nested_obligations = Vec::new();
         let (infer_predicate, _) = self.infcx.replace_bound_vars_with_fresh_vars(
             obligation.cause.span,
@@ -1553,20 +1556,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         if is_match {
             let generics = self.tcx().generics_of(obligation.predicate.item_def_id);
-            if !generics.params.is_empty() {
-                // If any of the obligation's predicate substs shallow-resolve to
-                // something new, that means that we must have newly inferred something
-                // about the GAT. We should give up with ambiguity in that case.
-                if obligation.predicate.substs[generics.parent_count..]
+            // FIXME(generic-associated-types): Addresses aggressive inference in #92917.
+            // If this type is a GAT, and of the GAT substs resolve to something new,
+            // that means that we must have newly inferred something about the GAT.
+            // We should give up in that case.
+            if !generics.params.is_empty()
+                && obligation.predicate.substs[generics.parent_count..]
                     .iter()
                     .any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p)
-                {
-                    return None;
-                }
+            {
+                ProjectionMatchesProjection::Ambiguous
+            } else {
+                ProjectionMatchesProjection::Yes
             }
+        } else {
+            ProjectionMatchesProjection::No
         }
-
-        Some(is_match)
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -2766,3 +2771,9 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
         write!(f, "TraitObligationStack({:?})", self.obligation)
     }
 }
+
+pub enum ProjectionMatchesProjection {
+    Yes,
+    Ambiguous,
+    No,
+}