66//!
77//! [rustc dev guide]:
88//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
9+ use rustc_ast:: Mutability ;
910use rustc_data_structures:: stack:: ensure_sufficient_stack;
1011use rustc_hir:: lang_items:: LangItem ;
1112use rustc_infer:: infer:: LateBoundRegionConversionTime :: HigherRankedType ;
@@ -295,6 +296,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
295296 Ok ( None ) => Ok ( vec ! [ ] ) ,
296297 Err ( _) => Err ( Unimplemented ) ,
297298 // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll`
299+ // Not possible until the trait solver supports disjunctions of obligations
298300 Ok ( Some ( rustc_transmute:: Condition :: IfAll ( answers) ) )
299301 | Ok ( Some ( rustc_transmute:: Condition :: IfAny ( answers) ) ) => {
300302 let mut nested = vec ! [ ] ;
@@ -311,7 +313,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
311313 let scope = predicate. trait_ref . substs . type_at ( 2 ) ;
312314 let assume_const = predicate. trait_ref . substs . const_at ( 3 ) ;
313315 let make_obl = |from_ty, to_ty| {
314- let trait_ref1 = tcx. mk_trait_ref (
316+ let trait_ref1 = ty:: TraitRef :: new (
317+ tcx,
315318 trait_def_id,
316319 [
317320 ty:: GenericArg :: from ( to_ty) ,
@@ -329,8 +332,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
329332 )
330333 } ;
331334
332- // FIXME(bryangarza): Check src.mutability or dst.mutability to know whether dst -> src obligation is needed
333- Ok ( vec ! [ make_obl( src. ty, dst. ty) , make_obl( dst. ty, src. ty) ] )
335+ // If Dst is mutable, check bidirectionally.
336+ // For example, transmuting bool -> u8 is OK as long as you can't update that u8
337+ // to be > 1, because you could later transmute the u8 back to a bool and get UB.
338+ let mut obligations = vec ! [ make_obl( src. ty, dst. ty) ] ;
339+ if dst. mutability == Mutability :: Mut {
340+ obligations. push ( make_obl ( dst. ty , src. ty ) ) ;
341+ }
342+ Ok ( obligations)
334343 }
335344 }
336345 }
@@ -353,6 +362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
353362
354363 let dst = predicate. trait_ref . substs . type_at ( 0 ) ;
355364 let src = predicate. trait_ref . substs . type_at ( 1 ) ;
365+ debug ! ( ?src, ?dst) ;
356366 let mut transmute_env = rustc_transmute:: TransmuteTypeEnv :: new ( self . infcx ) ;
357367 let maybe_transmutable = transmute_env. is_transmutable (
358368 obligation. cause . clone ( ) ,
@@ -361,7 +371,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
361371 assume,
362372 ) ;
363373
364- debug ! ( ?src, ?dst) ;
365374 let fully_flattened =
366375 flatten_answer_tree ( self . tcx ( ) , obligation, predicate, maybe_transmutable) ?;
367376 debug ! ( ?fully_flattened) ;
0 commit comments