Auto merge of #56051 - pietroalbini:rollup, r=pietroalbini
Rollup of 25 pull requests Successful merges: - #55562 (Add powerpc- and powerpc64-unknown-linux-musl targets) - #55564 (test/linkage-visibility: Ignore on musl targets) - #55827 (A few tweaks to iterations/collecting) - #55834 (Forward the ABI of the non-zero sized fields of an union if they have the same ABI) - #55857 (remove unused dependency) - #55862 (in which the E0618 "expected function" diagnostic gets a makeover) - #55867 (do not panic just because cargo failed) - #55894 (miri enum discriminant handling: Fix treatment of pointers, better error when it is undef) - #55916 (Make miri value visitor useful for mutation) - #55919 (core/tests/num: Simplify `test_int_from_str_overflow()` test code) - #55923 (reword #[test] attribute error on fn items) - #55949 (ty: return impl Iterator from Predicate::walk_tys) - #55952 (Update to Clang 7 on CI.) - #55953 (#53488 Refactoring UpvarId) - #55962 (rustdoc: properly calculate spans for intra-doc link resolution errors) - #55963 (Stress test for MPSC) - #55968 (Clean up some non-mod-rs stuff.) - #55970 (Miri backtrace improvements) - #56007 (CTFE: dynamically make sure we do not call non-const-fn) - #56011 (Replace data.clone() by Arc::clone(&data) in mutex doc.) - #56012 (avoid shared ref in UnsafeCell::get) - #56016 (Add VecDeque::resize_with) - #56027 (docs: Add missing backtick in object_safety.rs docs) - #56043 (remove "approx env bounds" if we already know from trait) - #56059 (Increase `Duration` approximate equal threshold to 1us)
This commit is contained in:
commit
9e8a982a23
@ -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
|
||||
|
@ -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)",
|
||||
|
@ -22,7 +22,7 @@
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -13,7 +13,7 @@ set -ex
|
||||
|
||||
source shared.sh
|
||||
|
||||
LLVM=6.0.0
|
||||
LLVM=7.0.0
|
||||
|
||||
mkdir clang
|
||||
cd clang
|
||||
|
@ -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
|
||||
|
@ -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 @@ pub fn resize(&mut self, new_len: usize, value: T) {
|
||||
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.
|
||||
|
@ -1509,7 +1509,9 @@ impl<T: ?Sized> UnsafeCell<T> {
|
||||
#[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<T>` to `T` because of
|
||||
// #[repr(transparent)]
|
||||
self as *const UnsafeCell<T> as *const T as *mut T
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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::<i8>().ok(), Some(i8_val));
|
||||
assert_eq!("127".parse::<i8>().ok(), Some(127i8));
|
||||
assert_eq!("128".parse::<i8>().ok(), None);
|
||||
|
||||
i8_val = i8_val.wrapping_add(1);
|
||||
assert_eq!("-128".parse::<i8>().ok(), Some(i8_val));
|
||||
assert_eq!("-128".parse::<i8>().ok(), Some(-128i8));
|
||||
assert_eq!("-129".parse::<i8>().ok(), None);
|
||||
|
||||
let mut i16_val: i16 = 32_767;
|
||||
assert_eq!("32767".parse::<i16>().ok(), Some(i16_val));
|
||||
assert_eq!("32767".parse::<i16>().ok(), Some(32_767i16));
|
||||
assert_eq!("32768".parse::<i16>().ok(), None);
|
||||
|
||||
i16_val = i16_val.wrapping_add(1);
|
||||
assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val));
|
||||
assert_eq!("-32768".parse::<i16>().ok(), Some(-32_768i16));
|
||||
assert_eq!("-32769".parse::<i16>().ok(), None);
|
||||
|
||||
let mut i32_val: i32 = 2_147_483_647;
|
||||
assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val));
|
||||
assert_eq!("2147483647".parse::<i32>().ok(), Some(2_147_483_647i32));
|
||||
assert_eq!("2147483648".parse::<i32>().ok(), None);
|
||||
|
||||
i32_val = i32_val.wrapping_add(1);
|
||||
assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val));
|
||||
assert_eq!("-2147483648".parse::<i32>().ok(), Some(-2_147_483_648i32));
|
||||
assert_eq!("-2147483649".parse::<i32>().ok(), None);
|
||||
|
||||
let mut i64_val: i64 = 9_223_372_036_854_775_807;
|
||||
assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val));
|
||||
assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(9_223_372_036_854_775_807i64));
|
||||
assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
|
||||
|
||||
i64_val = i64_val.wrapping_add(1);
|
||||
assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
|
||||
assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(-9_223_372_036_854_775_808i64));
|
||||
assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
|
||||
}
|
||||
|
||||
|
@ -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>> {
|
||||
|
@ -1062,8 +1062,7 @@ fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> {
|
||||
attrs
|
||||
.iter()
|
||||
.map(|a| self.lower_attr(a))
|
||||
.collect::<Vec<_>>()
|
||||
.into()
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
|
||||
|
@ -216,7 +216,9 @@ fn hash_stable<W: StableHasherResult>(&self,
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn hash_stable<W: StableHasherResult>(
|
||||
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<'tcx, O> for enum mir::interpret::EvalErrorKind<'tcx, O>
|
||||
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<'tcx, O> for enum mir::interpret::EvalErrorKind<'tcx, O>
|
||||
}
|
||||
);
|
||||
|
||||
impl_stable_hash_for!(enum mir::interpret::InboundsCheck {
|
||||
Live,
|
||||
MaybeDead
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum mir::interpret::Lock {
|
||||
NoLock,
|
||||
WriteLock(dl),
|
||||
|
@ -1315,7 +1315,7 @@ fn report_inference_failure(
|
||||
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)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ pub(super) fn note_region_origin(&self,
|
||||
"...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 @@ pub(super) fn report_concrete_failure(&self,
|
||||
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,
|
||||
|
@ -389,16 +389,6 @@ fn projection_must_outlive(
|
||||
// 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 environment. This
|
||||
// is an "approximate" match -- in some cases, these bounds
|
||||
// may not apply.
|
||||
let 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.
|
||||
@ -406,6 +396,32 @@ fn projection_must_outlive(
|
||||
.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 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
|
||||
);
|
||||
|
||||
// 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. `<T as Foo<'a>>::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,
|
||||
// then, we can break down the outlives into more primitive
|
||||
|
@ -938,7 +938,7 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) {
|
||||
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);
|
||||
|
@ -818,7 +818,7 @@ fn cat_upvar(&self,
|
||||
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(),
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,14 @@
|
||||
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<Tag=(),Extra=()> {
|
||||
/// The actual bytes of the allocation.
|
||||
|
@ -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 fn assert_reported(self) {
|
||||
pub struct ConstEvalErr<'tcx> {
|
||||
pub span: Span,
|
||||
pub error: ::mir::interpret::EvalErrorKind<'tcx, u64>,
|
||||
pub stacktrace: Vec<FrameInfo>,
|
||||
pub stacktrace: Vec<FrameInfo<'tcx>>,
|
||||
}
|
||||
|
||||
#[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<ast::NodeId>,
|
||||
}
|
||||
|
||||
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 @@ fn struct_generic(
|
||||
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, "<unknown>\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) => {
|
||||
|
@ -28,7 +28,7 @@ macro_rules! err {
|
||||
pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};
|
||||
|
||||
pub use self::allocation::{
|
||||
Allocation, AllocationExtra,
|
||||
InboundsCheck, Allocation, AllocationExtra,
|
||||
Relocations, UndefMask,
|
||||
};
|
||||
|
||||
|
@ -470,7 +470,7 @@ fn object_ty_for_trait(self, trait_def_id: DefId, lifetime: ty::Region<'tcx>) ->
|
||||
///
|
||||
/// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
|
||||
/// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
|
||||
/// for `self: Pin<Box<Self>>, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
|
||||
/// for `self: Pin<Box<Self>>`, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
|
||||
//
|
||||
// FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
|
||||
// fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
|
||||
|
@ -789,7 +789,7 @@ fn hash_stable<W: StableHasherResult>(&self,
|
||||
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 @@ fn hash_stable<W: StableHasherResult>(&self,
|
||||
|
||||
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))
|
||||
});
|
||||
|
||||
|
@ -697,7 +697,9 @@ enum StructKind {
|
||||
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 @@ enum StructKind {
|
||||
} 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)
|
||||
}));
|
||||
|
@ -49,7 +49,6 @@
|
||||
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 @@ pub fn empty<'a>() -> &'a List<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 @@ fn to_predicate(&self) -> Predicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// A custom iterator used by Predicate::walk_tys.
|
||||
enum WalkTysIter<'tcx, I, J, K>
|
||||
where I: Iterator<Item = Ty<'tcx>>,
|
||||
J: Iterator<Item = Ty<'tcx>>,
|
||||
K: Iterator<Item = Ty<'tcx>>
|
||||
{
|
||||
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<Item = Ty<'tcx>>,
|
||||
J: Iterator<Item = Ty<'tcx>>,
|
||||
K: Iterator<Item = Ty<'tcx>>
|
||||
{
|
||||
type Item = Ty<'tcx>;
|
||||
|
||||
fn next(&mut self) -> Option<Ty<'tcx>> {
|
||||
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<Ty<'tcx>> {
|
||||
let vec: Vec<_> = match *self {
|
||||
pub fn walk_tys(&'a self) -> impl Iterator<Item = Ty<'tcx>> + '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<PolyTraitRef<'tcx>> {
|
||||
@ -1998,6 +2041,12 @@ pub fn inhibit_enum_layout_opt(&self) -> bool {
|
||||
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 {
|
||||
|
@ -281,7 +281,7 @@ pub fn serialize<'a, 'tcx, E>(&self,
|
||||
// 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;
|
||||
|
@ -678,8 +678,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -453,8 +453,8 @@ pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
|
||||
}
|
||||
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)) |
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -846,7 +846,7 @@ fn report_bckerr(&self, err: &BckError<'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 @@ pub fn append_loan_path_to_string(&self,
|
||||
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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
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)
|
||||
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -365,13 +365,19 @@ fn find_fn(
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> 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) {
|
||||
|
@ -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);
|
||||
|
@ -44,16 +44,22 @@ pub fn cast(
|
||||
}
|
||||
|
||||
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 @@ pub fn cast(
|
||||
}
|
||||
}
|
||||
} 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 @@ pub fn cast(
|
||||
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)?;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
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 @@ pub fn dump_place(&self, place: Place<M::PointerTag>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo> {
|
||||
pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo<'tcx>> {
|
||||
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 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo>
|
||||
} 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 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> Vec<FrameInfo>
|
||||
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
|
||||
|
@ -28,7 +28,7 @@
|
||||
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 @@ pub fn check_align(
|
||||
// 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 @@ pub fn check_align(
|
||||
|
||||
/// 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<M::PointerTag>, 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<M::PointerTag>,
|
||||
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 @@ pub fn check_bounds(
|
||||
&self,
|
||||
ptr: Pointer<M::PointerTag>,
|
||||
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 @@ fn get_bytes_internal(
|
||||
) -> 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 @@ fn get_bytes_mut(
|
||||
) -> 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)?;
|
||||
|
@ -39,6 +39,6 @@
|
||||
|
||||
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;
|
||||
|
@ -19,7 +19,7 @@
|
||||
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 @@ pub fn read_discriminant(
|
||||
// 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 @@ pub fn read_discriminant(
|
||||
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)),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -17,11 +17,11 @@
|
||||
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 @@ fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> EvalResult<'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 @@ fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'
|
||||
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 @@ fn visit_primitive(&mut self, value: ImmTy<'tcx, M::PointerTag>) -> EvalResult<'
|
||||
}
|
||||
// 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
|
||||
|
@ -8,7 +8,7 @@
|
||||
};
|
||||
|
||||
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 @@ fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> EvalResult<
|
||||
{ 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 @@ fn walk_value(&mut self, v: Self::V) -> EvalResult<'tcx>
|
||||
_ => 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.
|
||||
|
@ -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<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + 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() {
|
||||
|
@ -229,7 +229,7 @@ fn data_layout(&self) -> &TargetDataLayout {
|
||||
}
|
||||
|
||||
/// Endianness of the target, which must match cfg(target-endian).
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum Endian {
|
||||
Little,
|
||||
Big
|
||||
|
@ -297,7 +297,9 @@ fn $module() {
|
||||
("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),
|
||||
|
32
src/librustc_target/spec/powerpc64_unknown_linux_musl.rs
Normal file
32
src/librustc_target/spec/powerpc64_unknown_linux_musl.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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,
|
||||
})
|
||||
}
|
31
src/librustc_target/spec/powerpc_unknown_linux_musl.rs
Normal file
31
src/librustc_target/spec/powerpc_unknown_linux_musl.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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,
|
||||
})
|
||||
}
|
@ -219,35 +219,62 @@ fn confirm_builtin_call(&self,
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
});
|
||||
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),
|
||||
});
|
||||
|
||||
err.span_label(call_expr.span, "not a function");
|
||||
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 @@ fn confirm_builtin_call(&self,
|
||||
_ => 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.
|
||||
|
@ -45,14 +45,14 @@
|
||||
use middle::expr_use_visitor as euv;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::mem_categorization::Categorization;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
|
||||
use rustc::infer::UpvarRegion;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
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;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
pub fn closure_analyze(&self, body: &'gcx hir::Body) {
|
||||
@ -121,7 +121,7 @@ fn analyze_closure(
|
||||
}
|
||||
};
|
||||
|
||||
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 @@ fn analyze_closure(
|
||||
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 @@ fn analyze_closure(
|
||||
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 @@ fn final_upvar_tys(&self, closure_id: ast::NodeId) -> Vec<Ty<'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 @@ fn final_upvar_tys(&self, closure_id: ast::NodeId) -> Vec<Ty<'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 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'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 @@ fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'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 @@ fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'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 @@ fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'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 @@ fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'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 @@ fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'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 @@ fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::Borr
|
||||
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 @@ fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::Borr
|
||||
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 @@ fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::Borr
|
||||
/// 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 @@ fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, kind: ty::BorrowKi
|
||||
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 @@ fn adjust_closure_kind(
|
||||
) {
|
||||
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 @@ fn adjust_closure_kind(
|
||||
|
||||
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 @@ fn consume(
|
||||
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 @@ fn borrow(
|
||||
) {
|
||||
debug!(
|
||||
"borrow(borrow_id={}, cmt={:?}, bk={:?})",
|
||||
borrow_id,
|
||||
cmt,
|
||||
bk
|
||||
borrow_id, cmt, bk
|
||||
);
|
||||
|
||||
match bk {
|
||||
|
@ -306,7 +306,7 @@ fn visit_upvar_borrow_map(&mut self) {
|
||||
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,
|
||||
|
@ -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()
|
||||
})
|
||||
};
|
||||
|
||||
|
@ -146,7 +146,7 @@ fn from_hex(&self) -> Result<Vec<u8>, FromHexError> {
|
||||
}
|
||||
|
||||
match modulus {
|
||||
0 => Ok(b.into_iter().collect()),
|
||||
0 => Ok(b),
|
||||
_ => Err(InvalidHexLength),
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@
|
||||
///
|
||||
/// 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
|
||||
|
@ -481,7 +481,7 @@ macro_rules! assert_almost_eq {
|
||||
let (a, b) = ($a, $b);
|
||||
if a != b {
|
||||
let (a, b) = if a > b {(a, b)} else {(b, a)};
|
||||
assert!(a - Duration::new(0, 100) <= b,
|
||||
assert!(a - Duration::new(0, 1000) <= b,
|
||||
"{:?} is not almost equal to {:?}", a, b);
|
||||
}
|
||||
})
|
||||
|
@ -1890,7 +1890,6 @@ fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
|
||||
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![]),
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,6 @@ pub struct ParseSess {
|
||||
pub raw_identifier_spans: Lock<Vec<Span>>,
|
||||
/// The registered diagnostics codes
|
||||
crate registered_diagnostics: Lock<ErrorMap>,
|
||||
// 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<Vec<(ast::Ident, Span)>>,
|
||||
/// Used to determine and report recursive mod inclusions
|
||||
included_mod_stack: Lock<Vec<PathBuf>>,
|
||||
source_map: Lrc<SourceMap>,
|
||||
@ -81,7 +78,6 @@ pub fn with_span_handler(handler: Handler, source_map: Lrc<SourceMap>) -> ParseS
|
||||
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![]),
|
||||
}
|
||||
}
|
||||
|
@ -6591,16 +6591,7 @@ fn submod_path(&mut self,
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
@ -1200,16 +1200,14 @@ fn build_enum_match_tuple<'b>(&self,
|
||||
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::<Vec<String>>();
|
||||
)
|
||||
).collect::<Vec<String>>();
|
||||
|
||||
let self_arg_idents = self_arg_names.iter()
|
||||
.map(|name| cx.ident_of(&name[..]))
|
||||
@ -1218,7 +1216,7 @@ fn build_enum_match_tuple<'b>(&self,
|
||||
// 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<ast::Ident> = 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()
|
||||
|
@ -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 {
|
||||
|
80
src/test/codegen/union-abi.rs
Normal file
80
src/test/codegen/union-abi.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 {} }
|
||||
|
@ -19,6 +19,7 @@ const fn f(x: usize) -> usize {
|
||||
for i in 0..x {
|
||||
//~^ ERROR E0015
|
||||
//~| ERROR E0019
|
||||
//~| ERROR E0080
|
||||
sum += i;
|
||||
}
|
||||
sum
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
172
src/test/run-pass/mpsc_stress.rs
Normal file
172
src/test/run-pass/mpsc_stress.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<AtomicUsize>,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl Barrier {
|
||||
fn new(count: usize) -> Vec<Barrier> {
|
||||
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::<Vec<_>>());
|
||||
}
|
||||
|
||||
#[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 '<unnamed>' 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();
|
||||
}
|
||||
}
|
@ -12,3 +12,7 @@
|
||||
|
||||
pub mod inner_modrs_mod;
|
||||
pub mod inner_foors_mod;
|
||||
pub mod inline {
|
||||
#[path="somename.rs"]
|
||||
pub mod innie;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
pub fn foo() {}
|
@ -0,0 +1 @@
|
||||
pub fn foo() {}
|
@ -10,3 +10,7 @@
|
||||
|
||||
pub mod inner_modrs_mod;
|
||||
pub mod inner_foors_mod;
|
||||
pub mod inline {
|
||||
#[path="somename.rs"]
|
||||
pub mod innie;
|
||||
}
|
||||
|
16
src/test/run-pass/non_modrs_mods/non_modrs_mods.rs
Normal file
16
src/test/run-pass/non_modrs_mods/non_modrs_mods.rs
Normal file
@ -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();
|
||||
}
|
24
src/test/rustdoc-ui/intra-link-span-ice-55723.rs
Normal file
24
src/test/rustdoc-ui/intra-link-span-ice-55723.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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!();
|
||||
}
|
13
src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
Normal file
13
src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
Normal file
@ -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 `/]`
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0080.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -39,6 +39,7 @@ union TransmuteEnum2 {
|
||||
in3: (),
|
||||
out1: Enum2,
|
||||
out2: Wrap<Enum2>, // something wrapping the enum so that we test layout first, not enum
|
||||
out3: Option<Enum2>,
|
||||
}
|
||||
const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 };
|
||||
//~^ ERROR is undefined behavior
|
||||
@ -51,6 +52,10 @@ union TransmuteEnum2 {
|
||||
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<Enum2> = 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 {
|
||||
|
@ -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<Enum2> = 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<Enum2> = 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<Enum2> = 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 .<downcast-variant(Some)>.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`.
|
||||
|
@ -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 .<deref>, but expected plain bytes
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .<deref>, 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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
|
||||
mod auxiliary {
|
||||
mod foo;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -4,7 +4,9 @@ error[E0618]: expected function, found `U`
|
||||
LL | fn foo<U>(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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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}`
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -23,6 +23,8 @@ fn dim() -> usize {
|
||||
fn main() {
|
||||
let array: [usize; Dim3::dim()]
|
||||
//~^ ERROR E0015
|
||||
//~| ERROR E0080
|
||||
= [0; Dim3::dim()];
|
||||
//~^ ERROR E0015
|
||||
//~| ERROR E0080
|
||||
}
|
||||
|
@ -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 `<Dim3 as Dim>::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 `<Dim3 as Dim>::dim`
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Some errors occurred: E0015, E0080.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
5
src/test/ui/missing_non_modrs_mod/foo_inline.rs
Normal file
5
src/test/ui/missing_non_modrs_mod/foo_inline.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// ignore-test this is just a helper for the real test in this dir
|
||||
|
||||
mod inline {
|
||||
mod missing;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user