Skip to content

Commit

Permalink
Rollup merge of #73652 - da-x:add-reexported-to-use-suggestions, r=pe…
Browse files Browse the repository at this point in the history
…trochenkov

Add re-exports to use suggestions

In the following example, an inaccessible path is suggested via `use foo::bar::X;` whereas an accessible public exported path can be suggested instead.

```rust
mod foo {
    mod bar {
        pub struct X;
    }
    pub use self::bar::X;
}

fn main() { X; }
```

This fixes the issue.
  • Loading branch information
Dylan-DPC committed Jun 24, 2020
2 parents 45de677 + 037e930 commit 2a6e660
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 17 deletions.
28 changes: 20 additions & 8 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,18 +643,18 @@ impl<'a> Resolver<'a> {
let not_local_module = crate_name.name != kw::Crate;
let mut worklist =
vec![(start_module, Vec::<ast::PathSegment>::new(), true, not_local_module)];
let mut worklist_via_import = vec![];

while let Some((in_module, path_segments, accessible, in_module_is_extern)) = worklist.pop()
while let Some((in_module, path_segments, accessible, in_module_is_extern)) =
match worklist.pop() {
None => worklist_via_import.pop(),
Some(x) => Some(x),
}
{
// We have to visit module children in deterministic order to avoid
// instabilities in reported imports (#43552).
in_module.for_each_child(self, |this, ident, ns, name_binding| {
// avoid imports entirely
if name_binding.is_import() && !name_binding.is_extern_crate() {
return;
}

// avoid non-importable candidates as well
// avoid non-importable candidates
if !name_binding.is_importable() {
return;
}
Expand All @@ -667,6 +667,17 @@ impl<'a> Resolver<'a> {
return;
}

let via_import = name_binding.is_import() && !name_binding.is_extern_crate();

// There is an assumption elsewhere that paths of variants are in the enum's
// declaration and not imported. With this assumption, the variant component is
// chopped and the rest of the path is assumed to be the enum's own path. For
// errors where a variant is used as the type instead of the enum, this causes
// funny looking invalid suggestions, i.e `foo` instead of `foo::MyEnum`.
if via_import && name_binding.is_possibly_imported_variant() {
return;
}

// collect results based on the filter function
// avoid suggesting anything from the same module in which we are resolving
if ident.name == lookup_ident.name
Expand Down Expand Up @@ -724,7 +735,8 @@ impl<'a> Resolver<'a> {
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
// add the module to the lookup
if seen_modules.insert(module.def_id().unwrap()) {
worklist.push((module, path_segments, child_accessible, is_extern));
if via_import { &mut worklist_via_import } else { &mut worklist }
.push((module, path_segments, child_accessible, is_extern));
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,13 @@ impl<'a> NameBinding<'a> {
}
}

fn is_possibly_imported_variant(&self) -> bool {
match self.kind {
NameBindingKind::Import { binding, .. } => binding.is_possibly_imported_variant(),
_ => self.is_variant(),
}
}

// We sometimes need to treat variants as `pub` for backwards compatibility.
fn pseudo_vis(&self) -> ty::Visibility {
if self.is_variant() && self.res().def_id().is_local() {
Expand Down
4 changes: 4 additions & 0 deletions src/test/ui/glob-resolve1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ fn main() {
foo::<C>(); //~ ERROR: cannot find type `C` in this scope
foo::<D>(); //~ ERROR: cannot find type `D` in this scope
}

mod other {
pub fn import() {}
}
5 changes: 5 additions & 0 deletions src/test/ui/glob-resolve1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ error[E0425]: cannot find function `import` in this scope
|
LL | import();
| ^^^^^^ not found in this scope
|
help: consider importing this function
|
LL | use other::import;
|

error[E0412]: cannot find type `A` in this scope
--> $DIR/glob-resolve1.rs:28:11
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/namespace/namespace-mix.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ help: consider importing one of these items instead
|
LL | use m2::S;
|
LL | use namespace_mix::xm2::S;
LL | use xm2::S;
|

error[E0423]: expected value, found type alias `xm1::S`
Expand All @@ -39,7 +39,7 @@ help: consider importing one of these items instead
|
LL | use m2::S;
|
LL | use namespace_mix::xm2::S;
LL | use xm2::S;
|

error[E0423]: expected value, found struct variant `m7::V`
Expand All @@ -61,7 +61,7 @@ help: consider importing one of these items instead
|
LL | use m8::V;
|
LL | use namespace_mix::xm8::V;
LL | use xm8::V;
|

error[E0423]: expected value, found struct variant `xm7::V`
Expand All @@ -83,7 +83,7 @@ help: consider importing one of these items instead
|
LL | use m8::V;
|
LL | use namespace_mix::xm8::V;
LL | use xm8::V;
|

error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/resolve/issue-21221-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ error[E0405]: cannot find trait `T` in this scope
LL | impl T for Foo { }
| ^ not found in this scope
|
help: consider importing this trait
help: consider importing one of these items
|
LL | use baz::T;
|
LL | use foo::bar::T;
|
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/resolve/privacy-enum-ctor.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ LL | let _: E = m::n::Z;
| ^
help: consider importing this enum
|
LL | use m::n::Z;
LL | use m::Z;
|

error[E0423]: expected value, found enum `m::n::Z`
Expand Down Expand Up @@ -165,7 +165,7 @@ LL | let _: E = m::n::Z::Fn;
| ^
help: consider importing this enum
|
LL | use m::n::Z;
LL | use m::Z;
|

error[E0412]: cannot find type `Z` in this scope
Expand All @@ -183,7 +183,7 @@ LL | let _: E = m::n::Z::Struct;
| ^
help: consider importing this enum
|
LL | use m::n::Z;
LL | use m::Z;
|

error[E0423]: expected value, found struct variant `m::n::Z::Struct`
Expand Down Expand Up @@ -212,7 +212,7 @@ LL | let _: E = m::n::Z::Unit {};
| ^
help: consider importing this enum
|
LL | use m::n::Z;
LL | use m::Z;
|

error[E0603]: enum `Z` is private
Expand Down

0 comments on commit 2a6e660

Please sign in to comment.