Skip to content

Commit

Permalink
Unrolled build for rust-lang#126496
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#126496 - compiler-errors:more-generics, r=lcnr

Make proof tree probing and `Candidate`/`CandidateSource` generic over interner

`<TyCtxt<'tcx>>` is ugly, but will become `<I>` when things actually become generic.

r? lcnr
  • Loading branch information
rust-timer authored Jun 15, 2024
2 parents 92af831 + c2e416c commit e0e05c6
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 143 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,10 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
{
self.resolve_vars_if_possible(value)
}

fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
self.probe(|_| probe())
}
}

/// See the `error_reporting` module for more details.
Expand Down
99 changes: 50 additions & 49 deletions compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
//! Code shared by trait and projection goals for candidate assembly.

use derivative::Derivative;
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::query::NoSolution;
use rustc_middle::bug;
use rustc_middle::traits::solve::inspect::ProbeKind;
use rustc_middle::traits::solve::{
CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult,
};
use rustc_middle::traits::solve::{Certainty, Goal, MaybeCause, QueryResult};
use rustc_middle::traits::BuiltinImplSource;
use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{fast_reject, TypeFoldable};
use rustc_middle::ty::{TypeVisitableExt, Upcast};
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
use std::fmt::Debug;
use rustc_type_ir::solve::{CandidateSource, CanonicalResponse};
use rustc_type_ir::Interner;

use crate::solve::GoalSource;
use crate::solve::{EvalCtxt, SolverMode};
Expand All @@ -26,10 +26,11 @@ pub(super) mod structural_traits;
///
/// It consists of both the `source`, which describes how that goal would be proven,
/// and the `result` when using the given `source`.
#[derive(Debug, Clone)]
pub(super) struct Candidate<'tcx> {
pub(super) source: CandidateSource<'tcx>,
pub(super) result: CanonicalResponse<'tcx>,
#[derive(Derivative)]
#[derivative(Debug(bound = ""), Clone(bound = ""))]
pub(super) struct Candidate<I: Interner> {
pub(super) source: CandidateSource<I>,
pub(super) result: CanonicalResponse<I>,
}

/// Methods used to assemble candidates for either trait or projection goals.
Expand All @@ -50,22 +51,22 @@ pub(super) trait GoalKind<'tcx>:
/// [`EvalCtxt::evaluate_added_goals_and_make_canonical_response`]).
fn probe_and_match_goal_against_assumption(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
source: CandidateSource<'tcx>,
source: CandidateSource<TyCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
assumption: ty::Clause<'tcx>,
then: impl FnOnce(&mut EvalCtxt<'_, InferCtxt<'tcx>>) -> QueryResult<'tcx>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// Consider a clause, which consists of a "assumption" and some "requirements",
/// to satisfy a goal. If the requirements hold, then attempt to satisfy our
/// goal by equating it with the assumption.
fn probe_and_consider_implied_clause(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
parent_source: CandidateSource<'tcx>,
parent_source: CandidateSource<TyCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
assumption: ty::Clause<'tcx>,
requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
) -> Result<Candidate<'tcx>, NoSolution> {
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| {
for (nested_source, goal) in requirements {
ecx.add_goal(nested_source, goal);
Expand All @@ -79,10 +80,10 @@ pub(super) trait GoalKind<'tcx>:
/// since they're not implied by the well-formedness of the object type.
fn probe_and_consider_object_bound_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
source: CandidateSource<'tcx>,
source: CandidateSource<TyCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
assumption: ty::Clause<'tcx>,
) -> Result<Candidate<'tcx>, NoSolution> {
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
let tcx = ecx.interner();
let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
Expand All @@ -105,7 +106,7 @@ pub(super) trait GoalKind<'tcx>:
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
impl_def_id: DefId,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// If the predicate contained an error, we want to avoid emitting unnecessary trait
/// errors but still want to emit errors for other trait goals. We have some special
Expand All @@ -116,7 +117,7 @@ pub(super) trait GoalKind<'tcx>:
fn consider_error_guaranteed_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
guar: ErrorGuaranteed,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// A type implements an `auto trait` if its components do as well.
///
Expand All @@ -125,13 +126,13 @@ pub(super) trait GoalKind<'tcx>:
fn consider_auto_trait_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

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

/// A type is `Sized` if its tail component is `Sized`.
///
Expand All @@ -140,7 +141,7 @@ pub(super) trait GoalKind<'tcx>:
fn consider_builtin_sized_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
///
Expand All @@ -149,50 +150,50 @@ pub(super) trait GoalKind<'tcx>:
fn consider_builtin_copy_clone_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// A type is `PointerLike` if we can compute its layout, and that layout
/// matches the layout of `usize`.
fn consider_builtin_pointer_like_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// A type is a `FnPtr` if it is of `FnPtr` type.
fn consider_builtin_fn_ptr_trait_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// 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<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
kind: ty::ClosureKind,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// An async closure is known to implement the `AsyncFn<A>` family of traits
/// where `A` is given by the signature of the type.
fn consider_builtin_async_fn_trait_candidates(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
kind: ty::ClosureKind,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which
/// is used internally to delay computation for async closures until after
/// upvar analysis is performed in HIR typeck.
fn consider_builtin_async_fn_kind_helper_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

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

/// `Pointee` is always implemented.
///
Expand All @@ -202,63 +203,63 @@ pub(super) trait GoalKind<'tcx>:
fn consider_builtin_pointee_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

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

/// A coroutine (that comes from a `gen` desugaring) is known to implement
/// `Iterator<Item = O>`, where `O` is given by the generator's yield type
/// that was computed during type-checking.
fn consider_builtin_iterator_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// A coroutine (that comes from a `gen` desugaring) is known to implement
/// `FusedIterator`
fn consider_builtin_fused_iterator_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

fn consider_builtin_async_iterator_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// A coroutine (that doesn't come from an `async` or `gen` desugaring) is known to
/// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
/// and return types of the coroutine computed during type-checking.
fn consider_builtin_coroutine_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

fn consider_builtin_discriminant_kind_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

fn consider_builtin_async_destruct_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

fn consider_builtin_destruct_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

fn consider_builtin_transmute_candidate(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Result<Candidate<'tcx>, NoSolution>;
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution>;

/// Consider (possibly several) candidates to upcast or unsize a type to another
/// type, excluding the coercion of a sized type into a `dyn Trait`.
Expand All @@ -270,14 +271,14 @@ pub(super) trait GoalKind<'tcx>:
fn consider_structural_builtin_unsize_candidates(
ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>,
goal: Goal<'tcx, Self>,
) -> Vec<Candidate<'tcx>>;
) -> Vec<Candidate<TyCtxt<'tcx>>>;
}

impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
) -> Vec<Candidate<'tcx>> {
) -> Vec<Candidate<TyCtxt<'tcx>>> {
let Ok(normalized_self_ty) =
self.structurally_normalize_ty(goal.param_env, goal.predicate.self_ty())
else {
Expand Down Expand Up @@ -324,7 +325,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
pub(super) fn forced_ambiguity(
&mut self,
cause: MaybeCause,
) -> Result<Candidate<'tcx>, NoSolution> {
) -> Result<Candidate<TyCtxt<'tcx>>, NoSolution> {
// This may fail if `try_evaluate_added_goals` overflows because it
// fails to reach a fixpoint but ends up getting an error after
// running for some additional step.
Expand All @@ -340,7 +341,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let tcx = self.interner();
let self_ty = goal.predicate.self_ty();
Expand Down Expand Up @@ -456,7 +457,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn assemble_blanket_impl_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let tcx = self.interner();
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
Expand All @@ -479,7 +480,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn assemble_builtin_impl_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let tcx = self.interner();
let trait_def_id = goal.predicate.trait_def_id(tcx);
Expand Down Expand Up @@ -552,7 +553,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn assemble_param_env_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() {
candidates.extend(G::probe_and_consider_implied_clause(
Expand All @@ -569,7 +570,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn assemble_alias_bound_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| {
ecx.assemble_alias_bound_candidates_recur(goal.predicate.self_ty(), goal, candidates);
Expand All @@ -589,7 +590,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
&mut self,
self_ty: Ty<'tcx>,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let (kind, alias_ty) = match *self_ty.kind() {
ty::Bool
Expand Down Expand Up @@ -673,7 +674,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let tcx = self.interner();
if !tcx.trait_def(goal.predicate.trait_def_id(tcx)).implement_via_object {
Expand Down Expand Up @@ -764,7 +765,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let tcx = self.interner();

Expand Down Expand Up @@ -793,7 +794,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
fn discard_impls_shadowed_by_env<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
candidates: &mut Vec<Candidate<TyCtxt<'tcx>>>,
) {
let tcx = self.interner();
let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> =
Expand Down Expand Up @@ -841,7 +842,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
#[instrument(level = "debug", skip(self), ret)]
pub(super) fn merge_candidates(
&mut self,
candidates: Vec<Candidate<'tcx>>,
candidates: Vec<Candidate<TyCtxt<'tcx>>>,
) -> QueryResult<'tcx> {
// First try merging all candidates. This is complete and fully sound.
let responses = candidates.iter().map(|c| c.result).collect::<Vec<_>>();
Expand Down
Loading

0 comments on commit e0e05c6

Please sign in to comment.