This is a list of changes to the Swift language that are frequently proposed but that are unlikely to be accepted. If you're interested in pursuing something in this space, please familiarize yourself with the discussions that we have already had. In order to bring one of these topics up, you'll be expected to add new information to the discussion, not just to say, "I really want this" or "this exists in some other language and I liked it there".
Additionally, proposals for out-of-scope changes will not be scheduled for review. The readme file identifies a list of priorities for the next major release of Swift, and the proposal review status page includes a list of changes that have been deferred for future discussion because they were deemed to be out of scope at the time of review (in addition to a list of changes proposed and rejected after a formal review).
Several of the discussions below refer to "C family" languages. This is intended to mean the extended family of languages that resemble C at a syntactic level, such as C++, C#, Objective-C, Java, and Javascript. Swift embraces its C heritage. Where it deviates from other languages in the family, it does so because the feature was thought actively harmful (such as the pre/post-increment ++
) or to reduce needless clutter (such as ;
or parentheses in if
statements).
-
Replace
{}
brace syntax with Python-style indentation: Surely a polarizing issue, but Swift will not change to use indentation for scoping instead of curly braces. -
Remove
;
semicolons: Semicolons within a line are an intentional expressivity feature. Semicolons at the end of the line should be handled by a linter, not by the compiler. -
Replace logical operators (
&&
,||
,!
, etc.) with words like "and", "or", "not", and allow non-punctuation operators and infix functions: The operator and identifier grammars are intentionally partitioned in Swift, which is a key part of how user-defined overloaded operators are supported. Requiring the compiler to see the "operator" declaration to know how to parse a file would break the ability to be able to parse a Swift file without parsing all of its imports. This has a major negative effect on tooling support. While not needing infix support,not
would need operator or keyword status to omit the parentheses as!
can, andnot somePredicate()
visually binds too loosely compared to!somePredicate()
. -
Replace
?:
ternary operator: Definitely magical, but it serves a very important use-case for terse selection of different values. Proposals for alternatives have been intensely discussed, but none have been "better enough" for it to make sense to diverge from the precedent established by the C family of languages.
- Change
Array<T>
subscript access to returnT?
orT!
instead ofT
: The current array behavior is intentional, as it accurately reflects the fact that out-of-bounds array access is a logic error. Changing the current behavior would slowArray
accesses to an unacceptable degree. Changing the unlabeled array subscript to return an optional has come up multiple times before and is very unlikely to be accepted.
-
if/else
andswitch
as expressions: These are conceptually interesting things to support, but many of the problems solved by making these into expressions are already solved in Swift in other ways. Making them expressions introduces significant tradeoffs, and on balance, we haven't found a design that is clearly better than what we have so far. -
Replace
continue
keyword with synonyms from other scripting languages (e.g. next, skip, advance, etc): Swift is designed to feel like a member of the C family of languages. Switching keywords away from C precedent without strong motivation is a non-goal. -
Remove support for
default:
inswitch
and just usecase _:
:default
is widely used,case _
is too magical, anddefault
is widely precedented in many C family languages. -
Rename
guard
tounless
: It is a common request thatguard
be renamedunless
. People requesting this change argue thatguard
is simply a logically invertedif
statement, and thereforeunless
is a more obvious keyword. However, such requests stem from a fundamental misunderstanding of the functionality provided byguard
. Unlikeif
,guard
enforces that the code within its curly braces provides an early exit from the codepath. In other words, aguard
block mustreturn
,throw
,break
,continue
or call a function that does not return, such asfatalError()
. This differs fromif
quite significantly, and therefore the parallels assumed betweenguard
andif
are not valid. -
Infer
return
for omittedguard
body: It has been proposed many times to allow omission of theguard
body for the sake of brevity. However, a core principle of Swift is to make control flow explicit and visible. For example, thetry
keyword exists solely to indicate to the human reader where thrown errors can happen. Implicit returns would violate this principle, favoring terseness over clarity in a way that isn't typical of Swift. Furthermore, there are many ways of exiting the scope other thanreturn
(loops may wantbreak
orcontinue
), and not every function has an obvious default value to return. -
Change closure literal syntax: Closure syntax in Swift has been carefully debated internally, and aspects of the design have strong motivations. It is unlikely that we'll find something better, and any proposals to change it should have a very detailed understanding of the Swift grammar.
-
Use pattern-matching in
if let
instead of optional-unwrapping: We actually tried this and got a lot of negative feedback, for several reasons: (1) Most developers don't think about things in "pattern matching" terms, they think about "destructuring". (2) The vastly most common use case forif let
is actually for optional matching, and this change made the common case more awkward. (3) This change increases the learning curve of Swift, changing pattern matching from being a concept that can be learned late to something that must be confronted early. (4) The current design ofif case
unifies "pattern matching" around thecase
keyword. (5) If a developer unfamiliar withif case
runs into one in some code, they can successfully search for it in a search engine or Stack Overflow. -
Syntactic sugar for
if let
self-assignment: An alternative syntax (such asif let foo? { ... }
orif let foo=? { ... }
) to serve as a shorthand forif let foo = foo { ... }
is often proposed and rejected because it is favoring terseness over clarity by introducing new magic syntactic sugar. -
Remove or deprecate the force-unwrap operator
!
: Force-unwrap and force-try are legitimately useful parts of the language, and not just for source stability reasons. Therefore, proposals to deprecate or remove the force-unwrap operator (ortry!
), even in a mode enabled via compiler flag, will not be considered by the core team. Whether the Swift compiler should gain a more general "linting" capability to guide coding style remains a possible topic of discussion. -
Replace the
do
/try
/repeat
keywords with C++-style syntax: Swift's error handling approach is carefully designed to make it obvious to maintainers of code when a call can "throw" an error. It is intentionally designed to be syntactically similar in some ways, but different in other key ways, to exception handling in other languages. Its design is a careful balance that favors maintainers of code that uses errors, to make sure someone reading the code understands what can throw. Before proposing a change to this system, please read the Error Handling Rationale and Proposal in full to understand why the current design is the way it is, and be ready to explain why your changes would be worth unbalancing this design.
-
Use garbage collection (GC) instead of automatic reference counting (ARC): Mark-and-sweep garbage collection is a well-known technique used in many popular and widely used languages (e.g., Java and JavaScript) and it has the advantage of automatically collecting reference cycles that ARC requires the programmer to reason about. That said, garbage collection has a large number of disadvantages and using it would prevent Swift from successfully targeting a number of systems programming domains. For example, real-time systems (video or audio processing), deeply embedded controllers, and most kernels find GC to be generally unsuitable. Further, GC is only efficient when given 3–4× more memory to work with than the process is using at any time, and this tradeoff is not acceptable for Swift.
-
Disjunctions (logical ORs) in type constraints: These include anonymous union-like types (e.g.
(Int | String)
for a type that can be inhabited by either an integer or a string). "[This type of constraint is] something that the type system cannot and should not support." -
Rewrite the Swift compiler in Swift: This would be a lot of fun someday, but (unless you include rewriting all of LLVM) requires the ability to import C++ APIs into Swift. Additionally, there are lots of higher priority ways to make Swift better.