Skip to content

Instantly share code, notes, and snippets.

@DougGregor
DougGregor / conformance_search.swift
Created January 20, 2017 18:01
SubstitutionMap conformance search
protocol P { }
protocol Q {
associatedtype Assoc
func assoc() -> Assoc
}
protocol R : Q {
associatedtype Assoc: P
}
@DougGregor
DougGregor / false_recursion.swift
Created February 24, 2017 05:44
False recursion
protocol P {
associatedtype PType
}
public protocol Q {
associatedtype QType: R
}
public protocol R {
associatedtype RType
@DougGregor
DougGregor / subpaths.swift
Created March 8, 2017 17:13
Trivial yet fun example for requirement signatures and conformance access paths
protocol P { }
protocol Q {
associatedtype A: P
}
protocol R: Q {
associatedtype A: P
}
protocol Fooable {
associatedtype Foo
}
protocol Barrable {
associatedtype Bar: Fooable
}
struct X {}
struct Y: Fooable {
@DougGregor
DougGregor / recursive-constraints.md
Last active February 3, 2019 08:45
Implementing Recursive Protocol Constraints

Implementing Recursive Protocol Constraints

Recursive protocol constraints are a small-looking feature (really, eliminating a limitation that feels arbitrary to users) that can also greatly improve the standard library. However, their implementation will require a number of changes throughout the Swift compiler. This document attempts to catalogue the kinds of changes required in the compiler to implement this feature, to provide some scoping and direction for the work.

ArchetypeBuilder

The ArchetypeBuilder is responsible for processing the requirements in a protocol, generic function, generic type, or extension of a generic type to determine whether they are consistent. It also plays a central role in producing and canonicalizing generic signatures, as well as producing archetypes for a generic signature in a given generic environment. It is where recursive protocol constraints are detected and diagnosed, and the primary place where we will need to deal with recursion.

Lazily expand nested t

@DougGregor
DougGregor / scan-type-metadata.patch
Created August 9, 2019 00:15
Scan type metadata to populate the context descriptor cache
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index 49ff72a487a..472dcbe0afd 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -237,7 +237,8 @@ struct TypeMetadataPrivateState {
llvm::DenseMap<llvm::StringRef,
llvm::TinyPtrVector<const ContextDescriptor *>>
ContextDescriptorCache;
- size_t ContextDescriptorLastSectionScanned = 0;
+ size_t ConformanceDescriptorLastSectionScanned = 0;
@DougGregor
DougGregor / actor_counters.swift
Last active December 18, 2020 04:55
Actor counters example
#if canImport(Darwin)
import Darwin
#elseif canImport(Glibc)
import Glibc
#endif
actor class Counter {
private var value = 0
private let scratchBuffer: UnsafeMutableBufferPointer<Int>
@DougGregor
DougGregor / initiating-async-work.md
Created April 26, 2021 20:26
Initiating async work from synchronous code

Initiating async work from synchronous code

Motivation

Swift async functions can only directly be called from other async functions. In synchronous code, the only mechanism provided by the Swift Concurrency model to create asynchronous work is detach. The detach operation creates a new, detached task that is completely independent of the code that initiated the detach: the closure executes concurrently, is independent of any actor unless it explicitly opts into an actor, and does not inherit certain information (such as priority).

Detached tasks are important and have their place, but they don't map well to cases where the natural "flow" of control is from the synchronous function into async code, e.g., when reacting to an event triggered in a UI:

@MainActor func saveResults() {
@DougGregor
DougGregor / dynamic_member_lookup_environment.swift
Created May 2, 2018 16:59
Using Swift 4.2's @dynamicMemberLookup to expose environment variables
import Darwin
@dynamicMemberLookup
struct Environment {
subscript(dynamicMember name: String) -> String? {
get {
guard let value = getenv(name) else { return nil }
return String(validatingUTF8: value)
}