Skip to content

Commit

Permalink
Rollup merge of rust-lang#110126 - compiler-errors:new-solver-safe-tr…
Browse files Browse the repository at this point in the history
…ansmute, r=oli-obk

Support safe transmute in new solver

Basically copies the same implementation as the old solver, but instead of looking for param types, we look for type or const placeholders.
  • Loading branch information
compiler-errors authored Apr 11, 2023
2 parents cd2044f + 4adee91 commit b912d4c
Show file tree
Hide file tree
Showing 17 changed files with 1,184 additions and 121 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_middle/src/ty/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
| TypeFlags::HAS_CT_PLACEHOLDER,
)
}
fn has_non_region_placeholders(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER)
}
fn needs_subst(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_SUBST)
}
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<TyCtxt<'tcx>> + Copy + Eq {
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;

fn consider_builtin_transmute_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
}

impl<'tcx> EvalCtxt<'_, 'tcx> {
Expand Down Expand Up @@ -373,6 +378,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
G::consider_builtin_discriminant_kind_candidate(self, goal)
} else if lang_items.destruct_trait() == Some(trait_def_id) {
G::consider_builtin_destruct_candidate(self, goal)
} else if lang_items.transmute_trait() == Some(trait_def_id) {
G::consider_builtin_transmute_candidate(self, goal)
} else {
Err(NoSolution)
};
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,4 +639,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg)
.map(|obligations| obligations.into_iter().map(|obligation| obligation.into()))
}

pub(super) fn is_transmutable(
&self,
src_and_dst: rustc_transmute::Types<'tcx>,
scope: Ty<'tcx>,
assume: rustc_transmute::Assume,
) -> Result<Certainty, NoSolution> {
// FIXME(transmutability): This really should be returning nested goals for `Answer::If*`
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
ObligationCause::dummy(),
ty::Binder::dummy(src_and_dst),
scope,
assume,
) {
rustc_transmute::Answer::Yes => Ok(Certainty::Yes),
rustc_transmute::Answer::No(_)
| rustc_transmute::Answer::IfTransmutable { .. }
| rustc_transmute::Answer::IfAll(_)
| rustc_transmute::Answer::IfAny(_) => Err(NoSolution),
}
}
}
7 changes: 7 additions & 0 deletions compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
) -> QueryResult<'tcx> {
bug!("`Destruct` does not have an associated type: {:?}", goal);
}

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

/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
Expand Down
29 changes: 29 additions & 0 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,35 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
Err(NoSolution)
}
}

fn consider_builtin_transmute_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
// `rustc_transmute` does not have support for type or const params
if goal.has_non_region_placeholders() {
return Err(NoSolution);
}

// Erase regions because we compute layouts in `rustc_transmute`,
// which will ICE for region vars.
let substs = ecx.tcx().erase_regions(goal.predicate.trait_ref.substs);

let Some(assume) = rustc_transmute::Assume::from_const(
ecx.tcx(),
goal.param_env,
substs.const_at(3),
) else {
return Err(NoSolution);
};

let certainty = ecx.is_transmutable(
rustc_transmute::Types { dst: substs.type_at(0), src: substs.type_at(1) },
substs.type_at(2),
assume,
)?;
ecx.evaluate_added_goals_and_make_canonical_response(certainty)
}
}

impl<'tcx> EvalCtxt<'_, 'tcx> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error[E0277]: `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
--> $DIR/bool.rs:22:35
--> $DIR/bool.rs:24:35
|
LL | assert::is_transmutable::<u8, bool>();
| ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
|
= help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `bool`
note: required by a bound in `is_transmutable`
--> $DIR/bool.rs:12:14
--> $DIR/bool.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this function
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/transmutability/primitives/bool.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0277]: `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
--> $DIR/bool.rs:24:35
|
LL | assert::is_transmutable::<u8, bool>();
| ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
|
= help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `bool`
note: required by a bound in `is_transmutable`
--> $DIR/bool.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this function
LL | where
LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
4 changes: 3 additions & 1 deletion tests/ui/transmutability/primitives/bool.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// revisions: current next
//[next] compile-flags: -Ztrait-solver=next

#![crate_type = "lib"]
#![feature(transmutability)]
#![allow(dead_code)]
#![allow(incomplete_features)]

mod assert {
use std::mem::{Assume, BikeshedIntrinsicFrom};
pub struct Context;
Expand Down
Loading

0 comments on commit b912d4c

Please sign in to comment.