diff --git a/.travis.yml b/.travis.yml index b208e760d95c6..14fb17aeeddca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -227,9 +227,9 @@ install: chmod +x /usr/local/bin/sccache && travis_retry curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin && chmod +x /usr/local/bin/stamp && - travis_retry curl -f http://releases.llvm.org/6.0.0/clang+llvm-6.0.0-x86_64-apple-darwin.tar.xz | tar xJf - && - export CC=`pwd`/clang+llvm-6.0.0-x86_64-apple-darwin/bin/clang && - export CXX=`pwd`/clang+llvm-6.0.0-x86_64-apple-darwin/bin/clang++ && + travis_retry curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - && + export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang && + export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ && export AR=ar ;; esac diff --git a/appveyor.yml b/appveyor.yml index 372b53b05f238..ac27211217a58 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,8 @@ environment: - SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c + # This is required for at least an AArch64 compiler in one image, and is + # otherwise recommended by AppVeyor currently for seeing if it has any + # affect on our job times. + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview # By default schannel checks revocation of certificates unlike some other SSL # backends, but we've historically had problems on CI where a revocation @@ -88,7 +91,6 @@ environment: DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 CI_JOB_NAME: dist-x86_64-msvc - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview - RUST_CONFIGURE_ARGS: > --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc diff --git a/src/Cargo.lock b/src/Cargo.lock index a5b3e7bc55ecc..94a07f6c91cfa 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2191,7 +2191,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/bootstrap/compile.rs b/src/bootstrap/compile.rs index c8689f7814086..b6bb11d07ef04 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 diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index 8df49f364a372..b087ea7899f4c 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -67,7 +67,7 @@ RUN ./build-gcc.sh COPY dist-x86_64-linux/build-python.sh /tmp/ RUN ./build-python.sh -# Now build LLVM+Clang 6, afterwards configuring further compilations to use the +# Now build LLVM+Clang 7, afterwards configuring further compilations to use the # clang/clang++ compilers. COPY dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index 0a2dae72f7382..a1a778c2b2c61 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -67,7 +67,7 @@ RUN ./build-gcc.sh COPY dist-x86_64-linux/build-python.sh /tmp/ RUN ./build-python.sh -# Now build LLVM+Clang 6, afterwards configuring further compilations to use the +# Now build LLVM+Clang 7, afterwards configuring further compilations to use the # clang/clang++ compilers. COPY dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh diff --git a/src/ci/docker/dist-x86_64-linux/build-clang.sh b/src/ci/docker/dist-x86_64-linux/build-clang.sh index 4595eacb31061..2762f0bf7ec74 100755 --- a/src/ci/docker/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/dist-x86_64-linux/build-clang.sh @@ -13,7 +13,7 @@ set -ex source shared.sh -LLVM=6.0.0 +LLVM=7.0.0 mkdir clang cd clang diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index fcebfb932474c..11d85471b7c08 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -51,7 +51,7 @@ hide_output make clean cd .. -LLVM=60 +LLVM=70 # may have been downloaded in a previous run if [ ! -d libunwind-release_$LLVM ]; then diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 88e76033f273e..cbf104a8fcde9 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -19,7 +19,7 @@ use core::cmp::Ordering; use core::fmt; -use core::iter::{repeat, FromIterator, FusedIterator}; +use core::iter::{repeat, repeat_with, FromIterator, FusedIterator}; use core::mem; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{Index, IndexMut, RangeBounds}; @@ -1920,6 +1920,44 @@ impl VecDeque { self.truncate(new_len); } } + + /// Modifies the `VecDeque` in-place so that `len()` is equal to `new_len`, + /// either by removing excess elements from the back or by appending + /// elements generated by calling `generator` to the back. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_resize_with)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.push_back(5); + /// buf.push_back(10); + /// buf.push_back(15); + /// assert_eq!(buf, [5, 10, 15]); + /// + /// buf.resize_with(5, Default::default); + /// assert_eq!(buf, [5, 10, 15, 0, 0]); + /// + /// buf.resize_with(2, || unreachable!()); + /// assert_eq!(buf, [5, 10]); + /// + /// let mut state = 100; + /// buf.resize_with(5, || { state += 1; state }); + /// assert_eq!(buf, [5, 10, 101, 102, 103]); + /// ``` + #[unstable(feature = "vec_resize_with", issue = "41758")] + pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) { + let len = self.len(); + + if new_len > len { + self.extend(repeat_with(generator).take(new_len - len)) + } else { + self.truncate(new_len); + } + } } /// Returns the index in the underlying buffer for a given logical element index. diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9cf42eff219ba..d8d51f53377f7 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1509,7 +1509,9 @@ 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 + // We can just cast the pointer from `UnsafeCell` to `T` because of + // #[repr(transparent)] + self as *const UnsafeCell as *const T as *mut T } } 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); } 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 e532b50a28b6b..ce1e678043188 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/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f3a62975dd9f4..64685446e8fe1 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, @@ -387,10 +389,10 @@ impl_stable_hash_for!(enum mir::interpret::ErrorHandled { TooGeneric }); -impl_stable_hash_for!(struct mir::interpret::FrameInfo { - span, +impl_stable_hash_for!(struct mir::interpret::FrameInfo<'tcx> { + call_site, lint_root, - location + instance }); impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs }); @@ -451,7 +453,7 @@ impl_stable_hash_for!( FunctionRetMismatch(a, b), NoMirFor(s), UnterminatedCString(ptr), - PointerOutOfBounds { ptr, access, allocation_size }, + PointerOutOfBounds { ptr, check, allocation_size }, InvalidBoolOp(bop), Unimplemented(s), BoundsCheck { len, index }, @@ -471,6 +473,11 @@ impl_stable_hash_for!( } ); +impl_stable_hash_for!(enum mir::interpret::InboundsCheck { + Live, + MaybeDead +}); + impl_stable_hash_for!(enum mir::interpret::Lock { NoLock, WriteLock(dl), 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/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 0114f9e9321e1..502a5828f3ea5 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -389,22 +389,38 @@ where // rule might not apply (but another rule might). For now, we err // on the side of adding too few edges into the graph. + // Compute the bounds we can derive from the trait definition. + // These are guaranteed to apply, no matter the inference + // results. + let trait_bounds: Vec<_> = self.verify_bound + .projection_declared_bounds_from_trait(projection_ty) + .collect(); + // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. - let approx_env_bounds = self.verify_bound + let mut approx_env_bounds = self.verify_bound .projection_approx_declared_bounds_from_env(projection_ty); debug!( "projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds ); - // Compute the bounds we can derive from the trait definition. - // These are guaranteed to apply, no matter the inference - // results. - let trait_bounds: Vec<_> = self.verify_bound - .projection_declared_bounds_from_trait(projection_ty) - .collect(); + // Remove outlives bounds that we get from the environment but + // which are also deducable from the trait. This arises (cc + // #55756) in cases where you have e.g. `>::Item: + // 'a` in the environment but `trait Foo<'b> { type Item: 'b + // }` in the trait definition. + approx_env_bounds.retain(|bound| { + match bound.0.sty { + ty::Projection(projection_ty) => { + self.verify_bound.projection_declared_bounds_from_trait(projection_ty) + .all(|r| r != bound.1) + } + + _ => panic!("expected only projection types from env, not {:?}", bound.0), + } + }); // If declared bounds list is empty, the only applicable rule is // OutlivesProjectionComponent. If there are inference variables, 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/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index cc92b63256c1f..02c0ebcec4fef 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -19,6 +19,14 @@ use mir; use std::ops::{Deref, DerefMut}; use rustc_data_structures::sorted_map::SortedMap; +/// Used by `check_bounds` to indicate whether the pointer needs to be just inbounds +/// or also inbounds of a *live* allocation. +#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable)] +pub enum InboundsCheck { + Live, + MaybeDead, +} + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Allocation { /// The actual bytes of the allocation. diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index f28aa41ed4222..f1c95e0f00024 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -10,20 +10,20 @@ use std::{fmt, env}; +use hir::map::definitions::DefPathData; use mir; -use ty::{Ty, layout}; +use ty::{self, Ty, layout}; use ty::layout::{Size, Align, LayoutError}; use rustc_target::spec::abi::Abi; -use super::{Pointer, Scalar}; +use super::{Pointer, InboundsCheck, ScalarMaybeUndef}; use backtrace::Backtrace; -use ty; use ty::query::TyCtxtAt; use errors::DiagnosticBuilder; -use syntax_pos::Span; +use syntax_pos::{Pos, Span}; use syntax::ast; use syntax::symbol::Symbol; @@ -52,16 +52,35 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; pub struct ConstEvalErr<'tcx> { pub span: Span, pub error: ::mir::interpret::EvalErrorKind<'tcx, u64>, - pub stacktrace: Vec, + pub stacktrace: Vec>, } #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub struct FrameInfo { - pub span: Span, - pub location: String, +pub struct FrameInfo<'tcx> { + pub call_site: Span, // this span is in the caller! + pub instance: ty::Instance<'tcx>, pub lint_root: Option, } +impl<'tcx> fmt::Display for FrameInfo<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ty::tls::with(|tcx| { + if tcx.def_key(self.instance.def_id()).disambiguated_data.data + == DefPathData::ClosureExpr + { + write!(f, "inside call to closure")?; + } else { + write!(f, "inside call to `{}`", self.instance)?; + } + if !self.call_site.is_dummy() { + let lo = tcx.sess.source_map().lookup_char_pos_adj(self.call_site.lo()); + write!(f, " at {}:{}:{}", lo.filename, lo.line, lo.col.to_usize() + 1)?; + } + Ok(()) + }) + } +} + impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { pub fn struct_error(&self, tcx: TyCtxtAt<'a, 'gcx, 'tcx>, @@ -135,8 +154,13 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { struct_error(tcx, message) }; err.span_label(self.span, self.error.to_string()); - for FrameInfo { span, location, .. } in &self.stacktrace { - err.span_label(*span, format!("inside call to `{}`", location)); + // Skip the last, which is just the environment of the constant. The stacktrace + // is sometimes empty because we create "fake" eval contexts in CTFE to do work + // on constant values. + if self.stacktrace.len() > 0 { + for frame_info in &self.stacktrace[..self.stacktrace.len()-1] { + err.span_label(frame_info.call_site, frame_info.to_string()); + } } Ok(err) } @@ -172,16 +196,23 @@ fn print_backtrace(backtrace: &mut Backtrace) -> String { write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap(); 'frames: for (i, frame) in backtrace.frames().iter().enumerate() { if frame.symbols().is_empty() { - write!(trace_text, "{}: no symbols\n", i).unwrap(); + write!(trace_text, " {}: no symbols\n", i).unwrap(); } + let mut first = true; for symbol in frame.symbols() { - write!(trace_text, "{}: ", i).unwrap(); + if first { + write!(trace_text, " {}: ", i).unwrap(); + first = false; + } else { + let len = i.to_string().len(); + write!(trace_text, " {} ", " ".repeat(len)).unwrap(); + } if let Some(name) = symbol.name() { write!(trace_text, "{}\n", name).unwrap(); } else { write!(trace_text, "\n").unwrap(); } - write!(trace_text, "\tat ").unwrap(); + write!(trace_text, " at ").unwrap(); if let Some(file_path) = symbol.filename() { write!(trace_text, "{}", file_path.display()).unwrap(); } else { @@ -240,10 +271,10 @@ pub enum EvalErrorKind<'tcx, O> { InvalidMemoryAccess, InvalidFunctionPointer, InvalidBool, - InvalidDiscriminant(Scalar), + InvalidDiscriminant(ScalarMaybeUndef), PointerOutOfBounds { ptr: Pointer, - access: bool, + check: InboundsCheck, allocation_size: Size, }, InvalidNullPointerUsage, @@ -457,9 +488,13 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use self::EvalErrorKind::*; match *self { - PointerOutOfBounds { ptr, access, allocation_size } => { - write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}", - if access { "memory access" } else { "pointer computed" }, + PointerOutOfBounds { ptr, check, allocation_size } => { + write!(f, "Pointer must be in-bounds{} at offset {}, but is outside bounds of \ + allocation {} which has size {}", + match check { + InboundsCheck::Live => " and live", + InboundsCheck::MaybeDead => "", + }, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) }, ValidationFailure(ref err) => { diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 40daf78f546fb..ec25431bd1ffe 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -28,7 +28,7 @@ pub use self::error::{ pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef}; pub use self::allocation::{ - Allocation, AllocationExtra, + InboundsCheck, Allocation, AllocationExtra, Relocations, UndefMask, }; diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 715ce0d7e805b..c79fa3861234f 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -470,7 +470,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { /// /// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>` /// for `self: Rc`, this means `Rc: DispatchFromDyn>` - /// for `self: Pin>, this means `Pin>: DispatchFromDyn>>` + /// for `self: Pin>`, this means `Pin>: DispatchFromDyn>>` // // FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this // fallback query: `Receiver: Unsize U]>` to support receivers like 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/layout.rs b/src/librustc/ty/layout.rs index 79324bd97a3db..d7fb8da7acd05 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 96f4b1ef8e32a..dfdffa2d54783 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; @@ -731,12 +730,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, } @@ -1343,49 +1347,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> { @@ -1998,6 +2041,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/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/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_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" diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index a01f8940a948a..0aa1924c0e59c 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -664,7 +664,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/const_eval.rs b/src/librustc_mir/const_eval.rs index 7bff76f948e57..51046399ec201 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -365,13 +365,19 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> ret: Option, ) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> { debug!("eval_fn_call: {:?}", instance); - if !ecx.tcx.is_const_fn(instance.def_id()) { + // Execution might have wandered off into other crates, so we cannot to a stability- + // sensitive check here. But we can at least rule out functions that are not const + // at all. + if !ecx.tcx.is_const_fn_raw(instance.def_id()) { // Some functions we support even if they are non-const -- but avoid testing - // that for const fn! - if ecx.hook_fn(instance, args, dest)? { + // that for const fn! We certainly do *not* want to actually call the fn + // though, so be sure we return here. + return if ecx.hook_fn(instance, args, dest)? { ecx.goto_block(ret)?; // fully evaluated and done - return Ok(None); - } + Ok(None) + } else { + err!(MachineError(format!("calling non-const function `{}`", instance))) + }; } // This is a const fn. Call it. Ok(Some(match ecx.load_mir(instance.def) { 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_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)?; } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ca09857bbd5ff..ce7269d1e7839 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -14,7 +14,6 @@ use std::mem; use syntax::source_map::{self, Span, DUMMY_SP}; use rustc::hir::def_id::DefId; use rustc::hir::def::Def; -use rustc::hir::map::definitions::DefPathData; use rustc::mir; use rustc::ty::layout::{ self, Size, Align, HasDataLayout, LayoutOf, TyLayout @@ -667,11 +666,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } } - pub fn generate_stacktrace(&self, explicit_span: Option) -> Vec { + pub fn generate_stacktrace(&self, explicit_span: Option) -> Vec> { let mut last_span = None; let mut frames = Vec::new(); - // skip 1 because the last frame is just the environment of the constant - for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().skip(1).rev() { + for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().rev() { // make sure we don't emit frames that are duplicates of the previous if explicit_span == Some(span) { last_span = Some(span); @@ -684,13 +682,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } else { last_span = Some(span); } - let location = if self.tcx.def_key(instance.def_id()).disambiguated_data.data - == DefPathData::ClosureExpr - { - "closure".to_owned() - } else { - instance.to_string() - }; let block = &mir.basic_blocks()[block]; let source_info = if stmt < block.statements.len() { block.statements[stmt].source_info @@ -701,7 +692,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root), mir::ClearCrossCrate::Clear => None, }; - frames.push(FrameInfo { span, location, lint_root }); + frames.push(FrameInfo { call_site: span, instance, lint_root }); } trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span); frames diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index e125927e7d273..c5a242f334c90 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -28,7 +28,7 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use syntax::ast::Mutability; use super::{ - Pointer, AllocId, Allocation, ConstValue, GlobalId, AllocationExtra, + Pointer, AllocId, Allocation, ConstValue, GlobalId, AllocationExtra, InboundsCheck, EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic, Machine, AllocMap, MayLeak, ScalarMaybeUndef, ErrorHandled, }; @@ -249,17 +249,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // Check non-NULL/Undef, extract offset let (offset, alloc_align) = match ptr { Scalar::Ptr(ptr) => { - let (size, align) = self.get_size_and_align(ptr.alloc_id); // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - if ptr.offset > size { - return err!(PointerOutOfBounds { - ptr: ptr.erase_tag(), - access: true, - allocation_size: size, - }); - }; - // keep data for alignment check + self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead)?; + // data required for alignment check + let (_, align) = self.get_size_and_align(ptr.alloc_id); (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { @@ -293,18 +287,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end /// of an allocation (i.e., at the first *inaccessible* location) *is* considered - /// in-bounds! This follows C's/LLVM's rules. The `access` boolean is just used - /// for the error message. - /// If you want to check bounds before doing a memory access, be sure to - /// check the pointer one past the end of your access, then everything will - /// work out exactly. - pub fn check_bounds_ptr(&self, ptr: Pointer, access: bool) -> EvalResult<'tcx> { - let alloc = self.get(ptr.alloc_id)?; - let allocation_size = alloc.bytes.len() as u64; + /// in-bounds! This follows C's/LLVM's rules. `check` indicates whether we + /// additionally require the pointer to be pointing to a *live* (still allocated) + /// allocation. + /// If you want to check bounds before doing a memory access, better use `check_bounds`. + pub fn check_bounds_ptr( + &self, + ptr: Pointer, + check: InboundsCheck, + ) -> EvalResult<'tcx> { + let allocation_size = match check { + InboundsCheck::Live => { + let alloc = self.get(ptr.alloc_id)?; + alloc.bytes.len() as u64 + } + InboundsCheck::MaybeDead => { + self.get_size_and_align(ptr.alloc_id).0.bytes() + } + }; if ptr.offset.bytes() > allocation_size { return err!(PointerOutOfBounds { ptr: ptr.erase_tag(), - access, + check, allocation_size: Size::from_bytes(allocation_size), }); } @@ -317,10 +321,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &self, ptr: Pointer, size: Size, - access: bool + check: InboundsCheck, ) -> EvalResult<'tcx> { // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) - self.check_bounds_ptr(ptr.offset(size, &*self)?, access) + self.check_bounds_ptr(ptr.offset(size, &*self)?, check) } } @@ -626,7 +630,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { ) -> EvalResult<'tcx, &[u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; - self.check_bounds(ptr, size, true)?; + self.check_bounds(ptr, size, InboundsCheck::Live)?; if check_defined_and_ptr { self.check_defined(ptr, size)?; @@ -677,7 +681,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { ) -> EvalResult<'tcx, &mut [u8]> { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_align(ptr.into(), align)?; - self.check_bounds(ptr, size, true)?; + self.check_bounds(ptr, size, InboundsCheck::Live)?; self.mark_definedness(ptr, size, true)?; self.clear_relocations(ptr, size)?; 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; diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 578bcdc09295d..b7910ad3bce9e 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -19,7 +19,7 @@ use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerEx use rustc::mir::interpret::{ GlobalId, AllocId, ConstValue, Pointer, Scalar, - EvalResult, EvalErrorKind + EvalResult, EvalErrorKind, InboundsCheck, }; use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind}; pub use rustc::mir::interpret::ScalarMaybeUndef; @@ -601,7 +601,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // read raw discriminant value let discr_op = self.operand_field(rval, 0)?; let discr_val = self.read_immediate(discr_op)?; - let raw_discr = discr_val.to_scalar()?; + let raw_discr = discr_val.to_scalar_or_undef(); trace!("discr value: {:?}", raw_discr); // post-process Ok(match rval.layout.variants { @@ -647,28 +647,33 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let variants_start = niche_variants.start().as_u32() as u128; let variants_end = niche_variants.end().as_u32() as u128; match raw_discr { - Scalar::Ptr(_) => { - // The niche must be just 0 (which a pointer value never is) - assert!(niche_start == 0); - assert!(variants_start == variants_end); + ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => { + // The niche must be just 0 (which an inbounds pointer value never is) + let ptr_valid = niche_start == 0 && variants_start == variants_end && + self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok(); + if !ptr_valid { + return err!(InvalidDiscriminant(raw_discr.erase_tag())); + } (dataful_variant.as_u32() as u128, dataful_variant) }, - Scalar::Bits { bits: raw_discr, size } => { + ScalarMaybeUndef::Scalar(Scalar::Bits { bits: raw_discr, size }) => { assert_eq!(size as u64, discr_val.layout.size.bytes()); - let discr = raw_discr.wrapping_sub(niche_start) + let adjusted_discr = raw_discr.wrapping_sub(niche_start) .wrapping_add(variants_start); - if variants_start <= discr && discr <= variants_end { - let index = discr as usize; - assert_eq!(index as u128, discr); + if variants_start <= adjusted_discr && adjusted_discr <= variants_end { + let index = adjusted_discr as usize; + assert_eq!(index as u128, adjusted_discr); assert!(index < rval.layout.ty .ty_adt_def() .expect("tagged layout for non adt") .variants.len()); - (discr, VariantIdx::from_usize(index)) + (adjusted_discr, VariantIdx::from_usize(index)) } else { (dataful_variant.as_u32() as u128, dataful_variant) } }, + ScalarMaybeUndef::Undef => + return err!(InvalidDiscriminant(ScalarMaybeUndef::Undef)), } } }) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 988ff7e75163d..ad7ffd291bed1 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -17,11 +17,11 @@ use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ - Scalar, AllocType, EvalResult, EvalErrorKind, + Scalar, AllocType, EvalResult, EvalErrorKind, InboundsCheck, }; use super::{ - OpTy, MPlaceTy, ImmTy, Machine, EvalContext, ValueVisitor + OpTy, MPlaceTy, Machine, EvalContext, ValueVisitor }; macro_rules! validation_failure { @@ -274,15 +274,16 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ), EvalErrorKind::ReadPointerAsBytes => validation_failure!( - "a pointer", self.path, "plain bytes" + "a pointer", self.path, "plain (non-pointer) bytes" ), _ => Err(err), } } } - 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 { @@ -304,7 +305,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> if self.const_mode { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous try_validation!(value.to_bits(size), - value, self.path, "initialized plain bits"); + value, self.path, "initialized plain (non-pointer) bytes"); } else { // At run-time, for now, we accept *anything* for these types, including // undef. We should fix that, but let's start low. @@ -394,7 +395,8 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> } // Maintain the invariant that the place we are checking is // already verified to be in-bounds. - try_validation!(self.ecx.memory.check_bounds(ptr, size, false), + try_validation!( + self.ecx.memory.check_bounds(ptr, size, InboundsCheck::Live), "dangling (not entirely in bounds) reference", self.path); } // Check if we have encountered this pointer+layout combination 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. diff --git a/src/librustc_target/abi/call/powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs index 80a4d693dc36b..f7ef1390f14de 100644 --- a/src/librustc_target/abi/call/powerpc64.rs +++ b/src/librustc_target/abi/call/powerpc64.rs @@ -14,11 +14,12 @@ use abi::call::{FnType, ArgType, Reg, RegKind, Uniform}; use abi::{Align, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use spec::HasTargetSpec; #[derive(Debug, Clone, Copy, PartialEq)] enum ABI { ELFv1, // original ABI used for powerpc64 (big-endian) - ELFv2, // newer ABI used for powerpc64le + ELFv2, // newer ABI used for powerpc64le and musl (both endians) } use self::ABI::*; @@ -75,7 +76,9 @@ fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>, abi: ABI) let size = ret.layout.size; let bits = size.bits(); if bits <= 128 { - let unit = if bits <= 8 { + let unit = if cx.data_layout().endian == Endian::Big { + Reg { kind: RegKind::Integer, size } + } else if bits <= 8 { Reg::i8() } else if bits <= 16 { Reg::i16() @@ -110,22 +113,15 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI) } let size = arg.layout.size; - let (unit, total) = match abi { - ELFv1 => { - // In ELFv1, aggregates smaller than a doubleword should appear in - // the least-significant bits of the parameter doubleword. The rest - // should be padded at their tail to fill out multiple doublewords. - if size.bits() <= 64 { - (Reg { kind: RegKind::Integer, size }, size) - } else { - let align = Align::from_bits(64, 64).unwrap(); - (Reg::i64(), size.abi_align(align)) - } - }, - ELFv2 => { - // In ELFv2, we can just cast directly. - (Reg::i64(), size) - }, + let (unit, total) = if size.bits() <= 64 { + // Aggregates smaller than a doubleword should appear in + // the least-significant bits of the parameter doubleword. + (Reg { kind: RegKind::Integer, size }, size) + } else { + // Aggregates larger than a doubleword should be padded + // at the tail to fill out a whole number of doublewords. + let align = Align::from_bits(64, 64).unwrap(); + (Reg::i64(), size.abi_align(align)) }; arg.cast_to(Uniform { @@ -136,11 +132,15 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI) pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>) where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout + C: LayoutOf> + HasDataLayout + HasTargetSpec { - let abi = match cx.data_layout().endian { - Endian::Big => ELFv1, - Endian::Little => ELFv2, + let abi = if cx.target_spec().target_env == "musl" { + ELFv2 + } else { + match cx.data_layout().endian { + Endian::Big => ELFv1, + Endian::Little => ELFv2 + } }; if !fty.ret.is_ignore() { diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 88f22912fa6fc..22afb0da05bc1 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -229,7 +229,7 @@ impl HasDataLayout for TargetDataLayout { } /// Endianness of the target, which must match cfg(target-endian). -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq)] pub enum Endian { Little, Big diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 16dc2a91030f1..f67152ee90b7a 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -297,7 +297,9 @@ supported_targets! { ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu), ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu), ("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe), + ("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl), ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu), + ("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl), ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu), ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl), ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu), diff --git a/src/librustc_target/spec/powerpc64_unknown_linux_musl.rs b/src/librustc_target/spec/powerpc64_unknown_linux_musl.rs new file mode 100644 index 0000000000000..95e95510e1fea --- /dev/null +++ b/src/librustc_target/spec/powerpc64_unknown_linux_musl.rs @@ -0,0 +1,32 @@ +// 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. + +use spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_musl_base::opts(); + base.cpu = "ppc64".to_string(); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.max_atomic_width = Some(64); + + Ok(Target { + llvm_target: "powerpc64-unknown-linux-musl".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:e-i64:64-n32:64".to_string(), + arch: "powerpc64".to_string(), + target_os: "linux".to_string(), + target_env: "musl".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_target/spec/powerpc_unknown_linux_musl.rs b/src/librustc_target/spec/powerpc_unknown_linux_musl.rs new file mode 100644 index 0000000000000..1a4d0cb323f1f --- /dev/null +++ b/src/librustc_target/spec/powerpc_unknown_linux_musl.rs @@ -0,0 +1,31 @@ +// 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. + +use spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_musl_base::opts(); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.max_atomic_width = Some(32); + + Ok(Target { + llvm_target: "powerpc-unknown-linux-musl".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(), + arch: "powerpc".to_string(), + target_os: "linux".to_string(), + target_env: "musl".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 411583b36b9e3..7a71cf57a2f27 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -219,35 +219,62 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - let mut err = type_error_struct!( - self.tcx.sess, - call_expr.span, - callee_ty, - E0618, - "expected function, found {}", - match unit_variant { - Some(ref path) => format!("enum variant `{}`", path), - None => format!("`{}`", callee_ty), - }); - - err.span_label(call_expr.span, "not a function"); + if let hir::ExprKind::Call(ref callee, _) = call_expr.node { + let mut err = type_error_struct!( + self.tcx.sess, + callee.span, + callee_ty, + E0618, + "expected function, found {}", + match unit_variant { + Some(ref path) => format!("enum variant `{}`", path), + None => format!("`{}`", callee_ty), + }); - if let Some(ref path) = unit_variant { - err.span_suggestion_with_applicability( - call_expr.span, - &format!("`{}` is a unit variant, you need to write it \ - without the parenthesis", path), - path.to_string(), - Applicability::MachineApplicable - ); - } + if let Some(ref path) = unit_variant { + err.span_suggestion_with_applicability( + call_expr.span, + &format!("`{}` is a unit variant, you need to write it \ + without the parenthesis", path), + path.to_string(), + Applicability::MachineApplicable + ); + } - if let hir::ExprKind::Call(ref expr, _) = call_expr.node { - let def = if let hir::ExprKind::Path(ref qpath) = expr.node { - self.tables.borrow().qpath_def(qpath, expr.hir_id) - } else { - Def::Err + let mut inner_callee_path = None; + let def = match callee.node { + hir::ExprKind::Path(ref qpath) => { + self.tables.borrow().qpath_def(qpath, callee.hir_id) + }, + hir::ExprKind::Call(ref inner_callee, _) => { + // If the call spans more than one line and the callee kind is + // itself another `ExprCall`, that's a clue that we might just be + // missing a semicolon (Issue #51055) + let call_is_multiline = self.tcx.sess.source_map() + .is_multiline(call_expr.span); + if call_is_multiline { + let span = self.tcx.sess.source_map().next_point(callee.span); + err.span_suggestion_with_applicability( + span, + "try adding a semicolon", + ";".to_owned(), + Applicability::MaybeIncorrect + ); + } + if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.node { + inner_callee_path = Some(inner_qpath); + self.tables.borrow().qpath_def(inner_qpath, inner_callee.hir_id) + } else { + Def::Err + } + }, + _ => { + Def::Err + } }; + + err.span_label(call_expr.span, "call expression requires function"); + let def_span = match def { Def::Err => None, Def::Local(id) | Def::Upvar(id, ..) => { @@ -256,16 +283,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => self.tcx.hir.span_if_local(def.def_id()) }; if let Some(span) = def_span { - let name = match unit_variant { - Some(path) => path, - None => callee_ty.to_string(), + let label = match (unit_variant, inner_callee_path) { + (Some(path), _) => format!("`{}` defined here", path), + (_, Some(hir::QPath::Resolved(_, path))) => format!( + "`{}` defined here returns `{}`", path, callee_ty.to_string() + ), + _ => format!("`{}` defined here", callee_ty.to_string()), }; - err.span_label(span, format!("`{}` defined here", name)); + err.span_label(span, label); } + err.emit(); + } else { + bug!("call_expr.node should be an ExprKind::Call, got {:?}", call_expr.node); } - err.emit(); - // This is the "default" function signature, used in case of error. // In that case, we check each argument against "error" in order to // set up all the node type bindings. diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index df994ad9e55c4..312ce402775d2 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 { @@ -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); @@ -213,12 +215,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); } @@ -249,16 +250,16 @@ 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); debug!( "var_id={:?} freevar_ty={:?} capture={:?}", - var_node_id, - freevar_ty, - capture + var_node_id, freevar_ty, capture ); match capture { @@ -271,8 +272,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }, ), } - }) - .collect() + }).collect() }) } } @@ -301,12 +301,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 @@ -349,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 @@ -366,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 => {} @@ -381,9 +383,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 +401,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 +416,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 +432,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, @@ -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 @@ -493,15 +497,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 +514,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 +540,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 +554,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 +588,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 +617,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 { 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, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 85c9b6ee7285e..f5056cead567e 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/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/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 diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 590506566dd5f..0584cd5a3df47 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1890,7 +1890,6 @@ mod tests { missing_fragment_specifiers: Lock::new(FxHashSet::default()), raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), - non_modrs_mods: Lock::new(vec![]), buffered_lints: Lock::new(vec![]), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index fd66bf55a74be..ac972f20f9432 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -52,9 +52,6 @@ pub struct ParseSess { pub raw_identifier_spans: Lock>, /// The registered diagnostics codes crate registered_diagnostics: Lock, - // Spans where a `mod foo;` statement was included in a non-mod.rs file. - // These are used to issue errors if the non_modrs_mods feature is not enabled. - pub non_modrs_mods: Lock>, /// Used to determine and report recursive mod inclusions included_mod_stack: Lock>, source_map: Lrc, @@ -81,7 +78,6 @@ impl ParseSess { registered_diagnostics: Lock::new(ErrorMap::new()), included_mod_stack: Lock::new(vec![]), source_map, - non_modrs_mods: Lock::new(vec![]), buffered_lints: Lock::new(vec![]), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d90ec4ea081b2..b4fc9c2c6fc7c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6591,16 +6591,7 @@ impl<'a> Parser<'a> { } let relative = match self.directory.ownership { - DirectoryOwnership::Owned { relative } => { - // Push the usage onto the list of non-mod.rs mod uses. - // This is used later for feature-gate error reporting. - if let Some(cur_file_ident) = relative { - self.sess - .non_modrs_mods.borrow_mut() - .push((cur_file_ident, id_sp)); - } - relative - }, + DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod(_) => None, }; diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 2f6b306e8f8ba..a5b12ce4c4d83 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() diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index be3485cfa7cc2..b8a171b52adf2 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -53,7 +53,7 @@ pub fn expand_test_or_bench( if let Annotatable::Item(i) = item { i } else { cx.parse_sess.span_diagnostic.span_fatal(item.span(), - "#[test] attribute is only allowed on fn items").raise(); + "#[test] attribute is only allowed on non associated functions").raise(); }; if let ast::ItemKind::Mac(_) = item.node { diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs new file mode 100644 index 0000000000000..786968128ec1b --- /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 void @test_UnionI64x4(<4 x i64>* {{.*}} %arg0) +#[no_mangle] +pub fn test_UnionI64x4(_: UnionI64x4) { loop {} } + +pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 } + +// CHECK: define void @test_UnionI64x4_(<4 x i64>* {{.*}} %arg0) +#[no_mangle] +pub fn test_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 fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } + +pub union UnionF32F32{a:f32, b:f32} + +// CHECK: define float @test_UnionF32F32(float %arg0) +#[no_mangle] +pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} } + +pub union UnionF32U32{a:f32, b:u32} + +// CHECK: define i32 @test_UnionF32U32(i32) +#[no_mangle] +pub 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 {} } + diff --git a/src/test/compile-fail/const-fn-error.rs b/src/test/compile-fail/const-fn-error.rs index 83f2735aa9d8e..17dc9f94fe19c 100644 --- a/src/test/compile-fail/const-fn-error.rs +++ b/src/test/compile-fail/const-fn-error.rs @@ -19,6 +19,7 @@ const fn f(x: usize) -> usize { for i in 0..x { //~^ ERROR E0015 //~| ERROR E0019 + //~| ERROR E0080 sum += i; } sum diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs index fc42f87ccbfda..1ed513033fd5d 100644 --- a/src/test/compile-fail/issue-52443.rs +++ b/src/test/compile-fail/issue-52443.rs @@ -14,4 +14,5 @@ fn main() { [(); {while true {break}; 0}]; //~ ERROR constant contains unimplemented expression type [(); { for _ in 0usize.. {}; 0}]; //~ ERROR calls in constants are limited to constant functions //~^ ERROR constant contains unimplemented expression type + //~| ERROR evaluation of constant value failed } 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 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(); + } +} diff --git a/src/test/run-pass/non_modrs_mods/foors_mod.rs b/src/test/run-pass/non_modrs_mods/foors_mod.rs index 7d37c6d939954..b2fea9b5e53f8 100644 --- a/src/test/run-pass/non_modrs_mods/foors_mod.rs +++ b/src/test/run-pass/non_modrs_mods/foors_mod.rs @@ -12,3 +12,7 @@ pub mod inner_modrs_mod; pub mod inner_foors_mod; +pub mod inline { + #[path="somename.rs"] + pub mod innie; +} diff --git a/src/test/run-pass/non_modrs_mods/foors_mod/inline/somename.rs b/src/test/run-pass/non_modrs_mods/foors_mod/inline/somename.rs new file mode 100644 index 0000000000000..b76b4321d62aa --- /dev/null +++ b/src/test/run-pass/non_modrs_mods/foors_mod/inline/somename.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-pass/non_modrs_mods/modrs_mod/inline/somename.rs b/src/test/run-pass/non_modrs_mods/modrs_mod/inline/somename.rs new file mode 100644 index 0000000000000..b76b4321d62aa --- /dev/null +++ b/src/test/run-pass/non_modrs_mods/modrs_mod/inline/somename.rs @@ -0,0 +1 @@ +pub fn foo() {} diff --git a/src/test/run-pass/non_modrs_mods/modrs_mod/mod.rs b/src/test/run-pass/non_modrs_mods/modrs_mod/mod.rs index 9e3f10f12ed63..99684c86d2eaf 100644 --- a/src/test/run-pass/non_modrs_mods/modrs_mod/mod.rs +++ b/src/test/run-pass/non_modrs_mods/modrs_mod/mod.rs @@ -10,3 +10,7 @@ pub mod inner_modrs_mod; pub mod inner_foors_mod; +pub mod inline { + #[path="somename.rs"] + pub mod innie; +} diff --git a/src/test/run-pass/non_modrs_mods/non_modrs_mods.rs b/src/test/run-pass/non_modrs_mods/non_modrs_mods.rs new file mode 100644 index 0000000000000..f664b0166d80d --- /dev/null +++ b/src/test/run-pass/non_modrs_mods/non_modrs_mods.rs @@ -0,0 +1,16 @@ +// run-pass +// +// ignore-pretty issue #37195 +pub mod modrs_mod; +pub mod foors_mod; +#[path = "some_crazy_attr_mod_dir/arbitrary_name.rs"] +pub mod attr_mod; +pub fn main() { + modrs_mod::inner_modrs_mod::innest::foo(); + modrs_mod::inner_foors_mod::innest::foo(); + modrs_mod::inline::innie::foo(); + foors_mod::inner_modrs_mod::innest::foo(); + foors_mod::inner_foors_mod::innest::foo(); + foors_mod::inline::innie::foo(); + attr_mod::inner_modrs_mod::innest::foo(); +} 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 `/]` + diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 990fb404c9466..194cfab8527c0 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -12,8 +12,16 @@ LL | |y| x + y error[E0618]: expected function, found `()` --> $DIR/issue-20862.rs:17:13 | -LL | let x = foo(5)(2); - | ^^^^^^^^^ not a function +LL | / fn foo(x: i32) { +LL | | |y| x + y +LL | | //~^ ERROR: mismatched types +LL | | } + | |_- `foo` defined here returns `()` +... +LL | let x = foo(5)(2); + | ^^^^^^--- + | | + | call expression requires function error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-call.rs b/src/test/ui/consts/const-call.rs index 18476494300b2..bd407192cd7a1 100644 --- a/src/test/ui/consts/const-call.rs +++ b/src/test/ui/consts/const-call.rs @@ -15,4 +15,5 @@ fn f(x: usize) -> usize { fn main() { let _ = [0; f(2)]; //~^ ERROR calls in constants are limited to constant functions + //~| ERROR evaluation of constant value failed } diff --git a/src/test/ui/consts/const-call.stderr b/src/test/ui/consts/const-call.stderr index 81be93e916e8b..219fcec51b386 100644 --- a/src/test/ui/consts/const-call.stderr +++ b/src/test/ui/consts/const-call.stderr @@ -4,6 +4,13 @@ error[E0015]: calls in constants are limited to constant functions, tuple struct LL | let _ = [0; f(2)]; | ^^^^ -error: aborting due to previous error +error[E0080]: evaluation of constant value failed + --> $DIR/const-call.rs:16:17 + | +LL | let _ = [0; f(2)]; + | ^^^^ calling non-const function `f` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors occurred: E0015, E0080. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr index cc1db5db6915c..0126743eedecb 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:24:5 | LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:36:5 | LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -74,7 +74,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:51:5 | LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -96,7 +96,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:60:5 | LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -144,7 +144,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:78:5 | LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -184,7 +184,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:93:5 | LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -208,7 +208,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:102:5 | LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr index 3075be9e28b35..608094b179dd6 100644 --- a/src/test/ui/consts/const-eval/issue-52442.stderr +++ b/src/test/ui/consts/const-eval/issue-52442.stderr @@ -8,7 +8,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-52442.rs:12:11 | LL | [(); { &loop { break } as *const _ as usize } ]; //~ ERROR unimplemented expression type - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr index d55c1c2c70ba1..c4bad73eb0276 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ref_to_int_match.rs:33:1 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; //~ ERROR it is undefined behavior to use this value - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 0aa15c8393879..89b449464419e 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -39,6 +39,7 @@ union TransmuteEnum2 { in3: (), out1: Enum2, out2: Wrap, // something wrapping the enum so that we test layout first, not enum + out3: Option, } const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; //~^ ERROR is undefined behavior @@ -51,6 +52,10 @@ const BAD_ENUM4: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; const BAD_ENUM_UNDEF: [Enum2; 2] = [unsafe { TransmuteEnum2 { in3: () }.out1 }; 2]; //~^ ERROR is undefined behavior +// Pointer value in an enum with a niche that is not just 0. +const BAD_ENUM_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; +//~^ ERROR is undefined behavior + // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). union TransmuteChar { diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index d36e96b08174a..5aae3a2f35110 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { a: &1 }.out }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:43:1 + --> $DIR/ub-enum.rs:44:1 | LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -15,7 +15,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:45:1 + --> $DIR/ub-enum.rs:46:1 | LL | const BAD_ENUM3: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant @@ -23,7 +23,7 @@ LL | const BAD_ENUM3: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:47:1 + --> $DIR/ub-enum.rs:48:1 | LL | const BAD_ENUM4: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be in the range 2..=2 @@ -31,21 +31,29 @@ LL | const BAD_ENUM4: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:51:1 + --> $DIR/ub-enum.rs:52:1 | LL | const BAD_ENUM_UNDEF: [Enum2; 2] = [unsafe { TransmuteEnum2 { in3: () }.out1 }; 2]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at [0], but expected a valid enum discriminant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:61:1 + --> $DIR/ub-enum.rs:56:1 + | +LL | const BAD_ENUM_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:66:1 | LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected something less or equal to 1114111 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index c3f5f4a26f555..fe969d40a2ea6 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:22:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior @@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:25:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/consts/const-eval/union-ice.stderr b/src/test/ui/consts/const-eval/union-ice.stderr index d5a20640771df..98c2c1472aae0 100644 --- a/src/test/ui/consts/const-eval/union-ice.stderr +++ b/src/test/ui/consts/const-eval/union-ice.stderr @@ -13,7 +13,7 @@ LL | / const FIELD_PATH: Struct = Struct { //~ ERROR it is undefined behavior to LL | | a: 42, LL | | b: unsafe { UNION.field3 }, LL | | }; - | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain bits + | |__^ type validation failed: encountered uninitialized bytes at .b, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/empty/empty-struct-unit-expr.stderr b/src/test/ui/empty/empty-struct-unit-expr.stderr index fff696fc80f05..360e0c6f107b2 100644 --- a/src/test/ui/empty/empty-struct-unit-expr.stderr +++ b/src/test/ui/empty/empty-struct-unit-expr.stderr @@ -5,7 +5,9 @@ LL | struct Empty2; | -------------- `Empty2` defined here ... LL | let e2 = Empty2(); //~ ERROR expected function, found `Empty2` - | ^^^^^^^^ not a function + | ^^^^^^-- + | | + | call expression requires function error[E0618]: expected function, found enum variant `E::Empty4` --> $DIR/empty-struct-unit-expr.rs:26:14 @@ -14,7 +16,9 @@ LL | Empty4 | ------ `E::Empty4` defined here ... LL | let e4 = E::Empty4(); - | ^^^^^^^^^^^ not a function + | ^^^^^^^^^-- + | | + | call expression requires function help: `E::Empty4` is a unit variant, you need to write it without the parenthesis | LL | let e4 = E::Empty4; @@ -24,13 +28,17 @@ error[E0618]: expected function, found `empty_struct::XEmpty2` --> $DIR/empty-struct-unit-expr.rs:28:15 | LL | let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2` - | ^^^^^^^^^ not a function + | ^^^^^^^-- + | | + | call expression requires function error[E0618]: expected function, found enum variant `XE::XEmpty4` --> $DIR/empty-struct-unit-expr.rs:29:15 | LL | let xe4 = XE::XEmpty4(); - | ^^^^^^^^^^^^^ not a function + | ^^^^^^^^^^^-- + | | + | call expression requires function help: `XE::XEmpty4` is a unit variant, you need to write it without the parenthesis | LL | let xe4 = XE::XEmpty4; diff --git a/src/test/ui/error-codes/E0618.stderr b/src/test/ui/error-codes/E0618.stderr index ef7ace44d59a6..3bcc83e01c1f0 100644 --- a/src/test/ui/error-codes/E0618.stderr +++ b/src/test/ui/error-codes/E0618.stderr @@ -5,7 +5,9 @@ LL | Entry, | ----- `X::Entry` defined here ... LL | X::Entry(); - | ^^^^^^^^^^ not a function + | ^^^^^^^^-- + | | + | call expression requires function help: `X::Entry` is a unit variant, you need to write it without the parenthesis | LL | X::Entry; @@ -17,7 +19,9 @@ error[E0618]: expected function, found `i32` LL | let x = 0i32; | - `i32` defined here LL | x(); - | ^^^ not a function + | ^-- + | | + | call expression requires function error: aborting due to 2 previous errors diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.stderr b/src/test/ui/infinite/infinite-recursion-const-fn.stderr index ef35bb6d98dae..4246ec2dad332 100644 --- a/src/test/ui/infinite/infinite-recursion-const-fn.stderr +++ b/src/test/ui/infinite/infinite-recursion-const-fn.stderr @@ -5,61 +5,61 @@ LL | const fn a() -> usize { b() } //~ ERROR evaluation of constant value failed | ^^^ | | | reached the configured maximum number of stack frames - | inside call to `b` + | inside call to `b` at $DIR/infinite-recursion-const-fn.rs:13:25 LL | const fn b() -> usize { a() } | --- | | - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` - | inside call to `a` + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 + | inside call to `a` at $DIR/infinite-recursion-const-fn.rs:14:25 LL | const ARR: [i32; a()] = [5; 6]; - | --- inside call to `a` + | --- inside call to `a` at $DIR/infinite-recursion-const-fn.rs:15:18 error: aborting due to previous error diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs b/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs index c0a10fe3e60fe..229b005ec7d56 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.rs @@ -9,7 +9,6 @@ // except according to those terms. // ignore-tidy-linelength -// ignore-windows mod auxiliary { mod foo; diff --git a/src/test/ui/issues/issue-10969.stderr b/src/test/ui/issues/issue-10969.stderr index edc4ecbab525a..d04108ca39e24 100644 --- a/src/test/ui/issues/issue-10969.stderr +++ b/src/test/ui/issues/issue-10969.stderr @@ -4,7 +4,9 @@ error[E0618]: expected function, found `i32` LL | fn func(i: i32) { | - `i32` defined here LL | i(); //~ERROR expected function, found `i32` - | ^^^ not a function + | ^-- + | | + | call expression requires function error[E0618]: expected function, found `i32` --> $DIR/issue-10969.rs:16:5 @@ -12,7 +14,9 @@ error[E0618]: expected function, found `i32` LL | let i = 0i32; | - `i32` defined here LL | i(); //~ERROR expected function, found `i32` - | ^^^ not a function + | ^-- + | | + | call expression requires function error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-18532.stderr b/src/test/ui/issues/issue-18532.stderr index 8f10cb0f7b03d..c297c20069ec2 100644 --- a/src/test/ui/issues/issue-18532.stderr +++ b/src/test/ui/issues/issue-18532.stderr @@ -2,7 +2,9 @@ error[E0618]: expected function, found `!` --> $DIR/issue-18532.rs:16:5 | LL | (return)((),()); //~ ERROR expected function, found `!` - | ^^^^^^^^^^^^^^^ not a function + | ^^^^^^^^------- + | | + | call expression requires function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20714.stderr b/src/test/ui/issues/issue-20714.stderr index 1ea85ee440e21..70a9736d2a243 100644 --- a/src/test/ui/issues/issue-20714.stderr +++ b/src/test/ui/issues/issue-20714.stderr @@ -5,7 +5,9 @@ LL | struct G; | --------- `G` defined here ... LL | let g = G(); //~ ERROR: expected function, found `G` - | ^^^ not a function + | ^-- + | | + | call expression requires function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21701.stderr b/src/test/ui/issues/issue-21701.stderr index 9fb9a7b51f280..b94e0833a5810 100644 --- a/src/test/ui/issues/issue-21701.stderr +++ b/src/test/ui/issues/issue-21701.stderr @@ -4,7 +4,9 @@ error[E0618]: expected function, found `U` LL | fn foo(t: U) { | - `U` defined here LL | let y = t(); - | ^^^ not a function + | ^-- + | | + | call expression requires function error[E0618]: expected function, found `Bar` --> $DIR/issue-21701.rs:19:13 @@ -13,7 +15,9 @@ LL | struct Bar; | ----------- `Bar` defined here ... LL | let f = Bar(); - | ^^^^^ not a function + | ^^^-- + | | + | call expression requires function error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-22468.stderr b/src/test/ui/issues/issue-22468.stderr index 034a076fbfe83..af32c0e20ce9d 100644 --- a/src/test/ui/issues/issue-22468.stderr +++ b/src/test/ui/issues/issue-22468.stderr @@ -4,7 +4,9 @@ error[E0618]: expected function, found `&str` LL | let foo = "bar"; | --- `&str` defined here LL | let x = foo("baz"); - | ^^^^^^^^^^ not a function + | ^^^------- + | | + | call expression requires function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26237.rs b/src/test/ui/issues/issue-26237.rs index 22772e596b19e..ffffe6d3ab5db 100644 --- a/src/test/ui/issues/issue-26237.rs +++ b/src/test/ui/issues/issue-26237.rs @@ -11,7 +11,6 @@ macro_rules! macro_panic { ($not_a_function:expr, $some_argument:ident) => { $not_a_function($some_argument) - //~^ ERROR expected function, found `{integer}` } } @@ -19,5 +18,5 @@ fn main() { let mut value_a = 0; let mut value_b = 0; macro_panic!(value_a, value_b); - //~^ in this expansion of macro_panic! + //~^ ERROR expected function, found `{integer}` } diff --git a/src/test/ui/issues/issue-26237.stderr b/src/test/ui/issues/issue-26237.stderr index ae6fda8b93248..7f481c230ba65 100644 --- a/src/test/ui/issues/issue-26237.stderr +++ b/src/test/ui/issues/issue-26237.stderr @@ -1,14 +1,14 @@ error[E0618]: expected function, found `{integer}` - --> $DIR/issue-26237.rs:13:9 + --> $DIR/issue-26237.rs:20:18 | LL | $not_a_function($some_argument) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a function + | ------------------------------- call expression requires function ... LL | let mut value_a = 0; | ----------- `{integer}` defined here LL | let mut value_b = 0; LL | macro_panic!(value_a, value_b); - | ------------------------------- in this macro invocation + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39559-2.rs b/src/test/ui/issues/issue-39559-2.rs index 2e480a29774ce..f01fd1fd8f144 100644 --- a/src/test/ui/issues/issue-39559-2.rs +++ b/src/test/ui/issues/issue-39559-2.rs @@ -23,6 +23,8 @@ impl Dim for Dim3 { fn main() { let array: [usize; Dim3::dim()] //~^ ERROR E0015 + //~| ERROR E0080 = [0; Dim3::dim()]; //~^ ERROR E0015 + //~| ERROR E0080 } diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/issues/issue-39559-2.stderr index ca9da096b6c16..57e9f23e0b33c 100644 --- a/src/test/ui/issues/issue-39559-2.stderr +++ b/src/test/ui/issues/issue-39559-2.stderr @@ -4,12 +4,25 @@ error[E0015]: calls in constants are limited to constant functions, tuple struct LL | let array: [usize; Dim3::dim()] | ^^^^^^^^^^^ +error[E0080]: evaluation of constant value failed + --> $DIR/issue-39559-2.rs:24:24 + | +LL | let array: [usize; Dim3::dim()] + | ^^^^^^^^^^^ calling non-const function `::dim` + error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants - --> $DIR/issue-39559-2.rs:26:15 + --> $DIR/issue-39559-2.rs:27:15 | LL | = [0; Dim3::dim()]; | ^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/issue-39559-2.rs:27:15 + | +LL | = [0; Dim3::dim()]; + | ^^^^^^^^^^^ calling non-const function `::dim` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0015`. +Some errors occurred: E0015, E0080. +For more information about an error, try `rustc --explain E0015`. diff --git a/src/test/ui/issues/issue-43105.rs b/src/test/ui/issues/issue-43105.rs index 2bddc443d5baf..60b18a66f1a38 100644 --- a/src/test/ui/issues/issue-43105.rs +++ b/src/test/ui/issues/issue-43105.rs @@ -12,10 +12,12 @@ fn xyz() -> u8 { 42 } const NUM: u8 = xyz(); //~^ ERROR calls in constants are limited to constant functions, tuple structs and tuple variants +//~| ERROR any use of this value will cause an error [const_err] fn main() { match 1 { NUM => unimplemented!(), + //~^ ERROR could not evaluate constant pattern _ => unimplemented!(), } } diff --git a/src/test/ui/issues/issue-43105.stderr b/src/test/ui/issues/issue-43105.stderr index 67a6008cd8ebc..f26447ed2b9f0 100644 --- a/src/test/ui/issues/issue-43105.stderr +++ b/src/test/ui/issues/issue-43105.stderr @@ -4,6 +4,22 @@ error[E0015]: calls in constants are limited to constant functions, tuple struct LL | const NUM: u8 = xyz(); | ^^^^^ -error: aborting due to previous error +error: any use of this value will cause an error + --> $DIR/issue-43105.rs:13:1 + | +LL | const NUM: u8 = xyz(); + | ^^^^^^^^^^^^^^^^-----^ + | | + | calling non-const function `xyz` + | + = note: #[deny(const_err)] on by default + +error: could not evaluate constant pattern + --> $DIR/issue-43105.rs:19:9 + | +LL | NUM => unimplemented!(), + | ^^^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/issues/issue-45965.stderr b/src/test/ui/issues/issue-45965.stderr index 2b3870feef37c..b7b5f76395a9d 100644 --- a/src/test/ui/issues/issue-45965.stderr +++ b/src/test/ui/issues/issue-45965.stderr @@ -2,7 +2,9 @@ error[E0618]: expected function, found `{float}` --> $DIR/issue-45965.rs:12:30 | LL | let a = |r: f64| if r != 0.0(r != 0.0) { 1.0 } else { 0.0 }; - | ^^^^^^^^^^^^^ not a function + | ^^^---------- + | | + | call expression requires function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-46771.stderr b/src/test/ui/issues/issue-46771.stderr index 0d57d61e9ffe6..90adb3ed73f56 100644 --- a/src/test/ui/issues/issue-46771.stderr +++ b/src/test/ui/issues/issue-46771.stderr @@ -4,7 +4,9 @@ error[E0618]: expected function, found `main::Foo` LL | struct Foo; | ----------- `main::Foo` defined here LL | (1 .. 2).find(|_| Foo(0) == 0); //~ ERROR expected function, found `main::Foo` - | ^^^^^^ not a function + | ^^^--- + | | + | call expression requires function error: aborting due to previous error diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr index 6f5a84966bf35..305ee2f547145 100644 --- a/src/test/ui/issues/issue-5100.stderr +++ b/src/test/ui/issues/issue-5100.stderr @@ -47,9 +47,9 @@ error[E0618]: expected function, found `(char, char)` --> $DIR/issue-5100.rs:58:14 | LL | let v = [('a', 'b') //~ ERROR expected function, found `(char, char)` - | ______________^ + | ______________-^^^^^^^^^ LL | | ('c', 'd'), - | |_______________________^ not a function + | |_______________________- call expression requires function error[E0308]: mismatched types --> $DIR/issue-5100.rs:65:19 diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr index 03de0efd07362..a4c228416147e 100644 --- a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr +++ b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/issue-52023-array-size-pointer-cast.rs:12:17 | LL | let _ = [0; (&0 as *const i32) as usize]; //~ ERROR casting pointers to integers in constants - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain bits + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior diff --git a/src/test/ui/missing_non_modrs_mod/foo_inline.rs b/src/test/ui/missing_non_modrs_mod/foo_inline.rs new file mode 100644 index 0000000000000..df60629eca161 --- /dev/null +++ b/src/test/ui/missing_non_modrs_mod/foo_inline.rs @@ -0,0 +1,5 @@ +// ignore-test this is just a helper for the real test in this dir + +mod inline { + mod missing; +} diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs index 9c95f45939367..84fa1f032d78e 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.rs @@ -8,7 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-windows - mod foo; fn main() {} diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs new file mode 100644 index 0000000000000..9ebb4f1bdbdb3 --- /dev/null +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.rs @@ -0,0 +1,2 @@ +mod foo_inline; +fn main() {} diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr new file mode 100644 index 0000000000000..457e8fcccbfb3 --- /dev/null +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr @@ -0,0 +1,11 @@ +error[E0583]: file not found for module `missing` + --> $DIR/foo_inline.rs:4:9 + | +LL | mod missing; + | ^^^^^^^ + | + = help: name the file either missing.rs or missing/mod.rs inside the directory "$DIR/foo_inline/inline" + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0583`. diff --git a/src/test/ui/nll/ty-outlives/issue-55756.rs b/src/test/ui/nll/ty-outlives/issue-55756.rs new file mode 100644 index 0000000000000..cda3915849e2d --- /dev/null +++ b/src/test/ui/nll/ty-outlives/issue-55756.rs @@ -0,0 +1,37 @@ +// Regression test for #55756. +// +// In this test, the result of `self.callee` is a projection `>::Guard`. As it may contain a destructor, the dropck +// rules require that this type outlivess the scope of `state`. Unfortunately, +// our region inference is not smart enough to figure out how to +// translate a requirement like +// +// >::guard: 'r +// +// into a requirement that `'0: 'r` -- in particular, it fails to do +// so because it *also* knows that `>::Guard: 'a` +// from the trait definition. Faced with so many choices, the current +// solver opts to do nothing. +// +// Fixed by tweaking the solver to recognize that the constraint from +// the environment duplicates one from the trait. +// +// compile-pass + +#![crate_type="lib"] + +pub trait Database<'a> { + type Guard: 'a; +} + +pub struct Stateful<'a, D: 'a>(&'a D); + +impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> { + pub fn callee<'a>(&'a self) -> >::Guard { + unimplemented!() + } + pub fn caller<'a>(&'a self) -> >::Guard { + let state = self.callee(); + unimplemented!() + } +} diff --git a/src/test/ui/non_modrs_mods/foors_mod/compiletest-ignore-dir b/src/test/ui/non_modrs_mods/foors_mod/compiletest-ignore-dir deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/test/ui/non_modrs_mods/foors_mod/inner_foors_mod.rs b/src/test/ui/non_modrs_mods/foors_mod/inner_foors_mod.rs deleted file mode 100644 index 77cab972352bd..0000000000000 --- a/src/test/ui/non_modrs_mods/foors_mod/inner_foors_mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub mod innest; diff --git a/src/test/ui/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs b/src/test/ui/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs deleted file mode 100644 index b61667cfd882c..0000000000000 --- a/src/test/ui/non_modrs_mods/foors_mod/inner_foors_mod/innest.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub fn foo() {} diff --git a/src/test/ui/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs b/src/test/ui/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs deleted file mode 100644 index b61667cfd882c..0000000000000 --- a/src/test/ui/non_modrs_mods/foors_mod/inner_modrs_mod/innest.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub fn foo() {} diff --git a/src/test/ui/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs b/src/test/ui/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs deleted file mode 100644 index 77cab972352bd..0000000000000 --- a/src/test/ui/non_modrs_mods/foors_mod/inner_modrs_mod/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub mod innest; diff --git a/src/test/ui/non_modrs_mods/modrs_mod/compiletest-ignore-dir b/src/test/ui/non_modrs_mods/modrs_mod/compiletest-ignore-dir deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/test/ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs b/src/test/ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs deleted file mode 100644 index 77cab972352bd..0000000000000 --- a/src/test/ui/non_modrs_mods/modrs_mod/inner_foors_mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub mod innest; diff --git a/src/test/ui/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs b/src/test/ui/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs deleted file mode 100644 index b61667cfd882c..0000000000000 --- a/src/test/ui/non_modrs_mods/modrs_mod/inner_foors_mod/innest.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub fn foo() {} diff --git a/src/test/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs b/src/test/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs deleted file mode 100644 index b61667cfd882c..0000000000000 --- a/src/test/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/innest.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub fn foo() {} diff --git a/src/test/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs b/src/test/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs deleted file mode 100644 index 77cab972352bd..0000000000000 --- a/src/test/ui/non_modrs_mods/modrs_mod/inner_modrs_mod/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub mod innest; diff --git a/src/test/ui/non_modrs_mods/modrs_mod/mod.rs b/src/test/ui/non_modrs_mods/modrs_mod/mod.rs deleted file mode 100644 index 9e3f10f12ed63..0000000000000 --- a/src/test/ui/non_modrs_mods/modrs_mod/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -pub mod inner_modrs_mod; -pub mod inner_foors_mod; diff --git a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs b/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs deleted file mode 100644 index 226e6fda0a41f..0000000000000 --- a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/arbitrary_name.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub mod inner_modrs_mod; diff --git a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/compiletest-ignore-dir b/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/compiletest-ignore-dir deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs b/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs deleted file mode 100644 index b61667cfd882c..0000000000000 --- a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/innest.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub fn foo() {} diff --git a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs b/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs deleted file mode 100644 index 77cab972352bd..0000000000000 --- a/src/test/ui/non_modrs_mods/some_crazy_attr_mod_dir/inner_modrs_mod/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -pub mod innest; diff --git a/src/test/ui/parse-error-correct.stderr b/src/test/ui/parse-error-correct.stderr index 3eb0b19a6aaea..9c87806da9e5d 100644 --- a/src/test/ui/parse-error-correct.stderr +++ b/src/test/ui/parse-error-correct.stderr @@ -17,7 +17,9 @@ LL | let y = 42; | - `{integer}` defined here LL | let x = y.; //~ ERROR unexpected token LL | let x = y.(); //~ ERROR unexpected token - | ^^^^ not a function + | ^--- + | | + | call expression requires function error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/parse-error-correct.rs:21:15 diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 8e08f124d6807..01e6488de5303 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -171,7 +171,9 @@ LL | Unit, | ---- `Z::Unit` defined here ... LL | let _ = Z::Unit(); - | ^^^^^^^^^ not a function + | ^^^^^^^-- + | | + | call expression requires function help: `Z::Unit` is a unit variant, you need to write it without the parenthesis | LL | let _ = Z::Unit; @@ -193,7 +195,9 @@ LL | Unit, | ---- `m::E::Unit` defined here ... LL | let _: E = m::E::Unit(); - | ^^^^^^^^^^^^ not a function + | ^^^^^^^^^^-- + | | + | call expression requires function help: `m::E::Unit` is a unit variant, you need to write it without the parenthesis | LL | let _: E = m::E::Unit; @@ -215,7 +219,9 @@ LL | Unit, | ---- `E::Unit` defined here ... LL | let _: E = E::Unit(); - | ^^^^^^^^^ not a function + | ^^^^^^^-- + | | + | call expression requires function help: `E::Unit` is a unit variant, you need to write it without the parenthesis | LL | let _: E = E::Unit; diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs new file mode 100644 index 0000000000000..37f078285d695 --- /dev/null +++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs @@ -0,0 +1,8 @@ +fn vindictive() -> bool { true } + +fn perfidy() -> (i32, i32) { + vindictive() //~ ERROR expected function, found `bool` + (1, 2) +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr new file mode 100644 index 0000000000000..40ddb5ec53c29 --- /dev/null +++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr @@ -0,0 +1,16 @@ +error[E0618]: expected function, found `bool` + --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:4:5 + | +LL | fn vindictive() -> bool { true } + | -------------------------------- `vindictive` defined here returns `bool` +... +LL | vindictive() //~ ERROR expected function, found `bool` + | -^^^^^^^^^^^- help: try adding a semicolon: `;` + | _____| + | | +LL | | (1, 2) + | |__________- call expression requires function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`. diff --git a/src/test/ui/non_modrs_mods/foors_mod.rs b/src/test/ui/test-attr-non-associated-functions.rs similarity index 50% rename from src/test/ui/non_modrs_mods/foors_mod.rs rename to src/test/ui/test-attr-non-associated-functions.rs index 7d37c6d939954..348bc6b4e982d 100644 --- a/src/test/ui/non_modrs_mods/foors_mod.rs +++ b/src/test/ui/test-attr-non-associated-functions.rs @@ -1,4 +1,4 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -7,8 +7,23 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -// -// ignore-test: not a test, used by non_modrs_mods.rs -pub mod inner_modrs_mod; -pub mod inner_foors_mod; +// #[test] attribute is not allowed on associated functions or methods +// reworded error message +// compile-flags:--test + +struct A {} + +impl A { + #[test] + fn new() -> A { //~ ERROR #[test] attribute is only allowed on non associated functions + A {} + } +} + +#[test] +fn test() { + let _ = A::new(); +} + +fn main() {} diff --git a/src/test/ui/test-attr-non-associated-functions.stderr b/src/test/ui/test-attr-non-associated-functions.stderr new file mode 100644 index 0000000000000..491fcc0143119 --- /dev/null +++ b/src/test/ui/test-attr-non-associated-functions.stderr @@ -0,0 +1,10 @@ +error: #[test] attribute is only allowed on non associated functions + --> $DIR/test-attr-non-associated-functions.rs:19:5 + | +LL | / fn new() -> A { //~ ERROR #[test] attribute is only allowed on non associated functions +LL | | A {} +LL | | } + | |_____^ + +error: aborting due to previous error +