From f3553691a89ffeb9af770051a4f7e7ac0d771406 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 23 Jul 2023 12:30:52 -0700 Subject: [PATCH] Comment stuff in the new solver --- .../src/solve/alias_relate.rs | 20 +++++++++++++- .../src/solve/assembly/structural_traits.rs | 2 ++ .../src/solve/eval_ctxt/canonical.rs | 27 ++++++++++++------- .../src/solve/inherent_projection.rs | 6 +++++ .../rustc_trait_selection/src/solve/mod.rs | 13 ++++++--- .../src/solve/normalize.rs | 3 ++- .../src/solve/opaques.rs | 3 +++ .../src/solve/weak_types.rs | 5 ++++ 8 files changed, 63 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/alias_relate.rs b/compiler/rustc_trait_selection/src/solve/alias_relate.rs index 73362d82306..c46b4df1125 100644 --- a/compiler/rustc_trait_selection/src/solve/alias_relate.rs +++ b/compiler/rustc_trait_selection/src/solve/alias_relate.rs @@ -1,3 +1,15 @@ +//! Implements the `AliasRelate` goal, which is used to unify two aliases in the +//! new solver, which uses "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. use super::{EvalCtxt, SolverMode}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; @@ -115,6 +127,8 @@ fn assemble_normalizes_to_candidate( }) } + // Computes the normalizes-to branch, with side-effects. This must be performed + // in a probe in order to not taint the evaluation context. fn normalizes_to_inner( &mut self, param_env: ty::ParamEnv<'tcx>, @@ -124,9 +138,13 @@ fn normalizes_to_inner( invert: Invert, ) -> Result<(), NoSolution> { let other = match direction { - // This is purely an optimization. + // This is purely an optimization. No need to instantiate a new + // infer var and equate the RHS to it. ty::AliasRelationDirection::Equate => other, + // Instantiate an infer var and subtype our RHS to it, so that we + // properly represent a subtype relation between the LHS and RHS + // of the goal. ty::AliasRelationDirection::Subtype => { let fresh = self.next_term_infer_of_kind(other); let (sub, sup) = match invert { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index a8ba98bef6d..a2db35e069e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -1,3 +1,5 @@ +//! Code which is used by built-in goals that match "structurally", such a auto +//! traits, `Copy`/`Clone`. use rustc_data_structures::fx::FxHashMap; use rustc_hir::{def_id::DefId, Movability, Mutability}; use rustc_infer::traits::query::NoSolution; diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 9f58e66d04e..7323b98b8ce 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -1,13 +1,13 @@ -/// Canonicalization is used to separate some goal from its context, -/// throwing away unnecessary information in the process. -/// -/// This is necessary to cache goals containing inference variables -/// and placeholders without restricting them to the current `InferCtxt`. -/// -/// Canonicalization is fairly involved, for more details see the relevant -/// section of the [rustc-dev-guide][c]. -/// -/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html +//! Canonicalization is used to separate some goal from its context, +//! throwing away unnecessary information in the process. +//! +//! This is necessary to cache goals containing inference variables +//! and placeholders without restricting them to the current `InferCtxt`. +//! +//! Canonicalization is fairly involved, for more details see the relevant +//! section of the [rustc-dev-guide][c]. +//! +//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html use super::{CanonicalInput, Certainty, EvalCtxt, Goal}; use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer}; use crate::solve::{CanonicalResponse, QueryResult, Response}; @@ -135,6 +135,13 @@ pub(in crate::solve) fn make_ambiguous_response_no_constraints( ) } + /// Computes the region constraints and *new* opaque types registered when + /// proving a goal. + /// + /// If an opaque was already constrained before proving this goal, then the + /// external constraints do not need to record that opaque, since if it is + /// further constrained by inference, that will be passed back in the var + /// values. #[instrument(level = "debug", skip(self), ret)] fn compute_external_query_constraints(&self) -> Result, NoSolution> { // We only check for leaks from universes which were entered inside diff --git a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs index d10a14ff742..28fe59b7f6a 100644 --- a/compiler/rustc_trait_selection/src/solve/inherent_projection.rs +++ b/compiler/rustc_trait_selection/src/solve/inherent_projection.rs @@ -1,3 +1,9 @@ +//! Computes a normalizes-to (projection) goal for inherent associated types, +//! `#![feature(inherent_associated_type)]`. Since astconv already determines +//! which impl the IAT is being projected from, we just: +//! 1. instantiate substs, +//! 2. equate the self type, and +//! 3. instantiate and register where clauses. use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; use rustc_middle::ty; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 7c15c3c0e8b..cc59dd5df03 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -1,14 +1,19 @@ -//! The new trait solver, currently still WIP. +//! The next-generation trait solver, currently still WIP. //! -//! As a user of the trait system, you can use `TyCtxt::evaluate_goal` to -//! interact with this solver. +//! As a user of rust, you can use `-Ztrait-solver=next` or `next-coherence` +//! to enable the new trait solver always, or just within coherence, respectively. +//! +//! As a developer of rustc, you probably shouldn't be using the new trait +//! solver without asking the trait-system-refactor-initiative, but it can +//! be enabled with `InferCtxtBuilder::with_next_trait_solver`. This will +//! ensure that trait solving using that inference context will be routed +//! to the new trait solver. //! //! For a high-level overview of how this solver works, check out the relevant //! section of the rustc-dev-guide. //! //! FIXME(@lcnr): Write that section. If you read this before then ask me //! about it on zulip. - use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_infer::traits::query::NoSolution; diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index f51f4edb933..0e5b137c5de 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -28,7 +28,8 @@ pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable>>( /// its input to be already fully resolved. /// /// Additionally takes a list of universes which represents the binders which have been -/// entered before passing `value` to the function. +/// entered before passing `value` to the function. This is currently needed for +/// `normalize_erasing_regions`, which skips binders as it walks through a type. pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable>>( at: At<'_, 'tcx>, value: T, diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs index 2e537d1c358..f08adc0208b 100644 --- a/compiler/rustc_trait_selection/src/solve/opaques.rs +++ b/compiler/rustc_trait_selection/src/solve/opaques.rs @@ -1,3 +1,6 @@ +//! Computes a normalizes-to (projection) goal for opaque types. This goal +//! behaves differently depending on the param-env's reveal mode and whether +//! the opaque is in a defining scope. use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; use rustc_middle::traits::Reveal; diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs index c7717879a4a..fea634a2ad2 100644 --- a/compiler/rustc_trait_selection/src/solve/weak_types.rs +++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs @@ -1,3 +1,8 @@ +//! Computes a normalizes-to (projection) goal for inherent associated types, +//! `#![feature(lazy_type_alias)]` and `#![feature(type_alias_impl_trait)]`. +//! +//! Since a weak alias is not ambiguous, this just computes the `type_of` of +//! the alias and registers any where-clause predicates on the type alias. use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; use rustc_middle::ty;