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
17 changes: 9 additions & 8 deletions compiler/rustc_hir_typeck/src/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
let typeck_results = self.cx.typeck_results();
let adjustments = typeck_results.expr_adjustments(expr);
let mut place_with_id = self.cat_expr_unadjusted(expr)?;
for adjustment in adjustments {
for (adjustment_index, adjustment) in adjustments.iter().enumerate() {
let is_last_adjustment = adjustment_index + 1 == adjustments.len();
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
match adjustment.kind {
adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => {
Expand All @@ -752,13 +753,13 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
self.walk_autoref(expr, &place_with_id, autoref);
}

adjustment::Adjust::GenericReborrow(_reborrow) => {
// To build an expression as a place expression, it needs to be a field
// projection or deref at the outmost layer. So it is field projection or deref
// on an adjusted value. But this means that adjustment is applied on a
// subexpression that is not the final operand/rvalue for function call or
// assignment. This is a contradiction.
unreachable!("Reborrow trait usage during adjustment walk");
adjustment::Adjust::GenericReborrow(mutability) if is_last_adjustment => {
let bk = ty::BorrowKind::from_mutbl(mutability);
Comment thread
P8L1 marked this conversation as resolved.
self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
}

adjustment::Adjust::GenericReborrow(_) => {
span_bug!(expr.span, "generic reborrow adjustment must be terminal");
}
}
place_with_id = self.cat_expr_adjusted(expr, place_with_id, adjustment)?;
Expand Down
34 changes: 34 additions & 0 deletions tests/ui/reborrow/generic-reborrow-expr-use-visitor-closure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//@ check-pass

#![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> {}

#[allow(unused)]
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 takes_mut(_: CustomMut<'_, ()>) {}
fn takes_shared(_: CustomRef<'_, ()>) {}

fn main() {
let a = CustomMut(&mut ());

let mut f = || {
takes_mut(a);
takes_shared(a);
};

f();
f();
}
32 changes: 32 additions & 0 deletions tests/ui/reborrow/generic-reborrow-expr-use-visitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//@ check-pass

#![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> {}

#[allow(unused)]
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 takes_mut(_: CustomMut<'_, ()>) {}
fn takes_shared(_: CustomRef<'_, ()>) {}

fn main() {
let a = CustomMut(&mut ());

takes_mut(a);
takes_mut(a);

takes_shared(a);
takes_shared(a);
}
Loading