1
Fork 0

Implement .use keyword as an alias of clone

This commit is contained in:
Santiago Pastorino 2024-10-02 16:35:37 -03:00
parent 0cf8dbc96c
commit 05c516446a
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF
36 changed files with 247 additions and 24 deletions

View file

@ -582,6 +582,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::Yield { .. }
| ExprKind::ThreadLocalRef(_)
| ExprKind::Call { .. }
| ExprKind::ByUse { .. }
| ExprKind::WrapUnsafeBinder { .. } => {
// these are not places, so we need to make a temporary.
debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place)));

View file

@ -572,6 +572,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
block.and(Rvalue::Use(operand))
}
ExprKind::ByUse { expr, span: _ } => {
let operand = unpack!(
block =
this.as_operand(block, scope, expr, LocalInfo::Boring, NeedsTemporary::No)
);
block.and(Rvalue::Use(operand))
}
}
}

View file

@ -56,6 +56,7 @@ impl Category {
| ExprKind::RawBorrow { .. }
| ExprKind::Yield { .. }
| ExprKind::Call { .. }
| ExprKind::ByUse { .. }
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
ExprKind::Array { .. }

View file

@ -4,10 +4,12 @@ use rustc_ast::{AsmMacro, InlineAsmOptions};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::thir::*;
use rustc_middle::ty::CanonicalUserTypeAnnotation;
use rustc_middle::ty::{CanonicalUserTypeAnnotation, Ty};
use rustc_span::DUMMY_SP;
use rustc_span::source_map::Spanned;
use tracing::{debug, instrument};
@ -289,6 +291,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.diverge_from(block);
success.unit()
}
ExprKind::ByUse { expr, span } => {
let place = unpack!(block = this.as_place(block, expr));
let ty = place.ty(&this.local_decls, this.tcx).ty;
// Convert `expr.use` to a call like `Clone::clone(&expr)`
let success = this.cfg.start_new_block();
let clone_trait = this.tcx.require_lang_item(LangItem::Clone, None);
let clone_fn = this.tcx.associated_item_def_ids(clone_trait)[0];
let func = Operand::function_handle(this.tcx, clone_fn, [ty.into()], expr_span);
let ref_ty = Ty::new_imm_ref(this.tcx, this.tcx.lifetimes.re_erased, ty);
let ref_place = this.temp(ref_ty, span);
this.cfg.push_assign(
block,
source_info,
ref_place,
Rvalue::Ref(this.tcx.lifetimes.re_erased, BorrowKind::Shared, place),
);
this.cfg.terminate(
block,
source_info,
TerminatorKind::Call {
func,
args: [Spanned { node: Operand::Move(ref_place), span: DUMMY_SP }].into(),
destination,
target: Some(success),
unwind: UnwindAction::Unreachable,
call_source: CallSource::Misc,
fn_span: expr_span,
},
);
success.unit()
}
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
ExprKind::Borrow { arg, borrow_kind } => {
// We don't do this in `as_rvalue` because we use `as_place`

View file

@ -451,6 +451,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
| ExprKind::Tuple { .. }
| ExprKind::Unary { .. }
| ExprKind::Call { .. }
| ExprKind::ByUse { .. }
| ExprKind::Assign { .. }
| ExprKind::AssignOp { .. }
| ExprKind::Break { .. }

View file

@ -464,6 +464,10 @@ impl<'tcx> ThirBuildCx<'tcx> {
}
}
hir::ExprKind::Use(expr, span) => {
ExprKind::ByUse { expr: self.mirror_expr(expr), span }
}
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, arg) => {
ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
}

View file

@ -345,6 +345,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
| Borrow { .. }
| Box { .. }
| Call { .. }
| ByUse { .. }
| Closure { .. }
| ConstBlock { .. }
| ConstParam { .. }

View file

@ -246,6 +246,13 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
print_indented!(self, "}", depth_lvl);
}
ByUse { expr, span } => {
print_indented!(self, "ByUse {", depth_lvl);
print_indented!(self, "expr:", depth_lvl + 1);
self.print_expr(*expr, depth_lvl + 2);
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
print_indented!(self, "}", depth_lvl);
}
Deref { arg } => {
print_indented!(self, "Deref {", depth_lvl);
self.print_expr(*arg, depth_lvl + 1);