Auto merge of #73498 - RalfJung:rollup-1mfjcju, r=RalfJung
Rollup of 13 pull requests Successful merges: - #70740 (Enabling static-pie for musl) - #72331 (Report error when casting an C-like enum implementing Drop) - #72486 (Fix asinh of negative values) - #72497 (tag/niche terminology cleanup) - #72999 (Create self-contained directory and move there some of external binaries/libs) - #73130 (Remove const prop for indirects) - #73142 (Ensure std benchmarks get tested.) - #73305 (Disallow loading crates with non-ascii identifier name.) - #73346 (Add rust specific features to print target features) - #73362 (Test that bounds checks are elided when slice len is checked up-front) - #73459 (Reduce pointer casts in Box::into_boxed_slice) - #73464 (Document format correction) - #73479 (Minor tweaks to liballoc) Failed merges: r? @ghost
This commit is contained in:
commit
63b441aafb
@ -23,7 +23,7 @@ use crate::builder::Cargo;
|
||||
use crate::dist;
|
||||
use crate::native;
|
||||
use crate::util::{exe, is_dylib, symlink_dir};
|
||||
use crate::{Compiler, GitRepo, Mode};
|
||||
use crate::{Compiler, DependencyType, GitRepo, Mode};
|
||||
|
||||
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
@ -74,6 +74,7 @@ impl Step for Std {
|
||||
// Even if we're not building std this stage, the new sysroot must
|
||||
// still contain the third party objects needed by various targets.
|
||||
copy_third_party_objects(builder, &compiler, target);
|
||||
copy_self_contained_objects(builder, &compiler, target);
|
||||
|
||||
builder.ensure(StdLink {
|
||||
compiler: compiler_to_use,
|
||||
@ -83,7 +84,8 @@ impl Step for Std {
|
||||
return;
|
||||
}
|
||||
|
||||
target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter());
|
||||
target_deps.extend(copy_third_party_objects(builder, &compiler, target));
|
||||
target_deps.extend(copy_self_contained_objects(builder, &compiler, target));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
|
||||
std_cargo(builder, target, compiler.stage, &mut cargo);
|
||||
@ -109,21 +111,76 @@ impl Step for Std {
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_and_stamp(
|
||||
builder: &Builder<'_>,
|
||||
libdir: &Path,
|
||||
sourcedir: &Path,
|
||||
name: &str,
|
||||
target_deps: &mut Vec<(PathBuf, DependencyType)>,
|
||||
dependency_type: DependencyType,
|
||||
) {
|
||||
let target = libdir.join(name);
|
||||
builder.copy(&sourcedir.join(name), &target);
|
||||
|
||||
target_deps.push((target, dependency_type));
|
||||
}
|
||||
|
||||
/// Copies third party objects needed by various targets.
|
||||
fn copy_third_party_objects(
|
||||
builder: &Builder<'_>,
|
||||
compiler: &Compiler,
|
||||
target: Interned<String>,
|
||||
) -> Vec<PathBuf> {
|
||||
) -> Vec<(PathBuf, DependencyType)> {
|
||||
let libdir = builder.sysroot_libdir(*compiler, target);
|
||||
|
||||
let mut target_deps = vec![];
|
||||
|
||||
let mut copy_and_stamp = |sourcedir: &Path, name: &str| {
|
||||
let target = libdir.join(name);
|
||||
builder.copy(&sourcedir.join(name), &target);
|
||||
target_deps.push(target);
|
||||
// Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
|
||||
//
|
||||
// This target needs to be linked to Fortanix's port of llvm's libunwind.
|
||||
// libunwind requires support for rwlock and printing to stderr,
|
||||
// which is provided by std for this target.
|
||||
if target == "x86_64-fortanix-unknown-sgx" {
|
||||
let src_path_env = "X86_FORTANIX_SGX_LIBS";
|
||||
let src =
|
||||
env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env));
|
||||
copy_and_stamp(
|
||||
builder,
|
||||
&*libdir,
|
||||
Path::new(&src),
|
||||
"libunwind.a",
|
||||
&mut target_deps,
|
||||
DependencyType::Target,
|
||||
);
|
||||
}
|
||||
|
||||
if builder.config.sanitizers && compiler.stage != 0 {
|
||||
// The sanitizers are only copied in stage1 or above,
|
||||
// to avoid creating dependency on LLVM.
|
||||
target_deps.extend(
|
||||
copy_sanitizers(builder, &compiler, target)
|
||||
.into_iter()
|
||||
.map(|d| (d, DependencyType::Target)),
|
||||
);
|
||||
}
|
||||
|
||||
target_deps
|
||||
}
|
||||
|
||||
/// Copies third party objects needed by various targets for self-contained linkage.
|
||||
fn copy_self_contained_objects(
|
||||
builder: &Builder<'_>,
|
||||
compiler: &Compiler,
|
||||
target: Interned<String>,
|
||||
) -> Vec<(PathBuf, DependencyType)> {
|
||||
// cfg(bootstrap)
|
||||
// Remove when upgrading bootstrap compiler.
|
||||
let libdir_self_contained = if compiler.stage == 0 {
|
||||
builder.sysroot_libdir(*compiler, target).to_path_buf()
|
||||
} else {
|
||||
builder.sysroot_libdir(*compiler, target).join("self-contained")
|
||||
};
|
||||
t!(fs::create_dir_all(&libdir_self_contained));
|
||||
let mut target_deps = vec![];
|
||||
|
||||
// Copies the CRT objects.
|
||||
//
|
||||
@ -135,29 +192,32 @@ fn copy_third_party_objects(
|
||||
if target.contains("musl") {
|
||||
let srcdir = builder.musl_root(target).unwrap().join("lib");
|
||||
for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
|
||||
copy_and_stamp(&srcdir, obj);
|
||||
copy_and_stamp(
|
||||
builder,
|
||||
&libdir_self_contained,
|
||||
&srcdir,
|
||||
obj,
|
||||
&mut target_deps,
|
||||
DependencyType::TargetSelfContained,
|
||||
);
|
||||
}
|
||||
} else if target.ends_with("-wasi") {
|
||||
let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
|
||||
copy_and_stamp(&srcdir, "crt1.o");
|
||||
}
|
||||
|
||||
// Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
|
||||
//
|
||||
// This target needs to be linked to Fortanix's port of llvm's libunwind.
|
||||
// libunwind requires support for rwlock and printing to stderr,
|
||||
// which is provided by std for this target.
|
||||
if target == "x86_64-fortanix-unknown-sgx" {
|
||||
let src_path_env = "X86_FORTANIX_SGX_LIBS";
|
||||
let src =
|
||||
env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env));
|
||||
copy_and_stamp(Path::new(&src), "libunwind.a");
|
||||
}
|
||||
|
||||
if builder.config.sanitizers && compiler.stage != 0 {
|
||||
// The sanitizers are only copied in stage1 or above,
|
||||
// to avoid creating dependency on LLVM.
|
||||
target_deps.extend(copy_sanitizers(builder, &compiler, target));
|
||||
copy_and_stamp(
|
||||
builder,
|
||||
&libdir_self_contained,
|
||||
&srcdir,
|
||||
"crt1.o",
|
||||
&mut target_deps,
|
||||
DependencyType::TargetSelfContained,
|
||||
);
|
||||
} else if target.contains("windows-gnu") {
|
||||
for obj in ["crt2.o", "dllcrt2.o"].iter() {
|
||||
let src = compiler_file(builder, builder.cc(target), target, obj);
|
||||
let target = libdir_self_contained.join(obj);
|
||||
builder.copy(&src, &target);
|
||||
target_deps.push((target, DependencyType::TargetSelfContained));
|
||||
}
|
||||
}
|
||||
|
||||
target_deps
|
||||
@ -335,7 +395,7 @@ pub struct StartupObjects {
|
||||
}
|
||||
|
||||
impl Step for StartupObjects {
|
||||
type Output = Vec<PathBuf>;
|
||||
type Output = Vec<(PathBuf, DependencyType)>;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/rtstartup")
|
||||
@ -354,7 +414,7 @@ impl Step for StartupObjects {
|
||||
/// They don't require any library support as they're just plain old object
|
||||
/// files, so we just use the nightly snapshot compiler to always build them (as
|
||||
/// no other compilers are guaranteed to be available).
|
||||
fn run(self, builder: &Builder<'_>) -> Vec<PathBuf> {
|
||||
fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
|
||||
let for_compiler = self.compiler;
|
||||
let target = self.target;
|
||||
if !target.contains("windows-gnu") {
|
||||
@ -388,14 +448,7 @@ impl Step for StartupObjects {
|
||||
|
||||
let target = sysroot_dir.join((*file).to_string() + ".o");
|
||||
builder.copy(dst_file, &target);
|
||||
target_deps.push(target);
|
||||
}
|
||||
|
||||
for obj in ["crt2.o", "dllcrt2.o"].iter() {
|
||||
let src = compiler_file(builder, builder.cc(target), target, obj);
|
||||
let target = sysroot_dir.join(obj);
|
||||
builder.copy(&src, &target);
|
||||
target_deps.push(target);
|
||||
target_deps.push((target, DependencyType::Target));
|
||||
}
|
||||
|
||||
target_deps
|
||||
@ -808,14 +861,17 @@ pub fn add_to_sysroot(
|
||||
sysroot_host_dst: &Path,
|
||||
stamp: &Path,
|
||||
) {
|
||||
let self_contained_dst = &sysroot_dst.join("self-contained");
|
||||
t!(fs::create_dir_all(&sysroot_dst));
|
||||
t!(fs::create_dir_all(&sysroot_host_dst));
|
||||
for (path, host) in builder.read_stamp_file(stamp) {
|
||||
if host {
|
||||
builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap()));
|
||||
} else {
|
||||
builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
|
||||
}
|
||||
t!(fs::create_dir_all(&self_contained_dst));
|
||||
for (path, dependency_type) in builder.read_stamp_file(stamp) {
|
||||
let dst = match dependency_type {
|
||||
DependencyType::Host => sysroot_host_dst,
|
||||
DependencyType::Target => sysroot_dst,
|
||||
DependencyType::TargetSelfContained => self_contained_dst,
|
||||
};
|
||||
builder.copy(&path, &dst.join(path.file_name().unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -824,7 +880,7 @@ pub fn run_cargo(
|
||||
cargo: Cargo,
|
||||
tail_args: Vec<String>,
|
||||
stamp: &Path,
|
||||
additional_target_deps: Vec<PathBuf>,
|
||||
additional_target_deps: Vec<(PathBuf, DependencyType)>,
|
||||
is_check: bool,
|
||||
) -> Vec<PathBuf> {
|
||||
if builder.config.dry_run {
|
||||
@ -875,7 +931,7 @@ pub fn run_cargo(
|
||||
if filename.starts_with(&host_root_dir) {
|
||||
// Unless it's a proc macro used in the compiler
|
||||
if crate_types.iter().any(|t| t == "proc-macro") {
|
||||
deps.push((filename.to_path_buf(), true));
|
||||
deps.push((filename.to_path_buf(), DependencyType::Host));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -883,7 +939,7 @@ pub fn run_cargo(
|
||||
// If this was output in the `deps` dir then this is a precise file
|
||||
// name (hash included) so we start tracking it.
|
||||
if filename.starts_with(&target_deps_dir) {
|
||||
deps.push((filename.to_path_buf(), false));
|
||||
deps.push((filename.to_path_buf(), DependencyType::Target));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -935,17 +991,21 @@ pub fn run_cargo(
|
||||
let candidate = format!("{}.lib", path_to_add);
|
||||
let candidate = PathBuf::from(candidate);
|
||||
if candidate.exists() {
|
||||
deps.push((candidate, false));
|
||||
deps.push((candidate, DependencyType::Target));
|
||||
}
|
||||
}
|
||||
deps.push((path_to_add.into(), false));
|
||||
deps.push((path_to_add.into(), DependencyType::Target));
|
||||
}
|
||||
|
||||
deps.extend(additional_target_deps.into_iter().map(|d| (d, false)));
|
||||
deps.extend(additional_target_deps);
|
||||
deps.sort();
|
||||
let mut new_contents = Vec::new();
|
||||
for (dep, proc_macro) in deps.iter() {
|
||||
new_contents.extend(if *proc_macro { b"h" } else { b"t" });
|
||||
for (dep, dependency_type) in deps.iter() {
|
||||
new_contents.extend(match *dependency_type {
|
||||
DependencyType::Host => b"h",
|
||||
DependencyType::Target => b"t",
|
||||
DependencyType::TargetSelfContained => b"s",
|
||||
});
|
||||
new_contents.extend(dep.to_str().unwrap().as_bytes());
|
||||
new_contents.extend(b"\0");
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ use crate::channel;
|
||||
use crate::compile;
|
||||
use crate::tool::{self, Tool};
|
||||
use crate::util::{exe, is_dylib, timeit};
|
||||
use crate::{Compiler, Mode, LLVM_TOOLS};
|
||||
use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS};
|
||||
use time::{self, Timespec};
|
||||
|
||||
pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
|
||||
@ -306,7 +306,12 @@ fn make_win_dist(
|
||||
}
|
||||
|
||||
//Copy platform tools to platform-specific bin directory
|
||||
let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin");
|
||||
let target_bin_dir = plat_root
|
||||
.join("lib")
|
||||
.join("rustlib")
|
||||
.join(target_triple)
|
||||
.join("bin")
|
||||
.join("self-contained");
|
||||
fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
|
||||
for src in target_tools {
|
||||
builder.copy_to_folder(&src, &target_bin_dir);
|
||||
@ -321,7 +326,12 @@ fn make_win_dist(
|
||||
);
|
||||
|
||||
//Copy platform libs to platform-specific lib directory
|
||||
let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
|
||||
let target_lib_dir = plat_root
|
||||
.join("lib")
|
||||
.join("rustlib")
|
||||
.join(target_triple)
|
||||
.join("lib")
|
||||
.join("self-contained");
|
||||
fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
|
||||
for src in target_libs {
|
||||
builder.copy_to_folder(&src, &target_lib_dir);
|
||||
@ -652,9 +662,13 @@ fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
|
||||
/// Copy stamped files into an image's `target/lib` directory.
|
||||
fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) {
|
||||
let dst = image.join("lib/rustlib").join(target).join("lib");
|
||||
let self_contained_dst = dst.join("self-contained");
|
||||
t!(fs::create_dir_all(&dst));
|
||||
for (path, host) in builder.read_stamp_file(stamp) {
|
||||
if !host || builder.config.build == target {
|
||||
t!(fs::create_dir_all(&self_contained_dst));
|
||||
for (path, dependency_type) in builder.read_stamp_file(stamp) {
|
||||
if dependency_type == DependencyType::TargetSelfContained {
|
||||
builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap()));
|
||||
} else if dependency_type == DependencyType::Target || builder.config.build == target {
|
||||
builder.copy(&path, &dst.join(path.file_name().unwrap()));
|
||||
}
|
||||
}
|
||||
|
@ -280,6 +280,17 @@ impl Crate {
|
||||
}
|
||||
}
|
||||
|
||||
/// When building Rust various objects are handled differently.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum DependencyType {
|
||||
/// Libraries originating from proc-macros.
|
||||
Host,
|
||||
/// Typical Rust libraries.
|
||||
Target,
|
||||
/// Non Rust libraries and objects shipped to ease usage of certain targets.
|
||||
TargetSelfContained,
|
||||
}
|
||||
|
||||
/// The various "modes" of invoking Cargo.
|
||||
///
|
||||
/// These entries currently correspond to the various output directories of the
|
||||
@ -1097,7 +1108,7 @@ impl Build {
|
||||
ret
|
||||
}
|
||||
|
||||
fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> {
|
||||
fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, DependencyType)> {
|
||||
if self.config.dry_run {
|
||||
return Vec::new();
|
||||
}
|
||||
@ -1110,9 +1121,14 @@ impl Build {
|
||||
if part.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let host = part[0] as char == 'h';
|
||||
let dependency_type = match part[0] as char {
|
||||
'h' => DependencyType::Host,
|
||||
's' => DependencyType::TargetSelfContained,
|
||||
't' => DependencyType::Target,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let path = PathBuf::from(t!(str::from_utf8(&part[1..])));
|
||||
paths.push((path, host));
|
||||
paths.push((path, dependency_type));
|
||||
}
|
||||
paths
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ path = "../liballoc/tests/lib.rs"
|
||||
[[bench]]
|
||||
name = "collectionsbenches"
|
||||
path = "../liballoc/benches/lib.rs"
|
||||
test = true
|
||||
|
||||
[[bench]]
|
||||
name = "vec_deque_append_bench"
|
||||
|
@ -248,7 +248,7 @@ impl<T> Box<T> {
|
||||
#[unstable(feature = "box_into_boxed_slice", issue = "71582")]
|
||||
pub fn into_boxed_slice(boxed: Box<T>) -> Box<[T]> {
|
||||
// *mut T and *mut [T; 1] have the same size and alignment
|
||||
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1] as *mut [T]) }
|
||||
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1]) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1639,7 +1639,7 @@ impl<T: Default> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// This code generalises `extend_with_{element,default}`.
|
||||
// This code generalizes `extend_with_{element,default}`.
|
||||
trait ExtendWith<T> {
|
||||
fn next(&mut self) -> T;
|
||||
fn last(self) -> T;
|
||||
@ -1837,7 +1837,7 @@ unsafe trait IsZero {
|
||||
}
|
||||
|
||||
macro_rules! impl_is_zero {
|
||||
($t: ty, $is_zero: expr) => {
|
||||
($t:ty, $is_zero:expr) => {
|
||||
unsafe impl IsZero for $t {
|
||||
#[inline]
|
||||
fn is_zero(&self) -> bool {
|
||||
@ -2362,9 +2362,9 @@ macro_rules! __impl_slice_eq1 {
|
||||
__impl_slice_eq1! { [] Vec<A>, Vec<B>, }
|
||||
__impl_slice_eq1! { [] Vec<A>, &[B], }
|
||||
__impl_slice_eq1! { [] Vec<A>, &mut [B], }
|
||||
__impl_slice_eq1! { [] Cow<'_, [A]>, Vec<B>, A: Clone }
|
||||
__impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone }
|
||||
__impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone }
|
||||
__impl_slice_eq1! { [] Cow<'_, [A]>, Vec<B>, A: Clone }
|
||||
__impl_slice_eq1! { [const N: usize] Vec<A>, [B; N], [B; N]: LengthAtMost32 }
|
||||
__impl_slice_eq1! { [const N: usize] Vec<A>, &[B; N], [B; N]: LengthAtMost32 }
|
||||
|
||||
|
@ -19,6 +19,7 @@ path = "../libcore/tests/lib.rs"
|
||||
[[bench]]
|
||||
name = "corebenches"
|
||||
path = "../libcore/benches/lib.rs"
|
||||
test = true
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7"
|
||||
|
@ -1,3 +1,5 @@
|
||||
// wasm32 does not support benches (no time).
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
#![feature(flt2dec)]
|
||||
#![feature(test)]
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use self::EnumDiscriminantInfo::*;
|
||||
use self::EnumTagInfo::*;
|
||||
use self::MemberDescriptionFactory::*;
|
||||
use self::RecursiveTypeDescription::*;
|
||||
|
||||
@ -40,7 +40,7 @@ use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::config::{self, DebugInfo};
|
||||
use rustc_span::symbol::{Interner, Symbol};
|
||||
use rustc_span::{self, SourceFile, SourceFileHash, Span};
|
||||
use rustc_target::abi::{Abi, Align, DiscriminantKind, HasDataLayout, Integer, LayoutOf};
|
||||
use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding};
|
||||
use rustc_target::abi::{Int, Pointer, F32, F64};
|
||||
use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
|
||||
|
||||
@ -1335,7 +1335,7 @@ fn generator_layout_and_saved_local_names(
|
||||
struct EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
enum_type: Ty<'tcx>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
discriminant_type_metadata: Option<&'ll DIType>,
|
||||
tag_type_metadata: Option<&'ll DIType>,
|
||||
containing_scope: &'ll DIScope,
|
||||
span: Span,
|
||||
}
|
||||
@ -1385,7 +1385,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
cx,
|
||||
self.layout,
|
||||
variant_info,
|
||||
NoDiscriminant,
|
||||
NoTag,
|
||||
self_metadata,
|
||||
self.span,
|
||||
);
|
||||
@ -1409,19 +1409,19 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
}]
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr_index,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag_field,
|
||||
ref variants,
|
||||
..
|
||||
} => {
|
||||
let discriminant_info = if fallback {
|
||||
RegularDiscriminant {
|
||||
discr_field: Field::from(discr_index),
|
||||
discr_type_metadata: self.discriminant_type_metadata.unwrap(),
|
||||
let tag_info = if fallback {
|
||||
RegularTag {
|
||||
tag_field: Field::from(tag_field),
|
||||
tag_type_metadata: self.tag_type_metadata.unwrap(),
|
||||
}
|
||||
} else {
|
||||
// This doesn't matter in this case.
|
||||
NoDiscriminant
|
||||
NoTag
|
||||
};
|
||||
variants
|
||||
.iter_enumerated()
|
||||
@ -1432,7 +1432,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
cx,
|
||||
variant,
|
||||
variant_info,
|
||||
discriminant_info,
|
||||
tag_info,
|
||||
self_metadata,
|
||||
self.span,
|
||||
);
|
||||
@ -1467,11 +1467,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
.collect()
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind:
|
||||
DiscriminantKind::Niche { ref niche_variants, niche_start, dataful_variant },
|
||||
ref discr,
|
||||
tag_encoding:
|
||||
TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
|
||||
ref tag,
|
||||
ref variants,
|
||||
discr_index,
|
||||
tag_field,
|
||||
} => {
|
||||
if fallback {
|
||||
let variant = self.layout.for_variant(cx, dataful_variant);
|
||||
@ -1480,7 +1480,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
cx,
|
||||
variant,
|
||||
variant_info_for(dataful_variant),
|
||||
OptimizedDiscriminant,
|
||||
OptimizedTag,
|
||||
self.containing_scope,
|
||||
self.span,
|
||||
);
|
||||
@ -1524,8 +1524,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
cx,
|
||||
&mut name,
|
||||
self.layout,
|
||||
self.layout.fields.offset(discr_index),
|
||||
self.layout.field(cx, discr_index).size,
|
||||
self.layout.fields.offset(tag_field),
|
||||
self.layout.field(cx, tag_field).size,
|
||||
);
|
||||
variant_info_for(*niche_variants.start()).map_struct_name(|variant_name| {
|
||||
name.push_str(variant_name);
|
||||
@ -1552,7 +1552,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
cx,
|
||||
variant,
|
||||
variant_info,
|
||||
OptimizedDiscriminant,
|
||||
OptimizedTag,
|
||||
self_metadata,
|
||||
self.span,
|
||||
);
|
||||
@ -1573,7 +1573,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
let value = (i.as_u32() as u128)
|
||||
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
||||
.wrapping_add(niche_start);
|
||||
let value = truncate(value, discr.value.size(cx));
|
||||
let value = truncate(value, tag.value.size(cx));
|
||||
// NOTE(eddyb) do *NOT* remove this assert, until
|
||||
// we pass the full 128-bit value to LLVM, otherwise
|
||||
// truncation will be silent and remain undetected.
|
||||
@ -1603,7 +1603,7 @@ struct VariantMemberDescriptionFactory<'ll, 'tcx> {
|
||||
/// Cloned from the `layout::Struct` describing the variant.
|
||||
offsets: Vec<Size>,
|
||||
args: Vec<(String, Ty<'tcx>)>,
|
||||
discriminant_type_metadata: Option<&'ll DIType>,
|
||||
tag_type_metadata: Option<&'ll DIType>,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
@ -1617,7 +1617,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
|
||||
MemberDescription {
|
||||
name: name.to_string(),
|
||||
type_metadata: if use_enum_fallback(cx) {
|
||||
match self.discriminant_type_metadata {
|
||||
match self.tag_type_metadata {
|
||||
// Discriminant is always the first field of our variant
|
||||
// when using the enum fallback.
|
||||
Some(metadata) if i == 0 => metadata,
|
||||
@ -1637,11 +1637,14 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: terminology here should be aligned with `abi::TagEncoding`.
|
||||
// `OptimizedTag` is `TagEncoding::Niche`, `RegularTag` is `TagEncoding::Direct`.
|
||||
// `NoTag` should be removed; users should use `Option<EnumTagInfo>` instead.
|
||||
#[derive(Copy, Clone)]
|
||||
enum EnumDiscriminantInfo<'ll> {
|
||||
RegularDiscriminant { discr_field: Field, discr_type_metadata: &'ll DIType },
|
||||
OptimizedDiscriminant,
|
||||
NoDiscriminant,
|
||||
enum EnumTagInfo<'ll> {
|
||||
RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType },
|
||||
OptimizedTag,
|
||||
NoTag,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -1706,7 +1709,7 @@ fn describe_enum_variant(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
layout: layout::TyAndLayout<'tcx>,
|
||||
variant: VariantInfo<'_, 'tcx>,
|
||||
discriminant_info: EnumDiscriminantInfo<'ll>,
|
||||
discriminant_info: EnumTagInfo<'ll>,
|
||||
containing_scope: &'ll DIScope,
|
||||
span: Span,
|
||||
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
|
||||
@ -1722,12 +1725,12 @@ fn describe_enum_variant(
|
||||
let (offsets, args) = if use_enum_fallback(cx) {
|
||||
// If this is not a univariant enum, there is also the discriminant field.
|
||||
let (discr_offset, discr_arg) = match discriminant_info {
|
||||
RegularDiscriminant { discr_field, .. } => {
|
||||
RegularTag { tag_field, .. } => {
|
||||
// We have the layout of an enum variant, we need the layout of the outer enum
|
||||
let enum_layout = cx.layout_of(layout.ty);
|
||||
let offset = enum_layout.fields.offset(discr_field.as_usize());
|
||||
let offset = enum_layout.fields.offset(tag_field.as_usize());
|
||||
let args =
|
||||
("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, discr_field.as_usize()).ty);
|
||||
("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
|
||||
(Some(offset), Some(args))
|
||||
}
|
||||
_ => (None, None),
|
||||
@ -1757,8 +1760,8 @@ fn describe_enum_variant(
|
||||
let member_description_factory = VariantMDF(VariantMemberDescriptionFactory {
|
||||
offsets,
|
||||
args,
|
||||
discriminant_type_metadata: match discriminant_info {
|
||||
RegularDiscriminant { discr_type_metadata, .. } => Some(discr_type_metadata),
|
||||
tag_type_metadata: match discriminant_info {
|
||||
RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata),
|
||||
_ => None,
|
||||
},
|
||||
span,
|
||||
@ -1880,18 +1883,18 @@ fn prepare_enum_metadata(
|
||||
|
||||
if let (
|
||||
&Abi::Scalar(_),
|
||||
&Variants::Multiple { discr_kind: DiscriminantKind::Tag, ref discr, .. },
|
||||
&Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. },
|
||||
) = (&layout.abi, &layout.variants)
|
||||
{
|
||||
return FinalMetadata(discriminant_type_metadata(discr.value));
|
||||
return FinalMetadata(discriminant_type_metadata(tag.value));
|
||||
}
|
||||
|
||||
if use_enum_fallback(cx) {
|
||||
let discriminant_type_metadata = match layout.variants {
|
||||
Variants::Single { .. }
|
||||
| Variants::Multiple { discr_kind: DiscriminantKind::Niche { .. }, .. } => None,
|
||||
Variants::Multiple { discr_kind: DiscriminantKind::Tag, ref discr, .. } => {
|
||||
Some(discriminant_type_metadata(discr.value))
|
||||
| Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None,
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
|
||||
Some(discriminant_type_metadata(tag.value))
|
||||
}
|
||||
};
|
||||
|
||||
@ -1927,7 +1930,7 @@ fn prepare_enum_metadata(
|
||||
EnumMDF(EnumMemberDescriptionFactory {
|
||||
enum_type,
|
||||
layout,
|
||||
discriminant_type_metadata,
|
||||
tag_type_metadata: discriminant_type_metadata,
|
||||
containing_scope,
|
||||
span,
|
||||
}),
|
||||
@ -1943,16 +1946,13 @@ fn prepare_enum_metadata(
|
||||
Variants::Single { .. } => None,
|
||||
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Niche { .. },
|
||||
ref discr,
|
||||
discr_index,
|
||||
..
|
||||
tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, ..
|
||||
} => {
|
||||
// Find the integer type of the correct size.
|
||||
let size = discr.value.size(cx);
|
||||
let align = discr.value.align(cx);
|
||||
let size = tag.value.size(cx);
|
||||
let align = tag.value.align(cx);
|
||||
|
||||
let discr_type = match discr.value {
|
||||
let tag_type = match tag.value {
|
||||
Int(t, _) => t,
|
||||
F32 => Integer::I32,
|
||||
F64 => Integer::I64,
|
||||
@ -1960,7 +1960,7 @@ fn prepare_enum_metadata(
|
||||
}
|
||||
.to_ty(cx.tcx, false);
|
||||
|
||||
let discr_metadata = basic_type_metadata(cx, discr_type);
|
||||
let tag_metadata = basic_type_metadata(cx, tag_type);
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateMemberType(
|
||||
DIB(cx),
|
||||
@ -1971,17 +1971,15 @@ fn prepare_enum_metadata(
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
align.abi.bits() as u32,
|
||||
layout.fields.offset(discr_index).bits(),
|
||||
layout.fields.offset(tag_field).bits(),
|
||||
DIFlags::FlagArtificial,
|
||||
discr_metadata,
|
||||
tag_metadata,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag, ref discr, discr_index, ..
|
||||
} => {
|
||||
let discr_type = discr.value.to_ty(cx.tcx);
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => {
|
||||
let discr_type = tag.value.to_ty(cx.tcx);
|
||||
let (size, align) = cx.size_and_align_of(discr_type);
|
||||
|
||||
let discr_metadata = basic_type_metadata(cx, discr_type);
|
||||
@ -1995,7 +1993,7 @@ fn prepare_enum_metadata(
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
size.bits(),
|
||||
align.bits() as u32,
|
||||
layout.fields.offset(discr_index).bits(),
|
||||
layout.fields.offset(tag_field).bits(),
|
||||
DIFlags::FlagArtificial,
|
||||
discr_metadata,
|
||||
))
|
||||
@ -2081,7 +2079,7 @@ fn prepare_enum_metadata(
|
||||
EnumMDF(EnumMemberDescriptionFactory {
|
||||
enum_type,
|
||||
layout,
|
||||
discriminant_type_metadata: None,
|
||||
tag_type_metadata: None,
|
||||
containing_scope,
|
||||
span,
|
||||
}),
|
||||
|
@ -1075,6 +1075,10 @@ fn get_object_file_path(sess: &Session, name: &str) -> PathBuf {
|
||||
if file_path.exists() {
|
||||
return file_path;
|
||||
}
|
||||
let file_path = fs.get_selfcontained_lib_path().join(name);
|
||||
if file_path.exists() {
|
||||
return file_path;
|
||||
}
|
||||
for search_path in fs.search_paths() {
|
||||
let file_path = search_path.dir.join(name);
|
||||
if file_path.exists() {
|
||||
@ -1470,6 +1474,9 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
|
||||
// The location of crates will be determined as needed.
|
||||
let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
|
||||
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
|
||||
|
||||
let lib_path = sess.target_filesearch(PathKind::All).get_selfcontained_lib_path();
|
||||
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
|
||||
}
|
||||
|
||||
/// Add options making relocation sections in the produced ELF files read-only
|
||||
|
@ -10,7 +10,7 @@ use rustc_middle::mir;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_target::abi::{Abi, Align, DiscriminantKind, FieldsShape, Int};
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape, Int, TagEncoding};
|
||||
use rustc_target::abi::{LayoutOf, VariantIdx, Variants};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -199,7 +199,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
if self.layout.abi.is_uninhabited() {
|
||||
return bx.cx().const_undef(cast_to);
|
||||
}
|
||||
let (discr_scalar, discr_kind, discr_index) = match self.layout.variants {
|
||||
let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants {
|
||||
Variants::Single { index } => {
|
||||
let discr_val = self
|
||||
.layout
|
||||
@ -208,33 +208,33 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
.map_or(index.as_u32() as u128, |discr| discr.val);
|
||||
return bx.cx().const_uint_big(cast_to, discr_val);
|
||||
}
|
||||
Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => {
|
||||
(discr, discr_kind, discr_index)
|
||||
Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
|
||||
(tag, tag_encoding, tag_field)
|
||||
}
|
||||
};
|
||||
|
||||
// Read the tag/niche-encoded discriminant from memory.
|
||||
let encoded_discr = self.project_field(bx, discr_index);
|
||||
let encoded_discr = bx.load_operand(encoded_discr);
|
||||
let tag = self.project_field(bx, tag_field);
|
||||
let tag = bx.load_operand(tag);
|
||||
|
||||
// Decode the discriminant (specifically if it's niche-encoded).
|
||||
match *discr_kind {
|
||||
DiscriminantKind::Tag => {
|
||||
let signed = match discr_scalar.value {
|
||||
match *tag_encoding {
|
||||
TagEncoding::Direct => {
|
||||
let signed = match tag_scalar.value {
|
||||
// We use `i1` for bytes that are always `0` or `1`,
|
||||
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
|
||||
// let LLVM interpret the `i1` as signed, because
|
||||
// then `i1 1` (i.e., `E::B`) is effectively `i8 -1`.
|
||||
Int(_, signed) => !discr_scalar.is_bool() && signed,
|
||||
Int(_, signed) => !tag_scalar.is_bool() && signed,
|
||||
_ => false,
|
||||
};
|
||||
bx.intcast(encoded_discr.immediate(), cast_to, signed)
|
||||
bx.intcast(tag.immediate(), cast_to, signed)
|
||||
}
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
// Rebase from niche values to discriminants, and check
|
||||
// whether the result is in range for the niche variants.
|
||||
let niche_llty = bx.cx().immediate_backend_type(encoded_discr.layout);
|
||||
let encoded_discr = encoded_discr.immediate();
|
||||
let niche_llty = bx.cx().immediate_backend_type(tag.layout);
|
||||
let tag = tag.immediate();
|
||||
|
||||
// We first compute the "relative discriminant" (wrt `niche_variants`),
|
||||
// that is, if `n = niche_variants.end() - niche_variants.start()`,
|
||||
@ -248,9 +248,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
let relative_discr = if niche_start == 0 {
|
||||
// Avoid subtracting `0`, which wouldn't work for pointers.
|
||||
// FIXME(eddyb) check the actual primitive type here.
|
||||
encoded_discr
|
||||
tag
|
||||
} else {
|
||||
bx.sub(encoded_discr, bx.cx().const_uint_big(niche_llty, niche_start))
|
||||
bx.sub(tag, bx.cx().const_uint_big(niche_llty, niche_start))
|
||||
};
|
||||
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
|
||||
let is_niche = {
|
||||
@ -312,8 +312,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
Variants::Single { index } => {
|
||||
assert_eq!(index, variant_index);
|
||||
}
|
||||
Variants::Multiple { discr_kind: DiscriminantKind::Tag, discr_index, .. } => {
|
||||
let ptr = self.project_field(bx, discr_index);
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => {
|
||||
let ptr = self.project_field(bx, tag_field);
|
||||
let to =
|
||||
self.layout.ty.discriminant_for_variant(bx.tcx(), variant_index).unwrap().val;
|
||||
bx.store(
|
||||
@ -323,9 +323,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
);
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind:
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
discr_index,
|
||||
tag_encoding:
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
if variant_index != dataful_variant {
|
||||
@ -339,7 +339,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||
bx.memset(self.llval, fill_byte, size, self.align, MemFlags::empty());
|
||||
}
|
||||
|
||||
let niche = self.project_field(bx, discr_index);
|
||||
let niche = self.project_field(bx, tag_field);
|
||||
let niche_llty = bx.cx().immediate_backend_type(niche.layout);
|
||||
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
|
||||
let niche_value = (niche_value as u128).wrapping_add(niche_start);
|
||||
|
@ -15,7 +15,7 @@ use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_span::source_map;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{DiscriminantKind, Integer, LayoutOf, VariantIdx, Variants};
|
||||
use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use log::debug;
|
||||
@ -1056,15 +1056,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
||||
};
|
||||
let (variants, tag) = match layout.variants {
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
ref discr,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
ref tag,
|
||||
ref variants,
|
||||
..
|
||||
} => (variants, discr),
|
||||
} => (variants, tag),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let discr_size = tag.value.size(&cx.tcx).bytes();
|
||||
let tag_size = tag.value.size(&cx.tcx).bytes();
|
||||
|
||||
debug!(
|
||||
"enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||
@ -1078,8 +1078,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
||||
.iter()
|
||||
.zip(variants)
|
||||
.map(|(variant, variant_layout)| {
|
||||
// Subtract the size of the enum discriminant.
|
||||
let bytes = variant_layout.size.bytes().saturating_sub(discr_size);
|
||||
// Subtract the size of the enum tag.
|
||||
let bytes = variant_layout.size.bytes().saturating_sub(tag_size);
|
||||
|
||||
debug!("- variant `{}` is {} bytes large", variant.ident, bytes);
|
||||
bytes
|
||||
|
@ -452,6 +452,14 @@ impl<'a> CrateLoader<'a> {
|
||||
if dep.is_none() {
|
||||
self.used_extern_options.insert(name);
|
||||
}
|
||||
if !name.as_str().is_ascii() {
|
||||
self.sess
|
||||
.struct_span_err(
|
||||
span,
|
||||
&format!("cannot load a crate with a non-ascii name `{}`", name,),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
|
||||
}
|
||||
|
||||
|
@ -390,8 +390,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
|
||||
InvalidBool(u8),
|
||||
/// Using a non-character `u32` as character.
|
||||
InvalidChar(u32),
|
||||
/// An enum discriminant was set to a value which was outside the range of valid values.
|
||||
InvalidDiscriminant(Scalar),
|
||||
/// The tag of an enum does not encode an actual discriminant.
|
||||
InvalidTag(Scalar),
|
||||
/// Using a pointer-not-to-a-function as function pointer.
|
||||
InvalidFunctionPointer(Pointer),
|
||||
/// Using a string that is not valid UTF-8,
|
||||
@ -463,7 +463,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
|
||||
InvalidChar(c) => {
|
||||
write!(f, "interpreting an invalid 32-bit value as a char: 0x{:08x}", c)
|
||||
}
|
||||
InvalidDiscriminant(val) => write!(f, "enum value has invalid discriminant: {}", val),
|
||||
InvalidTag(val) => write!(f, "enum value has invalid tag: {}", val),
|
||||
InvalidFunctionPointer(p) => {
|
||||
write!(f, "using {} as function pointer but it does not point to a function", p)
|
||||
}
|
||||
|
@ -974,13 +974,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
return Ok(tcx.intern_layout(Layout {
|
||||
variants: Variants::Multiple {
|
||||
discr: niche_scalar,
|
||||
discr_kind: DiscriminantKind::Niche {
|
||||
tag: niche_scalar,
|
||||
tag_encoding: TagEncoding::Niche {
|
||||
dataful_variant: i,
|
||||
niche_variants,
|
||||
niche_start,
|
||||
},
|
||||
discr_index: 0,
|
||||
tag_field: 0,
|
||||
variants: st,
|
||||
},
|
||||
fields: FieldsShape::Arbitrary {
|
||||
@ -1216,9 +1216,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
tcx.intern_layout(Layout {
|
||||
variants: Variants::Multiple {
|
||||
discr: tag,
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr_index: 0,
|
||||
tag,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag_field: 0,
|
||||
variants: layout_variants,
|
||||
},
|
||||
fields: FieldsShape::Arbitrary {
|
||||
@ -1399,15 +1399,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
// Build a prefix layout, including "promoting" all ineligible
|
||||
// locals as part of the prefix. We compute the layout of all of
|
||||
// these fields at once to get optimal packing.
|
||||
let discr_index = substs.as_generator().prefix_tys().count();
|
||||
let tag_index = substs.as_generator().prefix_tys().count();
|
||||
|
||||
// `info.variant_fields` already accounts for the reserved variants, so no need to add them.
|
||||
let max_discr = (info.variant_fields.len() - 1) as u128;
|
||||
let discr_int = Integer::fit_unsigned(max_discr);
|
||||
let discr_int_ty = discr_int.to_ty(tcx, false);
|
||||
let discr = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
|
||||
let discr_layout = self.tcx.intern_layout(Layout::scalar(self, discr.clone()));
|
||||
let discr_layout = TyAndLayout { ty: discr_int_ty, layout: discr_layout };
|
||||
let tag = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
|
||||
let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone()));
|
||||
let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
|
||||
|
||||
let promoted_layouts = ineligible_locals
|
||||
.iter()
|
||||
@ -1418,7 +1418,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
.as_generator()
|
||||
.prefix_tys()
|
||||
.map(|ty| self.layout_of(ty))
|
||||
.chain(iter::once(Ok(discr_layout)))
|
||||
.chain(iter::once(Ok(tag_layout)))
|
||||
.chain(promoted_layouts)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let prefix = self.univariant_uninterned(
|
||||
@ -1441,7 +1441,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
// "a" (`0..b_start`) and "b" (`b_start..`) correspond to
|
||||
// "outer" and "promoted" fields respectively.
|
||||
let b_start = (discr_index + 1) as u32;
|
||||
let b_start = (tag_index + 1) as u32;
|
||||
let offsets_b = offsets.split_off(b_start as usize);
|
||||
let offsets_a = offsets;
|
||||
|
||||
@ -1558,9 +1558,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
let layout = tcx.intern_layout(Layout {
|
||||
variants: Variants::Multiple {
|
||||
discr,
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr_index,
|
||||
tag: tag,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag_field: tag_index,
|
||||
variants,
|
||||
},
|
||||
fields: outer_fields,
|
||||
@ -1680,7 +1680,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
}
|
||||
}
|
||||
|
||||
Variants::Multiple { ref discr, ref discr_kind, .. } => {
|
||||
Variants::Multiple { ref tag, ref tag_encoding, .. } => {
|
||||
debug!(
|
||||
"print-type-size `{:#?}` adt general variants def {}",
|
||||
layout.ty,
|
||||
@ -1702,8 +1702,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
record(
|
||||
adt_kind.into(),
|
||||
adt_packed,
|
||||
match discr_kind {
|
||||
DiscriminantKind::Tag => Some(discr.value.size(self)),
|
||||
match tag_encoding {
|
||||
TagEncoding::Direct => Some(tag.value.size(self)),
|
||||
_ => None,
|
||||
},
|
||||
variant_infos,
|
||||
@ -2028,11 +2028,11 @@ where
|
||||
|
||||
fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
|
||||
let tcx = cx.tcx();
|
||||
let discr_layout = |discr: &Scalar| -> C::TyAndLayout {
|
||||
let layout = Layout::scalar(cx, discr.clone());
|
||||
let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
|
||||
let layout = Layout::scalar(cx, tag.clone());
|
||||
MaybeResult::from(Ok(TyAndLayout {
|
||||
layout: tcx.intern_layout(layout),
|
||||
ty: discr.value.to_ty(tcx),
|
||||
ty: tag.value.to_ty(tcx),
|
||||
}))
|
||||
};
|
||||
|
||||
@ -2109,9 +2109,9 @@ where
|
||||
.unwrap()
|
||||
.nth(i)
|
||||
.unwrap(),
|
||||
Variants::Multiple { ref discr, discr_index, .. } => {
|
||||
if i == discr_index {
|
||||
return discr_layout(discr);
|
||||
Variants::Multiple { ref tag, tag_field, .. } => {
|
||||
if i == tag_field {
|
||||
return tag_layout(tag);
|
||||
}
|
||||
substs.as_generator().prefix_tys().nth(i).unwrap()
|
||||
}
|
||||
@ -2128,9 +2128,9 @@ where
|
||||
Variants::Single { index } => def.variants[index].fields[i].ty(tcx, substs),
|
||||
|
||||
// Discriminant field for enums (where applicable).
|
||||
Variants::Multiple { ref discr, .. } => {
|
||||
Variants::Multiple { ref tag, .. } => {
|
||||
assert_eq!(i, 0);
|
||||
return discr_layout(discr);
|
||||
return tag_layout(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2207,10 +2207,10 @@ where
|
||||
// using more niches than just null (e.g., the first page of
|
||||
// the address space, or unaligned pointers).
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Niche { dataful_variant, .. },
|
||||
discr_index,
|
||||
tag_encoding: TagEncoding::Niche { dataful_variant, .. },
|
||||
tag_field,
|
||||
..
|
||||
} if this.fields.offset(discr_index) == offset => {
|
||||
} if this.fields.offset(tag_field) == offset => {
|
||||
Some(this.for_variant(cx, dataful_variant))
|
||||
}
|
||||
_ => Some(this),
|
||||
|
@ -293,7 +293,6 @@ pub enum InternKind {
|
||||
Static(hir::Mutability),
|
||||
Constant,
|
||||
Promoted,
|
||||
ConstProp,
|
||||
}
|
||||
|
||||
/// Intern `ret` and everything it references.
|
||||
@ -314,9 +313,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
||||
let base_intern_mode = match intern_kind {
|
||||
InternKind::Static(mutbl) => InternMode::Static(mutbl),
|
||||
// FIXME: what about array lengths, array initializers?
|
||||
InternKind::Constant | InternKind::ConstProp | InternKind::Promoted => {
|
||||
InternMode::ConstBase
|
||||
}
|
||||
InternKind::Constant | InternKind::Promoted => InternMode::ConstBase,
|
||||
};
|
||||
|
||||
// Type based interning.
|
||||
@ -358,7 +355,10 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
||||
Err(error) => {
|
||||
ecx.tcx.sess.delay_span_bug(
|
||||
ecx.tcx.span,
|
||||
"error during interning should later cause validation failure",
|
||||
&format!(
|
||||
"error during interning should later cause validation failure: {}",
|
||||
error
|
||||
),
|
||||
);
|
||||
// Some errors shouldn't come up because creating them causes
|
||||
// an allocation, which we should avoid. When that happens,
|
||||
@ -399,7 +399,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
||||
// immutability is so important.
|
||||
alloc.mutability = Mutability::Not;
|
||||
}
|
||||
InternKind::Constant | InternKind::ConstProp => {
|
||||
InternKind::Constant => {
|
||||
// If it's a constant, we should not have any "leftovers" as everything
|
||||
// is tracked by const-checking.
|
||||
// FIXME: downgrade this to a warning? It rejects some legitimate consts,
|
||||
|
@ -11,7 +11,7 @@ use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
|
||||
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_target::abi::{Abi, DiscriminantKind, HasDataLayout, LayoutOf, Size};
|
||||
use rustc_target::abi::{Abi, HasDataLayout, LayoutOf, Size, TagEncoding};
|
||||
use rustc_target::abi::{VariantIdx, Variants};
|
||||
|
||||
use super::{
|
||||
@ -587,7 +587,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
op: OpTy<'tcx, M::PointerTag>,
|
||||
) -> InterpResult<'tcx, (Scalar<M::PointerTag>, VariantIdx)> {
|
||||
trace!("read_discriminant_value {:#?}", op.layout);
|
||||
|
||||
// Get type and layout of the discriminant.
|
||||
let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
|
||||
trace!("discriminant type: {:?}", discr_layout.ty);
|
||||
@ -596,10 +595,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// This is not to be confused with its "variant index", which is just determining its position in the
|
||||
// declared list of variants -- they can differ with explicitly assigned discriminants.
|
||||
// We use "tag" to refer to how the discriminant is encoded in memory, which can be either
|
||||
// straight-forward (`DiscriminantKind::Tag`) or with a niche (`DiscriminantKind::Niche`).
|
||||
// Unfortunately, the rest of the compiler calls the latter "discriminant", too, which makes things
|
||||
// rather confusing.
|
||||
let (tag_scalar_layout, tag_kind, tag_index) = match op.layout.variants {
|
||||
// straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
|
||||
let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants {
|
||||
Variants::Single { index } => {
|
||||
let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
|
||||
Some(discr) => {
|
||||
@ -615,8 +612,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
};
|
||||
return Ok((discr, index));
|
||||
}
|
||||
Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => {
|
||||
(discr, discr_kind, discr_index)
|
||||
Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
|
||||
(tag, tag_encoding, tag_field)
|
||||
}
|
||||
};
|
||||
|
||||
@ -633,21 +630,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?;
|
||||
|
||||
// Read tag and sanity-check `tag_layout`.
|
||||
let tag_val = self.read_immediate(self.operand_field(op, tag_index)?)?;
|
||||
let tag_val = self.read_immediate(self.operand_field(op, tag_field)?)?;
|
||||
assert_eq!(tag_layout.size, tag_val.layout.size);
|
||||
assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
|
||||
let tag_val = tag_val.to_scalar()?;
|
||||
trace!("tag value: {:?}", tag_val);
|
||||
|
||||
// Figure out which discriminant and variant this corresponds to.
|
||||
Ok(match *tag_kind {
|
||||
DiscriminantKind::Tag => {
|
||||
Ok(match *tag_encoding {
|
||||
TagEncoding::Direct => {
|
||||
let tag_bits = self
|
||||
.force_bits(tag_val, tag_layout.size)
|
||||
.map_err(|_| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?;
|
||||
.map_err(|_| err_ub!(InvalidTag(tag_val.erase_tag())))?;
|
||||
// Cast bits from tag layout to discriminant layout.
|
||||
let discr_val_cast = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
|
||||
let discr_bits = discr_val_cast.assert_bits(discr_layout.size);
|
||||
let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
|
||||
let discr_bits = discr_val.assert_bits(discr_layout.size);
|
||||
// Convert discriminant to variant index, and catch invalid discriminants.
|
||||
let index = match op.layout.ty.kind {
|
||||
ty::Adt(adt, _) => {
|
||||
@ -661,11 +658,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
_ => bug!("tagged layout for non-adt non-generator"),
|
||||
}
|
||||
.ok_or_else(|| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?;
|
||||
.ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_tag())))?;
|
||||
// Return the cast value, and the index.
|
||||
(discr_val_cast, index.0)
|
||||
(discr_val, index.0)
|
||||
}
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => {
|
||||
// Compute the variant this niche value/"tag" corresponds to. With niche layout,
|
||||
// discriminant (encoded in niche/tag) and variant index are the same.
|
||||
let variants_start = niche_variants.start().as_u32();
|
||||
@ -677,7 +674,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
&& variants_start == variants_end
|
||||
&& !self.memory.ptr_may_be_null(ptr);
|
||||
if !ptr_valid {
|
||||
throw_ub!(InvalidDiscriminant(tag_val.erase_tag()))
|
||||
throw_ub!(InvalidTag(tag_val.erase_tag()))
|
||||
}
|
||||
dataful_variant
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use rustc_macros::HashStable;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_target::abi::{Abi, Align, DiscriminantKind, FieldsShape};
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
|
||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
|
||||
|
||||
use super::{
|
||||
@ -1045,7 +1045,8 @@ where
|
||||
MPlaceTy { mplace, layout }
|
||||
}
|
||||
|
||||
pub fn write_discriminant_index(
|
||||
/// Writes the discriminant of the given variant.
|
||||
pub fn write_discriminant(
|
||||
&mut self,
|
||||
variant_index: VariantIdx,
|
||||
dest: PlaceTy<'tcx, M::PointerTag>,
|
||||
@ -1061,9 +1062,9 @@ where
|
||||
assert_eq!(index, variant_index);
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Tag,
|
||||
discr: ref discr_layout,
|
||||
discr_index,
|
||||
tag_encoding: TagEncoding::Direct,
|
||||
tag: ref tag_layout,
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
// No need to validate that the discriminant here because the
|
||||
@ -1075,17 +1076,17 @@ where
|
||||
// raw discriminants for enums are isize or bigger during
|
||||
// their computation, but the in-memory tag is the smallest possible
|
||||
// representation
|
||||
let size = discr_layout.value.size(self);
|
||||
let discr_val = truncate(discr_val, size);
|
||||
let size = tag_layout.value.size(self);
|
||||
let tag_val = truncate(discr_val, size);
|
||||
|
||||
let discr_dest = self.place_field(dest, discr_index)?;
|
||||
self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?;
|
||||
let tag_dest = self.place_field(dest, tag_field)?;
|
||||
self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?;
|
||||
}
|
||||
Variants::Multiple {
|
||||
discr_kind:
|
||||
DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
discr: ref discr_layout,
|
||||
discr_index,
|
||||
tag_encoding:
|
||||
TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
|
||||
tag: ref tag_layout,
|
||||
tag_field,
|
||||
..
|
||||
} => {
|
||||
// No need to validate that the discriminant here because the
|
||||
@ -1098,19 +1099,19 @@ where
|
||||
.checked_sub(variants_start)
|
||||
.expect("overflow computing relative variant idx");
|
||||
// We need to use machine arithmetic when taking into account `niche_start`:
|
||||
// discr_val = variant_index_relative + niche_start_val
|
||||
let discr_layout = self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?;
|
||||
let niche_start_val = ImmTy::from_uint(niche_start, discr_layout);
|
||||
// tag_val = variant_index_relative + niche_start_val
|
||||
let tag_layout = self.layout_of(tag_layout.value.to_int_ty(*self.tcx))?;
|
||||
let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
|
||||
let variant_index_relative_val =
|
||||
ImmTy::from_uint(variant_index_relative, discr_layout);
|
||||
let discr_val = self.binary_op(
|
||||
ImmTy::from_uint(variant_index_relative, tag_layout);
|
||||
let tag_val = self.binary_op(
|
||||
mir::BinOp::Add,
|
||||
variant_index_relative_val,
|
||||
niche_start_val,
|
||||
)?;
|
||||
// Write result.
|
||||
let niche_dest = self.place_field(dest, discr_index)?;
|
||||
self.write_immediate(*discr_val, niche_dest)?;
|
||||
let niche_dest = self.place_field(dest, tag_field)?;
|
||||
self.write_immediate(*tag_val, niche_dest)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
SetDiscriminant { place, variant_index } => {
|
||||
let dest = self.eval_place(**place)?;
|
||||
self.write_discriminant_index(*variant_index, dest)?;
|
||||
self.write_discriminant(*variant_index, dest)?;
|
||||
}
|
||||
|
||||
// Mark locals as alive
|
||||
@ -179,7 +179,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Aggregate(ref kind, ref operands) => {
|
||||
let (dest, active_field_index) = match **kind {
|
||||
mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => {
|
||||
self.write_discriminant_index(variant_index, dest)?;
|
||||
self.write_discriminant(variant_index, dest)?;
|
||||
if adt_def.is_enum() {
|
||||
(self.place_downcast(dest, variant_index)?, active_field_index)
|
||||
} else {
|
||||
|
@ -208,8 +208,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize) -> PathElem {
|
||||
// First, check if we are projecting to a variant.
|
||||
match layout.variants {
|
||||
Variants::Multiple { discr_index, .. } => {
|
||||
if discr_index == field {
|
||||
Variants::Multiple { tag_field, .. } => {
|
||||
if tag_field == field {
|
||||
return match layout.ty.kind {
|
||||
ty::Adt(def, ..) if def.is_enum() => PathElem::EnumTag,
|
||||
ty::Generator(..) => PathElem::GeneratorTag,
|
||||
@ -697,8 +697,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
try_validation!(
|
||||
self.walk_value(op),
|
||||
self.path,
|
||||
err_ub!(InvalidDiscriminant(val)) =>
|
||||
{ "{}", val } expected { "a valid enum discriminant" },
|
||||
err_ub!(InvalidTag(val)) =>
|
||||
{ "{}", val } expected { "a valid enum tag" },
|
||||
err_unsup!(ReadPointerAsBytes) =>
|
||||
{ "a pointer" } expected { "plain (non-pointer) bytes" },
|
||||
);
|
||||
|
@ -27,9 +27,9 @@ use rustc_trait_selection::traits;
|
||||
|
||||
use crate::const_eval::error_to_const_error;
|
||||
use crate::interpret::{
|
||||
self, compile_time_machine, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy,
|
||||
Immediate, InternKind, InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy,
|
||||
Operand as InterpOperand, PlaceTy, Pointer, ScalarMaybeUninit, StackPopCleanup,
|
||||
self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, LocalState,
|
||||
LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer,
|
||||
ScalarMaybeUninit, StackPopCleanup,
|
||||
};
|
||||
use crate::transform::{MirPass, MirSource};
|
||||
|
||||
@ -702,11 +702,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
ScalarMaybeUninit::Scalar(l),
|
||||
ScalarMaybeUninit::Scalar(r),
|
||||
)) => l.is_bits() && r.is_bits(),
|
||||
interpret::Operand::Indirect(_) if mir_opt_level >= 2 => {
|
||||
let mplace = op.assert_mem_place(&self.ecx);
|
||||
intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,10 @@ impl<'a> FileSearch<'a> {
|
||||
make_target_lib_path(self.sysroot, self.triple)
|
||||
}
|
||||
|
||||
pub fn get_selfcontained_lib_path(&self) -> PathBuf {
|
||||
self.get_lib_path().join("self-contained")
|
||||
}
|
||||
|
||||
pub fn search<F>(&self, mut pick: F)
|
||||
where
|
||||
F: FnMut(&SearchPathFile, PathKind) -> FileMatch,
|
||||
@ -94,7 +98,7 @@ impl<'a> FileSearch<'a> {
|
||||
p.push(RUST_LIB_DIR);
|
||||
p.push(&self.triple);
|
||||
p.push("bin");
|
||||
vec![p]
|
||||
vec![p.clone(), p.join("self-contained")]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,6 +534,16 @@ declare_lint! {
|
||||
@feature_gate = sym::unsafe_block_in_unsafe_fn;
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub CENUM_IMPL_DROP_CAST,
|
||||
Warn,
|
||||
"a C-like enum implementing Drop is cast",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #73333 <https://github.com/rust-lang/rust/issues/73333>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass! {
|
||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||
/// that are used by other parts of the compiler.
|
||||
@ -607,6 +617,7 @@ declare_lint_pass! {
|
||||
ASM_SUB_REGISTER,
|
||||
UNSAFE_OP_IN_UNSAFE_FN,
|
||||
INCOMPLETE_INCLUDE,
|
||||
CENUM_IMPL_DROP_CAST,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -809,25 +809,30 @@ pub enum Variants {
|
||||
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
|
||||
Single { index: VariantIdx },
|
||||
|
||||
/// Enum-likes with more than one inhabited variant: for each case there is
|
||||
/// a struct, and they all have space reserved for the discriminant.
|
||||
/// For enums this is the sole field of the layout.
|
||||
/// Enum-likes with more than one inhabited variant: each variant comes with
|
||||
/// a *discriminant* (usually the same as the variant index but the user can
|
||||
/// assign explicit discriminant values). That discriminant is encoded
|
||||
/// as a *tag* on the machine. The layout of each variant is
|
||||
/// a struct, and they all have space reserved for the tag.
|
||||
/// For enums, the tag is the sole field of the layout.
|
||||
Multiple {
|
||||
discr: Scalar,
|
||||
discr_kind: DiscriminantKind,
|
||||
discr_index: usize,
|
||||
tag: Scalar,
|
||||
tag_encoding: TagEncoding,
|
||||
tag_field: usize,
|
||||
variants: IndexVec<VariantIdx, Layout>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub enum DiscriminantKind {
|
||||
/// Integer tag holding the discriminant value itself.
|
||||
Tag,
|
||||
pub enum TagEncoding {
|
||||
/// The tag directly stores the discriminant, but possibly with a smaller layout
|
||||
/// (so converting the tag to the discriminant can require sign extension).
|
||||
Direct,
|
||||
|
||||
/// Niche (values invalid for a type) encoding the discriminant:
|
||||
/// the variant `dataful_variant` contains a niche at an arbitrary
|
||||
/// offset (field `discr_index` of the enum), which for a variant with
|
||||
/// Discriminant and variant index coincide.
|
||||
/// The variant `dataful_variant` contains a niche at an arbitrary
|
||||
/// offset (field `tag_field` of the enum), which for a variant with
|
||||
/// discriminant `d` is set to
|
||||
/// `(d - niche_variants.start).wrapping_add(niche_start)`.
|
||||
///
|
||||
|
@ -6,6 +6,7 @@ pub fn target() -> TargetResult {
|
||||
base.max_atomic_width = Some(64);
|
||||
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
|
||||
base.stack_probes = true;
|
||||
base.static_position_independent_executables = true;
|
||||
|
||||
Ok(Target {
|
||||
llvm_target: "x86_64-unknown-linux-musl".to_string(),
|
||||
|
@ -678,7 +678,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
|
||||
|
||||
// prim -> prim
|
||||
(Int(CEnum), Int(_)) => Ok(CastKind::EnumCast),
|
||||
(Int(CEnum), Int(_)) => {
|
||||
self.cenum_impl_drop_lint(fcx);
|
||||
Ok(CastKind::EnumCast)
|
||||
}
|
||||
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
|
||||
|
||||
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
|
||||
@ -775,11 +778,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
// Coerce to a raw pointer so that we generate AddressOf in MIR.
|
||||
let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
|
||||
fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No)
|
||||
.unwrap_or_else(|_| bug!(
|
||||
.unwrap_or_else(|_| {
|
||||
bug!(
|
||||
"could not cast from reference to array to pointer to array ({:?} to {:?})",
|
||||
self.expr_ty,
|
||||
array_ptr_type,
|
||||
));
|
||||
)
|
||||
});
|
||||
|
||||
// this will report a type mismatch if needed
|
||||
fcx.demand_eqtype(self.span, ety, m_cast.ty);
|
||||
@ -809,6 +814,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
|
||||
if let ty::Adt(d, _) = self.expr_ty.kind {
|
||||
if d.has_dtor(fcx.tcx) {
|
||||
fcx.tcx.struct_span_lint_hir(
|
||||
lint::builtin::CENUM_IMPL_DROP_CAST,
|
||||
self.expr.hir_id,
|
||||
self.span,
|
||||
|err| {
|
||||
err.build(&format!(
|
||||
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
|
||||
self.expr_ty, self.cast_ty
|
||||
))
|
||||
.emit();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
@ -74,3 +74,8 @@ std_detect_dlsym_getauxval = []
|
||||
threads = 125
|
||||
# Maximum heap size
|
||||
heap_size = 0x8000000
|
||||
|
||||
[[bench]]
|
||||
name = "stdbenches"
|
||||
path = "benches/lib.rs"
|
||||
test = true
|
||||
|
@ -832,11 +832,7 @@ impl f32 {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn asinh(self) -> f32 {
|
||||
if self == Self::NEG_INFINITY {
|
||||
Self::NEG_INFINITY
|
||||
} else {
|
||||
(self + ((self * self) + 1.0).sqrt()).ln().copysign(self)
|
||||
}
|
||||
(self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self)
|
||||
}
|
||||
|
||||
/// Inverse hyperbolic cosine function.
|
||||
@ -1413,6 +1409,8 @@ mod tests {
|
||||
assert!((-0.0f32).asinh().is_sign_negative()); // issue 63271
|
||||
assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32);
|
||||
assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32);
|
||||
// regression test for the catastrophic cancellation fixed in 72486
|
||||
assert_approx_eq!((-3000.0f32).asinh(), -8.699514775987968673236893537700647f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -834,11 +834,7 @@ impl f64 {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn asinh(self) -> f64 {
|
||||
if self == Self::NEG_INFINITY {
|
||||
Self::NEG_INFINITY
|
||||
} else {
|
||||
(self + ((self * self) + 1.0).sqrt()).ln().copysign(self)
|
||||
}
|
||||
(self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self)
|
||||
}
|
||||
|
||||
/// Inverse hyperbolic cosine function.
|
||||
@ -1442,6 +1438,8 @@ mod tests {
|
||||
// issue 63271
|
||||
assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64);
|
||||
assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64);
|
||||
// regression test for the catastrophic cancellation fixed in 72486
|
||||
assert_approx_eq!((-67452098.07139316f64).asinh(), -18.72007542627454439398548429400083);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -242,7 +242,8 @@ pub trait PermissionsExt {
|
||||
/// let permissions = metadata.permissions();
|
||||
///
|
||||
/// println!("permissions: {:o}", permissions.mode());
|
||||
/// Ok(()) }
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "fs_ext", since = "1.1.0")]
|
||||
fn mode(&self) -> u32;
|
||||
@ -262,7 +263,8 @@ pub trait PermissionsExt {
|
||||
///
|
||||
/// permissions.set_mode(0o644); // Read/write for owner and read for others.
|
||||
/// assert_eq!(permissions.mode(), 0o644);
|
||||
/// Ok(()) }
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "fs_ext", since = "1.1.0")]
|
||||
fn set_mode(&mut self, mode: u32);
|
||||
|
@ -424,6 +424,12 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
|
||||
printf("Available features for this target:\n");
|
||||
for (auto &Feature : FeatTable)
|
||||
printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
|
||||
printf("\nRust-specific features:\n");
|
||||
printf(" %-*s - %s.\n",
|
||||
MaxFeatLen,
|
||||
"crt-static",
|
||||
"Enables libraries with C Run-time Libraries(CRT) to be statically linked"
|
||||
);
|
||||
printf("\n");
|
||||
|
||||
printf("Use +feature to enable a feature, or -feature to disable it.\n"
|
||||
|
44
src/test/codegen/issue-69101-bounds-check.rs
Normal file
44
src/test/codegen/issue-69101-bounds-check.rs
Normal file
@ -0,0 +1,44 @@
|
||||
// no-system-llvm
|
||||
// compile-flags: -O
|
||||
// ignore-debug: the debug assertions get in the way
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// Make sure no bounds checks are emitted in the loop when upfront slicing
|
||||
// ensures that the slices are big enough.
|
||||
// In particular, bounds checks were not always optimized out if the upfront
|
||||
// check was for a greater len than the loop requires.
|
||||
// (i.e. `already_sliced_no_bounds_check` was not always optimized even when
|
||||
// `already_sliced_no_bounds_check_exact` was)
|
||||
// CHECK-LABEL: @already_sliced_no_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
|
||||
// CHECK: slice_index_len_fail
|
||||
// CHECK-NOT: panic_bounds_check
|
||||
let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
|
||||
for i in 0..1024 {
|
||||
c[i] = a[i] ^ b[i];
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @already_sliced_no_bounds_check_exact
|
||||
#[no_mangle]
|
||||
pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
|
||||
// CHECK: slice_index_len_fail
|
||||
// CHECK-NOT: panic_bounds_check
|
||||
let _ = (&a[..1024], &b[..1024], &mut c[..1024]);
|
||||
for i in 0..1024 {
|
||||
c[i] = a[i] ^ b[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we're checking for the right thing: there can be a panic if the slice is too small.
|
||||
// CHECK-LABEL: @already_sliced_bounds_check
|
||||
#[no_mangle]
|
||||
pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
|
||||
// CHECK: slice_index_len_fail
|
||||
// CHECK: panic_bounds_check
|
||||
let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
|
||||
for i in 0..1024 {
|
||||
c[i] = a[i] ^ b[i];
|
||||
}
|
||||
}
|
@ -1,5 +1,10 @@
|
||||
// compile-flags: -O
|
||||
|
||||
// FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with
|
||||
// `let x = 42` but that doesn't work because const-prop doesn't support `Operand::Indirect`
|
||||
// and `InterpCx::eval_place()` always forces an allocation which creates the `Indirect`.
|
||||
// Fixing either of those will allow us to const-prop this away.
|
||||
|
||||
// EMIT_MIR_FOR_EACH_BIT_WIDTH
|
||||
// EMIT_MIR rustc.main.ConstProp.diff
|
||||
fn main() {
|
||||
|
@ -2,100 +2,93 @@
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:5:11: 5:11
|
||||
let _1: i32; // in scope 0 at $DIR/discriminant.rs:6:9: 6:10
|
||||
let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
let mut _3: std::option::Option<bool>; // in scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:10:11: 10:11
|
||||
let _1: i32; // in scope 0 at $DIR/discriminant.rs:11:9: 11:10
|
||||
let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
let mut _3: std::option::Option<bool>; // in scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
scope 1 {
|
||||
debug x => _1; // in scope 1 at $DIR/discriminant.rs:6:9: 6:10
|
||||
debug x => _1; // in scope 1 at $DIR/discriminant.rs:11:9: 11:10
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:6:9: 6:10
|
||||
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
- _3 = std::option::Option::<bool>::Some(const true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
+ _3 = const std::option::Option::<bool>::Some(true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10
|
||||
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
- _3 = std::option::Option::<bool>::Some(const true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
+ _3 = const std::option::Option::<bool>::Some(true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
// ty::Const
|
||||
- // + ty: bool
|
||||
+ // + ty: std::option::Option<bool>
|
||||
// + val: Value(Scalar(0x01))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/discriminant.rs:6:39: 6:43
|
||||
- // + span: $DIR/discriminant.rs:11:39: 11:43
|
||||
- // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
+ // + span: $DIR/discriminant.rs:6:34: 6:44
|
||||
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // + span: $DIR/discriminant.rs:11:34: 11:44
|
||||
+ // + literal: Const { ty: std::option::Option<bool>, val: Value(Scalar(0x01)) }
|
||||
+ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
+ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // ty::Const
|
||||
+ // + ty: isize
|
||||
+ // + val: Value(Scalar(0x00000001))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/discriminant.rs:6:21: 6:31
|
||||
+ // + span: $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // + literal: Const { ty: isize, val: Value(Scalar(0x00000001)) }
|
||||
+ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
+ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // ty::Const
|
||||
+ // + ty: isize
|
||||
+ // + val: Value(Scalar(0x00000001))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/discriminant.rs:6:21: 6:31
|
||||
+ // + span: $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // + literal: Const { ty: isize, val: Value(Scalar(0x00000001)) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_2 = const 10i32; // scope 0 at $DIR/discriminant.rs:6:59: 6:61
|
||||
_2 = const 10i32; // scope 0 at $DIR/discriminant.rs:11:59: 11:61
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x0000000a))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:6:59: 6:61
|
||||
// + span: $DIR/discriminant.rs:11:59: 11:61
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x0000000a)) }
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30
|
||||
+ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x01))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/discriminant.rs:6:26: 6:30
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_2 = const 42i32; // scope 0 at $DIR/discriminant.rs:6:47: 6:49
|
||||
_2 = const 42i32; // scope 0 at $DIR/discriminant.rs:11:47: 11:49
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x0000002a))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:6:47: 6:49
|
||||
// + span: $DIR/discriminant.rs:11:47: 11:49
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) }
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:6:13: 6:68
|
||||
_1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:11:13: 11:68
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:6:67: 6:68
|
||||
// + span: $DIR/discriminant.rs:11:67: 11:68
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
|
||||
StorageDead(_2); // scope 0 at $DIR/discriminant.rs:6:67: 6:68
|
||||
StorageDead(_3); // scope 0 at $DIR/discriminant.rs:6:68: 6:69
|
||||
_0 = const (); // scope 0 at $DIR/discriminant.rs:5:11: 7:2
|
||||
StorageDead(_2); // scope 0 at $DIR/discriminant.rs:11:67: 11:68
|
||||
StorageDead(_3); // scope 0 at $DIR/discriminant.rs:11:68: 11:69
|
||||
_0 = const (); // scope 0 at $DIR/discriminant.rs:10:11: 12:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:5:11: 7:2
|
||||
// + span: $DIR/discriminant.rs:10:11: 12:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_1); // scope 0 at $DIR/discriminant.rs:7:1: 7:2
|
||||
return; // scope 0 at $DIR/discriminant.rs:7:2: 7:2
|
||||
StorageDead(_1); // scope 0 at $DIR/discriminant.rs:12:1: 12:2
|
||||
return; // scope 0 at $DIR/discriminant.rs:12:2: 12:2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,100 +2,93 @@
|
||||
+ // MIR for `main` after ConstProp
|
||||
|
||||
fn main() -> () {
|
||||
let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:5:11: 5:11
|
||||
let _1: i32; // in scope 0 at $DIR/discriminant.rs:6:9: 6:10
|
||||
let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
let mut _3: std::option::Option<bool>; // in scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:10:11: 10:11
|
||||
let _1: i32; // in scope 0 at $DIR/discriminant.rs:11:9: 11:10
|
||||
let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
let mut _3: std::option::Option<bool>; // in scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
scope 1 {
|
||||
debug x => _1; // in scope 1 at $DIR/discriminant.rs:6:9: 6:10
|
||||
debug x => _1; // in scope 1 at $DIR/discriminant.rs:11:9: 11:10
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:6:9: 6:10
|
||||
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
- _3 = std::option::Option::<bool>::Some(const true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
+ _3 = const std::option::Option::<bool>::Some(true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44
|
||||
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10
|
||||
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
- _3 = std::option::Option::<bool>::Some(const true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
+ _3 = const std::option::Option::<bool>::Some(true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
|
||||
// ty::Const
|
||||
- // + ty: bool
|
||||
+ // + ty: std::option::Option<bool>
|
||||
// + val: Value(Scalar(0x01))
|
||||
// mir::Constant
|
||||
- // + span: $DIR/discriminant.rs:6:39: 6:43
|
||||
- // + span: $DIR/discriminant.rs:11:39: 11:43
|
||||
- // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
+ // + span: $DIR/discriminant.rs:6:34: 6:44
|
||||
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // + span: $DIR/discriminant.rs:11:34: 11:44
|
||||
+ // + literal: Const { ty: std::option::Option<bool>, val: Value(Scalar(0x01)) }
|
||||
+ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
+ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // ty::Const
|
||||
+ // + ty: isize
|
||||
+ // + val: Value(Scalar(0x0000000000000001))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/discriminant.rs:6:21: 6:31
|
||||
+ // + span: $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000001)) }
|
||||
+ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31
|
||||
+ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // ty::Const
|
||||
+ // + ty: isize
|
||||
+ // + val: Value(Scalar(0x0000000000000001))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/discriminant.rs:6:21: 6:31
|
||||
+ // + span: $DIR/discriminant.rs:11:21: 11:31
|
||||
+ // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000001)) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_2 = const 10i32; // scope 0 at $DIR/discriminant.rs:6:59: 6:61
|
||||
_2 = const 10i32; // scope 0 at $DIR/discriminant.rs:11:59: 11:61
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x0000000a))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:6:59: 6:61
|
||||
// + span: $DIR/discriminant.rs:11:59: 11:61
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x0000000a)) }
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30
|
||||
+ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30
|
||||
+ // ty::Const
|
||||
+ // + ty: bool
|
||||
+ // + val: Value(Scalar(0x01))
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/discriminant.rs:6:26: 6:30
|
||||
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
|
||||
switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_2 = const 42i32; // scope 0 at $DIR/discriminant.rs:6:47: 6:49
|
||||
_2 = const 42i32; // scope 0 at $DIR/discriminant.rs:11:47: 11:49
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x0000002a))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:6:47: 6:49
|
||||
// + span: $DIR/discriminant.rs:11:47: 11:49
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) }
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64
|
||||
goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64
|
||||
}
|
||||
|
||||
bb4: {
|
||||
_1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:6:13: 6:68
|
||||
_1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:11:13: 11:68
|
||||
// ty::Const
|
||||
// + ty: i32
|
||||
// + val: Value(Scalar(0x00000000))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:6:67: 6:68
|
||||
// + span: $DIR/discriminant.rs:11:67: 11:68
|
||||
// + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
|
||||
StorageDead(_2); // scope 0 at $DIR/discriminant.rs:6:67: 6:68
|
||||
StorageDead(_3); // scope 0 at $DIR/discriminant.rs:6:68: 6:69
|
||||
_0 = const (); // scope 0 at $DIR/discriminant.rs:5:11: 7:2
|
||||
StorageDead(_2); // scope 0 at $DIR/discriminant.rs:11:67: 11:68
|
||||
StorageDead(_3); // scope 0 at $DIR/discriminant.rs:11:68: 11:69
|
||||
_0 = const (); // scope 0 at $DIR/discriminant.rs:10:11: 12:2
|
||||
// ty::Const
|
||||
// + ty: ()
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/discriminant.rs:5:11: 7:2
|
||||
// + span: $DIR/discriminant.rs:10:11: 12:2
|
||||
// + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
|
||||
StorageDead(_1); // scope 0 at $DIR/discriminant.rs:7:1: 7:2
|
||||
return; // scope 0 at $DIR/discriminant.rs:7:2: 7:2
|
||||
StorageDead(_1); // scope 0 at $DIR/discriminant.rs:12:1: 12:2
|
||||
return; // scope 0 at $DIR/discriminant.rs:12:2: 12:2
|
||||
}
|
||||
}
|
||||
|
||||
|
15
src/test/run-make/static-pie/Makefile
Normal file
15
src/test/run-make/static-pie/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
# only-x86_64-unknown-linux-musl
|
||||
|
||||
# How to manually run this
|
||||
# $ ./x.py test --target x86_64-unknown-linux-musl src/test/run-make/static-pie
|
||||
|
||||
all:
|
||||
$(RUSTC) --target $(TARGET) -C target-feature=+crt-static test-aslr.rs
|
||||
# Check that no dynamic interpreter is set
|
||||
! readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) INTERP
|
||||
# Check that we have a dynamic executable
|
||||
readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) DYNAMIC
|
||||
# Check for address space layout randomization
|
||||
$(call RUN,test-aslr) --test-aslr
|
43
src/test/run-make/static-pie/test-aslr.rs
Normal file
43
src/test/run-make/static-pie/test-aslr.rs
Normal file
@ -0,0 +1,43 @@
|
||||
const NUM_RUNS: usize = 10;
|
||||
|
||||
fn run_self(exe: &str) -> usize {
|
||||
use std::process::Command;
|
||||
let mut set = std::collections::HashSet::new();
|
||||
|
||||
let mut cmd = Command::new(exe);
|
||||
cmd.arg("--report");
|
||||
(0..NUM_RUNS).for_each(|_| {
|
||||
set.insert(cmd.output().expect("failed to execute process").stdout);
|
||||
});
|
||||
set.len()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = std::env::args();
|
||||
let arg0 = args.next().unwrap();
|
||||
match args.next() {
|
||||
Some(s) if s.eq("--report") => {
|
||||
println!("main = {:#?}", &main as *const _);
|
||||
}
|
||||
Some(s) if s.eq("--test-no-aslr") => {
|
||||
let cnt = run_self(&arg0);
|
||||
if cnt != 1 {
|
||||
eprintln!("FAIL: {} most likely ASLR", arg0);
|
||||
std::process::exit(1);
|
||||
}
|
||||
println!("PASS: {} does no ASLR", arg0);
|
||||
}
|
||||
Some(s) if s.eq("--test-aslr") => {
|
||||
let cnt = run_self(&arg0);
|
||||
if cnt != NUM_RUNS {
|
||||
eprintln!("FAIL: {} most likely no ASLR", arg0);
|
||||
std::process::exit(1);
|
||||
}
|
||||
println!("PASS: {} does ASLR", arg0);
|
||||
}
|
||||
Some(_) | None => {
|
||||
println!("Usage: {} --test-no-aslr | --test-aslr", arg0);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
18
src/test/ui/cenum_impl_drop_cast.rs
Normal file
18
src/test/ui/cenum_impl_drop_cast.rs
Normal file
@ -0,0 +1,18 @@
|
||||
#![deny(cenum_impl_drop_cast)]
|
||||
|
||||
enum E {
|
||||
A = 0,
|
||||
}
|
||||
|
||||
impl Drop for E {
|
||||
fn drop(&mut self) {
|
||||
println!("Drop");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let e = E::A;
|
||||
let i = e as u32;
|
||||
//~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop`
|
||||
//~| WARN this was previously accepted
|
||||
}
|
16
src/test/ui/cenum_impl_drop_cast.stderr
Normal file
16
src/test/ui/cenum_impl_drop_cast.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: cannot cast enum `E` into integer `u32` because it implements `Drop`
|
||||
--> $DIR/cenum_impl_drop_cast.rs:15:13
|
||||
|
|
||||
LL | let i = e as u32;
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/cenum_impl_drop_cast.rs:1:9
|
||||
|
|
||||
LL | #![deny(cenum_impl_drop_cast)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #73333 <https://github.com/rust-lang/rust/issues/73333>
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -5,7 +5,7 @@ LL | / static FOO: (&Foo, &Bar) = unsafe {(
|
||||
LL | | Union { u8: &BAR }.foo,
|
||||
LL | | Union { u8: &BAR }.bar,
|
||||
LL | | )};
|
||||
| |___^ type validation failed: encountered 0x05 at .1.<deref>, but expected a valid enum discriminant
|
||||
| |___^ type validation failed: encountered 0x05 at .1.<deref>, but expected a valid enum tag
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc 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/ub-enum.rs:24:1
|
||||
|
|
||||
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001, but expected a valid enum discriminant
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001, but expected a valid enum tag
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc 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-enum.rs:42:1
|
||||
|
|
||||
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000, but expected a valid enum discriminant
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000, but expected a valid enum tag
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
|
@ -10,15 +10,15 @@ error: layout_of(E) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
discr: Scalar {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
discr_kind: Tag,
|
||||
discr_index: 0,
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
@ -202,15 +202,15 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
discr: Scalar {
|
||||
tag: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=1,
|
||||
},
|
||||
discr_kind: Tag,
|
||||
discr_index: 0,
|
||||
tag_encoding: Direct,
|
||||
tag_field: 0,
|
||||
variants: [
|
||||
Layout {
|
||||
fields: Arbitrary {
|
||||
|
6
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs
Normal file
6
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![feature(non_ascii_idents)]
|
||||
|
||||
extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг`
|
||||
//~| ERROR can't find crate for `ьаг`
|
||||
|
||||
fn main() {}
|
15
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr
Normal file
15
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: cannot load a crate with a non-ascii name `ьаг`
|
||||
--> $DIR/crate_name_nonascii_forbidden-1.rs:3:1
|
||||
|
|
||||
LL | extern crate ьаг;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0463]: can't find crate for `ьаг`
|
||||
--> $DIR/crate_name_nonascii_forbidden-1.rs:3:1
|
||||
|
|
||||
LL | extern crate ьаг;
|
||||
| ^^^^^^^^^^^^^^^^^ can't find crate
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0463`.
|
9
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs
Normal file
9
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// compile-flags:--extern му_сгате
|
||||
// edition:2018
|
||||
#![feature(non_ascii_idents)]
|
||||
|
||||
use му_сгате::baz; //~ ERROR cannot load a crate with a non-ascii name `му_сгате`
|
||||
//~| can't find crate for `му_сгате`
|
||||
|
||||
|
||||
fn main() {}
|
15
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr
Normal file
15
src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: cannot load a crate with a non-ascii name `му_сгате`
|
||||
--> $DIR/crate_name_nonascii_forbidden-2.rs:5:5
|
||||
|
|
||||
LL | use му_сгате::baz;
|
||||
| ^^^^^^^^
|
||||
|
||||
error[E0463]: can't find crate for `му_сгате`
|
||||
--> $DIR/crate_name_nonascii_forbidden-2.rs:5:5
|
||||
|
|
||||
LL | use му_сгате::baz;
|
||||
| ^^^^^^^^ can't find crate
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0463`.
|
Loading…
Reference in New Issue
Block a user