Skip to content

Commit e80162f

Browse files
authored
Merge pull request #66770 from jckarter/disallow-dynamic-move-only-definite-init-5.9
[5.9] DefiniteInitialization: Error when noncopyable types are conditionally initialized.
2 parents 2d1cbb6 + b7a898d commit e80162f

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

include/swift/AST/DiagnosticsSIL.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ ERROR(ivar_not_initialized_by_init_accessor,none,
193193
"property %0 not initialized by init accessor",
194194
(DeclName))
195195

196+
ERROR(noncopyable_dynamic_lifetime_unsupported,none,
197+
"conditional initialization or destruction of noncopyable types is not "
198+
"supported; this variable must be consistently in an initialized or "
199+
"uninitialized state through every code path", ())
200+
196201
ERROR(self_use_before_fully_init,none,
197202
"'self' used in %select{method call|property access}1 %0 before "
198203
"%select{all stored properties are initialized|"

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,11 @@ void LifetimeChecker::doIt() {
12201220
} else if (auto *ABI = dyn_cast<AllocBoxInst>(memAddr)) {
12211221
ABI->setDynamicLifetime();
12221222
}
1223+
// We don't support noncopyable types with dynamic lifetimes currently.
1224+
if (TheMemory.getType().isMoveOnly()) {
1225+
diagnose(Module, TheMemory.getUninitializedValue()->getLoc(),
1226+
diag::noncopyable_dynamic_lifetime_unsupported);
1227+
}
12231228
}
12241229
if (!ConditionalDestroys.empty())
12251230
handleConditionalDestroys(ControlVariable);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend -emit-sil -verify %s
2+
3+
enum E: Error { case err }
4+
5+
struct NC: ~Copyable {
6+
let x = 0
7+
8+
deinit { print("deinit") }
9+
}
10+
11+
func chk(_ cond: Bool) throws {
12+
let y: NC // expected-error{{not supported}} expected-warning{{never used}}
13+
if cond {
14+
y = NC()
15+
}
16+
throw E.err
17+
}
18+
19+
try? chk(true)

0 commit comments

Comments
 (0)