For a GenericFunctionType, use `substGenericArgs`
instead of `subst`, as the latter would form a bad
generic signature if there were UnresolvedTypes
present in the base type, causing the GSB to blow
up when attempting to canonicalize it.
rdar://80635105
`CodeCompletioString::getName()` was used only as the sorting keys in
`CodeCompletionContext::sortCompletionResults()` which is effectively
deprecated. There's no reason to check them in `swift-ide-test`. Instead,
check `printCodeCompletionResultFilterName()` that is actually used for
filtering.
The GenericSig might come from a protocol extension.
The original types in the Requirement come from this generic signature.
However, the Requirement can then be substituted with the base type's
concrete substitutions, and if the base type is a conforming nominal
type, we now have a Requirement whose types are written in terms of
the conforming nominal type's generic signature.
Therefore, the call to getCanonicalTypeInContext() might not produce
correct results, since there's no guarantee the protocol extension's
GenericSignature has the same requirements as the conforming type's.
This used to just silently produce incorrect results, but now asserts
when the RequirementMachine is enabled.
To fix this I replaced these calls with plain old getCanonicalType()
that does not take a GenericSignature.
If we find a case that is now broken as a result of this change, we'll
need to re-introduce some bookkeeping here to keep track of *which*
GenericSignature generates the types in the substituted Requirement.
Inside capture lists like `{ [test] in }`, `test` refers to both the newly declared, captured variable and the referenced variable it is initialized from. We currently try to rename it twice, yielding invalid, confusing results. Make sure to only record this situation once.
Fixes rdar://78522816 [SR-14661]
In the previous `fatalError` message `Expected non-nil result 'result' for nil error`, it wasn’t exactly clear wht the `error` referred to. In some cases, when the error was ignored, there wasn’t even an `error` variable in the refactored code.
The new `Expected non-nil result '...' in the non-error case` is a little more generic and also fits if an error is ignored.
The 'success param/argument' is a terminology we use internally in the refactoring and not one we want to present to the user. Just name it 'result' instead.
Since we aren’t checking that all result arguments are `nil` if there was an `error` in all the other refactorings, also remove the assertions in the async wrapper.
Previously, when a completion handler call had arguments for both the success and error parameters, we were always interpreting it as an error call. In case the error argument was an `Optional`, this could cause us to generate code that didn't compile, because we `throw`ed the `Error?` or passed it to `continuation.resume(throwing)`, both of which didn't work.
We now generate an `if let` statement that checks if the error is `nil`. If it is, the error is thrown. Otherwise, we interpret the call as a success call and return the result.
- Example 1 (convert to continuation)
-- Base Code
```swift
func test(completionHandler: (Int?, Error?) -> Void) {
withoutAsyncAlternativeThrowing { (theValue, theError) in
completionHandler(theValue, theError)
}
}
```
-- Old Refactoring Result
```swift
func test() async throws -> Int {
return try await withCheckedThrowingContinuation { continuation in
withoutAsyncAlternativeThrowing { (theValue, theError) in
continuation.resume(throwing: theError) // error: Argument type 'Error?' does not conform to expected type 'Error'
}
}
}
-- New Refactoring Result
```swift
func testThrowingContinuationRelayingErrorAndResult() async throws -> Int {
return try await withCheckedThrowingContinuation { continuation in
withoutAsyncAlternativeThrowing { (theValue, theError) in
if let error = theError {
continuation.resume(throwing: error)
} else {
guard let theValue = theValue else {
fatalError("Expected non-nil success argument 'theValue' for nil error")
}
continuation.resume(returning: theValue)
}
}
}
}
```
- Example 2 (convert to async/await)
-- Base Code
```swift
func test(completion: (String?, Error?) -> Void) {
simpleErr() { (res, err) in
completion(res, err)
}
}
```
-- Old Refactoring Result
```swift
func test() async throws -> String {
let res = try await simpleErr()
throw <#err#>
}
```
-- New Refactoring Result
```swift
func test() async throws -> String {
let res = try await simpleErr()
return res
}
```
The `std::vector` keeps its elements alive. Currently, we might be accessing uninitalized memory if the call of `callArgs(CE)` (which owns its elements in case there is a single element) goes out of scope before `Args`.
Two mostly-cosmetic change to the "Add Async Wrapper" refactoring
- Rename the continuation from `cont` to `continuation` and error from `err` to `error` to better match Swifts naming guidelines
- Add assertions that all result parameters are `nil` if an error is passed to the completion handler.
Resolves rdar://80172152
The `compare_lower` API was replaced with `compare_insensitive` in llvm
commit 2e4a2b8430aca6f7aef8100a5ff81ca0328d03f9.
git clang-format ran.
(cherry picked from commit aca2de95ee)
The `equals_lower` API was replaced with `equals_insensitive` in llvm
commit 2e4a2b8430aca6f7aef8100a5ff81ca0328d03f9 and
3eed57e7ef7da5eda765ccc19fd26fb8dfcd8d41.
Ran git clang-format.
(cherry picked from commit e21e70a6bf)
If we are requested to convert a function to async, but the call in the function’s body that eventually calls the completion handler doesn’t have an async alternative, we are currently copying the call as-is, replacing any calls to the completion handler by placeholders.
For example,
```swift
func testDispatch(completionHandler: @escaping (Int) -> Void) {
DispatchQueue.global.async {
completionHandler(longSyncFunc())
}
}
```
becomes
```swift
func testDispatch() async -> Int {
DispatchQueue.global.async {
<#completionHandler#>(longSyncFunc())
}
}
```
and
```swift
func testUrlSession(completionHandler: @escaping (Data) -> Void) {
let task = URLSession.shared.dataTask(with: request) { data, response, error in
completion(data!)
}
task.resume()
}
```
becomes
```swift
func testUrlSession() async -> Data {
let task = URLSession.shared.dataTask(with: request) { data, response, error in
<#completion#>(data!)
}
task.resume()
}
```
Both of these are better modelled using continuations. Thus, if we find an expression that contains a call to the completion handler and can’t be hoisted to an await statement, we are wrapping the rest of the current scope in a `withChecked(Throwing)Continuation`, producing the following results:
```swift
func testDispatch() async -> Int {
return await withCheckedContinuation { (continuation: CheckedContinuation<Int, Never>) in
DispatchQueue.global.async {
continuation.resume(returning: syncComputation())
}
}
}
```
and
```swift
func testDataTask() async -> Int?
return await withCheckedContinuation { (continuation: CheckedContinuation<Data, Never>) in
let task = URLSession.shared.dataTask { data, response, error in
continuation.resume(returning: data!)
}
task.resume()
}
}
```
I think both are much closer to what the developer is actually expecting.
Resolves rdar://79304583
Previously, in the following case we were failing to add a `return` keyword inside `withImplicitReturn`.
```
func withImplicitReturn(completionHandler: (String) -> Void) {
simple {
completionHandler($0)
}
}
```
This is because the call of `completionHandler($0)` is wrapped by an implicit `ReturnStmt` and thus we assumed that there was already a `return` keyword present.
Fix this issue by checking if the wrapping `ReturnStmt` is implicit and if it is, add the `return` keyword.
Fixes rdar://80009760
Treat actors as being semantically `final` throughout the type checker.
This allows, for example, a non-`required` initializer to satisfy a
protocol requirement.
We're leaving the ABI open for actor inheritance should we need it.
Addresses rdar://78269551.
This commit essentially consistes of the following steps:
- Add a new code completion key path component that represents the code completion token inside a key path. Previously, the key path would have an invalid component at the end if it contained a code completion token.
- When type checking the key path, model the code completion token’s result type by a new type variable that is unrelated to the previous components (because the code completion token might resolve to anything).
- Since the code completion token is now properly modelled in the constraint system, we can use the solver based code completion implementation and inspect any solution determined by the constraint solver. The base type for code completion is now the result type of the key path component that preceeds the code completion component.
This resolves bugs where code completion was not working correctly if the key path’s type had a generic base or result type. It’s also nice to have moved another completion type over to the solver-based implementation.
Resolves rdar://78779234 [SR-14685] and rdar://78779335 [SR-14703]
If a completion handler specifies internal parameter labels, we can use those to label the elements of the tuple returned by the async alternative.
For example
```swift
func foo(completion: (_ first: String, _ second: String) -> Void) { }
```
gets refactored to
```swift
func foo() async -> (first: String, second: String) { }
```
Resolves rdar://77268040
struct Generic<T> {
init(destination: T, isActive: Bool) { }
}
invalid {
Generic(destination: true, #^COMPLETE^#)
}
In this case, since `invalid { ... }` cannot be type checked.
`ExprContextAnalysis` tries to type check `Generic` alone which resolves
to bound `Generic` type with an unresolved type. Previously, we used to
give up the analysis when seeing unresolved type. That caused mis callee
analyis.
rdar://79092374
Rename VariableTypeCollector::getTypeOffsets to ::getTypeOffset and only
return the start offset, since the end offset is no longer needed (the
string is null-terminated).
Also improve variable naming slightly.
- Add VariableTypeCollector
This new SourceEntityWalker collects types from variable declarations.
- Add SwiftLangSupport::collectVariableTypes
- Implement CollectVariableType request
- Provide information about explicit types in CollectVarType
- Fix HasExplicitType in VariableTypeArray
- Fix typo
- Implement ranged CollectVariableTypes requests
- Use offset/length params for CollectVariableType in sourcekitd-test
- Address a bunch of PR suggestions
- Remove CanonicalType from VariableTypeCollector
This turned out not to be needed (for now).
- Improve doc comment on VariableTypeCollector::getTypeOffsets
- Remove unused CanonicalTy variable
- Remove out-of-date comment
- Run clang-format on the CollectVariableType implementation
- Fix some minor style issues
- Use emplace_back while collecting variable infos
- Pass CollectVariableType range to VariableTypeCollector
- Use capitalized variable names in VariableTypeArray
...as recommended by the LLVM coding standards
- Use PrintOptions for type printing in VariableTypeCollector
- Return void for collectVariableType
This seems to be cleaner stylistically.
- Avoid visiting subranges of invalid range in VariableTypeCollector
- Use std::string for type buffer in VariableTypeCollectorASTConsumer
- Use plural for PrintedType in VariableTypeArray
- Remove unused fields in VariableTypeArrayBuilder
- Add suggested doc comments to VariableTypeArray
- Remove unused VariableTypeInfo.TypeLength
- Fix typo of ostream in VariableTypeCollectorASTConsumer
- Fix typo
- Document Offset and Length semantics in collectVariableTypes
Previously, we weren’t suggesting argument labels of enum elements when doing an unresolved member completion. Treat `EnumElementDecl` similar to static `AbstractFunctionDecl`s to show their argument labels.
Fixes rdar://78780690 [SR-14689]
Annotate cross-actor references to global actors as `async` and mark them as not-recommended if they must be executed on a different actor than the current context is on.
Resolves rdar://75902598
Previously we only supported `case` patterns that bound with a `let` inside the associated value like `case .success(let value)`. With this change, we also support `case let .success(value)`.
Fixes rdar://79279846 [SR-14772]