diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 4155b120e51c9..83d45ca78d9d9 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -61,6 +61,10 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArg self.region_at(i) } + fn const_at(self, i: usize) -> ty::Const<'tcx> { + self.const_at(i) + } + fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericArgsRef<'tcx> { GenericArgs::identity_for_item(tcx, def_id) } diff --git a/compiler/rustc_next_trait_solver/src/infcx.rs b/compiler/rustc_next_trait_solver/src/infcx.rs index e0ce6c937a02f..c249eb94cf654 100644 --- a/compiler/rustc_next_trait_solver/src/infcx.rs +++ b/compiler/rustc_next_trait_solver/src/infcx.rs @@ -2,7 +2,7 @@ use std::fmt::Debug; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::relate::Relate; -use rustc_type_ir::solve::{Goal, NoSolution, SolverMode}; +use rustc_type_ir::solve::{Certainty, Goal, NoSolution, SolverMode}; use rustc_type_ir::{self as ty, Interner}; pub trait SolverDelegate: Sized { @@ -194,4 +194,12 @@ pub trait SolverDelegate: Sized { trait_assoc_def_id: ::DefId, impl_def_id: ::DefId, ) -> Result::DefId>, NoSolution>; + + fn is_transmutable( + &self, + param_env: ::ParamEnv, + dst: ::Ty, + src: ::Ty, + assume: ::Const, + ) -> Result; } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 6775d6ddae459..485758b91a285 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -890,25 +890,6 @@ where self.infcx.well_formed_goals(param_env, arg) } - /* - pub(super) fn is_transmutable( - &self, - src_and_dst: rustc_transmute::Types, - assume: rustc_transmute::Assume, - ) -> Result { - use rustc_transmute::Answer; - // FIXME(transmutability): This really should be returning nested goals for `Answer::If*` - match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable( - ObligationCause::dummy(), - src_and_dst, - assume, - ) { - Answer::Yes => Ok(Certainty::Yes), - Answer::No(_) | Answer::If(_) => Err(NoSolution), - } - } - */ - pub(super) fn trait_ref_is_knowable( &mut self, param_env: I::ParamEnv, @@ -1016,6 +997,16 @@ where ) -> Option { self.infcx.try_const_eval_resolve(param_env, unevaluated) } + + pub(super) fn is_transmutable( + &mut self, + param_env: I::ParamEnv, + dst: I::Ty, + src: I::Ty, + assume: I::Const, + ) -> Result { + self.infcx.is_transmutable(param_env, dst, src, assume) + } } /// Eagerly replace aliases with inference variables, emitting `AliasRelate` diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 7f46d72cba839..d1419bf5db9a5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -601,12 +601,10 @@ where } fn consider_builtin_transmute_candidate( - _ecx: &mut EvalCtxt<'_, Infcx>, - _goal: Goal, + ecx: &mut EvalCtxt<'_, Infcx>, + goal: Goal, ) -> Result, NoSolution> { - // TODO: - todo!() - /* if goal.predicate.polarity != ty::PredicatePolarity::Positive { + if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -615,26 +613,17 @@ where return Err(NoSolution); } - // Erase regions because we compute layouts in `rustc_transmute`, - // which will ICE for region vars. - let args = ecx.interner().erase_regions(goal.predicate.trait_ref.args); - - let Some(assume) = - rustc_transmute::Assume::from_const(ecx.interner(), goal.param_env, args.const_at(2)) - else { - return Err(NoSolution); - }; - // FIXME: This actually should destructure the `Result` we get from transmutability and // register candiates. We probably need to register >1 since we may have an OR of ANDs. ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { let certainty = ecx.is_transmutable( - rustc_transmute::Types { dst: args.type_at(0), src: args.type_at(1) }, - assume, + goal.param_env, + goal.predicate.trait_ref.args.type_at(0), + goal.predicate.trait_ref.args.type_at(1), + goal.predicate.trait_ref.args.const_at(2), )?; ecx.evaluate_added_goals_and_make_canonical_response(certainty) }) - */ } /// ```ignore (builtin impl example) diff --git a/compiler/rustc_trait_selection/src/solve/infcx.rs b/compiler/rustc_trait_selection/src/solve/infcx.rs index 2a5aaa26f3faf..e574166cbfc26 100644 --- a/compiler/rustc_trait_selection/src/solve/infcx.rs +++ b/compiler/rustc_trait_selection/src/solve/infcx.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; use rustc_type_ir::relate::Relate; -use rustc_type_ir::solve::{NoSolution, SolverMode}; +use rustc_type_ir::solve::{Certainty, NoSolution, SolverMode}; use crate::traits::coherence::trait_ref_is_knowable; use crate::traits::specialization_graph; @@ -406,4 +406,30 @@ impl<'tcx> rustc_next_trait_solver::infcx::SolverDelegate for SolverDelegate<'tc // FIXME: Check for defaultness here may cause diagnostics problems. if eligible { Ok(Some(node_item.item.def_id)) } else { Ok(None) } } + + fn is_transmutable( + &self, + param_env: ty::ParamEnv<'tcx>, + dst: Ty<'tcx>, + src: Ty<'tcx>, + assume: ty::Const<'tcx>, + ) -> Result { + // Erase regions because we compute layouts in `rustc_transmute`, + // which will ICE for region vars. + let (dst, src) = self.tcx.erase_regions((dst, src)); + + let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, param_env, assume) else { + return Err(NoSolution); + }; + + // FIXME(transmutability): This really should be returning nested goals for `Answer::If*` + match rustc_transmute::TransmuteTypeEnv::new(&self.0).is_transmutable( + ObligationCause::dummy(), + rustc_transmute::Types { src, dst }, + assume, + ) { + rustc_transmute::Answer::Yes => Ok(Certainty::Yes), + rustc_transmute::Answer::No(_) | rustc_transmute::Answer::If(_) => Err(NoSolution), + } + } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index c790c737fc921..64d3400976a8e 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -374,6 +374,8 @@ pub trait GenericArgs>: fn region_at(self, i: usize) -> I::Region; + fn const_at(self, i: usize) -> I::Const; + fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs; fn extend_with_error(