最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - @preconcurrency import does not silence Sendable warning - Stack Overflow

programmeradmin3浏览0评论

I have this Objective-C framework FooModule:

// Foo2.h

#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN

typedef void (^Reply)(id data);
typedef void (^Handler)(Reply reply);

@interface Foo2 : NSObject
- (id)initWithQueue: (dispatch_queue_t)queue;
- (void)setupHandler: (Handler)handler;
@end
NS_ASSUME_NONNULL_END
// Foo2.m

#import "Foo2.h"

@implementation Foo2 {
  dispatch_queue_t _queue;
}
- (id)initWithQueue: (dispatch_queue_t)queue {
  if ((self = [super init])) {
    _queue = queue;
  }
  return self;
}

- (void)setupHandler:(Handler)handler {
  dispatch_async(_queue, ^{
    handler(^(id data){
      NSLog(@"data is %@", data);
    });
  });
}
@end

Then in my app binary, I do

@preconcurrency import FooModule
func aGlobalFreeFunction() {

  let foo = Foo2(queue: .global())
  foo.setupHandler { reply in
    Task {
      reply("foo")
    }
  }
}

This gives me error (not warning) in swift 6 mode:

Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure

I wonder why @preconcurrency import doesn't silence the error.

I tried out another non-closure type:

@interface FooNonSendable : NSObject
@property int foo;
@end

@implementation FooNonSendable
@end

Then in my swift code, after using @preconcurrent import:



func aGlobalFreeFunction() {
  let fooNonSendable = FooNonSendable()

  Task {
    Task { @MainActor in
      print(fooNonSendable)
    }
  }
}

This code does not give any errors or warnings, meaning that @preconcurrency is able to silence error for fooNonSendable, but not reply closure.

I have this Objective-C framework FooModule:

// Foo2.h

#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN

typedef void (^Reply)(id data);
typedef void (^Handler)(Reply reply);

@interface Foo2 : NSObject
- (id)initWithQueue: (dispatch_queue_t)queue;
- (void)setupHandler: (Handler)handler;
@end
NS_ASSUME_NONNULL_END
// Foo2.m

#import "Foo2.h"

@implementation Foo2 {
  dispatch_queue_t _queue;
}
- (id)initWithQueue: (dispatch_queue_t)queue {
  if ((self = [super init])) {
    _queue = queue;
  }
  return self;
}

- (void)setupHandler:(Handler)handler {
  dispatch_async(_queue, ^{
    handler(^(id data){
      NSLog(@"data is %@", data);
    });
  });
}
@end

Then in my app binary, I do

@preconcurrency import FooModule
func aGlobalFreeFunction() {

  let foo = Foo2(queue: .global())
  foo.setupHandler { reply in
    Task {
      reply("foo")
    }
  }
}

This gives me error (not warning) in swift 6 mode:

Passing closure as a 'sending' parameter risks causing data races between code in the current task and concurrent execution of the closure

I wonder why @preconcurrency import doesn't silence the error.

I tried out another non-closure type:

@interface FooNonSendable : NSObject
@property int foo;
@end

@implementation FooNonSendable
@end

Then in my swift code, after using @preconcurrent import:



func aGlobalFreeFunction() {
  let fooNonSendable = FooNonSendable()

  Task {
    Task { @MainActor in
      print(fooNonSendable)
    }
  }
}

This code does not give any errors or warnings, meaning that @preconcurrency is able to silence error for fooNonSendable, but not reply closure.

Share Improve this question edited Feb 4 at 23:53 HL666 asked Jan 31 at 18:43 HL666HL666 1055 bronze badges 8
  • @preconcurrency reduces an error to a warning. It does not make the facts magically go away. – matt Commented Feb 1 at 0:58
  • @matt re- "preconcurrency reduces an error to a warning. It does not make the facts magically go away." I believe this is false, with preconcurrency import, I was able to silence the error for a non-closure type. see my new code added at the end – HL666 Commented Feb 1 at 1:38
  • I wasn't able to get any error from the code you originally showed, so I could not comment directly on your assertions. – matt Commented Feb 1 at 16:10
  • @matt did you enable swift 6? – HL666 Commented Feb 1 at 22:42
  • Sorry what is a GAIT? The code is inside viewDidLoad of an empty template project (i didn't know it matters, but i was clearly wrong, sorry) – HL666 Commented Feb 4 at 1:29
 |  Show 3 more comments

1 Answer 1

Reset to default 1

You ask why “@preconcurrency import does not silence Sendable warning?”

The error you are receiving is not about trying to send a non-Sendable type. It is about your use of this sending closure (as outlined in SE-0430), which is an specific extension to region-based isolation. Do not conflate Sendable types with sending parameters; they are two different things. The @preconcurrency import addresses the former (temporarily silencing non-Sendable warnings for legacy types that have not gone through a review for concurrency), but not the latter.

发布评论

评论列表(0)

  1. 暂无评论