about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/solve/mod.rs
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2023-11-09 11:06:48 +0100
committerlcnr <rust@lcnr.de>2023-11-09 11:32:50 +0100
commite3850f404dfdc4805f0e2b863117ff4563d5f00e (patch)
treeeb1c9e8b9116f46a9e4ad67bb241892f08056d3c /compiler/rustc_trait_selection/src/solve/mod.rs
parent1c54494888d79ff17e03a45aeb4d944bfb181ae2 (diff)
downloadrust-e3850f404dfdc4805f0e2b863117ff4563d5f00e.tar.gz
rust-e3850f404dfdc4805f0e2b863117ff4563d5f00e.zip
rework alias-relate to `norm(lhs) == norm(rhs)`
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve/mod.rs')
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs26
1 files changed, 22 insertions, 4 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 17992d72e25..5b44d396379 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -16,13 +16,14 @@
 //! about it on zulip.
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
+use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::query::NoSolution;
 use rustc_middle::infer::canonical::CanonicalVarInfos;
 use rustc_middle::traits::solve::{
     CanonicalResponse, Certainty, ExternalConstraintsData, Goal, IsNormalizesToHack, QueryResult,
     Response,
 };
-use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{
     CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
 };
@@ -299,12 +300,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         ty: Ty<'tcx>,
     ) -> Option<Ty<'tcx>> {
-        self.try_normalize_ty_recur(param_env, 0, ty)
+        self.try_normalize_ty_recur(param_env, DefineOpaqueTypes::Yes, 0, ty)
     }
 
     fn try_normalize_ty_recur(
         &mut self,
         param_env: ty::ParamEnv<'tcx>,
+        define_opaque_types: DefineOpaqueTypes,
         depth: usize,
         ty: Ty<'tcx>,
     ) -> Option<Ty<'tcx>> {
@@ -312,10 +314,26 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             return None;
         }
 
-        let ty::Alias(_, projection_ty) = *ty.kind() else {
+        let ty::Alias(kind, projection_ty) = *ty.kind() else {
             return Some(ty);
         };
 
+        // We do no always define opaque types eagerly to allow non-defining uses in the defining scope.
+        if let (DefineOpaqueTypes::No, ty::AliasKind::Opaque) = (define_opaque_types, kind) {
+            if let Some(def_id) = projection_ty.def_id.as_local() {
+                if self
+                    .unify_existing_opaque_tys(
+                        param_env,
+                        OpaqueTypeKey { def_id, args: projection_ty.args },
+                        self.next_ty_infer(),
+                    )
+                    .is_empty()
+                {
+                    return Some(ty);
+                }
+            }
+        }
+
         // FIXME(@lcnr): If the normalization of the alias adds an inference constraint which
         // causes a previously added goal to fail, then we treat the alias as rigid.
         //
@@ -331,7 +349,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             this.add_goal(normalizes_to_goal);
             this.try_evaluate_added_goals()?;
             let ty = this.resolve_vars_if_possible(normalized_ty);
-            Ok(this.try_normalize_ty_recur(param_env, depth + 1, ty))
+            Ok(this.try_normalize_ty_recur(param_env, define_opaque_types, depth + 1, ty))
         }) {
             Ok(ty) => ty,
             Err(NoSolution) => Some(ty),