summaryrefslogtreecommitdiff
path: root/src/librustc_resolve
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-11-18 03:25:59 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-11-27 00:32:30 +0300
commitdae4c7b1ff62da4901caf28653baa3133a40496c (patch)
treec805c4c5ed9442f48ed0a611cacdce35b03947d8 /src/librustc_resolve
parentfba116fc5fb7018faeb1834d42422d7bdbcc4f64 (diff)
downloadrust-dae4c7b1ff62da4901caf28653baa3133a40496c.tar.gz
resolve: Implement edition hygiene for imports and absolute paths
Use per-span hygiene in a few other places in resolve Prefer `rust_2015`/`rust_2018` helpers to comparing editions
Diffstat (limited to 'src/librustc_resolve')
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs19
-rw-r--r--src/librustc_resolve/error_reporting.rs5
-rw-r--r--src/librustc_resolve/lib.rs67
-rw-r--r--src/librustc_resolve/macros.rs5
4 files changed, 50 insertions, 46 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 72fe7355e4c..3f0780191fb 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -133,14 +133,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
// The root is prepended lazily, when the first non-empty prefix or terminating glob
// appears, so imports in braced groups can have roots prepended independently.
let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
- let crate_root = if !self.session.rust_2018() &&
- prefix_iter.peek().map_or(is_glob, |seg| !seg.ident.is_path_segment_keyword()) {
- Some(Segment::from_ident(Ident::new(
- keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo()
- )))
- } else {
- None
- };
+ let crate_root = match prefix_iter.peek() {
+ Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
+ Some(seg.ident.span.ctxt())
+ }
+ None if is_glob && use_tree.span.rust_2015() => {
+ Some(use_tree.span.ctxt())
+ }
+ _ => None,
+ }.map(|ctxt| Segment::from_ident(Ident::new(
+ keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt)
+ )));
let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>();
debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs
index 263d23d133e..e2a6303f579 100644
--- a/src/librustc_resolve/error_reporting.rs
+++ b/src/librustc_resolve/error_reporting.rs
@@ -33,7 +33,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
(Some(fst), Some(snd)) if fst.ident.name == keywords::CrateRoot.name() &&
!snd.ident.is_path_segment_keyword() => {}
// `ident::...` on 2018
- (Some(fst), _) if self.session.rust_2018() && !fst.ident.is_path_segment_keyword() => {
+ (Some(fst), _) if fst.ident.span.rust_2018() &&
+ !fst.ident.is_path_segment_keyword() => {
// Insert a placeholder that's later replaced by `self`/`super`/etc.
path.insert(0, Segment::from_ident(keywords::Invalid.ident()));
}
@@ -141,7 +142,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<(Vec<Segment>, Option<String>)> {
- if !self.session.rust_2018() {
+ if path[1].ident.span.rust_2015() {
return None;
}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 443b1ccdef8..2e7ed80c91b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2354,14 +2354,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}
fn future_proof_import(&mut self, use_tree: &ast::UseTree) {
- if !self.session.rust_2018() {
- return;
- }
-
let segments = &use_tree.prefix.segments;
if !segments.is_empty() {
let ident = segments[0].ident;
- if ident.is_path_segment_keyword() {
+ if ident.is_path_segment_keyword() || ident.span.rust_2015() {
return;
}
@@ -3181,10 +3177,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// Try to lookup the name in more relaxed fashion for better error reporting.
let ident = path.last().unwrap().ident;
- let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
+ let candidates = this.lookup_import_candidates(ident, ns, is_expected);
if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
let enum_candidates =
- this.lookup_import_candidates(ident.name, ns, is_enum_variant);
+ this.lookup_import_candidates(ident, ns, is_enum_variant);
let mut enum_candidates = enum_candidates.iter()
.map(|suggestion| import_candidate_to_paths(&suggestion)).collect::<Vec<_>>();
enum_candidates.sort();
@@ -3772,7 +3768,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
continue;
}
if name == keywords::Extern.name() ||
- name == keywords::CrateRoot.name() && self.session.rust_2018() {
+ name == keywords::CrateRoot.name() && ident.span.rust_2018() {
module =
Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude));
continue;
@@ -3875,7 +3871,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
let msg = if module_def == self.graph_root.def() {
let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
let mut candidates =
- self.lookup_import_candidates(name, TypeNS, is_mod);
+ self.lookup_import_candidates(ident, TypeNS, is_mod);
candidates.sort_by_cached_key(|c| {
(c.path.segments.len(), c.path.to_string())
});
@@ -3911,11 +3907,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
path_span: Span,
second_binding: Option<&NameBinding>,
) {
- // In the 2018 edition this lint is a hard error, so nothing to do
- if self.session.rust_2018() {
- return
- }
-
let (diag_id, diag_span) = match crate_lint {
CrateLint::No => return,
CrateLint::SimplePath(id) => (id, path_span),
@@ -3924,8 +3915,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
};
let first_name = match path.get(0) {
- Some(ident) => ident.ident.name,
- None => return,
+ // In the 2018 edition this lint is a hard error, so nothing to do
+ Some(seg) if seg.ident.span.rust_2015() => seg.ident.name,
+ _ => return,
};
// We're only interested in `use` paths which should start with
@@ -4507,7 +4499,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}
fn lookup_import_candidates_from_module<FilterFn>(&mut self,
- lookup_name: Name,
+ lookup_ident: Ident,
namespace: Namespace,
start_module: &'a ModuleData<'a>,
crate_name: Ident,
@@ -4534,11 +4526,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
if !name_binding.is_importable() { return; }
// collect results based on the filter function
- if ident.name == lookup_name && ns == namespace {
+ if ident.name == lookup_ident.name && ns == namespace {
if filter_fn(name_binding.def()) {
// create the path
let mut segms = path_segments.clone();
- if self.session.rust_2018() {
+ if lookup_ident.span.rust_2018() {
// crate-local absolute paths start with `crate::` in edition 2018
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
segms.insert(
@@ -4572,7 +4564,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
let is_extern_crate_that_also_appears_in_prelude =
name_binding.is_extern_crate() &&
- self.session.rust_2018();
+ lookup_ident.span.rust_2018();
let is_visible_to_user =
!in_module_is_extern || name_binding.vis == ty::Visibility::Public;
@@ -4599,16 +4591,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
/// 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,
+ lookup_ident: Ident,
namespace: Namespace,
filter_fn: FilterFn)
-> Vec<ImportSuggestion>
where FilterFn: Fn(Def) -> bool
{
let mut suggestions = self.lookup_import_candidates_from_module(
- lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn);
+ lookup_ident, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn);
- if self.session.rust_2018() {
+ if lookup_ident.span.rust_2018() {
let extern_prelude_names = self.extern_prelude.clone();
for (ident, _) in extern_prelude_names.into_iter() {
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
@@ -4620,7 +4612,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
self.populate_module_if_necessary(&crate_root);
suggestions.extend(self.lookup_import_candidates_from_module(
- lookup_name, namespace, crate_root, ident, &filter_fn));
+ lookup_ident, namespace, crate_root, ident, &filter_fn));
}
}
}
@@ -4712,19 +4704,26 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
ast::VisibilityKind::Restricted { ref path, id, .. } => {
// For visibilities we are not ready to provide correct implementation of "uniform
// paths" right now, so on 2018 edition we only allow module-relative paths for now.
- let first_ident = path.segments[0].ident;
- if self.session.rust_2018() && !first_ident.is_path_segment_keyword() {
+ // On 2015 edition visibilities are resolved as crate-relative by default,
+ // so we are prepending a root segment if necessary.
+ let ident = path.segments.get(0).expect("empty path in visibility").ident;
+ let crate_root = if ident.is_path_segment_keyword() {
+ None
+ } else if ident.span.rust_2018() {
let msg = "relative paths are not supported in visibilities on 2018 edition";
- self.session.struct_span_err(first_ident.span, msg)
+ self.session.struct_span_err(ident.span, msg)
.span_suggestion(path.span, "try", format!("crate::{}", path))
.emit();
return ty::Visibility::Public;
- }
- // On 2015 visibilities are resolved as crate-relative by default,
- // add starting root segment if necessary.
- let segments = path.make_root().iter().chain(path.segments.iter())
- .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) })
- .collect::<Vec<_>>();
+ } else {
+ let ctxt = ident.span.ctxt();
+ Some(Segment::from_ident(Ident::new(
+ keywords::CrateRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt)
+ )))
+ };
+
+ let segments = crate_root.into_iter()
+ .chain(path.segments.iter().map(|seg| seg.into())).collect::<Vec<_>>();
let def = self.smart_resolve_path_fragment(
id,
None,
@@ -4837,7 +4836,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
help_msgs.push(format!("consider adding an explicit import of \
`{ident}` to disambiguate", ident = ident))
}
- if b.is_extern_crate() && self.session.rust_2018() {
+ if b.is_extern_crate() && ident.span.rust_2018() {
help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously",
ident = ident, thing = b.descr()))
}
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 581756dc6bf..6fa9110fedb 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -605,6 +605,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
assert!(force || !record_used); // `record_used` implies `force`
assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
+ let rust_2015 = ident.span.rust_2015();
ident = ident.modern();
// Make sure `self`, `super` etc produce an error when passed to here.
@@ -696,7 +697,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
}
WhereToResolve::MacroUsePrelude => {
- if use_prelude || self.session.rust_2015() {
+ if use_prelude || rust_2015 {
match self.macro_use_prelude.get(&ident.name).cloned() {
Some(binding) =>
Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)),
@@ -725,7 +726,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
}
WhereToResolve::LegacyPluginHelpers => {
- if (use_prelude || self.session.rust_2015()) &&
+ if (use_prelude || rust_2015) &&
self.session.plugin_attributes.borrow().iter()
.any(|(name, _)| ident.name == &**name) {
let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),