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:
bors 2019-07-13 17:11:36 +00:00
commit 69656fa4cb
32 changed files with 313 additions and 88 deletions

View file

@ -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)",

View file

@ -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(),
));
}
});

View file

@ -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)]

View file

@ -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(_, _) => {

View file

@ -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,
}
}

View file

@ -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()))

View file

@ -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,

View file

@ -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" }

View file

@ -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]

View file

@ -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;

View file

@ -1,4 +1,4 @@
use syntax::{register_diagnostic, register_diagnostics};
use syntax::register_diagnostics;
register_diagnostics! {
E0721, // `await` keyword

View file

@ -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##"

View file

@ -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(_)) => {

View file

@ -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

View file

@ -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();

View file

@ -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)]

View file

@ -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)
}
};

View file

@ -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! {
/*

View file

@ -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! {

View file

@ -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

View file

@ -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};

View file

@ -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;

View file

@ -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)
}

View file

@ -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;
}
}

View file

@ -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 })*
)
}

View file

@ -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)]

View file

@ -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) {

View file

@ -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.

View file

@ -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 });

View file

@ -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::<&[()]>());
}

View 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

View 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