Skip to content

Commit 75a369c

Browse files
committed
Auto merge of #56759 - petrochenkov:prestabuni, r=nikomatsakis
Stabilize `uniform_paths` Address all the things described in #56417. Assign visibilities to `macro_rules` items - `pub` to `macro_export`-ed macros and `pub(crate)` to non-exported macros, these visibilities determine how far these macros can be reexported with `use`. Prohibit use of reexported inert attributes and "tool modules", after renaming (e.g. `use inline as imported_inline`) their respective tools and even compiler passes won't be able to recognize and properly check them. Also turn use of uniform paths in 2015 macros into an error, I'd prefer to neither remove nor stabilize them right away because I still want to make some experiments in this area (uniform path fallback was added to 2015 macros used on 2018 edition in #56053 (comment)). UPDATE: The last commit also stabilizes the feature `uniform_paths`. Closes #53130 Closes #55618 Closes #56326 Closes #56398 Closes #56417 Closes #56821 Closes #57252 Closes #57422
2 parents d6525ef + 250935d commit 75a369c

38 files changed

+229
-263
lines changed

Diff for: src/librustc/hir/def.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ impl CtorKind {
240240
}
241241

242242
impl NonMacroAttrKind {
243-
fn descr(self) -> &'static str {
243+
pub fn descr(self) -> &'static str {
244244
match self {
245245
NonMacroAttrKind::Builtin => "built-in attribute",
246246
NonMacroAttrKind::Tool => "tool attribute",

Diff for: src/librustc_resolve/lib.rs

+28-5
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan};
6767
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
6868

6969
use std::cell::{Cell, RefCell};
70-
use std::{cmp, fmt, iter, ptr};
70+
use std::{cmp, fmt, iter, mem, ptr};
7171
use std::collections::BTreeSet;
7272
use std::mem::replace;
7373
use rustc_data_structures::ptr_key::PtrKey;
@@ -2375,11 +2375,27 @@ impl<'a> Resolver<'a> {
23752375
ast::UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..],
23762376
_ => &[TypeNS],
23772377
};
2378+
let report_error = |this: &Self, ns| {
2379+
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
2380+
this.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
2381+
};
2382+
23782383
for &ns in nss {
2379-
if let Some(LexicalScopeBinding::Def(..)) =
2380-
self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
2381-
let what = if ns == TypeNS { "type parameters" } else { "local variables" };
2382-
self.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
2384+
match self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
2385+
Some(LexicalScopeBinding::Def(..)) => {
2386+
report_error(self, ns);
2387+
}
2388+
Some(LexicalScopeBinding::Item(binding)) => {
2389+
let orig_blacklisted_binding =
2390+
mem::replace(&mut self.blacklisted_binding, Some(binding));
2391+
if let Some(LexicalScopeBinding::Def(..)) =
2392+
self.resolve_ident_in_lexical_scope(ident, ns, None,
2393+
use_tree.prefix.span) {
2394+
report_error(self, ns);
2395+
}
2396+
self.blacklisted_binding = orig_blacklisted_binding;
2397+
}
2398+
None => {}
23832399
}
23842400
}
23852401
} else if let ast::UseTreeKind::Nested(use_trees) = &use_tree.kind {
@@ -3874,6 +3890,13 @@ impl<'a> Resolver<'a> {
38743890
module = Some(ModuleOrUniformRoot::Module(next_module));
38753891
record_segment_def(self, def);
38763892
} else if def == Def::ToolMod && i + 1 != path.len() {
3893+
if binding.is_import() {
3894+
self.session.struct_span_err(
3895+
ident.span, "cannot use a tool module through an import"
3896+
).span_note(
3897+
binding.span, "the tool module imported here"
3898+
).emit();
3899+
}
38773900
let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
38783901
return PathResult::NonModule(PathResolution::new(def));
38793902
} else if def == Def::Err {

Diff for: src/librustc_resolve/macros.rs

+35-18
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ impl<'a> Resolver<'a> {
376376
.push((path, path_span, kind, parent_scope.clone(), def.ok()));
377377
}
378378

379+
self.prohibit_imported_non_macro_attrs(None, def.ok(), path_span);
379380
def
380381
} else {
381382
let binding = self.early_resolve_ident_in_lexical_scope(
@@ -390,7 +391,9 @@ impl<'a> Resolver<'a> {
390391
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
391392
}
392393

393-
binding.map(|binding| binding.def())
394+
let def = binding.map(|binding| binding.def());
395+
self.prohibit_imported_non_macro_attrs(binding.ok(), def.ok(), path_span);
396+
def
394397
}
395398
}
396399

@@ -828,27 +831,23 @@ impl<'a> Resolver<'a> {
828831
// but its `Def` should coincide with a crate passed with `--extern`
829832
// (otherwise there would be ambiguity) and we can skip feature error in this case.
830833
'ok: {
831-
if !is_import || self.session.features_untracked().uniform_paths {
834+
if !is_import || !rust_2015 {
832835
break 'ok;
833836
}
834837
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
835838
break 'ok;
836839
}
837-
if rust_2015 {
838-
let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
839-
let root_module = self.resolve_crate_root(root_ident);
840-
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
841-
orig_ident, ns, None, false, path_span)
842-
.is_ok() {
843-
break 'ok;
844-
}
840+
let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
841+
let root_module = self.resolve_crate_root(root_ident);
842+
if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
843+
orig_ident, ns, None, false, path_span)
844+
.is_ok() {
845+
break 'ok;
845846
}
846847

847-
let msg = "imports can only refer to extern crate names \
848-
passed with `--extern` on stable channel";
849-
let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
850-
ident.span, GateIssue::Language, msg);
851-
848+
let msg = "imports can only refer to extern crate names passed with \
849+
`--extern` in macros originating from 2015 edition";
850+
let mut err = self.session.struct_span_err(ident.span, msg);
852851
let what = self.binding_description(binding, ident,
853852
flags.contains(Flags::MISC_FROM_PRELUDE));
854853
let note_msg = format!("this import refers to {what}", what = what);
@@ -977,6 +976,20 @@ impl<'a> Resolver<'a> {
977976
}
978977
}
979978

979+
fn prohibit_imported_non_macro_attrs(&self, binding: Option<&'a NameBinding<'a>>,
980+
def: Option<Def>, span: Span) {
981+
if let Some(Def::NonMacroAttr(kind)) = def {
982+
if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) {
983+
let msg = format!("cannot use a {} through an import", kind.descr());
984+
let mut err = self.session.struct_span_err(span, &msg);
985+
if let Some(binding) = binding {
986+
err.span_note(binding.span, &format!("the {} imported here", kind.descr()));
987+
}
988+
err.emit();
989+
}
990+
}
991+
}
992+
980993
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
981994
err: &mut DiagnosticBuilder<'a>, span: Span) {
982995
// First check if this is a locally-defined bang macro.
@@ -1073,17 +1086,21 @@ impl<'a> Resolver<'a> {
10731086
let ident = ident.modern();
10741087
self.macro_names.insert(ident);
10751088
let def = Def::Macro(def_id, MacroKind::Bang);
1076-
let vis = ty::Visibility::Invisible; // Doesn't matter for legacy bindings
1089+
let is_macro_export = attr::contains_name(&item.attrs, "macro_export");
1090+
let vis = if is_macro_export {
1091+
ty::Visibility::Public
1092+
} else {
1093+
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
1094+
};
10771095
let binding = (def, vis, item.span, expansion).to_name_binding(self.arenas);
10781096
self.set_binding_parent_module(binding, self.current_module);
10791097
let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
10801098
parent_legacy_scope: *current_legacy_scope, binding, ident
10811099
});
10821100
*current_legacy_scope = LegacyScope::Binding(legacy_binding);
10831101
self.all_macros.insert(ident.name, def);
1084-
if attr::contains_name(&item.attrs, "macro_export") {
1102+
if is_macro_export {
10851103
let module = self.graph_root;
1086-
let vis = ty::Visibility::Public;
10871104
self.define(module, ident, MacroNS,
10881105
(def, vis, item.span, expansion, IsMacroExport));
10891106
} else {

Diff for: src/librustc_resolve/resolve_imports.rs

+5
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ impl<'a> Resolver<'a> {
223223
}
224224

225225
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
226+
if let Some(blacklisted_binding) = this.blacklisted_binding {
227+
if ptr::eq(binding, blacklisted_binding) {
228+
return Err((Determined, Weak::No));
229+
}
230+
}
226231
// `extern crate` are always usable for backwards compatibility, see issue #37020,
227232
// remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
228233
let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();

Diff for: src/libsyntax/feature_gate.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,6 @@ declare_features! (
434434
// support for arbitrary delimited token streams in non-macro attributes
435435
(active, unrestricted_attribute_tokens, "1.30.0", Some(55208), None),
436436

437-
// Allows `use x::y;` to resolve through `self::x`, not just `::x`.
438-
(active, uniform_paths, "1.30.0", Some(53130), None),
439-
440437
// Allows unsized rvalues at arguments and parameters.
441438
(active, unsized_locals, "1.30.0", Some(48055), None),
442439

@@ -687,6 +684,8 @@ declare_features! (
687684
(accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
688685
// Top level or-patterns (`p | q`) in `if let` and `while let`.
689686
(accepted, if_while_or_patterns, "1.33.0", Some(48215), None),
687+
// Allows `use x::y;` to search `x` in the current scope.
688+
(accepted, uniform_paths, "1.32.0", Some(53130), None),
690689
);
691690

692691
// If you change this, please modify `src/doc/unstable-book` as well. You must

Diff for: src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// edition:2018
22

3-
#![feature(uniform_paths)]
4-
53
mod m { pub fn f() {} }
64
mod n { pub fn g() {} }
75

Diff for: src/test/run-pass/uniform-paths/basic-nested.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// run-pass
2-
#![allow(unused_imports)]
3-
#![allow(non_camel_case_types)]
1+
// This test is similar to `basic.rs`, but nested in modules.
42

3+
// run-pass
54
// edition:2018
65

7-
#![feature(decl_macro, uniform_paths)]
6+
#![feature(decl_macro)]
87

9-
// This test is similar to `basic.rs`, but nested in modules.
8+
#![allow(unused_imports)]
9+
#![allow(non_camel_case_types)]
1010

1111
mod foo {
1212
// Test that ambiguity errors are not emitted between `self::test` and

Diff for: src/test/run-pass/uniform-paths/basic.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
// run-pass
2-
#![allow(unused_imports)]
3-
#![allow(non_camel_case_types)]
4-
52
// edition:2018
63

7-
#![feature(uniform_paths)]
4+
#![allow(unused_imports)]
5+
#![allow(non_camel_case_types)]
86

97
// Test that ambiguity errors are not emitted between `self::test` and
108
// `::test`, assuming the latter (crate) is not in `extern_prelude`.

Diff for: src/test/run-pass/uniform-paths/macros-nested.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
// run-pass
2-
#![allow(non_camel_case_types)]
1+
// This test is similar to `macros.rs`, but nested in modules.
32

3+
// run-pass
44
// edition:2018
55

6-
#![feature(uniform_paths)]
7-
8-
// This test is similar to `macros.rs`, but nested in modules.
6+
#![allow(non_camel_case_types)]
97

108
mod foo {
119
// Test that ambiguity errors are not emitted between `self::test` and

Diff for: src/test/run-pass/uniform-paths/macros.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
// run-pass
2-
#![allow(non_camel_case_types)]
1+
// This test is similar to `basic.rs`, but with macros defining local items.
32

3+
// run-pass
44
// edition:2018
55

6-
#![feature(uniform_paths)]
7-
8-
// This test is similar to `basic.rs`, but with macros defining local items.
6+
#![allow(non_camel_case_types)]
97

108
// Test that ambiguity errors are not emitted between `self::test` and
119
// `::test`, assuming the latter (crate) is not in `extern_prelude`.

Diff for: src/test/run-pass/uniform-paths/same-crate.rs

-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// run-pass
2-
32
// edition:2018
43

5-
#![feature(uniform_paths)]
6-
74
pub const A: usize = 0;
85

96
pub mod foo {

Diff for: src/test/ui/editions/edition-imports-2015.rs

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
// aux-build:edition-imports-2018.rs
44
// aux-build:absolute.rs
55

6-
#![feature(uniform_paths)]
7-
86
#[macro_use]
97
extern crate edition_imports_2018;
108

Diff for: src/test/ui/editions/edition-imports-2015.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: cannot glob-import all possible crates
2-
--> $DIR/edition-imports-2015.rs:25:5
2+
--> $DIR/edition-imports-2015.rs:23:5
33
|
44
LL | gen_glob!(); //~ ERROR cannot glob-import all possible crates
55
| ^^^^^^^^^^^^

Diff for: src/test/ui/editions/edition-imports-virtual-2015-gated.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
1+
error: imports can only refer to extern crate names passed with `--extern` in macros originating from 2015 edition
22
--> <::edition_imports_2015::gen_gated macros>:1:50
33
|
44
LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } }
@@ -9,7 +9,6 @@ LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } }
99
LL | gen_gated!();
1010
| ------------- not an extern crate passed with `--extern`
1111
|
12-
= help: add #![feature(uniform_paths)] to the crate attributes to enable
1312
note: this import refers to the enum defined here
1413
--> $DIR/edition-imports-virtual-2015-gated.rs:9:5
1514
|
@@ -19,4 +18,3 @@ LL | gen_gated!();
1918

2019
error: aborting due to previous error
2120

22-
For more information about this error, try `rustc --explain E0658`.

Diff for: src/test/ui/feature-gates/feature-gate-uniform-paths.rs

-19
This file was deleted.

Diff for: src/test/ui/feature-gates/feature-gate-uniform-paths.stderr

-50
This file was deleted.

Diff for: src/test/ui/imports/issue-56125.rs

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// compile-flags:--extern issue_56125
33
// aux-build:issue-56125.rs
44

5-
#![feature(uniform_paths)]
6-
75
mod m1 {
86
use issue_56125::last_segment::*;
97
//~^ ERROR `issue_56125` is ambiguous

0 commit comments

Comments
 (0)