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