Commit Graph

232 Commits

Author SHA1 Message Date
Ben Barham
ab85807f06 Merge pull request #41136 from louisdh/refactoring-codable
[Refactoring] Add Codable refactoring action
2022-02-03 19:34:08 -08:00
Louis D'hauwe
da98eb33ca [Refactoring] Don't copy CursorInfo for AddEquatable 2022-02-02 14:16:17 -08:00
Louis D'hauwe
5d36507a2f [Refactoring] Add Codable refactoring action
Inserts the synthesized implementation.
As part of this, fix some ASTPrinter bugs.

rdar://87904700
2022-02-02 14:14:23 -08:00
Holly Borla
6cee193fc0 [Type System] When explicit existential types are enabled, wrap Error
in ExistentialType for the type of error values.
2022-01-13 19:30:44 -08:00
Alex Hoppen
63c31033fc [Frontend] Load standard libarary in CompilerInstance::setup
Instead of checking that the stdlib can be loaded in a variety of places, check it when setting up the compiler instance. This required a couple more checks to avoid loading the stdlib in cases where it’s not needed.

To be able to differentiate stdlib loading failures from other setup errors, make `CompilerInstance::setup` return an error message on failure via an inout parameter. Consume that error on the call side, replacing a previous, more generic error message, adding error handling where appropriate or ignoring the error message, depending on the context.
2021-12-13 15:32:08 +01:00
Saleem Abdulrasool
910fbee14e gardening: make c++98-compat-extra-semi an error
This cleans up 90 instances of this warning and reduces the build spew
when building on Linux.  This helps identify actual issues when
building which can get lost in the stream of warning messages.  It also
helps restore the ability to build the compiler with gcc.
2021-11-27 11:40:17 -08:00
Hamish Knight
97a1653863 Merge pull request #39159 from hamishknight/conditions-apply
[Async Refactoring] Drop bool flag parameter binding
2021-09-07 13:35:22 +01:00
Hamish Knight
72070b7d41 [Async Refactoring] Bind known bool param in fallback
Generalize the logic to handle different BlockKinds,
and add binding logic that lets us assign `true` or
`false` to the given bool success param in the
fallback case.
2021-09-06 21:25:09 +01:00
Hamish Knight
00977afc7b [Async Refactoring] Placeholder dropped params in fallback case
Make sure to convert any references to parameters
that get dropped in the fallback case to
placeholders.
2021-09-06 21:25:09 +01:00
Hamish Knight
1e34f31545 [Async Refactoring] Drop bool flag parameter binding
If we have a known bool flag parameter, drop it
from the success parameters being bound in a
refactored await call, as the async variant drops
it.

rdar://81896460
2021-09-06 21:25:08 +01:00
Hamish Knight
fa3efeefcb [Async Refactoring] Add ClosureCallbackParams
Refactor some closure parameter handling logic
into a new ClosureCallbackParams type, which lets
us clean up some of the parameters passed to
CallbackClassifier, and better distinguish between
an error param and a Result param.
2021-09-06 21:25:07 +01:00
Hamish Knight
9b493970aa [Aync Refactoring] Better handle comment trailing whitespace
Use `getCommentRange` to trim off the comment's
trailing whitespace, avoiding outputting
extraneous empty lines.

rdar://82072147
2021-09-06 17:51:39 +01:00
Hamish Knight
3e28bbbd2c Update for review feedback
- Remove OriginalArguments in favor of storing the
pre-rewritten argument list, which simplifies things
nicely
- Adopt llvm::indexed_accessor_iterator
2021-09-01 18:40:29 +01:00
Hamish Knight
78d8d09b99 [IDE] Adopt ArgumentList 2021-09-01 18:40:26 +01:00
Rintaro Ishizaki
49547a5378 [NFC][Basic] Import llvm::isa_and_nonnull to 'swift' namespace
Just for convenicence.

* Replace `llvm::isa_and_nonnull` with imported `isa_and_nonnull`
* Repalce some `EXPR && isa<T>(EXPR)` with `isa_and_nonnull<T>(EXPR)`
2021-08-27 11:36:21 -07:00
Ben Barham
9b8d9e22ef Merge pull request #38981 from apple/skip-underscore
[Refactoring] Do not try to unique '_'
2021-08-24 11:33:15 +10:00
Ben Barham
3b99e9079b Merge pull request #38920 from apple/show-cursor-refactorings
[Refactorings] Add cursor refactorings for the start of the range
2021-08-21 07:35:51 +10:00
Ben Barham
6a79964ad4 [Refactoring] Do not try to unique '_'
The async refactorings should not try to unique '_' when it's used as
the parameter name. Also skip adding a let binding to the `catch` if the
error parameter is '_'.

Resolves rdar://82158389
2021-08-21 07:30:53 +10:00
Ben Barham
86c47e45f0 [Refactoring] Do not add "async" if function is already async
Convert Function to Async is available on an async function. It could be
useful to run this refactoring still, as it would attempt to convert any
completion-handler functions to their async alternatives. Keep allowing
this, but make sure not to re-add "async" to the function declaration.

Resolves rdar://82156720
2021-08-20 15:24:17 +10:00
Ben Barham
c7620fa979 [Refactorings] Add cursor refactorings for the start of the range
When a range is a single expression/statement/decl or part of
expression, also return cursor based refactorings for the start of the
range.

This is a stop gap until the available refactorings are properly fixed
to be more lenient in general - the current fix is a little odd as eg.
if all of `foo.bar()` is selected, rename will be returned as an
available refactoring for `foo`. Still an improvement over completely
missing cursor based refactorings, however.

Resolves rdar://82060063
2021-08-18 14:04:10 +10:00
Ben Barham
5bd2d0b932 [Refactoring] Fix invalid legacy body for Result<Void, ...> handler
When adding an async alternative for a function with a
`(Result<Void, ...>) -> Void` completion handler, the legacy body was
adding a call to the handler with `.success(result)`. We don't assign to
`result` for `Void` handlers, so pass `()` instead.

Resolves rdar://81829392
2021-08-12 21:04:18 +10:00
Ben Barham
f6a8dab93d [Refactoring] Use known alternative in async refactoring if one exists
Update the async refactorings to use the name from the async alternative
if one is known, rather than always assuming the name matches the
synchronous function.

Note that this could also be used to determine whether results remain
optional or not, but that has been left for a future patch.

Resolves rdar://80612521
2021-08-03 08:46:44 +10:00
Hamish Knight
813a721760 Merge pull request #38674 from hamishknight/following-the-trail 2021-07-29 17:36:10 +01:00
Ben Barham
e7e9b57051 Replace @completionHandlerAsync with @available(*, renamed:)
Instead of a new attribute `@completionHandlerAsync`, allow the use of
the existing `renamed` parameter of `@available` to specify the
asynchronous alternative of a synchronous function.

No errors will be output from invalid names as `@completionHandlerAsync`
had, but if a function is correctly matched then it will be used to
output warnings when using the synchronous function in an asynchronous
context (as before).

Resolves rdar://80612731
2021-07-29 09:14:44 +10:00
Alex Hoppen
1286bbedf1 Merge pull request #38665 from ahoppen/pr/async-refactoring-parens-around-result
[Async Refactoring] Handle parenthesis around params that no longer need to be unwrapped after refactoring
2021-07-28 21:54:29 +02:00
Hamish Knight
06908adb08 [Async Refactoring] Handle multiple trailing closures
Update the trailing closure handling logic to
handle multiple trailing closures, and adjust the
refactoring output to surround the call in
parentheses rather than adding '.self'. This allows
the parser to deal with the multiple trailing
closures and also silences a warning that would
previously occur.

rdar://81230908
2021-07-28 20:50:40 +01:00
Alex Hoppen
3bea2b728c [Async Refactoring] Handle parenthesis around params that no longer need to be unwrapped after refactoring
Throw another `getSemanticsProvidingExpr` in the async refactoring code for better results.
2021-07-28 18:13:02 +02:00
Hamish Knight
40e20a270d Don't apply "Convert to Trailing Closure" to call with multiple trailing closures
Previously we'd perform an invalid transform or hit
an assertion failure. For now, disallow the transform
for a call that already uses trailing closure syntax.

rdar://81106400
2021-07-26 17:15:22 +01:00
Hamish Knight
1ebb1fd2f5 [Async Refactoring] Add parens around custom error cast
When passing a forwarded error to a CustomError?
completion handler parameter, wrap the cast in a
set of parentheses to silence a warning in the
refactored code.

rdar://80409905
2021-07-22 23:20:24 +01:00
Hamish Knight
007b91cf7b [Async Refactoring] Update to use Task's init
Use the Task initializer instead of the top-level
`async` function to match the latest Concurrency
API.

rdar:80888385
2021-07-21 11:40:35 +01:00
Alex Hoppen
ebfb3a5f5e Merge pull request #38331 from ahoppen/pr/rename-captured-variables-once
[Refactoring] Only rename variables in capture lists once
2021-07-13 19:11:20 +02:00
Doug Gregor
06bbc70b3e Module printing and serialization support for @unchecked Sendable 2021-07-11 12:29:54 -07:00
Alex Hoppen
a535203096 [Refactoring] Only rename variables in capture lists once
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]
2021-07-09 11:38:37 +02:00
Alex Hoppen
cd31fa0f73 [Async Refactoring] Improve fatalError message to unwrap result arguments in continuation
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.
2021-07-07 12:05:37 +02:00
Alex Hoppen
edc1393291 [Async Refactoring] Rename 'success param/argument' to 'result' in fatalError messages
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.
2021-07-07 11:54:11 +02:00
Alex Hoppen
06219cdfa2 [Async Refactoring] Remove assertions for nil result values in async wrapper
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.
2021-07-07 11:54:11 +02:00
Alex Hoppen
6cbbb7cb1f [Async Refactoring] Split ambiguous (error + success) completion handler calls into success and error case
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
}
```
2021-07-07 11:54:11 +02:00
Alex Hoppen
03d3887bba [Async Refactoring] Convert data structure storing continuation resume args to std::vector
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`.
2021-07-06 18:08:12 +02:00
Alex Hoppen
c3e9676cb1 Merge pull request #38261 from ahoppen/pr/check-semantics-expr-for-completion-handler-call
[Async Refactoring] Get semantics providing expr to decide if call is to completion handler
2021-07-06 10:53:56 +02:00
Alex Hoppen
ec8957972a [Async Refactoring] Get semantics providing expr to decide if call is to completion handler
Resolves rdar://78011350
2021-07-05 17:41:39 +02:00
Alex Hoppen
3dcb08a369 [Async Refactoring] Cosmetic Improvements to "Add Async Wrapper" Refactoring
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
2021-07-05 13:34:27 +02:00
Alex Hoppen
54fcc90841 [Async Refactoring] Wrap code in a continuation if conversion doesn't yield reasonable results
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
2021-07-02 15:48:41 +02:00
Alex Hoppen
d0472e1b21 [Async Refactoring] Code style improvements 2021-07-01 15:57:42 +02:00
Alex Hoppen
7a68a1d834 Merge pull request #38191 from ahoppen/pr/implict-return-async-refactoring
[Async Refactoring] Add `return` keyword if wrapping `ReturnStmt` is implicit
2021-07-01 15:40:00 +02:00
Alex Hoppen
f7c7599a8c [Async Refactoring] Add return keyword if wrapping ReturnStmt is implicit
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
2021-07-01 10:21:46 +02:00
Hamish Knight
0d4eb978da [Async Refactoring] Add missing null type check
Don't crash if we have a boolean condition without
a type, as that may occur in invalid code.

rdar://79864182
2021-06-28 16:03:54 +01:00
Alex Hoppen
ffbbbaffca Merge pull request #38052 from ahoppen/pr/use-closure-label-for-async-return-type
[Refactoring] Use internal completion handler labels for async function's return type
2021-06-25 12:57:00 +02:00
Alex Hoppen
d944b8bd49 [Refactoring] Use internal completion handler labels for async function's return type
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
2021-06-24 08:00:28 +02:00
Alex Hoppen
81b37fdb4c [Refactoring] Support refactoring for case let patterns
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]
2021-06-14 12:31:01 +02:00
Hamish Knight
e97c781ca1 [Async Refactoring] Add @discardableResult for defaulted completion
If the completion handler parameter has a default
argument, mark the resulting async function as
`@discardableResult`, as the caller may not care
about the result.

rdar://79190170
2021-06-11 11:39:16 +01:00