Skip to content

Commit

Permalink
Consolidate trait upcasting and unsize into one normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jul 25, 2023
1 parent c02d1a6 commit de81007
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 197 deletions.
25 changes: 10 additions & 15 deletions compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub(super) enum CandidateSource {
#[derive(Debug, Clone, Copy)]
pub(super) enum BuiltinImplSource {
TraitUpcasting,
TupleUnsize,
Object,
Misc,
Ambiguity,
Expand Down Expand Up @@ -281,20 +282,19 @@ pub(super) trait GoalKind<'tcx>:
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

/// Consider (possibly several) goals to upcast or unsize a type to another
/// type.
///
/// The most common forms of unsizing are array to slice, and concrete (Sized)
/// type into a `dyn Trait`. ADTs and Tuples can also have their final field
/// unsized if it's generic.
fn consider_builtin_unsize_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

///
/// `dyn Trait1` can be unsized to `dyn Trait2` if they are the same trait, or
/// if `Trait2` is a (transitive) supertrait of `Trait2`.
fn consider_builtin_dyn_upcast_candidates(
ecx: &mut EvalCtxt<'_, 'tcx>,
fn consider_builtin_unsize_and_upcast_candidates(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> Vec<CanonicalResponse<'tcx>>;
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)>;

fn consider_builtin_discriminant_kind_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
Expand Down Expand Up @@ -610,8 +610,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
G::consider_builtin_future_candidate(self, goal)
} else if lang_items.gen_trait() == Some(trait_def_id) {
G::consider_builtin_generator_candidate(self, goal)
} else if lang_items.unsize_trait() == Some(trait_def_id) {
G::consider_builtin_unsize_candidate(self, goal)
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
G::consider_builtin_discriminant_kind_candidate(self, goal)
} else if lang_items.destruct_trait() == Some(trait_def_id) {
Expand All @@ -633,11 +631,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// There may be multiple unsize candidates for a trait with several supertraits:
// `trait Foo: Bar<A> + Bar<B>` and `dyn Foo: Unsize<dyn Bar<_>>`
if lang_items.unsize_trait() == Some(trait_def_id) {
for result in G::consider_builtin_dyn_upcast_candidates(self, goal) {
candidates.push(Candidate {
source: CandidateSource::BuiltinImpl(BuiltinImplSource::TraitUpcasting),
result,
});
for (result, source) in G::consider_builtin_unsize_and_upcast_candidates(self, goal) {
candidates.push(Candidate { source: CandidateSource::BuiltinImpl(source), result });
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,19 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> {
),
) => rematch_object(self, goal, nested_obligations),

(Certainty::Maybe(_), CandidateSource::BuiltinImpl(BuiltinImplSource::Misc))
(
Certainty::Maybe(_),
CandidateSource::BuiltinImpl(
BuiltinImplSource::Misc | BuiltinImplSource::TupleUnsize,
),
) if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => {
rematch_unsize(self, goal, nested_obligations)
}

(Certainty::Yes, CandidateSource::BuiltinImpl(BuiltinImplSource::TupleUnsize))
if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) =>
{
rematch_unsize(self, goal, nested_obligations)
Ok(Some(ImplSource::TupleUnsizing(nested_obligations)))
}

// Technically some builtin impls have nested obligations, but if
Expand Down
13 changes: 3 additions & 10 deletions compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::traits::specialization_graph;

use super::assembly::{self, structural_traits};
use super::assembly::{self, structural_traits, BuiltinImplSource};
use super::EvalCtxt;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
Expand Down Expand Up @@ -502,17 +502,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
)
}

fn consider_builtin_unsize_candidate(
fn consider_builtin_unsize_and_upcast_candidates(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
bug!("`Unsize` does not have an associated type: {:?}", goal);
}

fn consider_builtin_dyn_upcast_candidates(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> Vec<CanonicalResponse<'tcx>> {
) -> Vec<(CanonicalResponse<'tcx>, BuiltinImplSource)> {
bug!("`Unsize` does not have an associated type: {:?}", goal);
}

Expand Down
Loading

0 comments on commit de81007

Please sign in to comment.