As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
Dave, what exactly are you trying to do?
At some point, I plan on adding static checking for exclusivity like the ownership model. I imagine we could just error whenever we can not eliminate a runtime check. Would that solve your problem?
···
On Oct 5, 2017, at 1:42 PM, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:
It's worth noting that this is impossible in the general case:
// Library.swift
public class Foo {
public var x: Int = 0
public init() {}
}
public func testExclusivity(_ a: Foo, _ b: Foo, by callback: (inout Int, inout Int) -> Void) {
callback(&a.x, &b.x)
}
// Client.swift, compiled as a separate target
let foo = Foo()
testExclusivity(foo, foo) { $0 = 42; $1 = 8192 }
That doesn't necessarily mean there aren't improvements to be made, but it might change your goals.
Jordan
···
On Oct 5, 2017, at 13:42, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:
Hello,
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
Dave, what exactly are you trying to do?
Hi Michael,
I’m trying to understand the exclusivity model in practice and I’m finding that auditing the SIL/assembly output for dynamic checks is a kind of pain.
At some point, I plan on adding static checking for exclusivity like the ownership model. I imagine we could just error whenever we can not eliminate a runtime check. Would that solve your problem?
To be clear, the “problem” I’m solving is my own curiosity. Ultimately, I was just looking for some hints on where I could hack in some code to warn/note when checks are generated and error when SIL cannot eliminate dynamic checks.
Thanks,
Dave
···
On Oct 5, 2017, at 16:50, Michael Gottesman via swift-dev <swift-dev@swift.org> wrote:
On Oct 5, 2017, at 1:42 PM, David Zarzycki via swift-dev <swift-dev@swift.org> wrote:
Thanks for writing the above code. Just to be clear, are you pointing out that exclusivity checking through opaque code (like a library) is problematic? Or that classes introduce their own aliasing challenges? Or both? Or something else entirely?
If we set aside resiliency for a second, couldn't the exclusivity checker dynamically crash in the above scenario if two or more InOutExprs end up resolving to the same address? If not, then why not?
Thanks,
Dave
···
On Oct 5, 2017, at 18:08, Jordan Rose <jordan_rose@apple.com> wrote:
On Oct 5, 2017, at 13:42, David Zarzycki via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
Hello,
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
It's worth noting that this is impossible in the general case:
// Library.swift
public class Foo {
public var x: Int = 0
public init() {}
}
public func testExclusivity(_ a: Foo, _ b: Foo, by callback: (inout Int, inout Int) -> Void) {
callback(&a.x, &b.x)
}
// Client.swift, compiled as a separate target
let foo = Foo()
testExclusivity(foo, foo) { $0 = 42; $1 = 8192 }
That doesn't necessarily mean there aren't improvements to be made, but it might change your goals.
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
It's worth noting that this is impossible in the general case:
// Library.swift
public class Foo {
public var x: Int = 0
public init() {}
}
public func testExclusivity(_ a: Foo, _ b: Foo, by callback: (inout Int, inout Int) -> Void) {
callback(&a.x, &b.x)
}
// Client.swift, compiled as a separate target
let foo = Foo()
testExclusivity(foo, foo) { $0 = 42; $1 = 8192 }
That doesn't necessarily mean there aren't improvements to be made, but it might change your goals.
Hi Jordan,
Thanks for writing the above code. Just to be clear, are you pointing out that exclusivity checking through opaque code (like a library) is problematic? Or that classes introduce their own aliasing challenges? Or both? Or something else entirely?
The former, really. Classes are just the most convenient way to get coincidental aliasing.
If we set aside resiliency for a second, couldn't the exclusivity checker dynamically crash in the above scenario if two or more InOutExprs end up resolving to the same address? If not, then why not?
"If we set aside resiliency" isn't something that works today. Local builds don't actually have access to the SIL of any of their dependencies at the moment (for a handful of reasons). Opaque code really does have to be treated as opaque.
(If this isn't convincing, then consider 'a' and 'b' coming directly from Objective-C code, where there's no exclusivity checking logic at all.)
Jordan
···
On Oct 5, 2017, at 15:23, David Zarzycki <dave@znu.io> wrote:
On Oct 5, 2017, at 18:08, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
On Oct 5, 2017, at 13:42, David Zarzycki via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
Let’s step back for a second. How comprehensive is the exclusivity checker within a single/pure Swift module? As long as external modules aren’t involed, is the model exhaustive? Or can some scenarios slip through both the static and dynamic checking? (Again, just within a single pure Swift module.)
This has been very helpful. Thanks,
Dave
···
On Oct 5, 2017, at 18:34, Jordan Rose <jordan_rose@apple.com> wrote:
On Oct 5, 2017, at 15:23, David Zarzycki <dave@znu.io <mailto:dave@znu.io>> wrote:
On Oct 5, 2017, at 18:08, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
On Oct 5, 2017, at 13:42, David Zarzycki via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
Hello,
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
It's worth noting that this is impossible in the general case:
// Library.swift
public class Foo {
public var x: Int = 0
public init() {}
}
public func testExclusivity(_ a: Foo, _ b: Foo, by callback: (inout Int, inout Int) -> Void) {
callback(&a.x, &b.x)
}
// Client.swift, compiled as a separate target
let foo = Foo()
testExclusivity(foo, foo) { $0 = 42; $1 = 8192 }
That doesn't necessarily mean there aren't improvements to be made, but it might change your goals.
Hi Jordan,
Thanks for writing the above code. Just to be clear, are you pointing out that exclusivity checking through opaque code (like a library) is problematic? Or that classes introduce their own aliasing challenges? Or both? Or something else entirely?
The former, really. Classes are just the most convenient way to get coincidental aliasing.
If we set aside resiliency for a second, couldn't the exclusivity checker dynamically crash in the above scenario if two or more InOutExprs end up resolving to the same address? If not, then why not?
"If we set aside resiliency" isn't something that works today. Local builds don't actually have access to the SIL of any of their dependencies at the moment (for a handful of reasons). Opaque code really does have to be treated as opaque.
(If this isn't convincing, then consider 'a' and 'b' coming directly from Objective-C code, where there's no exclusivity checking logic at all.)
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
It's worth noting that this is impossible in the general case:
// Library.swift
public class Foo {
public var x: Int = 0
public init() {}
}
public func testExclusivity(_ a: Foo, _ b: Foo, by callback: (inout Int, inout Int) -> Void) {
callback(&a.x, &b.x)
}
// Client.swift, compiled as a separate target
let foo = Foo()
testExclusivity(foo, foo) { $0 = 42; $1 = 8192 }
That doesn't necessarily mean there aren't improvements to be made, but it might change your goals.
Hi Jordan,
Thanks for writing the above code. Just to be clear, are you pointing out that exclusivity checking through opaque code (like a library) is problematic? Or that classes introduce their own aliasing challenges? Or both? Or something else entirely?
The former, really. Classes are just the most convenient way to get coincidental aliasing.
The important point here is that the "conservatively emit static errors for every exclusivity check we can't resolve statically" rule is basically equivalent to "disallow mutable class properties", because we do not have any language support for the sort of unique-right-to-access rules that would be necessary to ever resolve any of those statically.
John.
···
On Oct 5, 2017, at 6:34 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:
On Oct 5, 2017, at 15:23, David Zarzycki <dave@znu.io <mailto:dave@znu.io>> wrote:
On Oct 5, 2017, at 18:08, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
On Oct 5, 2017, at 13:42, David Zarzycki via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
If we set aside resiliency for a second, couldn't the exclusivity checker dynamically crash in the above scenario if two or more InOutExprs end up resolving to the same address? If not, then why not?
"If we set aside resiliency" isn't something that works today. Local builds don't actually have access to the SIL of any of their dependencies at the moment (for a handful of reasons). Opaque code really does have to be treated as opaque.
(If this isn't convincing, then consider 'a' and 'b' coming directly from Objective-C code, where there's no exclusivity checking logic at all.)
John or Devin would be better at answering this, but I believe that the combined static/dynamic model will catch everything except accesses through UnsafePointer (sure), accesses from C (sure), and accesses across threads (ouch). The last can be caught by TSan, though.
One other caveat: I believe we turn off the dynamic checking completely under -O in the Swift 4 release. I'm not sure if there are plans to change that or if the cost of the check really is that bad.
Jordan
···
On Oct 5, 2017, at 15:44, David Zarzycki <dave@znu.io> wrote:
On Oct 5, 2017, at 18:34, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
On Oct 5, 2017, at 15:23, David Zarzycki <dave@znu.io <mailto:dave@znu.io>> wrote:
On Oct 5, 2017, at 18:08, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
On Oct 5, 2017, at 13:42, David Zarzycki via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
Hello,
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
It's worth noting that this is impossible in the general case:
// Library.swift
public class Foo {
public var x: Int = 0
public init() {}
}
public func testExclusivity(_ a: Foo, _ b: Foo, by callback: (inout Int, inout Int) -> Void) {
callback(&a.x, &b.x)
}
// Client.swift, compiled as a separate target
let foo = Foo()
testExclusivity(foo, foo) { $0 = 42; $1 = 8192 }
That doesn't necessarily mean there aren't improvements to be made, but it might change your goals.
Hi Jordan,
Thanks for writing the above code. Just to be clear, are you pointing out that exclusivity checking through opaque code (like a library) is problematic? Or that classes introduce their own aliasing challenges? Or both? Or something else entirely?
The former, really. Classes are just the most convenient way to get coincidental aliasing.
If we set aside resiliency for a second, couldn't the exclusivity checker dynamically crash in the above scenario if two or more InOutExprs end up resolving to the same address? If not, then why not?
"If we set aside resiliency" isn't something that works today. Local builds don't actually have access to the SIL of any of their dependencies at the moment (for a handful of reasons). Opaque code really does have to be treated as opaque.
(If this isn't convincing, then consider 'a' and 'b' coming directly from Objective-C code, where there's no exclusivity checking logic at all.)
Right, that make sense.
Let’s step back for a second. How comprehensive is the exclusivity checker within a single/pure Swift module? As long as external modules aren’t involed, is the model exhaustive? Or can some scenarios slip through both the static and dynamic checking? (Again, just within a single pure Swift module.)
As an experiment, I’d like to force the exclusivity checking logic to always error at compile time, rather than a mix of compile time and run time. Near as I can tell, there is no built in debugging logic to do this (not even to warn when dynamic checks are added). Am I missing something? Where would be the best place in the code to make the dynamic checker error/warning at compile time? Would a warning be useful to others? Or should I just keep this on a throwaway branch?
It's worth noting that this is impossible in the general case:
// Library.swift
public class Foo {
public var x: Int = 0
public init() {}
}
public func testExclusivity(_ a: Foo, _ b: Foo, by callback: (inout Int, inout Int) -> Void) {
callback(&a.x, &b.x)
}
// Client.swift, compiled as a separate target
let foo = Foo()
testExclusivity(foo, foo) { $0 = 42; $1 = 8192 }
That doesn't necessarily mean there aren't improvements to be made, but it might change your goals.
Hi Jordan,
Thanks for writing the above code. Just to be clear, are you pointing out that exclusivity checking through opaque code (like a library) is problematic? Or that classes introduce their own aliasing challenges? Or both? Or something else entirely?
The former, really. Classes are just the most convenient way to get coincidental aliasing.
The important point here is that the "conservatively emit static errors for every exclusivity check we can't resolve statically" rule is basically equivalent to "disallow mutable class properties", because we do not have any language support for the sort of unique-right-to-access rules that would be necessary to ever resolve any of those statically.
Thanks John!
···
On Oct 5, 2017, at 20:28, John McCall <rjmccall@apple.com> wrote:
On Oct 5, 2017, at 6:34 PM, Jordan Rose via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
On Oct 5, 2017, at 15:23, David Zarzycki <dave@znu.io <mailto:dave@znu.io>> wrote:
On Oct 5, 2017, at 18:08, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:
On Oct 5, 2017, at 13:42, David Zarzycki via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:
John.
If we set aside resiliency for a second, couldn't the exclusivity checker dynamically crash in the above scenario if two or more InOutExprs end up resolving to the same address? If not, then why not?
"If we set aside resiliency" isn't something that works today. Local builds don't actually have access to the SIL of any of their dependencies at the moment (for a handful of reasons). Opaque code really does have to be treated as opaque.
(If this isn't convincing, then consider 'a' and 'b' coming directly from Objective-C code, where there's no exclusivity checking logic at all.)