Skip to content

[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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Rajveer100
Copy link
Contributor

Resolves #80363

Using isolated in unintended contexts caused the compiler to crash in many scenarios.

@YOCKOW
Copy link
Member

YOCKOW commented Mar 30, 2025

Thank you for fixing #80363.

By the way, #80363 indeed focuses on constant declarations and this PR also focuses on them.
However, there is another case that the compiler crashes at the same point (only with Swift 6 language mode):

// -swift-version 6
isolated struct S {} // 💥

Is it possible to cover such cases as well in one fix?

@Rajveer100
Copy link
Contributor Author

Rajveer100 commented Mar 30, 2025

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 | 

@YOCKOW
Copy link
Member

YOCKOW commented Mar 31, 2025

@Rajveer100

This works without any further changes:

Hmm.
On my local machine, the compiler with your patch still crashes with Swift 6 language mode while compiling isolated struct S.
Specifically speaking, the test fails when, in your "/test/Concurrency/isolated_invalid_uses.swift",

  • Replacing // RUN: lines with // RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -swift-version 6 %s -emit-sil -o /dev/null -verify to specify Swift 6 language mode.
  • Replacing class C {} with isolated struct S {}.

@Rajveer100
Copy link
Contributor Author

@YOCKOW
My bad, I hadn't added the version flag earlier. Made few more changes.

// 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-

Copy link
Member

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 RUNs?
  • Is -verify-additional-prefix necessary?

Copy link
Contributor Author

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",
())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't isolated be single-quoted?
Or...
Can't we use 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.

Copy link
Contributor Author

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));
Copy link
Member

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 calls getActorIsolation is called before checkDeclAttributes in DeclChecker::visitBoundVariable.
  • isolated struct S {}: createImplicitConstructor calls getActorIsolation early if Feature::IsolatedDefaultValues is enabled.
    • That's why the compiler doesn't crash with isolated struct S { init() {} }.

I want to hear opinions from the author here. @ktoso
(cc: @sophiapoirier as the author of checkGlobalIsolation, @hborla as the author of IsolatedDefaultValues)

Copy link
Contributor Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[6.2, 6.1 regression] Misused isolated keyword crashes the compiler.
3 participants