Skip to content

[SR-14764] @MainActor ignored by the compiler #57114

Closed

Description

@DevAndArtist
Previous ID SR-14764
Radar rdar://problem/79352544
Original Reporter @DevAndArtist
Type Bug
Status Resolved
Resolution Done
Environment

Version 13.0 beta (13A5154h)
swift-driver version: 1.26 Apple Swift version 5.5 (swiftlang-1300.0.19.104 clang-1300.0.18.4)
Target: arm64-apple-macosx11.0

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 489030d069b5154dcc245685ee400a89

Issue Description:

Compiler seems to ignore `@MainActor` in the following code example:

import SwiftUI

class Model: ObservableObject {
  @Published
  var data: Data?
}

struct TestView: View {
  @ObservedObject
  var _model = Model()

  @MainActor
  func apply(_ data: Data) {
    // runtime warning:
    // Publishing changes from background threads is not allowed; make
    // sure to publish values from the main thread (via operators like
    // receive(on:)) on model updates.

    _model.data = data

    // runtime crash
    dispatchPrecondition(condition: .onQueue(.main))
  }

  func fetchData() async throws {
    let urlString = "https://google.com"
    guard case let url? = URL(string: urlString) else {
      return
    }
    let (data, response) = try await URLSession.shared.data(from: url)
    guard
      case let httpResponse? = response as? HTTPURLResponse,
      httpResponse.statusCode == 200
    else {
      return
    }

    // note there is NO `await` here as the compiler does not ask for it at all
    apply(data)
  }

  var body: some View {
    Text("\(_model.data.map(\.count) ?? 0)")
      .task {
        do {
          try await fetchData()
        } catch {
          print(error)
        }
      }
  }
}

I can try adding `await` infant of the `apply` call, but this results into a `No 'async' operations occur within 'await' expression` warning.

I can apply two workarounds:

  • Make `apply(_: )` method `async` and add `await` infant of it as the compiler correctly would ask for, but this doesn't make sense as this should be a non-suspendible synchronous method just to hop back to the main thread and sign the value.

  • I can move `@MainActor` to the entire type and make `fetchData` as `nonisolated`, which works as intended, but the original example should also work and require the `await` keyword.

Discussion on the forum: https://forums.swift.org/t/mainactor-ignored-by-the-compiler/49533

Activity

  1. typesanitizer commented on Jun 15, 2021

    @typesanitizer

    @swift-ci create

  2. DougGregor commented on Dec 11, 2021

    @DougGregor
    Member

    This was fixed by #40388 and I'm adding a more-specific test in #40522

  3. swift-ci commented on Dec 19, 2021

    @swift-ci
    Contributor

    Comment by Erik Aigner (JIRA)

    I have the same issue, @MainActory should either make the method async implicitly or require the async keyword

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itself

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions