From e753d2105159397eff162aa3f1f7715f96b5772d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Nov 2018 11:23:34 +0100 Subject: [PATCH 01/27] miri: accept extern types in structs if they are the only field --- src/librustc_mir/interpret/eval_context.rs | 15 ++++++++++++-- src/librustc_mir/interpret/place.rs | 3 ++- src/test/ui/consts/const-eval/issue-55541.rs | 21 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/consts/const-eval/issue-55541.rs diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index bc7ad16dc97bc..48a8d0bbe56d6 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -371,8 +371,19 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc // the last field). Can't have foreign types here, how would we // adjust alignment and size for them? let field = layout.field(self, layout.fields.count() - 1)?; - let (unsized_size, unsized_align) = self.size_and_align_of(metadata, field)? - .expect("Fields cannot be extern types"); + let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? { + Some(size_and_align) => size_and_align, + None => { + // A field with extern type. If this is the only field, + // we treat this struct just the same. Else, this is an error + // (for now). + if layout.fields.count() == 1 { + return Ok(None) + } else { + bug!("Fields cannot be extern types, unless they are the only field") + } + } + }; // FIXME (#26403, #27023): We should be adding padding // to `sized_size` (to accommodate the `unsized_align` diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 3b104e2284fe2..8bd29aff841cf 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -354,7 +354,8 @@ where let (meta, offset) = if field_layout.is_unsized() { // re-use parent metadata to determine dynamic field layout let (_, align) = self.size_and_align_of(base.meta, field_layout)? - .expect("Fields cannot be extern types"); + // If this is an extern type, we fall back to its static size and alignment. + .unwrap_or_else(|| base.layout.size_and_align()); (base.meta, offset.abi_align(align)) } else { // base.meta could be present; we might be accessing a sized field of an unsized diff --git a/src/test/ui/consts/const-eval/issue-55541.rs b/src/test/ui/consts/const-eval/issue-55541.rs new file mode 100644 index 0000000000000..bf8965e836182 --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-55541.rs @@ -0,0 +1,21 @@ +// compile-pass + +// Test that we can handle newtypes wrapping extern types + +#![feature(extern_types, const_transmute)] + +extern "C" { + pub type ExternType; +} +unsafe impl Sync for ExternType {} + +#[repr(transparent)] +pub struct Wrapper(ExternType); + +static MAGIC_FFI_STATIC: u8 = 42; + +pub static MAGIC_FFI_REF: &'static Wrapper = unsafe { + std::mem::transmute(&MAGIC_FFI_STATIC) +}; + +fn main() {} From aca76d42a05c419a539d9b34fa30b88d4cdcadcc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Nov 2018 11:55:39 +0100 Subject: [PATCH 02/27] test for offset and alignment of the sized part, instead of field count --- src/librustc_mir/interpret/eval_context.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 48a8d0bbe56d6..c1c2efdae7516 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -374,13 +374,13 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? { Some(size_and_align) => size_and_align, None => { - // A field with extern type. If this is the only field, - // we treat this struct just the same. Else, this is an error - // (for now). - if layout.fields.count() == 1 { + // A field with extern type. If this field is at offset 0 and the sized + // part makes no alignment constraints, we behave like the underlying + // extern type. + if sized_size == Size::ZERO && sized_align.abi() == 1 { return Ok(None) } else { - bug!("Fields cannot be extern types, unless they are the only field") + bug!("Fields cannot be extern types, unless they are at offset 0") } } }; From bb17f717499132a23e1b54bf3fdd0727c09715ff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Nov 2018 14:43:05 +0100 Subject: [PATCH 03/27] also test with PhantomData --- src/test/ui/consts/const-eval/issue-55541.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/test/ui/consts/const-eval/issue-55541.rs b/src/test/ui/consts/const-eval/issue-55541.rs index bf8965e836182..611fb89341de4 100644 --- a/src/test/ui/consts/const-eval/issue-55541.rs +++ b/src/test/ui/consts/const-eval/issue-55541.rs @@ -4,18 +4,24 @@ #![feature(extern_types, const_transmute)] +use std::marker::PhantomData; + extern "C" { pub type ExternType; } unsafe impl Sync for ExternType {} +static MAGIC_FFI_STATIC: u8 = 42; #[repr(transparent)] pub struct Wrapper(ExternType); - -static MAGIC_FFI_STATIC: u8 = 42; - pub static MAGIC_FFI_REF: &'static Wrapper = unsafe { std::mem::transmute(&MAGIC_FFI_STATIC) }; +#[repr(transparent)] +pub struct Wrapper2(PhantomData>, ExternType); +pub static MAGIC_FFI_REF2: &'static Wrapper2 = unsafe { + std::mem::transmute(&MAGIC_FFI_STATIC) +}; + fn main() {} From 5ebd077f54c735aeb634d18080c9f127016f1c87 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Nov 2018 11:14:21 +0100 Subject: [PATCH 04/27] make it more obvious that the size is not relevant --- src/librustc_mir/interpret/place.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 8bd29aff841cf..3dcd081edf9d9 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -353,9 +353,10 @@ where // Offset may need adjustment for unsized fields let (meta, offset) = if field_layout.is_unsized() { // re-use parent metadata to determine dynamic field layout - let (_, align) = self.size_and_align_of(base.meta, field_layout)? - // If this is an extern type, we fall back to its static size and alignment. - .unwrap_or_else(|| base.layout.size_and_align()); + let align = self.size_and_align_of(base.meta, field_layout)? + .map(|(_, align)| align) + // If this is an extern type, we fall back to its static alignment. + .unwrap_or_else(|| base.layout.align); (base.meta, offset.abi_align(align)) } else { // base.meta could be present; we might be accessing a sized field of an unsized From a6622c265c9a359c277af576c4849a74d476f597 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Nov 2018 11:20:01 +0100 Subject: [PATCH 05/27] note some FIXMEs --- src/librustc_mir/interpret/eval_context.rs | 3 +++ src/librustc_mir/interpret/place.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index c1c2efdae7516..797e0458e5312 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -377,6 +377,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc // A field with extern type. If this field is at offset 0 and the sized // part makes no alignment constraints, we behave like the underlying // extern type. + // FIXME: Once we have made decisions for how to handle size and alignment + // of `extern type`, this should be adapted. It is just a temporary hack + // to get some code to work that probably ought to work. if sized_size == Size::ZERO && sized_align.abi() == 1 { return Ok(None) } else { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 3dcd081edf9d9..c60ae7b4a00c4 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -356,6 +356,9 @@ where let align = self.size_and_align_of(base.meta, field_layout)? .map(|(_, align)| align) // If this is an extern type, we fall back to its static alignment. + // FIXME: Once we have made decisions for how to handle size and alignment + // of `extern type`, this should be adapted. It is just a temporary hack + // to get some code to work that probably ought to work. .unwrap_or_else(|| base.layout.align); (base.meta, offset.abi_align(align)) } else { From ba0bab39e04a13ad996e41a2ef2ca9b83fbb2cf4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 6 Nov 2018 08:41:56 +0100 Subject: [PATCH 06/27] make sure we only guess field alignment at offset 0 --- src/librustc_mir/interpret/eval_context.rs | 7 +++---- src/librustc_mir/interpret/place.rs | 18 +++++++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 797e0458e5312..cca4e8a3ce31a 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -374,13 +374,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? { Some(size_and_align) => size_and_align, None => { - // A field with extern type. If this field is at offset 0 and the sized - // part makes no alignment constraints, we behave like the underlying - // extern type. + // A field with extern type. If this field is at offset 0, we behave + // like the underlying extern type. // FIXME: Once we have made decisions for how to handle size and alignment // of `extern type`, this should be adapted. It is just a temporary hack // to get some code to work that probably ought to work. - if sized_size == Size::ZERO && sized_align.abi() == 1 { + if sized_size == Size::ZERO { return Ok(None) } else { bug!("Fields cannot be extern types, unless they are at offset 0") diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index c60ae7b4a00c4..a836a199f768d 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -353,13 +353,17 @@ where // Offset may need adjustment for unsized fields let (meta, offset) = if field_layout.is_unsized() { // re-use parent metadata to determine dynamic field layout - let align = self.size_and_align_of(base.meta, field_layout)? - .map(|(_, align)| align) - // If this is an extern type, we fall back to its static alignment. - // FIXME: Once we have made decisions for how to handle size and alignment - // of `extern type`, this should be adapted. It is just a temporary hack - // to get some code to work that probably ought to work. - .unwrap_or_else(|| base.layout.align); + let align = match self.size_and_align_of(base.meta, field_layout)? { + Some((_, align)) => align, + None if offset == Size::ZERO => + // An extern type at offset 0, we fall back to its static alignment. + // FIXME: Once we have made decisions for how to handle size and alignment + // of `extern type`, this should be adapted. It is just a temporary hack + // to get some code to work that probably ought to work. + field_layout.align, + None => + bug!("Cannot compute offset for extern type field at non-0 offset"), + }; (base.meta, offset.abi_align(align)) } else { // base.meta could be present; we might be accessing a sized field of an unsized From b7c319c56ae8380aa2ab03d2b9b6702ae43d49b3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Nov 2018 10:43:33 +0100 Subject: [PATCH 07/27] do not panic just because cargo failed --- src/bootstrap/compile.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index cef0849937bf0..71b204b2de985 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -22,7 +22,7 @@ use std::fs::{self, File}; use std::io::BufReader; use std::io::prelude::*; use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; +use std::process::{Command, Stdio, exit}; use std::str; use build_helper::{output, mtime, up_to_date}; @@ -1098,7 +1098,7 @@ pub fn run_cargo(builder: &Builder, }); if !ok { - panic!("cargo must succeed"); + exit(1); } // Ok now we need to actually find all the files listed in `toplevel`. We've From 0c085299344d9af4e9bfd892a15d746b116ebe00 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 5 Nov 2018 15:30:04 +0100 Subject: [PATCH 08/27] A few tweaks to iterations/collecting --- src/librustc/cfg/graphviz.rs | 3 +-- src/librustc/hir/lowering.rs | 3 +-- src/librustc/ty/query/on_disk_cache.rs | 2 +- src/libserialize/hex.rs | 2 +- src/libsyntax_ext/deriving/generic/mod.rs | 18 ++++++++---------- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs index cc4f3f95d079a..650aa39114fad 100644 --- a/src/librustc/cfg/graphviz.rs +++ b/src/librustc/cfg/graphviz.rs @@ -106,8 +106,7 @@ impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG { type Node = Node<'a>; type Edge = Edge<'a>; fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { - let mut v = Vec::new(); - self.graph.each_node(|i, nd| { v.push((i, nd)); true }); + let v: Vec<_> = self.graph.enumerated_nodes().collect(); v.into() } fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dd5d4b8f6afff..4f94b427ec169 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1062,8 +1062,7 @@ impl<'a> LoweringContext<'a> { attrs .iter() .map(|a| self.lower_attr(a)) - .collect::>() - .into() + .collect() } fn lower_attr(&mut self, attr: &Attribute) -> Attribute { diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 54550b8a2055f..7d3ae64f4fcd6 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -281,7 +281,7 @@ impl<'sess> OnDiskCache<'sess> { // otherwise, abort break; } - interpret_alloc_index.reserve(new_n); + interpret_alloc_index.reserve(new_n - n); for idx in n..new_n { let id = encoder.interpret_allocs_inverse[idx]; let pos = encoder.position() as u32; diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index 7f3736e82caa6..5604729d2f8dc 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -146,7 +146,7 @@ impl FromHex for str { } match modulus { - 0 => Ok(b.into_iter().collect()), + 0 => Ok(b), _ => Err(InvalidHexLength), } } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index dd90ef06c3929..bfdb53a9d9e18 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1200,16 +1200,14 @@ impl<'a> MethodDef<'a> { let sp = trait_.span; let variants = &enum_def.variants; - let self_arg_names = self_args.iter() - .enumerate() - .map(|(arg_count, _self_arg)| { - if arg_count == 0 { - "__self".to_string() - } else { + let self_arg_names = iter::once("__self".to_string()).chain( + self_args.iter() + .enumerate() + .skip(1) + .map(|(arg_count, _self_arg)| format!("__arg_{}", arg_count) - } - }) - .collect::>(); + ) + ).collect::>(); let self_arg_idents = self_arg_names.iter() .map(|name| cx.ident_of(&name[..])) @@ -1218,7 +1216,7 @@ impl<'a> MethodDef<'a> { // The `vi_idents` will be bound, solely in the catch-all, to // a series of let statements mapping each self_arg to an int // value corresponding to its discriminant. - let vi_idents: Vec = self_arg_names.iter() + let vi_idents = self_arg_names.iter() .map(|name| { let vi_suffix = format!("{}_vi", &name[..]); cx.ident_of(&vi_suffix[..]).gensym() From 562be7e1a1955742d61320d0855550794c4b6c22 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 8 Nov 2018 20:12:05 +0100 Subject: [PATCH 09/27] Forward the ABI of the non-zero sized fields of an union if they have the same ABI This is supposed to fix the performence regression of using MaybeUninit in https://github.com/rust-lang/rust/pull/54668 --- src/librustc/ty/layout.rs | 35 ++++++++++++++- src/librustc/ty/mod.rs | 6 +++ src/test/codegen/union-abi.rs | 80 +++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/test/codegen/union-abi.rs diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 877bd5a82e6a0..0b00cfc2d7fd4 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -697,7 +697,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { Align::from_bytes(repr_align, repr_align).unwrap()); } + let optimize = !def.repr.inhibit_union_abi_opt(); let mut size = Size::ZERO; + let mut abi = Abi::Aggregate { sized: true }; let index = VariantIdx::new(0); for field in &variants[index] { assert!(!field.is_unsized()); @@ -708,13 +710,44 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } else { align = align.max(field.align); } + + // If all non-ZST fields have the same ABI, forward this ABI + if optimize && !field.is_zst() { + // Normalize scalar_unit to the maximal valid range + let field_abi = match &field.abi { + Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)), + Abi::ScalarPair(x, y) => { + Abi::ScalarPair( + scalar_unit(x.value), + scalar_unit(y.value), + ) + } + Abi::Vector { element: x, count } => { + Abi::Vector { + element: scalar_unit(x.value), + count: *count, + } + } + Abi::Uninhabited | + Abi::Aggregate { .. } => Abi::Aggregate { sized: true }, + }; + + if size == Size::ZERO { + // first non ZST: initialize 'abi' + abi = field_abi; + } else if abi != field_abi { + // different fields have different ABI: reset to Aggregate + abi = Abi::Aggregate { sized: true }; + } + } + size = cmp::max(size, field.size); } return Ok(tcx.intern_layout(LayoutDetails { variants: Variants::Single { index }, fields: FieldPlacement::Union(variants[index].len()), - abi: Abi::Aggregate { sized: true }, + abi, align, size: size.abi_align(align) })); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 83feadd50d77f..9553d1244837c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1994,6 +1994,12 @@ impl ReprOptions { pub fn inhibit_struct_field_reordering_opt(&self) -> bool { !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1) } + + /// Returns true if this `#[repr()]` should inhibit union abi optimisations + pub fn inhibit_union_abi_opt(&self) -> bool { + self.c() + } + } impl<'a, 'gcx, 'tcx> AdtDef { diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs new file mode 100644 index 0000000000000..0fa06fa777b29 --- /dev/null +++ b/src/test/codegen/union-abi.rs @@ -0,0 +1,80 @@ +// Copyright 2017 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. + +// compile-flags: -C no-prepopulate-passes + +// This test that using union forward the abi of the inner type, as +// discussed in #54668 + +#![crate_type="lib"] +#![feature(repr_simd)] + +#[derive(Copy, Clone)] +pub enum Unhab {} + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct i64x4(i64, i64, i64, i64); + +#[derive(Copy, Clone)] +pub union UnionI64x4{ a:(), b: i64x4 } + +// CHECK: define <4 x i64> @test_UnionI64x4(<4 x i64> %arg0) +#[no_mangle] +pub extern fn test_UnionI64x4(_: UnionI64x4) -> UnionI64x4 { loop {} } + +pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 } + +// CHECK: define <4 x i64> @test_UnionI64x4_(<4 x i64> %arg0) +#[no_mangle] +pub extern fn test_UnionI64x4_(_: UnionI64x4_) -> UnionI64x4_ { loop {} } + +pub union UnionI64x4I64{ a: i64x4, b: i64 } + +// CHECK: define void @test_UnionI64x4I64(%UnionI64x4I64* {{.*}} %arg0) +#[no_mangle] +pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} } + +pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) } + +// CHECK: define void @test_UnionI64x4Tuple(%UnionI64x4Tuple* {{.*}} %arg0) +#[no_mangle] +pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} } + + +pub union UnionF32{a:f32} + +// CHECK: define float @test_UnionF32(float %arg0) +#[no_mangle] +pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } + +pub union UnionF32F32{a:f32, b:f32} + +// CHECK: define float @test_UnionF32F32(float %arg0) +#[no_mangle] +pub extern fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} } + +pub union UnionF32U32{a:f32, b:u32} + +// CHECK: define i32 @test_UnionF32U32(i32) +#[no_mangle] +pub extern fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} } + +pub union UnionU128{a:u128} +// CHECK: define i128 @test_UnionU128(i128 %arg0) +#[no_mangle] +pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} } + +#[repr(C)] +pub union CUnionU128{a:u128} +// CHECK: define void @test_CUnionU128(%CUnionU128* {{.*}} %arg0) +#[no_mangle] +pub fn test_CUnionU128(_: CUnionU128) { loop {} } + From cfbae3e1940f75fa1f5f99bf60f68ed9756a202b Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Tue, 13 Nov 2018 13:19:24 +0100 Subject: [PATCH 10/27] core/tests/num: Simplify `test_int_from_str_overflow()` test code This commit changes the test code to compare against easier-to-read, static values instead of relying on the result of `wrapping_add()` which may or may not result in the value that we expect. --- src/libcore/tests/num/mod.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index ab96d3126bb22..0928f7560e175 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -82,36 +82,28 @@ fn from_str_issue7588() { #[test] fn test_int_from_str_overflow() { - let mut i8_val: i8 = 127; - assert_eq!("127".parse::().ok(), Some(i8_val)); + assert_eq!("127".parse::().ok(), Some(127i8)); assert_eq!("128".parse::().ok(), None); - i8_val = i8_val.wrapping_add(1); - assert_eq!("-128".parse::().ok(), Some(i8_val)); + assert_eq!("-128".parse::().ok(), Some(-128i8)); assert_eq!("-129".parse::().ok(), None); - let mut i16_val: i16 = 32_767; - assert_eq!("32767".parse::().ok(), Some(i16_val)); + assert_eq!("32767".parse::().ok(), Some(32_767i16)); assert_eq!("32768".parse::().ok(), None); - i16_val = i16_val.wrapping_add(1); - assert_eq!("-32768".parse::().ok(), Some(i16_val)); + assert_eq!("-32768".parse::().ok(), Some(-32_768i16)); assert_eq!("-32769".parse::().ok(), None); - let mut i32_val: i32 = 2_147_483_647; - assert_eq!("2147483647".parse::().ok(), Some(i32_val)); + assert_eq!("2147483647".parse::().ok(), Some(2_147_483_647i32)); assert_eq!("2147483648".parse::().ok(), None); - i32_val = i32_val.wrapping_add(1); - assert_eq!("-2147483648".parse::().ok(), Some(i32_val)); + assert_eq!("-2147483648".parse::().ok(), Some(-2_147_483_648i32)); assert_eq!("-2147483649".parse::().ok(), None); - let mut i64_val: i64 = 9_223_372_036_854_775_807; - assert_eq!("9223372036854775807".parse::().ok(), Some(i64_val)); + assert_eq!("9223372036854775807".parse::().ok(), Some(9_223_372_036_854_775_807i64)); assert_eq!("9223372036854775808".parse::().ok(), None); - i64_val = i64_val.wrapping_add(1); - assert_eq!("-9223372036854775808".parse::().ok(), Some(i64_val)); + assert_eq!("-9223372036854775808".parse::().ok(), Some(-9_223_372_036_854_775_808i64)); assert_eq!("-9223372036854775809".parse::().ok(), None); } From 1ca505a30adb1d392d3166a34ec40b0bf584acf9 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Wed, 14 Nov 2018 08:41:16 -0800 Subject: [PATCH 11/27] capture_disjoint_fields(rust-lang#53488) Just running RustFmt on upvar.rs --- src/librustc_typeck/check/upvar.rs | 144 ++++++++++++++--------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index df994ad9e55c4..ef29e13d9fe12 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -45,14 +45,14 @@ use super::FnCtxt; use middle::expr_use_visitor as euv; use middle::mem_categorization as mc; use middle::mem_categorization::Categorization; +use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts}; +use rustc::hir::def_id::LocalDefId; +use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::infer::UpvarRegion; +use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts}; use syntax::ast; use syntax_pos::Span; -use rustc::hir; -use rustc::hir::def_id::LocalDefId; -use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn closure_analyze(&self, body: &'gcx hir::Body) { @@ -121,7 +121,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; - let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs{ + let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs { if self.closure_kind(closure_def_id, closure_substs).is_none() { Some(closure_substs) } else { @@ -213,12 +213,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let final_upvar_tys = self.final_upvar_tys(closure_node_id); debug!( "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}", - closure_node_id, - substs, - final_upvar_tys + closure_node_id, substs, final_upvar_tys ); - for (upvar_ty, final_upvar_ty) in substs.upvar_tys(closure_def_id, self.tcx) - .zip(final_upvar_tys) + for (upvar_ty, final_upvar_ty) in substs + .upvar_tys(closure_def_id, self.tcx) + .zip(final_upvar_tys) { self.demand_suptype(span, upvar_ty, final_upvar_ty); } @@ -256,9 +255,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!( "var_id={:?} freevar_ty={:?} capture={:?}", - var_node_id, - freevar_ty, - capture + var_node_id, freevar_ty, capture ); match capture { @@ -271,8 +268,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, ), } - }) - .collect() + }).collect() }) } } @@ -301,12 +297,14 @@ struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { - fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'tcx>, - mode: euv::ConsumeMode) { + fn adjust_upvar_borrow_kind_for_consume( + &mut self, + cmt: &mc::cmt_<'tcx>, + mode: euv::ConsumeMode, + ) { debug!( "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})", - cmt, - mode + cmt, mode ); // we only care about moves @@ -381,9 +379,9 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt); match cmt.cat.clone() { - Categorization::Deref(base, mc::Unique) | - Categorization::Interior(base, _) | - Categorization::Downcast(base, _) => { + Categorization::Deref(base, mc::Unique) + | Categorization::Interior(base, _) + | Categorization::Downcast(base, _) => { // Interior or owned data is mutable if base is // mutable, so iterate to the base. self.adjust_upvar_borrow_kind_for_mut(&base); @@ -399,12 +397,12 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { } } - Categorization::Deref(_, mc::UnsafePtr(..)) | - Categorization::StaticItem | - Categorization::ThreadLocal(..) | - Categorization::Rvalue(..) | - Categorization::Local(_) | - Categorization::Upvar(..) => { + Categorization::Deref(_, mc::UnsafePtr(..)) + | Categorization::StaticItem + | Categorization::ThreadLocal(..) + | Categorization::Rvalue(..) + | Categorization::Local(_) + | Categorization::Upvar(..) => { return; } } @@ -414,9 +412,9 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt); match cmt.cat.clone() { - Categorization::Deref(base, mc::Unique) | - Categorization::Interior(base, _) | - Categorization::Downcast(base, _) => { + Categorization::Deref(base, mc::Unique) + | Categorization::Interior(base, _) + | Categorization::Downcast(base, _) => { // Interior or owned data is unique if base is // unique. self.adjust_upvar_borrow_kind_for_unique(&base); @@ -430,18 +428,20 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { } } - Categorization::Deref(_, mc::UnsafePtr(..)) | - Categorization::StaticItem | - Categorization::ThreadLocal(..) | - Categorization::Rvalue(..) | - Categorization::Local(_) | - Categorization::Upvar(..) => {} + Categorization::Deref(_, mc::UnsafePtr(..)) + | Categorization::StaticItem + | Categorization::ThreadLocal(..) + | Categorization::Rvalue(..) + | Categorization::Local(_) + | Categorization::Upvar(..) => {} } } - fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::BorrowKind) - -> bool - { + fn try_adjust_upvar_deref( + &mut self, + cmt: &mc::cmt_<'tcx>, + borrow_kind: ty::BorrowKind, + ) -> bool { assert!(match borrow_kind { ty::MutBorrow => true, ty::UniqueImmBorrow => true, @@ -493,15 +493,14 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { /// Here the argument `mutbl` is the borrow_kind that is required by /// some particular use. fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, kind: ty::BorrowKind) { - let upvar_capture = self.adjust_upvar_captures + let upvar_capture = self + .adjust_upvar_captures .get(&upvar_id) .cloned() .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id)); debug!( "adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})", - upvar_id, - upvar_capture, - kind + upvar_id, upvar_capture, kind ); match upvar_capture { @@ -511,18 +510,18 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { ty::UpvarCapture::ByRef(mut upvar_borrow) => { match (upvar_borrow.kind, kind) { // Take RHS: - (ty::ImmBorrow, ty::UniqueImmBorrow) | - (ty::ImmBorrow, ty::MutBorrow) | - (ty::UniqueImmBorrow, ty::MutBorrow) => { + (ty::ImmBorrow, ty::UniqueImmBorrow) + | (ty::ImmBorrow, ty::MutBorrow) + | (ty::UniqueImmBorrow, ty::MutBorrow) => { upvar_borrow.kind = kind; self.adjust_upvar_captures .insert(upvar_id, ty::UpvarCapture::ByRef(upvar_borrow)); } // Take LHS: - (ty::ImmBorrow, ty::ImmBorrow) | - (ty::UniqueImmBorrow, ty::ImmBorrow) | - (ty::UniqueImmBorrow, ty::UniqueImmBorrow) | - (ty::MutBorrow, _) => {} + (ty::ImmBorrow, ty::ImmBorrow) + | (ty::UniqueImmBorrow, ty::ImmBorrow) + | (ty::UniqueImmBorrow, ty::UniqueImmBorrow) + | (ty::MutBorrow, _) => {} } } } @@ -537,10 +536,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { ) { debug!( "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})", - closure_id, - new_kind, - upvar_span, - var_name + closure_id, new_kind, upvar_span, var_name ); // Is this the closure whose kind is currently being inferred? @@ -554,22 +550,20 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { debug!( "adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}", - closure_id, - existing_kind, - new_kind + closure_id, existing_kind, new_kind ); match (existing_kind, new_kind) { - (ty::ClosureKind::Fn, ty::ClosureKind::Fn) | - (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) | - (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) | - (ty::ClosureKind::FnOnce, _) => { + (ty::ClosureKind::Fn, ty::ClosureKind::Fn) + | (ty::ClosureKind::FnMut, ty::ClosureKind::Fn) + | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) + | (ty::ClosureKind::FnOnce, _) => { // no change needed } - (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) | - (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) | - (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { + (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) + | (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) + | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { // new kind is stronger than the old kind self.current_closure_kind = new_kind; self.current_origin = Some((upvar_span, var_name)); @@ -590,12 +584,20 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { self.adjust_upvar_borrow_kind_for_consume(cmt, mode); } - fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: &mc::cmt_<'tcx>, - _mode: euv::MatchMode) { + fn matched_pat( + &mut self, + _matched_pat: &hir::Pat, + _cmt: &mc::cmt_<'tcx>, + _mode: euv::MatchMode, + ) { } - fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: &mc::cmt_<'tcx>, - mode: euv::ConsumeMode) { + fn consume_pat( + &mut self, + _consume_pat: &hir::Pat, + cmt: &mc::cmt_<'tcx>, + mode: euv::ConsumeMode, + ) { debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode); self.adjust_upvar_borrow_kind_for_consume(cmt, mode); } @@ -611,9 +613,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { ) { debug!( "borrow(borrow_id={}, cmt={:?}, bk={:?})", - borrow_id, - cmt, - bk + borrow_id, cmt, bk ); match bk { From c040a483bcb522b60865130ea5e94e2ef2915f94 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 14 Nov 2018 18:09:54 +0100 Subject: [PATCH 12/27] Remove extern and some return value as an attempt to make the test pass on more platforms --- src/test/codegen/union-abi.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index 0fa06fa777b29..786968128ec1b 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -26,15 +26,15 @@ pub struct i64x4(i64, i64, i64, i64); #[derive(Copy, Clone)] pub union UnionI64x4{ a:(), b: i64x4 } -// CHECK: define <4 x i64> @test_UnionI64x4(<4 x i64> %arg0) +// CHECK: define void @test_UnionI64x4(<4 x i64>* {{.*}} %arg0) #[no_mangle] -pub extern fn test_UnionI64x4(_: UnionI64x4) -> UnionI64x4 { loop {} } +pub fn test_UnionI64x4(_: UnionI64x4) { loop {} } pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 } -// CHECK: define <4 x i64> @test_UnionI64x4_(<4 x i64> %arg0) +// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %arg0) #[no_mangle] -pub extern fn test_UnionI64x4_(_: UnionI64x4_) -> UnionI64x4_ { loop {} } +pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} } pub union UnionI64x4I64{ a: i64x4, b: i64 } @@ -53,19 +53,19 @@ pub union UnionF32{a:f32} // CHECK: define float @test_UnionF32(float %arg0) #[no_mangle] -pub extern fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } +pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } pub union UnionF32F32{a:f32, b:f32} // CHECK: define float @test_UnionF32F32(float %arg0) #[no_mangle] -pub extern fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} } +pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} } pub union UnionF32U32{a:f32, b:u32} // CHECK: define i32 @test_UnionF32U32(i32) #[no_mangle] -pub extern fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} } +pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} } pub union UnionU128{a:u128} // CHECK: define i128 @test_UnionU128(i128 %arg0) From aa3d7a4e6e62aad4f96d7f0b547853641d980eca Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 14 Nov 2018 18:14:31 -0600 Subject: [PATCH 13/27] properly calculate spans for intra-doc link resolution errors --- .../passes/collect_intra_doc_links.rs | 2 +- .../rustdoc-ui/intra-link-span-ice-55723.rs | 24 +++++++++++++++++++ .../intra-link-span-ice-55723.stderr | 13 ++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-ui/intra-link-span-ice-55723.rs create mode 100644 src/test/rustdoc-ui/intra-link-span-ice-55723.stderr diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index a780322e85e86..f25aa000d803d 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -527,7 +527,7 @@ fn resolution_failure( doc_comment_padding + // Each subsequent leading whitespace and `///` code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| { - sum + doc_comment_padding + line.len() - line.trim().len() + sum + doc_comment_padding + line.len() - line.trim_start().len() }) }; diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.rs b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs new file mode 100644 index 0000000000000..12e59a4813f85 --- /dev/null +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.rs @@ -0,0 +1,24 @@ +// 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. + +// ignore-tidy-end-whitespace + +#![deny(intra_doc_link_resolution_failure)] + +// An error in calculating spans while reporting intra-doc link resolution errors caused rustdoc to +// attempt to slice in the middle of a multibyte character. See +// https://github.com/rust-lang/rust/issues/55723 + +/// ## For example: +/// +/// (arr[i]) +pub fn test_ice() { + unimplemented!(); +} diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr new file mode 100644 index 0000000000000..7ae6af4a75e8c --- /dev/null +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr @@ -0,0 +1,13 @@ +error: `[i]` cannot be resolved, ignoring it... + --> $DIR/intra-link-span-ice-55723.rs:21:10 + | +LL | /// (arr[i]) + | ^ cannot be resolved, ignoring + | +note: lint level defined here + --> $DIR/intra-link-span-ice-55723.rs:13:9 + | +LL | #![deny(intra_doc_link_resolution_failure)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]` + From a1f83e75afefad37b1eed868c0aefba99563969d Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 15 Nov 2018 00:18:19 +0000 Subject: [PATCH 14/27] Stress test for MPSC `concurrent_recv_timeout_and_upgrade` reproduces a problem 100% times on my MacBook with command: ``` ./x.py test --stage 0 ./src/test/run-pass/mpsc_stress.rs ``` Thus it is commented out. Other tests cases were useful for catching another test cases which may arise during the fix. This diff is a part of my previous rewrite attempt: #42883 CC #39364 --- src/test/run-pass/mpsc_stress.rs | 172 +++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 src/test/run-pass/mpsc_stress.rs diff --git a/src/test/run-pass/mpsc_stress.rs b/src/test/run-pass/mpsc_stress.rs new file mode 100644 index 0000000000000..aa369bb17fead --- /dev/null +++ b/src/test/run-pass/mpsc_stress.rs @@ -0,0 +1,172 @@ +// Copyright 2017 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. + +// compile-flags:--test +// ignore-emscripten + +use std::sync::mpsc::channel; +use std::sync::mpsc::TryRecvError; +use std::sync::mpsc::RecvError; +use std::sync::mpsc::RecvTimeoutError; +use std::sync::Arc; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; + +use std::thread; +use std::time::Duration; + + +/// Simple thread synchronization utility +struct Barrier { + // Not using mutex/condvar for precision + shared: Arc, + count: usize, +} + +impl Barrier { + fn new(count: usize) -> Vec { + let shared = Arc::new(AtomicUsize::new(0)); + (0..count).map(|_| Barrier { shared: shared.clone(), count: count }).collect() + } + + fn new2() -> (Barrier, Barrier) { + let mut v = Barrier::new(2); + (v.pop().unwrap(), v.pop().unwrap()) + } + + /// Returns when `count` threads enter `wait` + fn wait(self) { + self.shared.fetch_add(1, Ordering::SeqCst); + while self.shared.load(Ordering::SeqCst) != self.count { + } + } +} + + +fn shared_close_sender_does_not_lose_messages_iter() { + let (tb, rb) = Barrier::new2(); + + let (tx, rx) = channel(); + let _ = tx.clone(); // convert to shared + + thread::spawn(move || { + tb.wait(); + thread::sleep(Duration::from_micros(1)); + tx.send(17).expect("send"); + drop(tx); + }); + + let i = rx.into_iter(); + rb.wait(); + // Make sure it doesn't return disconnected before returning an element + assert_eq!(vec![17], i.collect::>()); +} + +#[test] +fn shared_close_sender_does_not_lose_messages() { + for _ in 0..10000 { + shared_close_sender_does_not_lose_messages_iter(); + } +} + + +// https://github.com/rust-lang/rust/issues/39364 +fn concurrent_recv_timeout_and_upgrade_iter() { + // 1 us + let sleep = Duration::new(0, 1_000); + + let (a, b) = Barrier::new2(); + let (tx, rx) = channel(); + let th = thread::spawn(move || { + a.wait(); + loop { + match rx.recv_timeout(sleep) { + Ok(_) => { + break; + }, + Err(_) => {}, + } + } + }); + b.wait(); + thread::sleep(sleep); + tx.clone().send(()).expect("send"); + th.join().unwrap(); +} + +#[test] +fn concurrent_recv_timeout_and_upgrade() { + // FIXME: fix and enable + if true { return } + + // at the moment of writing this test fails like this: + // thread '' panicked at 'assertion failed: `(left == right)` + // left: `4561387584`, + // right: `0`', libstd/sync/mpsc/shared.rs:253:13 + + for _ in 0..10000 { + concurrent_recv_timeout_and_upgrade_iter(); + } +} + + +fn concurrent_writes_iter() { + const THREADS: usize = 4; + const PER_THR: usize = 100; + + let mut bs = Barrier::new(THREADS + 1); + let (tx, rx) = channel(); + + let mut threads = Vec::new(); + for j in 0..THREADS { + let tx = tx.clone(); + let b = bs.pop().unwrap(); + threads.push(thread::spawn(move || { + b.wait(); + for i in 0..PER_THR { + tx.send(j * 1000 + i).expect("send"); + } + })); + } + + let b = bs.pop().unwrap(); + b.wait(); + + let mut v: Vec<_> = rx.iter().take(THREADS * PER_THR).collect(); + v.sort(); + + for j in 0..THREADS { + for i in 0..PER_THR { + assert_eq!(j * 1000 + i, v[j * PER_THR + i]); + } + } + + for t in threads { + t.join().unwrap(); + } + + let one_us = Duration::new(0, 1000); + + assert_eq!(TryRecvError::Empty, rx.try_recv().unwrap_err()); + assert_eq!(RecvTimeoutError::Timeout, rx.recv_timeout(one_us).unwrap_err()); + + drop(tx); + + assert_eq!(RecvError, rx.recv().unwrap_err()); + assert_eq!(RecvTimeoutError::Disconnected, rx.recv_timeout(one_us).unwrap_err()); + assert_eq!(TryRecvError::Disconnected, rx.try_recv().unwrap_err()); +} + +#[test] +fn concurrent_writes() { + for _ in 0..100 { + concurrent_writes_iter(); + } +} From 6779bb485c7fb3af47278d7eeefce34eeeb5eaf8 Mon Sep 17 00:00:00 2001 From: Blitzerr Date: Wed, 14 Nov 2018 21:14:46 -0800 Subject: [PATCH 15/27] capture_disjoint_fields(rust-lang#53488) Refactoring out the HirId of the UpvarId in another struct. --- src/librustc/ich/impls_ty.rs | 4 +++- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/infer/error_reporting/note.rs | 4 ++-- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/ty/context.rs | 6 +++--- src/librustc/ty/mod.rs | 7 ++++++- src/librustc/util/ppaux.rs | 4 ++-- .../borrowck/gather_loans/mod.rs | 4 ++-- .../borrowck/gather_loans/move_error.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 10 +++++----- src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 4 ++-- src/librustc_typeck/check/upvar.rs | 16 ++++++++++------ src/librustc_typeck/check/writeback.rs | 2 +- 15 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f3a62975dd9f4..928a6accf2d12 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -216,7 +216,9 @@ impl<'gcx> HashStable> for ty::adjustment::AutoBorrow } } -impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id }); +impl_stable_hash_for!(struct ty::UpvarPath { hir_id }); + +impl_stable_hash_for!(struct ty::UpvarId { var_path, closure_expr_id }); impl_stable_hash_for!(enum ty::BorrowKind { ImmBorrow, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index f833ebc7ca763..59a490f4a013d 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1315,7 +1315,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { format!(" for lifetime parameter `{}` in coherence check", name) } infer::UpvarRegion(ref upvar_id, _) => { - let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id); + let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); let var_name = self.tcx.hir.name(var_node_id); format!(" for capture of `{}` by closure", var_name) } diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index 54d01a035a8be..a539c321af3f0 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -41,7 +41,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "...so that reference does not outlive borrowed content"); } infer::ReborrowUpvar(span, ref upvar_id) => { - let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id); + let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); let var_name = self.tcx.hir.name(var_node_id); err.span_note(span, &format!("...so that closure can access `{}`", var_name)); @@ -174,7 +174,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err } infer::ReborrowUpvar(span, ref upvar_id) => { - let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id); + let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); let var_name = self.tcx.hir.name(var_node_id); let mut err = struct_span_err!(self.tcx.sess, span, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7e9b26bbf729c..5b92bfe6ad3c4 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -938,7 +938,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let var_hir_id = self.tcx().hir.node_to_hir_id(freevar.var_id()); let closure_def_id = self.tcx().hir.local_def_id(closure_expr.id); let upvar_id = ty::UpvarId { - var_id: var_hir_id, + var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_def_id.to_local(), }; let upvar_capture = self.mc.tables.upvar_capture(upvar_id); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 59ef8fa14484b..cadf0c42d228f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -818,7 +818,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let closure_expr_def_id = self.tcx.hir.local_def_id(fn_node_id); let var_hir_id = self.tcx.hir.node_to_hir_id(var_id); let upvar_id = ty::UpvarId { - var_id: var_hir_id, + var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_expr_def_id.to_local(), }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index cdfe8f53b854b..923d362c2345f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -789,7 +789,7 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { pat_adjustments.hash_stable(hcx, hasher); hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| { let ty::UpvarId { - var_id, + var_path, closure_expr_id } = *up_var_id; @@ -798,14 +798,14 @@ impl<'a, 'gcx> HashStable> for TypeckTables<'gcx> { let var_owner_def_id = DefId { krate: local_id_root.krate, - index: var_id.owner, + index: var_path.hir_id.owner, }; let closure_def_id = DefId { krate: local_id_root.krate, index: closure_expr_id.to_def_id().index, }; (hcx.def_path_hash(var_owner_def_id), - var_id.local_id, + var_path.hir_id.local_id, hcx.def_path_hash(closure_def_id)) }); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8197136d189ae..d1497c42af78f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -731,12 +731,17 @@ impl List { } } +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +pub struct UpvarPath { + pub hir_id: hir::HirId, +} + /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced /// by the upvar) and the id of the closure expression. #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UpvarId { - pub var_id: hir::HirId, + pub var_path: UpvarPath, pub closure_expr_id: LocalDefId, } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index e44c0c05bb1a6..d53370d242bd9 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -678,8 +678,8 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "UpvarId({:?};`{}`;{:?})", - self.var_id, - ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_id))), + self.var_path.hir_id, + ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_path.hir_id))), self.closure_expr_id) } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 78a31ed668fca..21fb0cdf90ad1 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -453,8 +453,8 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { } None } - LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => { - self.bccx.used_mut_nodes.borrow_mut().insert(var_id); + LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath { hir_id }, closure_expr_id: _ }) => { + self.bccx.used_mut_nodes.borrow_mut().insert(hir_id); None } LpExtend(ref base, mc::McInherited, LpDeref(pointer_kind)) | diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index e1a4473539c8c..cfd530b7e3d09 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -97,7 +97,7 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, errors: &[MoveErr } } if let NoteClosureEnv(upvar_id) = error.move_from.note { - let var_node_id = bccx.tcx.hir.hir_to_node_id(upvar_id.var_id); + let var_node_id = bccx.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); err.span_label(bccx.tcx.hir.span(var_node_id), "captured outer variable"); } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index d52d78181b77a..d189460d08848 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -846,7 +846,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { MutabilityViolation => { let mut db = self.cannot_assign(error_span, &descr, Origin::Ast); if let mc::NoteClosureEnv(upvar_id) = err.cmt.note { - let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id); + let node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_path.hir_id); let sp = self.tcx.hir.span(node_id); let fn_closure_msg = "`Fn` closures cannot capture their enclosing \ environment for modifications"; @@ -1415,7 +1415,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { loan_path: &LoanPath<'tcx>, out: &mut String) { match loan_path.kind { - LpUpvar(ty::UpvarId { var_id: id, closure_expr_id: _ }) => { + LpUpvar(ty::UpvarId { var_path: ty::UpvarPath { hir_id: id}, closure_expr_id: _ }) => { out.push_str(&self.tcx.hir.name(self.tcx.hir.hir_to_node_id(id)).as_str()); } LpVar(id) => { @@ -1533,7 +1533,7 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> { write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_string(id))) } - LpUpvar(ty::UpvarId{ var_id, closure_expr_id }) => { + LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath {hir_id: var_id}, closure_expr_id }) => { let s = ty::tls::with(|tcx| { let var_node_id = tcx.hir.hir_to_node_id(var_id); tcx.hir.node_to_string(var_node_id) @@ -1568,9 +1568,9 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> { write!(f, "$({})", ty::tls::with(|tcx| tcx.hir.node_to_user_string(id))) } - LpUpvar(ty::UpvarId{ var_id, closure_expr_id: _ }) => { + LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath { hir_id }, closure_expr_id: _ }) => { let s = ty::tls::with(|tcx| { - let var_node_id = tcx.hir.hir_to_node_id(var_id); + let var_node_id = tcx.hir.hir_to_node_id(hir_id); tcx.hir.node_to_string(var_node_id) }); write!(f, "$({} captured by closure)", s) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 5b4001f0652ad..94d1874e9c9e8 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -612,7 +612,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let var_hir_id = tcx.hir.node_to_hir_id(var_id); let closure_expr_id = tcx.hir.local_def_id(fn_id); let capture = hir.tables().upvar_capture(ty::UpvarId { - var_id: var_hir_id, + var_path: ty::UpvarPath {hir_id: var_hir_id}, closure_expr_id: LocalDefId::from_def_id(closure_expr_id), }); let by_ref = match capture { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 656a467fb4912..2e9edf20c5708 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -1061,7 +1061,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // ...but the upvar might be an `&T` or `&mut T` capture, at which // point we need an implicit deref let upvar_id = ty::UpvarId { - var_id: var_hir_id, + var_path: ty::UpvarPath {hir_id: var_hir_id}, closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; match cx.tables().upvar_capture(upvar_id) { @@ -1178,7 +1178,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, -> ExprRef<'tcx> { let var_hir_id = cx.tcx.hir.node_to_hir_id(freevar.var_id()); let upvar_id = ty::UpvarId { - var_id: var_hir_id, + var_path: ty::UpvarPath { hir_id: var_hir_id }, closure_expr_id: cx.tcx.hir.local_def_id(closure_expr.id).to_local(), }; let upvar_capture = cx.tables().upvar_capture(upvar_id); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index ef29e13d9fe12..312ce402775d2 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -134,7 +134,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx.with_freevars(closure_node_id, |freevars| { for freevar in freevars { let upvar_id = ty::UpvarId { - var_id: self.tcx.hir.node_to_hir_id(freevar.var_id()), + var_path: ty::UpvarPath { + hir_id : self.tcx.hir.node_to_hir_id(freevar.var_id()), + }, closure_expr_id: LocalDefId::from_def_id(closure_def_id), }; debug!("seed upvar_id {:?}", upvar_id); @@ -248,7 +250,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let var_hir_id = tcx.hir.node_to_hir_id(var_node_id); let freevar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { - var_id: var_hir_id, + var_path: ty::UpvarPath { + hir_id: var_hir_id, + }, closure_expr_id: LocalDefId::from_def_id(closure_def_index), }; let capture = self.tables.borrow().upvar_capture(upvar_id); @@ -347,7 +351,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { upvar_id.closure_expr_id, ty::ClosureKind::FnOnce, guarantor.span, - var_name(tcx, upvar_id.var_id), + var_name(tcx, upvar_id.var_path.hir_id), ); self.adjust_upvar_captures @@ -364,7 +368,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { upvar_id.closure_expr_id, ty::ClosureKind::FnOnce, guarantor.span, - var_name(tcx, upvar_id.var_id), + var_name(tcx, upvar_id.var_path.hir_id), ); } mc::NoteIndex | mc::NoteNone => {} @@ -465,7 +469,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { upvar_id.closure_expr_id, ty::ClosureKind::FnMut, cmt.span, - var_name(tcx, upvar_id.var_id), + var_name(tcx, upvar_id.var_path.hir_id), ); true @@ -478,7 +482,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { upvar_id.closure_expr_id, ty::ClosureKind::FnMut, cmt.span, - var_name(tcx, upvar_id.var_id), + var_name(tcx, upvar_id.var_path.hir_id), ); true diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index d968bf222aa09..4460d5f64ce26 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -306,7 +306,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByRef(ref upvar_borrow) => { let r = upvar_borrow.region; - let r = self.resolve(&r, &upvar_id.var_id); + let r = self.resolve(&r, &upvar_id.var_path.hir_id); ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r, From c5bc83b60d10492f8e71461b03f5adb8505e53d6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 13 Nov 2018 11:14:18 +0100 Subject: [PATCH 16/27] expose MutValueVisitor --- src/librustc_mir/interpret/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 82fe08fa038a4..96ea0d5094966 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -39,6 +39,6 @@ pub use self::machine::{Machine, AllocMap, MayLeak}; pub use self::operand::{ScalarMaybeUndef, Immediate, ImmTy, Operand, OpTy}; -pub use self::visitor::ValueVisitor; +pub use self::visitor::{ValueVisitor, MutValueVisitor}; pub use self::validity::RefTracking; From e4d03f82b582824d2b6c3fb68420883d26598178 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 13 Nov 2018 12:44:40 +0100 Subject: [PATCH 17/27] miri value visitor: provide place when visiting a primitive --- src/librustc_mir/interpret/validity.rs | 5 +++-- src/librustc_mir/interpret/visitor.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index c3554512806b3..229f48381eaa4 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -21,7 +21,7 @@ use rustc::mir::interpret::{ }; use super::{ - OpTy, MPlaceTy, ImmTy, Machine, EvalContext, ValueVisitor + OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor }; macro_rules! validation_failure { @@ -281,8 +281,9 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> } } - fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx> + fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> EvalResult<'tcx> { + let value = self.ecx.read_immediate(value)?; // Go over all the primitive types let ty = value.layout.ty; match ty.sty { diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 4a47045643253..f0a71242599bf 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -8,7 +8,7 @@ use rustc::mir::interpret::{ }; use super::{ - Machine, EvalContext, MPlaceTy, OpTy, ImmTy, + Machine, EvalContext, MPlaceTy, OpTy, }; // A thing that we can project into, and that has a layout. @@ -201,9 +201,11 @@ macro_rules! make_value_visitor { { Ok(()) } /// Called whenever we reach a value of primitive type. There can be no recursion - /// below such a value. This is the leave function. + /// below such a value. This is the leaf function. + /// We do *not* provide an `ImmTy` here because some implementations might want + /// to write to the place this primitive lives in. #[inline(always)] - fn visit_primitive(&mut self, _val: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'tcx> + fn visit_primitive(&mut self, _v: Self::V) -> EvalResult<'tcx> { Ok(()) } // Default recursors. Not meant to be overloaded. @@ -279,9 +281,7 @@ macro_rules! make_value_visitor { _ => v.layout().ty.builtin_deref(true).is_some(), }; if primitive { - let op = v.to_op(self.ecx())?; - let val = self.ecx().read_immediate(op)?; - return self.visit_primitive(val); + return self.visit_primitive(v); } // Proceed into the fields. From e6e56357308d1e20b56f1be9af2c2dfc73c49d0d Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 14 Nov 2018 15:00:57 +0100 Subject: [PATCH 18/27] ty: return impl Iterator from Predicate::walk_tys --- src/librustc/ty/mod.rs | 78 +++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8197136d189ae..c801cb99a1e2c 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -49,7 +49,6 @@ use std::hash::{Hash, Hasher}; use std::ops::Deref; use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter}; use std::slice; -use std::vec::IntoIter; use std::{mem, ptr}; use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; use syntax::attr; @@ -1343,49 +1342,88 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { } } +// A custom iterator used by Predicate::walk_tys. +enum WalkTysIter<'tcx, I, J, K> + where I: Iterator>, + J: Iterator>, + K: Iterator> +{ + None, + One(Ty<'tcx>), + Two(Ty<'tcx>, Ty<'tcx>), + Types(I), + InputTypes(J), + ProjectionTypes(K) +} + +impl<'tcx, I, J, K> Iterator for WalkTysIter<'tcx, I, J, K> + where I: Iterator>, + J: Iterator>, + K: Iterator> +{ + type Item = Ty<'tcx>; + + fn next(&mut self) -> Option> { + match *self { + WalkTysIter::None => None, + WalkTysIter::One(item) => { + *self = WalkTysIter::None; + Some(item) + }, + WalkTysIter::Two(item1, item2) => { + *self = WalkTysIter::One(item2); + Some(item1) + }, + WalkTysIter::Types(ref mut iter) => { + iter.next() + }, + WalkTysIter::InputTypes(ref mut iter) => { + iter.next() + }, + WalkTysIter::ProjectionTypes(ref mut iter) => { + iter.next() + } + } + } +} + impl<'tcx> Predicate<'tcx> { /// Iterates over the types in this predicate. Note that in all /// cases this is skipping over a binder, so late-bound regions /// with depth 0 are bound by the predicate. - pub fn walk_tys(&self) -> IntoIter> { - let vec: Vec<_> = match *self { + pub fn walk_tys(&'a self) -> impl Iterator> + 'a { + match *self { ty::Predicate::Trait(ref data) => { - data.skip_binder().input_types().collect() + WalkTysIter::InputTypes(data.skip_binder().input_types()) } ty::Predicate::Subtype(binder) => { let SubtypePredicate { a, b, a_is_expected: _ } = binder.skip_binder(); - vec![a, b] + WalkTysIter::Two(a, b) } ty::Predicate::TypeOutlives(binder) => { - vec![binder.skip_binder().0] + WalkTysIter::One(binder.skip_binder().0) } ty::Predicate::RegionOutlives(..) => { - vec![] + WalkTysIter::None } ty::Predicate::Projection(ref data) => { let inner = data.skip_binder(); - inner.projection_ty.substs.types().chain(Some(inner.ty)).collect() + WalkTysIter::ProjectionTypes( + inner.projection_ty.substs.types().chain(Some(inner.ty))) } ty::Predicate::WellFormed(data) => { - vec![data] + WalkTysIter::One(data) } ty::Predicate::ObjectSafe(_trait_def_id) => { - vec![] + WalkTysIter::None } ty::Predicate::ClosureKind(_closure_def_id, closure_substs, _kind) => { - closure_substs.substs.types().collect() + WalkTysIter::Types(closure_substs.substs.types()) } ty::Predicate::ConstEvaluatable(_, substs) => { - substs.types().collect() + WalkTysIter::Types(substs.types()) } - }; - - // FIXME: The only reason to collect into a vector here is that I was - // too lazy to make the full (somewhat complicated) iterator - // type that would be needed here. But I wanted this fn to - // return an iterator conceptually, rather than a `Vec`, so as - // to be closer to `Ty::walk`. - vec.into_iter() + } } pub fn to_opt_poly_trait_ref(&self) -> Option> { From 8c8ff6a4e14fc8c9ded15b37a910127bbce6cda2 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 Sep 2018 16:35:41 +0000 Subject: [PATCH 19/27] test/linkage-visibility: Ignore on musl targets DynamicLibrary uses libc's dlsym() function internally to find symbols. Some implementations of dlsym(), like musl's, only look at dynamically- exported symbols, as found in shared libraries. To also export symbols from the main executable, we would need to pass --export-dynamic to the linker. Since this flag isn't available everywhere, ignore the test for now. --- src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs b/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs index 4ea3d0d0d0a07..2aaa28341ad91 100644 --- a/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs +++ b/src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-musl - dlsym doesn't see symbols without "-C link-arg=-Wl,--export-dynamic" + #![feature(rustc_private)] // We're testing linkage visibility; the compiler warns us, but we want to From 764e2a71963999bfd897d37212d3a5251276fa7a Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 7 Nov 2018 12:04:40 -0700 Subject: [PATCH 20/27] Disable some pretty-printers when gdb is rust-enabled A rust-enabled gdb already knows how to display string slices, structs, tuples, and enums (and after #54004, the pretty-printers can't handle enums at all). This patch disables these pretty-printers when gdb is rust-enabled. The "gdb-pretty-struct-and-enums-pre-gdb-7-7.rs" test is renamed, because it does not seem to depend on any behavior of that version of gdb, and because gdb 7.7 is 4 years old now. --- src/etc/gdb_rust_pretty_printing.py | 43 +++++++++++-------- ...-7-7.rs => gdb-pretty-struct-and-enums.rs} | 19 ++++---- 2 files changed, 34 insertions(+), 28 deletions(-) rename src/test/debuginfo/{gdb-pretty-struct-and-enums-pre-gdb-7-7.rs => gdb-pretty-struct-and-enums.rs} (71%) diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index e6d5ef1a23ff7..a5c8e73f919ed 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -18,6 +18,8 @@ if sys.version_info[0] >= 3: xrange = range +rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string = True) + #=============================================================================== # GDB Pretty Printing Module for Rust #=============================================================================== @@ -99,27 +101,9 @@ def rust_pretty_printer_lookup_function(gdb_val): val = GdbValue(gdb_val) type_kind = val.type.get_type_kind() - if type_kind == rustpp.TYPE_KIND_EMPTY: - return RustEmptyPrinter(val) - - if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: - return RustStructPrinter(val, - omit_first_field = False, - omit_type_name = False, - is_tuple_like = False) - - if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: - return RustStructPrinter(val, - omit_first_field = True, - omit_type_name = False, - is_tuple_like = False) - if type_kind == rustpp.TYPE_KIND_SLICE: return RustSlicePrinter(val) - if type_kind == rustpp.TYPE_KIND_STR_SLICE: - return RustStringSlicePrinter(val) - if type_kind == rustpp.TYPE_KIND_STD_VEC: return RustStdVecPrinter(val) @@ -138,6 +122,29 @@ def rust_pretty_printer_lookup_function(gdb_val): if type_kind == rustpp.TYPE_KIND_OS_STRING: return RustOsStringPrinter(val) + # Checks after this point should only be for "compiler" types -- + # things that gdb's Rust language support knows about. + if rust_enabled: + return None + + if type_kind == rustpp.TYPE_KIND_EMPTY: + return RustEmptyPrinter(val) + + if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT: + return RustStructPrinter(val, + omit_first_field = False, + omit_type_name = False, + is_tuple_like = False) + + if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT: + return RustStructPrinter(val, + omit_first_field = True, + omit_type_name = False, + is_tuple_like = False) + + if type_kind == rustpp.TYPE_KIND_STR_SLICE: + return RustStringSlicePrinter(val) + if type_kind == rustpp.TYPE_KIND_TUPLE: return RustStructPrinter(val, omit_first_field = False, diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs similarity index 71% rename from src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs rename to src/test/debuginfo/gdb-pretty-struct-and-enums.rs index 158a1f17fc03d..40dd42898f81d 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs @@ -8,34 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-bitrig -// ignore-solaris -// ignore-windows failing on win32 bot -// ignore-freebsd: gdb package too new // ignore-tidy-linelength // ignore-lldb -// ignore-android: FIXME(#10381) +// min-gdb-version: 7.11 + // compile-flags:-g // gdb-command: run // gdb-command: print regular_struct -// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false} +// gdbg-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false} +// gdbr-check:$1 = gdb_pretty_struct_and_enums::RegularStruct {the_first_field: 101, the_second_field: 102.5, the_third_field: false} // gdb-command: print empty_struct -// gdb-check:$2 = EmptyStruct +// gdbg-check:$2 = EmptyStruct +// gdbr-check:$2 = gdb_pretty_struct_and_enums::EmptyStruct // gdb-command: print c_style_enum1 // gdbg-check:$3 = CStyleEnumVar1 -// gdbr-check:$3 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar1 +// gdbr-check:$3 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar1 // gdb-command: print c_style_enum2 // gdbg-check:$4 = CStyleEnumVar2 -// gdbr-check:$4 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar2 +// gdbr-check:$4 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar2 // gdb-command: print c_style_enum3 // gdbg-check:$5 = CStyleEnumVar3 -// gdbr-check:$5 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar3 +// gdbr-check:$5 = gdb_pretty_struct_and_enums::CStyleEnum::CStyleEnumVar3 #![allow(dead_code, unused_variables)] From 03aaa4b659a546e11a94de476d0d43417b4719ce Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sat, 10 Nov 2018 23:43:41 +0100 Subject: [PATCH 21/27] remove unused dependency --- src/Cargo.lock | 1 - src/librustc_data_structures/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index a0bb92867ff4e..2eaa937baa244 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2161,7 +2161,6 @@ dependencies = [ "graphviz 0.0.0", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 10820007629ff..79f073d643ddc 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -16,7 +16,6 @@ serialize = { path = "../libserialize" } graphviz = { path = "../libgraphviz" } cfg-if = "0.1.2" stable_deref_trait = "1.0.0" -parking_lot_core = "0.2.8" rustc-rayon = "0.1.1" rustc-rayon-core = "0.1.1" rustc-hash = "1.0.1" From c1221e2072beebe90d6bbe8be99a51be1e6d11ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20C?= Date: Fri, 16 Nov 2018 15:34:12 -0500 Subject: [PATCH 22/27] Replace data.clone() by Arc::clone(&data) in mutex doc. Arc::clone(&from) is considered as more idiomatic because it conveys more explicitly the meaning of the code. --- src/libstd/sync/mutex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 54bfd8122b4ed..ec9207ea45b4f 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -69,7 +69,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult}; /// /// let (tx, rx) = channel(); /// for _ in 0..N { -/// let (data, tx) = (data.clone(), tx.clone()); +/// let (data, tx) = (Arc::clone(&data), tx.clone()); /// thread::spawn(move || { /// // The shared state can only be accessed once the lock is held. /// // Our non-atomic increment is safe because we're the only thread From 41434e001be222a7ce70faf3c5a23d97f462dfb8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 16 Nov 2018 22:17:26 +0100 Subject: [PATCH 23/27] avoid shared ref in UnsafeCell::get --- src/libcore/cell.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9cf42eff219ba..b1ef15b4513ad 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1509,7 +1509,7 @@ impl UnsafeCell { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn get(&self) -> *mut T { - &self.value as *const T as *mut T + self as *const UnsafeCell as *const T as *mut T } } From a7b312f8255db978f0446cf62383402fee02bae3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Nov 2018 09:08:30 +0100 Subject: [PATCH 24/27] erase the tag on casts involving (raw) pointers --- src/librustc_mir/interpret/cast.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 118539fc58ebf..7d636b77ced4c 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -44,16 +44,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } Misc => { + let src_layout = src.layout; let src = self.read_immediate(src)?; - if self.type_is_fat_ptr(src.layout.ty) { - match (*src, self.type_is_fat_ptr(dest.layout.ty)) { + // There are no casts to references + assert!(!dest.layout.ty.is_region_ptr()); + // Hence we make all casts erase the tag + let src = src.erase_tag().with_default_tag(); + + if self.type_is_fat_ptr(src_layout.ty) { + match (src, self.type_is_fat_ptr(dest.layout.ty)) { // pointers to extern types (Immediate::Scalar(_),_) | // slices and trait objects to other slices/trait objects (Immediate::ScalarPair(..), true) => { // No change to immediate - self.write_immediate(*src, dest)?; + self.write_immediate(src, dest)?; } // slices and trait objects to thin pointers (dropping the metadata) (Immediate::ScalarPair(data, _), false) => { @@ -61,11 +67,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } } } else { - match src.layout.variants { + match src_layout.variants { layout::Variants::Single { index } => { - if let Some(def) = src.layout.ty.ty_adt_def() { + if let Some(def) = src_layout.ty.ty_adt_def() { // Cast from a univariant enum - assert!(src.layout.is_zst()); + assert!(src_layout.is_zst()); let discr_val = def .discriminant_for_variant(*self.tcx, index) .val; @@ -78,7 +84,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> layout::Variants::NicheFilling { .. } => {}, } - let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?; + let dest_val = self.cast_scalar(src.to_scalar()?, src_layout, dest.layout)?; self.write_scalar(dest_val, dest)?; } } From 01127ca6669f037030279766c093837421c79384 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 16 Nov 2018 03:08:23 -0800 Subject: [PATCH 25/27] Update Cargo submodule Brings in some fixes and stabilizations! --- src/Cargo.lock | 27 +++++++++++++++++++++++++-- src/tools/cargo | 2 +- src/tools/tidy/src/deps.rs | 2 ++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 8b7f3591a2505..a5b3e7bc55ecc 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -185,11 +185,11 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "crates-io 0.21.0", - "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -539,6 +539,14 @@ name = "crossbeam-utils" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-utils" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crypto-hash" version = "0.3.1" @@ -662,6 +670,18 @@ dependencies = [ "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "env_logger" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "environment" version = "0.1.1" @@ -731,6 +751,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3211,6 +3232,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" +"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816" "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4" "checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16" "checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870" @@ -3223,6 +3245,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee" "checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621" "checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" diff --git a/src/tools/cargo b/src/tools/cargo index 241fac0e39330..b3d0b2e545b61 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 241fac0e3933063fa48a1a01f5d577e40af12e4d +Subproject commit b3d0b2e545b61d4cd08096911724b7d49d213f73 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 72c47273e63b5..2dfb9fc68ac16 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -92,6 +92,7 @@ const WHITELIST: &[Crate] = &[ Crate("kernel32-sys"), Crate("lazy_static"), Crate("libc"), + Crate("libz-sys"), Crate("lock_api"), Crate("log"), Crate("log_settings"), @@ -133,6 +134,7 @@ const WHITELIST: &[Crate] = &[ Crate("utf8-ranges"), Crate("version_check"), Crate("void"), + Crate("vcpkg"), Crate("winapi"), Crate("winapi-build"), Crate("winapi-i686-pc-windows-gnu"), From 25d46f309130be1671d7e44d48e67b23f510bcdc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 17 Nov 2018 10:20:28 +0100 Subject: [PATCH 26/27] add comment explaining why what we do is legal --- src/libcore/cell.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index b1ef15b4513ad..d8d51f53377f7 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1509,6 +1509,8 @@ impl UnsafeCell { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub const fn get(&self) -> *mut T { + // We can just cast the pointer from `UnsafeCell` to `T` because of + // #[repr(transparent)] self as *const UnsafeCell as *const T as *mut T } } From d12de8f1eb54b0df68011cdfbee739bcaaea5616 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 17 Nov 2018 01:50:38 -0800 Subject: [PATCH 27/27] std: Add debugging for a failing test on appveyor I'm not sure why this is failing, so let's hopefully get some more information to help investigation! --- src/libstd/time.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 90ab349159915..651c874583e69 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -481,7 +481,8 @@ mod tests { let (a, b) = ($a, $b); if a != b { let (a, b) = if a > b {(a, b)} else {(b, a)}; - assert!(a - Duration::new(0, 100) <= b); + assert!(a - Duration::new(0, 100) <= b, + "{:?} is not almost equal to {:?}", a, b); } }) }