Skip to content

Commit 36306c6

Browse files
committed
[move-only] Treat black hole initialization as a consuming operation.
Otherwise, we don't treat `let _ = x` as a consuming operation. rdar://102196620
1 parent 1084d89 commit 36306c6

File tree

5 files changed

+112
-3
lines changed

5 files changed

+112
-3
lines changed

lib/SILGen/Initialization.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,7 @@ class BlackHoleInitialization : public Initialization {
341341
}
342342

343343
void copyOrInitValueInto(SILGenFunction &SGF, SILLocation loc,
344-
ManagedValue value, bool isInit) override {
345-
/// This just ignores the provided value.
346-
}
344+
ManagedValue value, bool isInit) override;
347345

348346
void finishUninitialized(SILGenFunction &SGF) override {
349347
// do nothing

lib/SILGen/SILGenDecl.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,3 +2081,21 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
20812081

20822082
llvm_unreachable("unhandled case");
20832083
}
2084+
2085+
void BlackHoleInitialization::copyOrInitValueInto(SILGenFunction &SGF, SILLocation loc,
2086+
ManagedValue value, bool isInit) {
2087+
// Normally we do not do anything if we have a black hole
2088+
// initialization... but if we have a move only object, insert a move value.
2089+
if (!value.getType().isMoveOnly())
2090+
return;
2091+
2092+
// If we have an address, then this will create a new temporary allocation
2093+
// which will trigger the move checker. If we have an object though, we need
2094+
// to insert an extra move_value to make sure the object checker behaves
2095+
// correctly.
2096+
value = value.ensurePlusOne(SGF, loc);
2097+
if (value.getType().isAddress())
2098+
return;
2099+
2100+
value = SGF.B.createMoveValue(loc, value);
2101+
}

test/SILGen/moveonly.swift

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,71 @@ extension NonTrivialEnum {
175175
let _ = x
176176
}
177177
}
178+
179+
///////////////////////////////
180+
// Black Hole Initialization //
181+
///////////////////////////////
182+
183+
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleLetInitialization1yyF : $@convention(thin) () -> () {
184+
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly5KlassCACycfC : $@convention(method) (@thick Klass.Type) -> @owned Klass
185+
// CHECK: [[X:%.*]] = apply [[FN]](
186+
// CHECK: [[X_MV_LEXICAL:%.*]] = move_value [lexical] [[X]]
187+
// CHECK: [[X_MV_ONLY:%.*]] = mark_must_check [no_implicit_copy] [[X_MV_LEXICAL]]
188+
// CHECK: [[X_MV_ONLY_BORROW:%.*]] = begin_borrow [[X_MV_ONLY]]
189+
// CHECK: [[X_MV_ONLY_COPY:%.*]] = copy_value [[X_MV_ONLY_BORROW]]
190+
// CHECK: [[X_MV_ONLY_CONSUME:%.*]] = move_value [[X_MV_ONLY_COPY]]
191+
// CHECK: } // end sil function '$s8moveonly27blackHoleLetInitialization1yyF'
192+
func blackHoleLetInitialization1() {
193+
let x = Klass()
194+
let _ = x
195+
}
196+
197+
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleLetInitialization2yyF : $@convention(thin) () -> () {
198+
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly5KlassCACycfC : $@convention(method) (@thick Klass.Type) -> @owned Klass
199+
// CHECK: [[X:%.*]] = apply [[FN]](
200+
// CHECK: [[X_MV_LEXICAL:%.*]] = move_value [lexical] [[X]]
201+
// CHECK: [[X_MV_ONLY:%.*]] = mark_must_check [no_implicit_copy] [[X_MV_LEXICAL]]
202+
// CHECK: [[X_MV_ONLY_BORROW:%.*]] = begin_borrow [[X_MV_ONLY]]
203+
// CHECK: [[X_MV_ONLY_COPY:%.*]] = copy_value [[X_MV_ONLY_BORROW]]
204+
// CHECK: [[X_MV_ONLY_CONSUME:%.*]] = move_value [[X_MV_ONLY_COPY]]
205+
// CHECK: } // end sil function '$s8moveonly27blackHoleLetInitialization2yyF'
206+
func blackHoleLetInitialization2() {
207+
let x = Klass()
208+
var _ = x
209+
}
210+
211+
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleVarInitialization1yyF : $@convention(thin) () -> () {
212+
// CHECK: [[BOX:%.*]] = alloc_box
213+
// CHECK: [[BOX_BORROW:%.*]] = begin_borrow [lexical] [[BOX]]
214+
// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]]
215+
// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_implicit_copy] [[PROJECT_BOX]]
216+
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly5KlassCACycfC : $@convention(method) (@thick Klass.Type) -> @owned Klass
217+
// CHECK: [[X:%.*]] = apply [[FN]](
218+
// CHECK: store [[X]] to [init] [[MARKED_ADDR]]
219+
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[MARKED_ADDR]]
220+
// CHECK: [[LD:%.*]] = load [copy] [[READ]]
221+
// CHECK: [[CONSUME:%.*]] = move_value [[LD]]
222+
// CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization1yyF'
223+
func blackHoleVarInitialization1() {
224+
var x = Klass()
225+
x = Klass()
226+
let _ = x
227+
}
228+
229+
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleVarInitialization2yyF : $@convention(thin) () -> () {
230+
// CHECK: [[BOX:%.*]] = alloc_box
231+
// CHECK: [[BOX_BORROW:%.*]] = begin_borrow [lexical] [[BOX]]
232+
// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]]
233+
// CHECK: [[MARKED_ADDR:%.*]] = mark_must_check [no_implicit_copy] [[PROJECT_BOX]]
234+
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly5KlassCACycfC : $@convention(method) (@thick Klass.Type) -> @owned Klass
235+
// CHECK: [[X:%.*]] = apply [[FN]](
236+
// CHECK: store [[X]] to [init] [[MARKED_ADDR]]
237+
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[MARKED_ADDR]]
238+
// CHECK: [[LD:%.*]] = load [copy] [[READ]]
239+
// CHECK: [[CONSUME:%.*]] = move_value [[LD]]
240+
// CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization2yyF'
241+
func blackHoleVarInitialization2() {
242+
var x = Klass()
243+
x = Klass()
244+
var _ = x
245+
}

test/SILOptimizer/moveonly_addresschecker_diagnostics.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,3 +2073,18 @@ func moveOperatorTest(_ k: __owned Klass) {
20732073
let _ = _move k2 // expected-note {{consuming use}}
20742074
let _ = k3
20752075
}
2076+
2077+
/////////////////////////////////////////
2078+
// Black hole initialization test case//
2079+
/////////////////////////////////////////
2080+
2081+
func blackHoleTestCase(_ k: __owned Klass) {
2082+
var k2 = k // expected-error {{'k2' consumed more than once}}
2083+
// expected-error @-1 {{'k2' consumed more than once}}
2084+
let _ = k2 // expected-note {{consuming use}}
2085+
let _ = k2 // expected-note {{consuming use}}
2086+
2087+
k2 = Klass()
2088+
var _ = k2 // expected-note {{consuming use}}
2089+
var _ = k2 // expected-note {{consuming use}}
2090+
}

test/SILOptimizer/moveonly_objectchecker_diagnostics.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2337,3 +2337,13 @@ func moveOperatorTest(_ k: __owned Klass) {
23372337
let _ = _move k2 // expected-note {{consuming use}}
23382338
let _ = k3
23392339
}
2340+
2341+
/////////////////////////////////////////
2342+
// Black hole initialization test case//
2343+
/////////////////////////////////////////
2344+
2345+
func blackHoleTestCase(_ k: __owned Klass) {
2346+
let k2 = k // expected-error {{'k2' consumed more than once}}
2347+
let _ = k2 // expected-note {{consuming use}}
2348+
let _ = k2 // expected-note {{consuming use}}
2349+
}

0 commit comments

Comments
 (0)