Rollup merge of #48014 - Manishearth:stealing-chickens-on-the-internet, r=nikomatsakis
Implement RFC 2052 (Epochs) This adds -Zepochs and uses it for tyvar_behind_raw_pointer (#46906) When we move this to --epoch=XXX, we'll need to gate the 2018 epoch on nightly, but not the 2015 one. I can make these changes here itself though it's kinda pointless given that the entire flag is nightly-only. r? @nikomatsakis @aturon cc #44581 (epoch tracking) cc #46906 (tyvar_behind_raw_pointer)
This commit is contained in:
commit
6908fb762d
@ -58,6 +58,7 @@
|
||||
#![feature(macro_vis_matcher)]
|
||||
#![feature(match_default_bindings)]
|
||||
#![feature(never_type)]
|
||||
#![feature(non_exhaustive)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(quote)]
|
||||
#![feature(refcell_replace_swap)]
|
||||
|
@ -112,6 +112,31 @@ pub enum OutputType {
|
||||
DepInfo,
|
||||
}
|
||||
|
||||
/// The epoch of the compiler (RFC 2052)
|
||||
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub enum Epoch {
|
||||
// epochs must be kept in order, newest to oldest
|
||||
|
||||
/// The 2015 epoch
|
||||
Epoch2015,
|
||||
/// The 2018 epoch
|
||||
Epoch2018,
|
||||
|
||||
// when adding new epochs, be sure to update:
|
||||
//
|
||||
// - the list in the `parse_epoch` static
|
||||
// - the match in the `parse_epoch` function
|
||||
// - add a `rust_####()` function to the session
|
||||
// - update the enum in Cargo's sources as well
|
||||
//
|
||||
// When -Zepoch becomes --epoch, there will
|
||||
// also be a check for the epoch being nightly-only
|
||||
// somewhere. That will need to be updated
|
||||
// whenever we're stabilizing/introducing a new epoch
|
||||
// as well as changing the default Cargo template.
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(enum self::OutputType {
|
||||
Bitcode,
|
||||
Assembly,
|
||||
@ -783,11 +808,13 @@ macro_rules! options {
|
||||
Some("`string` or `string=string`");
|
||||
pub const parse_lto: Option<&'static str> =
|
||||
Some("one of `thin`, `fat`, or omitted");
|
||||
pub const parse_epoch: Option<&'static str> =
|
||||
Some("one of: `2015`, `2018`");
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod $mod_set {
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto, Epoch};
|
||||
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -991,6 +1018,15 @@ macro_rules! options {
|
||||
};
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool {
|
||||
match v {
|
||||
Some("2015") => *slot = Epoch::Epoch2015,
|
||||
Some("2018") => *slot = Epoch::Epoch2018,
|
||||
_ => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
) }
|
||||
|
||||
@ -1278,6 +1314,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
`everybody_loops` (all function bodies replaced with `loop {}`),
|
||||
`hir` (the HIR), `hir,identified`, or
|
||||
`hir,typed` (HIR with types for each node)."),
|
||||
epoch: Epoch = (Epoch::Epoch2015, parse_epoch, [TRACKED],
|
||||
"The epoch to build Rust with. Newer epochs may include features
|
||||
that require breaking changes. The default epoch is 2015 (the first
|
||||
epoch). Crates compiled with different epochs can be linked together."),
|
||||
}
|
||||
|
||||
pub fn default_lib_output() -> CrateType {
|
||||
@ -2069,7 +2109,7 @@ mod dep_tracking {
|
||||
use std::path::PathBuf;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use super::{Passes, CrateType, OptLevel, DebugInfoLevel, Lto,
|
||||
OutputTypes, Externs, ErrorOutputType, Sanitizer};
|
||||
OutputTypes, Externs, ErrorOutputType, Sanitizer, Epoch};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
|
||||
@ -2131,6 +2171,7 @@ mod dep_tracking {
|
||||
impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
|
||||
impl_dep_tracking_hash_via_hash!(Sanitizer);
|
||||
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
|
||||
impl_dep_tracking_hash_via_hash!(Epoch);
|
||||
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!(String);
|
||||
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
|
||||
|
@ -19,7 +19,7 @@ use lint;
|
||||
use middle::allocator::AllocatorKind;
|
||||
use middle::dependency_format;
|
||||
use session::search_paths::PathKind;
|
||||
use session::config::{BorrowckMode, DebugInfoLevel, OutputType};
|
||||
use session::config::{BorrowckMode, DebugInfoLevel, OutputType, Epoch};
|
||||
use ty::tls;
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
use util::common::{duration_to_secs_str, ErrorReported};
|
||||
@ -864,6 +864,11 @@ impl Session {
|
||||
pub fn teach(&self, code: &DiagnosticId) -> bool {
|
||||
self.opts.debugging_opts.teach && !self.parse_sess.span_diagnostic.code_emitted(code)
|
||||
}
|
||||
|
||||
/// Are we allowed to use features from the Rust 2018 epoch?
|
||||
pub fn rust_2018(&self) -> bool {
|
||||
self.opts.debugging_opts.epoch >= Epoch::Epoch2018
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_session(sopts: config::Options,
|
||||
|
@ -326,13 +326,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
if reached_raw_pointer
|
||||
&& !self.tcx.sess.features.borrow().arbitrary_self_types {
|
||||
// this case used to be allowed by the compiler,
|
||||
// so we do a future-compat lint here
|
||||
// so we do a future-compat lint here for the 2015 epoch
|
||||
// (see https://github.com/rust-lang/rust/issues/46906)
|
||||
self.tcx.lint_node(
|
||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
&format!("the type of this value must be known in this context"));
|
||||
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");
|
||||
} else {
|
||||
self.tcx.lint_node(
|
||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
&format!("the type of this value must be known in this context"));
|
||||
}
|
||||
} else {
|
||||
let t = self.structurally_resolved_type(span, final_ty);
|
||||
assert_eq!(t, self.tcx.types.err);
|
||||
|
@ -4698,6 +4698,55 @@ element type `T`. Also note that the error is conservatively reported even when
|
||||
the alignment of the zero-sized type is less than or equal to the data field's
|
||||
alignment.
|
||||
"##,
|
||||
|
||||
|
||||
E0908: r##"
|
||||
A method was called on a raw pointer whose inner type wasn't completely known.
|
||||
|
||||
For example, you may have done something like:
|
||||
|
||||
```compile_fail
|
||||
# #![deny(warnings)]
|
||||
let foo = &1;
|
||||
let bar = foo as *const _;
|
||||
if bar.is_null() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Here, the type of `bar` isn't known; it could be a pointer to anything. Instead,
|
||||
specify a type for the pointer (preferably something that makes sense for the
|
||||
thing you're pointing to):
|
||||
|
||||
```
|
||||
let foo = &1;
|
||||
let bar = foo as *const i32;
|
||||
if bar.is_null() {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Even though `is_null()` exists as a method on any raw pointer, Rust shows this
|
||||
error because Rust allows for `self` to have arbitrary types (behind the
|
||||
arbitrary_self_types feature flag).
|
||||
|
||||
This means that someone can specify such a function:
|
||||
|
||||
```ignore (cannot-doctest-feature-doesnt-exist-yet)
|
||||
impl Foo {
|
||||
fn is_null(self: *const Self) -> bool {
|
||||
// do something else
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
and now when you call `.is_null()` on a raw pointer to `Foo`, there's ambiguity.
|
||||
|
||||
Given that we don't know what type the pointer is, and there's potential
|
||||
ambiguity for some types, we disallow calling methods on raw pointers when
|
||||
the type is unknown.
|
||||
"##,
|
||||
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
|
23
src/test/compile-fail/epoch-raw-pointer-method-2015.rs
Normal file
23
src/test/compile-fail/epoch-raw-pointer-method-2015.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2012 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.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: -Zepoch=2015 -Zunstable-options
|
||||
|
||||
// tests that epochs work with the tyvar warning-turned-error
|
||||
|
||||
#[deny(warnings)]
|
||||
fn main() {
|
||||
let x = 0;
|
||||
let y = &x as *const _;
|
||||
let _ = y.is_null();
|
||||
//~^ error: the type of this value must be known in this context [tyvar_behind_raw_pointer]
|
||||
//~^^ warning: this was previously accepted
|
||||
}
|
22
src/test/compile-fail/epoch-raw-pointer-method-2018.rs
Normal file
22
src/test/compile-fail/epoch-raw-pointer-method-2018.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2012 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.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: -Zepoch=2018 -Zunstable-options
|
||||
|
||||
// tests that epochs work with the tyvar warning-turned-error
|
||||
|
||||
#[deny(warnings)]
|
||||
fn main() {
|
||||
let x = 0;
|
||||
let y = &x as *const _;
|
||||
let _ = y.is_null();
|
||||
//~^ error: the type of this value must be known to call a method on a raw pointer on it [E0908]
|
||||
}
|
Loading…
Reference in New Issue
Block a user