Skip to content

[Sema] Fix spurious use_local_before_declaration errors. #16967

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

Merged
merged 1 commit into from
Jun 27, 2018

Conversation

dingobye
Copy link
Contributor

@dingobye dingobye commented Jun 3, 2018

The current implementation of type checker is overly strict for use_local_before_declaration cases.
When performing name lookup for UnresolvedDeclRefExpr, if a local declaration after use is detected, an error is raised immediately, without checking outer results where legal candidates may occur.

This PR adds relevant checking to see if we can find better matching candidates from outer results before raising a use_local_before_declaration error.

Resolves SR-7660.

When performing name lookup for UnresolvedDeclRefExpr, if a
local declaration after use is detected, we check outer results
to see if we can find better matching candidates before raising
a use_local_before_declaration error.

Resolves: SR-7660.
@slavapestov
Copy link
Contributor

I think it would make more sense if name lookup was driven by a source location and didn’t find declarations before their definition at all.

@slavapestov
Copy link
Contributor

@DougGregor is probably the best person to review this and give guidance.

if (Loc.isValid() && D->getLoc().isValid() &&
D->getDeclContext()->isLocalContext() &&
D->getDeclContext() == DC &&
Context.SourceMgr.isBeforeInBuffer(Loc, D->getLoc())) {
Copy link
Member

Choose a reason for hiding this comment

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

This check is necessary, but not sufficient for all cases. For example, a variable in a guard cannot be used within the else of that guard:

guard let x = someOptional else { /* x is not visible here */ }

However, I think that's okay: this pull request is about improving on the current situation, and as the FIXME notes, ASTScope-based name lookup is the full answer. More importantly, it's not wrong to do what this new code is doing, i.e., it won't reject valid code.

@DougGregor
Copy link
Member

@swift-ci please smoke test

@dingobye
Copy link
Contributor Author

dingobye commented Jun 5, 2018

Thanks for the comments and review.

@AnnaZaks
Copy link
Contributor

@swift-ci please smoke test

@DougGregor DougGregor merged commit 2a57027 into swiftlang:master Jun 27, 2018
DougGregor added a commit to DougGregor/swift that referenced this pull request Jul 10, 2018
Recent work to improve checking for forward references to local types
(swiftlang#16967) started rejecting code
that referred to a local type before it is defined. Swift previously
accepted such code, because local types can’t capture anyway, so allow
it again… for now.

As a separate action item, I’d like to revisit the language design
here, because it’s somewhat surprising when we can vs. cannot
forward-reference local declarations, and the rules differ from
those of top-level code in scripts *and* top-level code for non-scripts.

Fixes rdar://problem/41659447
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