[CSDiagnostics/Tests] Add tests for any Sendable vs. Any interaction in non-strict concurrency contexts

This commit is contained in:
Pavel Yaskevich
2024-12-13 09:35:34 -08:00
parent fb54682753
commit c8f3524961
3 changed files with 171 additions and 0 deletions

View File

@@ -2798,6 +2798,9 @@ ERROR(types_not_inherited_decl,none,
ERROR(types_not_inherited_in_decl_ref,none,
"referencing %kind0 on %1 requires that %2 inherit from %3",
(const ValueDecl *, Type, Type, Type))
ERROR(cannot_reference_conditional_member_on_base_multiple_mismatches,none,
"cannot reference %kind0 on %1",
(const ValueDecl *, Type))
NOTE(where_requirement_failure_one_subst,none,
"where %0 = %1", (Type, Type))
NOTE(where_requirement_failure_both_subst,none,

View File

@@ -1044,6 +1044,34 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
break;
}
case ConstraintLocator::Member: {
auto *memberLoc = getConstraintLocator(anchor, path);
auto selectedOverload = getOverloadChoiceIfAvailable(memberLoc);
if (!selectedOverload)
return false;
auto baseTy = selectedOverload->choice.getBaseType()->getRValueType();
auto *memberRef = selectedOverload->choice.getDecl();
if (Mismatches.size() == 1) {
auto mismatchIdx = Mismatches.front();
auto actualArgTy = getActual()->getGenericArgs()[mismatchIdx];
auto requiredArgTy = getRequired()->getGenericArgs()[mismatchIdx];
emitDiagnostic(diag::types_not_equal_in_decl_ref, memberRef, baseTy,
actualArgTy, requiredArgTy);
emitDiagnosticAt(memberRef, diag::decl_declared_here, memberRef);
return true;
}
emitDiagnostic(
diag::cannot_reference_conditional_member_on_base_multiple_mismatches,
memberRef, baseTy);
emitDiagnosticAt(memberRef, diag::decl_declared_here, memberRef);
emitNotesForMismatches();
return true;
}
default:
break;
}

View File

@@ -0,0 +1,140 @@
// RUN: %target-typecheck-verify-swift
// RUN: %target-typecheck-verify-swift -swift-version 5 -strict-concurrency=complete -verify-additional-prefix swift6-
// RUN: %target-typecheck-verify-swift -swift-version 6 -verify-additional-prefix swift6-
class User {
@preconcurrency var dict: [String : any Sendable] = [:]
@preconcurrency var arr: [any Sendable] = []
// Note: No Set because `any Sendable` is not Hashable
}
extension Dictionary where Key == String, Value == Any {
func onlyWhenValueAny() {} // expected-swift6-note {{'onlyWhenValueAny()' declared here}}
}
extension Array where Element == Any {
func onlyWhenValueAny() {} // expected-swift6-note {{'onlyWhenValueAny()' declared here}}
}
func test_conditional_on_collections(u: User) {
u.dict.onlyWhenValueAny() // Ok with non-strict concurrency
// expected-swift6-error@-1 {{referencing instance method 'onlyWhenValueAny()' on '[String : any Sendable]' requires the types 'any Sendable' and 'Any' be equivalent}}
u.arr.onlyWhenValueAny() // Ok with non-strict concurrency
// expected-swift6-error@-1 {{referencing instance method 'onlyWhenValueAny()' on '[any Sendable]' requires the types 'any Sendable' and 'Any' be equivalent}}
}
// Check that `any Sendable` extension is preferred.
extension Dictionary where Key == String, Value == Any {
func noAmbiguity() {}
}
extension Array where Element == Any {
func noAmbiguity() {}
}
extension Dictionary where Key == String, Value == any Sendable {
func noAmbiguity() {}
}
extension Array where Element == any Sendable {
func noAmbiguity() {}
}
func test_no_ambiguity_with_Sendable_extension(u: User) {
u.dict.noAmbiguity() // Ok in general
u.arr.noAmbiguity() // Ok in general
}
struct S<T> {
// expected-note@-1 3 {{arguments to generic parameter 'T' ('any Sendable' and 'Any') are expected to be equal}}
// expected-note@-2 4 {{arguments to generic parameter 'T' ('(any Sendable) -> Void' and '(Any) -> Void') are expected to be equal}}
// expected-swift6-note@-3 3 {{arguments to generic parameter 'T' ('any Sendable' and 'Any') are expected to be equal}}
}
extension S where T == Any {
func anyOnly() {} // expected-note {{'anyOnly()' declared here}} expected-swift6-note {{'anyOnly()' declared here}}
}
struct TestGeneral {
@preconcurrency var v: S<any Sendable>
@preconcurrency var optV: S<[(any Sendable)?]>
@preconcurrency var nonOptV: S<[any Sendable]>
@preconcurrency var funcV: S<((any Sendable)) -> Void>
var regularV: S<any Sendable>
var regularOptV: S<[(any Sendable)?]>
var regularFuncV: S<((any Sendable)) -> Void>
func accepts_any(_: S<Any>) {}
func accepts_opt_any(_: S<[Any?]>) {}
func accepts_func_any(_: S<(Any) -> Void>) {}
func test_contextual() -> S<Any> {
v // Ok with non-strict concurrency
// expected-swift6-error@-1 {{cannot convert return expression of type 'S<any Sendable>' to return type 'S<Any>'}}
}
func test_contextual_error() -> S<Any> {
regularV // expected-error {{cannot convert return expression of type 'S<any Sendable>' to return type 'S<Any>'}}
}
func test_member_ref() {
v.anyOnly() // Ok with non-strict concurrency
// expected-swift6-error@-1 {{referencing instance method 'anyOnly()' on 'S<any Sendable>' requires the types 'any Sendable' and 'Any' be equivalent}}
regularV.anyOnly()
// expected-error@-1 {{referencing instance method 'anyOnly()' on 'S<any Sendable>' requires the types 'any Sendable' and 'Any' be equivalent}}
}
func test_passing_as_argument(t: TestGeneral) {
accepts_any(v) // Ok with non-strict concurrency
// expected-swift6-error@-1 {{cannot convert value of type 'S<any Sendable>' to expected argument type 'S<Any>'}}
accepts_any(t.v) // Ok with non-strict concurrency
// expected-swift6-error@-1 {{cannot convert value of type 'S<any Sendable>' to expected argument type 'S<Any>'}}
accepts_any(regularV) // expected-error {{cannot convert value of type 'S<any Sendable>' to expected argument type 'S<Any>'}}
accepts_any(t.regularV) // expected-error {{cannot convert value of type 'S<any Sendable>' to expected argument type 'S<Any>'}}
}
func test_complex_contextual() -> S<[Any?]> {
optV // Ok with non-strict concurrency
// expected-swift6-error@-1 {{cannot convert return expression of type 'S<[(any Sendable)?]>' to return type 'S<[Any?]>'}}
// expected-swift6-note@-2 {{arguments to generic parameter 'Wrapped' ('any Sendable' and 'Any') are expected to be equal}}
}
func test_complex_contextual_error() {
let _: S<[Any?]> = optV // Ok with non-strict concurrency
// expected-swift6-error@-1 {{cannot assign value of type 'S<[(any Sendable)?]>' to type 'S<[Any?]>'}}
// expected-swift6-note@-2 {{arguments to generic parameter 'Wrapped' ('any Sendable' and 'Any') are expected to be equal}}
let _: S<[Any?]> = nonOptV // expected-error {{cannot assign value of type 'S<[any Sendable]>' to type 'S<[Any?]>'}}
// expected-note@-1 {{arguments to generic parameter 'Element' ('any Sendable' and 'Any?') are expected to be equal}}
let _: S<[Any?]> = regularOptV // expected-error {{cannot assign value of type 'S<[(any Sendable)?]>' to type 'S<[Any?]>'}}
// expected-note@-1 {{arguments to generic parameter 'Wrapped' ('any Sendable' and 'Any') are expected to be equal}}
}
func test_complex_with_argument(t: TestGeneral) {
accepts_opt_any(optV) // Ok with non-strict concurrency
// expected-swift6-error@-1 {{cannot convert value of type 'S<[(any Sendable)?]>' to expected argument type 'S<[Any?]>'}}
// expected-swift6-note@-2 {{arguments to generic parameter 'Wrapped' ('any Sendable' and 'Any') are expected to be equal}}
accepts_opt_any(t.optV) // Ok with non-strict concurrency
// expected-swift6-error@-1 {{cannot convert value of type 'S<[(any Sendable)?]>' to expected argument type 'S<[Any?]>'}}
// expected-swift6-note@-2 {{arguments to generic parameter 'Wrapped' ('any Sendable' and 'Any') are expected to be equal}}
accepts_opt_any(nonOptV) // expected-error {{cannot convert value of type 'S<[any Sendable]>' to expected argument type 'S<[Any?]>'}}
// expected-note@-1 {{arguments to generic parameter 'Element' ('any Sendable' and 'Any?') are expected to be equal}}
accepts_opt_any(t.nonOptV) // expected-error {{cannot convert value of type 'S<[any Sendable]>' to expected argument type 'S<[Any?]>'}}
// expected-note@-1 {{arguments to generic parameter 'Element' ('any Sendable' and 'Any?') are expected to be equal}}
accepts_opt_any(regularOptV) // expected-error {{cannot convert value of type 'S<[(any Sendable)?]>' to expected argument type 'S<[Any?]>'}}
// expected-note@-1 {{arguments to generic parameter 'Wrapped' ('any Sendable' and 'Any') are expected to be equal}}
}
func test_no_function_conversions() {
let _: S<(Any) -> Void> = funcV // expected-error {{cannot assign value of type 'S<(any Sendable) -> Void>' to type 'S<(Any) -> Void>'}}
let _: S<(Any) -> Void> = regularFuncV // expected-error {{cannot assign value of type 'S<(any Sendable) -> Void>' to type 'S<(Any) -> Void>'}}
accepts_func_any(funcV)
// expected-error@-1 {{cannot convert value of type 'S<(any Sendable) -> Void>' to expected argument type 'S<(Any) -> Void>'}}
accepts_func_any(regularFuncV)
// expected-error@-1 {{cannot convert value of type 'S<(any Sendable) -> Void>' to expected argument type 'S<(Any) -> Void>'}}
}
}