@@ -44,6 +44,18 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
4444 }
4545 } ;
4646
47+ // Sometimes, the return place is assigned a local of a different but coercable type, for
48+ // example `&T` instead of `&mut T`. Overwriting the `LocalInfo` for the return place would
49+ // result in it having an incorrect type. Although this doesn't seem to cause a problem in
50+ // codegen, bail out anyways since it happens so rarely.
51+ let ret_ty = body. local_decls [ mir:: RETURN_PLACE ] . ty ;
52+ let assigned_ty = body. local_decls [ returned_local] . ty ;
53+ if ret_ty != assigned_ty {
54+ debug ! ( "`{:?}` was eligible for NRVO but for type mismatch" , src. def_id( ) ) ;
55+ debug ! ( "typeof(_0) != typeof({:?}); {:?} != {:?}" , returned_local, ret_ty, assigned_ty) ;
56+ return ;
57+ }
58+
4759 debug ! (
4860 "`{:?}` was eligible for NRVO, making {:?} the return place" ,
4961 src. def_id( ) ,
@@ -60,7 +72,6 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
6072 // Overwrite the debuginfo of `_0` with that of the renamed local.
6173 let ( renamed_decl, ret_decl) =
6274 body. local_decls . pick2_mut ( returned_local, mir:: RETURN_PLACE ) ;
63- debug_assert_eq ! ( ret_decl. ty, renamed_decl. ty) ;
6475 ret_decl. clone_from ( renamed_decl) ;
6576
6677 // The return place is always mutable.
0 commit comments