Skip to content

Commit

Permalink
Rollup merge of rust-lang#72451 - ecstatic-morse:nrvo-type-mismatch, …
Browse files Browse the repository at this point in the history
…r=matthewjasper

Perform MIR NRVO even if types don't match

This is the most straightforward way to resolve rust-lang#72428, but it could cause problems in codegen since the type of `_0` may no longer match the return type of the body.
  • Loading branch information
Dylan-DPC authored May 25, 2020
2 parents 3ee1a17 + d24ba6d commit 123d918
Showing 1 changed file with 6 additions and 12 deletions.
18 changes: 6 additions & 12 deletions src/librustc_mir/transform/nrvo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,6 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
}
};

// Sometimes, the return place is assigned a local of a different but coercable type, for
// example `&T` instead of `&mut T`. Overwriting the `LocalInfo` for the return place would
// result in it having an incorrect type. Although this doesn't seem to cause a problem in
// codegen, bail out anyways since it happens so rarely.
let ret_ty = body.local_decls[mir::RETURN_PLACE].ty;
let assigned_ty = body.local_decls[returned_local].ty;
if ret_ty != assigned_ty {
debug!("`{:?}` was eligible for NRVO but for type mismatch", src.def_id());
debug!("typeof(_0) != typeof({:?}); {:?} != {:?}", returned_local, ret_ty, assigned_ty);
return;
}

debug!(
"`{:?}` was eligible for NRVO, making {:?} the return place",
src.def_id(),
Expand All @@ -72,6 +60,12 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
// Overwrite the debuginfo of `_0` with that of the renamed local.
let (renamed_decl, ret_decl) =
body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);

// Sometimes, the return place is assigned a local of a different but coercable type, for
// example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means
// its type may no longer match the return type of its function. This doesn't cause a
// problem in codegen because these two types are layout-compatible, but may be unexpected.
debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty);
ret_decl.clone_from(renamed_decl);

// The return place is always mutable.
Expand Down

0 comments on commit 123d918

Please sign in to comment.