From d419a5fdaebb36dbf3c600f624c964d9ea651661 Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Sun, 1 Dec 2019 13:39:01 +0100 Subject: [PATCH 01/12] Fix pointing at arg when cause is outside of call --- src/librustc_typeck/check/mod.rs | 65 +++++++++++++++------------ src/test/ui/issues/issue-66923.rs | 13 ++++++ src/test/ui/issues/issue-66923.stderr | 19 ++++++++ 3 files changed, 69 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/issues/issue-66923.rs create mode 100644 src/test/ui/issues/issue-66923.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c7a0190a1d1b..5e644df99bee 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3880,36 +3880,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_sp: Span, args: &'tcx [hir::Expr], ) { - if !call_sp.desugaring_kind().is_some() { - // We *do not* do this for desugared call spans to keep good diagnostics when involving - // the `?` operator. - for error in errors { - if let ty::Predicate::Trait(predicate) = error.obligation.predicate { - // Collect the argument position for all arguments that could have caused this - // `FulfillmentError`. - let mut referenced_in = final_arg_types.iter() - .map(|(i, checked_ty, _)| (i, checked_ty)) - .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty))) - .flat_map(|(i, ty)| { - let ty = self.resolve_vars_if_possible(ty); - // We walk the argument type because the argument's type could have - // been `Option`, but the `FulfillmentError` references `T`. - ty.walk() - .filter(|&ty| ty == predicate.skip_binder().self_ty()) - .map(move |_| *i) - }) - .collect::>(); + // We *do not* do this for desugared call spans to keep good diagnostics when involving + // the `?` operator. + if call_sp.desugaring_kind().is_some() { + return + } + + for error in errors { + // Only if the cause is somewhere inside the expression we want try to point at arg. + // Otherwise, it means that the cause is somewhere else and we should not change + // anything because we can break the correct span. + if !call_sp.contains(error.obligation.cause.span) { + continue + } + + if let ty::Predicate::Trait(predicate) = error.obligation.predicate { + // Collect the argument position for all arguments that could have caused this + // `FulfillmentError`. + let mut referenced_in = final_arg_types.iter() + .map(|(i, checked_ty, _)| (i, checked_ty)) + .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty))) + .flat_map(|(i, ty)| { + let ty = self.resolve_vars_if_possible(ty); + // We walk the argument type because the argument's type could have + // been `Option`, but the `FulfillmentError` references `T`. + ty.walk() + .filter(|&ty| ty == predicate.skip_binder().self_ty()) + .map(move |_| *i) + }) + .collect::>(); - // Both checked and coerced types could have matched, thus we need to remove - // duplicates. - referenced_in.dedup(); + // Both checked and coerced types could have matched, thus we need to remove + // duplicates. + referenced_in.dedup(); - if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { - // We make sure that only *one* argument matches the obligation failure - // and we assign the obligation's span to its expression's. - error.obligation.cause.span = args[ref_in].span; - error.points_at_arg_span = true; - } + if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) { + // We make sure that only *one* argument matches the obligation failure + // and we assign the obligation's span to its expression's. + error.obligation.cause.span = args[ref_in].span; + error.points_at_arg_span = true; } } } diff --git a/src/test/ui/issues/issue-66923.rs b/src/test/ui/issues/issue-66923.rs new file mode 100644 index 000000000000..a452e6384a3d --- /dev/null +++ b/src/test/ui/issues/issue-66923.rs @@ -0,0 +1,13 @@ +fn main() { + let v = vec![1_f64, 2.2_f64]; + let mut fft: Vec> = vec![]; + + let x1: &[f64] = &v; + let x2: Vec = x1.into_iter().collect(); + //~^ ERROR a collection of type + fft.push(x2); + + let x3 = x1.into_iter().collect::>(); + //~^ ERROR a collection of type + fft.push(x3); +} diff --git a/src/test/ui/issues/issue-66923.stderr b/src/test/ui/issues/issue-66923.stderr new file mode 100644 index 000000000000..a2eec7caee50 --- /dev/null +++ b/src/test/ui/issues/issue-66923.stderr @@ -0,0 +1,19 @@ +error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923.rs:6:39 + | +LL | let x2: Vec = x1.into_iter().collect(); + | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923.rs:10:29 + | +LL | let x3 = x1.into_iter().collect::>(); + | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From e305bf8bc8cecaf93080f07962a4f763cd66f5ce Mon Sep 17 00:00:00 2001 From: Janusz Marcinkiewicz Date: Tue, 3 Dec 2019 08:20:17 +0100 Subject: [PATCH 02/12] Rename tests and add short test description --- .../core-traits-no-impls-length-33.rs | 1 + .../core-traits-no-impls-length-33.stderr | 19 ++++++++++++++----- ...ssue-66923-show-error-for-correct-call.rs} | 6 ++++-- ...e-66923-show-error-for-correct-call.stderr | 19 +++++++++++++++++++ src/test/ui/issues/issue-66923.stderr | 19 ------------------- 5 files changed, 38 insertions(+), 26 deletions(-) rename src/test/ui/issues/{issue-66923.rs => issue-66923-show-error-for-correct-call.rs} (61%) create mode 100644 src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr delete mode 100644 src/test/ui/issues/issue-66923.stderr diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs index 8397d204f35c..7fa059583f53 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs @@ -6,6 +6,7 @@ pub fn no_debug() { pub fn no_hash() { use std::collections::HashSet; let mut set = HashSet::new(); + //~^ ERROR arrays only have std trait implementations for lengths 0..=32 set.insert([0_usize; 33]); //~^ ERROR arrays only have std trait implementations for lengths 0..=32 } diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr index 594a0d4b5d84..d885c98dcb28 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr @@ -8,15 +8,24 @@ LL | println!("{:?}", [0_usize; 33]); = note: required by `std::fmt::Debug::fmt` error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/core-traits-no-impls-length-33.rs:9:16 + --> $DIR/core-traits-no-impls-length-33.rs:10:16 | LL | set.insert([0_usize; 33]); | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` | = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]` +error[E0277]: arrays only have std trait implementations for lengths 0..=32 + --> $DIR/core-traits-no-impls-length-33.rs:8:19 + | +LL | let mut set = HashSet::new(); + | ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]` + | + = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]` + = note: required by `std::collections::HashSet::::new` + error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]` - --> $DIR/core-traits-no-impls-length-33.rs:14:19 + --> $DIR/core-traits-no-impls-length-33.rs:15:19 | LL | [0_usize; 33] == [1_usize; 33] | ------------- ^^ ------------- [usize; 33] @@ -26,7 +35,7 @@ LL | [0_usize; 33] == [1_usize; 33] = note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]` error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]` - --> $DIR/core-traits-no-impls-length-33.rs:19:19 + --> $DIR/core-traits-no-impls-length-33.rs:20:19 | LL | [0_usize; 33] < [1_usize; 33] | ------------- ^ ------------- [usize; 33] @@ -36,7 +45,7 @@ LL | [0_usize; 33] < [1_usize; 33] = note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]` error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied - --> $DIR/core-traits-no-impls-length-33.rs:24:14 + --> $DIR/core-traits-no-impls-length-33.rs:25:14 | LL | for _ in &[0_usize; 33] { | ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]` @@ -48,7 +57,7 @@ LL | for _ in &[0_usize; 33] { <&'a mut [T] as std::iter::IntoIterator> = note: required by `std::iter::IntoIterator::into_iter` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0369. For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-66923.rs b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs similarity index 61% rename from src/test/ui/issues/issue-66923.rs rename to src/test/ui/issues/issue-66923-show-error-for-correct-call.rs index a452e6384a3d..833280739724 100644 --- a/src/test/ui/issues/issue-66923.rs +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.rs @@ -1,13 +1,15 @@ +// This test checks that errors are showed for lines with `collect` rather than `push` method. + fn main() { let v = vec![1_f64, 2.2_f64]; let mut fft: Vec> = vec![]; let x1: &[f64] = &v; let x2: Vec = x1.into_iter().collect(); - //~^ ERROR a collection of type + //~^ ERROR a value of type fft.push(x2); let x3 = x1.into_iter().collect::>(); - //~^ ERROR a collection of type + //~^ ERROR a value of type fft.push(x3); } diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr new file mode 100644 index 000000000000..8e7ee97e0b90 --- /dev/null +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -0,0 +1,19 @@ +error[E0277]: a value of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39 + | +LL | let x2: Vec = x1.into_iter().collect(); + | ^^^^^^^ value of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error[E0277]: a value of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` + --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29 + | +LL | let x3 = x1.into_iter().collect::>(); + | ^^^^^^^ value of type `std::vec::Vec` cannot be built from `std::iter::Iterator` + | + = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-66923.stderr b/src/test/ui/issues/issue-66923.stderr deleted file mode 100644 index a2eec7caee50..000000000000 --- a/src/test/ui/issues/issue-66923.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` - --> $DIR/issue-66923.rs:6:39 - | -LL | let x2: Vec = x1.into_iter().collect(); - | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` - | - = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` - -error[E0277]: a collection of type `std::vec::Vec` cannot be built from an iterator over elements of type `&f64` - --> $DIR/issue-66923.rs:10:29 - | -LL | let x3 = x1.into_iter().collect::>(); - | ^^^^^^^ a collection of type `std::vec::Vec` cannot be built from `std::iter::Iterator` - | - = help: the trait `std::iter::FromIterator<&f64>` is not implemented for `std::vec::Vec` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. From 3594d8b8a14d48c8aec90a2e702cf312ea2d7f02 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sun, 15 Dec 2019 12:47:40 +0000 Subject: [PATCH 03/12] make htons const fn --- src/libstd/net/addr.rs | 14 +++++++------- src/libstd/net/mod.rs | 19 ++++--------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index d5f4ece726be..a9d88370c612 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -4,7 +4,7 @@ use crate::hash; use crate::io; use crate::iter; use crate::mem; -use crate::net::{hton, ntoh, IpAddr, Ipv4Addr, Ipv6Addr}; +use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr}; use crate::option; use crate::slice; use crate::sys::net::netc as c; @@ -276,7 +276,7 @@ impl SocketAddrV4 { SocketAddrV4 { inner: c::sockaddr_in { sin_family: c::AF_INET as c::sa_family_t, - sin_port: hton(port), + sin_port: htons(port), sin_addr: *ip.as_inner(), ..unsafe { mem::zeroed() } }, @@ -326,7 +326,7 @@ impl SocketAddrV4 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { - ntoh(self.inner.sin_port) + ntohs(self.inner.sin_port) } /// Changes the port number associated with this socket address. @@ -342,7 +342,7 @@ impl SocketAddrV4 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { - self.inner.sin_port = hton(new_port); + self.inner.sin_port = htons(new_port); } } @@ -368,7 +368,7 @@ impl SocketAddrV6 { SocketAddrV6 { inner: c::sockaddr_in6 { sin6_family: c::AF_INET6 as c::sa_family_t, - sin6_port: hton(port), + sin6_port: htons(port), sin6_addr: *ip.as_inner(), sin6_flowinfo: flowinfo, sin6_scope_id: scope_id, @@ -420,7 +420,7 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { - ntoh(self.inner.sin6_port) + ntohs(self.inner.sin6_port) } /// Changes the port number associated with this socket address. @@ -436,7 +436,7 @@ impl SocketAddrV6 { /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { - self.inner.sin6_port = hton(new_port); + self.inner.sin6_port = htons(new_port); } /// Returns the flow information associated with this address. diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index b68146939fdc..8652ed8b046b 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -85,21 +85,10 @@ pub enum Shutdown { Both, } -#[doc(hidden)] -trait NetInt { - fn from_be(i: Self) -> Self; - fn to_be(&self) -> Self; -} -macro_rules! doit { - ($($t:ident)*) => ($(impl NetInt for $t { - fn from_be(i: Self) -> Self { <$t>::from_be(i) } - fn to_be(&self) -> Self { <$t>::to_be(*self) } - })*) -} -doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } - -fn hton(i: I) -> I { i.to_be() } -fn ntoh(i: I) -> I { I::from_be(i) } +#[inline] +const fn htons(i: u16) -> u16 { i.to_be() } +#[inline] +const fn ntohs(i: u16) -> u16 { u16::from_be(i) } fn each_addr(addr: A, mut f: F) -> io::Result where F: FnMut(io::Result<&SocketAddr>) -> io::Result From 6ad0b55597d58f65b775cc32588d5cb396993c0c Mon Sep 17 00:00:00 2001 From: Robin Kruppe Date: Sun, 15 Dec 2019 18:17:00 +0100 Subject: [PATCH 04/12] Remove now-redundant range check on u128 -> f32 casts This code was added to avoid UB in LLVM 6 and earlier, but we no longer support those LLVM versions. Since https://reviews.llvm.org/D47807 (released in LLVM 7), uitofp does exactly what we need. Closes #51872 --- src/librustc_codegen_ssa/mir/rvalue.rs | 43 +++++--------------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 488ae8dbf903..55d63f18cd90 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -341,6 +341,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { llval } } + (CastTy::Int(_), CastTy::Float) => { + if signed { + bx.sitofp(llval, ll_t_out) + } else { + bx.uitofp(llval, ll_t_out) + } + } (CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FnPtr, CastTy::Ptr(_)) | (CastTy::RPtr(_), CastTy::Ptr(_)) => @@ -352,8 +359,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed); bx.inttoptr(usize_llval, ll_t_out) } - (CastTy::Int(_), CastTy::Float) => - cast_int_to_float(&mut bx, signed, llval, ll_t_in, ll_t_out), (CastTy::Float, CastTy::Int(IntTy::I)) => cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out), (CastTy::Float, CastTy::Int(_)) => @@ -720,40 +725,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } -fn cast_int_to_float<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( - bx: &mut Bx, - signed: bool, - x: Bx::Value, - int_ty: Bx::Type, - float_ty: Bx::Type -) -> Bx::Value { - // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding. - // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity). - // LLVM's uitofp produces undef in those cases, so we manually check for that case. - let is_u128_to_f32 = !signed && - bx.cx().int_width(int_ty) == 128 && - bx.cx().float_width(float_ty) == 32; - if is_u128_to_f32 { - // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity, - // and for everything else LLVM's uitofp works just fine. - use rustc_apfloat::ieee::Single; - const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1) - << (Single::MAX_EXP - Single::PRECISION as i16); - let max = bx.cx().const_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP); - let overflow = bx.icmp(IntPredicate::IntUGE, x, max); - let infinity_bits = bx.cx().const_u32(ieee::Single::INFINITY.to_bits() as u32); - let infinity = bx.bitcast(infinity_bits, float_ty); - let fp = bx.uitofp(x, float_ty); - bx.select(overflow, infinity, fp) - } else { - if signed { - bx.sitofp(x, float_ty) - } else { - bx.uitofp(x, float_ty) - } - } -} - fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, signed: bool, From 720b865ea91c9af29fefc9a42ed9d9f692429e4b Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 15 Dec 2019 14:07:30 -0500 Subject: [PATCH 05/12] [mir-opt] Fix `Inline` pass to handle inlining into `box` expressions --- src/librustc_mir/transform/inline.rs | 30 +++++--- .../mir-opt/inline/inline-into-box-place.rs | 70 +++++++++++++++++++ 2 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 src/test/mir-opt/inline/inline-into-box-place.rs diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 9763913082dd..dca142279463 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -663,9 +663,9 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> { fn make_integrate_local(&self, local: &Local) -> Local { if *local == RETURN_PLACE { - match self.destination.as_local() { - Some(l) => return l, - ref place => bug!("Return place is {:?}, not local", place), + match self.destination.base { + PlaceBase::Local(l) => return l, + PlaceBase::Static(ref s) => bug!("Return place is {:?}, not local", s), } } @@ -695,14 +695,24 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { fn visit_place( &mut self, place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, + _context: PlaceContext, + _location: Location, ) { - if let Some(RETURN_PLACE) = place.as_local() { - // Return pointer; update the place itself - *place = self.destination.clone(); - } else { - self.super_place(place, context, location); + match &mut place.base { + PlaceBase::Static(_) => {}, + PlaceBase::Local(l) => { + // If this is the `RETURN_PLACE`, we need to rebase any projections onto it. + let dest_proj_len = self.destination.projection.len(); + if *l == RETURN_PLACE && dest_proj_len > 0 { + let mut projs = Vec::with_capacity(dest_proj_len + place.projection.len()); + projs.extend(self.destination.projection); + projs.extend(place.projection); + + place.projection = self.tcx.intern_place_elems(&*projs); + } + + *l = self.make_integrate_local(l); + } } } diff --git a/src/test/mir-opt/inline/inline-into-box-place.rs b/src/test/mir-opt/inline/inline-into-box-place.rs new file mode 100644 index 000000000000..e96b61a59932 --- /dev/null +++ b/src/test/mir-opt/inline/inline-into-box-place.rs @@ -0,0 +1,70 @@ +// ignore-tidy-linelength +#![feature(box_syntax)] + +fn main() { + let _x: Box> = box Vec::new(); +} + +// END RUST SOURCE +// START rustc.main.Inline.before.mir +// let mut _0: (); +// let _1: std::boxed::Box> as UserTypeProjection { base: UserType(0), projs: [] }; +// let mut _2: std::boxed::Box>; +// let mut _3: (); +// scope 1 { +// debug _x => _1; +// } +// bb0: { +// StorageLive(_1); +// StorageLive(_2); +// _2 = Box(std::vec::Vec); +// (*_2) = const std::vec::Vec::::new() -> [return: bb2, unwind: bb4]; +// } +// bb1 (cleanup): { +// resume; +// } +// bb2: { +// _1 = move _2; +// StorageDead(_2); +// _0 = (); +// drop(_1) -> [return: bb3, unwind: bb1]; +// } +// bb3: { +// StorageDead(_1); +// return; +// } +// bb4 (cleanup): { +// _3 = const alloc::alloc::box_free::>(move (_2.0: std::ptr::Unique>)) -> bb1; +// } +// END rustc.main.Inline.before.mir +// START rustc.main.Inline.after.mir +// let mut _0: (); +// let _1: std::boxed::Box> as UserTypeProjection { base: UserType(0), projs: [] }; +// let mut _2: std::boxed::Box>; +// let mut _3: (); +// let mut _4: &mut std::vec::Vec; +// scope 1 { +// debug _x => _1; +// } +// scope 2 { +// } +// bb0: { +// StorageLive(_1); +// StorageLive(_2); +// _2 = Box(std::vec::Vec); +// _4 = &mut (*_2); +// ((*_4).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec::::NEW; +// ((*_4).1: usize) = const 0usize; +// _1 = move _2; +// StorageDead(_2); +// _0 = (); +// drop(_1) -> [return: bb2, unwind: bb1]; +// } +// bb1 (cleanup): { +// resume; +// } +// bb2: { +// StorageDead(_1); +// return; +// } +// END rustc.main.Inline.after.mir From b50cee316dc1281b8949fc6dced1e986393d6c18 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 15 Dec 2019 15:37:28 -0500 Subject: [PATCH 06/12] Move the rest of the mir-opt inline tests into a folder --- src/test/mir-opt/{ => inline}/inline-any-operand.rs | 0 src/test/mir-opt/{ => inline}/inline-closure-borrows-arg.rs | 0 src/test/mir-opt/{ => inline}/inline-closure-captures.rs | 0 src/test/mir-opt/{ => inline}/inline-closure.rs | 0 src/test/mir-opt/{ => inline}/inline-retag.rs | 0 src/test/mir-opt/{ => inline}/inline-trait-method.rs | 0 src/test/mir-opt/{ => inline}/inline-trait-method_2.rs | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename src/test/mir-opt/{ => inline}/inline-any-operand.rs (100%) rename src/test/mir-opt/{ => inline}/inline-closure-borrows-arg.rs (100%) rename src/test/mir-opt/{ => inline}/inline-closure-captures.rs (100%) rename src/test/mir-opt/{ => inline}/inline-closure.rs (100%) rename src/test/mir-opt/{ => inline}/inline-retag.rs (100%) rename src/test/mir-opt/{ => inline}/inline-trait-method.rs (100%) rename src/test/mir-opt/{ => inline}/inline-trait-method_2.rs (100%) diff --git a/src/test/mir-opt/inline-any-operand.rs b/src/test/mir-opt/inline/inline-any-operand.rs similarity index 100% rename from src/test/mir-opt/inline-any-operand.rs rename to src/test/mir-opt/inline/inline-any-operand.rs diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline/inline-closure-borrows-arg.rs similarity index 100% rename from src/test/mir-opt/inline-closure-borrows-arg.rs rename to src/test/mir-opt/inline/inline-closure-borrows-arg.rs diff --git a/src/test/mir-opt/inline-closure-captures.rs b/src/test/mir-opt/inline/inline-closure-captures.rs similarity index 100% rename from src/test/mir-opt/inline-closure-captures.rs rename to src/test/mir-opt/inline/inline-closure-captures.rs diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline/inline-closure.rs similarity index 100% rename from src/test/mir-opt/inline-closure.rs rename to src/test/mir-opt/inline/inline-closure.rs diff --git a/src/test/mir-opt/inline-retag.rs b/src/test/mir-opt/inline/inline-retag.rs similarity index 100% rename from src/test/mir-opt/inline-retag.rs rename to src/test/mir-opt/inline/inline-retag.rs diff --git a/src/test/mir-opt/inline-trait-method.rs b/src/test/mir-opt/inline/inline-trait-method.rs similarity index 100% rename from src/test/mir-opt/inline-trait-method.rs rename to src/test/mir-opt/inline/inline-trait-method.rs diff --git a/src/test/mir-opt/inline-trait-method_2.rs b/src/test/mir-opt/inline/inline-trait-method_2.rs similarity index 100% rename from src/test/mir-opt/inline-trait-method_2.rs rename to src/test/mir-opt/inline/inline-trait-method_2.rs From aa0ef5a01ff329daa822e7443ca7d6ae2bfc8476 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Dec 2019 14:15:57 -0800 Subject: [PATCH 07/12] Fix handling of wasm import modules and names The WebAssembly targets of rustc have weird issues around name mangling and import the same name from different modules. This all largely stems from the fact that we're using literal symbol names in LLVM IR to represent what a function is called when it's imported, and we're not using the wasm-specific `wasm-import-name` attribute. This in turn leads to two issues: * If, in the same codegen unit, the same FFI symbol is referenced twice then rustc, when translating to LLVM IR, will only reference one symbol from the first wasm module referenced. * There's also a bug in LLD [1] where even if two codegen units reference different modules, having the same symbol names means that LLD coalesces the symbols and only refers to one wasm module. Put another way, all our imported wasm symbols from the environment are keyed off their LLVM IR symbol name, which has lots of collisions today. This commit fixes the issue by implementing two changes: 1. All wasm symbols with `#[link(wasm_import_module = "...")]` are mangled by default in LLVM IR. This means they're all given unique names. 2. Symbols then use the `wasm-import-name` attribute to ensure that the WebAssembly file uses the correct import name. When put together this should ensure we don't trip over the LLD bug [1] and we also codegen IR correctly always referencing the right symbols with the right import module/name pairs. Closes #50021 Closes #56309 Closes #63562 [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 --- src/librustc_codegen_llvm/attributes.rs | 11 +++++++ src/librustc_codegen_utils/symbol_names.rs | 28 +++++++++++++--- .../wasm-symbols-different-module/Makefile | 28 ++++++++++++++++ .../wasm-symbols-different-module/bar.rs | 33 +++++++++++++++++++ .../wasm-symbols-different-module/baz.rs | 22 +++++++++++++ .../wasm-symbols-different-module/foo.rs | 23 +++++++++++++ .../wasm-symbols-different-module/log.rs | 16 +++++++++ .../verify-imports.js | 32 ++++++++++++++++++ 8 files changed, 189 insertions(+), 4 deletions(-) create mode 100644 src/test/run-make/wasm-symbols-different-module/Makefile create mode 100644 src/test/run-make/wasm-symbols-different-module/bar.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/baz.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/foo.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/log.rs create mode 100644 src/test/run-make/wasm-symbols-different-module/verify-imports.js diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 1ea9362dc426..6779cce1f8a5 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -343,6 +343,17 @@ pub fn from_fn_attrs( const_cstr!("wasm-import-module"), &module, ); + + let name = codegen_fn_attrs.link_name.unwrap_or_else(|| { + cx.tcx.item_name(instance.def_id()) + }); + let name = CString::new(&name.as_str()[..]).unwrap(); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + const_cstr!("wasm-import-name"), + &name, + ); } } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index c52c6cfa83c9..922964ee45f6 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -142,12 +142,32 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { }; let attrs = tcx.codegen_fn_attrs(def_id); + + // Foreign items by default use no mangling for their symbol name. There's a + // few exceptions to this rule though: + // + // * This can be overridden with the `#[link_name]` attribute + // + // * On the wasm32 targets there is a bug (or feature) in LLD [1] where the + // same-named symbol when imported from different wasm modules will get + // hooked up incorectly. As a result foreign symbols, on the wasm target, + // with a wasm import module, get mangled. Additionally our codegen will + // deduplicate symbols based purely on the symbol name, but for wasm this + // isn't quite right because the same-named symbol on wasm can come from + // different modules. For these reasons if `#[link(wasm_import_module)]` + // is present we mangle everything on wasm because the demangled form will + // show up in the `wasm-import-name` custom attribute in LLVM IR. + // + // [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 if is_foreign { - if let Some(name) = attrs.link_name { - return name; + if tcx.sess.target.target.arch != "wasm32" || + !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id) + { + if let Some(name) = attrs.link_name { + return name; + } + return tcx.item_name(def_id); } - // Don't mangle foreign items. - return tcx.item_name(def_id); } if let Some(name) = attrs.export_name { diff --git a/src/test/run-make/wasm-symbols-different-module/Makefile b/src/test/run-make/wasm-symbols-different-module/Makefile new file mode 100644 index 000000000000..bb6a5d3c9d24 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/Makefile @@ -0,0 +1,28 @@ +-include ../../run-make-fulldeps/tools.mk + +# only-wasm32-bare + +all: + $(RUSTC) foo.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + $(RUSTC) foo.rs --target wasm32-unknown-unknown -O + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + $(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto + $(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo + + $(RUSTC) bar.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + $(RUSTC) bar.rs --target wasm32-unknown-unknown -C lto + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + $(RUSTC) bar.rs --target wasm32-unknown-unknown -O + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + $(RUSTC) bar.rs --target wasm32-unknown-unknown -O -C lto + $(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f + + $(RUSTC) baz.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/baz.wasm sqlite/allocate sqlite/deallocate + + $(RUSTC) log.rs --target wasm32-unknown-unknown + $(NODE) verify-imports.js $(TMPDIR)/log.wasm test/log diff --git a/src/test/run-make/wasm-symbols-different-module/bar.rs b/src/test/run-make/wasm-symbols-different-module/bar.rs new file mode 100644 index 000000000000..7567060d7813 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/bar.rs @@ -0,0 +1,33 @@ +//! Issue #50021 + +#![crate_type = "cdylib"] + +mod m1 { + #[link(wasm_import_module = "m1")] + extern "C" { + pub fn f(); + } + #[link(wasm_import_module = "m1")] + extern "C" { + pub fn g(); + } +} + +mod m2 { + #[link(wasm_import_module = "m2")] + extern "C" { + pub fn f(_: i32); + } +} + +#[no_mangle] +pub unsafe fn run() { + m1::f(); + m1::g(); + + // In generated code, expected: + // (import "m2" "f" (func $f (param i32))) + // but got: + // (import "m1" "f" (func $f (param i32))) + m2::f(0); +} diff --git a/src/test/run-make/wasm-symbols-different-module/baz.rs b/src/test/run-make/wasm-symbols-different-module/baz.rs new file mode 100644 index 000000000000..fbb78619bb8f --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/baz.rs @@ -0,0 +1,22 @@ +//! Issue #63562 + +#![crate_type = "cdylib"] + +mod foo { + #[link(wasm_import_module = "sqlite")] + extern "C" { + pub fn allocate(size: usize) -> i32; + pub fn deallocate(ptr: i32, size: usize); + } +} + +#[no_mangle] +pub extern "C" fn allocate() { + unsafe { + foo::allocate(1); + foo::deallocate(1, 2); + } +} + +#[no_mangle] +pub extern "C" fn deallocate() {} diff --git a/src/test/run-make/wasm-symbols-different-module/foo.rs b/src/test/run-make/wasm-symbols-different-module/foo.rs new file mode 100644 index 000000000000..a4ba7e714cc7 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/foo.rs @@ -0,0 +1,23 @@ +#![crate_type = "cdylib"] + +mod a { + #[link(wasm_import_module = "a")] + extern "C" { + pub fn foo(); + } +} + +mod b { + #[link(wasm_import_module = "b")] + extern "C" { + pub fn foo(); + } +} + +#[no_mangle] +pub fn start() { + unsafe { + a::foo(); + b::foo(); + } +} diff --git a/src/test/run-make/wasm-symbols-different-module/log.rs b/src/test/run-make/wasm-symbols-different-module/log.rs new file mode 100644 index 000000000000..ea3e0b4b2be9 --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/log.rs @@ -0,0 +1,16 @@ +//! Issue #56309 + +#![crate_type = "cdylib"] + +#[link(wasm_import_module = "test")] +extern "C" { + fn log(message_data: u32, message_size: u32); +} + +#[no_mangle] +pub fn main() { + let message = "Hello, world!"; + unsafe { + log(message.as_ptr() as u32, message.len() as u32); + } +} diff --git a/src/test/run-make/wasm-symbols-different-module/verify-imports.js b/src/test/run-make/wasm-symbols-different-module/verify-imports.js new file mode 100644 index 000000000000..7e9f90cf8bdc --- /dev/null +++ b/src/test/run-make/wasm-symbols-different-module/verify-imports.js @@ -0,0 +1,32 @@ +const fs = require('fs'); +const process = require('process'); +const assert = require('assert'); +const buffer = fs.readFileSync(process.argv[2]); + +let m = new WebAssembly.Module(buffer); +let list = WebAssembly.Module.imports(m); +console.log('imports', list); +if (list.length !== process.argv.length - 3) + throw new Error("wrong number of imports") + +const imports = new Map(); +for (let i = 3; i < process.argv.length; i++) { + const [module, name] = process.argv[i].split('/'); + if (!imports.has(module)) + imports.set(module, new Map()); + imports.get(module).set(name, true); +} + +for (let i of list) { + if (imports.get(i.module) === undefined || imports.get(i.module).get(i.name) === undefined) + throw new Error(`didn't find import of ${i.module}::${i.name}`); + imports.get(i.module).delete(i.name); + + if (imports.get(i.module).size === 0) + imports.delete(i.module); +} + +console.log(imports); +if (imports.size !== 0) { + throw new Error('extra imports'); +} From e77a55b5d91a7876e4ba23179d15ed0ce4affeb7 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Tue, 17 Dec 2019 23:41:55 +0100 Subject: [PATCH 08/12] Remove outdated references to @T from comments --- src/libsyntax/ptr.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index d987dc855b61..e75cc8b1756d 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -1,17 +1,12 @@ //! The AST pointer. //! -//! Provides `P`, a frozen owned smart pointer, as a replacement for `@T` in -//! the AST. +//! Provides `P`, a frozen owned smart pointer. //! //! # Motivations and benefits //! //! * **Identity**: sharing AST nodes is problematic for the various analysis //! passes (e.g., one may be able to bypass the borrow checker with a shared -//! `ExprKind::AddrOf` node taking a mutable borrow). The only reason `@T` in the -//! AST hasn't caused issues is because of inefficient folding passes which -//! would always deduplicate any such shared nodes. Even if the AST were to -//! switch to an arena, this would still hold, i.e., it couldn't use `&'a T`, -//! but rather a wrapper like `P<'a, T>`. +//! `ExprKind::AddrOf` node taking a mutable borrow). //! //! * **Immutability**: `P` disallows mutating its inner `T`, unlike `Box` //! (unless it contains an `Unsafe` interior, but that may be denied later). From 71278cbdcb0aaf93edd370c6aec24d670a3c1eab Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 28 Oct 2019 14:02:59 +1100 Subject: [PATCH 09/12] Remove some unnecessary `ATTR_*` constants. --- src/librustc/ich/mod.rs | 22 ++++++------------- src/librustc_incremental/assert_dep_graph.rs | 9 ++++---- .../assert_module_sources.rs | 8 +++---- .../persist/dirty_clean.rs | 7 +++--- 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index ece438266c0c..cd2e32de9d5c 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -12,21 +12,13 @@ mod impls_hir; mod impls_ty; mod impls_syntax; -pub const ATTR_DIRTY: Symbol = sym::rustc_dirty; -pub const ATTR_CLEAN: Symbol = sym::rustc_clean; -pub const ATTR_IF_THIS_CHANGED: Symbol = sym::rustc_if_this_changed; -pub const ATTR_THEN_THIS_WOULD_NEED: Symbol = sym::rustc_then_this_would_need; -pub const ATTR_PARTITION_REUSED: Symbol = sym::rustc_partition_reused; -pub const ATTR_PARTITION_CODEGENED: Symbol = sym::rustc_partition_codegened; -pub const ATTR_EXPECTED_CGU_REUSE: Symbol = sym::rustc_expected_cgu_reuse; - pub const IGNORED_ATTRIBUTES: &[Symbol] = &[ sym::cfg, - ATTR_IF_THIS_CHANGED, - ATTR_THEN_THIS_WOULD_NEED, - ATTR_DIRTY, - ATTR_CLEAN, - ATTR_PARTITION_REUSED, - ATTR_PARTITION_CODEGENED, - ATTR_EXPECTED_CGU_REUSE, + sym::rustc_if_this_changed, + sym::rustc_then_this_would_need, + sym::rustc_dirty, + sym::rustc_clean, + sym::rustc_partition_reused, + sym::rustc_partition_codegened, + sym::rustc_expected_cgu_reuse, ]; diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 07d426af6ee9..e3e3b0b17483 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -44,11 +44,10 @@ use rustc_data_structures::graph::implementation::{ }; use rustc::hir; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc::ich::{ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED}; use std::env; use std::fs::{self, File}; use std::io::Write; -use syntax::ast; +use syntax::{ast, symbol::sym}; use syntax_pos::Span; pub fn assert_dep_graph(tcx: TyCtxt<'_>) { @@ -78,7 +77,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { assert!(tcx.sess.opts.debugging_opts.query_dep_graph, "cannot use the `#[{}]` or `#[{}]` annotations \ without supplying `-Z query-dep-graph`", - ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED); + sym::rustc_if_this_changed, sym::rustc_then_this_would_need); } // Check paths. @@ -114,7 +113,7 @@ impl IfThisChanged<'tcx> { let def_id = self.tcx.hir().local_def_id(hir_id); let def_path_hash = self.tcx.def_path_hash(def_id); for attr in attrs { - if attr.check_name(ATTR_IF_THIS_CHANGED) { + if attr.check_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { None => def_path_hash.to_dep_node(DepKind::Hir), @@ -130,7 +129,7 @@ impl IfThisChanged<'tcx> { } }; self.if_this_changed.push((attr.span, def_id, dep_node)); - } else if attr.check_name(ATTR_THEN_THIS_WOULD_NEED) { + } else if attr.check_name(sym::rustc_then_this_would_need) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => { diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index c2e3fa8f28d2..1a675ea002cd 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -28,8 +28,6 @@ use rustc::ty::TyCtxt; use std::collections::BTreeSet; use syntax::ast; use syntax::symbol::{Symbol, sym}; -use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED, - ATTR_EXPECTED_CGU_REUSE}; pub fn assert_module_sources(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { @@ -62,11 +60,11 @@ struct AssertModuleSource<'tcx> { impl AssertModuleSource<'tcx> { fn check_attr(&self, attr: &ast::Attribute) { - let (expected_reuse, comp_kind) = if attr.check_name(ATTR_PARTITION_REUSED) { + let (expected_reuse, comp_kind) = if attr.check_name(sym::rustc_partition_reused) { (CguReuse::PreLto, ComparisonKind::AtLeast) - } else if attr.check_name(ATTR_PARTITION_CODEGENED) { + } else if attr.check_name(sym::rustc_partition_codegened) { (CguReuse::No, ComparisonKind::Exact) - } else if attr.check_name(ATTR_EXPECTED_CGU_REUSE) { + } else if attr.check_name(sym::rustc_expected_cgu_reuse) { match &*self.field(attr, sym::kind).as_str() { "no" => (CguReuse::No, ComparisonKind::Exact), "pre-lto" => (CguReuse::PreLto, ComparisonKind::Exact), diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index ea156a94ea17..c919db070a6b 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -22,7 +22,6 @@ use rustc::hir::Node as HirNode; use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; -use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN}; use rustc::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; @@ -224,7 +223,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { let mut all_attrs = FindAllAttrs { tcx, - attr_names: vec![ATTR_DIRTY, ATTR_CLEAN], + attr_names: vec![sym::rustc_dirty, sym::rustc_clean], found_attrs: vec![], }; intravisit::walk_crate(&mut all_attrs, krate); @@ -246,9 +245,9 @@ impl DirtyCleanVisitor<'tcx> { fn assertion_maybe(&mut self, item_id: hir::HirId, attr: &Attribute) -> Option { - let is_clean = if attr.check_name(ATTR_DIRTY) { + let is_clean = if attr.check_name(sym::rustc_dirty) { false - } else if attr.check_name(ATTR_CLEAN) { + } else if attr.check_name(sym::rustc_clean) { true } else { // skip: not rustc_clean/dirty From 58910255aab6634044fe2b6870a0ea6a4bfa0d6a Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 18 Dec 2019 08:46:00 +0100 Subject: [PATCH 10/12] Remove `SO_NOSIGPIPE` dummy variable on platforms that don't use it. --- src/libstd/sys/unix/net.rs | 17 ++++++----------- src/libstd/sys/vxworks/net.rs | 1 - 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 946b2b9d8dec..5d101ed1f2e2 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -28,14 +28,6 @@ use libc::SOCK_CLOEXEC; #[cfg(not(target_os = "linux"))] const SOCK_CLOEXEC: c_int = 0; -// Another conditional constant for name resolution: Macos et iOS use -// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. -// Other platforms do otherwise. -#[cfg(target_vendor = "apple")] -use libc::SO_NOSIGPIPE; -#[cfg(not(target_vendor = "apple"))] -const SO_NOSIGPIPE: c_int = 0; - pub struct Socket(FileDesc); pub fn init() {} @@ -89,9 +81,12 @@ impl Socket { let fd = FileDesc::new(fd); fd.set_cloexec()?; let socket = Socket(fd); - if cfg!(target_vendor = "apple") { - setsockopt(&socket, libc::SOL_SOCKET, SO_NOSIGPIPE, 1)?; - } + + // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt` + // flag to disable `SIGPIPE` emission on socket. + #[cfg(target_vendor = "apple")] + setsockopt(&socket, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1)?; + Ok(socket) } } diff --git a/src/libstd/sys/vxworks/net.rs b/src/libstd/sys/vxworks/net.rs index 85f5fcff2c25..54466ff2c2e0 100644 --- a/src/libstd/sys/vxworks/net.rs +++ b/src/libstd/sys/vxworks/net.rs @@ -19,7 +19,6 @@ pub extern crate libc as netc; pub type wrlen_t = size_t; const SOCK_CLOEXEC: c_int = 0; -const SO_NOSIGPIPE: c_int = 0; pub struct Socket(FileDesc); From 9ce7f809ba53bdcddbf56004cd77afa52cfe4546 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 18 Dec 2019 14:19:03 +0100 Subject: [PATCH 11/12] Allow -Cllvm-args to override rustc's default LLVM args. --- src/librustc_codegen_llvm/llvm_util.rs | 46 ++++++++++++++++++-------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 40739387b00c..6f9bb6d1ac55 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -3,6 +3,7 @@ use crate::llvm; use syntax_pos::symbol::Symbol; use rustc::session::Session; use rustc::session::config::PrintRequest; +use rustc_data_structures::fx::FxHashSet; use rustc_target::spec::{MergeFunctions, PanicStrategy}; use libc::c_int; use std::ffi::CString; @@ -51,20 +52,39 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMRustInstallFatalErrorHandler(); + fn llvm_arg_to_arg_name(full_arg: &str) -> &str { + full_arg.trim().split(|c: char| { + c == '=' || c.is_whitespace() + }).next().unwrap_or("") + } + + let user_specified_args: FxHashSet<_> = sess + .opts + .cg + .llvm_args + .iter() + .map(|s| llvm_arg_to_arg_name(s)) + .filter(|s| s.len() > 0) + .collect(); + { - let mut add = |arg: &str| { - let s = CString::new(arg).unwrap(); - llvm_args.push(s.as_ptr()); - llvm_c_strs.push(s); + // This adds the given argument to LLVM. Unless `force` is true + // user specified arguments are *not* overridden. + let mut add = |arg: &str, force: bool| { + if force || !user_specified_args.contains(llvm_arg_to_arg_name(arg)) { + let s = CString::new(arg).unwrap(); + llvm_args.push(s.as_ptr()); + llvm_c_strs.push(s); + } }; - add("rustc"); // fake program name - if sess.time_llvm_passes() { add("-time-passes"); } - if sess.print_llvm_passes() { add("-debug-pass=Structure"); } + add("rustc", true); // fake program name + if sess.time_llvm_passes() { add("-time-passes", false); } + if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } if sess.opts.debugging_opts.disable_instrumentation_preinliner { - add("-disable-preinline"); + add("-disable-preinline", false); } if sess.opts.debugging_opts.generate_arange_section { - add("-generate-arange-section"); + add("-generate-arange-section", false); } if get_major_version() >= 8 { match sess.opts.debugging_opts.merge_functions @@ -72,22 +92,22 @@ unsafe fn configure_llvm(sess: &Session) { MergeFunctions::Disabled | MergeFunctions::Trampolines => {} MergeFunctions::Aliases => { - add("-mergefunc-use-aliases"); + add("-mergefunc-use-aliases", false); } } } if sess.target.target.target_os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind { - add("-enable-emscripten-cxx-exceptions"); + add("-enable-emscripten-cxx-exceptions", false); } // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes // during inlining. Unfortunately these may block other optimizations. - add("-preserve-alignment-assumptions-during-inlining=false"); + add("-preserve-alignment-assumptions-during-inlining=false", false); for arg in &sess.opts.cg.llvm_args { - add(&(*arg)); + add(&(*arg), true); } } From 58352fdfea52f0a7d6e680455fa0c27c82a750a1 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 18 Dec 2019 14:28:06 +0100 Subject: [PATCH 12/12] Remove rarely used -Zdisable_instrumentation_preinliner flag. The same effect can be achieved by `-Cllvm-args=-disable-preinline`. --- src/librustc_codegen_llvm/llvm_util.rs | 4 +--- src/librustc_session/config.rs | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 6f9bb6d1ac55..3145b0df63b8 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -80,9 +80,7 @@ unsafe fn configure_llvm(sess: &Session) { add("rustc", true); // fake program name if sess.time_llvm_passes() { add("-time-passes", false); } if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } - if sess.opts.debugging_opts.disable_instrumentation_preinliner { - add("-disable-preinline", false); - } + if sess.opts.debugging_opts.generate_arange_section { add("-generate-arange-section", false); } diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 359c8b3e73a9..0beebab23cb0 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1488,8 +1488,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "extra arguments to prepend to the linker invocation (space separated)"), profile: bool = (false, parse_bool, [TRACKED], "insert profiling code"), - disable_instrumentation_preinliner: bool = (false, parse_bool, [TRACKED], - "Disable the instrumentation pre-inliner, useful for profiling / PGO."), relro_level: Option = (None, parse_relro_level, [TRACKED], "choose which RELRO level to use"), nll_facts: bool = (false, parse_bool, [UNTRACKED],