Skip to content

Minor tweaks in the new solver #107344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -337,15 +337,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 @@ -378,22 +376,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 @@ -430,6 +428,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