Add UseCloned trait related code
This commit is contained in:
parent
57cb498989
commit
dcdfd551f0
16 changed files with 198 additions and 44 deletions
|
@ -171,6 +171,7 @@ language_item_table! {
|
|||
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
|
||||
CloneFn, sym::clone_fn, clone_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
UseCloned, sym::use_cloned, use_cloned_trait, Target::Trait, GenericRequirement::None;
|
||||
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
|
||||
/// The associated item of the `DiscriminantKind` trait.
|
||||
|
|
|
@ -11,6 +11,7 @@ use rustc_middle::thir::*;
|
|||
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};
|
||||
|
@ -295,33 +296,52 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
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(),
|
||||
if this.tcx.type_is_copy_modulo_regions(this.infcx.typing_env(this.param_env), ty) {
|
||||
this.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
destination,
|
||||
target: Some(success),
|
||||
unwind: UnwindAction::Unreachable,
|
||||
call_source: CallSource::Misc,
|
||||
fn_span: expr_span,
|
||||
},
|
||||
);
|
||||
success.unit()
|
||||
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 } => {
|
||||
|
|
|
@ -2182,6 +2182,7 @@ symbols! {
|
|||
unwrap,
|
||||
unwrap_binder,
|
||||
unwrap_or,
|
||||
use_cloned,
|
||||
use_extern_macros,
|
||||
use_nested_groups,
|
||||
used,
|
||||
|
|
|
@ -53,6 +53,16 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, clone_def_id)
|
||||
}
|
||||
|
||||
fn type_is_use_cloned_modulo_regions(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
let use_cloned_def_id = self.tcx.require_lang_item(LangItem::UseCloned, None);
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, use_cloned_def_id)
|
||||
}
|
||||
|
||||
fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
let lang_item = self.tcx.require_lang_item(LangItem::Sized, None);
|
||||
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue