Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-8788] Rethrowing/convenience initializer does not compile #51296

Closed
swift-ci opened this issue Sep 18, 2018 · 9 comments
Closed

[SR-8788] Rethrowing/convenience initializer does not compile #51296

swift-ci opened this issue Sep 18, 2018 · 9 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself good first issue Good for newcomers type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-8788
Radar None
Original Reporter Coder-256 (JIRA User)
Type Bug
Status Closed
Resolution Done
Environment

Swift 4.2, Xcode 10.0 (10A255), macOS 10.13.6 (17G2307)

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, StarterBug, TypeChecker
Assignee Coder-256 (JIRA)
Priority Medium

md5: 35970f5be3170943946b15431fb6980a

Issue Description:

This code should, in theory, compile:

class Foo {
    init(_ block: () throws -> ()) rethrows {
        try block()
    }
    
    convenience init(bar: Int) {
        self.init { // Call can throw, but it is not marked with 'try' and the error is not handled
            print("Foo!")
        }
    }
}

Foo { // No error
    print("Foo!")
}

However, the compiler emits the following error on the self.init line:

Call can throw, but it is not marked with 'try' and the error is not handled

This is incorrect because the initializer rethrows and is passed a non-throwing closure.

@belkadan
Copy link
Contributor

@xedin, think the fix is straightforward enough for a StarterBug?

@xedin
Copy link
Member

xedin commented Sep 18, 2018

It seems like a good StarterBug candidate indeed!

@swift-ci
Copy link
Collaborator Author

Comment by Jacob G (JIRA)

In that case, I'll see if I can fix it myself

@YOCKOW
Copy link
Collaborator

YOCKOW commented Sep 20, 2018

PMFJI

I've hit the similar issue in my project:

enum MyError: Error {
  case someError
}

func letsTry(_ trial:@autoclosure () throws -> Void) -> Void {
  do {
    try trial()
  } catch {
    print("There is an error.")
  }
}

func thrower() throws {
  throw MyError.someError
}

let nonThrowingClosure1 = { () -> Void in letsTry(try thrower()) }
nonThrowingClosure1()
// -> error: Call can throw but is not marked with 'try'

let nonThrowingClosure2: () -> Void = { letsTry(try thrower()) }
// -> error: Invalid conversion from throwing function of type '() throws -> Void' to non-throwing function type '() -> Void'

In this case, nonThrowingClosure1() seems to be similar to this issue SR-8788, on the other hand, nonThrowingClosure2 seems to be similar to SR-487.
I'm not sure if they are just similar or they have the same root of problem, due to my poor knowledge.
Does anyone know?

@swift-ci
Copy link
Collaborator Author

Comment by Jacob G (JIRA)

@YOCKOW It seems to me that the compiler is confused by the try statement inside letsTry's @autoclosure closure (likely because the closure passed to letsTry is not a bracketed expression). I would consider this a separate issue.

@xedin I am having trouble finding the cause of the main issue described. I started looking at TypeCheckError.cpp inside lib/Sema (which seems to me like a good place to start looking for both the main issue and the @autoclosure issue). However, I have no clue how to debug the semantic analyzer, do you have any idea how to use lldb to do that? I got a ninja build working, but I do not know what to do from there.

@xedin
Copy link
Member

xedin commented Sep 24, 2018

Coder-256 (JIRA User) To understand how everything works you need to enable type-checker logging, to do that you can pass `-Xfrontend -debug-constraints` to `swiftc` invocation. That would print a bunch of information about expression AST and deduced solutions (types, declarations). I'd suggest you to save `class Foo` declaration into separate file in order to avoid noise. Code related to solver is contained in `lib/Sema/CS*` files, and top-level entry point is `typeCheckExpression` located in `TypeCheckConstraints.cpp`.

For example from description, unlike one @YOCKOW provided, which involves `@autoclosure`, I think it actually makes sense that `try` is requested on `self.init` because closure is marked as `throws` and `init` is marked as `rethrows` which makes it always throwing regardless whether argument throws or not, you'll see that in the output of the solver, that type of the closure is deduced to be `throwing` based on parameter type.

Example from @YOCKOW is more interesting and looks like real problem because `nonThrowingClosure1` is deduced to be throwing although `letsTry` doesn't propagate errors.
To fix that problem you need to look at how constraints are generated by `ConstraintGenerator` and how function type of `@autoclosure` ends up having `throws` bit set, AFAIK it's done by `closureCanThrow` method in aforementioned class, which might need to be adjusted to fix the issue.

@YOCKOW
Copy link
Collaborator

YOCKOW commented Sep 25, 2018

Coder-256 (JIRA User), @xedin
Thank you both for the comments.
Although I cannot contribute this issue (or these issues) to be resolved, I'm glad if that can be source of discussion.

@slavapestov
Copy link
Member

#21974

@swift-ci
Copy link
Collaborator Author

Comment by Jacob G (JIRA)

@slavapestov Thank you!

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself good first issue Good for newcomers type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

5 participants