mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 06:51:58 +00:00
Auto merge of #68248 - JohnTitor:rollup-x0kml5f, r=JohnTitor
Rollup of 12 pull requests Successful merges: - #67784 (Reset Formatter flags on exit from pad_integral) - #67914 (Don't run const propagation on items with inconsistent bounds) - #68141 (use winapi for non-stdlib Windows bindings) - #68211 (Add failing example for E0170 explanation) - #68219 (Untangle ZST validation from integer validation and generalize it to all zsts) - #68222 (Update the wasi-libc bundled with libstd) - #68226 (Avoid calling tcx.hir().get() on CRATE_HIR_ID) - #68227 (Update to a version of cmake with windows arm64 support) - #68229 (Update iovec to a version with no winapi dependency) - #68230 (Update libssh2-sys to a version that can build for aarch64-pc-windows…) - #68231 (Better support for cross compilation on Windows.) - #68233 (Update compiler_builtins with changes to fix 128 bit integer remainder for aarch64 windows.) Failed merges: r? @ghost
This commit is contained in:
commit
6d0bb91bcb
23
Cargo.lock
23
Cargo.lock
@ -207,6 +207,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"time",
|
||||
"toml",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -520,9 +521,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.38"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96210eec534fc3fbfc0452a63769424eaa80205fda6cea98e5b61cb3d97bcec8"
|
||||
checksum = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
@ -576,9 +577,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.22"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6f083abf9bb9005a27d2da62706f661245278cb7096da37ab27410eaf60f2c1"
|
||||
checksum = "b9975aefa63997ef75ca9cf013ff1bb81487aaa0b622c21053afd3b92979a7af"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
@ -1587,12 +1588,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.2"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
|
||||
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1812,9 +1812,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libssh2-sys"
|
||||
version = "0.2.11"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
|
||||
checksum = "36aa6e813339d3a063292b77091dfbbb6152ff9006a459895fa5bebed7d34f10"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@ -3497,6 +3497,7 @@ dependencies = [
|
||||
"serialize",
|
||||
"smallvec 1.0.0",
|
||||
"stable_deref_trait",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3524,6 +3525,7 @@ dependencies = [
|
||||
"rustc_target",
|
||||
"serialize",
|
||||
"syntax",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3543,6 +3545,7 @@ dependencies = [
|
||||
"term_size",
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3654,6 +3657,7 @@ dependencies = [
|
||||
"smallvec 1.0.0",
|
||||
"syntax",
|
||||
"tempfile",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3723,6 +3727,7 @@ dependencies = [
|
||||
"smallvec 1.0.0",
|
||||
"stable_deref_trait",
|
||||
"syntax",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -49,5 +49,9 @@ lazy_static = "1.3.0"
|
||||
time = "0.1"
|
||||
ignore = "0.4.10"
|
||||
|
||||
[target.'cfg(windows)'.dependencies.winapi]
|
||||
version = "0.3"
|
||||
features = ["fileapi", "ioapiset", "jobapi2", "handleapi", "winioctl"]
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "0.5"
|
||||
|
@ -35,84 +35,16 @@ use std::io;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
type HANDLE = *mut u8;
|
||||
type BOOL = i32;
|
||||
type DWORD = u32;
|
||||
type LPHANDLE = *mut HANDLE;
|
||||
type LPVOID = *mut u8;
|
||||
type JOBOBJECTINFOCLASS = i32;
|
||||
type SIZE_T = usize;
|
||||
type LARGE_INTEGER = i64;
|
||||
type UINT = u32;
|
||||
type ULONG_PTR = usize;
|
||||
type ULONGLONG = u64;
|
||||
|
||||
const FALSE: BOOL = 0;
|
||||
const DUPLICATE_SAME_ACCESS: DWORD = 0x2;
|
||||
const PROCESS_DUP_HANDLE: DWORD = 0x40;
|
||||
const JobObjectExtendedLimitInformation: JOBOBJECTINFOCLASS = 9;
|
||||
const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: DWORD = 0x2000;
|
||||
const JOB_OBJECT_LIMIT_PRIORITY_CLASS: DWORD = 0x00000020;
|
||||
const SEM_FAILCRITICALERRORS: UINT = 0x0001;
|
||||
const SEM_NOGPFAULTERRORBOX: UINT = 0x0002;
|
||||
const BELOW_NORMAL_PRIORITY_CLASS: DWORD = 0x00004000;
|
||||
|
||||
extern "system" {
|
||||
fn CreateJobObjectW(lpJobAttributes: *mut u8, lpName: *const u8) -> HANDLE;
|
||||
fn CloseHandle(hObject: HANDLE) -> BOOL;
|
||||
fn GetCurrentProcess() -> HANDLE;
|
||||
fn OpenProcess(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE;
|
||||
fn DuplicateHandle(
|
||||
hSourceProcessHandle: HANDLE,
|
||||
hSourceHandle: HANDLE,
|
||||
hTargetProcessHandle: HANDLE,
|
||||
lpTargetHandle: LPHANDLE,
|
||||
dwDesiredAccess: DWORD,
|
||||
bInheritHandle: BOOL,
|
||||
dwOptions: DWORD,
|
||||
) -> BOOL;
|
||||
fn AssignProcessToJobObject(hJob: HANDLE, hProcess: HANDLE) -> BOOL;
|
||||
fn SetInformationJobObject(
|
||||
hJob: HANDLE,
|
||||
JobObjectInformationClass: JOBOBJECTINFOCLASS,
|
||||
lpJobObjectInformation: LPVOID,
|
||||
cbJobObjectInformationLength: DWORD,
|
||||
) -> BOOL;
|
||||
fn SetErrorMode(mode: UINT) -> UINT;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
|
||||
BasicLimitInformation: JOBOBJECT_BASIC_LIMIT_INFORMATION,
|
||||
IoInfo: IO_COUNTERS,
|
||||
ProcessMemoryLimit: SIZE_T,
|
||||
JobMemoryLimit: SIZE_T,
|
||||
PeakProcessMemoryUsed: SIZE_T,
|
||||
PeakJobMemoryUsed: SIZE_T,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct IO_COUNTERS {
|
||||
ReadOperationCount: ULONGLONG,
|
||||
WriteOperationCount: ULONGLONG,
|
||||
OtherOperationCount: ULONGLONG,
|
||||
ReadTransferCount: ULONGLONG,
|
||||
WriteTransferCount: ULONGLONG,
|
||||
OtherTransferCount: ULONGLONG,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct JOBOBJECT_BASIC_LIMIT_INFORMATION {
|
||||
PerProcessUserTimeLimit: LARGE_INTEGER,
|
||||
PerJobUserTimeLimit: LARGE_INTEGER,
|
||||
LimitFlags: DWORD,
|
||||
MinimumWorkingsetSize: SIZE_T,
|
||||
MaximumWorkingsetSize: SIZE_T,
|
||||
ActiveProcessLimit: DWORD,
|
||||
Affinity: ULONG_PTR,
|
||||
PriorityClass: DWORD,
|
||||
SchedulingClass: DWORD,
|
||||
}
|
||||
use winapi::shared::minwindef::{DWORD, FALSE, LPVOID};
|
||||
use winapi::um::errhandlingapi::SetErrorMode;
|
||||
use winapi::um::handleapi::{CloseHandle, DuplicateHandle};
|
||||
use winapi::um::jobapi2::{AssignProcessToJobObject, CreateJobObjectW, SetInformationJobObject};
|
||||
use winapi::um::processthreadsapi::{GetCurrentProcess, OpenProcess};
|
||||
use winapi::um::winbase::{BELOW_NORMAL_PRIORITY_CLASS, SEM_NOGPFAULTERRORBOX};
|
||||
use winapi::um::winnt::{
|
||||
JobObjectExtendedLimitInformation, DUPLICATE_SAME_ACCESS, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
|
||||
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
|
||||
};
|
||||
|
||||
pub unsafe fn setup(build: &mut Build) {
|
||||
// Enable the Windows Error Reporting dialog which msys disables,
|
||||
|
@ -230,6 +230,8 @@ impl Step for Llvm {
|
||||
cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
|
||||
} else if target.contains("freebsd") {
|
||||
cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
|
||||
} else if target.contains("windows") {
|
||||
cfg.define("CMAKE_SYSTEM_NAME", "Windows");
|
||||
}
|
||||
|
||||
cfg.define("LLVM_NATIVE_BUILD", builder.llvm_out(builder.config.build).join("build"));
|
||||
|
@ -123,37 +123,24 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
||||
// what can be found here:
|
||||
//
|
||||
// http://www.flexhex.com/docs/articles/hard-links.phtml
|
||||
//
|
||||
// Copied from std
|
||||
#[cfg(windows)]
|
||||
#[allow(nonstandard_style)]
|
||||
fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
|
||||
use std::ffi::OsStr;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::ptr;
|
||||
|
||||
const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
|
||||
const GENERIC_WRITE: DWORD = 0x40000000;
|
||||
const OPEN_EXISTING: DWORD = 3;
|
||||
const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
|
||||
const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
|
||||
const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
|
||||
const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003;
|
||||
const FILE_SHARE_DELETE: DWORD = 0x4;
|
||||
const FILE_SHARE_READ: DWORD = 0x1;
|
||||
const FILE_SHARE_WRITE: DWORD = 0x2;
|
||||
|
||||
type BOOL = i32;
|
||||
type DWORD = u32;
|
||||
type HANDLE = *mut u8;
|
||||
type LPCWSTR = *const u16;
|
||||
type LPDWORD = *mut DWORD;
|
||||
type LPOVERLAPPED = *mut u8;
|
||||
type LPSECURITY_ATTRIBUTES = *mut u8;
|
||||
type LPVOID = *mut u8;
|
||||
type WCHAR = u16;
|
||||
type WORD = u16;
|
||||
use winapi::shared::minwindef::{DWORD, WORD};
|
||||
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
|
||||
use winapi::um::handleapi::CloseHandle;
|
||||
use winapi::um::ioapiset::DeviceIoControl;
|
||||
use winapi::um::winbase::{FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT};
|
||||
use winapi::um::winioctl::FSCTL_SET_REPARSE_POINT;
|
||||
use winapi::um::winnt::{
|
||||
FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_WRITE,
|
||||
IO_REPARSE_TAG_MOUNT_POINT, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, WCHAR,
|
||||
};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[repr(C)]
|
||||
struct REPARSE_MOUNTPOINT_DATA_BUFFER {
|
||||
ReparseTag: DWORD,
|
||||
@ -165,29 +152,6 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
||||
ReparseTarget: WCHAR,
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
fn CreateFileW(
|
||||
lpFileName: LPCWSTR,
|
||||
dwDesiredAccess: DWORD,
|
||||
dwShareMode: DWORD,
|
||||
lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
|
||||
dwCreationDisposition: DWORD,
|
||||
dwFlagsAndAttributes: DWORD,
|
||||
hTemplateFile: HANDLE,
|
||||
) -> HANDLE;
|
||||
fn DeviceIoControl(
|
||||
hDevice: HANDLE,
|
||||
dwIoControlCode: DWORD,
|
||||
lpInBuffer: LPVOID,
|
||||
nInBufferSize: DWORD,
|
||||
lpOutBuffer: LPVOID,
|
||||
nOutBufferSize: DWORD,
|
||||
lpBytesReturned: LPDWORD,
|
||||
lpOverlapped: LPOVERLAPPED,
|
||||
) -> BOOL;
|
||||
fn CloseHandle(hObject: HANDLE) -> BOOL;
|
||||
}
|
||||
|
||||
fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
|
||||
Ok(s.as_ref().encode_wide().chain(Some(0)).collect())
|
||||
}
|
||||
@ -212,7 +176,7 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
|
||||
ptr::null_mut(),
|
||||
);
|
||||
|
||||
let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize];
|
||||
let db = data.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
|
||||
let buf = &mut (*db).ReparseTarget as *mut u16;
|
||||
let mut i = 0;
|
||||
|
@ -12,7 +12,7 @@ export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
|
||||
git clone https://github.com/CraneStation/wasi-libc
|
||||
|
||||
cd wasi-libc
|
||||
git reset --hard f645f498dfbbbc00a7a97874d33082d3605c3f21
|
||||
git reset --hard 1fad33890a5e299027ce0eab7b6ad5260585e347
|
||||
make -j$(nproc) INSTALL_DIR=/wasm32-wasi install
|
||||
|
||||
cd ..
|
||||
|
@ -1244,12 +1244,15 @@ impl<'a> Formatter<'a> {
|
||||
// The sign and prefix goes before the padding if the fill character
|
||||
// is zero
|
||||
Some(min) if self.sign_aware_zero_pad() => {
|
||||
self.fill = '0';
|
||||
self.align = rt::v1::Alignment::Right;
|
||||
let old_fill = crate::mem::replace(&mut self.fill, '0');
|
||||
let old_align = crate::mem::replace(&mut self.align, rt::v1::Alignment::Right);
|
||||
write_prefix(self, sign, prefix)?;
|
||||
let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;
|
||||
self.buf.write_str(buf)?;
|
||||
post_padding.write(self.buf)
|
||||
post_padding.write(self.buf)?;
|
||||
self.fill = old_fill;
|
||||
self.align = old_align;
|
||||
Ok(())
|
||||
}
|
||||
// Otherwise, the sign and prefix goes after the padding
|
||||
Some(min) => {
|
||||
|
@ -28,3 +28,18 @@ fn test_estimated_capacity() {
|
||||
assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
|
||||
assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pad_integral_resets() {
|
||||
struct Bar;
|
||||
|
||||
impl core::fmt::Display for Bar {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
"1".fmt(f)?;
|
||||
f.pad_integral(true, "", "5")?;
|
||||
"1".fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(format!("{:<03}", Bar), "1 0051 ");
|
||||
}
|
||||
|
@ -1219,7 +1219,7 @@ pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir
|
||||
let res = hir_id == scope;
|
||||
trace!(
|
||||
"may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
|
||||
tcx.hir().get(hir_id),
|
||||
tcx.hir().find(hir_id),
|
||||
tcx.hir().get(opaque_hir_id),
|
||||
res
|
||||
);
|
||||
|
@ -34,7 +34,6 @@
|
||||
#![feature(const_transmute)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(drain_filter)]
|
||||
#![cfg_attr(windows, feature(libc))]
|
||||
#![feature(never_type)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(overlapping_marker_traits)]
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
|
||||
use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
|
||||
use crate::session::config::OptLevel;
|
||||
use crate::traits::TraitQueryMode;
|
||||
use crate::ty::print::obsolete::DefPathBasedNames;
|
||||
use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
|
||||
use rustc_data_structures::base_n;
|
||||
@ -167,7 +168,9 @@ impl<'tcx> MonoItem<'tcx> {
|
||||
MonoItem::GlobalAsm(..) => return true,
|
||||
};
|
||||
|
||||
tcx.substitute_normalize_and_test_predicates((def_id, &substs))
|
||||
// We shouldn't encounter any overflow here, so we use TraitQueryMode::Standard\
|
||||
// to report an error if overflow somehow occurs.
|
||||
tcx.substitute_normalize_and_test_predicates((def_id, &substs, TraitQueryMode::Standard))
|
||||
}
|
||||
|
||||
pub fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String {
|
||||
|
@ -1148,11 +1148,11 @@ rustc_queries! {
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
|
||||
query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>, traits::TraitQueryMode)) -> bool {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
"testing substituted normalized predicates:`{}`",
|
||||
tcx.def_path_str(key.0)
|
||||
"testing substituted normalized predicates in mode {:?}:`{}`",
|
||||
key.2, tcx.def_path_str(key.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ use super::CodeSelectionError;
|
||||
use super::{ConstEvalFailure, Unimplemented};
|
||||
use super::{FulfillmentError, FulfillmentErrorCode};
|
||||
use super::{ObligationCause, PredicateObligation};
|
||||
use crate::traits::TraitQueryMode;
|
||||
|
||||
impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
|
||||
type Predicate = ty::Predicate<'tcx>;
|
||||
@ -62,6 +63,9 @@ pub struct FulfillmentContext<'tcx> {
|
||||
// a snapshot (they don't *straddle* a snapshot, so there
|
||||
// is no trouble there).
|
||||
usable_in_snapshot: bool,
|
||||
|
||||
// The `TraitQueryMode` used when constructing a `SelectionContext`
|
||||
query_mode: TraitQueryMode,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -75,12 +79,26 @@ pub struct PendingPredicateObligation<'tcx> {
|
||||
static_assert_size!(PendingPredicateObligation<'_>, 136);
|
||||
|
||||
impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||
/// Creates a new fulfillment context.
|
||||
/// Creates a new fulfillment context with `TraitQueryMode::Standard`
|
||||
/// You almost always want to use this instead of `with_query_mode`
|
||||
pub fn new() -> FulfillmentContext<'tcx> {
|
||||
FulfillmentContext {
|
||||
predicates: ObligationForest::new(),
|
||||
register_region_obligations: true,
|
||||
usable_in_snapshot: false,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new fulfillment context with the specified query mode.
|
||||
/// This should only be used when you want to ignore overflow,
|
||||
/// rather than reporting it as an error.
|
||||
pub fn with_query_mode(query_mode: TraitQueryMode) -> FulfillmentContext<'tcx> {
|
||||
FulfillmentContext {
|
||||
predicates: ObligationForest::new(),
|
||||
register_region_obligations: true,
|
||||
usable_in_snapshot: false,
|
||||
query_mode,
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,6 +107,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||
predicates: ObligationForest::new(),
|
||||
register_region_obligations: true,
|
||||
usable_in_snapshot: true,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,6 +116,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||
predicates: ObligationForest::new(),
|
||||
register_region_obligations: false,
|
||||
usable_in_snapshot: false,
|
||||
query_mode: TraitQueryMode::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,7 +237,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||
let mut selcx = SelectionContext::new(infcx);
|
||||
let mut selcx = SelectionContext::with_query_mode(infcx, self.query_mode);
|
||||
self.select(&mut selcx)
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ pub enum IntercrateMode {
|
||||
}
|
||||
|
||||
/// The mode that trait queries run in.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, HashStable)]
|
||||
pub enum TraitQueryMode {
|
||||
// Standard/un-canonicalized queries get accurate
|
||||
// spans etc. passed in and hence can do reasonable
|
||||
@ -1017,13 +1017,14 @@ where
|
||||
fn normalize_and_test_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
predicates: Vec<ty::Predicate<'tcx>>,
|
||||
mode: TraitQueryMode,
|
||||
) -> bool {
|
||||
debug!("normalize_and_test_predicates(predicates={:?})", predicates);
|
||||
debug!("normalize_and_test_predicates(predicates={:?}, mode={:?})", predicates, mode);
|
||||
|
||||
let result = tcx.infer_ctxt().enter(|infcx| {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let mut selcx = SelectionContext::new(&infcx);
|
||||
let mut fulfill_cx = FulfillmentContext::new();
|
||||
let mut selcx = SelectionContext::with_query_mode(&infcx, mode);
|
||||
let mut fulfill_cx = FulfillmentContext::with_query_mode(mode);
|
||||
let cause = ObligationCause::dummy();
|
||||
let Normalized { value: predicates, obligations } =
|
||||
normalize(&mut selcx, param_env, cause.clone(), &predicates);
|
||||
@ -1043,12 +1044,12 @@ fn normalize_and_test_predicates<'tcx>(
|
||||
|
||||
fn substitute_normalize_and_test_predicates<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: (DefId, SubstsRef<'tcx>),
|
||||
key: (DefId, SubstsRef<'tcx>, TraitQueryMode),
|
||||
) -> bool {
|
||||
debug!("substitute_normalize_and_test_predicates(key={:?})", key);
|
||||
|
||||
let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
|
||||
let result = normalize_and_test_predicates(tcx, predicates);
|
||||
let result = normalize_and_test_predicates(tcx, predicates, key.2);
|
||||
|
||||
debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
|
||||
result
|
||||
@ -1101,7 +1102,10 @@ fn vtable_methods<'tcx>(
|
||||
// Note that this method could then never be called, so we
|
||||
// do not want to try and codegen it, in that case (see #23435).
|
||||
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
|
||||
if !normalize_and_test_predicates(tcx, predicates.predicates) {
|
||||
// We don't expect overflow here, so report an error if it somehow ends
|
||||
// up happening.
|
||||
if !normalize_and_test_predicates(tcx, predicates.predicates, TraitQueryMode::Standard)
|
||||
{
|
||||
debug!("vtable_methods: predicates do not hold");
|
||||
return None;
|
||||
}
|
||||
|
@ -125,6 +125,15 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for (DefId, SubstsRef<'tcx>, traits::TraitQueryMode) {
|
||||
fn query_crate(&self) -> CrateNum {
|
||||
self.0.krate
|
||||
}
|
||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
||||
self.0.default_span(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
|
||||
fn query_crate(&self) -> CrateNum {
|
||||
self.1.def_id().krate
|
||||
|
@ -31,3 +31,6 @@ measureme = "0.7.1"
|
||||
[dependencies.parking_lot]
|
||||
version = "0.9"
|
||||
features = ["nightly"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["fileapi", "psapi"] }
|
||||
|
@ -87,39 +87,11 @@ cfg_if! {
|
||||
} else if #[cfg(windows)] {
|
||||
use std::mem;
|
||||
use std::os::windows::prelude::*;
|
||||
use std::os::windows::raw::HANDLE;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::os::raw::{c_ulong, c_int};
|
||||
|
||||
type DWORD = c_ulong;
|
||||
type BOOL = c_int;
|
||||
type ULONG_PTR = usize;
|
||||
|
||||
type LPOVERLAPPED = *mut OVERLAPPED;
|
||||
const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002;
|
||||
const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001;
|
||||
|
||||
const FILE_SHARE_DELETE: DWORD = 0x4;
|
||||
const FILE_SHARE_READ: DWORD = 0x1;
|
||||
const FILE_SHARE_WRITE: DWORD = 0x2;
|
||||
|
||||
#[repr(C)]
|
||||
struct OVERLAPPED {
|
||||
Internal: ULONG_PTR,
|
||||
InternalHigh: ULONG_PTR,
|
||||
Offset: DWORD,
|
||||
OffsetHigh: DWORD,
|
||||
hEvent: HANDLE,
|
||||
}
|
||||
|
||||
extern "system" {
|
||||
fn LockFileEx(hFile: HANDLE,
|
||||
dwFlags: DWORD,
|
||||
dwReserved: DWORD,
|
||||
nNumberOfBytesToLockLow: DWORD,
|
||||
nNumberOfBytesToLockHigh: DWORD,
|
||||
lpOverlapped: LPOVERLAPPED) -> BOOL;
|
||||
}
|
||||
use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
|
||||
use winapi::um::fileapi::LockFileEx;
|
||||
use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Lock {
|
||||
|
@ -33,9 +33,6 @@ extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate cfg_if;
|
||||
|
||||
#[cfg(windows)]
|
||||
extern crate libc;
|
||||
|
||||
pub use rustc_serialize::hex::ToHex;
|
||||
|
||||
#[inline(never)]
|
||||
|
@ -569,39 +569,19 @@ fn get_resident() -> Option<usize> {
|
||||
|
||||
#[cfg(windows)]
|
||||
fn get_resident() -> Option<usize> {
|
||||
type BOOL = i32;
|
||||
type DWORD = u32;
|
||||
type HANDLE = *mut u8;
|
||||
use libc::size_t;
|
||||
#[repr(C)]
|
||||
#[allow(non_snake_case)]
|
||||
struct PROCESS_MEMORY_COUNTERS {
|
||||
cb: DWORD,
|
||||
PageFaultCount: DWORD,
|
||||
PeakWorkingSetSize: size_t,
|
||||
WorkingSetSize: size_t,
|
||||
QuotaPeakPagedPoolUsage: size_t,
|
||||
QuotaPagedPoolUsage: size_t,
|
||||
QuotaPeakNonPagedPoolUsage: size_t,
|
||||
QuotaNonPagedPoolUsage: size_t,
|
||||
PagefileUsage: size_t,
|
||||
PeakPagefileUsage: size_t,
|
||||
}
|
||||
#[allow(non_camel_case_types)]
|
||||
type PPROCESS_MEMORY_COUNTERS = *mut PROCESS_MEMORY_COUNTERS;
|
||||
#[link(name = "psapi")]
|
||||
extern "system" {
|
||||
fn GetCurrentProcess() -> HANDLE;
|
||||
fn GetProcessMemoryInfo(
|
||||
Process: HANDLE,
|
||||
ppsmemCounters: PPROCESS_MEMORY_COUNTERS,
|
||||
cb: DWORD,
|
||||
) -> BOOL;
|
||||
}
|
||||
let mut pmc: PROCESS_MEMORY_COUNTERS = unsafe { std::mem::zeroed() };
|
||||
pmc.cb = std::mem::size_of_val(&pmc) as DWORD;
|
||||
match unsafe { GetProcessMemoryInfo(GetCurrentProcess(), &mut pmc, pmc.cb) } {
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::processthreadsapi::GetCurrentProcess;
|
||||
use winapi::um::psapi::{GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS};
|
||||
|
||||
let mut pmc = MaybeUninit::<PROCESS_MEMORY_COUNTERS>::uninit();
|
||||
match unsafe {
|
||||
GetProcessMemoryInfo(GetCurrentProcess(), pmc.as_mut_ptr(), mem::size_of_val(&pmc) as DWORD)
|
||||
} {
|
||||
0 => None,
|
||||
_ => Some(pmc.WorkingSetSize as usize),
|
||||
_ => {
|
||||
let pmc = unsafe { pmc.assume_init() };
|
||||
Some(pmc.WorkingSetSize as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,5 +32,8 @@ rustc_serialize = { path = "../libserialize", package = "serialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
|
||||
|
||||
[features]
|
||||
llvm = ['rustc_interface/llvm']
|
||||
|
@ -514,15 +514,10 @@ fn stdout_isatty() -> bool {
|
||||
|
||||
#[cfg(windows)]
|
||||
fn stdout_isatty() -> bool {
|
||||
type DWORD = u32;
|
||||
type BOOL = i32;
|
||||
type HANDLE = *mut u8;
|
||||
type LPDWORD = *mut u32;
|
||||
const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
|
||||
extern "system" {
|
||||
fn GetStdHandle(which: DWORD) -> HANDLE;
|
||||
fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
|
||||
}
|
||||
use winapi::um::consoleapi::GetConsoleMode;
|
||||
use winapi::um::processenv::GetStdHandle;
|
||||
use winapi::um::winbase::STD_OUTPUT_HANDLE;
|
||||
|
||||
unsafe {
|
||||
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
let mut out = 0;
|
||||
@ -1214,11 +1209,8 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
#[cfg(windows)]
|
||||
unsafe {
|
||||
if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
|
||||
extern "system" {
|
||||
fn DebugBreak();
|
||||
}
|
||||
// Trigger a debugger if we crashed during bootstrap
|
||||
DebugBreak();
|
||||
winapi::um::debugapi::DebugBreak();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,24 @@
|
||||
A pattern binding is using the same name as one of the variants of a type.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0170
|
||||
# #![deny(warnings)]
|
||||
enum Method {
|
||||
GET,
|
||||
POST,
|
||||
}
|
||||
|
||||
fn is_empty(s: Method) -> bool {
|
||||
match s {
|
||||
GET => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
Enum variants are qualified by default. For example, given this type:
|
||||
|
||||
```
|
||||
|
@ -19,3 +19,6 @@ atty = "0.2"
|
||||
termcolor = "1.0"
|
||||
annotate-snippets = "0.6.1"
|
||||
term_size = "0.3.1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["handleapi", "synchapi", "winbase"] }
|
||||
|
@ -12,31 +12,14 @@
|
||||
use std::any::Any;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[allow(nonstandard_style)]
|
||||
pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
|
||||
use std::ffi::CString;
|
||||
use std::io;
|
||||
|
||||
type LPSECURITY_ATTRIBUTES = *mut u8;
|
||||
type BOOL = i32;
|
||||
type LPCSTR = *const u8;
|
||||
type HANDLE = *mut u8;
|
||||
type DWORD = u32;
|
||||
|
||||
const INFINITE: DWORD = !0;
|
||||
const WAIT_OBJECT_0: DWORD = 0;
|
||||
const WAIT_ABANDONED: DWORD = 0x00000080;
|
||||
|
||||
extern "system" {
|
||||
fn CreateMutexA(
|
||||
lpMutexAttributes: LPSECURITY_ATTRIBUTES,
|
||||
bInitialOwner: BOOL,
|
||||
lpName: LPCSTR,
|
||||
) -> HANDLE;
|
||||
fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
|
||||
fn ReleaseMutex(hMutex: HANDLE) -> BOOL;
|
||||
fn CloseHandle(hObject: HANDLE) -> BOOL;
|
||||
}
|
||||
use winapi::shared::ntdef::HANDLE;
|
||||
use winapi::um::handleapi::CloseHandle;
|
||||
use winapi::um::synchapi::{CreateMutexA, ReleaseMutex, WaitForSingleObject};
|
||||
use winapi::um::winbase::{INFINITE, WAIT_ABANDONED, WAIT_OBJECT_0};
|
||||
|
||||
struct Handle(HANDLE);
|
||||
|
||||
@ -65,7 +48,7 @@ pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
|
||||
//
|
||||
// This will silently create one if it doesn't already exist, or it'll
|
||||
// open up a handle to one if it already exists.
|
||||
let mutex = CreateMutexA(std::ptr::null_mut(), 0, cname.as_ptr() as *const u8);
|
||||
let mutex = CreateMutexA(std::ptr::null_mut(), 0, cname.as_ptr());
|
||||
if mutex.is_null() {
|
||||
panic!(
|
||||
"failed to create global mutex named `{}`: {}",
|
||||
|
@ -43,6 +43,9 @@ rustc_resolve = { path = "../librustc_resolve" }
|
||||
tempfile = "3.0.5"
|
||||
once_cell = "1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["libloaderapi"] }
|
||||
|
||||
[dev-dependencies]
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
|
||||
|
@ -340,19 +340,17 @@ fn sysroot_candidates() -> Vec<PathBuf> {
|
||||
fn current_dll_path() -> Option<PathBuf> {
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::prelude::*;
|
||||
use std::ptr;
|
||||
|
||||
extern "system" {
|
||||
fn GetModuleHandleExW(dwFlags: u32, lpModuleName: usize, phModule: *mut usize) -> i32;
|
||||
fn GetModuleFileNameW(hModule: usize, lpFilename: *mut u16, nSize: u32) -> u32;
|
||||
}
|
||||
|
||||
const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: u32 = 0x00000004;
|
||||
use winapi::um::libloaderapi::{
|
||||
GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let mut module = 0;
|
||||
let mut module = ptr::null_mut();
|
||||
let r = GetModuleHandleExW(
|
||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
current_dll_path as usize,
|
||||
current_dll_path as usize as *mut _,
|
||||
&mut module,
|
||||
);
|
||||
if r == 0 {
|
||||
|
@ -215,12 +215,14 @@ fn main() {
|
||||
let mut cmd = Command::new(&llvm_config);
|
||||
cmd.arg(llvm_link_arg).arg("--ldflags");
|
||||
for lib in output(&mut cmd).split_whitespace() {
|
||||
if lib.starts_with("-LIBPATH:") {
|
||||
println!("cargo:rustc-link-search=native={}", &lib[9..]);
|
||||
} else if is_crossed {
|
||||
if lib.starts_with("-L") {
|
||||
if is_crossed {
|
||||
if lib.starts_with("-LIBPATH:") {
|
||||
println!("cargo:rustc-link-search=native={}", lib[9..].replace(&host, &target));
|
||||
} else if lib.starts_with("-L") {
|
||||
println!("cargo:rustc-link-search=native={}", lib[2..].replace(&host, &target));
|
||||
}
|
||||
} else if lib.starts_with("-LIBPATH:") {
|
||||
println!("cargo:rustc-link-search=native={}", &lib[9..]);
|
||||
} else if lib.starts_with("-l") {
|
||||
println!("cargo:rustc-link-lib={}", &lib[2..]);
|
||||
} else if lib.starts_with("-L") {
|
||||
|
@ -27,3 +27,6 @@ rustc_expand = { path = "../librustc_expand" }
|
||||
rustc_parse = { path = "../librustc_parse" }
|
||||
rustc_span = { path = "../librustc_span" }
|
||||
rustc_error_codes = { path = "../librustc_error_codes" }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] }
|
||||
|
@ -111,9 +111,9 @@ mod dl {
|
||||
) -> Result<*mut u8, String> {
|
||||
check_for_errors_in(|| libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8)
|
||||
}
|
||||
|
||||
pub(super) unsafe fn close(handle: *mut u8) {
|
||||
libc::dlclose(handle as *mut libc::c_void);
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,27 +124,15 @@ mod dl {
|
||||
use std::os::windows::prelude::*;
|
||||
use std::ptr;
|
||||
|
||||
use libc::{c_char, c_uint, c_void};
|
||||
|
||||
type DWORD = u32;
|
||||
type HMODULE = *mut u8;
|
||||
type BOOL = i32;
|
||||
type LPCWSTR = *const u16;
|
||||
type LPCSTR = *const i8;
|
||||
|
||||
extern "system" {
|
||||
fn SetThreadErrorMode(dwNewMode: DWORD, lpOldMode: *mut DWORD) -> c_uint;
|
||||
fn LoadLibraryW(name: LPCWSTR) -> HMODULE;
|
||||
fn GetModuleHandleExW(dwFlags: DWORD, name: LPCWSTR, handle: *mut HMODULE) -> BOOL;
|
||||
fn GetProcAddress(handle: HMODULE, name: LPCSTR) -> *mut c_void;
|
||||
fn FreeLibrary(handle: HMODULE) -> BOOL;
|
||||
}
|
||||
use winapi::shared::minwindef::HMODULE;
|
||||
use winapi::um::errhandlingapi::SetThreadErrorMode;
|
||||
use winapi::um::libloaderapi::{FreeLibrary, GetModuleHandleExW, GetProcAddress, LoadLibraryW};
|
||||
use winapi::um::winbase::SEM_FAILCRITICALERRORS;
|
||||
|
||||
pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
||||
// disable "dll load failed" error dialog.
|
||||
let prev_error_mode = unsafe {
|
||||
// SEM_FAILCRITICALERRORS 0x01
|
||||
let new_error_mode = 1;
|
||||
let new_error_mode = SEM_FAILCRITICALERRORS;
|
||||
let mut prev_error_mode = 0;
|
||||
let result = SetThreadErrorMode(new_error_mode, &mut prev_error_mode);
|
||||
if result == 0 {
|
||||
@ -156,12 +144,12 @@ mod dl {
|
||||
let result = match filename {
|
||||
Some(filename) => {
|
||||
let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect();
|
||||
let result = unsafe { LoadLibraryW(filename_str.as_ptr()) };
|
||||
let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8;
|
||||
ptr_result(result)
|
||||
}
|
||||
None => {
|
||||
let mut handle = ptr::null_mut();
|
||||
let succeeded = unsafe { GetModuleHandleExW(0 as DWORD, ptr::null(), &mut handle) };
|
||||
let succeeded = unsafe { GetModuleHandleExW(0, ptr::null(), &mut handle) };
|
||||
if succeeded == 0 {
|
||||
Err(io::Error::last_os_error().to_string())
|
||||
} else {
|
||||
@ -177,7 +165,10 @@ mod dl {
|
||||
result
|
||||
}
|
||||
|
||||
pub(super) unsafe fn symbol(handle: *mut u8, symbol: *const c_char) -> Result<*mut u8, String> {
|
||||
pub(super) unsafe fn symbol(
|
||||
handle: *mut u8,
|
||||
symbol: *const libc::c_char,
|
||||
) -> Result<*mut u8, String> {
|
||||
let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8;
|
||||
ptr_result(ptr)
|
||||
}
|
||||
|
@ -587,12 +587,6 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
// padding.
|
||||
match tys.kind {
|
||||
ty::Int(..) | ty::Uint(..) | ty::Float(..) => true,
|
||||
ty::Tuple(tys) if tys.len() == 0 => true,
|
||||
ty::Adt(adt_def, _)
|
||||
if adt_def.is_struct() && adt_def.all_fields().next().is_none() =>
|
||||
{
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
} =>
|
||||
@ -609,11 +603,6 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
}
|
||||
// This is the element type size.
|
||||
let layout = self.ecx.layout_of(tys)?;
|
||||
// Empty tuples and fieldless structs (the only ZSTs that allow reaching this code)
|
||||
// have no data to be checked.
|
||||
if layout.is_zst() {
|
||||
return Ok(());
|
||||
}
|
||||
// This is the size in bytes of the whole array.
|
||||
let size = layout.size * len;
|
||||
// Size is not 0, get a pointer.
|
||||
@ -656,6 +645,13 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fast path for arrays and slices of ZSTs. We only need to check a single ZST element
|
||||
// of an array and not all of them, because there's only a single value of a specific
|
||||
// ZST type, so either validation fails for all elements or none.
|
||||
ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(tys)?.is_zst() => {
|
||||
// Validate just the first element
|
||||
self.walk_aggregate(op, fields.take(1))?
|
||||
}
|
||||
_ => {
|
||||
self.walk_aggregate(op, fields)? // default handler
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use rustc::mir::{
|
||||
SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
|
||||
UnOp, RETURN_PLACE,
|
||||
};
|
||||
use rustc::traits::TraitQueryMode;
|
||||
use rustc::ty::layout::{
|
||||
HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout,
|
||||
};
|
||||
@ -74,6 +75,46 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's even possible to satisfy the 'where' clauses
|
||||
// for this item.
|
||||
// This branch will never be taken for any normal function.
|
||||
// However, it's possible to `#!feature(trivial_bounds)]` to write
|
||||
// a function with impossible to satisfy clauses, e.g.:
|
||||
// `fn foo() where String: Copy {}`
|
||||
//
|
||||
// We don't usually need to worry about this kind of case,
|
||||
// since we would get a compilation error if the user tried
|
||||
// to call it. However, since we can do const propagation
|
||||
// even without any calls to the function, we need to make
|
||||
// sure that it even makes sense to try to evaluate the body.
|
||||
// If there are unsatisfiable where clauses, then all bets are
|
||||
// off, and we just give up.
|
||||
//
|
||||
// Note that we use TraitQueryMode::Canonical here, which causes
|
||||
// us to treat overflow like any other error. This is because we
|
||||
// are "speculatively" evaluating this item with the default substs.
|
||||
// While this usually succeeds, it may fail with tricky impls
|
||||
// (e.g. the typenum crate). Const-propagation is fundamentally
|
||||
// "best-effort", and does not affect correctness in any way.
|
||||
// Therefore, it's perfectly fine to just "give up" if we're
|
||||
// unable to check the bounds with the default substs.
|
||||
//
|
||||
// False negatives (failing to run const-prop on something when we actually
|
||||
// could) are fine. However, false positives (running const-prop on
|
||||
// an item with unsatisfiable bounds) can lead to us generating invalid
|
||||
// MIR.
|
||||
if !tcx.substitute_normalize_and_test_predicates((
|
||||
source.def_id(),
|
||||
InternalSubsts::identity_for_item(tcx, source.def_id()),
|
||||
TraitQueryMode::Canonical,
|
||||
)) {
|
||||
trace!(
|
||||
"ConstProp skipped for item with unsatisfiable predicates: {:?}",
|
||||
source.def_id()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
trace!("ConstProp starting for {:?}", source.def_id());
|
||||
|
||||
let dummy_body = &Body::new(
|
||||
|
@ -1,6 +1,10 @@
|
||||
// build-pass
|
||||
// ignore-32bit
|
||||
|
||||
// This test is a canary test that will essentially not compile in a reasonable time frame
|
||||
// (so it'll take hours) if any of the optimizations regress. With the optimizations, these compile
|
||||
// in milliseconds just as if the length were set to `1`.
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Foo;
|
||||
|
||||
@ -8,4 +12,6 @@ fn main() {
|
||||
let _ = [(); 4_000_000_000];
|
||||
let _ = [0u8; 4_000_000_000];
|
||||
let _ = [Foo; 4_000_000_000];
|
||||
let _ = [(Foo, (), Foo, ((), Foo, [0; 0])); 4_000_000_000];
|
||||
let _ = [[0; 0]; 4_000_000_000];
|
||||
}
|
||||
|
20
src/test/ui/consts/issue-67696-const-prop-ice.rs
Normal file
20
src/test/ui/consts/issue-67696-const-prop-ice.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// check-pass
|
||||
// compile-flags: --emit=mir,link
|
||||
// Checks that we don't ICE due to attempting to run const prop
|
||||
// on a function with unsatisifable 'where' clauses
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
trait A {
|
||||
fn foo(&self) -> Self where Self: Copy;
|
||||
}
|
||||
|
||||
impl A for [fn(&())] {
|
||||
fn foo(&self) -> Self where Self: Copy { *(&[] as &[_]) }
|
||||
}
|
||||
|
||||
impl A for i32 {
|
||||
fn foo(&self) -> Self { 3 }
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,5 +1,9 @@
|
||||
#![feature(const_raw_ptr_deref, never_type)]
|
||||
|
||||
const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
|
||||
const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
|
||||
const _: &[!; 0] = unsafe { &*(1_usize as *const [!; 0]) }; // ok
|
||||
const _: &[!] = unsafe { &*(1_usize as *const [!; 0]) }; // ok
|
||||
const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
|
||||
const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR undefined behavior
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,11 +1,27 @@
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/validate_never_arrays.rs:3:1
|
||||
|
|
||||
LL | const FOO: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
|
||||
LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
|
||||
|
|
||||
= 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.
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/validate_never_arrays.rs:6:1
|
||||
|
|
||||
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>[0]
|
||||
|
|
||||
= 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.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/validate_never_arrays.rs:7:1
|
||||
|
|
||||
LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>[0]
|
||||
|
|
||||
= 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.
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -1,4 +1,8 @@
|
||||
// run-pass
|
||||
// check-pass
|
||||
// compile-flags: --emit=mir,link
|
||||
// Force mir to be emitted, to ensure that const
|
||||
// propagation doesn't ICE on a function
|
||||
// with an 'impossible' body. See issue #67696
|
||||
// Inconsistent bounds with trait implementations
|
||||
|
||||
#![feature(trivial_bounds)]
|
||||
|
@ -42,10 +42,8 @@ mod tests;
|
||||
#[cfg(windows)]
|
||||
fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
use std::sync::Mutex;
|
||||
const SEM_NOGPFAULTERRORBOX: u32 = 0x0002;
|
||||
extern "system" {
|
||||
fn SetErrorMode(mode: u32) -> u32;
|
||||
}
|
||||
use winapi::um::errhandlingapi::SetErrorMode;
|
||||
use winapi::um::winbase::SEM_NOGPFAULTERRORBOX;
|
||||
|
||||
lazy_static! {
|
||||
static ref LOCK: Mutex<()> = { Mutex::new(()) };
|
||||
|
Loading…
Reference in New Issue
Block a user