Skip to content

Commit 5bdd4e5

Browse files
committed
Improve @_implements for associated type witnesses
Allow `@_implements` to be expressed in an extension of the protocol in which the associated type is defined. Use this to uncomment an intended use of `@_implements` in `Sequence` that could be used to replace a longstanding hack for associated type inference. Since this change means that the standard library module interface won't be accepted by older compilers, introduce a suppressible feature ssociatedTypeImplements` that covers the use of `@_implements` on type declarations. This will hide the `@_implements` attribute from older compilers.
1 parent acc07db commit 5bdd4e5

File tree

7 files changed

+24
-7
lines changed

7 files changed

+24
-7
lines changed

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ SUPPRESSIBLE_LANGUAGE_FEATURE(Extern, 0, "@_extern")
169169
LANGUAGE_FEATURE(ExpressionMacroDefaultArguments, 422, "Expression macro as caller-side default argument")
170170
LANGUAGE_FEATURE(BuiltinStoreRaw, 0, "Builtin.storeRaw")
171171
LANGUAGE_FEATURE(BuiltinCreateTask, 0, "Builtin.createTask and Builtin.createDiscardingTask")
172+
SUPPRESSIBLE_LANGUAGE_FEATURE(AssociatedTypeImplements, 0, "@_implements on associated types")
172173

173174
// Swift 6
174175
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,6 +3083,14 @@ static void suppressingFeatureIsolatedAny(PrintOptions &options,
30833083
action();
30843084
}
30853085

3086+
static void suppressingFeatureAssociatedTypeImplements(PrintOptions &options,
3087+
llvm::function_ref<void()> action) {
3088+
unsigned originalExcludeAttrCount = options.ExcludeAttrList.size();
3089+
options.ExcludeAttrList.push_back(DeclAttrKind::Implements);
3090+
action();
3091+
options.ExcludeAttrList.resize(originalExcludeAttrCount);
3092+
}
3093+
30863094
/// Suppress the printing of a particular feature.
30873095
static void suppressingFeature(PrintOptions &options, Feature feature,
30883096
llvm::function_ref<void()> action) {

lib/AST/FeatureSet.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ static bool usesFeatureExtern(Decl *decl) {
342342
return decl->getAttrs().hasAttribute<ExternAttr>();
343343
}
344344

345+
static bool usesFeatureAssociatedTypeImplements(Decl *decl) {
346+
return isa<TypeDecl>(decl) && decl->getAttrs().hasAttribute<ImplementsAttr>();
347+
}
348+
345349
static bool usesFeatureExpressionMacroDefaultArguments(Decl *decl) {
346350
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
347351
for (auto param : *func->getParameters()) {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3886,7 +3886,7 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {
38863886
// conforms to the specified protocol.
38873887
NominalTypeDecl *NTD = DC->getSelfNominalTypeDecl();
38883888
if (auto *OtherPD = dyn_cast<ProtocolDecl>(NTD)) {
3889-
if (!OtherPD->inheritsFrom(PD) &&
3889+
if (!(OtherPD == PD || OtherPD->inheritsFrom(PD)) &&
38903890
!(OtherPD->isSpecificProtocol(KnownProtocolKind::DistributedActor) ||
38913891
PD->isSpecificProtocol(KnownProtocolKind::Actor))) {
38923892
diagnose(attr->getLocation(),

stdlib/public/Distributed/DistributedActor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,4 +448,4 @@ public protocol _DistributedActorStub where Self: DistributedActor {}
448448
@available(SwiftStdlib 6.0, *)
449449
public func _distributedStubFatalError(function: String = #function) -> Never {
450450
fatalError("Unexpected invocation of distributed method '\(function)' stub!")
451-
}
451+
}

stdlib/public/core/Sequence.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ public protocol Sequence<Element> {
453453
// Provides a default associated type witness for Iterator when the
454454
// Self type is both a Sequence and an Iterator.
455455
extension Sequence where Self: IteratorProtocol {
456-
// @_implements(Sequence, Iterator)
456+
@_implements(Sequence, Iterator)
457457
public typealias _Default_Iterator = Self
458458
}
459459

test/ModuleInterface/async_sequence_conformance.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,21 @@
44

55
// REQUIRES: concurrency, OS=macosx
66

7-
// CHECK: @available(
8-
// CHECK-NEXT: public struct SequenceAdapte
7+
// CHECK: public struct SequenceAdapte
98
@available(SwiftStdlib 5.1, *)
109
public struct SequenceAdapter<Base: AsyncSequence>: AsyncSequence {
1110
// CHECK-LABEL: public struct AsyncIterator
1211
// CHECK: @available{{.*}}macOS 10.15
1312
// CHECK-NEXT: public typealias Element = Base.Element
13+
14+
// CHECK: #if compiler(>=5.3) && $AssociatedTypeImplements
1415
// CHECK: @available(
1516
// CHECK: @_implements(_Concurrency.AsyncIteratorProtocol, Failure)
1617
// CHECK-SAME: public typealias __AsyncIteratorProtocol_Failure = Base.Failure
18+
// CHECK-NEXT: #else
19+
// CHECK-NOT: @_implements
20+
// CHECK: public typealias __AsyncIteratorProtocol_Failure = Base.Failure
21+
// CHECK-NEXT: #endif
1722
public typealias Element = Base.Element
1823

1924
public struct AsyncIterator: AsyncIteratorProtocol {
@@ -28,8 +33,7 @@ public struct SequenceAdapter<Base: AsyncSequence>: AsyncSequence {
2833
// CHECK-SAME: public typealias __AsyncSequence_Failure = Base.Failure
2934
}
3035

31-
// CHECK: @available(
32-
// CHECK-NEXT: public struct OtherSequenceAdapte
36+
// CHECK: public struct OtherSequenceAdapte
3337
@available(SwiftStdlib 5.1, *)
3438
public struct OtherSequenceAdapter<Base: AsyncSequence>: AsyncSequence {
3539
// CHECK: public typealias Element = Base.Element

0 commit comments

Comments
 (0)