diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 858e6dc6232..777543bcf37 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -125,36 +125,24 @@ impl<'a, 'cl> Resolver<'a, 'cl> { debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})", parent_prefix, use_tree, nested); - let uniform_paths = - self.session.rust_2018() && - self.session.features_untracked().uniform_paths; + let mut prefix_iter = parent_prefix.iter().cloned() + .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident)).peekable(); - let prefix_iter = || parent_prefix.iter().cloned() - .chain(use_tree.prefix.segments.iter().map(|seg| seg.into())); - let prefix_start = prefix_iter().next(); - let starts_with_non_keyword = prefix_start.map_or(false, |seg| { - !seg.ident.is_path_segment_keyword() - }); - - // Imports are resolved as global by default, prepend `CrateRoot`, - // unless `#![feature(uniform_paths)]` is enabled. - let inject_crate_root = - !uniform_paths && - match use_tree.kind { - // HACK(eddyb) special-case `use *` to mean `use ::*`. - ast::UseTreeKind::Glob if prefix_start.is_none() => true, - _ => starts_with_non_keyword, - }; - let root = if inject_crate_root { - let span = use_tree.prefix.span.shrink_to_lo(); - Some(Segment::from_ident(Ident::new(keywords::CrateRoot.name(), span))) + // On 2015 edition imports are resolved as crate-relative by default, + // so prefixes are prepended with crate root segment if necessary. + // 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, |ident| !ident.is_path_segment_keyword()) { + Some(Ident::new(keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo())) } else { None }; - let prefix: Vec<_> = root.into_iter().chain(prefix_iter()).collect(); - + let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>(); debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix); + let empty_for_self = |prefix: &[Segment]| { prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name() diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 50ab8ef9c7b..49661954e58 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -68,7 +68,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { ) -> Option<(Vec<Segment>, Option<String>)> { // Replace first ident with `self` and check if that is valid. path[0].ident.name = keywords::SelfValue.name(); - let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No); + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { Some((path, None)) @@ -92,7 +92,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { ) -> Option<(Vec<Segment>, Option<String>)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Crate.name(); - let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No); + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { Some(( @@ -123,7 +123,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { ) -> Option<(Vec<Segment>, Option<String>)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = keywords::Super.name(); - let result = self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No); + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { Some((path, None)) @@ -164,8 +164,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // Replace the first after root (a placeholder we inserted) with a crate name // and check if that is valid. path[1].ident.name = *name; - let result = - self.resolve_path(None, &path, None, parent_scope, false, span, CrateLint::No); + let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", name, path, result); if let PathResult::Module(..) = result { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 241db271177..279fbafdcd7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1661,8 +1661,8 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { let segments = &path.segments; let path = Segment::from_path(&path); // FIXME (Manishearth): Intra doc links won't get warned of epoch changes - let def = match self.resolve_path_without_parent_scope(None, &path, Some(namespace), - true, span, CrateLint::No) { + match self.resolve_path_without_parent_scope(&path, Some(namespace), true, span, + CrateLint::No) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => @@ -2466,7 +2466,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let span = trait_ref.path.span; if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path_without_parent_scope( - None, &path, Some(TypeNS), false, @@ -2991,7 +2990,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } else { let mod_path = &path[..path.len() - 1]; let mod_prefix = match this.resolve_path_without_parent_scope( - None, mod_path, Some(TypeNS), false, span, CrateLint::No + mod_path, Some(TypeNS), false, span, CrateLint::No ) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.def(), @@ -3480,7 +3479,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } let result = match self.resolve_path_without_parent_scope( - None, &path, Some(ns), true, @@ -3527,7 +3525,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { path[0].ident.name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path_without_parent_scope( - None, &[*path.last().unwrap()], Some(ns), false, @@ -3551,9 +3548,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_path_without_parent_scope( &mut self, - base_module: Option<ModuleOrUniformRoot<'a>>, path: &[Segment], - opt_ns: Option<Namespace>, // `None` indicates a module path + opt_ns: Option<Namespace>, // `None` indicates a module path in import record_used: bool, path_span: Span, crate_lint: CrateLint, @@ -3562,21 +3558,19 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // other paths will do okay with parent module alone. assert!(opt_ns != None && opt_ns != Some(MacroNS)); let parent_scope = ParentScope { module: self.current_module, ..self.dummy_parent_scope() }; - self.resolve_path(base_module, path, opt_ns, &parent_scope, - record_used, path_span, crate_lint) + self.resolve_path(path, opt_ns, &parent_scope, record_used, path_span, crate_lint) } fn resolve_path( &mut self, - base_module: Option<ModuleOrUniformRoot<'a>>, path: &[Segment], - opt_ns: Option<Namespace>, // `None` indicates a module path + opt_ns: Option<Namespace>, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, record_used: bool, path_span: Span, crate_lint: CrateLint, ) -> PathResult<'a> { - let mut module = base_module; + let mut module = None; let mut allow_super = true; let mut second_binding = None; self.current_module = parent_scope.module; @@ -3673,10 +3667,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let binding = if let Some(module) = module { self.resolve_ident_in_module(module, ident, ns, record_used, path_span) - } else if opt_ns == Some(MacroNS) { + } else if opt_ns.is_none() || opt_ns == Some(MacroNS) { assert!(ns == TypeNS); - self.early_resolve_ident_in_lexical_scope(ident, ns, None, parent_scope, - record_used, record_used, path_span) + self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(), + parent_scope, record_used, record_used, + path_span) } else { let record_used_id = if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None }; @@ -3763,9 +3758,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding); - PathResult::Module(module.unwrap_or_else(|| { - span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path); - })) + PathResult::Module(match module { + Some(module) => module, + None if path.is_empty() => ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name()), + _ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path), + }) } fn lint_if_path_starts_with_module( @@ -4050,7 +4047,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Search in module. let mod_path = &path[..path.len() - 1]; if let PathResult::Module(module) = self.resolve_path_without_parent_scope( - None, mod_path, Some(TypeNS), false, span, CrateLint::No + mod_path, Some(TypeNS), false, span, CrateLint::No ) { if let ModuleOrUniformRoot::Module(module) = module { add_module_candidates(module, &mut names); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index db5b516e7b2..4348f91a63e 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -477,7 +477,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } if path.len() > 1 { - let def = match self.resolve_path(None, &path, Some(MacroNS), parent_scope, + let def = match self.resolve_path(&path, Some(MacroNS), parent_scope, false, path_span, CrateLint::No) { PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), @@ -506,7 +506,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { def } else { let binding = self.early_resolve_ident_in_lexical_scope( - path[0].ident, MacroNS, Some(kind), parent_scope, false, force, path_span + path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span ); match binding { Ok(..) => {} @@ -525,12 +525,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during // expansion and import resolution (perhaps they can be merged in the future). // The function is used for resolving initial segments of macro paths (e.g. `foo` in - // `foo::bar!(); or `foo!();`) and can be used for "uniform path" imports in the future. + // `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition. crate fn early_resolve_ident_in_lexical_scope( &mut self, mut ident: Ident, ns: Namespace, - kind: Option<MacroKind>, + macro_kind: Option<MacroKind>, + is_import: bool, parent_scope: &ParentScope<'a>, record_used: bool, force: bool, @@ -604,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 ident = ident.modern(); // This is *the* result, resolution from the scope closest to the resolved identifier. @@ -792,7 +794,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { match result { Ok((binding, flags, ambig_flags)) => { - if sub_namespace_mismatch(kind, binding.macro_kind()) { + if sub_namespace_mismatch(macro_kind, binding.macro_kind()) { continue_search!(); } @@ -804,7 +806,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { = innermost_result { // Found another solution, if the first one was "weak", report an error. if binding.def() != innermost_binding.def() && - (innermost_binding.is_glob_import() || + (is_import || + innermost_binding.is_glob_import() || innermost_binding.may_appear_after(parent_scope.expansion, binding) || innermost_flags.intersects(ambig_flags) || flags.intersects(innermost_ambig_flags) || @@ -838,7 +841,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } let determinacy = Determinacy::determined(force); - if determinacy == Determinacy::Determined && kind == Some(MacroKind::Attr) { + if determinacy == Determinacy::Determined && macro_kind == Some(MacroKind::Attr) { // For single-segment attributes interpret determinate "no resolution" as a custom // attribute. (Lexical resolution implies the first segment and attr kind should imply // the last segment, so we are certainly working with a single-segment attribute here.) @@ -860,7 +863,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { for (mut path, parent_scope, path_span) in macro_resolutions { // FIXME: Path resolution will ICE if segment IDs present. for seg in &mut path { seg.id = None; } - match self.resolve_path(None, &path, Some(MacroNS), &parent_scope, + match self.resolve_path(&path, Some(MacroNS), &parent_scope, true, path_span, CrateLint::No) { PathResult::NonModule(_) => {}, PathResult::Failed(span, msg, _) => { @@ -874,7 +877,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new()); for (ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions { let binding = self.early_resolve_ident_in_lexical_scope( - ident, MacroNS, Some(kind), &parent_scope, true, true, ident.span + ident, MacroNS, Some(kind), false, &parent_scope, true, true, ident.span ); match binding { Ok(binding) => { @@ -915,7 +918,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new()); for (ident, parent_scope) in builtin_attrs { let binding = self.early_resolve_ident_in_lexical_scope( - ident, MacroNS, Some(MacroKind::Attr), &parent_scope, true, true, ident.span + ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span ); if let Ok(binding) = binding { if binding.def_ignoring_ambiguity() != diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index ece057358e6..60d6bb7bdc9 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -152,10 +152,6 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { let can_be_relative = !ident.is_path_segment_keyword() && root == keywords::Invalid.name(); if can_be_relative { - // Relative paths should only get here if the feature-gate is on. - assert!(self.session.rust_2018() && - self.session.features_untracked().uniform_paths); - // Try first to resolve relatively. let mut ctxt = ident.span.ctxt().modern(); let self_module = self.resolve_self(&mut ctxt, self.current_module); @@ -750,7 +746,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // while resolving its module path. directive.vis.set(ty::Visibility::Invisible); let result = self.resolve_path( - Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())), &directive.module_path[..], None, &directive.parent_scope, @@ -829,7 +824,6 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let ImportDirective { ref module_path, span, .. } = *directive; let module_result = self.resolve_path( - Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())), &module_path, None, &directive.parent_scope,