Skip to content

Fixes a small threading issue in code generation and a TODO #2233

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

Closed
wants to merge 4 commits into from

Conversation

benpious
Copy link
Contributor

errors was potentially mutated on multiple threads. previouslyGeneratedFiles, which is mutated on every loop, is locked just above it, so clearly we need to lock on all state that's mutated here.

I also cleaned up the TODO.

@kimdv
Copy link
Contributor

kimdv commented Sep 25, 2023

@swift-ci please test

Copy link
Contributor

@bnbarham bnbarham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @benpious! The failures are because format.py needs to be run.

@@ -154,6 +154,7 @@ struct GenerateSwiftSyntax: ParsableCommand {
}
)

let errorsLock = NSLock()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we should use async/await with multiple tasks that we reduce after here, but that's a larger change. For this IMO just rename previouslyGenerateFilesLock and use it for both.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that that should be the long term direction. Is this allowed in this project? I don't think that change should take long to make, provided the CI can verify that it works on Linux and windows.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We require being able to compile with >= 5.7 currently and this is just a generation tool, so unless there's some bugs preventing it, I don't see any reason it would be an issue.

Copy link
Contributor Author

@benpious benpious Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is an Structured Concurrency version of this pr. If this looks good to you I can abandon this pr and pr the Structured Concurrency version instead.

Copy link
Contributor

@bnbarham bnbarham Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, happy for you to put that up instead. Regarding the grouping below, I wouldn't worry about indenting personally - this is just for generation which typically shouldn't fail. What you could do is just separate them by file path, eg. ```

Errors occurred during generation.

'<file>':
<error here>

'<file>':
<error here>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created #2245. It also incorporates this feedback about printing which file produced which error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, using structured concurrency is so much cleaner. Thanks for putting it up. This means we can close this PR, right?

// TODO: It would be nice if we could emit all errors
throw firstError
if errors.count > 0 {
struct ComposititeError: Error, CustomStringConvertible {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct ComposititeError: Error, CustomStringConvertible {
struct CompositeError: Error, CustomStringConvertible {

Personally I'd define this top level, probably at the bottom of this file.

struct ComposititeError: Error, CustomStringConvertible {
var errors: [Error]
var description: String {
"Multiple errors emitted: \n" +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Multiple errors emitted: \n" +
"Multiple errors emitted:\n" +

"Multiple errors emitted: \n" +
errors
.map(String.init(describing: ))
.joined(separator: "\n")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do they already have a newline, or would it be worth adding an extra newline here? Do you happen to have an example of the output here for multiple errors?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make you some real output in a few hours, but in my original testing NSError does not include a newline, and that's the error that we're most likely to encounter in this code path today due to the use of FileManager.

I think in general that it will depend on how the error implements its description or debugDescription var and that the safest option is to add a newline even if we can find some errors that happen to do this for us.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, to be clear, we definitely want at least one newline here. My question was about whether we might want two so that there's a clearer cut between the errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah that makes a lot more sense. Here's the sample output of an NSError in this context:

Error: Multiple errors emitted: 
Error Domain=test error Code=0 "(null)"
Error Domain=test error Code=0 "(null)"
Error Domain=test error Code=0 "(null)"
Error Domain=test error Code=0 "(null)"
Error Domain=test error Code=0 "(null)"
Error Domain=test error Code=0 "(null)"

I think in an ideal world it would look something like

Multiple errors emitted: {

    Error Domain=test error Code=0 "(null)"

    Error Domain=test error Code=0 "(null)"

   ...

}

because they're separate, but grouped. But that would require adding a means of indenting text (in case of multi-line errors) which might be overkill. But I'm happy to add the indentation and newline, or just the second newline, or leave it out, whichever you prefer.

@ahoppen
Copy link
Member

ahoppen commented Mar 15, 2024

Closing because it’s been superseded by #2245 AFAICT.

@ahoppen ahoppen closed this Mar 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants