Skip to content

Commit d08a0a8

Browse files
committed
Auto merge of #55884 - petrochenkov:uni, r=eddyb
[beta] resolve: Implement uniform paths 2.0 With this PR paths in imports on 2018 edition are resolved as relative in the scope in which they are written, similarly to any other paths. The previous implementation worked differently - it tried to resolve the import in the current module (`self::import`) and in the "crate universe" (`::import`), and then merge these two resolutions if possible. The difference is that the new scheme can refer to strictly larger set of names in scope - names from unnamed blocks, names from all kinds of preludes, including macros imported with `#[macro_use] extern crate`, built-in types/macros, macros introduced with `macro_rules`. This means strictly more potential ambiguities and therefore ambiguity errors, since we keep the rule that any two different candidate names in scope conflict with each other during import resolution. So this is a breaking change for 2018 edition, but it should be relatively minor. All paths that don't start with an extern crate are also gated with the `uniform_paths` feature, paths that refer to extern crates are not gated (so we effectively get something like "future-proofed anchored paths" on stable). Another difference is treatment of paths in visibilities (`pub(in path)`). Few people remember about paths in visibilities, so before this PR they still used the old 2015 rules even on 2018 edition. Namely, paths in visibilities were crate-relative, analogous to 2015 edition imports. This PR resolves paths in visibilities as uniform as well, or rather future proofs them in this direction. Paths in visibilities are restricted to parent modules, so relative paths almost never make sense there, and `pub(in a)` needs to be rewritten as `pub(in crate::a)` in the uniform scheme, de-facto cementing the discouraged status of non-`pub(crate)` and non-`pub(super)` fine-grained visibilities. This is clearly a breaking change for 2018 edition as well, but also a minor one. The in-scope resolution strategy for import paths mirrors what is currently done for macro paths on stable (on both editions), so it will continue working even if the "ambiguity always means error" restriction is relaxed in the future. This PR also significantly improves diagnostics for all kinds of resolution ambiguities, from the newly introduced import ones to pretty old "glob vs glob" conflicts. (That's probably what I've spent most of the time on.) Why beta: - This is a breaking change on 2018 edition. - This is a large PR, it's less risky to forward-port it to nightly, than back-port to beta. cc #55618 cc #53130 cc rust-lang/rfcs#1289 Closes #18084 Closes #54525 Fixes #54390 Fixes #55668 r? @ghost
2 parents d4de9b1 + b366415 commit d08a0a8

File tree

187 files changed

+2224
-1516
lines changed

Some content is hidden

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

187 files changed

+2224
-1516
lines changed

src/doc/unstable-book/src/language-features/extern-in-paths.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ introducing `extern crate` items, using keyword `extern`.
1111

1212
For example, `extern::my_crat::a::b` will resolve to path `a::b` in crate `my_crate`.
1313

14-
`feature(extern_absolute_paths)` mode provides the same effect by resolving absolute paths like
15-
`::my_crate::a::b` to paths from extern crates by default.
14+
Absolute paths on 2018 edition (e.g. `::my_crate::a::b`) provide the same effect
15+
and resolve to extern crates (built-in or passed with `--extern`).
1616

1717
```rust,ignore
1818
#![feature(extern_in_paths)]

src/librustc/hir/def.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,6 @@ impl PathResolution {
128128
pub fn unresolved_segments(&self) -> usize {
129129
self.unresolved_segments
130130
}
131-
132-
pub fn kind_name(&self) -> &'static str {
133-
if self.unresolved_segments != 0 {
134-
"associated item"
135-
} else {
136-
self.base_def.kind_name()
137-
}
138-
}
139131
}
140132

141133
/// Different kinds of symbols don't influence each other.
@@ -269,27 +261,33 @@ impl NonMacroAttrKind {
269261

270262
impl Def {
271263
pub fn def_id(&self) -> DefId {
264+
self.opt_def_id().unwrap_or_else(|| {
265+
bug!("attempted .def_id() on invalid def: {:?}", self)
266+
})
267+
}
268+
269+
pub fn opt_def_id(&self) -> Option<DefId> {
272270
match *self {
273271
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
274272
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
275273
Def::TyAlias(id) | Def::TraitAlias(id) |
276274
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
277275
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
278276
Def::AssociatedConst(id) | Def::Macro(id, ..) |
279-
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) |
280-
Def::SelfCtor(id) => {
281-
id
277+
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
278+
Some(id)
282279
}
283280

284281
Def::Local(..) |
285282
Def::Upvar(..) |
286283
Def::Label(..) |
287284
Def::PrimTy(..) |
288285
Def::SelfTy(..) |
286+
Def::SelfCtor(..) |
289287
Def::ToolMod |
290288
Def::NonMacroAttr(..) |
291289
Def::Err => {
292-
bug!("attempted .def_id() on invalid def: {:?}", self)
290+
None
293291
}
294292
}
295293
}
@@ -333,4 +331,13 @@ impl Def {
333331
Def::Err => "unresolved item",
334332
}
335333
}
334+
335+
pub fn article(&self) -> &'static str {
336+
match *self {
337+
Def::AssociatedTy(..) | Def::AssociatedConst(..) | Def::AssociatedExistential(..) |
338+
Def::Enum(..) | Def::Existential(..) | Def::Err => "an",
339+
Def::Macro(.., macro_kind) => macro_kind.article(),
340+
_ => "a",
341+
}
342+
}
336343
}

src/librustc/hir/def_id.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ pub struct DefId {
225225

226226
impl fmt::Debug for DefId {
227227
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228-
write!(f, "DefId({:?}/{}:{}",
229-
self.krate.index(),
228+
write!(f, "DefId({}/{}:{}",
229+
self.krate,
230230
self.index.address_space().index(),
231231
self.index.as_array_index())?;
232232

src/librustc/middle/dead.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
8080
self.check_def_id(def.def_id());
8181
}
8282
_ if self.in_pat => (),
83-
Def::PrimTy(..) | Def::SelfTy(..) |
83+
Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) |
8484
Def::Local(..) | Def::Upvar(..) => {}
8585
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
8686
if let Some(enum_id) = self.tcx.parent_def_id(variant_id) {

src/librustc/middle/stability.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -781,10 +781,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
781781

782782
fn visit_path(&mut self, path: &'tcx hir::Path, id: hir::HirId) {
783783
let id = self.tcx.hir.hir_to_node_id(id);
784-
match path.def {
785-
Def::Local(..) | Def::Upvar(..) | Def::SelfCtor(..) |
786-
Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {}
787-
_ => self.tcx.check_stability(path.def.def_id(), Some(id), path.span)
784+
if let Some(def_id) = path.def.opt_def_id() {
785+
self.tcx.check_stability(def_id, Some(id), path.span)
788786
}
789787
intravisit::walk_path(self, path)
790788
}

src/librustc_mir/hair/pattern/check_match.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
298298
let label_msg = match pat.node {
299299
PatKind::Path(hir::QPath::Resolved(None, ref path))
300300
if path.segments.len() == 1 && path.segments[0].args.is_none() => {
301-
format!("interpreted as a {} pattern, not new variable", path.def.kind_name())
301+
format!("interpreted as {} {} pattern, not new variable",
302+
path.def.article(), path.def.kind_name())
302303
}
303304
_ => format!("pattern `{}` not covered", pattern_string),
304305
};

src/librustc_privacy/lib.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -361,9 +361,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
361361
let def_id = self.tcx.hir.local_def_id(id);
362362
if let Some(exports) = self.tcx.module_exports(def_id) {
363363
for export in exports.iter() {
364-
if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
365-
if export.vis == ty::Visibility::Public {
366-
self.update(node_id, Some(AccessLevel::Exported));
364+
if export.vis == ty::Visibility::Public {
365+
if let Some(def_id) = export.def.opt_def_id() {
366+
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
367+
self.update(node_id, Some(AccessLevel::Exported));
368+
}
367369
}
368370
}
369371
}

0 commit comments

Comments
 (0)