Auto merge of #62659 - Centril:rollup-90oz643, r=Centril
Rollup of 5 pull requests Successful merges: - #62577 (Add an AtomicCell abstraction) - #62585 (Make struct_tail normalize when possible) - #62604 (Handle errors during error recovery gracefully) - #62636 (rustbuild: Improve assert about building tools once) - #62651 (Make some rustc macros more hygienic) Failed merges: r? @ghost
This commit is contained in:
commit
69656fa4cb
32 changed files with 313 additions and 88 deletions
|
|
@ -3018,6 +3018,7 @@ name = "rustc_data_structures"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"graphviz 0.0.0",
|
||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
|||
|
|
@ -109,36 +109,63 @@ impl Step for ToolBuild {
|
|||
continue
|
||||
}
|
||||
|
||||
// Don't worry about libs that turn out to be host dependencies
|
||||
// or build scripts, we only care about target dependencies that
|
||||
// are in `deps`.
|
||||
if let Some(maybe_target) = val.1
|
||||
.parent() // chop off file name
|
||||
.and_then(|p| p.parent()) // chop off `deps`
|
||||
.and_then(|p| p.parent()) // chop off `release`
|
||||
.and_then(|p| p.file_name())
|
||||
.and_then(|p| p.to_str())
|
||||
{
|
||||
if maybe_target != &*target {
|
||||
continue
|
||||
// Don't worry about compiles that turn out to be host
|
||||
// dependencies or build scripts. To skip these we look for
|
||||
// anything that goes in `.../release/deps` but *doesn't* go in
|
||||
// `$target/release/deps`. This ensure that outputs in
|
||||
// `$target/release` are still considered candidates for
|
||||
// deduplication.
|
||||
if let Some(parent) = val.1.parent() {
|
||||
if parent.ends_with("release/deps") {
|
||||
let maybe_target = parent
|
||||
.parent()
|
||||
.and_then(|p| p.parent())
|
||||
.and_then(|p| p.file_name())
|
||||
.and_then(|p| p.to_str())
|
||||
.unwrap();
|
||||
if maybe_target != &*target {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record that we've built an artifact for `id`, and if one was
|
||||
// already listed then we need to see if we reused the same
|
||||
// artifact or produced a duplicate.
|
||||
let mut artifacts = builder.tool_artifacts.borrow_mut();
|
||||
let prev_artifacts = artifacts
|
||||
.entry(target)
|
||||
.or_default();
|
||||
if let Some(prev) = prev_artifacts.get(&*id) {
|
||||
if prev.1 != val.1 {
|
||||
duplicates.push((
|
||||
id.to_string(),
|
||||
val,
|
||||
prev.clone(),
|
||||
));
|
||||
let prev = match prev_artifacts.get(&*id) {
|
||||
Some(prev) => prev,
|
||||
None => {
|
||||
prev_artifacts.insert(id.to_string(), val);
|
||||
continue;
|
||||
}
|
||||
return
|
||||
};
|
||||
if prev.1 == val.1 {
|
||||
return; // same path, same artifact
|
||||
}
|
||||
prev_artifacts.insert(id.to_string(), val);
|
||||
|
||||
// If the paths are different and one of them *isn't* inside of
|
||||
// `release/deps`, then it means it's probably in
|
||||
// `$target/release`, or it's some final artifact like
|
||||
// `libcargo.rlib`. In these situations Cargo probably just
|
||||
// copied it up from `$target/release/deps/libcargo-xxxx.rlib`,
|
||||
// so if the features are equal we can just skip it.
|
||||
let prev_no_hash = prev.1.parent().unwrap().ends_with("release/deps");
|
||||
let val_no_hash = val.1.parent().unwrap().ends_with("release/deps");
|
||||
if prev.2 == val.2 || !prev_no_hash || !val_no_hash {
|
||||
return;
|
||||
}
|
||||
|
||||
// ... and otherwise this looks like we duplicated some sort of
|
||||
// compilation, so record it to generate an error later.
|
||||
duplicates.push((
|
||||
id.to_string(),
|
||||
val,
|
||||
prev.clone(),
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@
|
|||
#![feature(optin_builtin_traits)]
|
||||
#![feature(range_is_empty)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(specialization)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
|
@ -57,7 +56,6 @@
|
|||
#![feature(trace_macros)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(vec_remove_item)]
|
||||
#![feature(step_trait)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(integer_atomics)]
|
||||
#![feature(test)]
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||
return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
|
||||
}
|
||||
|
||||
let unsized_part = tcx.struct_tail(pointee);
|
||||
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
|
||||
let metadata = match unsized_part.sty {
|
||||
ty::Foreign(..) => {
|
||||
return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
|
||||
|
|
@ -1664,7 +1664,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
ty::Ref(_, pointee, _) |
|
||||
ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
let non_zero = !ty.is_unsafe_ptr();
|
||||
let tail = tcx.struct_tail(pointee);
|
||||
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
|
||||
match tail.sty {
|
||||
ty::Param(_) | ty::Projection(_) => {
|
||||
debug_assert!(tail.has_param_types() || tail.has_self_ty());
|
||||
|
|
@ -2015,7 +2015,7 @@ where
|
|||
}));
|
||||
}
|
||||
|
||||
match tcx.struct_tail(pointee).sty {
|
||||
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).sty {
|
||||
ty::Slice(_) |
|
||||
ty::Str => tcx.types.usize,
|
||||
ty::Dynamic(_, _) => {
|
||||
|
|
|
|||
|
|
@ -257,10 +257,46 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
false
|
||||
}
|
||||
|
||||
/// Returns the deeply last field of nested structures, or the same type,
|
||||
/// if not a structure at all. Corresponds to the only possible unsized
|
||||
/// field, and its type can be used to determine unsizing strategy.
|
||||
pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
/// Attempts to returns the deeply last field of nested structures, but
|
||||
/// does not apply any normalization in its search. Returns the same type
|
||||
/// if input `ty` is not a structure at all.
|
||||
pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx>
|
||||
{
|
||||
let tcx = self;
|
||||
tcx.struct_tail_with_normalize(ty, |ty| ty)
|
||||
}
|
||||
|
||||
/// Returns the deeply last field of nested structures, or the same type if
|
||||
/// not a structure at all. Corresponds to the only possible unsized field,
|
||||
/// and its type can be used to determine unsizing strategy.
|
||||
///
|
||||
/// Should only be called if `ty` has no inference variables and does not
|
||||
/// need its lifetimes preserved (e.g. as part of codegen); otherwise
|
||||
/// normalization attempt may cause compiler bugs.
|
||||
pub fn struct_tail_erasing_lifetimes(self,
|
||||
ty: Ty<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
let tcx = self;
|
||||
tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty))
|
||||
}
|
||||
|
||||
/// Returns the deeply last field of nested structures, or the same type if
|
||||
/// not a structure at all. Corresponds to the only possible unsized field,
|
||||
/// and its type can be used to determine unsizing strategy.
|
||||
///
|
||||
/// This is parameterized over the normalization strategy (i.e. how to
|
||||
/// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
|
||||
/// function to indicate no normalization should take place.
|
||||
///
|
||||
/// See also `struct_tail_erasing_lifetimes`, which is suitable for use
|
||||
/// during codegen.
|
||||
pub fn struct_tail_with_normalize(self,
|
||||
mut ty: Ty<'tcx>,
|
||||
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
loop {
|
||||
match ty.sty {
|
||||
ty::Adt(def, substs) => {
|
||||
|
|
@ -281,6 +317,15 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
ty::Projection(_) | ty::Opaque(..) => {
|
||||
let normalized = normalize(ty);
|
||||
if ty == normalized {
|
||||
return ty;
|
||||
} else {
|
||||
ty = normalized;
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
|
|
@ -294,10 +339,35 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// structure definitions.
|
||||
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
|
||||
/// whereas struct_tail produces `T`, and `Trait`, respectively.
|
||||
pub fn struct_lockstep_tails(self,
|
||||
source: Ty<'tcx>,
|
||||
target: Ty<'tcx>)
|
||||
-> (Ty<'tcx>, Ty<'tcx>) {
|
||||
///
|
||||
/// Should only be called if the types have no inference variables and do
|
||||
/// not need their lifetimes preserved (e.g. as part of codegen); otherwise
|
||||
/// normalization attempt may cause compiler bugs.
|
||||
pub fn struct_lockstep_tails_erasing_lifetimes(self,
|
||||
source: Ty<'tcx>,
|
||||
target: Ty<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>)
|
||||
-> (Ty<'tcx>, Ty<'tcx>)
|
||||
{
|
||||
let tcx = self;
|
||||
tcx.struct_lockstep_tails_with_normalize(
|
||||
source, target, |ty| tcx.normalize_erasing_regions(param_env, ty))
|
||||
}
|
||||
|
||||
/// Same as applying struct_tail on `source` and `target`, but only
|
||||
/// keeps going as long as the two types are instances of the same
|
||||
/// structure definitions.
|
||||
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
|
||||
/// whereas struct_tail produces `T`, and `Trait`, respectively.
|
||||
///
|
||||
/// See also `struct_lockstep_tails_erasing_lifetimes`, which is suitable for use
|
||||
/// during codegen.
|
||||
pub fn struct_lockstep_tails_with_normalize(self,
|
||||
source: Ty<'tcx>,
|
||||
target: Ty<'tcx>,
|
||||
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>)
|
||||
-> (Ty<'tcx>, Ty<'tcx>)
|
||||
{
|
||||
let (mut a, mut b) = (source, target);
|
||||
loop {
|
||||
match (&a.sty, &b.sty) {
|
||||
|
|
@ -319,6 +389,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
break;
|
||||
}
|
||||
},
|
||||
(ty::Projection(_), _) | (ty::Opaque(..), _) |
|
||||
(_, ty::Projection(_)) | (_, ty::Opaque(..)) => {
|
||||
// If either side is a projection, attempt to
|
||||
// progress via normalization. (Should be safe to
|
||||
// apply to both sides as normalization is
|
||||
// idempotent.)
|
||||
let a_norm = normalize(a);
|
||||
let b_norm = normalize(b);
|
||||
if a == a_norm && b == b_norm {
|
||||
break;
|
||||
} else {
|
||||
a = a_norm;
|
||||
b = b_norm;
|
||||
}
|
||||
}
|
||||
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,8 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
|
|||
target: Ty<'tcx>,
|
||||
old_info: Option<Cx::Value>,
|
||||
) -> Cx::Value {
|
||||
let (source, target) = cx.tcx().struct_lockstep_tails(source, target);
|
||||
let (source, target) =
|
||||
cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, cx.param_env());
|
||||
match (&source.sty, &target.sty) {
|
||||
(&ty::Array(_, len), &ty::Slice(_)) => {
|
||||
cx.const_usize(len.unwrap_usize(cx.tcx()))
|
||||
|
|
|
|||
|
|
@ -77,11 +77,12 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
|
|||
}
|
||||
|
||||
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
|
||||
if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let tail = self.tcx().struct_tail(ty);
|
||||
let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env);
|
||||
match tail.sty {
|
||||
ty::Foreign(..) => false,
|
||||
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ lazy_static = "1"
|
|||
serialize = { path = "../libserialize" }
|
||||
graphviz = { path = "../libgraphviz" }
|
||||
cfg-if = "0.1.2"
|
||||
crossbeam-utils = { version = "0.6.5", features = ["nightly"] }
|
||||
stable_deref_trait = "1.0.0"
|
||||
rayon = { version = "0.2.0", package = "rustc-rayon" }
|
||||
rayon-core = { version = "0.2.0", package = "rustc-rayon-core" }
|
||||
|
|
|
|||
|
|
@ -57,12 +57,13 @@ impl Idx for u32 {
|
|||
/// `u32::MAX`. You can also customize things like the `Debug` impl,
|
||||
/// what traits are derived, and so forth via the macro.
|
||||
#[macro_export]
|
||||
#[allow_internal_unstable(step_trait, rustc_attrs)]
|
||||
macro_rules! newtype_index {
|
||||
// ---- public rules ----
|
||||
|
||||
// Use default constants
|
||||
($(#[$attrs:meta])* $v:vis struct $name:ident { .. }) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
// Leave out derives marker so we can use its absence to ensure it comes first
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$name]
|
||||
|
|
@ -74,7 +75,7 @@ macro_rules! newtype_index {
|
|||
|
||||
// Define any constants
|
||||
($(#[$attrs:meta])* $v:vis struct $name:ident { $($tokens:tt)+ }) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
// Leave out derives marker so we can use its absence to ensure it comes first
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$name]
|
||||
|
|
@ -258,7 +259,7 @@ macro_rules! newtype_index {
|
|||
}
|
||||
}
|
||||
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@handle_debug
|
||||
@derives [$($derives,)*]
|
||||
@type [$type]
|
||||
|
|
@ -294,7 +295,7 @@ macro_rules! newtype_index {
|
|||
@derives [$_derive:ident, $($derives:ident,)*]
|
||||
@type [$type:ident]
|
||||
@debug_format [$debug_format:tt]) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@handle_debug
|
||||
@derives [$($derives,)*]
|
||||
@type [$type]
|
||||
|
|
@ -309,7 +310,7 @@ macro_rules! newtype_index {
|
|||
@debug_format [$debug_format:tt]
|
||||
derive [$($derives:ident),*]
|
||||
$($tokens:tt)*) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
@max [$max]
|
||||
|
|
@ -329,7 +330,7 @@ macro_rules! newtype_index {
|
|||
derive [$($derives:ident,)+]
|
||||
ENCODABLE = custom
|
||||
$($tokens:tt)*) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@attrs [$(#[$attrs])*]
|
||||
@derives [$($derives,)+]
|
||||
@type [$type]
|
||||
|
|
@ -348,7 +349,7 @@ macro_rules! newtype_index {
|
|||
@debug_format [$debug_format:tt]
|
||||
derive [$($derives:ident,)+]
|
||||
$($tokens:tt)*) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives [$($derives,)+ RustcEncodable,]
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
@ -356,7 +357,7 @@ macro_rules! newtype_index {
|
|||
@vis [$v]
|
||||
@debug_format [$debug_format]
|
||||
$($tokens)*);
|
||||
newtype_index!(@decodable $type);
|
||||
$crate::newtype_index!(@decodable $type);
|
||||
);
|
||||
|
||||
// The case where no derives are added, but encodable is overridden. Don't
|
||||
|
|
@ -368,7 +369,7 @@ macro_rules! newtype_index {
|
|||
@debug_format [$debug_format:tt]
|
||||
ENCODABLE = custom
|
||||
$($tokens:tt)*) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives []
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
@ -385,7 +386,7 @@ macro_rules! newtype_index {
|
|||
@vis [$v:vis]
|
||||
@debug_format [$debug_format:tt]
|
||||
$($tokens:tt)*) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives [RustcEncodable,]
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
@ -393,7 +394,7 @@ macro_rules! newtype_index {
|
|||
@vis [$v]
|
||||
@debug_format [$debug_format]
|
||||
$($tokens)*);
|
||||
newtype_index!(@decodable $type);
|
||||
$crate::newtype_index!(@decodable $type);
|
||||
);
|
||||
|
||||
(@decodable $type:ident) => (
|
||||
|
|
@ -420,7 +421,7 @@ macro_rules! newtype_index {
|
|||
@vis [$v:vis]
|
||||
@debug_format [$debug_format:tt]
|
||||
$name:ident = $constant:expr) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives [$($derives,)*]
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
@ -439,7 +440,7 @@ macro_rules! newtype_index {
|
|||
@debug_format [$debug_format:tt]
|
||||
$(#[doc = $doc:expr])*
|
||||
const $name:ident = $constant:expr) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives [$($derives,)*]
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
@ -458,7 +459,7 @@ macro_rules! newtype_index {
|
|||
@debug_format [$debug_format:tt]
|
||||
MAX = $max:expr,
|
||||
$($tokens:tt)*) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives [$($derives,)*]
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
@ -477,7 +478,7 @@ macro_rules! newtype_index {
|
|||
@debug_format [$_debug_format:tt]
|
||||
DEBUG_FORMAT = $debug_format:tt,
|
||||
$($tokens:tt)*) => (
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives [$($derives,)*]
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
@ -499,7 +500,7 @@ macro_rules! newtype_index {
|
|||
$($tokens:tt)*) => (
|
||||
$(#[doc = $doc])*
|
||||
pub const $name: $type = $type::from_u32_const($constant);
|
||||
newtype_index!(
|
||||
$crate::newtype_index!(
|
||||
@derives [$($derives,)*]
|
||||
@attrs [$(#[$attrs])*]
|
||||
@type [$type]
|
||||
|
|
|
|||
|
|
@ -67,6 +67,51 @@ cfg_if! {
|
|||
use std::ops::Add;
|
||||
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
|
||||
|
||||
/// This is a single threaded variant of AtomicCell provided by crossbeam.
|
||||
/// Unlike `Atomic` this is intended for all `Copy` types,
|
||||
/// but it lacks the explicit ordering arguments.
|
||||
#[derive(Debug)]
|
||||
pub struct AtomicCell<T: Copy>(Cell<T>);
|
||||
|
||||
impl<T: Copy> AtomicCell<T> {
|
||||
#[inline]
|
||||
pub fn new(v: T) -> Self {
|
||||
AtomicCell(Cell::new(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
self.0.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy> AtomicCell<T> {
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0.into_inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn load(&self) -> T {
|
||||
self.0.get()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn store(&self, val: T) {
|
||||
self.0.set(val)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn swap(&self, val: T) -> T {
|
||||
self.0.replace(val)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
|
||||
/// It differs from `AtomicCell` in that it has explicit ordering arguments
|
||||
/// and is only intended for use with the native atomic types.
|
||||
/// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
|
||||
/// as it's not intended to be used separately.
|
||||
#[derive(Debug)]
|
||||
pub struct Atomic<T: Copy>(Cell<T>);
|
||||
|
||||
|
|
@ -77,7 +122,8 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + PartialEq> Atomic<T> {
|
||||
impl<T: Copy> Atomic<T> {
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0.into_inner()
|
||||
}
|
||||
|
|
@ -92,10 +138,14 @@ cfg_if! {
|
|||
self.0.set(val)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn swap(&self, val: T, _: Ordering) -> T {
|
||||
self.0.replace(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + PartialEq> Atomic<T> {
|
||||
#[inline]
|
||||
pub fn compare_exchange(&self,
|
||||
current: T,
|
||||
new: T,
|
||||
|
|
@ -113,6 +163,7 @@ cfg_if! {
|
|||
}
|
||||
|
||||
impl<T: Add<Output=T> + Copy> Atomic<T> {
|
||||
#[inline]
|
||||
pub fn fetch_add(&self, val: T, _: Ordering) -> T {
|
||||
let old = self.0.get();
|
||||
self.0.set(old + val);
|
||||
|
|
@ -271,6 +322,8 @@ cfg_if! {
|
|||
|
||||
pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
|
||||
|
||||
pub use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
pub use std::sync::Arc as Lrc;
|
||||
pub use std::sync::Weak as Weak;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use syntax::{register_diagnostic, register_diagnostics};
|
||||
use syntax::register_diagnostics;
|
||||
|
||||
register_diagnostics! {
|
||||
E0721, // `await` keyword
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
|
||||
use syntax::{register_diagnostics, register_long_diagnostics};
|
||||
|
||||
register_long_diagnostics! {
|
||||
E0454: r##"
|
||||
|
|
|
|||
|
|
@ -270,7 +270,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
dty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// A<Struct> -> A<Trait> conversion
|
||||
let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty);
|
||||
let (src_pointee_ty, dest_pointee_ty) =
|
||||
self.tcx.struct_lockstep_tails_erasing_lifetimes(sty, dty, self.param_env);
|
||||
|
||||
match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
|
||||
(&ty::Array(_, length), &ty::Slice(_)) => {
|
||||
|
|
|
|||
|
|
@ -146,7 +146,9 @@ for
|
|||
let value = self.ecx.read_immediate(mplace.into())?;
|
||||
// Handle trait object vtables
|
||||
if let Ok(meta) = value.to_meta() {
|
||||
if let ty::Dynamic(..) = self.ecx.tcx.struct_tail(referenced_ty).sty {
|
||||
if let ty::Dynamic(..) =
|
||||
self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.param_env).sty
|
||||
{
|
||||
if let Ok(vtable) = meta.unwrap().to_ptr() {
|
||||
// explitly choose `Immutable` here, since vtables are immutable, even
|
||||
// if the reference of the fat pointer is mutable
|
||||
|
|
|
|||
|
|
@ -361,7 +361,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
|||
"uninitialized data in fat pointer metadata", self.path);
|
||||
let layout = self.ecx.layout_of(value.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
if layout.is_unsized() {
|
||||
let tail = self.ecx.tcx.struct_tail(layout.ty);
|
||||
let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(layout.ty,
|
||||
self.ecx.param_env);
|
||||
match tail.sty {
|
||||
ty::Dynamic(..) => {
|
||||
let vtable = meta.unwrap();
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
|
|||
#![feature(decl_macro)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(never_type)]
|
||||
#![feature(specialization)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(unicode_internals)]
|
||||
#![feature(step_trait)]
|
||||
#![feature(slice_concat_ext)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(try_blocks)]
|
||||
|
|
|
|||
|
|
@ -851,12 +851,13 @@ fn find_vtable_types_for_unsizing<'tcx>(
|
|||
target_ty: Ty<'tcx>,
|
||||
) -> (Ty<'tcx>, Ty<'tcx>) {
|
||||
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let type_has_metadata = |ty: Ty<'tcx>| -> bool {
|
||||
use syntax_pos::DUMMY_SP;
|
||||
if ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
|
||||
if ty.is_sized(tcx.at(DUMMY_SP), param_env) {
|
||||
return false;
|
||||
}
|
||||
let tail = tcx.struct_tail(ty);
|
||||
let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);
|
||||
match tail.sty {
|
||||
ty::Foreign(..) => false,
|
||||
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
|
||||
|
|
@ -866,7 +867,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
|
|||
if type_has_metadata(inner_source) {
|
||||
(inner_source, inner_target)
|
||||
} else {
|
||||
tcx.struct_lockstep_tails(inner_source, inner_target)
|
||||
tcx.struct_lockstep_tails_erasing_lifetimes(inner_source, inner_target, param_env)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
|
||||
use syntax::{register_diagnostics, register_long_diagnostics};
|
||||
|
||||
register_long_diagnostics! {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
|
||||
use syntax::{register_diagnostics, register_long_diagnostics};
|
||||
|
||||
register_long_diagnostics! {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use syntax::{register_diagnostic, register_diagnostics, register_long_diagnostics};
|
||||
use syntax::{register_diagnostics, register_long_diagnostics};
|
||||
|
||||
// Error messages for EXXXX errors. Each message should start and end with a
|
||||
// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use crate::spec::Target;
|
|||
use std::fmt;
|
||||
use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
|
||||
|
||||
use rustc_data_structures::newtype_index;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use syntax_pos::symbol::{sym, Symbol};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,7 @@
|
|||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(nll)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(step_trait)]
|
||||
|
||||
#![deny(rust_2018_idioms)]
|
||||
#![deny(unused_lifetimes)]
|
||||
|
|
@ -23,8 +21,5 @@
|
|||
#[allow(unused_extern_crates)]
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_data_structures;
|
||||
|
||||
pub mod abi;
|
||||
pub mod spec;
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
|
|||
/// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
|
||||
/// for examples of where this comes up,.
|
||||
fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
|
||||
match fcx.tcx.struct_tail(ty).sty {
|
||||
match fcx.tcx.struct_tail_without_normalization(ty).sty {
|
||||
ty::Slice(_) | ty::Str | ty::Dynamic(..) => {
|
||||
ExpectRvalueLikeUnsized(ty)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,7 +366,8 @@ fn check_item_type(
|
|||
|
||||
let mut forbid_unsized = true;
|
||||
if allow_foreign_ty {
|
||||
if let ty::Foreign(_) = fcx.tcx.struct_tail(item_ty).sty {
|
||||
let tail = fcx.tcx.struct_tail_erasing_lifetimes(item_ty, fcx.param_env);
|
||||
if let ty::Foreign(_) = tail.sty {
|
||||
forbid_unsized = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,19 +170,19 @@ macro_rules! help {
|
|||
#[macro_export]
|
||||
macro_rules! register_diagnostics {
|
||||
($($code:tt),*) => (
|
||||
$(register_diagnostic! { $code })*
|
||||
$($crate::register_diagnostic! { $code })*
|
||||
);
|
||||
($($code:tt),*,) => (
|
||||
$(register_diagnostic! { $code })*
|
||||
$($crate::register_diagnostic! { $code })*
|
||||
)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! register_long_diagnostics {
|
||||
($($code:tt: $description:tt),*) => (
|
||||
$(register_diagnostic! { $code, $description })*
|
||||
$($crate::register_diagnostic! { $code, $description })*
|
||||
);
|
||||
($($code:tt: $description:tt),*,) => (
|
||||
$(register_diagnostic! { $code, $description })*
|
||||
$($crate::register_diagnostic! { $code, $description })*
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,7 @@
|
|||
#![feature(label_break_value)]
|
||||
#![feature(mem_take)]
|
||||
#![feature(nll)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(step_trait)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(unicode_internals)]
|
||||
|
||||
|
|
|
|||
|
|
@ -7410,10 +7410,13 @@ impl<'a> Parser<'a> {
|
|||
} else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
|
||||
let ident = self.parse_ident().unwrap();
|
||||
self.bump(); // `(`
|
||||
let kw_name = if let Ok(Some(_)) = self.parse_self_arg_with_attrs() {
|
||||
"method"
|
||||
} else {
|
||||
"function"
|
||||
let kw_name = match self.parse_self_arg_with_attrs() {
|
||||
Ok(Some(_)) => "method",
|
||||
Ok(None) => "function",
|
||||
Err(mut err) => {
|
||||
err.cancel();
|
||||
"function"
|
||||
}
|
||||
};
|
||||
self.consume_block(token::Paren);
|
||||
let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use syntax::{register_diagnostic, register_long_diagnostics};
|
||||
use syntax::register_long_diagnostics;
|
||||
|
||||
// Error messages for EXXXX errors.
|
||||
// Each message should start and end with a new line, and be wrapped to 80 characters.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#![feature(rustc_attrs, rustc_private, step_trait)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
#[macro_use] extern crate rustc_data_structures;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate serialize as rustc_serialize;
|
||||
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::{newtype_index, indexed_vec::Idx};
|
||||
|
||||
newtype_index!(struct MyIdx { MAX = 0xFFFF_FFFA });
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// rust-lang/rust#60431: This is a scenario where to determine the size of
|
||||
// `&Ref<Obstack>`, we need to know the concrete type of the last field in
|
||||
// `Ref<Obstack>` (i.e. its "struct tail"), and determining that concrete type
|
||||
// requires normalizing `Obstack::Dyn`.
|
||||
//
|
||||
// The old "struct tail" computation did not perform such normalization, and so
|
||||
// the compiler would ICE when trying to figure out if `Ref<Obstack>` is a
|
||||
// dynamically-sized type (DST).
|
||||
|
||||
// run-pass
|
||||
|
||||
use std::mem;
|
||||
|
||||
pub trait Arena {
|
||||
type Dyn : ?Sized;
|
||||
}
|
||||
|
||||
pub struct DynRef {
|
||||
_dummy: [()],
|
||||
}
|
||||
|
||||
pub struct Ref<A: Arena> {
|
||||
_value: u8,
|
||||
_dyn_arena: A::Dyn,
|
||||
}
|
||||
|
||||
pub struct Obstack;
|
||||
|
||||
impl Arena for Obstack {
|
||||
type Dyn = DynRef;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(mem::size_of::<&Ref<Obstack>>(), mem::size_of::<&[()]>());
|
||||
}
|
||||
3
src/test/ui/parser/issue-62546.rs
Normal file
3
src/test/ui/parser/issue-62546.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pub t(#
|
||||
//~^ ERROR missing `fn` or `struct` for function or struct definition
|
||||
//~ ERROR this file contains an un-closed delimiter
|
||||
17
src/test/ui/parser/issue-62546.stderr
Normal file
17
src/test/ui/parser/issue-62546.stderr
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
error: this file contains an un-closed delimiter
|
||||
--> $DIR/issue-62546.rs:3:53
|
||||
|
|
||||
LL | pub t(#
|
||||
| - un-closed delimiter
|
||||
LL |
|
||||
LL |
|
||||
| ^
|
||||
|
||||
error: missing `fn` or `struct` for function or struct definition
|
||||
--> $DIR/issue-62546.rs:1:4
|
||||
|
|
||||
LL | pub t(#
|
||||
| ---^- help: if you meant to call a macro, try: `t!`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue