diff options
Diffstat (limited to 'compiler/rustc_mir_build/src')
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/as_constant.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/as_place.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/category.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/into.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/mod.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/check_unsafety.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/expr.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/print.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/util.rs | 22 |
13 files changed, 123 insertions, 9 deletions
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 84c9297e658..f743ea60a45 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -117,7 +117,12 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> ConstValue::Scalar(Scalar::from_uint(result, width)) }; - let value = match (lit, ty.kind()) { + let lit_ty = match *ty.kind() { + ty::Pat(base, _) => base, + _ => ty, + }; + + let value = match (lit, lit_ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 581f45db6c4..50ca924baf9 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -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))); diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index 2c9a1de7f99..97d34b85f50 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -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)) + } } } diff --git a/compiler/rustc_mir_build/src/builder/expr/category.rs b/compiler/rustc_mir_build/src/builder/expr/category.rs index ca55d36bfc6..34524aed406 100644 --- a/compiler/rustc_mir_build/src/builder/expr/category.rs +++ b/compiler/rustc_mir_build/src/builder/expr/category.rs @@ -56,6 +56,7 @@ impl Category { | ExprKind::RawBorrow { .. } | ExprKind::Yield { .. } | ExprKind::Call { .. } + | ExprKind::ByUse { .. } | ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)), ExprKind::Array { .. } diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 72443e2f60d..333e69475c5 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -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` diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 94955954934..f9fa750e750 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -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}")), } }) @@ -612,7 +612,8 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - | DefKind::AssocConst | DefKind::AnonConst | DefKind::InlineConst - | DefKind::Static { .. } => (vec![], tcx.type_of(def_id).instantiate_identity(), None), + | DefKind::Static { .. } + | DefKind::GlobalAsm => (vec![], tcx.type_of(def_id).instantiate_identity(), None), DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => { let sig = tcx.liberate_late_bound_regions( def_id.to_def_id(), @@ -871,7 +872,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); } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index c2eafd0a74e..d78c874c766 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -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 { .. } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 7139516702e..e46e8c9871a 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -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, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 2e069cae426..3d55c1401b6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -207,7 +207,7 @@ impl<'tcx> ThirBuildCx<'tcx> { &self, hir_id: HirId, ) -> Option<ty::CanonicalUserType<'tcx>> { - crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id) + crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 954d0cf97ab..dadd1e85461 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -345,6 +345,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { | Borrow { .. } | Box { .. } | Call { .. } + | ByUse { .. } | Closure { .. } | ConstBlock { .. } | ConstParam { .. } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 8dc3f998e09..4bfeab44bf4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -539,7 +539,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { &self, hir_id: hir::HirId, ) -> Option<ty::CanonicalUserType<'tcx>> { - crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id) + crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id) } /// Takes a HIR Path. If the path is a constant, evaluates it and feeds diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index cd56d93afcf..16cef0ec3ac 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -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); diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs index 60a47a94e3a..457957f5fce 100644 --- a/compiler/rustc_mir_build/src/thir/util.rs +++ b/compiler/rustc_mir_build/src/thir/util.rs @@ -1,12 +1,16 @@ +use std::assert_matches::assert_matches; + use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_middle::bug; -use rustc_middle::ty::{self, CanonicalUserType}; +use rustc_middle::ty::{self, CanonicalUserType, TyCtxt}; use tracing::debug; /// Looks up the type associated with this hir-id and applies the /// user-given generic parameters; the hir-id must map to a suitable /// type. pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>( + tcx: TyCtxt<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, hir_id: hir::HirId, ) -> Option<CanonicalUserType<'tcx>> { @@ -16,7 +20,23 @@ pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>( let ty = typeck_results.node_type(hir_id); match ty.kind() { ty::Adt(adt_def, ..) => { + // This "fixes" user type annotations for tupled ctor patterns for ADTs. + // That's because `type_of(ctor_did)` returns a FnDef, but we actually + // want to be annotating the type of the ADT itself. It's a bit goofy, + // but it's easier to adjust this here rather than in the path lowering + // code for patterns in HIR. if let ty::UserTypeKind::TypeOf(did, _) = &mut user_ty.value.kind { + // This is either already set up correctly (struct, union, enum, or variant), + // or needs adjusting (ctor). Make sure we don't start adjusting other + // user annotations like consts or fn calls. + assert_matches!( + tcx.def_kind(*did), + DefKind::Ctor(..) + | DefKind::Struct + | DefKind::Enum + | DefKind::Union + | DefKind::Variant + ); *did = adt_def.did(); } Some(user_ty) |
