Skip to content

Commit

Permalink
Rollup merge of #107344 - compiler-errors:new-solver-tweaks, r=lcnr
Browse files Browse the repository at this point in the history
Minor tweaks in the new solver

1. `InferCtxt::probe` is not needed in `compute_subtype_goal` and `compute_well_formed_goal`.
2. Add a handful of comments.
3. Add a micro-optimization in `consider_assumption` where we check the def-ids of the assumption and goal match before instantiating any binders.

r? ``@lcnr``
  • Loading branch information
matthiaskrgr authored Jan 28, 2023
2 parents a5caa98 + 8a0b215 commit ab769a0
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 23 deletions.
25 changes: 25 additions & 0 deletions compiler/rustc_trait_selection/src/solve/assembly.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Code shared by trait and projection goals for candidate assembly.

use super::infcx_ext::InferCtxtExt;
#[cfg(doc)]
use super::trait_goals::structural_traits::*;
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
Expand Down Expand Up @@ -98,52 +100,75 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
assumption: ty::Predicate<'tcx>,
) -> QueryResult<'tcx>;

// A type implements an `auto trait` if its components do as well. These components
// are given by built-in rules from [`instantiate_constituent_tys_for_auto_trait`].
fn consider_auto_trait_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// A trait alias holds if the RHS traits and `where` clauses hold.
fn consider_trait_alias_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// A type is `Copy` or `Clone` if its components are `Sized`. These components
// are given by built-in rules from [`instantiate_constituent_tys_for_sized_trait`].
fn consider_builtin_sized_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`. These
// components are given by built-in rules from [`instantiate_constituent_tys_for_copy_clone_trait`].
fn consider_builtin_copy_clone_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// A type is `PointerSized` if we can compute its layout, and that layout
// matches the layout of `usize`.
fn consider_builtin_pointer_sized_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// A callable type (a closure, fn def, or fn ptr) is known to implement the `Fn<A>`
// family of traits where `A` is given by the signature of the type.
fn consider_builtin_fn_trait_candidates(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
kind: ty::ClosureKind,
) -> QueryResult<'tcx>;

// `Tuple` is implemented if the `Self` type is a tuple.
fn consider_builtin_tuple_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// `Pointee` is always implemented.
//
// See the projection implementation for the `Metadata` types for all of
// the built-in types. For structs, the metadata type is given by the struct
// tail.
fn consider_builtin_pointee_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// A generator (that comes from an `async` desugaring) is known to implement
// `Future<Output = O>`, where `O` is given by the generator's return type
// that was computed during type-checking.
fn consider_builtin_future_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

// A generator (that doesn't come from an `async` desugaring) is known to
// implement `Generator<R, Yield = Y, Return = O>`, given the resume, yield,
// and return types of the generator computed during type-checking.
fn consider_builtin_generator_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
Expand Down
44 changes: 23 additions & 21 deletions compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,15 +335,13 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
// That won't actually reflect in the query response, so it seems moot.
self.make_canonical_response(Certainty::AMBIGUOUS)
} else {
self.infcx.probe(|_| {
let InferOk { value: (), obligations } = self
.infcx
.at(&ObligationCause::dummy(), goal.param_env)
.sub(goal.predicate.a, goal.predicate.b)?;
self.evaluate_all_and_make_canonical_response(
obligations.into_iter().map(|pred| pred.into()).collect(),
)
})
let InferOk { value: (), obligations } = self
.infcx
.at(&ObligationCause::dummy(), goal.param_env)
.sub(goal.predicate.a, goal.predicate.b)?;
self.evaluate_all_and_make_canonical_response(
obligations.into_iter().map(|pred| pred.into()).collect(),
)
}
}

Expand Down Expand Up @@ -376,22 +374,22 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
&mut self,
goal: Goal<'tcx, ty::GenericArg<'tcx>>,
) -> QueryResult<'tcx> {
self.infcx.probe(|_| {
match crate::traits::wf::unnormalized_obligations(
self.infcx,
goal.param_env,
goal.predicate,
) {
Some(obligations) => self.evaluate_all_and_make_canonical_response(
obligations.into_iter().map(|o| o.into()).collect(),
),
None => self.make_canonical_response(Certainty::AMBIGUOUS),
}
})
match crate::traits::wf::unnormalized_obligations(
self.infcx,
goal.param_env,
goal.predicate,
) {
Some(obligations) => self.evaluate_all_and_make_canonical_response(
obligations.into_iter().map(|o| o.into()).collect(),
),
None => self.make_canonical_response(Certainty::AMBIGUOUS),
}
}
}

impl<'tcx> EvalCtxt<'_, 'tcx> {
// Recursively evaluates a list of goals to completion, returning the certainty
// of all of the goals.
fn evaluate_all(
&mut self,
mut goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
Expand Down Expand Up @@ -428,6 +426,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
})
}

// Recursively evaluates a list of goals to completion, making a query response.
//
// This is just a convenient way of calling [`EvalCtxt::evaluate_all`],
// then [`EvalCtxt::make_canonical_response`].
fn evaluate_all_and_make_canonical_response(
&mut self,
goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
goal: Goal<'tcx, Self>,
assumption: ty::Predicate<'tcx>,
) -> QueryResult<'tcx> {
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred() {
if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred()
&& poly_projection_pred.projection_def_id() == goal.predicate.def_id()
{
ecx.infcx.probe(|_| {
let assumption_projection_pred =
ecx.infcx.instantiate_bound_vars_with_infer(poly_projection_pred);
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
goal: Goal<'tcx, Self>,
assumption: ty::Predicate<'tcx>,
) -> QueryResult<'tcx> {
if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() {
if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
&& poly_trait_pred.def_id() == goal.predicate.def_id()
{
// FIXME: Constness and polarity
ecx.infcx.probe(|_| {
let assumption_trait_pred =
Expand Down

0 comments on commit ab769a0

Please sign in to comment.