Rollup merge of #107344 - compiler-errors:new-solver-tweaks, r=lcnr
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``
This commit is contained in:
commit
ab769a0bac
4 changed files with 54 additions and 23 deletions
|
@ -1,6 +1,8 @@
|
||||||
//! Code shared by trait and projection goals for candidate assembly.
|
//! Code shared by trait and projection goals for candidate assembly.
|
||||||
|
|
||||||
use super::infcx_ext::InferCtxtExt;
|
use super::infcx_ext::InferCtxtExt;
|
||||||
|
#[cfg(doc)]
|
||||||
|
use super::trait_goals::structural_traits::*;
|
||||||
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
|
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal, QueryResult};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
|
@ -98,52 +100,75 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
|
||||||
assumption: ty::Predicate<'tcx>,
|
assumption: ty::Predicate<'tcx>,
|
||||||
) -> QueryResult<'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(
|
fn consider_auto_trait_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> QueryResult<'tcx>;
|
||||||
|
|
||||||
|
// A trait alias holds if the RHS traits and `where` clauses hold.
|
||||||
fn consider_trait_alias_candidate(
|
fn consider_trait_alias_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> 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(
|
fn consider_builtin_sized_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> 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(
|
fn consider_builtin_copy_clone_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> 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(
|
fn consider_builtin_pointer_sized_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> 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(
|
fn consider_builtin_fn_trait_candidates(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
kind: ty::ClosureKind,
|
kind: ty::ClosureKind,
|
||||||
) -> QueryResult<'tcx>;
|
) -> QueryResult<'tcx>;
|
||||||
|
|
||||||
|
// `Tuple` is implemented if the `Self` type is a tuple.
|
||||||
fn consider_builtin_tuple_candidate(
|
fn consider_builtin_tuple_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> 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(
|
fn consider_builtin_pointee_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> 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(
|
fn consider_builtin_future_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
) -> QueryResult<'tcx>;
|
) -> 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(
|
fn consider_builtin_generator_candidate(
|
||||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
|
|
|
@ -335,7 +335,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
// That won't actually reflect in the query response, so it seems moot.
|
// That won't actually reflect in the query response, so it seems moot.
|
||||||
self.make_canonical_response(Certainty::AMBIGUOUS)
|
self.make_canonical_response(Certainty::AMBIGUOUS)
|
||||||
} else {
|
} else {
|
||||||
self.infcx.probe(|_| {
|
|
||||||
let InferOk { value: (), obligations } = self
|
let InferOk { value: (), obligations } = self
|
||||||
.infcx
|
.infcx
|
||||||
.at(&ObligationCause::dummy(), goal.param_env)
|
.at(&ObligationCause::dummy(), goal.param_env)
|
||||||
|
@ -343,7 +342,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
self.evaluate_all_and_make_canonical_response(
|
self.evaluate_all_and_make_canonical_response(
|
||||||
obligations.into_iter().map(|pred| pred.into()).collect(),
|
obligations.into_iter().map(|pred| pred.into()).collect(),
|
||||||
)
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +374,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, ty::GenericArg<'tcx>>,
|
goal: Goal<'tcx, ty::GenericArg<'tcx>>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
self.infcx.probe(|_| {
|
|
||||||
match crate::traits::wf::unnormalized_obligations(
|
match crate::traits::wf::unnormalized_obligations(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
|
@ -387,11 +384,12 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
),
|
),
|
||||||
None => self.make_canonical_response(Certainty::AMBIGUOUS),
|
None => self.make_canonical_response(Certainty::AMBIGUOUS),
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
|
// Recursively evaluates a list of goals to completion, returning the certainty
|
||||||
|
// of all of the goals.
|
||||||
fn evaluate_all(
|
fn evaluate_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
mut goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||||
|
@ -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(
|
fn evaluate_all_and_make_canonical_response(
|
||||||
&mut self,
|
&mut self,
|
||||||
goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||||
|
|
|
@ -296,7 +296,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
assumption: ty::Predicate<'tcx>,
|
assumption: ty::Predicate<'tcx>,
|
||||||
) -> QueryResult<'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(|_| {
|
ecx.infcx.probe(|_| {
|
||||||
let assumption_projection_pred =
|
let assumption_projection_pred =
|
||||||
ecx.infcx.instantiate_bound_vars_with_infer(poly_projection_pred);
|
ecx.infcx.instantiate_bound_vars_with_infer(poly_projection_pred);
|
||||||
|
|
|
@ -65,7 +65,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||||
goal: Goal<'tcx, Self>,
|
goal: Goal<'tcx, Self>,
|
||||||
assumption: ty::Predicate<'tcx>,
|
assumption: ty::Predicate<'tcx>,
|
||||||
) -> QueryResult<'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
|
// FIXME: Constness and polarity
|
||||||
ecx.infcx.probe(|_| {
|
ecx.infcx.probe(|_| {
|
||||||
let assumption_trait_pred =
|
let assumption_trait_pred =
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue