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,