Track the implied result exprs in the constraint
system, and allow arbitrary propagation of
implied results down if/switch expression
branches. This is required for allowing implied
results in non-single-expression closures.
Teach the constraint solver about the subtyping rule that permits
converting one function type to another when the effective thrown error
type of one is a subtype of the effective thrown error type of the
other, using `any Error` for untyped throws and `Never` for
non-throwing.
With minor other fixes, this allows us to use typed throws for generic
functions that carry a typed error from their arguments through to
themselves, which is in effect a typed `rethrows`:
```swift
func mapArray<T, U, E: Error>(_ array: [T], body: (T) throws(E) -> U)
throws(E) -> [U] {
var resultArray: [U] = .init()
for value in array {
resultArray.append(try body(value))
}
return resultArray
}
```
These allow multi-statement `if`/`switch` expression
branches that can produce a value at the end by
saying `then <expr>`. This is gated behind
`-enable-experimental-feature ThenStatements`
pending evolution discussion.
Skip type-checking multi-statement branches if the
completion is in a single-expression branch, and
skip type-checking the expression as a whole if
the completion is in a multi-statement branch.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
There's still plenty of more work to do here for
pattern diagnostics, including introducing a
bunch of new locator elements, and handling things
like argument list mismatches. This at least lets
us fall back to a generic mismatch diagnostic.
Rather than eagerly binding them to holes if the
sequence element type ends up being Any, let's
record the CollectionElementContextualMismatch fix,
and then if the patterns end up becoming holes,
skip penalizing them if we know the fix was
recorded. This avoids prematurely turning type
variables for ExprPatterns into holes, which
should be able to get better bindings from the
expression provided. Also this means we'll apply
the logic to non-Any sequence types, which
previously we would give a confusing diagnostic
to.
* Use fancy arrows (`→`) because they are distinct from and shorter than `->`,
and fancier.
* We have two ways of demarcating locators: `@ <locator>` and `[[<locator>]];`.
Stick to the first, which is shorter and clearer.
* 'attempting type variable' → 'attempting binding'. *Bindings* are attempted,
not type variables.
* `considering ->` → `considering:`. I think a colon is semantically more fit
and makes things easier to read if the considered constraint has arrows in its
description or types. It’s also shorter this way.
Introduce SingleValueStmtExpr, which allows the
embedding of a statement in an expression context.
This then allows us to parse and type-check `if`
and `switch` statements as expressions, gated
behind the `IfSwitchExpression` experimental
feature for now. In the future,
SingleValueStmtExpr could also be used for e.g
`do` expressions.
For now, only single expression branches are
supported for producing a value from an
`if`/`switch` expression, and each branch is
type-checked independently. A multi-statement
branch may only appear if it ends with a `throw`,
and it may not `break`, `continue`, or `return`.
The placement of `if`/`switch` expressions is also
currently limited by a syntactic use diagnostic.
Currently they're only allowed in bindings,
assignments, throws, and returns. But this could
be lifted in the future if desired.
If we don't have an associated TypeRepr for a
contextual type in the constraint system, dump the
ASTNode that it's for instead.
Before:
```
Contextual Type: $T2
```
After:
```
Contextual Type: $T2 at DeclRef@/Users/hamish/src/swift-test-arena/swift-test-arena/main.swift:1493:21
```
`SyntacticElement` represents a statement, pattern, declaration,
condition, or expression and could originate from i.e. a closure,
a function or a result builder body.
In order to fit with the new IUO model where
functions with IUO results have the disjunction
formed when matching result types, we need to
update this logic to form applicable fn
constraints for the implicit `x[dynamicMember:]`
subscript call.
This is done using a new ImplicitDynamicMemberSubscript
locator path element to allow easy identification of
what the right callee and argument list should be.
Use this new element to represent the overload type
for a constructor call, and have it store a bit
indicating whether the call is for a short-form
`X(...)` or self-delegating `self.init(...)` call.
* [TypeResolver][TypeChecker] Add support for structural opaque result types
* [TypeResolver][TypeChecker] Clean up changes that add structural opaque result types