Skip to content

Commit 1982f18

Browse files
committed
Auto merge of #55297 - petrochenkov:uni, r=Mark-Simulacrum
Partial implementation of uniform paths 2.0 to land before beta Reimplementation of uniform paths using in-scope resolution rather than canaries is a minor breaking change due to stricter future-proofing, so it needs to be landed before beta or backported later. I hope to implement at least something until beta so we have less to backport. r? @Mark-Simulacrum
2 parents 18311a6 + c57f0a7 commit 1982f18

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+518
-544
lines changed

src/librustc/hir/lowering.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -3133,7 +3133,8 @@ impl<'a> LoweringContext<'a> {
31333133
// Privatize the degenerate import base, used only to check
31343134
// the stability of `use a::{};`, to avoid it showing up as
31353135
// a re-export by accident when `pub`, e.g. in documentation.
3136-
let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
3136+
let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err);
3137+
let path = P(self.lower_path_extra(def, &prefix, None, ParamMode::Explicit, None));
31373138
*vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
31383139
hir::ItemKind::Use(path, hir::UseKind::ListStem)
31393140
}

src/librustc_resolve/build_reduced_graph.rs

+100-88
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use syntax::ast::{Name, Ident};
3535
use syntax::attr;
3636

3737
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
38-
use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
38+
use syntax::ast::{MetaItemKind, Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
3939
use syntax::ext::base::{MacroKind, SyntaxExtension};
4040
use syntax::ext::base::Determinacy::Undetermined;
4141
use syntax::ext::hygiene::Mark;
@@ -83,12 +83,6 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark, IsMacroExport)
8383
}
8484
}
8585

86-
#[derive(Default, PartialEq, Eq)]
87-
struct LegacyMacroImports {
88-
import_all: Option<Span>,
89-
imports: Vec<(Name, Span)>,
90-
}
91-
9286
impl<'a, 'cl> Resolver<'a, 'cl> {
9387
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
9488
/// otherwise, reports an error.
@@ -117,23 +111,23 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
117111

118112
fn build_reduced_graph_for_use_tree(
119113
&mut self,
120-
root_use_tree: &ast::UseTree,
121-
root_id: NodeId,
114+
// This particular use tree
122115
use_tree: &ast::UseTree,
123116
id: NodeId,
124-
vis: ty::Visibility,
125117
parent_prefix: &[Segment],
126-
mut uniform_paths_canary_emitted: bool,
127118
nested: bool,
119+
mut uniform_paths_canary_emitted: bool,
120+
// The whole `use` item
121+
parent_scope: ParentScope<'a>,
128122
item: &Item,
129-
expansion: Mark,
123+
vis: ty::Visibility,
124+
root_span: Span,
130125
) {
131126
debug!("build_reduced_graph_for_use_tree(parent_prefix={:?}, \
132127
uniform_paths_canary_emitted={}, \
133128
use_tree={:?}, nested={})",
134129
parent_prefix, uniform_paths_canary_emitted, use_tree, nested);
135130

136-
let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
137131
let uniform_paths =
138132
self.session.rust_2018() &&
139133
self.session.features_untracked().uniform_paths;
@@ -221,10 +215,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
221215
subclass,
222216
source.ident.span,
223217
id,
224-
root_use_tree.span,
225-
root_id,
218+
root_span,
219+
item.id,
226220
ty::Visibility::Invisible,
227-
expansion,
221+
parent_scope.clone(),
228222
true, // is_uniform_paths_canary
229223
);
230224
};
@@ -259,6 +253,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
259253
uniform_paths_canary_emitted = true;
260254
}
261255

256+
let empty_for_self = |prefix: &[Segment]| {
257+
prefix.is_empty() ||
258+
prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name()
259+
};
262260
match use_tree.kind {
263261
ast::UseTreeKind::Simple(rename, ..) => {
264262
let mut ident = use_tree.ident();
@@ -271,10 +269,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
271269
if source.ident.name == keywords::SelfValue.name() {
272270
type_ns_only = true;
273271

274-
let empty_prefix = module_path.last().map_or(true, |seg| {
275-
seg.ident.name == keywords::CrateRoot.name()
276-
});
277-
if empty_prefix {
272+
if empty_for_self(&module_path) {
278273
resolve_error(
279274
self,
280275
use_tree.span,
@@ -351,27 +346,27 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
351346
subclass,
352347
use_tree.span,
353348
id,
354-
root_use_tree.span,
355-
root_id,
349+
root_span,
350+
item.id,
356351
vis,
357-
expansion,
352+
parent_scope,
358353
false, // is_uniform_paths_canary
359354
);
360355
}
361356
ast::UseTreeKind::Glob => {
362357
let subclass = GlobImport {
363-
is_prelude,
358+
is_prelude: attr::contains_name(&item.attrs, "prelude_import"),
364359
max_vis: Cell::new(ty::Visibility::Invisible),
365360
};
366361
self.add_import_directive(
367362
prefix,
368363
subclass,
369364
use_tree.span,
370365
id,
371-
root_use_tree.span,
372-
root_id,
366+
root_span,
367+
item.id,
373368
vis,
374-
expansion,
369+
parent_scope,
375370
false, // is_uniform_paths_canary
376371
);
377372
}
@@ -400,42 +395,55 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
400395

401396
for &(ref tree, id) in items {
402397
self.build_reduced_graph_for_use_tree(
403-
root_use_tree,
404-
root_id,
405-
tree,
406-
id,
407-
vis,
408-
&prefix,
409-
uniform_paths_canary_emitted,
410-
true,
411-
item,
412-
expansion,
398+
// This particular use tree
399+
tree, id, &prefix, true, uniform_paths_canary_emitted,
400+
// The whole `use` item
401+
parent_scope.clone(), item, vis, root_span,
402+
);
403+
}
404+
405+
// Empty groups `a::b::{}` are turned into synthetic `self` imports
406+
// `a::b::c::{self as _}`, so that their prefixes are correctly
407+
// resolved and checked for privacy/stability/etc.
408+
if items.is_empty() && !empty_for_self(&prefix) {
409+
let new_span = prefix[prefix.len() - 1].ident.span;
410+
let tree = ast::UseTree {
411+
prefix: ast::Path::from_ident(
412+
Ident::new(keywords::SelfValue.name(), new_span)
413+
),
414+
kind: ast::UseTreeKind::Simple(
415+
Some(Ident::new(keywords::Underscore.name().gensymed(), new_span)),
416+
ast::DUMMY_NODE_ID,
417+
ast::DUMMY_NODE_ID,
418+
),
419+
span: use_tree.span,
420+
};
421+
self.build_reduced_graph_for_use_tree(
422+
// This particular use tree
423+
&tree, id, &prefix, true, uniform_paths_canary_emitted,
424+
// The whole `use` item
425+
parent_scope.clone(), item, ty::Visibility::Invisible, root_span,
413426
);
414427
}
415428
}
416429
}
417430
}
418431

419432
/// Constructs the reduced graph for one item.
420-
fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
421-
let parent = self.current_module;
433+
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScope<'a>) {
434+
let parent = parent_scope.module;
435+
let expansion = parent_scope.expansion;
422436
let ident = item.ident;
423437
let sp = item.span;
424438
let vis = self.resolve_visibility(&item.vis);
425439

426440
match item.node {
427441
ItemKind::Use(ref use_tree) => {
428442
self.build_reduced_graph_for_use_tree(
429-
use_tree,
430-
item.id,
431-
use_tree,
432-
item.id,
433-
vis,
434-
&[],
435-
false, // uniform_paths_canary_emitted
436-
false,
437-
item,
438-
expansion,
443+
// This particular use tree
444+
use_tree, item.id, &[], false, false,
445+
// The whole `use` item
446+
parent_scope, item, vis, use_tree.span,
439447
);
440448
}
441449

@@ -448,7 +456,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
448456
self.injected_crate = Some(module);
449457
}
450458

451-
let used = self.process_legacy_macro_imports(item, module, expansion);
459+
let used = self.process_legacy_macro_imports(item, module, &parent_scope);
452460
let binding =
453461
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
454462
if ptr::eq(self.current_module, self.graph_root) {
@@ -473,7 +481,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
473481
let directive = self.arenas.alloc_import_directive(ImportDirective {
474482
root_id: item.id,
475483
id: item.id,
476-
parent,
484+
parent_scope,
477485
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
478486
subclass: ImportDirectiveSubclass::ExternCrate {
479487
source: orig_name,
@@ -483,7 +491,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
483491
span: item.span,
484492
module_path: Vec::new(),
485493
vis: Cell::new(vis),
486-
expansion,
487494
used: Cell::new(used),
488495
is_uniform_paths_canary: false,
489496
});
@@ -856,43 +863,61 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
856863
}
857864

858865
// This returns true if we should consider the underlying `extern crate` to be used.
859-
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark)
860-
-> bool {
861-
let allow_shadowing = expansion == Mark::root();
862-
let legacy_imports = self.legacy_macro_imports(&item.attrs);
863-
let used = legacy_imports != LegacyMacroImports::default();
864-
865-
// `#[macro_use]` is only allowed at the crate root.
866-
if self.current_module.parent.is_some() && used {
867-
span_err!(self.session, item.span, E0468,
868-
"an `extern crate` loading macros must be at the crate root");
866+
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>,
867+
parent_scope: &ParentScope<'a>) -> bool {
868+
let mut import_all = None;
869+
let mut single_imports = Vec::new();
870+
for attr in &item.attrs {
871+
if attr.check_name("macro_use") {
872+
if self.current_module.parent.is_some() {
873+
span_err!(self.session, item.span, E0468,
874+
"an `extern crate` loading macros must be at the crate root");
875+
}
876+
let ill_formed = |span| span_err!(self.session, span, E0466, "bad macro import");
877+
match attr.meta() {
878+
Some(meta) => match meta.node {
879+
MetaItemKind::Word => {
880+
import_all = Some(meta.span);
881+
break;
882+
}
883+
MetaItemKind::List(nested_metas) => for nested_meta in nested_metas {
884+
match nested_meta.word() {
885+
Some(word) => single_imports.push((word.name(), word.span)),
886+
None => ill_formed(nested_meta.span),
887+
}
888+
}
889+
MetaItemKind::NameValue(..) => ill_formed(meta.span),
890+
}
891+
None => ill_formed(attr.span()),
892+
}
893+
}
869894
}
870895

871-
let (graph_root, arenas) = (self.graph_root, self.arenas);
896+
let arenas = self.arenas;
872897
let macro_use_directive = |span| arenas.alloc_import_directive(ImportDirective {
873898
root_id: item.id,
874899
id: item.id,
875-
parent: graph_root,
900+
parent_scope: parent_scope.clone(),
876901
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
877902
subclass: ImportDirectiveSubclass::MacroUse,
878903
root_span: span,
879904
span,
880905
module_path: Vec::new(),
881906
vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))),
882-
expansion,
883907
used: Cell::new(false),
884908
is_uniform_paths_canary: false,
885909
});
886910

887-
if let Some(span) = legacy_imports.import_all {
911+
let allow_shadowing = parent_scope.expansion == Mark::root();
912+
if let Some(span) = import_all {
888913
let directive = macro_use_directive(span);
889914
self.potentially_unused_imports.push(directive);
890915
module.for_each_child(|ident, ns, binding| if ns == MacroNS {
891916
let imported_binding = self.import(binding, directive);
892917
self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
893918
});
894919
} else {
895-
for (name, span) in legacy_imports.imports {
920+
for (name, span) in single_imports.iter().cloned() {
896921
let ident = Ident::with_empty_ctxt(name);
897922
let result = self.resolve_ident_in_module(
898923
ModuleOrUniformRoot::Module(module),
@@ -911,7 +936,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
911936
}
912937
}
913938
}
914-
used
939+
import_all.is_some() || !single_imports.is_empty()
915940
}
916941

917942
// does this attribute list contain "macro_use"?
@@ -937,25 +962,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
937962

938963
false
939964
}
940-
941-
fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImports {
942-
let mut imports = LegacyMacroImports::default();
943-
for attr in attrs {
944-
if attr.check_name("macro_use") {
945-
match attr.meta_item_list() {
946-
Some(names) => for attr in names {
947-
if let Some(word) = attr.word() {
948-
imports.imports.push((word.name(), attr.span()));
949-
} else {
950-
span_err!(self.session, attr.span(), E0466, "bad macro import");
951-
}
952-
},
953-
None => imports.import_all = Some(attr.span),
954-
}
955-
}
956-
}
957-
imports
958-
}
959965
}
960966

961967
pub struct BuildReducedGraphVisitor<'a, 'b: 'a, 'c: 'b> {
@@ -1010,7 +1016,13 @@ impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> {
10101016

10111017
let orig_current_module = self.resolver.current_module;
10121018
let orig_current_legacy_scope = self.current_legacy_scope;
1013-
self.resolver.build_reduced_graph_for_item(item, self.expansion);
1019+
let parent_scope = ParentScope {
1020+
module: self.resolver.current_module,
1021+
expansion: self.expansion,
1022+
legacy: self.current_legacy_scope,
1023+
derives: Vec::new(),
1024+
};
1025+
self.resolver.build_reduced_graph_for_item(item, parent_scope);
10141026
visit::walk_item(self, item);
10151027
self.resolver.current_module = orig_current_module;
10161028
if !macro_use {

0 commit comments

Comments
 (0)