Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't ask what edition we are in; ask what edition a span is in #50999

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,13 @@ impl Lint {

pub fn default_level(&self, session: &Session) -> Level {
if let Some(edition_deny) = self.edition_deny {
if session.edition() >= edition_deny {
// Ideally, we would get the edition for the actual span,
// but that is kind of a pain in the neck to do right
// now. Also, lints are not breaking things anyway (due to
// `-Acap-lints`), and the lint itself should probably be
// checking the span to see if the code was injected via
// macro etc, so for now we'll just use the local level.
if session.local_edition() >= edition_deny {
return Level::Deny
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,12 +948,14 @@ impl Session {
self.opts.debugging_opts.teach && self.parse_sess.span_diagnostic.must_teach(code)
}

/// Are we allowed to use features from the Rust 2018 edition?
pub fn rust_2018(&self) -> bool {
self.opts.edition >= Edition::Edition2018
}

pub fn edition(&self) -> Edition {
/// What is the edition of the "local crate" being compiled?
///
/// You should not call this except as a last resort. It is better
/// to do `span.edition()` instead, which gives the edition for a
/// particular span: that way, when you are looking at code
/// creating a macro from a Rust 2015 crate, you will use the Rust
/// 2015 Edition rules.
pub fn local_edition(&self) -> Edition {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably just implement Default for Edition.
"Local edition" needs to be kept in global data anyway because it's an "edition of SyntaxContext(0) aka not-a-macro-expansion" and it's set from default-default Edition2015 to self.opts.edition immediately after options are parsed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. True, though I'm not wild about the fact that we rely so heavily on global / TLS data for this stuff.

self.opts.edition
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ where
krate,
&sess.parse_sess,
sess.opts.test,
sess.edition(),
sess.local_edition(),
);
// these need to be set "early" so that expansion sees `quote` if enabled.
sess.init_features(features);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3276,7 +3276,7 @@ impl<'a> Resolver<'a> {
if prev_name == keywords::Extern.name() ||
prev_name == keywords::CrateRoot.name() &&
self.session.features_untracked().extern_absolute_paths &&
self.session.rust_2018() {
path_span.edition().rust_2018() {
// `::extern_crate::a::b`
let crate_id = self.crate_loader.process_path_extern(name, ident.span);
let crate_root =
Expand Down Expand Up @@ -3446,7 +3446,7 @@ impl<'a> Resolver<'a> {

fn lint_path_starts_with_module(&self, id: NodeId, span: Span) {
// In the 2018 edition this lint is a hard error, so nothing to do
if self.session.rust_2018() {
if span.edition().rust_2018() {
return
}
// In the 2015 edition there's no use in emitting lints unless the
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
module_path[0].name == keywords::Extern.name()) {
let is_extern = module_path[0].name == keywords::Extern.name() ||
(self.session.features_untracked().extern_absolute_paths &&
self.session.rust_2018());
span.edition().rust_2018());
match directive.subclass {
GlobImport { .. } if is_extern => {
return Some((directive.span,
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// this case used to be allowed by the compiler,
// so we do a future-compat lint here for the 2015 edition
// (see https://github.com/rust-lang/rust/issues/46906)
if self.tcx.sess.rust_2018() {
span_err!(self.tcx.sess, span, E0908,
"the type of this value must be known \
to call a method on a raw pointer on it");
if span.edition().rust_2018() {
span_err!(self.tcx.sess, span, E0908,
"the type of this value must be known \
to call a method on a raw pointer on it");
} else {
self.tcx.lint_node(
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
Expand Down
5 changes: 5 additions & 0 deletions src/libsyntax_pos/edition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ impl Edition {
Edition::Edition2018 => false,
}
}

/// Is this at least 2018?
pub fn rust_2018(self) -> bool {
self >= Edition::Edition2018
}
}

impl FromStr for Edition {
Expand Down
39 changes: 39 additions & 0 deletions src/test/ui/rust-2018/auxiliary/inject-2015-use-root-module-lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// this is a rust 2015 crate

#[macro_export]
macro_rules! inject_me_at_the_root {
($name1:ident, $name2:ident) => {
mod $name1 {
pub(crate) const THE_CONSTANT: u32 = 22;
}

fn $name2() -> u32 {
// Key point: this `use` statement -- in Rust 2018 --
// would be an error. But because this crate is in Rust
// 2015, it works, even when executed from a Rust 2018
// environment.
use $name1::THE_CONSTANT;
THE_CONSTANT
}
}
}

#[macro_export]
macro_rules! print_me {
($p:path) => {
{
use $p as V;
println!("{}", V);
}
}
}
29 changes: 29 additions & 0 deletions src/test/ui/rust-2018/inject-2015-use-root-module-path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags:--edition 2018
// aux-build:inject-2015-use-root-module-lib.rs

// The macro `inject_me_at_the_root!` generates some code that uses
// `use x::y` to name the global item `x`. In Rust 2018, that should
// be `use crate::x::y`, but we test here that we still accept it,
// as `inject_2015_lib` is in the 2015 edition.

#[macro_use]
extern crate inject_2015_use_root_module_lib;

inject_me_at_the_root!(x, y);

fn main() {
println!("Hello, world: {}", y());

// This path comes out as an error, because `x::y` comes from Rust 2018
print_me!(x::y); //~ ERROR unresolved import `x::y`
}
29 changes: 29 additions & 0 deletions src/test/ui/rust-2018/inject-2015-use-root-module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags:--edition 2018
// aux-build:inject-2015-use-root-module-lib.rs
// run-pass

// The macro `inject_me_at_the_root!` generates some code that uses
// `use x::y` to name the global item `x`. In Rust 2018, that should
// be `use crate::x::y`, but we test here that we still accept it,
// as `inject_2015_lib` is in the 2015 edition.

#[macro_use]
extern crate inject_2015_use_root_module_lib;

inject_me_at_the_root!(x, y);

fn main() {
println!("Hello, world: {}", y());

print_me!(crate::x::y);
}