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
[SR-8266] Compiler crash when checking exclusivity of inout alias #50797
Comments
@swift-ci create |
The crash was fixed on 4.2: <rdar://problem/42242406> [SR-8266]: Compiler crash when checking exclusivity of inout alias The diagnostic will be strengthened on master shortly: <rdar://problem/42560459> [Exclusivity] Failure to statically diagnose a conflict when passing conditional noescape closures. |
@atrick How does the resolution work in the end for the supplied testcase? Is the reference to mutable self legal here (I.e. is the immutable copy alias ( |
@palimondo thanks for filing this and following through! I'm able to write the test case code like this now without any crash or violation: func byTags(b: BenchmarkInfo) -> Bool {
return b.tags.isSuperset(of: tags) && b.tags.isDisjoint(with: skipTags)
} Can you point me directly to the code that has an exclusivity violation? You mentioned a closure in this bug description. If you point me to that, I'll explain why it's a violation. |
@atrick Thanks, the above case working is the best I was hoping for! With inline closures, I was referring to the commented out So, from my (shallow) understanding of the PR #18234, you did unify the implementation so that the exclusivity check works the same for inline closures and nested functions, therefore I'd expect those inline closures should now also work and not report errors? |
@palimondo, thanks again! I'm still fixing two bugs in the exclusivity checker, and I now see there's a third bug in the type checker: https://bugs.swift.org/browse/SR-8546. So, nested functions have always been modeled mostly like "inline" closures at each point they are used, but the type checker handles them differently. That means, assuming the type checker is happy, nested functiond can always be considered non-escaping whenever they're not passed to an explicitly `escaping` argument, meaning they can capture `inout` arguments. (sorry this is complicated, I'm doing my best to explain) Sadly, this is in no way properly supported, but it now accidentally works if you don't violate the closure escaping guarantee. Specifically, the type checker "accidentally" correctly allows the nested function case. I say accidentally because it does not properly diagnose escaping violations. I did recently fix the exclusivity checker to handle this case so it at least detects exclusivity conflicts: func doit(x: inout Int, _ f: ()->()) { f() }
public func outerFoo1(x: inout Int) {
func innerFoo1() {
x = 1
}
func innerFoo2() {
x = 2
}
doit(x: &x, x == 0 ? innerFoo2 : innerFoo2)
} error: overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable
doit(x: &x, x == 0 ? innerFoo2 : innerFoo2) The type checker does not uniformly handle nested functions and inline closures. So it currently does not allow you to write the same code this way: public func outerFoo2(x: inout Int) {
doit(x: &x, x == 0 ? { x = 1 } : { x = 2})
} error: escaping closures can only capture inout parameters explicitly by value
doit(x: &x, x == 0 ? { x = 1 } : { x = 2}) If the type checker allowed it, then, yes, the exclusivity checker would uniformly handle both cases. |
Oh. So it looks like I've dug out some skeletons from the closet… |
From reading SR-8546 you want to make it illegal… correct? |
Ah, I think I get it now: that is illegal when passed to explicitly |
Right, the bug is a failure to diagnose a case that is clearly illegal. |
Attachment: Download
Environment
swift-DEVELOPMENT-SNAPSHOT-2018-07-12-a
Additional Detail from JIRA
md5: dc1f574d8884c55d3be4243ade084ea0
Issue Description:
While refactoring some legacy swift code, that included a peculiar workaround to avoid capturing mutable inout self reference when creating a closure passed filter method, I've stumbled upon a crash in one of the latest swift master builds (dev snapshot 2018-07-12). The particular closure is non-escaping, but it implicitly captures a mutable inout self, because it references two vars.
The old workaround was to create immutable copies of the vars and use those inside the closure:
let (_tags, _skipTags) = (tags, skipTags)
I thought that current version of the compiler would be able to reason correctly about this code to not require the explicit copying...
The compiling attached file crashes with following error:
What's strange is that this code compile without error, when compiled with last Xcode Beta:
Apple Swift version 4.2 (swiftlang-1000.0.25.1 clang-1000.10.28.1
. I haven't tried running that, there might be some hidden failure, because when I don't use the nested funcs, but use inline closure syntax, the references totags
andskipTags
triggererror: reference to property 'tags' in closure requires explicit 'self.' to make capture semantics explicit
. But adding explicit self leads toerror: closure cannot implicitly capture a mutating self parameter
.As the crash on latest master happens in exclusivity check, I thought it had something to do with having two references to self, one for
tags
and one forskipTags
, but the crash happens even if one of them uses the immutable copy workaround.The text was updated successfully, but these errors were encountered: