Rollup merge of #134797 - spastorino:ergonomic-ref-counting-1, r=nikomatsakis
Ergonomic ref counting This is an experimental first version of ergonomic ref counting. This first version implements most of the RFC but doesn't implement any of the optimizations. This was left for following iterations. RFC: https://github.com/rust-lang/rfcs/pull/3680 Tracking issue: https://github.com/rust-lang/rust/issues/132290 Project goal: https://github.com/rust-lang/rust-project-goals/issues/107 r? ```@nikomatsakis```
This commit is contained in:
commit
f5a143f796
119 changed files with 1401 additions and 79 deletions
|
@ -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)));
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ impl Category {
|
|||
| ExprKind::RawBorrow { .. }
|
||||
| ExprKind::Yield { .. }
|
||||
| ExprKind::Call { .. }
|
||||
| ExprKind::ByUse { .. }
|
||||
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
|
||||
|
||||
ExprKind::Array { .. }
|
||||
|
|
|
@ -4,11 +4,14 @@ 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 rustc_trait_selection::infer::InferCtxtExt;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::builder::expr::category::{Category, RvalueFunc};
|
||||
|
@ -289,6 +292,57 @@ 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;
|
||||
|
||||
if this.tcx.type_is_copy_modulo_regions(this.infcx.typing_env(this.param_env), ty) {
|
||||
this.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
destination,
|
||||
Rvalue::Use(Operand::Copy(place)),
|
||||
);
|
||||
block.unit()
|
||||
} else if this.infcx.type_is_use_cloned_modulo_regions(this.param_env, 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()
|
||||
} else {
|
||||
this.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
destination,
|
||||
Rvalue::Use(Operand::Move(place)),
|
||||
);
|
||||
block.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`
|
||||
|
|
|
@ -37,7 +37,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
|
|||
.map(|captured_place| {
|
||||
let name = captured_place.to_symbol();
|
||||
match captured_place.info.capture_kind {
|
||||
ty::UpvarCapture::ByValue => name,
|
||||
ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => name,
|
||||
ty::UpvarCapture::ByRef(..) => Symbol::intern(&format!("_ref__{name}")),
|
||||
}
|
||||
})
|
||||
|
@ -871,7 +871,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let mut projs = closure_env_projs.clone();
|
||||
projs.push(ProjectionElem::Field(FieldIdx::new(i), ty));
|
||||
match capture {
|
||||
ty::UpvarCapture::ByValue => {}
|
||||
ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => {}
|
||||
ty::UpvarCapture::ByRef(..) => {
|
||||
projs.push(ProjectionElem::Deref);
|
||||
}
|
||||
|
|
|
@ -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 { .. }
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
@ -648,7 +652,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
}
|
||||
},
|
||||
|
||||
hir::ExprKind::Closure { .. } => {
|
||||
hir::ExprKind::Closure(hir::Closure { .. }) => {
|
||||
let closure_ty = self.typeck_results.expr_ty(expr);
|
||||
let (def_id, args, movability) = match *closure_ty.kind() {
|
||||
ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None),
|
||||
|
@ -1248,6 +1252,17 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
|
||||
match upvar_capture {
|
||||
ty::UpvarCapture::ByValue => captured_place_expr,
|
||||
ty::UpvarCapture::ByUse => {
|
||||
let span = captured_place_expr.span;
|
||||
let expr_id = self.thir.exprs.push(captured_place_expr);
|
||||
|
||||
Expr {
|
||||
temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible },
|
||||
ty: upvar_ty,
|
||||
span: closure_expr.span,
|
||||
kind: ExprKind::ByUse { expr: expr_id, span },
|
||||
}
|
||||
}
|
||||
ty::UpvarCapture::ByRef(upvar_borrow) => {
|
||||
let borrow_kind = match upvar_borrow {
|
||||
ty::BorrowKind::Immutable => BorrowKind::Shared,
|
||||
|
|
|
@ -345,6 +345,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
|||
| Borrow { .. }
|
||||
| Box { .. }
|
||||
| Call { .. }
|
||||
| ByUse { .. }
|
||||
| Closure { .. }
|
||||
| ConstBlock { .. }
|
||||
| ConstParam { .. }
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue