Skip to content
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

Implement unsizing in the new trait solver #107245

Merged
merged 3 commits into from
Jan 31, 2023
Merged
Changes from 1 commit
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
Prev Previous commit
nits
  • Loading branch information
compiler-errors committed Jan 30, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit f7fc0b712103d8832b305efa72e4c9851161bbdf
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/solve/assembly.rs
Original file line number Diff line number Diff line change
@@ -184,7 +184,7 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {

// `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_unsize_candidates(
fn consider_builtin_dyn_upcast_candidates(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> Vec<CanonicalResponse<'tcx>>;
@@ -334,7 +334,7 @@ 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_unsize_candidates(self, goal) {
for result in G::consider_builtin_dyn_upcast_candidates(self, goal) {
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result });
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
@@ -562,7 +562,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
bug!("`Unsize` does not have an associated type: {:?}", goal);
}

fn consider_builtin_dyn_unsize_candidates(
fn consider_builtin_dyn_upcast_candidates(
_ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> Vec<super::CanonicalResponse<'tcx>> {
26 changes: 13 additions & 13 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
@@ -262,11 +262,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// `T` -> `dyn Trait` unsizing
(_, &ty::Dynamic(data, region, ty::Dyn)) => {
// Can only unsize to an object-safe type
// FIXME: Can auto traits be *not* object safe?
if data
.auto_traits()
.chain(data.principal_def_id())
.any(|def_id| !tcx.is_object_safe(def_id))
.principal_def_id()
.map_or(false, |def_id| !tcx.check_is_object_safe(def_id))
{
return Err(NoSolution);
}
@@ -365,7 +363,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
})
}

fn consider_builtin_dyn_unsize_candidates(
fn consider_builtin_dyn_upcast_candidates(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> Vec<CanonicalResponse<'tcx>> {
@@ -387,9 +385,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
return vec![];
}

let mut responses = vec![];
let mut unsize_dyn_to_principal = |principal: Option<ty::PolyExistentialTraitRef<'tcx>>| {
let _ = ecx.infcx.probe(|_| -> Result<(), NoSolution> {
ecx.infcx.probe(|_| -> Result<_, NoSolution> {
// Require that all of the trait predicates from A match B, except for
// the auto traits. We do this by constructing a new A type with B's
// auto traits, and equating these types.
@@ -414,16 +411,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
goal.with(tcx, ty::Binder::dummy(ty::OutlivesPredicate(a_region, b_region))),
);

responses.push(ecx.evaluate_all_and_make_canonical_response(nested_obligations)?);

Ok(())
});
ecx.evaluate_all_and_make_canonical_response(nested_obligations)
})
};

let mut responses = vec![];
// If the principal def ids match (or are both none), then we're not doing
// trait upcasting. We're just removing auto traits (or shortening the lifetime).
if a_data.principal_def_id() == b_data.principal_def_id() {
unsize_dyn_to_principal(a_data.principal());
if let Ok(response) = unsize_dyn_to_principal(a_data.principal()) {
responses.push(response);
}
} else if let Some(a_principal) = a_data.principal()
&& let Some(b_principal) = b_data.principal()
{
@@ -433,7 +431,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
}
let erased_trait_ref = super_trait_ref
.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
unsize_dyn_to_principal(Some(erased_trait_ref));
if let Ok(response) = unsize_dyn_to_principal(Some(erased_trait_ref)) {
responses.push(response);
}
}
}

4 changes: 0 additions & 4 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -426,10 +426,6 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
},
};

// FIXME(eddyb) cache this (including computing `unsizing_params`)
// by putting it in a query; it would only need the `DefId` as it
// looks at declared field types, not anything substituted.

// The last field of the structure has to exist and contain type/const parameters.
let Some((tail_field, prefix_fields)) =
def.non_enum_variant().fields.split_last() else