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

Fix #2443 #2444

Closed
wants to merge 1 commit into from
Closed

Conversation

edwin0cheng
Copy link
Member

This PR try to fix #2443 by update all use-as alias after PerNs changed in DefCollector.

@edwin0cheng
Copy link
Member Author

Side note: The main reason I would like to fix this weird bug is, I want to move :
https://github.com/rust-analyzer/rust-analyzer/blob/8b278b1ab660df0728508e45e88ac769a2e03a58/crates/ra_hir_def/src/nameres/collector.rs#L770-L779

to

https://github.com/rust-analyzer/rust-analyzer/blob/8b278b1ab660df0728508e45e88ac769a2e03a58/crates/ra_hir_def/src/nameres/collector.rs#L470

And shared the collect_macro_expansion invocation. This will help us to refactor the whole macro expansion later.

@@ -115,6 +115,9 @@ pub struct ModuleData {
pub definition: Option<FileId>,

pub impls: Vec<ImplId>,

/// alias information (Name => Alias)
pub aliases: FxHashMap<Name, Name>,
Copy link
Member

Choose a reason for hiding this comment

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

This info is only need during name-resolutrion process, not afterweards, so this field should be a part of ModCollector

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I agreed.

Some((alias.clone(), res.clone()))
})
.collect();

Copy link
Member

Choose a reason for hiding this comment

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

Hm, I am feeling uneasy about this approach. Seems like Name -> Name mapping errases essential information (like from what import the name initially came). I imagine use foo::a as b; use bar::a as b might actually be legal if a's live in different namespaces?

And I think we actually have all the required infrastructure in place to fix this properly? Basically, an use foo as bar import should be marked unresolved, and, when we add foo to the module namespace, on the next iteration of the loop { } we should also add bar. It seems like we need to fix some bug in existing infra, rather than add something specific for aliases tracking.

Copy link
Member Author

@edwin0cheng edwin0cheng Dec 2, 2019

Choose a reason for hiding this comment

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

And I think we actually have all the required infrastructure in place to fix this properly? Basically, an use foo as bar import should be marked unresolved.

Um.. imagine this example:

mod m {
    macro_rules! _foo {
        ($x:ident) => { type $x = u64; }
    }
    pub(crate) use _foo as foo;
}

macro_rules! foo {
    () => {}
}

m::foo!(foo);
use foo as bar;   // <-----

The order of resolving will be:

mod m
macro_rules _foo 
use _foo as foo
macro_rules foo
use foo as bar  // foo is macro_rules! foo
m:foo!(foo)
type foo = u64

Copy link
Member Author

@edwin0cheng edwin0cheng Dec 2, 2019

Choose a reason for hiding this comment

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

Hm, I am feeling uneasy about this approach. Seems like Name -> Name mapping errases essential information (like from what import the name initially came). I imagine use foo::a as b; use bar::a as b might actually be legal if a's live in different namespaces?

Yes, I agree, I didn't think of this problem. Can I fix it by adding more information to alias map ? Or do you feel there is a better approach to solve it ?

Copy link
Member

Choose a reason for hiding this comment

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

Ah, so the problem is that we end up with bar only as macro, and miss bar as a type, right?

So looks like the problem is that we remove use foo as bar from the set of unresolved imports when it resolves in any namespace, while we should only do this if it resolves in all namespaces. I wonder if we construct a test case here which doens't involve any macros? something like this

type T = ();

use self::T as  Y;

use m::*;

mod m {
  pub const T: () = ();
}

fn main() { let _: Y = Y; }

Looks like rust-analyzer indeed fails to see that Y is a value here:

image

Copy link
Member

Choose a reason for hiding this comment

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

yeah, one doesn't need aliases to construct a similar problem:

image

image

Copy link
Member Author

@edwin0cheng edwin0cheng Dec 2, 2019

Choose a reason for hiding this comment

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

Yes indeed. The problem here is the use alias. My approach to fix it is mark the alias and rewrite to it. OTOH, we can mark it to unresolved, but the problem is, how can we know the resolve loop should be ended ?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, one doesn't need aliases to construct a similar problem:

Okay, my alias fix won't work in your case. :)

Copy link
Member

Choose a reason for hiding this comment

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

Just checked that IntelliJ also doesn't handle the above example 😩

@edwin0cheng
Copy link
Member Author

Closed, in flavor of #2466

@edwin0cheng edwin0cheng closed this Dec 3, 2019
@edwin0cheng edwin0cheng deleted the non-legacy-use-as branch December 3, 2019 11:42
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.

infer break use-as alias after macro expansion
2 participants