提交 f7202e40 编写于 作者: B bors

Auto merge of #51456 - qmx:crate-in-path, r=nikomatsakis

resolve suggestions should use `crate::` when enabled

I couldn't find a way to add a specific assertion for the ui test, so the expected output is living under the `crates-in-path.stderr` ui test.

- is this the right place for the test?

fixes #51212
......@@ -1952,9 +1952,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
"access to extern crates through prelude is experimental").emit();
}
let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(crate_root);
let crate_root = self.load_extern_prelude_crate_if_needed(ident);
let binding = (crate_root, ty::Visibility::Public,
ident.span, Mark::root()).to_name_binding(self.arenas);
......@@ -1982,6 +1980,13 @@ fn resolve_ident_in_lexical_scope(&mut self,
None
}
fn load_extern_prelude_crate_if_needed(&mut self, ident: Ident) -> Module<'a> {
let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(&crate_root);
crate_root
}
fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
-> Option<Module<'a>> {
if !module.expansion.is_descendant_of(span.ctxt().outer()) {
......@@ -4228,16 +4233,11 @@ fn get_traits_in_module_containing_item(&mut self,
}
}
/// When name resolution fails, this method can be used to look up candidate
/// entities with the expected name. It allows filtering them using the
/// supplied predicate (which should be used to only accept the types of
/// definitions expected e.g. traits). The lookup spans across all crates.
///
/// NOTE: The method does not look into imports, but this is not a problem,
/// since we report the definitions (thus, the de-aliased imports).
fn lookup_import_candidates<FilterFn>(&mut self,
fn lookup_import_candidates_from_module<FilterFn>(&mut self,
lookup_name: Name,
namespace: Namespace,
start_module: &'a ModuleData<'a>,
crate_name: Ident,
filter_fn: FilterFn)
-> Vec<ImportSuggestion>
where FilterFn: Fn(Def) -> bool
......@@ -4245,7 +4245,8 @@ fn lookup_import_candidates<FilterFn>(&mut self,
let mut candidates = Vec::new();
let mut worklist = Vec::new();
let mut seen_modules = FxHashSet();
worklist.push((self.graph_root, Vec::new(), false));
let not_local_module = crate_name != keywords::Crate.ident();
worklist.push((start_module, Vec::<ast::PathSegment>::new(), not_local_module));
while let Some((in_module,
path_segments,
......@@ -4264,17 +4265,14 @@ fn lookup_import_candidates<FilterFn>(&mut self,
if ident.name == lookup_name && ns == namespace {
if filter_fn(name_binding.def()) {
// create the path
let mut segms = if self.session.rust_2018() && !in_module_is_extern {
let mut segms = path_segments.clone();
if self.session.rust_2018() {
// crate-local absolute paths start with `crate::` in edition 2018
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
let mut full_segms = vec![
ast::PathSegment::from_ident(keywords::Crate.ident())
];
full_segms.extend(path_segments.clone());
full_segms
} else {
path_segments.clone()
};
segms.insert(
0, ast::PathSegment::from_ident(crate_name)
);
}
segms.push(ast::PathSegment::from_ident(ident));
let path = Path {
......@@ -4300,7 +4298,14 @@ fn lookup_import_candidates<FilterFn>(&mut self,
let mut path_segments = path_segments.clone();
path_segments.push(ast::PathSegment::from_ident(ident));
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
let is_extern_crate_that_also_appears_in_prelude =
name_binding.is_extern_crate() &&
self.session.rust_2018();
let is_visible_to_user =
!in_module_is_extern || name_binding.vis == ty::Visibility::Public;
if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
// add the module to the lookup
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
if seen_modules.insert(module.def_id().unwrap()) {
......@@ -4314,6 +4319,45 @@ fn lookup_import_candidates<FilterFn>(&mut self,
candidates
}
/// When name resolution fails, this method can be used to look up candidate
/// entities with the expected name. It allows filtering them using the
/// supplied predicate (which should be used to only accept the types of
/// definitions expected e.g. traits). The lookup spans across all crates.
///
/// NOTE: The method does not look into imports, but this is not a problem,
/// since we report the definitions (thus, the de-aliased imports).
fn lookup_import_candidates<FilterFn>(&mut self,
lookup_name: Name,
namespace: Namespace,
filter_fn: FilterFn)
-> Vec<ImportSuggestion>
where FilterFn: Fn(Def) -> bool
{
let mut suggestions = vec![];
suggestions.extend(
self.lookup_import_candidates_from_module(
lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn
)
);
if self.session.features_untracked().extern_prelude {
let extern_prelude_names = self.extern_prelude.clone();
for &krate_name in extern_prelude_names.iter() {
let krate_ident = Ident::with_empty_ctxt(krate_name);
let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident);
suggestions.extend(
self.lookup_import_candidates_from_module(
lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn
)
);
}
}
suggestions
}
fn find_module(&mut self,
module_def: Def)
-> Option<(Module<'a>, ImportSuggestion)>
......
-include ../tools.mk
all:
$(RUSTC) ep-nested-lib.rs
$(RUSTC) use-suggestions.rs --edition=2018 --extern ep_nested_lib=$(TMPDIR)/libep_nested_lib.rlib 2>&1 | $(CGREP) "use ep_nested_lib::foo::bar::Baz"
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "rlib"]
pub mod foo {
pub mod bar {
pub struct Baz;
}
}
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
let x = Baz{};
}
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// edition:2018
#![feature(edition_2018_preview)]
mod bar {
crate struct Foo;
}
fn main() {
Foo;
//~^ ERROR cannot find value `Foo` in this scope [E0425]
}
error[E0425]: cannot find value `Foo` in this scope
--> $DIR/crate-in-paths.rs:20:5
|
LL | Foo;
| ^^^ not found in this scope
help: possible candidate is found in another module, you can import it into scope
|
LL | use crate::bar::Foo;
|
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册