RFC: `swift migrate` command

Introduction

Adoption tooling for upcoming features pitch proposed to extend the Swift compiler to add an integrated mechanism for producing source-compatible adjustments to code that can be applied to preserve its behavior once a given eligible upcoming feature is enabled.

To enable seemless migration experience for Swift packages, I'd like to propose a new Swift Package Manager command - swift migrate to complement the Swift compiler-side changes.

The command would accept one or more features that have migration mode enabled and optionally a set of targets to migrate, if no targets are specified the whole package is going to be migrated to use new features.

Interface

USAGE: swift migrate [<options>] --to-feature <to-feature> ... OPTIONS: --targets <targets> The targets to migrate to specified set of features or a new language mode. --to-feature <to-feature> The Swift language upcoming/experimental feature to migrate to. -h, --help Show help information. 

Use case

swift migrate --targets MyTarget,MyTest --to-feature ExistentialAny 

This command would attempt to build MyTarget and MyTest targets with ExistentialAny:migrate feature flag, apply any fix-its associated with
the feature produced by the compiler, and update the Package.swift to
enable the feature(s) if both of the previous actions are successful:

.target( name: "MyTarget", ... swiftSettings: [ // ... existing settings, .enableUpcomingFeature("ExistentialAny") ] ) ... .testTarget( name: "MyTest", ... swiftSettings: [ // ... existing settings, .enableUpcomingFeature("ExistentialAny") ] ) 

In the "whole package" mode, every target is going to be updated to include
new feature flag(s). This is supported by the same functionality as swift package add-setting command.

If it's, for some reason, impossible to add the setting the diagnostic message would suggest what to add and where i.e. ...; please add '.enableUpcomingFeature("ExistentialAny")' to MyTarget target manually.

Impact on Interface

This proposal introduces a new command but does that does not interfere with existing commands. It follows the same pattern as swift build and swift test in a consistent manner.

13 Likes

Any and all feedback is welcome!

This is really cool.

What happens if the code fails to compile after the fix-its are applied? Will the modified code be left in the package, so any other necessary fixes can be made before enabling the feature?

1 Like

The compiler is responsible for not letting that happen since the fix-its for the migratable features should be source compatible but if it happens the code would stay modified. We did discuss possible rollback, it could be a future direction.

1 Like