Skip to content

Commit aaf2f7e

Browse files
authored
Merge pull request #71438 from kavon/ncgenerics-test-fixes-kavon-v4
Ncgenerics test fixes kavon v4
2 parents 66ecb47 + 3dda59f commit aaf2f7e

14 files changed

+117
-80
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2537,8 +2537,8 @@ ERROR(invalid_nominal_extension,none,
25372537
(Type, Type))
25382538
NOTE(invalid_extension_rewrite,none,
25392539
"did you mean to extend %0 instead?", (Type))
2540-
ERROR(synthesized_nominal_extension,none,
2541-
"cannot extend synthesized type %0", (Type))
2540+
ERROR(cannot_extend_nominal,none,
2541+
"cannot extend %kind0", (const NominalTypeDecl *))
25422542

25432543
ERROR(retroactive_not_in_extension_inheritance_clause,none,
25442544
"'retroactive' attribute only applies in inheritance clauses in "

lib/AST/ProtocolConformance.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,20 +1076,10 @@ void NominalTypeDecl::prepareConformanceTable() const {
10761076
}
10771077

10781078
SmallPtrSet<ProtocolDecl *, 2> protocols;
1079-
const bool haveNoncopyableGenerics =
1080-
ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics);
1081-
10821079
auto addSynthesized = [&](ProtocolDecl *proto) {
10831080
if (!proto)
10841081
return;
10851082

1086-
// No synthesized conformances for move-only nominals.
1087-
if (!haveNoncopyableGenerics && !canBeCopyable()) {
1088-
// assumption is Sendable gets synthesized elsewhere.
1089-
assert(!proto->isSpecificProtocol(KnownProtocolKind::Sendable));
1090-
return;
1091-
}
1092-
10931083
if (protocols.count(proto) == 0) {
10941084
ConformanceTable->addSynthesizedConformance(
10951085
mutableThis, proto, mutableThis);
@@ -1099,12 +1089,22 @@ void NominalTypeDecl::prepareConformanceTable() const {
10991089

11001090
// Synthesize the unconditional conformances to invertible protocols.
11011091
// For conditional ones, see findSynthesizedConformances .
1102-
if (haveNoncopyableGenerics) {
1092+
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
1093+
bool missingOne = false;
11031094
for (auto ip : InvertibleProtocolSet::full()) {
11041095
auto invertible = getMarking(ip);
11051096
if (!invertible.getInverse() || bool(invertible.getPositive()))
11061097
addSynthesized(ctx.getProtocol(getKnownProtocolKind(ip)));
1098+
else
1099+
missingOne = true;
11071100
}
1101+
1102+
// FIXME: rdar://122289155 (NCGenerics: convert Equatable, Hashable, and RawRepresentable to ~Copyable.)
1103+
if (missingOne)
1104+
return;
1105+
1106+
} else if (!canBeCopyable()) {
1107+
return; // No synthesized conformances for move-only nominals.
11081108
}
11091109

11101110
// Add protocols for any synthesized protocol attributes.

lib/Sema/CSBindings.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -625,15 +625,11 @@ bool BindingSet::finalize(
625625
for (auto *constraint : *TransitiveProtocols) {
626626
Type protocolTy = constraint->getSecondType();
627627

628-
// The Copyable/Escapable protocols can't have members, yet will be a
629-
// constraint of basically all type variables, so don't suggest it.
630-
//
631-
// NOTE: worth considering for all marker protocols, but keep in
632-
// mind that you're allowed to extend them with members!
628+
// Compiler-known marker protocols cannot be extended with members,
629+
// so do not consider them.
633630
if (auto p = protocolTy->getAs<ProtocolType>()) {
634631
if (ProtocolDecl *decl = p->getDecl())
635-
if (decl->isSpecificProtocol(KnownProtocolKind::Copyable) ||
636-
decl->isSpecificProtocol(KnownProtocolKind::Escapable))
632+
if (decl->getKnownProtocolKind() && decl->isMarkerProtocol())
637633
continue;
638634
}
639635

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12004,9 +12004,10 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
1200412004
if (type1->isTypeVariableOrMember() || type2->isTypeVariableOrMember())
1200512005
return formUnsolved();
1200612006

12007-
// Noncopyable types can't be involved in bridging conversions since a bridged
12008-
// type assumes the ability to copy.
12009-
if (type1->isNoncopyable()) {
12007+
// Noncopyable & Nonescapable types can't be involved in bridging conversions
12008+
// since a bridged type assumes such abilities are granted.
12009+
if (!type1->hasTypeVariable()
12010+
&& (type1->isNoncopyable() || !type1->isEscapable())) {
1201012011
return SolutionKind::Error;
1201112012
}
1201212013

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,29 +1957,33 @@ TypeChecker::typeCheckCheckedCast(Type fromType, Type toType,
19571957

19581958
// A cast from a function type to an existential type (except `Any`)
19591959
// or an archetype type (with constraints) cannot succeed
1960-
auto toArchetypeType = toType->is<ArchetypeType>();
1961-
auto fromFunctionType = fromType->is<FunctionType>();
1962-
auto toExistentialType = toType->isAnyExistentialType();
1963-
1964-
auto toConstrainedArchetype = false;
1965-
if (toArchetypeType) {
1966-
auto archetype = toType->castTo<ArchetypeType>();
1967-
toConstrainedArchetype = !archetype->getConformsTo().empty();
1968-
}
1969-
1970-
if (fromFunctionType &&
1971-
(toExistentialType || (toArchetypeType && toConstrainedArchetype))) {
1972-
switch (contextKind) {
1973-
case CheckedCastContextKind::None:
1974-
case CheckedCastContextKind::ConditionalCast:
1975-
case CheckedCastContextKind::ForcedCast:
1976-
return CheckedCastKind::Unresolved;
1960+
if (fromType->is<FunctionType>()) {
1961+
auto toArchetypeType = toType->is<ArchetypeType>();
1962+
auto toExistentialType = toType->isAnyExistentialType();
1963+
1964+
auto conformsToAllProtocols = true;
1965+
if (toArchetypeType) {
1966+
auto archetype = toType->castTo<ArchetypeType>();
1967+
conformsToAllProtocols = llvm::all_of(archetype->getConformsTo(),
1968+
[&](ProtocolDecl *proto) {
1969+
return module->checkConformance(fromType, proto,
1970+
/*allowMissing=*/false);
1971+
});
1972+
}
19771973

1978-
case CheckedCastContextKind::IsPattern:
1979-
case CheckedCastContextKind::EnumElementPattern:
1980-
case CheckedCastContextKind::IsExpr:
1981-
case CheckedCastContextKind::Coercion:
1982-
break;
1974+
if (toExistentialType || (toArchetypeType && !conformsToAllProtocols)) {
1975+
switch (contextKind) {
1976+
case CheckedCastContextKind::None:
1977+
case CheckedCastContextKind::ConditionalCast:
1978+
case CheckedCastContextKind::ForcedCast:
1979+
return CheckedCastKind::Unresolved;
1980+
1981+
case CheckedCastContextKind::IsPattern:
1982+
case CheckedCastContextKind::EnumElementPattern:
1983+
case CheckedCastContextKind::IsExpr:
1984+
case CheckedCastContextKind::Coercion:
1985+
break;
1986+
}
19831987
}
19841988
}
19851989

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3676,6 +3676,16 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
36763676
return true;
36773677
}
36783678

3679+
/// Compiler-known marker protocols cannot be extended with members.
3680+
static void diagnoseExtensionOfMarkerProtocol(ExtensionDecl *ED) {
3681+
auto *nominal = ED->getExtendedNominal();
3682+
if (auto *proto = dyn_cast_or_null<ProtocolDecl>(nominal)) {
3683+
if (proto->getKnownProtocolKind() && proto->isMarkerProtocol()) {
3684+
ED->diagnose(diag::cannot_extend_nominal, nominal);
3685+
}
3686+
}
3687+
}
3688+
36793689
static void checkTupleExtension(ExtensionDecl *ED) {
36803690
auto *nominal = ED->getExtendedNominal();
36813691
if (!nominal || !isa<BuiltinTupleDecl>(nominal))
@@ -3878,6 +3888,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
38783888
TypeChecker::checkDistributedActor(SF, nominal);
38793889

38803890
diagnoseIncompatibleProtocolsForMoveOnlyType(ED);
3891+
diagnoseExtensionOfMarkerProtocol(ED);
38813892

38823893
checkTupleExtension(ED);
38833894
}

test/Concurrency/sendable_objc_protocol_attr.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,11 @@ struct MyStruct: Sendable {
3232
let value: any MyObjCProtocol // Ok
3333
}
3434

35-
extension Sendable {
36-
func compute() {}
37-
}
35+
func compute<T: Sendable>(_ t: T) {}
3836

3937
extension MyObjCProtocol {
4038
func test() {
41-
compute() // Ok
39+
compute(self) // Ok
4240
}
4341
}
4442

test/Constraints/static_members_on_protocol_in_generic_context.swift

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -350,21 +350,16 @@ func test_leading_dot_syntax_with_typelias() {
350350
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
351351
}
352352

353-
extension Copyable where Self == Int {
354-
static func answer() -> Int { 42 }
355-
}
353+
// User-defined marker protocols do gain the inference for members, since they
354+
// support extensions.
355+
@_marker protocol SomeMarkerProto {}
356+
extension Int: SomeMarkerProto {}
356357

357-
extension Escapable where Self == String {
358-
static func question() -> String { "" }
358+
extension SomeMarkerProto where Self == Int {
359+
static func answer() -> Int { 42 }
359360
}
360361

361362
do {
362-
func testCopyable<T: Copyable>(_: T) {}
363-
func testEscapable<T: Escapable>(_: T) {}
364-
365-
testCopyable(.answer())
366-
// expected-error@-1 {{cannot infer contextual base in reference to member 'answer'}}
367-
368-
testEscapable(.question())
369-
// expected-error@-1 {{cannot infer contextual base in reference to member 'question'}}
363+
func testSomeMarkerProto<T: SomeMarkerProto>(_: T) {}
364+
testSomeMarkerProto(.answer())
370365
}

test/Interpreter/casts.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,13 @@ Casts.test("testCastProtocolWithAnyObjectToProtocolCompoTypeSuperclass") {
142142
let shouldBeNil = (F() as QAny) as? KQAny
143143
expectNil(shouldBeNil)
144144
}
145+
146+
func f1() -> Any { return 1 }
147+
func attemptFunctionCast<U>(_ u: U.Type) -> U? {
148+
return f1 as? U
149+
}
150+
Casts.test("testFunctionCastToArchetype") {
151+
expectNil(attemptFunctionCast(Int.self))
152+
expectNil(attemptFunctionCast(K.self))
153+
expectTrue(attemptFunctionCast(Any.self) != nil)
154+
}

test/Interpreter/protocol_extensions.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import StdlibUnittest
55

6+
defer { runAllTests() }
67

78
var ProtocolExtensionTestSuite = TestSuite("ProtocolExtensions")
89

@@ -363,4 +364,12 @@ ProtocolExtensionTestSuite.test("WitnessSelf") {
363364
}
364365
}
365366

366-
runAllTests()
367+
@_marker protocol Addable {}
368+
extension Addable {
369+
func increment(this x: Int) -> Int { return x + 100 }
370+
}
371+
extension String: Addable {}
372+
373+
ProtocolExtensionTestSuite.test("MarkerProtocolExtensions") {
374+
expectTrue("hello".increment(this: 11) == 111)
375+
}

test/Sema/copyable.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ enum namespace {
2626

2727
func Copyable() -> Copyable { return 0 }
2828
}
29+
30+
extension Copyable { // expected-error {{cannot extend protocol 'Copyable'}}
31+
func hello() {}
32+
}

test/Sema/moveonly_sendable.swift

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,6 @@ func createContainer(_ fd: borrowing FileDescriptor) {
150150
let _: Container<Sendable> = Container(CopyableStruct())
151151
}
152152

153-
func takeTwo<T: Sendable>(_ s1: T, _ s2: T) {}
154-
155-
extension Sendable {
156-
func doIllegalThings() {
157-
return takeTwo(self, self)
158-
}
159-
}
160-
161-
func tryToDupe(_ fd: borrowing FileDescriptor) {
162-
// FIXME: this should describe 'Self' as 'any Sendable' or something.
163-
fd.doIllegalThings() // expected-error {{noncopyable type 'FileDescriptor' cannot be substituted for copyable generic parameter 'Self' in 'Sendable'}}
164-
}
165-
166153
@_moveOnly
167154
struct PaperAirplaneFile {
168155
var fd: FileDescriptor

test/decl/ext/extensions.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,3 +393,12 @@ extension B4 {
393393
// expected-error@-1 {{extension of existential type 'B4' (aka 'any P4') is not supported}}
394394
// expected-note@-2 {{did you mean to extend 'P4' instead?}} {{11-13=P4}}
395395
}
396+
397+
398+
extension Sendable {} // expected-error {{cannot extend protocol 'Sendable'}}
399+
extension Copyable {} // expected-error {{cannot extend protocol 'Copyable'}}
400+
extension Escapable {} // expected-error {{cannot extend protocol 'Escapable'}}
401+
extension _BitwiseCopyable {} // expected-error {{cannot extend protocol '_BitwiseCopyable'}}
402+
403+
@_marker protocol MyMarkerProto {}
404+
extension MyMarkerProto {} // OK

test/expr/cast/as_coerce.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ protocol P_48579 {}
119119
do {
120120
func f1() -> Any {}
121121
func f2() {}
122+
@Sendable func f3() {}
122123

123124
_ = f1 is P_48579 // expected-warning {{cast from '() -> Any' to unrelated type 'any P_48579' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{9-9=()}}
124125
_ = f1 as! P_48579 // expected-warning {{cast from '() -> Any' to unrelated type 'any P_48579' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{9-9=()}}
@@ -133,20 +134,32 @@ do {
133134
_ = f2 as? Any // expected-warning {{conditional cast from '() -> ()' to 'Any' always succeeds}}
134135

135136

136-
func test1<T: P_48579>(_: T.Type) {
137+
func test1<T: P_48579, V: P_48579 & Sendable>(_: T.Type, _: V.Type) {
137138
_ = f1 is T // expected-warning {{cast from '() -> Any' to unrelated type 'T' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
138-
_ = f1 as! T // expected-warning {{cast from '() -> Any' to unrelated type 'T' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
139+
_ = f1 as! V // expected-warning {{cast from '() -> Any' to unrelated type 'V' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
139140
_ = f1 as? T // expected-warning {{cast from '() -> Any' to unrelated type 'T' always fails}} // expected-note {{did you mean to call 'f1' with '()'?}}{{11-11=()}}
140141
_ = f2 is T // expected-warning {{cast from '() -> ()' to unrelated type 'T' always fails}}
141-
_ = f2 as! T // expected-warning {{cast from '() -> ()' to unrelated type 'T' always fails}}
142+
_ = f2 as! V // expected-warning {{cast from '() -> ()' to unrelated type 'V' always fails}}
142143
_ = f2 as? T // expected-warning {{cast from '() -> ()' to unrelated type 'T' always fails}}
144+
_ = f3 is T // expected-warning {{cast from '@Sendable () -> ()' to unrelated type 'T' always fails}}
145+
_ = f3 as! V // expected-warning {{cast from '@Sendable () -> ()' to unrelated type 'V' always fails}}
146+
_ = f3 as? T // expected-warning {{cast from '@Sendable () -> ()' to unrelated type 'T' always fails}}
143147
}
144148

145-
func test2<U>(_: U.Type) {
149+
func test2<U, S: Sendable>(_: U.Type, _: S.Type) {
150+
_ = f1 is U // Okay
146151
_ = f1 as! U // Okay
147152
_ = f1 as? U // Okay
153+
_ = f1 is U // Okay
148154
_ = f2 as! U // Okay
149155
_ = f2 as? U // Okay
156+
157+
_ = f2 is S // expected-warning {{cast from '() -> ()' to unrelated type 'S' always fails}}
158+
_ = f2 as! S // expected-warning {{cast from '() -> ()' to unrelated type 'S' always fails}}
159+
_ = f2 as? S // expected-warning {{cast from '() -> ()' to unrelated type 'S' always fails}}
160+
_ = f3 is S // Okay
161+
_ = f3 as! S // Okay
162+
_ = f3 as? S // Okay
150163
}
151164
}
152165

0 commit comments

Comments
 (0)