Swift 3.1 makes dependency state explicit
Swift 3.1 separates editable dependencies from managed checkouts and records dependency versions. Tools-version declarations also let package authors adopt new tools without excluding every older client.
A dependency checkout has two different roles when an application author starts repairing the dependency itself. It remains an input to the application build, but it also becomes a working copy whose changes need protection from routine package updates. Swift 3.1 makes that distinction explicit with editable packages. The package manager can manage ordinary dependencies while leaving an intentionally edited dependency under the developer's control.
The March 27 release announcement places this change alongside version pinning and tools-version declarations. Together they describe different parts of dependency state. An editable package records who controls a checkout. A pin records which version a build should resolve. The tools version declares what the package requires to interpret its manifest. These mechanisms answer different questions, so using one does not remove the need for the others.
I like Swift's deliberate treatment of state, particularly its value collections and explicit optional values. Applying similar care to package management makes the build easier to understand. A developer should be able to tell whether a dependency is an ordinary resolved input or a working copy that contains changes intended for a separate contribution.
Editing is a declared operation
Package dependencies now live in the tool-managed build directory by default. The new editing command moves a dependency into the Packages directory under user control. While editable, it is exempt from dependency updates, and the developer can commit and push changes to that package. This is a meaningful change in responsibility for the checkout.
For a dependency named Utility, editing begins with the following operation. The package name identifies the dependency whose checkout needs that special treatment.
swift package edit Utility
The important behavior is the exemption from dependency updates. Without a distinction between managed inputs and working copies, a normal attempt to refresh dependencies can conflict with local development. Explicit editing gives the package manager information that it cannot reliably infer from the purpose of an arbitrary local change.
This workflow also keeps the relationship between an application and a dependency contribution visible. A repair can be developed while building the consuming application, yet remain a change to the dependency's own repository. The release announcement specifically describes the ability to commit and push from the editable package. It does not suggest that the application should take ownership of the dependency's source history.
Pins record a resolution
Swift 3.1 records dependency versions in Package.pins. The file can be checked in so other users of the package can share those versions. Dependency resolution fetches pinned versions by default. The swift package pin and swift package unpin commands provide explicit control over that state.
Updating dependencies has a different meaning. swift package update resolves the latest versions allowed by the package's constraints and updates the pinfile. A normal resolution can therefore preserve the recorded selection, while an explicit update asks the resolver to reconsider it. The distinction makes a dependency refresh an identifiable operation instead of an incidental consequence of every build.
A pin and an editable checkout should not be confused. The pinfile records a version selection that other users can reproduce. Editable state protects a particular working copy while its source changes. Sharing a pin does not share uncommitted work, and deciding to edit a dependency does not by itself explain which released version other users should consume. Each mechanism makes one part of the build's inputs explicit.
The release also corrects dependency-resolution cases that could previously select incorrect versions. That repair matters alongside pinning because the selected versions still need to satisfy the package graph. Recording a selection is useful only when the resolution leading to it is correct. Swift 3.1 also detects dependency cycles during a build, making another invalid relationship visible to the developer.
The manifest has its own version requirement
Packages can now declare their minimum Swift tools version at the top of Package.swift. The swift package tools-version command edits that requirement. The selected minimum determines both the Swift language version used to interpret the manifest and the available version of the PackageDescription API.
Dependency resolution ignores package versions that require newer tools than the client has. That permits a package author to publish a version using newer manifest capabilities without making every older client fail on that version's manifest. An older client can still resolve a compatible package version. The requirement therefore participates in version selection before an unsuitable manifest becomes the build's input.
Package source has a related but distinct compatibility declaration. Swift 3.1 lets a package specify whether its sources use Swift 3 or Swift 4 language rules. When unspecified, the package manager infers a default from the minimum tools version. Keeping the source language and manifest interpretation conceptually separate is useful even when the default relates them. The manifest describes a build, while the package's sources implement its libraries or executables.
The December release plan promised a limited, source-compatible update with package-manager improvements. These declarations fit that direction. They let the ecosystem express requirements as package metadata while preserving a route for clients whose tools have not yet moved forward.
The runtime libraries also need platform work
Swift 3.1 remains source compatible with Swift 3.0, but its Linux work shows why language compatibility alone does not describe a toolchain upgrade. The release adds implementations of NSDecimal, NSLengthFormatter and Progress. It improves URLSession API coverage and its use of libdispatch, repairs memory leaks in Foundation types, and improves Data and JSON serialization performance. The announcement does not supply a universal speedup figure for those changes.
These updates affect whether a program can use the same library abstractions across platforms. A source-level API name is insufficient when its implementation or coverage differs. Official binaries cover Ubuntu 14.04, 16.04 and 16.10, while Apple's platforms receive Swift 3.1 through Xcode 8.3. The release identifies its source revisions with the swift-3.1-RELEASE tag across the participating repositories.
I find the package-manager work especially useful because it reduces uncertainty before compilation begins. It also accompanies improvements to incremental rebuilding, which can rebuild fewer sources, and optional parallel dependency fetching. Those are concrete changes to the time and state involved in a build. The language additions, including prefix(while:), drop(while:) and failable numeric conversions, arrive within the same source-compatible release, so existing code can use the revised tooling without first adopting those APIs.