Skip to content

Unexpected compiler diagnostics when checking async Bools with Swift Testing’s #expect #1128

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

Closed
yakovmanshin opened this issue May 24, 2025 · 1 comment
Labels
bug 🪲 Something isn't working

Comments

@yakovmanshin
Copy link

Description

When Swift Testing’s #expect macro is used to check actors’ Bool values (accessed asynchronously), seemingly equivalent expressions (isEnabled vs. isEnabled == true) result in unexpected—inconsistent, misleading, or missing—compiler diagnostics.

Reported in swiftlang/swift#81765.

Reproduction

import Testing

actor Service {
    var isEnabled = true
}

struct ServiceTests {
    
    let service = Service()
    
    @Test func isEnabled1() async {
        // No inline warnings or errors;
        // Errors on build: “(…) can not be referenced from a nonisolated context”:
        #expect(service.isEnabled)
        #expect(!service.isEnabled)
        
        // These build fine (no warnings or errors, inline or build-time):
        #expect(await service.isEnabled)
        #expect(await !service.isEnabled)
        #expect(!(await service.isEnabled))
        
        // Misleading inline warnings: “No 'async' operations occur within 'await' expression”;
        // Errors on build: “(…) can not be referenced from a nonisolated context”:
        await #expect(service.isEnabled)
        await #expect(!service.isEnabled)
    }
    
    // With explicit equality checks, the compiler produces more reasonable diagnostics:
    @Test func isEnabled2() async {
        // Inline errors “Expression is 'async' (…)"; suggest fix-its:
        #expect(service.isEnabled == true)
        #expect(service.isEnabled != true)
        #expect(service.isEnabled == false)
        
        // The fix-its hoist `await`s, resulting in:
        await #expect(service.isEnabled == true)
        await #expect(service.isEnabled != true)
        await #expect(service.isEnabled == false)
        
        // But these work too:
        #expect(await service.isEnabled == true)
        #expect((await service.isEnabled) == true)
        #expect(await service.isEnabled != true)
        #expect((await service.isEnabled) != true)
        #expect(await service.isEnabled == false)
        #expect((await service.isEnabled) == false)
    }
    
}

Expected behavior

The plain isEnabled checks produce the same (correct) diagnostics as the isEnabled == true expressions.

Environment

  • macOS 15.5 (24F74)
  • Xcode 16.4 (16F6)
  • Swift 6.1
swift-driver version: 1.120.5 Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)
Target: x86_64-apple-macosx15.0

Additional information

This issue is also reported in the Swift compiler repo: swiftlang/swift#81765.

@yakovmanshin yakovmanshin added the bug 🪲 Something isn't working label May 24, 2025
@grynspan
Copy link
Contributor

To work around this, write the await inside the #expect() argument list (so #expect(await foo), not await #expect(foo)).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🪲 Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants