swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67k stars 10.32k forks source link

Warning suggests `@preconcurrency import` but when added, there is a warning that `@preconcurrency import` has no effect. #74904

Open jqsilver opened 1 week ago

jqsilver commented 1 week ago

Description

When I compile a class that implements WKNavigationDelegate, I get a warning on the line with import WebKit: Add '@preconcurrency' to suppress 'Sendable'-related warnings from module 'WebKit' However, there are no Sendable-related warnings in the file.

When I add the @preconcurrency to the import WebKit statement, I get this warning: '@preconcurrency' attribute on module 'WebKit' has no effect

Eventually I determined that the WKNavigationDelegate methods were outdated for iOS 18, and I needed to add a @MainActor attribute to a closure in one of the delegate methods.

Reproduction

I created a new project using Xcode 16 beta 2, and then added this code as a new file.

import UIKit
import WebKit  // warning: `Add '@preconcurrency' to suppress 'Sendable'-related warnings from module 'WebKit'`

public final class SmartHTMLView: UIView, WKNavigationDelegate {

  public override init(frame: CGRect) {
    super.init(frame: frame)
    addSubview(webView)
    webView.navigationDelegate = self
  }

  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  private let webView = WKWebView(frame: .zero)

  public func webView(
    _: WKWebView,
    decidePolicyFor navigationAction: WKNavigationAction,
    decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
  {
  }
}

When I add the @preconcurrency attribute, I get a different warning.

import UIKit
@preconcurrency import WebKit  // warning: `'@preconcurrency' attribute on module 'WebKit' has no effect`

public final class SmartHTMLView: UIView, WKNavigationDelegate {

  public override init(frame: CGRect) {
    super.init(frame: frame)
    addSubview(webView)
    webView.navigationDelegate = self
  }

  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  private let webView = WKWebView(frame: .zero)

  public func webView(
    _: WKWebView,
    decidePolicyFor navigationAction: WKNavigationAction,
    decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
  {
  }
}

I was able to fix the warnings by updating webView(:decidePolicyFor:decisionHandler:) method to match the iOS 18 WKNavigationDelegate API:

import UIKit
import WebKit

public final class SmartHTMLView: UIView, WKNavigationDelegate {

  public override init(frame: CGRect) {
    super.init(frame: frame)
    addSubview(webView)
    webView.navigationDelegate = self
  }

  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  private let webView = WKWebView(frame: .zero)

  public func webView(
    _: WKWebView,
    decidePolicyFor navigationAction: WKNavigationAction,
    decisionHandler: @escaping @MainActor (WKNavigationActionPolicy) -> Void)
  {
  }
}

Expected behavior

  1. A warning suggesting that @preconcurrency be added should not be emitted when there are no Sendable-related warnings in the file.
  2. There should be a warning that the following method doesn't match the updated WKNavigationDelegate protocol:
  public func webView(
     _: WKWebView,
     decidePolicyFor navigationAction: WKNavigationAction,
     decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
   {
   }

Environment

WebKitImportPreconcurrencyRepro (main)$ swiftc -version swift-driver version: 1.110 Apple Swift version 6.0 (swiftlang-6.0.0.4.52 clang-1600.0.21.1.3) Target: arm64-apple-macosx14.0

Additional information

No response

mikaelacaron commented 1 week ago

I am having this same issue! But when importing TabletopKit, without making any changes, it's happening to the TabletopKit sample project that you can download here: https://developer.apple.com/documentation/tabletopkit/tabletopkitsample

I'm using Xcode 16.0 Beta 2, on macOS 14.5

drewolbrich commented 6 days ago

Thank you so much for posting this. I spent quite a lot of time trying to figure this one out, and wasn't able to discover your webView(:decidePolicyFor:decisionHandler:) @MainActor fix myself.

I submitted feedback about the circular warning issue to Apple as FB14066938.

jqsilver commented 6 days ago

I noticed that with Xcode 16 beta 3 this protocol has been updated:

optional func webView(
    _ webView: WKWebView,
    decidePolicyFor navigationAction: WKNavigationAction,
    decisionHandler: @escaping @MainActor @Sendable (WKNavigationActionPolicy) -> Void
)

Note that the decisionHandler is now also @Sendable.

drewolbrich commented 6 days ago

I don't know if this is significant, but Xcode autocomplete does not include @Sendable:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, 
    decisionHandler: @escaping @MainActor (WKNavigationActionPolicy) -> Void) {
    // ...
}

I do see @Sendable in the corresponding method definition in the definition of WKNavigationDelegate, however.

jqsilver commented 4 days ago

I verified that these two warnings still occur in Xcode 16 beta 3, although it still goes away with just the @MainActor attribute and without the @Sendable attribute