From 01501ebc741aaa42b661c42ccba028c4cb1205ea Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 23 Nov 2018 00:50:15 +0300 Subject: [PATCH 1/7] Remove duplicate tests for uniform paths --- .../ambiguity-macros-nested.rs | 29 -------------- .../ambiguity-macros-nested.stderr | 23 ----------- .../ambiguity-macros.rs | 27 ------------- .../ambiguity-macros.stderr | 23 ----------- .../ambiguity-nested.rs | 24 ------------ .../ambiguity-nested.stderr | 20 ---------- .../uniform-paths-forward-compat/ambiguity.rs | 20 ---------- .../ambiguity.stderr | 20 ---------- .../block-scoped-shadow.rs | 21 ---------- .../block-scoped-shadow.stderr | 39 ------------------- .../issue-54253.rs | 27 ------------- .../issue-54253.stderr | 9 ----- .../uniform-paths-forward-compat/redundant.rs | 30 -------------- 13 files changed, 312 deletions(-) delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr delete mode 100644 src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs deleted file mode 100644 index 4819711115c27..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// edition:2018 - -// This test is similar to `ambiguity-macros.rs`, but nested in a module. - -mod foo { - pub use std::io; - //~^ ERROR `std` is ambiguous - - macro_rules! m { - () => { - mod std { - pub struct io; - } - } - } - m!(); -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr deleted file mode 100644 index 204e0a7e1411e..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros-nested.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity-macros-nested.rs:16:13 - | -LL | pub use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity-macros-nested.rs:21:13 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_____________^ -... -LL | m!(); - | ----- in this macro invocation - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs deleted file mode 100644 index 148320de556d3..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// edition:2018 - -// This test is similar to `ambiguity.rs`, but with macros defining local items. - -use std::io; -//~^ ERROR `std` is ambiguous - -macro_rules! m { - () => { - mod std { - pub struct io; - } - } -} -m!(); - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr deleted file mode 100644 index ac8d3b9d0cbe4..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-macros.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity-macros.rs:15:5 - | -LL | use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity-macros.rs:20:9 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_________^ -... -LL | m!(); - | ----- in this macro invocation - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs deleted file mode 100644 index 2791d4580daf1..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// edition:2018 - -// This test is similar to `ambiguity.rs`, but nested in a module. - -mod foo { - pub use std::io; - //~^ ERROR `std` is ambiguous - - mod std { - pub struct io; - } -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr deleted file mode 100644 index 7bcfc563d39fc..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity-nested.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity-nested.rs:16:13 - | -LL | pub use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity-nested.rs:19:5 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_____^ - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs deleted file mode 100644 index 2bfbb6b287153..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// edition:2018 - -use std::io; -//~^ ERROR `std` is ambiguous - -mod std { - pub struct io; -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr deleted file mode 100644 index beeb74654e5b5..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/ambiguity.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/ambiguity.rs:13:5 - | -LL | use std::io; - | ^^^ ambiguous name - | - = note: `std` could refer to a built-in extern crate - = help: use `::std` to refer to this extern crate unambiguously -note: `std` could also refer to the module defined here - --> $DIR/ambiguity.rs:16:1 - | -LL | / mod std { -LL | | pub struct io; -LL | | } - | |_^ - = help: use `self::std` to refer to this module unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs deleted file mode 100644 index 2853b4b3a5b3f..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// edition:2018 - -struct std; - -fn main() { - fn std() {} - enum std {} - use std as foo; - //~^ ERROR `std` is ambiguous - //~| ERROR `std` is ambiguous -} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr deleted file mode 100644 index 5d539e2d59f15..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/block-scoped-shadow.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/block-scoped-shadow.rs:18:9 - | -LL | use std as foo; - | ^^^ ambiguous name - | -note: `std` could refer to the enum defined here - --> $DIR/block-scoped-shadow.rs:17:5 - | -LL | enum std {} - | ^^^^^^^^^^^ -note: `std` could also refer to the struct defined here - --> $DIR/block-scoped-shadow.rs:13:1 - | -LL | struct std; - | ^^^^^^^^^^^ - = help: use `self::std` to refer to this struct unambiguously - -error[E0659]: `std` is ambiguous (name vs any other name during import resolution) - --> $DIR/block-scoped-shadow.rs:18:9 - | -LL | use std as foo; - | ^^^ ambiguous name - | -note: `std` could refer to the function defined here - --> $DIR/block-scoped-shadow.rs:16:5 - | -LL | fn std() {} - | ^^^^^^^^^^^ -note: `std` could also refer to the unit struct defined here - --> $DIR/block-scoped-shadow.rs:13:1 - | -LL | struct std; - | ^^^^^^^^^^^ - = help: use `self::std` to refer to this unit struct unambiguously - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs deleted file mode 100644 index ef2a1e3c70c6f..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// edition:2018 - -// Dummy import that previously introduced uniform path canaries. -use std; - -// fn version() -> &'static str {""} - -mod foo { - // Error wasn't reported, despite `version` being commented out above. - use crate::version; //~ ERROR unresolved import `crate::version` - - fn bar() { - version(); - } -} - -fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr b/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr deleted file mode 100644 index 6dcc451c60a61..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/issue-54253.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0432]: unresolved import `crate::version` - --> $DIR/issue-54253.rs:20:9 - | -LL | use crate::version; //~ ERROR unresolved import `crate::version` - | ^^^^^^^^^^^^^^ no `version` in the root - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs b/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs deleted file mode 100644 index 05048cfd45105..0000000000000 --- a/src/test/ui/rust-2018/uniform-paths-forward-compat/redundant.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// run-pass -// edition:2018 - -use std; -use std::io; - -mod foo { - pub use std as my_std; -} - -mod bar { - pub use std::{self}; -} - -fn main() { - io::stdout(); - self::std::io::stdout(); - foo::my_std::io::stdout(); - bar::std::io::stdout(); -} From 585d2c44b337c3dc4b98f02bccf42dba04965f83 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 18 Nov 2018 03:25:59 +0300 Subject: [PATCH 2/7] resolve: Implement edition hygiene for imports and absolute paths Use per-span hygiene in a few other places in resolve Prefer `rust_2015`/`rust_2018` helpers to comparing editions --- src/librustc/ty/context.rs | 11 +-- src/librustc/ty/item_path.rs | 3 +- src/librustc_resolve/build_reduced_graph.rs | 21 +++--- src/librustc_resolve/error_reporting.rs | 5 +- src/librustc_resolve/lib.rs | 67 +++++++++---------- src/librustc_resolve/macros.rs | 5 +- src/libsyntax/parse/parser.rs | 29 ++++---- src/libsyntax_pos/lib.rs | 10 +++ src/libsyntax_pos/symbol.rs | 3 +- .../auxiliary/edition-imports-2015.rs | 19 ++++++ .../proc-macro/edition-imports-2018.rs | 24 +++++++ src/test/ui/editions/auxiliary/absolute.rs | 1 + .../auxiliary/edition-imports-2015.rs | 17 +++++ .../auxiliary/edition-imports-2018.rs | 17 +++++ src/test/ui/editions/edition-imports-2015.rs | 28 ++++++++ .../ui/editions/edition-imports-2015.stderr | 10 +++ src/test/ui/editions/edition-imports-2018.rs | 33 +++++++++ 17 files changed, 226 insertions(+), 77 deletions(-) create mode 100644 src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs create mode 100644 src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs create mode 100644 src/test/ui/editions/auxiliary/absolute.rs create mode 100644 src/test/ui/editions/auxiliary/edition-imports-2015.rs create mode 100644 src/test/ui/editions/auxiliary/edition-imports-2018.rs create mode 100644 src/test/ui/editions/edition-imports-2015.rs create mode 100644 src/test/ui/editions/edition-imports-2015.stderr create mode 100644 src/test/ui/editions/edition-imports-2018.rs diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6485acf4ed2cc..f3fe53444bfe9 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1484,15 +1484,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// done with either: `-Ztwo-phase-borrows`, `#![feature(nll)]`, /// or by opting into an edition after 2015. pub fn two_phase_borrows(self) -> bool { - if self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows { - return true; - } - - match self.sess.edition() { - Edition::Edition2015 => false, - Edition::Edition2018 => true, - _ => true, - } + self.sess.rust_2018() || self.features().nll || + self.sess.opts.debugging_opts.two_phase_borrows } /// What mode(s) of borrowck should we run? AST? MIR? both? diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 7153c729d1542..6d92890fc08ad 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -14,7 +14,6 @@ use ty::{self, DefIdTree, Ty, TyCtxt}; use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; use syntax::symbol::{keywords, LocalInternedString, Symbol}; -use syntax_pos::edition::Edition; use std::cell::Cell; use std::fmt::Debug; @@ -140,7 +139,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { debug!("push_krate_path: name={:?}", name); buffer.push(&name); } - } else if self.sess.edition() == Edition::Edition2018 && !pushed_prelude_crate { + } else if self.sess.rust_2018() && !pushed_prelude_crate { SHOULD_PREFIX_WITH_CRATE.with(|flag| { // We only add the `crate::` keyword where appropriate. In particular, // when we've not previously pushed a prelude crate to this path. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index b3a70c79df144..c85ae2e633f1a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -133,16 +133,17 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // 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, |seg| !seg.ident.is_path_segment_keyword()) - { - Some(Segment::from_ident(Ident::new( - keywords::CrateRoot.name(), - use_tree.prefix.span.shrink_to_lo(), - ))) - } else { - None - }; + let crate_root = match prefix_iter.peek() { + Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => { + Some(seg.ident.span.ctxt()) + } + None if is_glob && use_tree.span.rust_2015() => { + Some(use_tree.span.ctxt()) + } + _ => None, + }.map(|ctxt| Segment::from_ident(Ident::new( + keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt) + ))); let prefix = crate_root.into_iter().chain(prefix_iter).collect::>(); debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix); diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 263d23d133e1c..e2a6303f57944 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -33,7 +33,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { (Some(fst), Some(snd)) if fst.ident.name == keywords::CrateRoot.name() && !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018 - (Some(fst), _) if self.session.rust_2018() && !fst.ident.is_path_segment_keyword() => { + (Some(fst), _) if fst.ident.span.rust_2018() && + !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. path.insert(0, Segment::from_ident(keywords::Invalid.ident())); } @@ -141,7 +142,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { mut path: Vec, parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Option)> { - if !self.session.rust_2018() { + if path[1].ident.span.rust_2015() { return None; } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 26fab593e4cdd..745a07f282960 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2359,14 +2359,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn future_proof_import(&mut self, use_tree: &ast::UseTree) { - if !self.session.rust_2018() { - return; - } - let segments = &use_tree.prefix.segments; if !segments.is_empty() { let ident = segments[0].ident; - if ident.is_path_segment_keyword() { + if ident.is_path_segment_keyword() || ident.span.rust_2015() { return; } @@ -3186,10 +3182,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Try to lookup the name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; - let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); + let candidates = this.lookup_import_candidates(ident, ns, is_expected); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = - this.lookup_import_candidates(ident.name, ns, is_enum_variant); + this.lookup_import_candidates(ident, ns, is_enum_variant); let mut enum_candidates = enum_candidates.iter() .map(|suggestion| import_candidate_to_paths(&suggestion)).collect::>(); enum_candidates.sort(); @@ -3774,7 +3770,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { continue; } if name == keywords::Extern.name() || - name == keywords::CrateRoot.name() && self.session.rust_2018() { + name == keywords::CrateRoot.name() && ident.span.rust_2018() { module = Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude)); continue; @@ -3877,7 +3873,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let msg = if module_def == self.graph_root.def() { let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let mut candidates = - self.lookup_import_candidates(name, TypeNS, is_mod); + self.lookup_import_candidates(ident, TypeNS, is_mod); candidates.sort_by_cached_key(|c| { (c.path.segments.len(), c.path.to_string()) }); @@ -3913,11 +3909,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { path_span: Span, second_binding: Option<&NameBinding>, ) { - // In the 2018 edition this lint is a hard error, so nothing to do - if self.session.rust_2018() { - return - } - let (diag_id, diag_span) = match crate_lint { CrateLint::No => return, CrateLint::SimplePath(id) => (id, path_span), @@ -3926,8 +3917,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; let first_name = match path.get(0) { - Some(ident) => ident.ident.name, - None => return, + // In the 2018 edition this lint is a hard error, so nothing to do + Some(seg) if seg.ident.span.rust_2015() => seg.ident.name, + _ => return, }; // We're only interested in `use` paths which should start with @@ -4509,7 +4501,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn lookup_import_candidates_from_module(&mut self, - lookup_name: Name, + lookup_ident: Ident, namespace: Namespace, start_module: &'a ModuleData<'a>, crate_name: Ident, @@ -4536,11 +4528,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { if !name_binding.is_importable() { return; } // collect results based on the filter function - if ident.name == lookup_name && ns == namespace { + if ident.name == lookup_ident.name && ns == namespace { if filter_fn(name_binding.def()) { // create the path let mut segms = path_segments.clone(); - if self.session.rust_2018() { + if lookup_ident.span.rust_2018() { // crate-local absolute paths start with `crate::` in edition 2018 // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660) segms.insert( @@ -4574,7 +4566,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let is_extern_crate_that_also_appears_in_prelude = name_binding.is_extern_crate() && - self.session.rust_2018(); + lookup_ident.span.rust_2018(); let is_visible_to_user = !in_module_is_extern || name_binding.vis == ty::Visibility::Public; @@ -4601,16 +4593,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { /// NOTE: The method does not look into imports, but this is not a problem, /// since we report the definitions (thus, the de-aliased imports). fn lookup_import_candidates(&mut self, - lookup_name: Name, + lookup_ident: Ident, namespace: Namespace, filter_fn: FilterFn) -> Vec where FilterFn: Fn(Def) -> bool { let mut suggestions = self.lookup_import_candidates_from_module( - lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn); + lookup_ident, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn); - if self.session.rust_2018() { + if lookup_ident.span.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); for (ident, _) in extern_prelude_names.into_iter() { if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name, @@ -4622,7 +4614,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.populate_module_if_necessary(&crate_root); suggestions.extend(self.lookup_import_candidates_from_module( - lookup_name, namespace, crate_root, ident, &filter_fn)); + lookup_ident, namespace, crate_root, ident, &filter_fn)); } } } @@ -4714,19 +4706,26 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ast::VisibilityKind::Restricted { ref path, id, .. } => { // For visibilities we are not ready to provide correct implementation of "uniform // paths" right now, so on 2018 edition we only allow module-relative paths for now. - let first_ident = path.segments[0].ident; - if self.session.rust_2018() && !first_ident.is_path_segment_keyword() { + // On 2015 edition visibilities are resolved as crate-relative by default, + // so we are prepending a root segment if necessary. + let ident = path.segments.get(0).expect("empty path in visibility").ident; + let crate_root = if ident.is_path_segment_keyword() { + None + } else if ident.span.rust_2018() { let msg = "relative paths are not supported in visibilities on 2018 edition"; - self.session.struct_span_err(first_ident.span, msg) + self.session.struct_span_err(ident.span, msg) .span_suggestion(path.span, "try", format!("crate::{}", path)) .emit(); return ty::Visibility::Public; - } - // On 2015 visibilities are resolved as crate-relative by default, - // add starting root segment if necessary. - let segments = path.make_root().iter().chain(path.segments.iter()) - .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) }) - .collect::>(); + } else { + let ctxt = ident.span.ctxt(); + Some(Segment::from_ident(Ident::new( + keywords::CrateRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt) + ))) + }; + + let segments = crate_root.into_iter() + .chain(path.segments.iter().map(|seg| seg.into())).collect::>(); let def = self.smart_resolve_path_fragment( id, None, @@ -4839,7 +4838,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { help_msgs.push(format!("consider adding an explicit import of \ `{ident}` to disambiguate", ident = ident)) } - if b.is_extern_crate() && self.session.rust_2018() { + if b.is_extern_crate() && ident.span.rust_2018() { help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously", ident = ident, thing = b.descr())) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index df73befa324f0..a26580144a97c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -605,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 + let rust_2015 = ident.span.rust_2015(); ident = ident.modern(); // Make sure `self`, `super` etc produce an error when passed to here. @@ -696,7 +697,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } WhereToResolve::MacroUsePrelude => { - if use_prelude || self.session.rust_2015() { + if use_prelude || rust_2015 { match self.macro_use_prelude.get(&ident.name).cloned() { Some(binding) => Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)), @@ -725,7 +726,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } WhereToResolve::LegacyPluginHelpers => { - if (use_prelude || self.session.rust_2015()) && + if (use_prelude || rust_2015) && self.session.plugin_attributes.borrow().iter() .any(|(name, _)| ident.name == &**name) { let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index be448f960df3f..184f4bdc25606 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -43,7 +43,7 @@ use ast::{BinOpKind, UnOp}; use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; use source_map::{self, SourceMap, Spanned, respan}; -use syntax_pos::{self, Span, MultiSpan, BytePos, FileName, edition::Edition}; +use syntax_pos::{self, Span, MultiSpan, BytePos, FileName}; use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId}; use parse::{self, SeqSep, classify, token}; use parse::lexer::TokenAndSpan; @@ -1403,11 +1403,7 @@ impl<'a> Parser<'a> { // definition... // We don't allow argument names to be left off in edition 2018. - if p.span.edition() >= Edition::Edition2018 { - p.parse_arg_general(true) - } else { - p.parse_arg_general(false) - } + p.parse_arg_general(p.span.rust_2018()) })?; generics.where_clause = self.parse_where_clause()?; @@ -1600,9 +1596,9 @@ impl<'a> Parser<'a> { impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) } else if self.check_keyword(keywords::Dyn) && - (self.span.edition() == Edition::Edition2018 || + (self.span.rust_2018() || self.look_ahead(1, |t| t.can_begin_bound() && - !can_continue_type_after_non_fn_ident(t))) { + !can_continue_type_after_non_fn_ident(t))) { self.bump(); // `dyn` // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; @@ -2043,8 +2039,9 @@ impl<'a> Parser<'a> { let lo = self.meta_var_span.unwrap_or(self.span); let mut segments = Vec::new(); + let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { - segments.push(PathSegment::crate_root(lo.shrink_to_lo())); + segments.push(PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); } self.parse_path_segments(&mut segments, style, enable_warning)?; @@ -2382,8 +2379,7 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } - if self.span.edition() >= Edition::Edition2018 && - self.check_keyword(keywords::Async) + if self.span.rust_2018() && self.check_keyword(keywords::Async) { if self.is_async_block() { // check for `async {` and `async move {` return self.parse_async_block(attrs); @@ -3395,7 +3391,7 @@ impl<'a> Parser<'a> { } else { Movability::Movable }; - let asyncness = if self.span.edition() >= Edition::Edition2018 { + let asyncness = if self.span.rust_2018() { self.parse_asyncness() } else { IsAsync::NotAsync @@ -4508,9 +4504,7 @@ impl<'a> Parser<'a> { fn is_try_block(&mut self) -> bool { self.token.is_keyword(keywords::Try) && self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) && - - self.span.edition() >= Edition::Edition2018 && - + self.span.rust_2018() && // prevent `while try {} {}`, `if try {} {} else {}`, etc. !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) } @@ -7599,8 +7593,11 @@ impl<'a> Parser<'a> { self.check(&token::BinOp(token::Star)) || self.is_import_coupler() { // `use *;` or `use ::*;` or `use {...};` or `use ::{...};` + let mod_sep_ctxt = self.span.ctxt(); if self.eat(&token::ModSep) { - prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo())); + prefix.segments.push( + PathSegment::crate_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) + ); } if self.eat(&token::BinOp(token::Star)) { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 45eaf1d3190f2..62c8f2a78e129 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -325,6 +325,16 @@ impl Span { |einfo| einfo.edition) } + #[inline] + pub fn rust_2015(&self) -> bool { + self.edition() == edition::Edition::Edition2015 + } + + #[inline] + pub fn rust_2018(&self) -> bool { + self.edition() >= edition::Edition::Edition2018 + } + /// Return the source callee. /// /// Returns `None` if the supplied span has no expansion trace, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 361353c82e25c..e333a4f2176f5 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -12,7 +12,6 @@ //! allows bidirectional lookup; i.e. given a value, one can easily find the //! type, and vice versa. -use edition::Edition; use hygiene::SyntaxContext; use {Span, DUMMY_SP, GLOBALS}; @@ -444,7 +443,7 @@ impl Ident { pub fn is_unused_keyword(self) -> bool { // Note: `span.edition()` is relatively expensive, don't call it unless necessary. self.name >= keywords::Abstract.name() && self.name <= keywords::Yield.name() || - self.name.is_unused_keyword_2018() && self.span.edition() == Edition::Edition2018 + self.name.is_unused_keyword_2018() && self.span.rust_2018() } /// Returns `true` if the token is either a special identifier or a keyword. diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs new file mode 100644 index 0000000000000..5bb818f7d23ba --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/edition-imports-2015.rs @@ -0,0 +1,19 @@ +// edition:2015 +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive2015)] +pub fn derive_2015(_: TokenStream) -> TokenStream { + " + use import::Path; + + fn check_absolute() { + let x = ::absolute::Path; + } + ".parse().unwrap() +} diff --git a/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs b/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs new file mode 100644 index 0000000000000..f8d6bc5e0785d --- /dev/null +++ b/src/test/ui-fulldeps/proc-macro/edition-imports-2018.rs @@ -0,0 +1,24 @@ +// compile-pass +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod import { + pub struct Path; +} +mod absolute { + pub struct Path; +} + +mod check { + #[derive(Derive2015)] // OK + struct S; + + fn check() { + Path; + } +} + +fn main() {} diff --git a/src/test/ui/editions/auxiliary/absolute.rs b/src/test/ui/editions/auxiliary/absolute.rs new file mode 100644 index 0000000000000..d596f97355f4c --- /dev/null +++ b/src/test/ui/editions/auxiliary/absolute.rs @@ -0,0 +1 @@ +pub struct Path; diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs new file mode 100644 index 0000000000000..fb1a89d402242 --- /dev/null +++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs @@ -0,0 +1,17 @@ +// edition:2015 + +#[macro_export] +macro_rules! gen_imports { () => { + use import::Path; + // use std::collections::LinkedList; // FIXME + + fn check_absolute() { + ::absolute::Path; + // ::std::collections::LinkedList::::new(); // FIXME + } +}} + +#[macro_export] +macro_rules! gen_glob { () => { + use *; +}} diff --git a/src/test/ui/editions/auxiliary/edition-imports-2018.rs b/src/test/ui/editions/auxiliary/edition-imports-2018.rs new file mode 100644 index 0000000000000..b08dc499a0ddd --- /dev/null +++ b/src/test/ui/editions/auxiliary/edition-imports-2018.rs @@ -0,0 +1,17 @@ +// edition:2018 + +#[macro_export] +macro_rules! gen_imports { () => { + use import::Path; + use std::collections::LinkedList; + + fn check_absolute() { + ::absolute::Path; + ::std::collections::LinkedList::::new(); + } +}} + +#[macro_export] +macro_rules! gen_glob { () => { + use *; +}} diff --git a/src/test/ui/editions/edition-imports-2015.rs b/src/test/ui/editions/edition-imports-2015.rs new file mode 100644 index 0000000000000..b89ca28e279db --- /dev/null +++ b/src/test/ui/editions/edition-imports-2015.rs @@ -0,0 +1,28 @@ +// edition:2015 +// compile-flags:--extern absolute +// aux-build:edition-imports-2018.rs +// aux-build:absolute.rs + +#![feature(uniform_paths)] + +#[macro_use] +extern crate edition_imports_2018; + +mod check { + mod import { + pub struct Path; + } + + gen_imports!(); // OK + + fn check() { + Path; + LinkedList::::new(); + } +} + +mod check_glob { + gen_glob!(); //~ ERROR cannot glob-import all possible crates +} + +fn main() {} diff --git a/src/test/ui/editions/edition-imports-2015.stderr b/src/test/ui/editions/edition-imports-2015.stderr new file mode 100644 index 0000000000000..fb6b2e64ef5b8 --- /dev/null +++ b/src/test/ui/editions/edition-imports-2015.stderr @@ -0,0 +1,10 @@ +error: cannot glob-import all possible crates + --> $DIR/edition-imports-2015.rs:25:5 + | +LL | gen_glob!(); //~ ERROR cannot glob-import all possible crates + | ^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs new file mode 100644 index 0000000000000..cef4ce3bf1675 --- /dev/null +++ b/src/test/ui/editions/edition-imports-2018.rs @@ -0,0 +1,33 @@ +// compile-pass +// edition:2018 +// aux-build:edition-imports-2015.rs + +#[macro_use] +extern crate edition_imports_2015; + +mod import { + pub struct Path; +} +mod absolute { + pub struct Path; +} + +mod check { + gen_imports!(); // OK + + fn check() { + Path; + // LinkedList::::new(); // FIXME + } +} + +mod check_glob { + gen_glob!(); // OK + + fn check() { + import::Path; + absolute::Path; + } +} + +fn main() {} From 490973323fb2239ff7c6078da802c6e7fa5253d1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 24 Nov 2018 15:07:03 +0300 Subject: [PATCH 3/7] resolve: Fallback to uniform paths in 2015 imports used from global 2018 edition --- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/lib.rs | 26 ++++- src/librustc_resolve/macros.rs | 102 ++++++++++++------ .../auxiliary/edition-imports-2015.rs | 15 ++- src/test/ui/editions/edition-imports-2018.rs | 2 +- .../edition-imports-virtual-2015-ambiguity.rs | 18 ++++ ...tion-imports-virtual-2015-ambiguity.stderr | 21 ++++ .../edition-imports-virtual-2015-gated.rs | 12 +++ .../edition-imports-virtual-2015-gated.stderr | 22 ++++ 9 files changed, 186 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-gated.rs create mode 100644 src/test/ui/editions/edition-imports-virtual-2015-gated.stderr diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index c85ae2e633f1a..715b788ea8a9d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -132,9 +132,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // 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. + // 2015 identifiers used on global 2018 edition enter special "virtual 2015 mode", don't + // get crate root prepended, but get special treatment during in-scope resolution instead. let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false }; let crate_root = match prefix_iter.peek() { - Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => { + Some(seg) if !seg.ident.is_path_segment_keyword() && + seg.ident.span.rust_2015() && self.session.rust_2015() => { Some(seg.ident.span.ctxt()) } None if is_glob && use_tree.span.rust_2015() => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 745a07f282960..3c42d22bcf130 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -13,6 +13,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] +#![feature(label_break_value)] #![feature(nll)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] @@ -2196,28 +2197,45 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_ident_in_module( &mut self, module: ModuleOrUniformRoot<'a>, - mut ident: Ident, + ident: Ident, ns: Namespace, parent_scope: Option<&ParentScope<'a>>, record_used: bool, path_span: Span ) -> Result<&'a NameBinding<'a>, Determinacy> { - ident.span = ident.span.modern(); + self.resolve_ident_in_module_ext( + module, ident, ns, parent_scope, record_used, path_span + ).map_err(|(determinacy, _)| determinacy) + } + + fn resolve_ident_in_module_ext( + &mut self, + module: ModuleOrUniformRoot<'a>, + mut ident: Ident, + ns: Namespace, + parent_scope: Option<&ParentScope<'a>>, + record_used: bool, + path_span: Span + ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let orig_current_module = self.current_module; match module { ModuleOrUniformRoot::Module(module) => { + ident.span = ident.span.modern(); if let Some(def) = ident.span.adjust(module.expansion) { self.current_module = self.macro_def_scope(def); } } ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => { + ident.span = ident.span.modern(); ident.span.adjust(Mark::root()); } - _ => {} + ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => { + // No adjustments + } } let result = self.resolve_ident_in_module_unadjusted_ext( module, ident, ns, parent_scope, false, record_used, path_span, - ).map_err(|(determinacy, _)| determinacy); + ); self.current_module = orig_current_module; result } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index a26580144a97c..c5a86a32f762a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -526,7 +526,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // `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, + orig_ident: Ident, ns: Namespace, macro_kind: Option, is_import: bool, @@ -582,6 +582,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { enum WhereToResolve<'a> { DeriveHelpers, MacroRules(LegacyScope<'a>), + CrateRoot, Module(Module<'a>), MacroUsePrelude, BuiltinMacros, @@ -605,8 +606,8 @@ 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 - let rust_2015 = ident.span.rust_2015(); - ident = ident.modern(); + let rust_2015 = orig_ident.span.rust_2015(); + let mut ident = orig_ident.modern(); // Make sure `self`, `super` etc produce an error when passed to here. if ident.is_path_segment_keyword() { @@ -627,10 +628,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let mut innermost_result: Option<(&NameBinding, Flags)> = None; // Go through all the scopes and try to resolve the name. - let mut where_to_resolve = if ns == MacroNS { - WhereToResolve::DeriveHelpers - } else { - WhereToResolve::Module(parent_scope.module) + let mut where_to_resolve = match ns { + _ if is_import && rust_2015 => WhereToResolve::CrateRoot, + TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), + MacroNS => WhereToResolve::DeriveHelpers, }; let mut use_prelude = !parent_scope.module.no_implicit_prelude; let mut determinacy = Determinacy::Determined; @@ -668,6 +669,26 @@ impl<'a, 'cl> Resolver<'a, 'cl> { Err(Determinacy::Undetermined), _ => Err(Determinacy::Determined), } + WhereToResolve::CrateRoot => { + let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span); + let root_module = self.resolve_crate_root(root_ident); + let binding = self.resolve_ident_in_module_ext( + ModuleOrUniformRoot::Module(root_module), + orig_ident, + ns, + None, + record_used, + path_span, + ); + match binding { + Ok(binding) => Ok((binding, Flags::MODULE)), + Err((Determinacy::Undetermined, Weak::No)) => + return Err(Determinacy::determined(force)), + Err((Determinacy::Undetermined, Weak::Yes)) => + Err(Determinacy::Undetermined), + Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), + } + } WhereToResolve::Module(module) => { let orig_current_module = mem::replace(&mut self.current_module, module); let binding = self.resolve_ident_in_module_unadjusted_ext( @@ -816,7 +837,11 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } else if innermost_flags.contains(Flags::MACRO_RULES) && flags.contains(Flags::MODULE) && !self.disambiguate_legacy_vs_modern(innermost_binding, - binding) { + binding) || + flags.contains(Flags::MACRO_RULES) && + innermost_flags.contains(Flags::MODULE) && + !self.disambiguate_legacy_vs_modern(binding, + innermost_binding) { Some(AmbiguityKind::LegacyVsModern) } else if innermost_binding.is_glob_import() { Some(AmbiguityKind::GlobVsOuter) @@ -867,6 +892,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> { LegacyScope::Empty => WhereToResolve::Module(parent_scope.module), LegacyScope::Uninitialized => unreachable!(), } + WhereToResolve::CrateRoot => match ns { + TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), + MacroNS => WhereToResolve::DeriveHelpers, + } WhereToResolve::Module(module) => { match self.hygienic_lexical_parent(module, &mut ident.span) { Some(parent_module) => WhereToResolve::Module(parent_module), @@ -899,30 +928,43 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // The first found solution was the only one, return it. if let Some((binding, flags)) = innermost_result { - if is_import && !self.session.features_untracked().uniform_paths { - // We get to here only if there's no ambiguity, in ambiguous cases an error will - // be reported anyway, so there's no reason to report an additional feature error. - // The `binding` can actually be introduced by something other than `--extern`, - // but its `Def` should coincide with a crate passed with `--extern` - // (otherwise there would be ambiguity) and we can skip feature error in this case. - if ns != TypeNS || !use_prelude || - self.extern_prelude_get(ident, true).is_none() { - let msg = "imports can only refer to extern crate names \ - passed with `--extern` on stable channel"; - let mut err = feature_err(&self.session.parse_sess, "uniform_paths", - ident.span, GateIssue::Language, msg); - - let what = self.binding_description(binding, ident, - flags.contains(Flags::MISC_FROM_PRELUDE)); - let note_msg = format!("this import refers to {what}", what = what); - if binding.span.is_dummy() { - err.note(¬e_msg); - } else { - err.span_note(binding.span, ¬e_msg); - err.span_label(binding.span, "not an extern crate passed with `--extern`"); + // We get to here only if there's no ambiguity, in ambiguous cases an error will + // be reported anyway, so there's no reason to report an additional feature error. + // The `binding` can actually be introduced by something other than `--extern`, + // but its `Def` should coincide with a crate passed with `--extern` + // (otherwise there would be ambiguity) and we can skip feature error in this case. + 'ok: { + if !is_import || self.session.features_untracked().uniform_paths { + break 'ok; + } + if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() { + break 'ok; + } + if rust_2015 { + let root_ident = Ident::new(keywords::CrateRoot.name(), orig_ident.span); + let root_module = self.resolve_crate_root(root_ident); + if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module), + orig_ident, ns, None, false, path_span) + .is_ok() { + break 'ok; } - err.emit(); } + + let msg = "imports can only refer to extern crate names \ + passed with `--extern` on stable channel"; + let mut err = feature_err(&self.session.parse_sess, "uniform_paths", + ident.span, GateIssue::Language, msg); + + let what = self.binding_description(binding, ident, + flags.contains(Flags::MISC_FROM_PRELUDE)); + let note_msg = format!("this import refers to {what}", what = what); + if binding.span.is_dummy() { + err.note(¬e_msg); + } else { + err.span_note(binding.span, ¬e_msg); + err.span_label(binding.span, "not an extern crate passed with `--extern`"); + } + err.emit(); } return Ok(binding); diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs index fb1a89d402242..d7985d12dae61 100644 --- a/src/test/ui/editions/auxiliary/edition-imports-2015.rs +++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs @@ -3,7 +3,7 @@ #[macro_export] macro_rules! gen_imports { () => { use import::Path; - // use std::collections::LinkedList; // FIXME + use std::collections::LinkedList; fn check_absolute() { ::absolute::Path; @@ -15,3 +15,16 @@ macro_rules! gen_imports { () => { macro_rules! gen_glob { () => { use *; }} + +#[macro_export] +macro_rules! gen_gated { () => { + fn check_gated() { + enum E { A } + use E::*; + } +}} + +#[macro_export] +macro_rules! gen_ambiguous { () => { + use Ambiguous; +}} diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs index cef4ce3bf1675..989170d041fe7 100644 --- a/src/test/ui/editions/edition-imports-2018.rs +++ b/src/test/ui/editions/edition-imports-2018.rs @@ -17,7 +17,7 @@ mod check { fn check() { Path; - // LinkedList::::new(); // FIXME + LinkedList::::new(); } } diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs new file mode 100644 index 0000000000000..2527b30f07b33 --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -0,0 +1,18 @@ +// edition:2018 +// aux-build:edition-imports-2015.rs +// error-pattern: `Ambiguous` is ambiguous + +#[macro_use] +extern crate edition_imports_2015; + +pub struct Ambiguous {} + +mod check { + pub struct Ambiguous {} + + fn check() { + gen_ambiguous!(); + } +} + +fn main() {} diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr new file mode 100644 index 0000000000000..8e0b135121e07 --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr @@ -0,0 +1,21 @@ +error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution) + --> <::edition_imports_2015::gen_ambiguous macros>:1:15 + | +LL | ( ) => { use Ambiguous ; } + | ^^^^^^^^^ ambiguous name + | +note: `Ambiguous` could refer to the struct defined here + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1 + | +LL | pub struct Ambiguous {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: `Ambiguous` could also refer to the struct defined here + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5 + | +LL | pub struct Ambiguous {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::Ambiguous` to refer to this struct unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.rs b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs new file mode 100644 index 0000000000000..a1bf4f5eb51dc --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.rs @@ -0,0 +1,12 @@ +// edition:2018 +// aux-build:edition-imports-2015.rs +// error-pattern: imports can only refer to extern crate names passed with `--extern` + +#[macro_use] +extern crate edition_imports_2015; + +mod check { + gen_gated!(); +} + +fn main() {} diff --git a/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr new file mode 100644 index 0000000000000..7c1837e3f56e3 --- /dev/null +++ b/src/test/ui/editions/edition-imports-virtual-2015-gated.stderr @@ -0,0 +1,22 @@ +error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130) + --> <::edition_imports_2015::gen_gated macros>:1:50 + | +LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } } + | ^ + | + ::: $DIR/edition-imports-virtual-2015-gated.rs:9:5 + | +LL | gen_gated!(); + | ------------- not an extern crate passed with `--extern` + | + = help: add #![feature(uniform_paths)] to the crate attributes to enable +note: this import refers to the enum defined here + --> $DIR/edition-imports-virtual-2015-gated.rs:9:5 + | +LL | gen_gated!(); + | ^^^^^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 2a0adc3a3e549bc9d133e0e396664d5dde87da4b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 24 Nov 2018 19:14:05 +0300 Subject: [PATCH 4/7] resolve: Generalize `early_resolve_ident_in_lexical_scope` slightly Flatten `ModuleOrUniformRoot` variants --- src/librustc_resolve/lib.rs | 51 +++++++-------- src/librustc_resolve/macros.rs | 22 ++++--- src/librustc_resolve/resolve_imports.rs | 86 ++++++++++++------------- 3 files changed, 77 insertions(+), 82 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 3c42d22bcf130..27474a3fa6676 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -102,6 +102,12 @@ enum Weak { No, } +enum ScopeSet { + Import(Namespace), + Macro(MacroKind), + Module, +} + /// A free importable items suggested in case of resolution failure. struct ImportSuggestion { path: Path, @@ -997,22 +1003,19 @@ impl<'a> LexicalScopeBinding<'a> { } } - -#[derive(Clone, Copy, PartialEq, Debug)] -enum UniformRootKind { - CurrentScope, - ExternPrelude, -} - #[derive(Copy, Clone, Debug)] enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), - /// This "virtual module" denotes either resolution in extern prelude - /// for paths starting with `::` on 2018 edition or `extern::`, - /// or resolution in current scope for single-segment imports. - UniformRoot(UniformRootKind), + /// Virtual module that denotes resolution in extern prelude. + /// Used for paths starting with `::` on 2018 edition or `extern::`. + ExternPrelude, + + /// Virtual module that denotes resolution in current scope. + /// Used only for resolving single-segment imports. The reason it exists is that import paths + /// are always split into two parts, the first of which should be some kind of module. + CurrentScope, } impl<'a> PartialEq for ModuleOrUniformRoot<'a> { @@ -1020,8 +1023,8 @@ impl<'a> PartialEq for ModuleOrUniformRoot<'a> { match (*self, *other) { (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), - (ModuleOrUniformRoot::UniformRoot(lhs), ModuleOrUniformRoot::UniformRoot(rhs)) => - lhs == rhs, + (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true, + (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, _ => false, } } @@ -1763,8 +1766,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { error_callback(self, span, ResolutionError::FailedToResolve(msg)); Def::Err } - PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | - PathResult::Indeterminate => unreachable!(), + PathResult::Module(..) | PathResult::Indeterminate => unreachable!(), PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); Def::Err @@ -2225,11 +2227,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.current_module = self.macro_def_scope(def); } } - ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => { + ModuleOrUniformRoot::ExternPrelude => { ident.span = ident.span.modern(); ident.span.adjust(Mark::root()); } - ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => { + ModuleOrUniformRoot::CurrentScope => { // No adjustments } } @@ -3669,8 +3671,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); err_path_resolution() } - PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | - PathResult::Failed(..) => return None, + PathResult::Module(..) | PathResult::Failed(..) => return None, PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; @@ -3789,8 +3790,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } if name == keywords::Extern.name() || name == keywords::CrateRoot.name() && ident.span.rust_2018() { - module = - Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude)); + module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } if name == keywords::CrateRoot.name() || @@ -3823,9 +3823,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span) } else if opt_ns.is_none() || opt_ns == Some(MacroNS) { assert!(ns == TypeNS); - self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(), - parent_scope, record_used, record_used, - path_span) + let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module }; + self.early_resolve_ident_in_lexical_scope(ident, scopes, 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 }; @@ -3914,8 +3914,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { PathResult::Module(match module { Some(module) => module, - None if path.is_empty() => - ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope), + None if path.is_empty() => ModuleOrUniformRoot::CurrentScope, _ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path), }) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index c5a86a32f762a..5493913fd811d 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -9,11 +9,11 @@ // except according to those terms. use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; -use {CrateLint, Resolver, ResolutionError, Weak}; +use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak}; use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; use {is_known_tool, resolve_error}; use ModuleOrUniformRoot; -use Namespace::{self, *}; +use Namespace::*; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use resolve_imports::ImportResolver; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, @@ -502,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { def } else { let binding = self.early_resolve_ident_in_lexical_scope( - path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span + path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span ); match binding { Ok(..) => {} @@ -527,9 +527,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { crate fn early_resolve_ident_in_lexical_scope( &mut self, orig_ident: Ident, - ns: Namespace, - macro_kind: Option, - is_import: bool, + scope_set: ScopeSet, parent_scope: &ParentScope<'a>, record_used: bool, force: bool, @@ -605,8 +603,6 @@ 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 - let rust_2015 = orig_ident.span.rust_2015(); let mut ident = orig_ident.modern(); // Make sure `self`, `super` etc produce an error when passed to here. @@ -628,6 +624,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let mut innermost_result: Option<(&NameBinding, Flags)> = None; // Go through all the scopes and try to resolve the name. + let rust_2015 = orig_ident.span.rust_2015(); + let (ns, macro_kind, is_import) = match scope_set { + ScopeSet::Import(ns) => (ns, None, true), + ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), + ScopeSet::Module => (TypeNS, None, false), + }; let mut where_to_resolve = match ns { _ if is_import && rust_2015 => WhereToResolve::CrateRoot, TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), @@ -1041,7 +1043,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let macro_resolutions = mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new()); for (ident, kind, parent_scope, initial_binding) in macro_resolutions { - match self.early_resolve_ident_in_lexical_scope(ident, MacroNS, Some(kind), false, + match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind), &parent_scope, true, true, ident.span) { Ok(binding) => { let initial_def = initial_binding.map(|initial_binding| { @@ -1067,7 +1069,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 _ = self.early_resolve_ident_in_lexical_scope( - ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span + ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span ); } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index d860bafce1329..fa6c86e3b4070 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -11,7 +11,7 @@ use self::ImportDirectiveSubclass::*; use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; -use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak}; +use {CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak}; use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; use {Resolver, Segment}; @@ -162,46 +162,42 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, - ModuleOrUniformRoot::UniformRoot(uniform_root_kind) => { + ModuleOrUniformRoot::ExternPrelude => { assert!(!restricted_shadowing); - match uniform_root_kind { - UniformRootKind::ExternPrelude => { - return if let Some(binding) = - self.extern_prelude_get(ident, !record_used) { - Ok(binding) - } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { - // Macro-expanded `extern crate` items can add names to extern prelude. - Err((Undetermined, Weak::No)) - } else { - Err((Determined, Weak::No)) - } - } - UniformRootKind::CurrentScope => { - let parent_scope = - parent_scope.expect("no parent scope for a single-segment import"); - - if ns == TypeNS { - if ident.name == keywords::Crate.name() || - ident.name == keywords::DollarCrate.name() { - let module = self.resolve_crate_root(ident); - let binding = (module, ty::Visibility::Public, - module.span, Mark::root()) - .to_name_binding(self.arenas); - return Ok(binding); - } else if ident.name == keywords::Super.name() || - ident.name == keywords::SelfValue.name() { - // FIXME: Implement these with renaming requirements so that e.g. - // `use super;` doesn't work, but `use super as name;` does. - // Fall through here to get an error from `early_resolve_...`. - } - } - - let binding = self.early_resolve_ident_in_lexical_scope( - ident, ns, None, true, parent_scope, record_used, record_used, path_span - ); - return binding.map_err(|determinacy| (determinacy, Weak::No)); + return if let Some(binding) = self.extern_prelude_get(ident, !record_used) { + Ok(binding) + } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { + // Macro-expanded `extern crate` items can add names to extern prelude. + Err((Undetermined, Weak::No)) + } else { + Err((Determined, Weak::No)) + } + } + ModuleOrUniformRoot::CurrentScope => { + assert!(!restricted_shadowing); + let parent_scope = + parent_scope.expect("no parent scope for a single-segment import"); + + if ns == TypeNS { + if ident.name == keywords::Crate.name() || + ident.name == keywords::DollarCrate.name() { + let module = self.resolve_crate_root(ident); + let binding = (module, ty::Visibility::Public, + module.span, Mark::root()) + .to_name_binding(self.arenas); + return Ok(binding); + } else if ident.name == keywords::Super.name() || + ident.name == keywords::SelfValue.name() { + // FIXME: Implement these with renaming requirements so that e.g. + // `use super;` doesn't work, but `use super as name;` does. + // Fall through here to get an error from `early_resolve_...`. } } + + let binding = self.early_resolve_ident_in_lexical_scope( + ident, ScopeSet::Import(ns), parent_scope, record_used, record_used, path_span + ); + return binding.map_err(|determinacy| (determinacy, Weak::No)); } }; @@ -334,7 +330,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } let module = match glob_import.imported_module.get() { Some(ModuleOrUniformRoot::Module(module)) => module, - Some(ModuleOrUniformRoot::UniformRoot(_)) => continue, + Some(_) => continue, None => return Err((Undetermined, Weak::Yes)), }; let (orig_current_module, mut ident) = (self.current_module, ident.modern()); @@ -967,9 +963,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { return if all_ns_failed { let resolutions = match module { - ModuleOrUniformRoot::Module(module) => - Some(module.resolutions.borrow()), - ModuleOrUniformRoot::UniformRoot(_) => None, + ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()), + _ => None, }; let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter()); let names = resolutions.filter_map(|(&(ref i, _), resolution)| { @@ -1007,7 +1002,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { format!("no `{}` in the root{}", ident, lev_suggestion) } } - ModuleOrUniformRoot::UniformRoot(_) => { + _ => { if !ident.is_path_segment_keyword() { format!("no `{}` external crate{}", ident, lev_suggestion) } else { @@ -1108,9 +1103,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { let module = match directive.imported_module.get().unwrap() { ModuleOrUniformRoot::Module(module) => module, - ModuleOrUniformRoot::UniformRoot(_) => { - self.session.span_err(directive.span, - "cannot glob-import all possible crates"); + _ => { + self.session.span_err(directive.span, "cannot glob-import all possible crates"); return; } }; From 3b5888071a2b54092d9670175e696f4233ed6b94 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Nov 2018 00:25:03 +0300 Subject: [PATCH 5/7] resolve: Fallback to extern prelude in 2015 imports used from global 2018 edition --- src/librustc_resolve/lib.rs | 22 +++++++++++++--- src/librustc_resolve/macros.rs | 26 ++++++++++++++----- src/librustc_resolve/resolve_imports.rs | 9 +++++++ .../auxiliary/edition-imports-2015.rs | 3 ++- src/test/ui/editions/edition-imports-2018.rs | 8 +----- .../ui/editions/edition-imports-2018.stderr | 10 +++++++ .../edition-imports-virtual-2015-ambiguity.rs | 9 ++++--- ...tion-imports-virtual-2015-ambiguity.stderr | 24 ++++++++++++++--- 8 files changed, 86 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/editions/edition-imports-2018.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 27474a3fa6676..a4ddf06b6c048 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -104,6 +104,7 @@ enum Weak { enum ScopeSet { Import(Namespace), + AbsolutePath(Namespace), Macro(MacroKind), Module, } @@ -1008,6 +1009,9 @@ enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), + /// Virtual module that denotes resolution in crate root with fallback to extern prelude. + CrateRootAndExternPrelude, + /// Virtual module that denotes resolution in extern prelude. /// Used for paths starting with `::` on 2018 edition or `extern::`. ExternPrelude, @@ -1021,9 +1025,11 @@ enum ModuleOrUniformRoot<'a> { impl<'a> PartialEq for ModuleOrUniformRoot<'a> { fn eq(&self, other: &Self) -> bool { match (*self, *other) { - (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => - ptr::eq(lhs, rhs), - (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true, + (ModuleOrUniformRoot::Module(lhs), + ModuleOrUniformRoot::Module(rhs)) => ptr::eq(lhs, rhs), + (ModuleOrUniformRoot::CrateRootAndExternPrelude, + ModuleOrUniformRoot::CrateRootAndExternPrelude) | + (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) | (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, _ => false, } @@ -1243,6 +1249,7 @@ struct UseError<'a> { #[derive(Clone, Copy, PartialEq, Debug)] enum AmbiguityKind { Import, + AbsolutePath, BuiltinAttr, DeriveHelper, LegacyHelperVsPrelude, @@ -1258,6 +1265,8 @@ impl AmbiguityKind { match self { AmbiguityKind::Import => "name vs any other name during import resolution", + AmbiguityKind::AbsolutePath => + "name in the crate root vs extern crate during absolute path resolution", AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name", AmbiguityKind::DeriveHelper => @@ -2231,6 +2240,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { ident.span = ident.span.modern(); ident.span.adjust(Mark::root()); } + ModuleOrUniformRoot::CrateRootAndExternPrelude | ModuleOrUniformRoot::CurrentScope => { // No adjustments } @@ -3793,6 +3803,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } + if name == keywords::CrateRoot.name() && + ident.span.rust_2015() && self.session.rust_2018() { + // `::a::b` from 2015 macro on 2018 global edition + module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude); + continue; + } if name == keywords::CrateRoot.name() || name == keywords::Crate.name() || name == keywords::DollarCrate.name() { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 5493913fd811d..d306e9ebe32b5 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -625,13 +625,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // Go through all the scopes and try to resolve the name. let rust_2015 = orig_ident.span.rust_2015(); - let (ns, macro_kind, is_import) = match scope_set { - ScopeSet::Import(ns) => (ns, None, true), - ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), - ScopeSet::Module => (TypeNS, None, false), + let (ns, macro_kind, is_import, is_absolute_path) = match scope_set { + ScopeSet::Import(ns) => (ns, None, true, false), + ScopeSet::AbsolutePath(ns) => (ns, None, false, true), + ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false, false), + ScopeSet::Module => (TypeNS, None, false, false), }; let mut where_to_resolve = match ns { - _ if is_import && rust_2015 => WhereToResolve::CrateRoot, + _ if is_absolute_path || is_import && rust_2015 => WhereToResolve::CrateRoot, TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), MacroNS => WhereToResolve::DeriveHelpers, }; @@ -761,7 +762,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } } WhereToResolve::ExternPrelude => { - if use_prelude { + if use_prelude || is_absolute_path { match self.extern_prelude_get(ident, !record_used) { Some(binding) => Ok((binding, Flags::PRELUDE)), None => Err(Determinacy::determined( @@ -827,6 +828,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let ambiguity_error_kind = if is_import { Some(AmbiguityKind::Import) + } else if is_absolute_path { + Some(AmbiguityKind::AbsolutePath) } else if innermost_def == builtin || def == builtin { Some(AmbiguityKind::BuiltinAttr) } else if innermost_def == derive_helper || def == derive_helper { @@ -894,10 +897,18 @@ impl<'a, 'cl> Resolver<'a, 'cl> { LegacyScope::Empty => WhereToResolve::Module(parent_scope.module), LegacyScope::Uninitialized => unreachable!(), } - WhereToResolve::CrateRoot => match ns { + WhereToResolve::CrateRoot if is_import => match ns { TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module), MacroNS => WhereToResolve::DeriveHelpers, } + WhereToResolve::CrateRoot if is_absolute_path => match ns { + TypeNS => { + ident.span.adjust(Mark::root()); + WhereToResolve::ExternPrelude + } + ValueNS | MacroNS => break, + } + WhereToResolve::CrateRoot => unreachable!(), WhereToResolve::Module(module) => { match self.hygienic_lexical_parent(module, &mut ident.span) { Some(parent_module) => WhereToResolve::Module(parent_module), @@ -915,6 +926,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs, WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers, WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search + WhereToResolve::ExternPrelude if is_absolute_path => break, WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude, WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude, WhereToResolve::StdLibPrelude => match ns { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index fa6c86e3b4070..88551f6566a25 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -162,6 +162,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, + ModuleOrUniformRoot::CrateRootAndExternPrelude => { + assert!(!restricted_shadowing); + let parent_scope = self.dummy_parent_scope(); + let binding = self.early_resolve_ident_in_lexical_scope( + ident, ScopeSet::AbsolutePath(ns), &parent_scope, + record_used, record_used, path_span, + ); + return binding.map_err(|determinacy| (determinacy, Weak::No)); + } ModuleOrUniformRoot::ExternPrelude => { assert!(!restricted_shadowing); return if let Some(binding) = self.extern_prelude_get(ident, !record_used) { diff --git a/src/test/ui/editions/auxiliary/edition-imports-2015.rs b/src/test/ui/editions/auxiliary/edition-imports-2015.rs index d7985d12dae61..c72331ca2e119 100644 --- a/src/test/ui/editions/auxiliary/edition-imports-2015.rs +++ b/src/test/ui/editions/auxiliary/edition-imports-2015.rs @@ -7,7 +7,7 @@ macro_rules! gen_imports { () => { fn check_absolute() { ::absolute::Path; - // ::std::collections::LinkedList::::new(); // FIXME + ::std::collections::LinkedList::::new(); } }} @@ -27,4 +27,5 @@ macro_rules! gen_gated { () => { #[macro_export] macro_rules! gen_ambiguous { () => { use Ambiguous; + type A = ::edition_imports_2015::Path; }} diff --git a/src/test/ui/editions/edition-imports-2018.rs b/src/test/ui/editions/edition-imports-2018.rs index 989170d041fe7..dcdbf0d050be1 100644 --- a/src/test/ui/editions/edition-imports-2018.rs +++ b/src/test/ui/editions/edition-imports-2018.rs @@ -1,4 +1,3 @@ -// compile-pass // edition:2018 // aux-build:edition-imports-2015.rs @@ -22,12 +21,7 @@ mod check { } mod check_glob { - gen_glob!(); // OK - - fn check() { - import::Path; - absolute::Path; - } + gen_glob!(); //~ ERROR cannot glob-import all possible crates } fn main() {} diff --git a/src/test/ui/editions/edition-imports-2018.stderr b/src/test/ui/editions/edition-imports-2018.stderr new file mode 100644 index 0000000000000..944f42ee0451b --- /dev/null +++ b/src/test/ui/editions/edition-imports-2018.stderr @@ -0,0 +1,10 @@ +error: cannot glob-import all possible crates + --> $DIR/edition-imports-2018.rs:24:5 + | +LL | gen_glob!(); //~ ERROR cannot glob-import all possible crates + | ^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs index 2527b30f07b33..562d3c9e70fb1 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -1,9 +1,12 @@ // edition:2018 +// compile-flags:--extern edition_imports_2015 // aux-build:edition-imports-2015.rs // error-pattern: `Ambiguous` is ambiguous +// error-pattern: `edition_imports_2015` is ambiguous -#[macro_use] -extern crate edition_imports_2015; +mod edition_imports_2015 { + pub struct Path; +} pub struct Ambiguous {} @@ -11,7 +14,7 @@ mod check { pub struct Ambiguous {} fn check() { - gen_ambiguous!(); + edition_imports_2015::gen_ambiguous!(); } } diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr index 8e0b135121e07..d0897d081c357 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr @@ -1,21 +1,37 @@ error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution) --> <::edition_imports_2015::gen_ambiguous macros>:1:15 | -LL | ( ) => { use Ambiguous ; } +LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } | ^^^^^^^^^ ambiguous name | note: `Ambiguous` could refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:8:1 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:1 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ note: `Ambiguous` could also refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:5 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:14:5 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::Ambiguous` to refer to this struct unambiguously -error: aborting due to previous error +error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution) + --> <::edition_imports_2015::gen_ambiguous macros>:1:39 + | +LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } + | ^^^^^^^^^^^^^^^^^^^^ ambiguous name + | + = note: `edition_imports_2015` could refer to an extern crate passed with `--extern` + = help: use `::edition_imports_2015` to refer to this extern crate unambiguously +note: `edition_imports_2015` could also refer to the module defined here + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:7:1 + | +LL | / mod edition_imports_2015 { +LL | | pub struct Path; +LL | | } + | |_^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`. From 581b68380f6740124100d6c434e7f3e3da03d764 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Nov 2018 16:08:43 +0300 Subject: [PATCH 6/7] resolve: Suggest `crate::` for resolving ambiguities when appropriate More precise spans for ambiguities from macros --- src/librustc_resolve/lib.rs | 22 +++++++++++----- src/librustc_resolve/macros.rs | 25 +++++++++++-------- ...helper-attr-blocked-by-import-ambig.stderr | 2 +- .../proc-macro/ambiguous-builtin-attrs.stderr | 10 ++++---- .../proc-macro/derive-helper-shadowing.stderr | 2 +- .../edition-imports-virtual-2015-ambiguity.rs | 5 ++-- ...tion-imports-virtual-2015-ambiguity.stderr | 23 +++++++++-------- .../local-modularized-tricky-fail-1.rs | 1 + .../local-modularized-tricky-fail-1.stderr | 15 +++++------ src/test/ui/imports/macro-paths.stderr | 2 +- .../macros/restricted-shadowing-legacy.stderr | 24 ++++++++++++++++++ .../macros/restricted-shadowing-modern.stderr | 18 +++++++++++++ .../uniform-paths/ambiguity-macros.stderr | 2 +- .../rust-2018/uniform-paths/ambiguity.stderr | 2 +- .../block-scoped-shadow-nested.stderr | 2 +- .../uniform-paths/block-scoped-shadow.stderr | 6 ++--- 16 files changed, 111 insertions(+), 50 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a4ddf06b6c048..70324f6a1498b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1292,6 +1292,7 @@ impl AmbiguityKind { /// Miscellaneous bits of metadata for better ambiguity error reporting. #[derive(Clone, Copy, PartialEq)] enum AmbiguityErrorMisc { + SuggestCrate, SuggestSelf, FromPrelude, None, @@ -4872,12 +4873,21 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { `{ident}` to disambiguate", ident = ident)) } if b.is_extern_crate() && ident.span.rust_2018() { - help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously", - ident = ident, thing = b.descr())) - } - if misc == AmbiguityErrorMisc::SuggestSelf { - help_msgs.push(format!("use `self::{ident}` to refer to this {thing} unambiguously", - ident = ident, thing = b.descr())) + help_msgs.push(format!( + "use `::{ident}` to refer to this {thing} unambiguously", + ident = ident, thing = b.descr(), + )) + } + if misc == AmbiguityErrorMisc::SuggestCrate { + help_msgs.push(format!( + "use `crate::{ident}` to refer to this {thing} unambiguously", + ident = ident, thing = b.descr(), + )) + } else if misc == AmbiguityErrorMisc::SuggestSelf { + help_msgs.push(format!( + "use `self::{ident}` to refer to this {thing} unambiguously", + ident = ident, thing = b.descr(), + )) } if b.span.is_dummy() { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index d306e9ebe32b5..5db3efee9f6a1 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -42,7 +42,7 @@ use syntax_pos::{Span, DUMMY_SP}; use errors::Applicability; use std::cell::Cell; -use std::mem; +use std::{mem, ptr}; use rustc_data_structures::sync::Lrc; #[derive(Clone, Debug)] @@ -594,11 +594,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { bitflags! { struct Flags: u8 { - const MACRO_RULES = 1 << 0; - const MODULE = 1 << 1; - const PRELUDE = 1 << 2; - const MISC_SUGGEST_SELF = 1 << 3; - const MISC_FROM_PRELUDE = 1 << 4; + const MACRO_RULES = 1 << 0; + const MODULE = 1 << 1; + const PRELUDE = 1 << 2; + const MISC_SUGGEST_CRATE = 1 << 3; + const MISC_SUGGEST_SELF = 1 << 4; + const MISC_FROM_PRELUDE = 1 << 5; } } @@ -684,7 +685,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { path_span, ); match binding { - Ok(binding) => Ok((binding, Flags::MODULE)), + Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)), Err((Determinacy::Undetermined, Weak::No)) => return Err(Determinacy::determined(force)), Err((Determinacy::Undetermined, Weak::Yes)) => @@ -706,7 +707,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.current_module = orig_current_module; match binding { Ok(binding) => { - let misc_flags = if module.is_normal() { + let misc_flags = if ptr::eq(module, self.graph_root) { + Flags::MISC_SUGGEST_CRATE + } else if module.is_normal() { Flags::MISC_SUGGEST_SELF } else { Flags::empty() @@ -857,7 +860,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { None }; if let Some(kind) = ambiguity_error_kind { - let misc = |f: Flags| if f.contains(Flags::MISC_SUGGEST_SELF) { + let misc = |f: Flags| if f.contains(Flags::MISC_SUGGEST_CRATE) { + AmbiguityErrorMisc::SuggestCrate + } else if f.contains(Flags::MISC_SUGGEST_SELF) { AmbiguityErrorMisc::SuggestSelf } else if f.contains(Flags::MISC_FROM_PRELUDE) { AmbiguityErrorMisc::FromPrelude @@ -866,7 +871,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { }; self.ambiguity_errors.push(AmbiguityError { kind, - ident, + ident: orig_ident, b1: innermost_binding, b2: binding, misc1: misc(innermost_flags), diff --git a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr index ee98873064fc4..d288d7295120c 100644 --- a/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr +++ b/src/test/ui-fulldeps/custom-derive/helper-attr-blocked-by-import-ambig.stderr @@ -14,7 +14,7 @@ note: `helper` could also refer to the attribute macro imported here | LL | use plugin::helper; | ^^^^^^^^^^^^^^ - = help: use `self::helper` to refer to this attribute macro unambiguously + = help: use `crate::helper` to refer to this attribute macro unambiguously error: aborting due to previous error diff --git a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr index 34b21ea26830c..79dc922b9db2c 100644 --- a/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr +++ b/src/test/ui-fulldeps/proc-macro/ambiguous-builtin-attrs.stderr @@ -16,7 +16,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:11:19 @@ -30,7 +30,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:20:34 @@ -44,7 +44,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `repr` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:22:11 @@ -58,7 +58,7 @@ note: `repr` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::repr` to refer to this attribute macro unambiguously + = help: use `crate::repr` to refer to this attribute macro unambiguously error[E0659]: `feature` is ambiguous (built-in attribute vs any other name) --> $DIR/ambiguous-builtin-attrs.rs:3:4 @@ -72,7 +72,7 @@ note: `feature` could also refer to the attribute macro imported here | LL | use builtin_attrs::*; | ^^^^^^^^^^^^^^^^ - = help: use `self::feature` to refer to this attribute macro unambiguously + = help: use `crate::feature` to refer to this attribute macro unambiguously error: aborting due to 6 previous errors diff --git a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr index f04782fac4d2d..cc50fefc46453 100644 --- a/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui-fulldeps/proc-macro/derive-helper-shadowing.stderr @@ -14,7 +14,7 @@ note: `my_attr` could also refer to the attribute macro imported here | LL | use derive_helper_shadowing::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: use `self::my_attr` to refer to this attribute macro unambiguously + = help: use `crate::my_attr` to refer to this attribute macro unambiguously error: aborting due to previous error diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs index 562d3c9e70fb1..53ec3867f0110 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.rs @@ -1,8 +1,6 @@ // edition:2018 // compile-flags:--extern edition_imports_2015 // aux-build:edition-imports-2015.rs -// error-pattern: `Ambiguous` is ambiguous -// error-pattern: `edition_imports_2015` is ambiguous mod edition_imports_2015 { pub struct Path; @@ -14,7 +12,8 @@ mod check { pub struct Ambiguous {} fn check() { - edition_imports_2015::gen_ambiguous!(); + edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous + //~| ERROR `edition_imports_2015` is ambiguous } } diff --git a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr index d0897d081c357..ac2bf21c5c0ba 100644 --- a/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr +++ b/src/test/ui/editions/edition-imports-virtual-2015-ambiguity.stderr @@ -1,36 +1,39 @@ error[E0659]: `Ambiguous` is ambiguous (name vs any other name during import resolution) - --> <::edition_imports_2015::gen_ambiguous macros>:1:15 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9 | -LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } - | ^^^^^^^^^ ambiguous name +LL | edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name | note: `Ambiguous` could refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:11:1 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:9:1 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::Ambiguous` to refer to this struct unambiguously note: `Ambiguous` could also refer to the struct defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:14:5 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:12:5 | LL | pub struct Ambiguous {} | ^^^^^^^^^^^^^^^^^^^^^^^ = help: use `self::Ambiguous` to refer to this struct unambiguously + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0659]: `edition_imports_2015` is ambiguous (name in the crate root vs extern crate during absolute path resolution) - --> <::edition_imports_2015::gen_ambiguous macros>:1:39 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:15:9 | -LL | ( ) => { use Ambiguous ; type A = :: edition_imports_2015 :: Path ; } - | ^^^^^^^^^^^^^^^^^^^^ ambiguous name +LL | edition_imports_2015::gen_ambiguous!(); //~ ERROR `Ambiguous` is ambiguous + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous name | = note: `edition_imports_2015` could refer to an extern crate passed with `--extern` - = help: use `::edition_imports_2015` to refer to this extern crate unambiguously note: `edition_imports_2015` could also refer to the module defined here - --> $DIR/edition-imports-virtual-2015-ambiguity.rs:7:1 + --> $DIR/edition-imports-virtual-2015-ambiguity.rs:5:1 | LL | / mod edition_imports_2015 { LL | | pub struct Path; LL | | } | |_^ + = help: use `crate::edition_imports_2015` to refer to this module unambiguously + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.rs b/src/test/ui/imports/local-modularized-tricky-fail-1.rs index fb05b95a96dc6..37633c7a4415f 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.rs +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.rs @@ -43,6 +43,7 @@ mod inner2 { fn main() { panic!(); //~ ERROR `panic` is ambiguous + //~| ERROR `panic` is ambiguous } mod inner3 { diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index 962294e48caef..1978648e206f1 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -22,7 +22,7 @@ LL | use inner1::*; = help: consider adding an explicit import of `exported` to disambiguate error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/local-modularized-tricky-fail-1.rs:56:1 + --> $DIR/local-modularized-tricky-fail-1.rs:57:1 | LL | include!(); //~ ERROR `include` is ambiguous | ^^^^^^^ ambiguous name @@ -38,7 +38,7 @@ LL | | } ... LL | define_include!(); | ------------------ in this macro invocation - = help: use `self::include` to refer to this macro unambiguously + = help: use `crate::include` to refer to this macro unambiguously error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) --> $DIR/local-modularized-tricky-fail-1.rs:45:5 @@ -57,13 +57,13 @@ LL | | } ... LL | define_panic!(); | ---------------- in this macro invocation - = help: use `self::panic` to refer to this macro unambiguously + = help: use `crate::panic` to refer to this macro unambiguously error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> <::std::macros::panic macros>:1:13 + --> $DIR/local-modularized-tricky-fail-1.rs:45:5 | -LL | ( ) => ( { panic ! ( "explicit panic" ) } ) ; ( $ msg : expr ) => ( - | ^^^^^ ambiguous name +LL | panic!(); //~ ERROR `panic` is ambiguous + | ^^^^^^^^^ ambiguous name | = note: `panic` could refer to a macro from prelude note: `panic` could also refer to the macro defined here @@ -76,7 +76,8 @@ LL | | } ... LL | define_panic!(); | ---------------- in this macro invocation - = help: use `self::panic` to refer to this macro unambiguously + = help: use `crate::panic` to refer to this macro unambiguously + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr index 8e8742f849bf0..3f481b0cfb0df 100644 --- a/src/test/ui/imports/macro-paths.stderr +++ b/src/test/ui/imports/macro-paths.stderr @@ -34,7 +34,7 @@ LL | / pub mod baz { LL | | pub use two_macros::m; LL | | } | |_^ - = help: use `self::baz` to refer to this module unambiguously + = help: use `crate::baz` to refer to this module unambiguously error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/restricted-shadowing-legacy.stderr b/src/test/ui/macros/restricted-shadowing-legacy.stderr index 2135d63c80ec2..9d61799713b04 100644 --- a/src/test/ui/macros/restricted-shadowing-legacy.stderr +++ b/src/test/ui/macros/restricted-shadowing-legacy.stderr @@ -3,6 +3,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -26,6 +29,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -49,6 +55,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -72,6 +81,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -95,6 +107,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -118,6 +133,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -141,6 +159,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 @@ -164,6 +185,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro_rules! gen_invoc { () => { m!() } } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-legacy.rs:88:9 diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr index 2449e8512d3cd..398a7660d3093 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.stderr +++ b/src/test/ui/macros/restricted-shadowing-modern.stderr @@ -3,6 +3,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -26,6 +29,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -49,6 +55,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -72,6 +81,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -95,6 +107,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | m!(); //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 @@ -118,6 +133,9 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name | LL | macro gen_invoc() { m!() } //~ ERROR `m` is ambiguous | ^ ambiguous name +... +LL | include!(); + | ----------- in this macro invocation | note: `m` could refer to the macro defined here --> $DIR/restricted-shadowing-modern.rs:91:9 diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr index ac8d3b9d0cbe4..a9e6da8f211b3 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr @@ -16,7 +16,7 @@ LL | | } ... LL | m!(); | ----- in this macro invocation - = help: use `self::std` to refer to this module unambiguously + = help: use `crate::std` to refer to this module unambiguously error: aborting due to previous error diff --git a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr index beeb74654e5b5..b1feb82fba90d 100644 --- a/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr +++ b/src/test/ui/rust-2018/uniform-paths/ambiguity.stderr @@ -13,7 +13,7 @@ LL | / mod std { LL | | pub struct io; LL | | } | |_^ - = help: use `self::std` to refer to this module unambiguously + = help: use `crate::std` to refer to this module unambiguously error: aborting due to previous error diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr index aa46947f93f4b..0088296b1a471 100644 --- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr +++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow-nested.stderr @@ -16,7 +16,7 @@ LL | / mod sub { LL | | pub fn bar() {} LL | | } | |_^ - = help: use `self::sub` to refer to this module unambiguously + = help: use `crate::sub` to refer to this module unambiguously error: aborting due to previous error diff --git a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr index 010b9efad393b..213f723385b1c 100644 --- a/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr +++ b/src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr @@ -14,7 +14,7 @@ note: `Foo` could also refer to the enum defined here | LL | enum Foo {} | ^^^^^^^^^^^ - = help: use `self::Foo` to refer to this enum unambiguously + = help: use `crate::Foo` to refer to this enum unambiguously error[E0659]: `std` is ambiguous (name vs any other name during import resolution) --> $DIR/block-scoped-shadow.rs:26:9 @@ -32,7 +32,7 @@ note: `std` could also refer to the struct defined here | LL | struct std; | ^^^^^^^^^^^ - = help: use `self::std` to refer to this struct unambiguously + = help: use `crate::std` to refer to this struct unambiguously error[E0659]: `std` is ambiguous (name vs any other name during import resolution) --> $DIR/block-scoped-shadow.rs:26:9 @@ -50,7 +50,7 @@ note: `std` could also refer to the unit struct defined here | LL | struct std; | ^^^^^^^^^^^ - = help: use `self::std` to refer to this unit struct unambiguously + = help: use `crate::std` to refer to this unit struct unambiguously error: aborting due to 3 previous errors From 37e03455c1fc0014c4caabca19905bf331c3940a Mon Sep 17 00:00:00 2001 From: F001 Date: Wed, 7 Nov 2018 12:26:05 +0800 Subject: [PATCH 7/7] fix ICE --- src/librustc_typeck/check/_match.rs | 12 +++++++----- src/test/ui/match/match-fn-call.rs | 12 ++++++++++++ src/test/ui/match/match-fn-call.stderr | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/match/match-fn-call.rs create mode 100644 src/test/ui/match/match-fn-call.stderr diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index a1e51402830c9..cd674c05abdd2 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -814,11 +814,6 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); report_unexpected_def(def); return self.tcx.types.err; } - // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type"); - - self.demand_eqtype(pat.span, expected, pat_ty); let variant = match def { Def::Err => { @@ -836,6 +831,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } _ => bug!("unexpected pattern definition: {:?}", def) }; + + // Replace constructor type with constructed type for tuple struct patterns. + let pat_ty = pat_ty.fn_sig(tcx).output(); + let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type"); + + self.demand_eqtype(pat.span, expected, pat_ty); + // Type check subpatterns. if subpats.len() == variant.fields.len() || subpats.len() < variant.fields.len() && ddpos.is_some() { diff --git a/src/test/ui/match/match-fn-call.rs b/src/test/ui/match/match-fn-call.rs new file mode 100644 index 0000000000000..d9c50e75c4944 --- /dev/null +++ b/src/test/ui/match/match-fn-call.rs @@ -0,0 +1,12 @@ +use std::path::Path; + +fn main() { + let path = Path::new("foo"); + match path { + Path::new("foo") => println!("foo"), + //~^ ERROR expected tuple struct/variant + Path::new("bar") => println!("bar"), + //~^ ERROR expected tuple struct/variant + _ => (), + } +} diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr new file mode 100644 index 0000000000000..4e24621706bdb --- /dev/null +++ b/src/test/ui/match/match-fn-call.stderr @@ -0,0 +1,15 @@ +error[E0164]: expected tuple struct/variant, found method `::new` + --> $DIR/match-fn-call.rs:6:9 + | +LL | Path::new("foo") => println!("foo"), + | ^^^^^^^^^^^^^^^^ not a tuple variant or struct + +error[E0164]: expected tuple struct/variant, found method `::new` + --> $DIR/match-fn-call.rs:8:9 + | +LL | Path::new("bar") => println!("bar"), + | ^^^^^^^^^^^^^^^^ not a tuple variant or struct + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0164`.