Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions compiler/rustc_const_eval/src/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
})?;
}

Reborrow(_, _, place) => {
let op = self.eval_place_to_op(place, Some(dest.layout))?;
self.copy_op(&op, &dest)?;
Reborrow(_, mutability, place) => {
let op = self.eval_place_to_op(place, None)?;
if mutability.is_not() {
// Shared generic reborrows use `CoerceShared`: a bitwise copy into a
// distinct same-layout target ADT.
self.copy_op_allow_transmute(&op, &dest)?;
} else {
self.copy_op(&op, &dest)?;
}
Comment thread
P8L1 marked this conversation as resolved.
}

RawPtr(kind, place) => {
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_mir_transform/src/promote_consts.rs
Comment thread
P8L1 marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -580,11 +580,7 @@ impl<'tcx> Validator<'_, 'tcx> {
self.validate_ref(*kind, place)?;
}

Rvalue::Reborrow(_, _, place) => {
// FIXME(reborrow): should probably have a place_simplified like above.
let op = &Operand::Copy(*place);
self.validate_operand(op)?
}
Rvalue::Reborrow(..) => return Err(Unpromotable),

Rvalue::Aggregate(_, operands) => {
for o in operands {
Expand Down
48 changes: 48 additions & 0 deletions src/tools/miri/tests/pass/reborrow-coerce-shared.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Regression test for the Miri reproducer in rust-lang/rust#156313.
//
// The issue's exact recursive example ICEd while evaluating the argument
// conversion before the recursion mattered. This keeps that same
// `CustomMut`-to-`CustomRef` call path, but terminates after one recursive
// call so it can be a pass test once the ICE is fixed.

#![feature(reborrow)]

use std::marker::{CoerceShared, Reborrow};

#[allow(unused)]
struct CustomMut<'a, T>(&'a mut T);
impl<'a, T> Reborrow for CustomMut<'a, T> {}
impl<'a, T> CoerceShared<CustomRef<'a, T>> for CustomMut<'a, T> {}

struct CustomRef<'a, T>(&'a T);

impl<'a, T> Clone for CustomRef<'a, T> {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<'a, T> Copy for CustomRef<'a, T> {}

fn method(_a: CustomRef<'_, ()>) {}

fn recursive_method(_a: CustomRef<'_, ()>, recurse: bool) {
if recurse {
let a = CustomMut(&mut ());
recursive_method(a, false);
}
}

fn issue_156313_runtime_reproducer() {
let a = CustomMut(&mut ());
method(a);
}

fn issue_156313_recursive_call_reproducer() {
let a = CustomMut(&mut ());
recursive_method(a, true);
}

fn main() {
issue_156313_runtime_reproducer();
issue_156313_recursive_call_reproducer();
}
28 changes: 28 additions & 0 deletions tests/ui/reborrow/coerce_shared_consteval.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//@ run-pass
// Regression test for the const-eval reproducer in rust-lang/rust#156313.

#![feature(reborrow)]
#![allow(dead_code)]
#![allow(unused_variables)]

use std::marker::{CoerceShared, Reborrow};

pub struct MyMut<'a>(&'a u8);

impl Reborrow for MyMut<'_> {}

#[derive(Clone, Copy)]
pub struct MyRef<'a>(&'a u8);

impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}

const fn consteval_reproducer() {
let value = 1;
foo(MyMut(&value));
}

const fn foo(x: MyRef<'_>) {}

fn main() {
const { consteval_reproducer(); }
}
21 changes: 21 additions & 0 deletions tests/ui/reborrow/reborrow-promotion-rejected.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ check-fail

#![feature(reborrow)]

use std::marker::{CoerceShared, Reborrow};

struct MyMut<'a>(&'a u8);
impl Reborrow for MyMut<'_> {}

#[derive(Clone, Copy)]
struct MyRef<'a>(&'a u8);
impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}

const fn coerce(x: MyRef<'_>) -> MyRef<'_> {
x
}

static BAD: &'static MyRef<'static> = &coerce(MyMut(&1));
//~^ ERROR temporary value dropped while borrowed

fn main() {}
13 changes: 13 additions & 0 deletions tests/ui/reborrow/reborrow-promotion-rejected.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/reborrow-promotion-rejected.rs:18:47
|
LL | static BAD: &'static MyRef<'static> = &coerce(MyMut(&1));
| --------^^^^^^^^^-
| | | |
| | | temporary value is freed at the end of this statement
| | creates a temporary value which is freed while still in use
| using this value as a static requires that borrow lasts for `'static`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0716`.
Loading