about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-11 03:02:39 +0100
committerGitHub <noreply@github.com>2024-01-11 03:02:39 +0100
commit859874f3eb7d46f9ca7bebb7c5c9fd04e729e43a (patch)
tree01f5731308697f34fa5cd1cb64dc79dda3cd5c0a
parent3cc4e02519bb4cca28bbde9762472a707021803c (diff)
parent427c55c65c16225227ef289358a3c44e755e503b (diff)
downloadrust-859874f3eb7d46f9ca7bebb7c5c9fd04e729e43a.tar.gz
rust-859874f3eb7d46f9ca7bebb7c5c9fd04e729e43a.zip
Rollup merge of #118915 - compiler-errors:alias-nits, r=lcnr
Add some comments, add `can_define_opaque_ty` check to `try_normalize_ty_recur`

Follow-up from #117278, since I was recently re-reviewing this code.
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs6
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs9
-rw-r--r--compiler/rustc_lint/src/types.rs3
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs6
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs14
-rw-r--r--compiler/rustc_trait_selection/src/solve/alias_relate.rs35
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs33
8 files changed, 65 insertions, 45 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index f1e712d814a..6606be2f9f4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -315,7 +315,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
             let mut failed = false;
 
             let elaborated_args = std::iter::zip(*args, &generics.params).map(|(arg, param)| {
-                if let Some(ty::Dynamic(obj, _, ty::DynKind::Dyn)) = arg.as_type().map(Ty::kind) {
+                if let Some(ty::Dynamic(obj, _, ty::Dyn)) = arg.as_type().map(Ty::kind) {
                     let default = tcx.object_lifetime_default(param.def_id);
 
                     let re_static = tcx.lifetimes.re_static;
@@ -339,7 +339,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
 
                     has_dyn = true;
 
-                    Ty::new_dynamic(tcx, obj, implied_region, ty::DynKind::Dyn).into()
+                    Ty::new_dynamic(tcx, obj, implied_region, ty::Dyn).into()
                 } else {
                     arg
                 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index b81cc6edaf2..875e94fcd9f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2348,11 +2348,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             GenericKind::Param(ref p) => format!("the parameter type `{p}`"),
             GenericKind::Placeholder(ref p) => format!("the placeholder type `{p:?}`"),
             GenericKind::Alias(ref p) => match p.kind(self.tcx) {
-                ty::AliasKind::Projection | ty::AliasKind::Inherent => {
+                ty::Projection | ty::Inherent => {
                     format!("the associated type `{p}`")
                 }
-                ty::AliasKind::Weak => format!("the type alias `{p}`"),
-                ty::AliasKind::Opaque => format!("the opaque type `{p}`"),
+                ty::Weak => format!("the type alias `{p}`"),
+                ty::Opaque => format!("the opaque type `{p}`"),
             },
         };
 
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 6634b192811..4b254fc7df5 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -510,7 +510,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
                 ));
             } else {
                 match a_ty.kind() {
-                    &ty::Alias(ty::AliasKind::Projection, data) => {
+                    &ty::Alias(ty::Projection, data) => {
                         // FIXME: This does not handle subtyping correctly, we could
                         // instead create a new inference variable for `a_ty`, emitting
                         // `Projection(a_ty, a_infer)` and `a_infer <: b_ty`.
@@ -522,10 +522,9 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
                         ))
                     }
                     // The old solver only accepts projection predicates for associated types.
-                    ty::Alias(
-                        ty::AliasKind::Inherent | ty::AliasKind::Weak | ty::AliasKind::Opaque,
-                        _,
-                    ) => return Err(TypeError::CyclicTy(a_ty)),
+                    ty::Alias(ty::Inherent | ty::Weak | ty::Opaque, _) => {
+                        return Err(TypeError::CyclicTy(a_ty));
+                    }
                     _ => bug!("generalizated `{a_ty:?} to infer, not an alias"),
                 }
             }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 6dade43a183..a86fe2db2b2 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -29,7 +29,6 @@ use rustc_span::{Span, Symbol};
 use rustc_target::abi::{Abi, Size, WrappingRange};
 use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
-use rustc_type_ir::DynKind;
 
 use std::iter;
 use std::ops::ControlFlow;
@@ -675,7 +674,7 @@ fn lint_wide_pointer<'tcx>(
         }
         match ty.kind() {
             ty::RawPtr(TypeAndMut { mutbl: _, ty }) => (!ty.is_sized(cx.tcx, cx.param_env))
-                .then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, DynKind::Dyn)))),
+                .then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))),
             _ => None,
         }
     };
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 38bf39bff90..8cf5fc8013f 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1225,7 +1225,7 @@ impl<'tcx> AliasTy<'tcx> {
 
     /// Whether this alias type is an opaque.
     pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool {
-        matches!(self.opt_kind(tcx), Some(ty::AliasKind::Opaque))
+        matches!(self.opt_kind(tcx), Some(ty::Opaque))
     }
 
     /// FIXME: rename `AliasTy` to `AliasTerm` and always handle
@@ -2745,7 +2745,7 @@ impl<'tcx> Ty<'tcx> {
             // Extern types have metadata = ().
             | ty::Foreign(..)
             // `dyn*` has no metadata
-            | ty::Dynamic(_, _, DynKind::DynStar)
+            | ty::Dynamic(_, _, ty::DynStar)
             // If returned by `struct_tail_without_normalization` this is a unit struct
             // without any fields, or not a struct, and therefore is Sized.
             | ty::Adt(..)
@@ -2754,7 +2754,7 @@ impl<'tcx> Ty<'tcx> {
             | ty::Tuple(..) => (tcx.types.unit, false),
 
             ty::Str | ty::Slice(_) => (tcx.types.usize, false),
-            ty::Dynamic(_, _, DynKind::Dyn) => {
+            ty::Dynamic(_, _, ty::Dyn) => {
                 let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
                 (tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false)
             },
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index f0f1d798d44..c0ecbfb9914 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -12,12 +12,11 @@ use crate::rustc_smir::{alloc, Stable, Tables};
 impl<'tcx> Stable<'tcx> for ty::AliasKind {
     type T = stable_mir::ty::AliasKind;
     fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
-        use rustc_middle::ty::AliasKind::*;
         match self {
-            Projection => stable_mir::ty::AliasKind::Projection,
-            Inherent => stable_mir::ty::AliasKind::Inherent,
-            Opaque => stable_mir::ty::AliasKind::Opaque,
-            Weak => stable_mir::ty::AliasKind::Weak,
+            ty::Projection => stable_mir::ty::AliasKind::Projection,
+            ty::Inherent => stable_mir::ty::AliasKind::Inherent,
+            ty::Opaque => stable_mir::ty::AliasKind::Opaque,
+            ty::Weak => stable_mir::ty::AliasKind::Weak,
         }
     }
 }
@@ -34,10 +33,9 @@ impl<'tcx> Stable<'tcx> for ty::DynKind {
     type T = stable_mir::ty::DynKind;
 
     fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
-        use rustc_middle::ty::DynKind;
         match self {
-            DynKind::Dyn => stable_mir::ty::DynKind::Dyn,
-            DynKind::DynStar => stable_mir::ty::DynKind::DynStar,
+            ty::Dyn => stable_mir::ty::DynKind::Dyn,
+            ty::DynStar => stable_mir::ty::DynKind::DynStar,
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
index 626569fb40f..c05c9961750 100644
--- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs
+++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs
@@ -2,15 +2,29 @@
 //! Doing this via a separate goal is called "deferred alias relation" and part
 //! of our more general approach to "lazy normalization".
 //!
-//! This goal, e.g. `A alias-relate B`, may be satisfied by one of three branches:
-//! * normalizes-to: If `A` is a projection, we can prove the equivalent
-//!   projection predicate with B as the right-hand side of the projection.
-//!   This goal is computed in both directions, if both are aliases.
-//! * subst-relate: Equate `A` and `B` by their substs, if they're both
-//!   aliases with the same def-id.
-//! * bidirectional-normalizes-to: If `A` and `B` are both projections, and both
-//!   may apply, then we can compute the "intersection" of both normalizes-to by
-//!   performing them together. This is used specifically to resolve ambiguities.
+//! This is done by first normalizing both sides of the goal, ending up in
+//! either a concrete type, rigid projection, opaque, or an infer variable.
+//! These are related further according to the rules below:
+//!
+//! (1.) If we end up with a rigid projection and a rigid projection, then we
+//! relate those projections structurally.
+//!
+//! (2.) If we end up with a rigid projection and an alias, then the opaque will
+//! have its hidden type defined to be that rigid projection.
+//!
+//! (3.) If we end up with an opaque and an opaque, then we assemble two
+//! candidates, one defining the LHS to be the hidden type of the RHS, and vice
+//! versa.
+//!
+//! (4.) If we end up with an infer var and an opaque or rigid projection, then
+//! we assign the alias to the infer var.
+//!
+//! (5.) If we end up with an opaque and a rigid (non-projection) type, then we
+//! define the hidden type of the opaque to be the rigid type.
+//!
+//! (6.) Otherwise, if we end with two rigid (non-projection) or infer types,
+//! relate them structurally.
+
 use super::{EvalCtxt, GoalSource};
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::traits::query::NoSolution;
@@ -50,6 +64,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     self.relate(param_env, lhs, variance, rhs)?;
                     self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                 } else if alias.is_opaque(tcx) {
+                    // FIXME: This doesn't account for variance.
                     self.define_opaque(param_env, alias, rhs)
                 } else {
                     Err(NoSolution)
@@ -60,6 +75,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     self.relate(param_env, lhs, variance, rhs)?;
                     self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                 } else if alias.is_opaque(tcx) {
+                    // FIXME: This doesn't account for variance.
                     self.define_opaque(param_env, alias, lhs)
                 } else {
                     Err(NoSolution)
@@ -72,6 +88,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         }
     }
 
+    // FIXME: This needs a name that reflects that it's okay to bottom-out with an inference var.
     /// Normalize the `term` to equate it later. This does not define opaque types.
     #[instrument(level = "debug", skip(self, param_env), ret)]
     fn try_normalize_term(
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 2f3111a2414..7c8f885a1f2 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -22,6 +22,7 @@ use rustc_middle::traits::solve::{
     CanonicalResponse, Certainty, ExternalConstraintsData, Goal, GoalSource, IsNormalizesToHack,
     QueryResult, Response,
 };
+use rustc_middle::traits::Reveal;
 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{
     CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
@@ -316,19 +317,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             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) = alias.def_id.as_local() {
-                if self
-                    .unify_existing_opaque_tys(
-                        param_env,
-                        OpaqueTypeKey { def_id, args: alias.args },
-                        self.next_ty_infer(),
-                    )
-                    .is_empty()
-                {
-                    return Some(ty);
-                }
+        // We do no always define opaque types eagerly to allow non-defining uses
+        // in the defining scope. However, if we can unify this opaque to an existing
+        // opaque, then we should attempt to eagerly reveal the opaque, and we fall
+        // through.
+        if let DefineOpaqueTypes::No = define_opaque_types
+            && let Reveal::UserFacing = param_env.reveal()
+            && let ty::Opaque = kind
+            && let Some(def_id) = alias.def_id.as_local()
+            && self.can_define_opaque_ty(def_id)
+        {
+            if self
+                .unify_existing_opaque_tys(
+                    param_env,
+                    OpaqueTypeKey { def_id, args: alias.args },
+                    self.next_ty_infer(),
+                )
+                .is_empty()
+            {
+                return Some(ty);
             }
         }