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

resolve: refactor path resolution #38014

Merged
merged 6 commits into from
Nov 30, 2016

Conversation

jseyfried
Copy link
Contributor

@jseyfried jseyfried commented Nov 26, 2016

This is a pure refactoring, modulo minor diagnostics improvements.
r? @nrc

@jseyfried
Copy link
Contributor Author

cc @eddyb @petrochenkov

@jseyfried jseyfried force-pushed the refactor_path_resolution branch from 8254908 to f8e5593 Compare November 26, 2016 13:14
@petrochenkov
Copy link
Contributor

Hey, I have a relatively large rewrite of high level path resolution and error reporting in progress: https://github.com/petrochenkov/rust/tree/altname.
I'll look through this patch and see how they integrate (it may make sense to wait with changes lying above resolve_path/resolve_possibly_assoc_item in call stack).

@petrochenkov
Copy link
Contributor

Reviewed. The changes are mostly orthogonal to my branch, the main contention is about resolve_path signature. The merge may be a bit painful, but nothing critically bad.
The patch looks good to me overall.

@@ -71,13 +71,13 @@ pub struct LoweringContext<'a> {

pub trait Resolver {
// Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def;
fn resolve_hir_path(&mut self, path: &hir::Path, is_value: bool) -> PathResolution;
Copy link
Member

Choose a reason for hiding this comment

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

FWIW, changes in this module conflict with #37676, so you can either revert them to merge earlier, or wait for that PR (which would be merged already if it weren't for windows).
Also keep in mind that PathResolution doesn't really matter after HIR lowering in #37676, but YMMV.

Copy link
Contributor Author

@jseyfried jseyfried Nov 27, 2016

Choose a reason for hiding this comment

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

I'll wait for #37676 to merge and then rebase.

@jseyfried jseyfried force-pushed the refactor_path_resolution branch from f8e5593 to cc0383b Compare November 26, 2016 22:04
@nrc
Copy link
Member

nrc commented Nov 28, 2016

@bors: r+

@bors
Copy link
Contributor

bors commented Nov 28, 2016

📌 Commit 84be399 has been approved by nrc

@eddyb
Copy link
Member

eddyb commented Nov 28, 2016

@nrc See #38014 (comment). @bors r-

@jseyfried jseyfried force-pushed the refactor_path_resolution branch from 84be399 to f0fddcc Compare November 28, 2016 03:51
@bors
Copy link
Contributor

bors commented Nov 28, 2016

☔ The latest upstream changes (presumably #37676) made this pull request unmergeable. Please resolve the merge conflicts.

@@ -191,10 +189,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
span: syntax_pos::Span,
resolution_error: ResolutionError<'c>)
-> DiagnosticBuilder<'a> {
if !resolver.emit_errors {
return resolver.session.diagnostic().struct_dummy();
Copy link
Contributor

Choose a reason for hiding this comment

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

There should be a way to do speculative resolution without reporting errors.
It's used at least once now in fresh binding disambiguation and I'm using it in my error reporting branch as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@petrochenkov You can still do speculative resolution by passing record_used: None to resolve_path, resolve_ident_in_lexical_scope, or resolve_name_in_module.

@jseyfried jseyfried force-pushed the refactor_path_resolution branch from f0fddcc to 8fe525d Compare November 29, 2016 00:30
@jseyfried
Copy link
Contributor Author

Rebased and added a new commit -- r? @eddyb for new commit.

@rust-highfive rust-highfive assigned eddyb and unassigned nrc Nov 29, 2016
Copy link
Member

@eddyb eddyb left a comment

Choose a reason for hiding this comment

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

r=me with nit fixed

@@ -353,9 +350,6 @@ impl<'a> LoweringContext<'a> {
// `<I as Iterator>::Item::default`.
let ty = self.ty(p.span, hir::TyPath(hir::QPath::Resolved(qself, path)));

// Associate that innermost path type with the base Def.
self.resolver.record_resolution(ty.id, resolution.base_def);

ty
Copy link
Member

Choose a reason for hiding this comment

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

You can avoid the ty variable.

@jseyfried jseyfried force-pushed the refactor_path_resolution branch from a2ebc4c to c871637 Compare November 29, 2016 04:48
@jseyfried
Copy link
Contributor Author

@bors r=nrc

@bors
Copy link
Contributor

bors commented Nov 29, 2016

📌 Commit c871637 has been approved by nrc

@bors
Copy link
Contributor

bors commented Nov 30, 2016

⌛ Testing commit c871637 with merge 5a02480...

bors added a commit that referenced this pull request Nov 30, 2016
resolve: refactor path resolution

This is a pure refactoring, modulo minor diagnostics improvements.
r? @nrc
@bors bors merged commit c871637 into rust-lang:master Nov 30, 2016
@jseyfried jseyfried deleted the refactor_path_resolution branch December 6, 2016 05:45
bors added a commit that referenced this pull request Dec 26, 2016
More systematic error reporting in path resolution

Path resolution for types, expressions and patterns used various heuristics to give more helpful messages on unresolved or incorrectly resolved paths.
This PR combines these heuristics and applies them to all non-import paths.

First a path is resolved in all namespaces, starting from its primary namespace (to give messages like "expected function, found macro, you probably forgot `!`").
If this resolution doesn't give a desired result we create a base error - either "path is not resolved" or "path is resolved, but the resolution is not acceptable in this context".
Other helps and notes are applied to this base error using heuristics.

Here's the list of heuristics for a path with a last segment `name` in order.
First we issue special messages for unresolved `Self` and `self`.
Second we try to find free items named `name` in other modules and suggest to import them.
Then we try to find fields and associated items named `name` and suggest `self.name` or `Self::name`.
After that we try several deterministic context dependent heuristics like "expected value, found struct, you probably forgot `{}`".
If nothing of the above works we try to find candidates with other names using Levenshtein distance.

---

Some alternatives/notes/unresolved questions:
- ~~I had a strong desire to migrate all affected tests to `test/ui`, diagnostics comparison becomes much more meaningful, but I did this only for few tests so far.~~ (Done)
- ~~Labels for "unresolved path" errors are mostly useless now, it may make sense to move some help/notes to these labels, help becomes closer to the error this way.~~ (Done)
- ~~Currently only the first successful heuristic results in additional message shown to the user, it may make sense to print them all, they are rarely compatible, so the diagnostics bloat is unlikely.~~ (Done)
- Now when #38014 landed `resolve_path` can potentially be replaced with `smart_resolve_path` in couple more places - e.g. ~~visibilities~~ (done), ~~import prefixes~~ (done), HIR paths.

---

Some additional fixes:
- Associated suggestions and typo suggestions are filtered with a context specific predicate to avoid inapplicable suggestions.
- `adjust_local_def` works properly in speculative resolution.
- I also fixed a recently introduced ICE in partially resolved UFCS paths (see test `ufcs-partially-resolved.rs`).     Minimal reproduction:
    ```
    enum E {}
    fn main() {
        <u8 as E>::A;
    }
    ```
    Fixes #38409, fixes #38504 (duplicates).
- Some bugs in resolution of visibilities are fixed - `pub(Enum)`, `pub(Trait)`, `pub(non::local::path)`.
- Fixes #38012.
---

r? @jseyfried for technical details + @jonathandturner  for diagnostics changes
How to read the patch: `smart_resolve_path(_fragment)/resolve_qpath_anywhere` are written anew and replace `resolve_trait_reference`/`resolve_type`/`resolve_pattern_path`/`resolve_struct_path`/`resolve_expr` for `ExprKind::Path`, everything else can be read as a diff.
bors added a commit that referenced this pull request Jan 5, 2017
…=petrochenkov

resolve: don't `unused_qualifications`-check global paths

We started `unused_qualifications`-checking global paths in #38014, causing #38682.
Fixes #38682.
r? @nrc
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.

5 participants