-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Concurrency] Prevent misuse of isolated
keyword to avoid crashes
#80390
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
base: main
Are you sure you want to change the base?
Conversation
Thank you for fixing #80363. By the way, #80363 indeed focuses on constant declarations and this PR also focuses on them. // -swift-version 6
isolated struct S {} // 💥 Is it possible to cover such cases as well in one fix? |
This works without any further changes: debug-80363.swift:1:1: error: 'isolated' may only be used on 'deinit' declarations
1 | isolated class C {}
| `- error: 'isolated' may only be used on 'deinit' declarations
2 | isolated struct S {}
3 |
debug-80363.swift:2:1: error: 'isolated' may only be used on 'deinit' declarations
1 | isolated class C {}
2 | isolated struct S {}
| `- error: 'isolated' may only be used on 'deinit' declarations
3 |
4 | func f() {
debug-80363.swift:9:3: error: invalid use of isolated in this context
7 |
8 | actor A {
9 | isolated var state: Int?
| `- error: invalid use of isolated in this context
10 | }
11 |
debug-80363.swift:9:3: error: 'isolated' may only be used on 'deinit' declarations
7 |
8 | actor A {
9 | isolated var state: Int?
| `- error: 'isolated' may only be used on 'deinit' declarations
10 | }
11 |
debug-80363.swift:5:3: error: invalid use of isolated in this context
3 |
4 | func f() {
5 | isolated let c = C()
| `- error: invalid use of isolated in this context
6 | }
7 |
debug-80363.swift:5:3: error: 'isolated' may only be used on 'deinit' declarations
3 |
4 | func f() {
5 | isolated let c = C()
| `- error: 'isolated' may only be used on 'deinit' declarations
6 | }
7 |
debug-80363.swift:5:16: warning: initialization of immutable value 'c' was never used; consider replacing with assignment to '_' or removing it [#no-usage]
3 |
4 | func f() {
5 | isolated let c = C()
| `- warning: initialization of immutable value 'c' was never used; consider replacing with assignment to '_' or removing it [#no-usage]
6 | }
7 | |
Hmm.
|
9eb7b26
to
02eec64
Compare
@YOCKOW |
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -swift-version 6 -strict-concurrency=complete %s -emit-sil -o /dev/null -verify -DALLOW_TYPECHECKER_ERRORS -verify-additional-prefix typechecker- | ||
|
||
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -swift-version 6 -strict-concurrency=complete %s -emit-sil -o /dev/null -verify -verify-additional-prefix tns- | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me leave some questions here:
- Why are there two
RUN
s? - Is
-verify-additional-prefix
necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was debugging and left this out accidentally.
@@ -6035,6 +6035,9 @@ ERROR(isolated_deinit_on_value_type,none, | |||
ERROR(isolated_deinit_unavailable,none, | |||
"isolated deinit is only available in %0 %1 or newer", | |||
(AvailabilityDomain, AvailabilityRange)) | |||
ERROR(isolated_misuse_in_decl,none, | |||
"invalid use of isolated in this context", | |||
()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't Can't we use isolated
be single-quoted?
Or...attr_only_one_decl_kind
instead of new diagnosis?
Edit: We might not need new diagnosis if we can trap invalid isolated
declarations in a different way. Please see below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that could be done.
ctx.Diags.diagnose(isolatedAttr->getLocation(), | ||
diag::isolated_misuse_in_decl); | ||
return std::nullopt; | ||
} | ||
assert(isa<DestructorDecl>(decl)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a reason why this is not if (!isa<DestructorDecl>(decl)) { ... }
but assert(isa<DestructorDecl>(decl));
.
I mean I suspect we should catch any declarations other than deinit
declarations more upstream.
💭 I guess the cause of #80363 is that getActorIsolation(ValueDecl*)
is called before TypeChecker::checkDeclAttributes(Decl*)
is called:
isolated let c = C()
:checkGlobalIsolation
which callsgetActorIsolation
is called beforecheckDeclAttributes
inDeclChecker::visitBoundVariable
.isolated struct S {}
:createImplicitConstructor
callsgetActorIsolation
early ifFeature::IsolatedDefaultValues
is enabled.- That's why the compiler doesn't crash with
isolated struct S { init() {} }
.
- That's why the compiler doesn't crash with
I want to hear opinions from the author here. @ktoso
(cc: @sophiapoirier as the author of checkGlobalIsolation
, @hborla as the author of IsolatedDefaultValues
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the first time when I too saw the backtrace it wasn't quite it to just add the if
's to handle it.
Resolves #80363
Using
isolated
in unintended contexts caused the compiler to crash in many scenarios.