Skip to content

Conversation

@hamishknight
Copy link
Contributor

When type-checking a caller-side expression macro default argument in a context where name lookup is unable to resolve it (but is able to resolve it in the parameter), we were previously exiting with a non-zero exit code without emitting any diagnostic. This was due to the fact that DiagnosticState::determineBehavior is stateful, meaning that querying DiagnosticTransaction::hasErrors could flip the "had error" bit for the DiagnosticEngine even if the transaction got later aborted.

This PR splits off the stateful bit of DiagnosticState::determineBehavior into a new function that we call during diagnostic emission. This then exposed the actual underlying issue here, which is that the diagnostic hack we have for caller-side default arguments, where we expect them to fail in the parameter if they fail at the call-site, is unsound for expression macros since name lookup may differ depending on context. Limit the hack such that it only applies to simple literals (magic literals + nil, [], and [:]).

rdar://154771596

Split out the state mutation into a new `updateFor`
function that we call for diagnostic emission, allowing
`DiagnosticTransaction::hasErrors` to query the behavior without
mutating any state.
We can't assume that type-checking the expression macro in the
parameter will also fail if it fails at the call site since e.g
name lookup may differ. Make sure we only apply this logic to simple
literals.

rdar://154771596
@hamishknight
Copy link
Contributor Author

@swift-ci please test

@hamishknight hamishknight merged commit 31408fe into swiftlang:main Jul 3, 2025
5 checks passed
@hamishknight hamishknight deleted the diag-it branch July 3, 2025 08:23
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.

2 participants