@@ -9,8 +9,8 @@ use rustc_middle::mir::*;
99use rustc_middle:: span_bug;
1010use rustc_middle:: thir:: * ;
1111use rustc_middle:: ty:: { self , CanonicalUserTypeAnnotation , Ty } ;
12- use rustc_span:: DUMMY_SP ;
1312use rustc_span:: source_map:: Spanned ;
13+ use rustc_span:: { DUMMY_SP , sym} ;
1414use rustc_trait_selection:: infer:: InferCtxtExt ;
1515use tracing:: { debug, instrument} ;
1616
@@ -365,6 +365,97 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
365365 None
366366 } )
367367 }
368+ // Some intrinsics are handled here because they desperately want to avoid introducing
369+ // unnecessary copies.
370+ ExprKind :: Call { ty, fun, ref args, .. }
371+ if let ty:: FnDef ( def_id, _generic_args) = ty. kind ( )
372+ && let Some ( intrinsic) = this. tcx . intrinsic ( def_id)
373+ && matches ! (
374+ intrinsic. name,
375+ sym:: write_via_move
376+ | sym:: write_via_move_for_vec_unsafe
377+ | sym:: init_box_via_move
378+ ) =>
379+ {
380+ // We still have to evaluate the callee expression as normal (but we don't care
381+ // about its result).
382+ let _fun = unpack ! ( block = this. as_local_operand( block, fun) ) ;
383+
384+ match intrinsic. name {
385+ sym:: write_via_move | sym:: write_via_move_for_vec_unsafe => {
386+ // `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping.
387+
388+ // The destination must have unit type (so we don't actually have to store anything
389+ // into it).
390+ assert ! ( destination. ty( & this. local_decls, this. tcx) . ty. is_unit( ) ) ;
391+
392+ // Compile this to an assignment of the argument into the destination.
393+ let [ ptr, val] = * * args else {
394+ span_bug ! ( expr_span, "invalid write_via_move call" )
395+ } ;
396+ let Some ( ptr) = unpack ! ( block = this. as_local_operand( block, ptr) ) . place ( )
397+ else {
398+ span_bug ! ( expr_span, "invalid write_via_move call" )
399+ } ;
400+ let ptr_deref = ptr. project_deeper ( & [ ProjectionElem :: Deref ] , this. tcx ) ;
401+ this. expr_into_dest ( ptr_deref, block, val)
402+ }
403+ // sym::init_box_via_move => {
404+ // use rustc_abi::FieldIdx;
405+ // // `init_box_via_move(b, val)` becomes
406+ // // ```
407+ // // *(b.0.0.0) = val;
408+ // // ```
409+ // let [b, val] = **args else {
410+ // span_bug!(expr_span, "invalid init_box_via_move call")
411+ // };
412+ // let Some(b) = unpack!(block = this.as_local_operand(block, b)).place()
413+ // else {
414+ // span_bug!(expr_span, "invalid init_box_via_move call")
415+ // };
416+ // // Project to the pointer inside `b`. First we need to get the types of all
417+ // // the fields we are projecting through.
418+ // let field_ty = |adt: &ty::AdtDef<'tcx>, idx: FieldIdx| {
419+ // let field = adt.non_enum_variant().fields[idx].did;
420+ // this.tcx.type_of(field).instantiate_identity()
421+ // };
422+ // let ty::Adt(box_adt, box_adt_args) =
423+ // b.ty(&this.local_decls, this.tcx).ty.kind()
424+ // else {
425+ // span_bug!(expr_span, "invalid init_box_via_move call")
426+ // };
427+ // // The `<T>` shared by Box, Unique, NonNull.
428+ // let ty_arg = this.tcx.mk_args(&[box_adt_args[0]]);
429+ // let ty::Adt(unique_adt, _args) = field_ty(box_adt, FieldIdx::Zero).kind()
430+ // else {
431+ // span_bug!(expr_span, "invalid init_box_via_move call")
432+ // };
433+ // let unique_ty = Ty::new_adt(this.tcx, unique_def, ty_arg);
434+ // let ty::Adt(nonnull_adt, _args) =
435+ // field_ty(unique_adt, FieldIdx::Zero).kind()
436+ // else {
437+ // span_bug!(expr_span, "invalid init_box_via_move call")
438+ // };
439+ // let nonnull_ty = Ty::new_adt(this.tcx, nonnull_adt, ty_arg);
440+ // // Then we can construct the projection.
441+ // let b_ptr_deref = b.project_deeper(
442+ // &[
443+ // ProjectionElem::Field(FieldIdx::ZERO, unique_ty),
444+ // ProjectionElem::Field(FieldIdx::ZERO, nonnull_ty),
445+ // ProjectionElem::Field(
446+ // FieldIdx::ZERO,
447+ // Ty::new_mut_ptr(tcx, ty_arg.type_at(0)),
448+ // ),
449+ // ProjectionElem::Deref,
450+ // ],
451+ // this.tcx,
452+ // );
453+ // // Store `val` into `b_ptr`.
454+ // this.expr_into_dest(b_ptr_deref, block, val)
455+ // }
456+ _ => rustc_middle:: bug!( ) ,
457+ }
458+ }
368459 ExprKind :: Call { ty : _, fun, ref args, from_hir_call, fn_span } => {
369460 let fun = unpack ! ( block = this. as_local_operand( block, fun) ) ;
370461 let args: Box < [ _ ] > = args
@@ -769,7 +860,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
769860 // these are the cases that are more naturally handled by some other mode
770861 ExprKind :: Unary { .. }
771862 | ExprKind :: Binary { .. }
772- | ExprKind :: Box { .. }
773863 | ExprKind :: Cast { .. }
774864 | ExprKind :: PointerCoercion { .. }
775865 | ExprKind :: Repeat { .. }
0 commit comments