Skip to content

DI: Remove unnecessary assertion [4.2] #16979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2176,9 +2176,6 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
continue;
}

assert(!TheMemory.isDelegatingInit() &&
"re-assignment of self in delegating init?");

// If this ambiguous store is only of trivial types, then we don't need to
// do anything special. We don't even need keep the init bit for the
// element precise.
Expand Down
152 changes: 78 additions & 74 deletions test/SILOptimizer/definite_init_value_types.swift
Original file line number Diff line number Diff line change
@@ -1,95 +1,115 @@
// RUN: %target-swift-frontend -emit-sil -enable-sil-ownership %s -o /dev/null -verify
// RUN: %target-swift-frontend -emit-sil -enable-sil-ownership %s | %FileCheck %s

struct EmptyStruct {}

struct ValueStruct {
var ivar: EmptyStruct // expected-note {{'self.ivar' not initialized}}

init() { ivar = EmptyStruct() }
enum ValueEnum {
case a(String)
case b
case c

init() { self = .b }

init(a: Double) {
self.init()
_ = ivar // okay: ivar has been initialized by the delegation above
}

init(a: Int) {
_ = ivar // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
self.init()
_ = self // okay: self has been initialized by the delegation above
self = .c
}

init(a: Float) {
self.init()
self.init() // this is now OK
}

init(c: Bool) {
if c {
return
init(e: Bool) {
if e {
self = ValueEnum()
} else {
self.init()
}
}

self.init()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}

init(d: Bool) {
if d {
return // expected-error {{return from initializer without initializing all stored properties}}
// CHECK-LABEL: sil hidden @$S25definite_init_value_types9ValueEnumO1xACSb_tcfC : $@convention(method) (Bool, @thin ValueEnum.Type) -> @owned ValueEnum
// CHECK: bb0(%0 : $Bool, %1 : $@thin ValueEnum.Type):
// CHECK-NEXT: [[STATE:%.*]] = alloc_stack $Builtin.Int1
// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $ValueEnum
// CHECK-NEXT: [[INIT_STATE:%.*]] = integer_literal $Builtin.Int1, 0
// CHECK-NEXT: store [[INIT_STATE]] to [[STATE]]
// CHECK: [[BOOL:%.*]] = struct_extract %0 : $Bool, #Bool._value
// CHECK-NEXT: cond_br [[BOOL]], bb1, bb2
// CHECK: bb1:
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin ValueEnum.Type
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $ValueEnum, #ValueEnum.b!enumelt
// CHECK-NEXT: [[SELF_ACCESS:%.*]] = begin_access [modify] [static] [[SELF_BOX]]
// CHECK-NEXT: [[NEW_STATE:%.*]] = integer_literal $Builtin.Int1, -1
// CHECK-NEXT: store [[NEW_STATE]] to [[STATE]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_ACCESS]]
// CHECK-NEXT: end_access [[SELF_ACCESS]]
// CHECK-NEXT: br bb2
// CHECK: bb2:
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin ValueEnum.Type
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $ValueEnum, #ValueEnum.c!enumelt
// CHECK-NEXT: [[SELF_ACCESS:%.*]] = begin_access [modify] [static] [[SELF_BOX]]
// CHECK-NEXT: [[STATE_VALUE:%.*]] = load [[STATE]]
// CHECK-NEXT: cond_br [[STATE_VALUE]], bb3, bb4
// CHECK: bb3:
// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: br bb4
// CHECK: bb4:
// CHECK-NEXT: [[NEW_STATE:%.*]] = integer_literal $Builtin.Int1, -1
// CHECK-NEXT: store [[NEW_STATE]] to [[STATE]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_ACCESS]]
// CHECK-NEXT: end_access [[SELF_ACCESS]]
// CHECK-NEXT: retain_value [[NEW_SELF]]
// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[STATE]]
// CHECK-NEXT: return [[NEW_SELF]]
init(x: Bool) {
if x {
self = .b
}

self = ValueStruct()
self = .c
}
}

enum AddressEnum {
case a(Any)
case b
case c

init() { self = .b }

init(e: Bool) {
if e {
self.init()
self = AddressEnum()
} else {
self = ValueStruct()
self.init()
}
}
}

enum ValueEnum {
case Dinosaur, Train, Truck
init(x: Bool) {
if x {
self = .b
}
self = .c
}
}

init() { self = .Train }
struct EmptyStruct {}

init(a: Double) {
self.init()
_ = self // okay: self has been initialized by the delegation above
self = .Dinosaur
}
struct ValueStruct {
var ivar: EmptyStruct

init(a: Int) {
_ = self // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
self.init()
}
init() { ivar = EmptyStruct() }

init(a: Float) {
self.init()
self.init() // this is now OK
}

init(c: Bool) {
if c {
return
}

self.init()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}

init(d: Bool) {
if d {
return
}

self = ValueEnum()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
}

init(e: Bool) {
if e {
self = ValueEnum()
} else {
self.init()
} else {
self = ValueStruct()
}
}
}
Expand All @@ -100,22 +120,6 @@ struct AddressStruct {

init() { ivar = EmptyStruct(); any = nil }

init(c: Bool) {
if c {
return
}

self.init()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}

init(d: Bool) {
if d {
return
}

self = AddressStruct()
} // expected-error {{return from initializer without initializing all stored properties}}

init(e: Bool) {
if e {
self = AddressStruct()
Expand Down
80 changes: 80 additions & 0 deletions test/SILOptimizer/definite_init_value_types_diagnostics.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// RUN: %target-swift-frontend -emit-sil -enable-sil-ownership %s -o /dev/null -verify

struct EmptyStruct {}

struct ValueStruct {
var ivar: EmptyStruct // expected-note {{'self.ivar' not initialized}}

init() { ivar = EmptyStruct() }

init(a: Int) {
_ = ivar // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
self.init()
}

init(c: Bool) {
if c {
return
}

self.init()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}

init(d: Bool) {
if d {
return // expected-error {{return from initializer without initializing all stored properties}}
}

self = ValueStruct()
}
}

enum ValueEnum {
case Dinosaur, Train, Truck

init() { self = .Train }

init(a: Int) {
_ = self // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
self.init()
}

init(c: Bool) {
if c {
return
}

self.init()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}

init(d: Bool) {
if d {
return
}

self = ValueEnum()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
}

struct AddressStruct {
var ivar: EmptyStruct // expected-note {{'self.ivar' not initialized}}
var any: Any?

init() { ivar = EmptyStruct(); any = nil }

init(c: Bool) {
if c {
return
}

self.init()
} // expected-error {{'self.init' isn't called on all paths before returning from initializer}}

init(d: Bool) {
if d {
return
}

self = AddressStruct()
} // expected-error {{return from initializer without initializing all stored properties}}
}