@@ -351,13 +351,13 @@ class LocalVariableInitialization : public SingleBufferInitialization {
351351 " can't emit a local var for a non-local var decl" );
352352 assert (decl->hasStorage () && " can't emit storage for a computed variable" );
353353 assert (!SGF.VarLocs .count (decl) && " Already have an entry for this decl?" );
354+
354355 // The box type's context is lowered in the minimal resilience domain.
356+ auto instanceType = SGF.SGM .Types .getLoweredRValueType (
357+ TypeExpansionContext::minimal (), decl->getType ());
355358 auto boxType = SGF.SGM .Types .getContextBoxTypeForCapture (
356- decl,
357- SGF.SGM .Types .getLoweredRValueType (TypeExpansionContext::minimal (),
358- decl->getType ()),
359- SGF.F .getGenericEnvironment (),
360- /* mutable*/ true );
359+ decl, instanceType, SGF.F .getGenericEnvironment (),
360+ /* mutable*/ !instanceType->isPureMoveOnly () || !decl->isLet ());
361361
362362 // The variable may have its lifetime extended by a closure, heap-allocate
363363 // it using a box.
@@ -376,12 +376,8 @@ class LocalVariableInitialization : public SingleBufferInitialization {
376376 }
377377 }
378378
379- Addr = SGF.B .createProjectBox (decl, Box, 0 );
380- if (Addr->getType ().isMoveOnly ()) {
381- // TODO: Handle no implicit copy here.
382- Addr = SGF.B .createMarkMustCheckInst (
383- decl, Addr, MarkMustCheckInst::CheckKind::ConsumableAndAssignable);
384- }
379+ if (!Box->getType ().isBoxedNonCopyableType (Box->getFunction ()))
380+ Addr = SGF.B .createProjectBox (decl, Box, 0 );
385381
386382 // Push a cleanup to destroy the local variable. This has to be
387383 // inactive until the variable is initialized.
@@ -401,16 +397,24 @@ class LocalVariableInitialization : public SingleBufferInitialization {
401397 }
402398
403399 SILValue getAddress () const {
400+ assert (Addr);
404401 return Addr;
405402 }
406403
404+ // / If we have an address, returns the address. Otherwise, if we only have a
405+ // / box, lazily projects it out and returns it.
407406 SILValue getAddressForInPlaceInitialization (SILGenFunction &SGF,
408407 SILLocation loc) override {
408+ if (!Addr && Box) {
409+ auto pbi = SGF.B .createProjectBox (loc, Box, 0 );
410+ return pbi;
411+ }
412+
409413 return getAddress ();
410414 }
411415
412416 bool isInPlaceInitializationOfGlobal () const override {
413- return isa <GlobalAddrInst>(getAddress () );
417+ return dyn_cast_or_null <GlobalAddrInst>(Addr );
414418 }
415419
416420 void finishUninitialized (SILGenFunction &SGF) override {
@@ -421,7 +425,11 @@ class LocalVariableInitialization : public SingleBufferInitialization {
421425 // / Remember that this is the memory location that we've emitted the
422426 // / decl to.
423427 assert (SGF.VarLocs .count (decl) == 0 && " Already emitted the local?" );
424- SGF.VarLocs [decl] = SILGenFunction::VarLoc::get (Addr, Box);
428+
429+ if (Addr)
430+ SGF.VarLocs [decl] = SILGenFunction::VarLoc::get (Addr, Box);
431+ else
432+ SGF.VarLocs [decl] = SILGenFunction::VarLoc::getForBox (Box);
425433
426434 SingleBufferInitialization::finishInitialization (SGF);
427435 assert (!DidFinish &&
@@ -485,9 +493,13 @@ class LetValueInitialization : public Initialization {
485493 isUninitialized = true ;
486494 } else {
487495 // If this is a let with an initializer or bound value, we only need a
488- // buffer if the type is address only.
496+ // buffer if the type is address only or is noncopyable.
497+ //
498+ // For noncopyable types, we always need to box them and eagerly
499+ // reproject.
489500 needsTemporaryBuffer =
490- lowering->isAddressOnly () && SGF.silConv .useLoweredAddresses ();
501+ (lowering->isAddressOnly () && SGF.silConv .useLoweredAddresses ()) ||
502+ lowering->getLoweredType ().isPureMoveOnly ();
491503 }
492504
493505 // Make sure that we have a non-address only type when binding a
@@ -634,8 +646,7 @@ class LetValueInitialization : public Initialization {
634646 // We do this before the begin_borrow "normal" path below since move only
635647 // types do not have no implicit copy attr on them.
636648 if (value->getOwnershipKind () == OwnershipKind::Owned &&
637- value->getType ().isMoveOnly () &&
638- !value->getType ().isMoveOnlyWrapped ()) {
649+ value->getType ().isPureMoveOnly ()) {
639650 value = SGF.B .createMoveValue (PrologueLoc, value, true /* isLexical*/ );
640651 return SGF.B .createMarkMustCheckInst (
641652 PrologueLoc, value,
@@ -1253,10 +1264,10 @@ SILGenFunction::emitInitializationForVarDecl(VarDecl *vd, bool forceImmutable) {
12531264
12541265 assert (!isa<InOutType>(varType) && " local variables should never be inout" );
12551266
1256- // If this is a 'let' initialization for a non-global, set up a
1257- // let binding, which stores the initialization value into VarLocs directly.
1267+ // If this is a 'let' initialization for a copyable non-global, set up a let
1268+ // binding, which stores the initialization value into VarLocs directly.
12581269 if (forceImmutable && vd->getDeclContext ()->isLocalContext () &&
1259- !isa<ReferenceStorageType>(varType))
1270+ !isa<ReferenceStorageType>(varType) && !varType-> isPureMoveOnly () )
12601271 return InitializationPtr (new LetValueInitialization (vd, *this ));
12611272
12621273 // If the variable has no initial value, emit a mark_uninitialized instruction
0 commit comments