Auto merge of #65152 - tmandry:rollup-btn4a01, r=tmandry
Rollup of 18 pull requests This contains changes from all the successful runs that bors marked as timed out, plus a revert of #63649 which appears to be the immediate cause of the timeouts. Successful merges: - #64708 (Stabilize `Option::as_deref` and `Option::as_deref_mut`) - #64728 (Stabilize UdpSocket::peer_addr) - #64765 (std: Reduce checks for `feature = "backtrace"`) - #64909 (When encountering chained operators use heuristics to recover from bad turbofish) - #65011 (Do not ICE when dereferencing non-Copy raw pointer) - #65064 (permit asyncawait-ondeck to be added by anyone) - #65066 ([const-prop] Fix ICE when trying to eval polymorphic promoted MIR) - #65100 (Replace GeneratorSubsts with SubstsRef) - #65105 (Split out some passes from librustc) - #65106 (Allow unused attributes to avoid incremental bug) - #65113 (Fix lonely backtick) - #65116 (Remove unneeded visit_statement definition) - #65118 (Update the documented default of -Z mutable-noalias) - #65123 (Account for macro invocation in `let mut $pat` diagnostic.) - #65124 (Replace some instances of `as *[const | mut] _` with `.cast()`) - #65126 (Fix typo on `now()` comments) - #65130 (lint: extern non-exhaustive types are improper) - #65151 (Revert #63649 - "Upgrade Emscripten targets to use upstream LLVM backend") Failed merges: r? @ghost
This commit is contained in:
commit
5a8fb7c24d
@ -3613,6 +3613,8 @@ dependencies = [
|
||||
"rustc",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_index",
|
||||
"rustc_target",
|
||||
"syntax",
|
||||
"syntax_pos",
|
||||
]
|
||||
|
@ -377,7 +377,6 @@
|
||||
# but you can also optionally enable the "emscripten" backend for asm.js or
|
||||
# make this an empty array (but that probably won't get too far in the
|
||||
# bootstrap)
|
||||
# FIXME: remove the obsolete emscripten backend option.
|
||||
#codegen-backends = ["llvm"]
|
||||
|
||||
# This is the name of the directory in which codegen backends will get installed
|
||||
|
@ -970,7 +970,6 @@ impl<'a> Builder<'a> {
|
||||
Some("-Wl,-rpath,@loader_path/../lib")
|
||||
} else if !target.contains("windows") &&
|
||||
!target.contains("wasm32") &&
|
||||
!target.contains("emscripten") &&
|
||||
!target.contains("fuchsia") {
|
||||
Some("-Wl,-rpath,$ORIGIN/../lib")
|
||||
} else {
|
||||
|
@ -1047,11 +1047,10 @@ impl Step for Compiletest {
|
||||
// Also provide `rust_test_helpers` for the host.
|
||||
builder.ensure(native::TestHelpers { target: compiler.host });
|
||||
|
||||
// As well as the target, except for plain wasm32, which can't build it
|
||||
if !target.contains("wasm32") || target.contains("emscripten") {
|
||||
// wasm32 can't build the test helpers
|
||||
if !target.contains("wasm32") {
|
||||
builder.ensure(native::TestHelpers { target });
|
||||
}
|
||||
|
||||
builder.ensure(RemoteCopyLibs { compiler, target });
|
||||
|
||||
let mut cmd = builder.tool_cmd(Tool::Compiletest);
|
||||
|
@ -11,8 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
cmake \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils \
|
||||
bzip2
|
||||
xz-utils
|
||||
|
||||
COPY scripts/emscripten.sh /scripts/
|
||||
RUN bash /scripts/emscripten.sh
|
||||
@ -21,16 +20,28 @@ COPY scripts/sccache.sh /scripts/
|
||||
RUN sh /scripts/sccache.sh
|
||||
|
||||
ENV PATH=$PATH:/emsdk-portable
|
||||
ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/
|
||||
ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/
|
||||
ENV BINARYEN_ROOT=/emsdk-portable/upstream/
|
||||
ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/
|
||||
ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/
|
||||
ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/
|
||||
ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/
|
||||
ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/
|
||||
ENV EM_CONFIG=/emsdk-portable/.emscripten
|
||||
|
||||
ENV TARGETS=asmjs-unknown-emscripten
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
ENV RUST_CONFIGURE_ARGS --enable-emscripten --disable-optimize-tests
|
||||
|
||||
# This is almost identical to the wasm32-unknown-emscripten target, so
|
||||
# running with assertions again is not useful
|
||||
ENV NO_DEBUG_ASSERTIONS=1
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS \
|
||||
src/test/ui \
|
||||
src/test/run-fail \
|
||||
src/libstd \
|
||||
src/liballoc \
|
||||
src/libcore
|
||||
|
||||
# Debug assertions in rustc are largely covered by other builders, and LLVM
|
||||
# assertions cause this builder to slow down by quite a large amount and don't
|
||||
# buy us a huge amount over other builders (not sure if we've ever seen an
|
||||
# asmjs-specific backend assertion trip), so disable assertions for these
|
||||
# tests.
|
||||
ENV NO_LLVM_ASSERTIONS=1
|
||||
ENV NO_DEBUG_ASSERTIONS=1
|
||||
|
35
src/ci/docker/disabled/wasm32-exp/Dockerfile
Normal file
35
src/ci/docker/disabled/wasm32-exp/Dockerfile
Normal file
@ -0,0 +1,35 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
g++ \
|
||||
make \
|
||||
file \
|
||||
curl \
|
||||
ca-certificates \
|
||||
python \
|
||||
git \
|
||||
cmake \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils \
|
||||
jq \
|
||||
bzip2
|
||||
|
||||
# emscripten
|
||||
COPY scripts/emscripten-wasm.sh /scripts/
|
||||
COPY wasm32-exp/node.sh /usr/local/bin/node
|
||||
RUN bash /scripts/emscripten-wasm.sh
|
||||
|
||||
# cache
|
||||
COPY scripts/sccache.sh /scripts/
|
||||
RUN sh /scripts/sccache.sh
|
||||
|
||||
# env
|
||||
ENV PATH=/wasm-install/emscripten:/wasm-install/bin:$PATH
|
||||
ENV EM_CONFIG=/root/.emscripten
|
||||
|
||||
ENV TARGETS=wasm32-experimental-emscripten
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --experimental-targets=WebAssembly
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
9
src/ci/docker/disabled/wasm32-exp/node.sh
Executable file
9
src/ci/docker/disabled/wasm32-exp/node.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
path="$(dirname $1)"
|
||||
file="$(basename $1)"
|
||||
|
||||
shift
|
||||
|
||||
cd "$path"
|
||||
exec /node-v8.0.0-linux-x64/bin/node "$file" "$@"
|
@ -11,9 +11,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
cmake \
|
||||
sudo \
|
||||
gdb \
|
||||
xz-utils \
|
||||
bzip2
|
||||
xz-utils
|
||||
|
||||
# emscripten
|
||||
COPY scripts/emscripten.sh /scripts/
|
||||
RUN bash /scripts/emscripten.sh
|
||||
|
||||
@ -21,18 +21,12 @@ COPY scripts/sccache.sh /scripts/
|
||||
RUN sh /scripts/sccache.sh
|
||||
|
||||
ENV PATH=$PATH:/emsdk-portable
|
||||
ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/
|
||||
ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/
|
||||
ENV BINARYEN_ROOT=/emsdk-portable/upstream/
|
||||
ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/
|
||||
ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/
|
||||
ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/
|
||||
ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/
|
||||
ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/
|
||||
ENV EM_CONFIG=/emsdk-portable/.emscripten
|
||||
|
||||
ENV TARGETS=wasm32-unknown-emscripten
|
||||
|
||||
# FIXME: Re-enable these tests once Cargo stops trying to execute wasms
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS \
|
||||
--exclude src/libcore \
|
||||
--exclude src/liballoc \
|
||||
--exclude src/libproc_macro \
|
||||
--exclude src/libstd \
|
||||
--exclude src/libterm \
|
||||
--exclude src/libtest
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
|
37
src/ci/docker/scripts/emscripten-wasm.sh
Normal file
37
src/ci/docker/scripts/emscripten-wasm.sh
Normal file
@ -0,0 +1,37 @@
|
||||
set -ex
|
||||
|
||||
hide_output() {
|
||||
set +x
|
||||
on_err="
|
||||
echo ERROR: An error was encountered with the build.
|
||||
cat /tmp/build.log
|
||||
exit 1
|
||||
"
|
||||
trap "$on_err" ERR
|
||||
bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
|
||||
PING_LOOP_PID=$!
|
||||
$@ &> /tmp/build.log
|
||||
trap - ERR
|
||||
kill $PING_LOOP_PID
|
||||
rm -f /tmp/build.log
|
||||
set -x
|
||||
}
|
||||
|
||||
# Download last known good emscripten from WebAssembly waterfall
|
||||
BUILD=$(curl -fL https://storage.googleapis.com/wasm-llvm/builds/linux/lkgr.json | \
|
||||
jq '.build | tonumber')
|
||||
curl -sL https://storage.googleapis.com/wasm-llvm/builds/linux/$BUILD/wasm-binaries.tbz2 | \
|
||||
hide_output tar xvkj
|
||||
|
||||
# node 8 is required to run wasm
|
||||
cd /
|
||||
curl -sL https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \
|
||||
tar -xJ
|
||||
|
||||
# Make emscripten use wasm-ready node and LLVM tools
|
||||
echo "EMSCRIPTEN_ROOT = '/wasm-install/emscripten'" >> /root/.emscripten
|
||||
echo "NODE_JS='/usr/local/bin/node'" >> /root/.emscripten
|
||||
echo "LLVM_ROOT='/wasm-install/bin'" >> /root/.emscripten
|
||||
echo "BINARYEN_ROOT = '/wasm-install'" >> /root/.emscripten
|
||||
echo "COMPILER_ENGINE = NODE_JS" >> /root/.emscripten
|
||||
echo "JS_ENGINES = [NODE_JS]" >> /root/.emscripten
|
@ -17,15 +17,20 @@ exit 1
|
||||
set -x
|
||||
}
|
||||
|
||||
git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable
|
||||
cd /
|
||||
curl -fL https://mozilla-games.s3.amazonaws.com/emscripten/releases/emsdk-portable.tar.gz | \
|
||||
tar -xz
|
||||
|
||||
cd /emsdk-portable
|
||||
hide_output ./emsdk install 1.38.46-upstream
|
||||
./emsdk activate 1.38.46-upstream
|
||||
./emsdk update
|
||||
hide_output ./emsdk install sdk-1.38.15-64bit
|
||||
./emsdk activate sdk-1.38.15-64bit
|
||||
|
||||
# Compile and cache libc
|
||||
source ./emsdk_env.sh
|
||||
echo "main(){}" > a.c
|
||||
HOME=/emsdk-portable/ emcc a.c
|
||||
HOME=/emsdk-portable/ emcc -s BINARYEN=1 a.c
|
||||
rm -f a.*
|
||||
|
||||
# Make emsdk usable by any user
|
||||
|
@ -1,5 +1,10 @@
|
||||
use std::cmp;
|
||||
use std::collections::BinaryHeap;
|
||||
use std::collections::binary_heap::{Drain, PeekMut};
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use rand::{thread_rng, seq::SliceRandom};
|
||||
|
||||
#[test]
|
||||
fn test_iterator() {
|
||||
@ -276,15 +281,9 @@ fn assert_covariance() {
|
||||
// even if the order may not be correct.
|
||||
//
|
||||
// Destructors must be called exactly once per element.
|
||||
// FIXME: re-enable emscripten once it can unwind again
|
||||
#[test]
|
||||
#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics
|
||||
#[cfg(not(miri))] // Miri does not support catching panics
|
||||
fn panic_safe() {
|
||||
use std::cmp;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use rand::{thread_rng, seq::SliceRandom};
|
||||
|
||||
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[derive(Eq, PartialEq, Ord, Clone, Debug)]
|
||||
|
@ -483,7 +483,7 @@ mod slice_index {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "emscripten"))] // hits an OOM
|
||||
#[cfg(not(target_arch = "asmjs"))] // hits an OOM
|
||||
#[cfg(not(miri))] // Miri is too slow
|
||||
fn simple_big() {
|
||||
fn a_million_letter_x() -> String {
|
||||
|
@ -1,10 +0,0 @@
|
||||
diff a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs (rejected hunks)
|
||||
@@ -483,7 +483,7 @@ mod slice_index {
|
||||
}
|
||||
|
||||
#[test]
|
||||
- #[cfg(not(target_arch = "asmjs"))] // hits an OOM
|
||||
+ #[cfg(not(target_arch = "js"))] // hits an OOM
|
||||
#[cfg(not(miri))] // Miri is too slow
|
||||
fn simple_big() {
|
||||
fn a_million_letter_x() -> String {
|
@ -944,10 +944,8 @@ fn drain_filter_complex() {
|
||||
}
|
||||
}
|
||||
|
||||
// Miri does not support catching panics
|
||||
// FIXME: re-enable emscripten once it can unwind again
|
||||
#[test]
|
||||
#[cfg(not(any(miri, target_os = "emscripten")))]
|
||||
#[cfg(not(miri))] // Miri does not support catching panics
|
||||
fn drain_filter_consumed_panic() {
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
@ -997,9 +995,8 @@ fn drain_filter_consumed_panic() {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Re-enable emscripten once it can catch panics
|
||||
#[test]
|
||||
#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics
|
||||
#[cfg(not(miri))] // Miri does not support catching panics
|
||||
fn drain_filter_unconsumed_panic() {
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
@ -49,10 +49,8 @@ impl fmt::Debug for c_void {
|
||||
/// Basic implementation of a `va_list`.
|
||||
// The name is WIP, using `VaListImpl` for now.
|
||||
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
|
||||
not(target_arch = "x86_64")),
|
||||
not(target_arch = "x86_64"), not(target_arch = "asmjs")),
|
||||
all(target_arch = "aarch64", target_os = "ios"),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows))]
|
||||
#[repr(transparent)]
|
||||
#[unstable(feature = "c_variadic",
|
||||
@ -69,10 +67,8 @@ pub struct VaListImpl<'f> {
|
||||
}
|
||||
|
||||
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
|
||||
not(target_arch = "x86_64")),
|
||||
not(target_arch = "x86_64"), not(target_arch = "asmjs")),
|
||||
all(target_arch = "aarch64", target_os = "ios"),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows))]
|
||||
#[unstable(feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
@ -141,6 +137,38 @@ pub struct VaListImpl<'f> {
|
||||
_marker: PhantomData<&'f mut &'f c_void>,
|
||||
}
|
||||
|
||||
/// asm.js ABI implementation of a `va_list`.
|
||||
// asm.js uses the PNaCl ABI, which specifies that a `va_list` is
|
||||
// an array of 4 32-bit integers, according to the old PNaCl docs at
|
||||
// https://web.archive.org/web/20130518054430/https://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Derived-Types
|
||||
// and clang does the same in `CreatePNaClABIBuiltinVaListDecl` from `lib/AST/ASTContext.cpp`
|
||||
#[cfg(all(target_arch = "asmjs", not(windows)))]
|
||||
#[repr(C)]
|
||||
#[unstable(feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930")]
|
||||
#[lang = "va_list"]
|
||||
pub struct VaListImpl<'f> {
|
||||
inner: [crate::mem::MaybeUninit<i32>; 4],
|
||||
_marker: PhantomData<&'f mut &'f c_void>,
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "asmjs", not(windows)))]
|
||||
#[unstable(feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930")]
|
||||
impl<'f> fmt::Debug for VaListImpl<'f> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
write!(f, "va_list* [{:#x}, {:#x}, {:#x}, {:#x}]",
|
||||
self.inner[0].read(), self.inner[1].read(),
|
||||
self.inner[2].read(), self.inner[3].read())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper for a `va_list`
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
@ -150,18 +178,14 @@ pub struct VaListImpl<'f> {
|
||||
issue = "44930")]
|
||||
pub struct VaList<'a, 'f: 'a> {
|
||||
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
|
||||
not(target_arch = "x86_64")),
|
||||
not(target_arch = "x86_64"), not(target_arch = "asmjs")),
|
||||
all(target_arch = "aarch64", target_os = "ios"),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows))]
|
||||
inner: VaListImpl<'f>,
|
||||
|
||||
#[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc",
|
||||
target_arch = "x86_64"),
|
||||
target_arch = "x86_64", target_arch = "asmjs"),
|
||||
any(not(target_arch = "aarch64"), not(target_os = "ios")),
|
||||
not(target_arch = "wasm32"),
|
||||
not(target_arch = "asmjs"),
|
||||
not(windows)))]
|
||||
inner: &'a mut VaListImpl<'f>,
|
||||
|
||||
@ -169,10 +193,8 @@ pub struct VaList<'a, 'f: 'a> {
|
||||
}
|
||||
|
||||
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
|
||||
not(target_arch = "x86_64")),
|
||||
not(target_arch = "x86_64"), not(target_arch = "asmjs")),
|
||||
all(target_arch = "aarch64", target_os = "ios"),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows))]
|
||||
#[unstable(feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
@ -190,10 +212,8 @@ impl<'f> VaListImpl<'f> {
|
||||
}
|
||||
|
||||
#[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc",
|
||||
target_arch = "x86_64"),
|
||||
target_arch = "x86_64", target_arch = "asmjs"),
|
||||
any(not(target_arch = "aarch64"), not(target_os = "ios")),
|
||||
not(target_arch = "wasm32"),
|
||||
not(target_arch = "asmjs"),
|
||||
not(windows)))]
|
||||
#[unstable(feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
|
@ -114,8 +114,24 @@ pub fn black_box<T>(dummy: T) -> T {
|
||||
// this. LLVM's intepretation of inline assembly is that it's, well, a black
|
||||
// box. This isn't the greatest implementation since it probably deoptimizes
|
||||
// more than we want, but it's so far good enough.
|
||||
#[cfg(not(any(
|
||||
target_arch = "asmjs",
|
||||
all(
|
||||
target_arch = "wasm32",
|
||||
target_os = "emscripten"
|
||||
)
|
||||
)))]
|
||||
unsafe {
|
||||
asm!("" : : "r"(&dummy));
|
||||
return dummy;
|
||||
}
|
||||
|
||||
// Not all platforms support inline assembly so try to do something without
|
||||
// inline assembly which in theory still hinders at least some optimizations
|
||||
// on those targets. This is the "best effort" scenario.
|
||||
unsafe {
|
||||
let ret = crate::ptr::read_volatile(&dummy);
|
||||
crate::mem::forget(dummy);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
@ -1102,7 +1102,6 @@ impl<T: Default> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
|
||||
impl<T: Deref> Option<T> {
|
||||
/// Converts from `Option<T>` (or `&Option<T>`) to `Option<&T::Target>`.
|
||||
///
|
||||
@ -1114,20 +1113,18 @@ impl<T: Deref> Option<T> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(inner_deref)]
|
||||
///
|
||||
/// let x: Option<String> = Some("hey".to_owned());
|
||||
/// assert_eq!(x.as_deref(), Some("hey"));
|
||||
///
|
||||
/// let x: Option<String> = None;
|
||||
/// assert_eq!(x.as_deref(), None);
|
||||
/// ```
|
||||
#[stable(feature = "option_deref", since = "1.40.0")]
|
||||
pub fn as_deref(&self) -> Option<&T::Target> {
|
||||
self.as_ref().map(|t| t.deref())
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
|
||||
impl<T: DerefMut> Option<T> {
|
||||
/// Converts from `Option<T>` (or `&mut Option<T>`) to `Option<&mut T::Target>`.
|
||||
///
|
||||
@ -1137,14 +1134,13 @@ impl<T: DerefMut> Option<T> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(inner_deref)]
|
||||
///
|
||||
/// let mut x: Option<String> = Some("hey".to_owned());
|
||||
/// assert_eq!(x.as_deref_mut().map(|x| {
|
||||
/// x.make_ascii_uppercase();
|
||||
/// x
|
||||
/// }), Some("HEY".to_owned().as_mut_str()));
|
||||
/// ```
|
||||
#[stable(feature = "option_deref", since = "1.40.0")]
|
||||
pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> {
|
||||
self.as_mut().map(|t| t.deref_mut())
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ impl<T> [T] {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
// SAFETY: const sound because we transmute out the length field as a usize (which it must be)
|
||||
#[allow(unused_attributes)]
|
||||
#[allow_internal_unstable(const_fn_union)]
|
||||
pub const fn len(&self) -> usize {
|
||||
unsafe {
|
||||
|
@ -2167,6 +2167,7 @@ impl str {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline(always)]
|
||||
// SAFETY: const sound because we transmute two types with the same layout
|
||||
#[allow(unused_attributes)]
|
||||
#[allow_internal_unstable(const_fn_union)]
|
||||
pub const fn as_bytes(&self) -> &[u8] {
|
||||
#[repr(C)]
|
||||
|
@ -466,66 +466,6 @@ fn main() {
|
||||
```
|
||||
"##,
|
||||
|
||||
// This shouldn't really ever trigger since the repeated value error comes first
|
||||
E0136: r##"
|
||||
A binary can only have one entry point, and by default that entry point is the
|
||||
function `main()`. If there are multiple such functions, please rename one.
|
||||
"##,
|
||||
|
||||
E0137: r##"
|
||||
More than one function was declared with the `#[main]` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0137
|
||||
#![feature(main)]
|
||||
|
||||
#[main]
|
||||
fn foo() {}
|
||||
|
||||
#[main]
|
||||
fn f() {} // error: multiple functions with a `#[main]` attribute
|
||||
```
|
||||
|
||||
This error indicates that the compiler found multiple functions with the
|
||||
`#[main]` attribute. This is an error because there must be a unique entry
|
||||
point into a Rust program. Example:
|
||||
|
||||
```
|
||||
#![feature(main)]
|
||||
|
||||
#[main]
|
||||
fn f() {} // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0138: r##"
|
||||
More than one function was declared with the `#[start]` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0138
|
||||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize {}
|
||||
|
||||
#[start]
|
||||
fn f(argc: isize, argv: *const *const u8) -> isize {}
|
||||
// error: multiple 'start' functions
|
||||
```
|
||||
|
||||
This error indicates that the compiler found multiple functions with the
|
||||
`#[start]` attribute. This is an error because there must be a unique entry
|
||||
point into a Rust program. Example:
|
||||
|
||||
```
|
||||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0139: r##"
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
@ -1626,33 +1566,6 @@ It is not possible to use stability attributes outside of the standard library.
|
||||
Also, for now, it is not possible to write deprecation messages either.
|
||||
"##,
|
||||
|
||||
E0512: r##"
|
||||
Transmute with two differently sized types was attempted. Erroneous code
|
||||
example:
|
||||
|
||||
```compile_fail,E0512
|
||||
fn takes_u8(_: u8) {}
|
||||
|
||||
fn main() {
|
||||
unsafe { takes_u8(::std::mem::transmute(0u16)); }
|
||||
// error: cannot transmute between types of different sizes,
|
||||
// or dependently-sized types
|
||||
}
|
||||
```
|
||||
|
||||
Please use types with same size or use the expected type directly. Example:
|
||||
|
||||
```
|
||||
fn takes_u8(_: u8) {}
|
||||
|
||||
fn main() {
|
||||
unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok!
|
||||
// or:
|
||||
unsafe { takes_u8(0u8); } // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0517: r##"
|
||||
This error indicates that a `#[repr(..)]` attribute was placed on an
|
||||
unsupported item.
|
||||
@ -1847,84 +1760,6 @@ See [RFC 1522] for more details.
|
||||
[RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md
|
||||
"##,
|
||||
|
||||
E0591: r##"
|
||||
Per [RFC 401][rfc401], if you have a function declaration `foo`:
|
||||
|
||||
```
|
||||
// For the purposes of this explanation, all of these
|
||||
// different kinds of `fn` declarations are equivalent:
|
||||
struct S;
|
||||
fn foo(x: S) { /* ... */ }
|
||||
# #[cfg(for_demonstration_only)]
|
||||
extern "C" { fn foo(x: S); }
|
||||
# #[cfg(for_demonstration_only)]
|
||||
impl S { fn foo(self) { /* ... */ } }
|
||||
```
|
||||
|
||||
the type of `foo` is **not** `fn(S)`, as one might expect.
|
||||
Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
|
||||
However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
|
||||
so you rarely notice this:
|
||||
|
||||
```
|
||||
# struct S;
|
||||
# fn foo(_: S) {}
|
||||
let x: fn(S) = foo; // OK, coerces
|
||||
```
|
||||
|
||||
The reason that this matter is that the type `fn(S)` is not specific to
|
||||
any particular function: it's a function _pointer_. So calling `x()` results
|
||||
in a virtual call, whereas `foo()` is statically dispatched, because the type
|
||||
of `foo` tells us precisely what function is being called.
|
||||
|
||||
As noted above, coercions mean that most code doesn't have to be
|
||||
concerned with this distinction. However, you can tell the difference
|
||||
when using **transmute** to convert a fn item into a fn pointer.
|
||||
|
||||
This is sometimes done as part of an FFI:
|
||||
|
||||
```compile_fail,E0591
|
||||
extern "C" fn foo(userdata: Box<i32>) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
# fn callback(_: extern "C" fn(*mut i32)) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo);
|
||||
callback(f);
|
||||
# }
|
||||
```
|
||||
|
||||
Here, transmute is being used to convert the types of the fn arguments.
|
||||
This pattern is incorrect because, because the type of `foo` is a function
|
||||
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
|
||||
is a function pointer, which is not zero-sized.
|
||||
This pattern should be rewritten. There are a few possible ways to do this:
|
||||
|
||||
- change the original fn declaration to match the expected signature,
|
||||
and do the cast in the fn body (the preferred option)
|
||||
- cast the fn item fo a fn pointer before calling transmute, as shown here:
|
||||
|
||||
```
|
||||
# extern "C" fn foo(_: Box<i32>) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||
# }
|
||||
```
|
||||
|
||||
The same applies to transmutes to `*mut fn()`, which were observed in practice.
|
||||
Note though that use of this type is generally incorrect.
|
||||
The intention is typically to describe a function pointer, but just `fn()`
|
||||
alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
|
||||
(Since these values are typically just passed to C code, however, this rarely
|
||||
makes a difference in practice.)
|
||||
|
||||
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||
"##,
|
||||
|
||||
E0593: r##"
|
||||
You tried to supply an `Fn`-based type with an incorrect number of arguments
|
||||
than what was expected.
|
||||
@ -1941,21 +1776,6 @@ fn main() {
|
||||
```
|
||||
"##,
|
||||
|
||||
E0601: r##"
|
||||
No `main` function was found in a binary crate. To fix this error, add a
|
||||
`main` function. For example:
|
||||
|
||||
```
|
||||
fn main() {
|
||||
// Your program will start here.
|
||||
println!("Hello world!");
|
||||
}
|
||||
```
|
||||
|
||||
If you don't know the basics of Rust, you can go look to the Rust Book to get
|
||||
started: https://doc.rust-lang.org/book/
|
||||
"##,
|
||||
|
||||
E0602: r##"
|
||||
An unknown lint was used on the command line.
|
||||
|
||||
|
@ -733,12 +733,12 @@ where
|
||||
// Skip lifetime parameters of the enclosing item(s)
|
||||
// Also skip the witness type, because that has no free regions.
|
||||
|
||||
for upvar_ty in substs.upvar_tys(def_id, self.tcx) {
|
||||
for upvar_ty in substs.as_generator().upvar_tys(def_id, self.tcx) {
|
||||
upvar_ty.visit_with(self);
|
||||
}
|
||||
|
||||
substs.return_ty(def_id, self.tcx).visit_with(self);
|
||||
substs.yield_ty(def_id, self.tcx).visit_with(self);
|
||||
substs.as_generator().return_ty(def_id, self.tcx).visit_with(self);
|
||||
substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self);
|
||||
}
|
||||
_ => {
|
||||
ty.super_visit_with(self);
|
||||
@ -902,7 +902,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
||||
ty::Generator(def_id, substs, movability) => {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let substs =
|
||||
self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| {
|
||||
self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| {
|
||||
if index < generics.parent_count {
|
||||
// Accommodate missing regions in the parent kinds...
|
||||
self.fold_kind_mapping_missing_regions_to_empty(kind)
|
||||
@ -912,7 +912,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
|
||||
}
|
||||
}));
|
||||
|
||||
self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability)
|
||||
self.tcx.mk_generator(def_id, substs, movability)
|
||||
}
|
||||
|
||||
ty::Param(..) => {
|
||||
|
@ -35,7 +35,6 @@
|
||||
#![feature(const_transmute)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(inner_deref)]
|
||||
#![cfg_attr(windows, feature(libc))]
|
||||
#![feature(never_type)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
@ -102,16 +101,12 @@ pub mod lint;
|
||||
pub mod middle {
|
||||
pub mod expr_use_visitor;
|
||||
pub mod cstore;
|
||||
pub mod dead;
|
||||
pub mod dependency_format;
|
||||
pub mod diagnostic_items;
|
||||
pub mod entry;
|
||||
pub mod exported_symbols;
|
||||
pub mod free_region;
|
||||
pub mod intrinsicck;
|
||||
pub mod lib_features;
|
||||
pub mod lang_items;
|
||||
pub mod liveness;
|
||||
pub mod mem_categorization;
|
||||
pub mod privacy;
|
||||
pub mod reachable;
|
||||
|
@ -15,7 +15,7 @@ use crate::ty::layout::VariantIdx;
|
||||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::ty::{
|
||||
self, AdtDef, CanonicalUserTypeAnnotations, GeneratorSubsts, Region, Ty, TyCtxt,
|
||||
self, AdtDef, CanonicalUserTypeAnnotations, Region, Ty, TyCtxt,
|
||||
UserTypeAnnotationIndex,
|
||||
};
|
||||
|
||||
@ -2189,7 +2189,7 @@ pub enum AggregateKind<'tcx> {
|
||||
Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
|
||||
|
||||
Closure(DefId, SubstsRef<'tcx>),
|
||||
Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
|
||||
Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
|
||||
|
@ -197,7 +197,7 @@ impl<'tcx> Rvalue<'tcx> {
|
||||
let ty = place.ty(local_decls, tcx).ty;
|
||||
match ty.kind {
|
||||
ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx),
|
||||
ty::Generator(_, substs, _) => substs.discr_ty(tcx),
|
||||
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
|
||||
_ => {
|
||||
// This can only be `0`, for now, so `u8` will suffice.
|
||||
tcx.types.u8
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::ty::subst::SubstsRef;
|
||||
use crate::ty::{CanonicalUserTypeAnnotation, GeneratorSubsts, Ty};
|
||||
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
|
||||
use crate::mir::*;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -230,12 +230,6 @@ macro_rules! make_mir_visitor {
|
||||
self.super_substs(substs);
|
||||
}
|
||||
|
||||
fn visit_generator_substs(&mut self,
|
||||
substs: & $($mutability)? GeneratorSubsts<'tcx>,
|
||||
_: Location) {
|
||||
self.super_generator_substs(substs);
|
||||
}
|
||||
|
||||
fn visit_local_decl(&mut self,
|
||||
local: Local,
|
||||
local_decl: & $($mutability)? LocalDecl<'tcx>) {
|
||||
@ -628,7 +622,7 @@ macro_rules! make_mir_visitor {
|
||||
generator_substs,
|
||||
_movability,
|
||||
) => {
|
||||
self.visit_generator_substs(generator_substs, location);
|
||||
self.visit_substs(generator_substs, location);
|
||||
}
|
||||
}
|
||||
|
||||
@ -846,10 +840,6 @@ macro_rules! make_mir_visitor {
|
||||
fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
|
||||
}
|
||||
|
||||
fn super_generator_substs(&mut self,
|
||||
_substs: & $($mutability)? GeneratorSubsts<'tcx>) {
|
||||
}
|
||||
|
||||
// Convenience methods
|
||||
|
||||
fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) {
|
||||
|
@ -1345,7 +1345,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
mir_opt_level: usize = (1, parse_uint, [TRACKED],
|
||||
"set the MIR optimization level (0-3, default: 1)"),
|
||||
mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"emit noalias metadata for mutable references (default: yes on LLVM >= 6)"),
|
||||
"emit noalias metadata for mutable references (default: no)"),
|
||||
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||
"dump MIR state to file.
|
||||
`val` is used to select which passes and functions to dump. For example:
|
||||
|
@ -610,7 +610,7 @@ pub struct VtableImplData<'tcx, N> {
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct VtableGeneratorData<'tcx, N> {
|
||||
pub generator_def_id: DefId,
|
||||
pub substs: ty::GeneratorSubsts<'tcx>,
|
||||
pub substs: SubstsRef<'tcx>,
|
||||
/// Nested obligations. This can be non-empty if the generator
|
||||
/// signature contains associated types.
|
||||
pub nested: Vec<N>
|
||||
|
@ -1259,7 +1259,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
|
||||
) -> Progress<'tcx> {
|
||||
let gen_sig = vtable.substs.poly_sig(vtable.generator_def_id, selcx.tcx());
|
||||
let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx());
|
||||
let Normalized {
|
||||
value: gen_sig,
|
||||
obligations
|
||||
|
@ -2761,8 +2761,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
.collect(),
|
||||
|
||||
ty::Generator(def_id, ref substs, _) => {
|
||||
let witness = substs.witness(def_id, self.tcx());
|
||||
let witness = substs.as_generator().witness(def_id, self.tcx());
|
||||
substs
|
||||
.as_generator()
|
||||
.upvar_tys(def_id, self.tcx())
|
||||
.chain(iter::once(witness))
|
||||
.collect()
|
||||
@ -3324,8 +3325,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
)?);
|
||||
|
||||
Ok(VtableGeneratorData {
|
||||
generator_def_id: generator_def_id,
|
||||
substs: substs.clone(),
|
||||
generator_def_id,
|
||||
substs,
|
||||
nested: obligations,
|
||||
})
|
||||
}
|
||||
@ -3911,9 +3912,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
substs: ty::GeneratorSubsts<'tcx>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
) -> ty::PolyTraitRef<'tcx> {
|
||||
let gen_sig = substs.poly_sig(closure_def_id, self.tcx());
|
||||
let gen_sig = substs.as_generator().poly_sig(closure_def_id, self.tcx());
|
||||
|
||||
// (1) Feels icky to skip the binder here, but OTOH we know
|
||||
// that the self-type is an generator type and hence is
|
||||
|
@ -29,7 +29,7 @@ use crate::traits;
|
||||
use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
|
||||
use crate::ty::{self, DefIdTree, Ty, TypeAndMut};
|
||||
use crate::ty::{TyS, TyKind, List};
|
||||
use crate::ty::{AdtKind, AdtDef, GeneratorSubsts, Region, Const};
|
||||
use crate::ty::{AdtKind, AdtDef, Region, Const};
|
||||
use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
|
||||
use crate::ty::RegionKind;
|
||||
use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid};
|
||||
@ -2510,7 +2510,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
#[inline]
|
||||
pub fn mk_generator(self,
|
||||
id: DefId,
|
||||
generator_substs: GeneratorSubsts<'tcx>,
|
||||
generator_substs: SubstsRef<'tcx>,
|
||||
movability: hir::GeneratorMovability)
|
||||
-> Ty<'tcx> {
|
||||
self.mk_ty(Generator(id, generator_substs, movability))
|
||||
|
@ -94,7 +94,7 @@ impl FlagComputation {
|
||||
&ty::Generator(_, ref substs, _) => {
|
||||
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
|
||||
self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
|
||||
self.add_substs(&substs.substs);
|
||||
self.add_substs(substs);
|
||||
}
|
||||
|
||||
&ty::GeneratorWitness(ref ts) => {
|
||||
|
@ -71,7 +71,7 @@ impl<'tcx> Instance<'tcx> {
|
||||
))
|
||||
}
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
let sig = substs.poly_sig(def_id, tcx);
|
||||
let sig = substs.as_generator().poly_sig(def_id, tcx);
|
||||
|
||||
let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
|
||||
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
|
||||
@ -395,7 +395,7 @@ fn resolve_associated_item<'tcx>(
|
||||
traits::VtableGenerator(generator_data) => {
|
||||
Some(Instance {
|
||||
def: ty::InstanceDef::Item(generator_data.generator_def_id),
|
||||
substs: generator_data.substs.substs
|
||||
substs: generator_data.substs
|
||||
})
|
||||
}
|
||||
traits::VtableClosure(closure_data) => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::session::{self, DataTypeKind};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
|
||||
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, subst::SubstsRef};
|
||||
|
||||
use syntax::ast::{self, Ident, IntTy, UintTy};
|
||||
use syntax::attr;
|
||||
@ -15,7 +15,6 @@ use std::ops::Bound;
|
||||
use crate::hir;
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
|
||||
use crate::ty::GeneratorSubsts;
|
||||
use crate::ty::subst::Subst;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
@ -671,7 +670,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
tcx.intern_layout(unit)
|
||||
}
|
||||
|
||||
ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, &substs)?,
|
||||
ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?,
|
||||
|
||||
ty::Closure(def_id, ref substs) => {
|
||||
let tys = substs.as_closure().upvar_tys(def_id, tcx);
|
||||
@ -1406,12 +1405,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
def_id: hir::def_id::DefId,
|
||||
substs: &GeneratorSubsts<'tcx>,
|
||||
substs: SubstsRef<'tcx>,
|
||||
) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> {
|
||||
use SavedLocalEligibility::*;
|
||||
let tcx = self.tcx;
|
||||
|
||||
let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs.substs) };
|
||||
let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs) };
|
||||
|
||||
let info = tcx.generator_layout(def_id);
|
||||
let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info);
|
||||
@ -1419,9 +1418,9 @@ 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.prefix_tys(def_id, tcx).count();
|
||||
let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count();
|
||||
// FIXME(eddyb) set the correct vaidity range for the discriminant.
|
||||
let discr_layout = self.layout_of(substs.discr_ty(tcx))?;
|
||||
let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?;
|
||||
let discr = match &discr_layout.abi {
|
||||
Abi::Scalar(s) => s.clone(),
|
||||
_ => bug!(),
|
||||
@ -1430,7 +1429,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
.map(|local| subst_field(info.field_tys[local]))
|
||||
.map(|ty| tcx.mk_maybe_uninit(ty))
|
||||
.map(|ty| self.layout_of(ty));
|
||||
let prefix_layouts = substs.prefix_tys(def_id, tcx)
|
||||
let prefix_layouts = substs.as_generator().prefix_tys(def_id, tcx)
|
||||
.map(|ty| self.layout_of(ty))
|
||||
.chain(iter::once(Ok(discr_layout)))
|
||||
.chain(promoted_layouts)
|
||||
@ -2153,7 +2152,7 @@ where
|
||||
ty::Generator(def_id, ref substs, _) => {
|
||||
match this.variants {
|
||||
Variants::Single { index } => {
|
||||
substs.state_tys(def_id, tcx)
|
||||
substs.as_generator().state_tys(def_id, tcx)
|
||||
.nth(index.as_usize()).unwrap()
|
||||
.nth(i).unwrap()
|
||||
}
|
||||
@ -2161,7 +2160,7 @@ where
|
||||
if i == discr_index {
|
||||
return discr_layout(discr);
|
||||
}
|
||||
substs.prefix_tys(def_id, tcx).nth(i).unwrap()
|
||||
substs.as_generator().prefix_tys(def_id, tcx).nth(i).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
ty::Generator(def_id, ref substs, _) => {
|
||||
// Same as the closure case
|
||||
for upvar_ty in substs.upvar_tys(def_id, *self) {
|
||||
for upvar_ty in substs.as_generator().upvar_tys(def_id, *self) {
|
||||
self.compute_components(upvar_ty, out);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir::interpret::ConstValue;
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{self, Const, GeneratorSubsts, Instance, Ty, TyCtxt};
|
||||
use rustc::ty::{self, Const, Instance, Ty, TyCtxt};
|
||||
use rustc::{bug, hir};
|
||||
use std::fmt::Write;
|
||||
use std::iter;
|
||||
@ -154,7 +154,7 @@ impl DefPathBasedNames<'tcx> {
|
||||
self.push_type_name(sig.output(), output, debug);
|
||||
}
|
||||
}
|
||||
ty::Generator(def_id, GeneratorSubsts { substs }, _)
|
||||
ty::Generator(def_id, substs, _)
|
||||
| ty::Closure(def_id, substs) => {
|
||||
self.push_def_path(def_id, output);
|
||||
let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
|
||||
|
@ -605,8 +605,8 @@ pub trait PrettyPrinter<'tcx>:
|
||||
}
|
||||
ty::Str => p!(write("str")),
|
||||
ty::Generator(did, substs, movability) => {
|
||||
let upvar_tys = substs.upvar_tys(did, self.tcx());
|
||||
let witness = substs.witness(did, self.tcx());
|
||||
let upvar_tys = substs.as_generator().upvar_tys(did, self.tcx());
|
||||
let witness = substs.as_generator().witness(did, self.tcx());
|
||||
if movability == hir::GeneratorMovability::Movable {
|
||||
p!(write("[generator"));
|
||||
} else {
|
||||
|
@ -163,7 +163,7 @@ pub enum TyKind<'tcx> {
|
||||
|
||||
/// The anonymous type of a generator. Used to represent the type of
|
||||
/// `|a| yield a`.
|
||||
Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
|
||||
Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability),
|
||||
|
||||
/// A type representin the types stored inside a generator.
|
||||
/// This should only appear in GeneratorInteriors.
|
||||
@ -512,7 +512,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
|
||||
/// variant indices.
|
||||
#[inline]
|
||||
pub fn discriminants(
|
||||
&'tcx self,
|
||||
self,
|
||||
def_id: DefId,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> {
|
||||
@ -524,7 +524,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
|
||||
/// Calls `f` with a reference to the name of the enumerator for the given
|
||||
/// variant `v`.
|
||||
#[inline]
|
||||
pub fn variant_name(&self, v: VariantIdx) -> Cow<'static, str> {
|
||||
pub fn variant_name(self, v: VariantIdx) -> Cow<'static, str> {
|
||||
match v.as_usize() {
|
||||
Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME),
|
||||
Self::RETURNED => Cow::from(Self::RETURNED_NAME),
|
||||
@ -570,7 +570,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum UpvarSubsts<'tcx> {
|
||||
Closure(SubstsRef<'tcx>),
|
||||
Generator(GeneratorSubsts<'tcx>),
|
||||
Generator(SubstsRef<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> UpvarSubsts<'tcx> {
|
||||
@ -582,7 +582,7 @@ impl<'tcx> UpvarSubsts<'tcx> {
|
||||
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
|
||||
let upvar_kinds = match self {
|
||||
UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds,
|
||||
UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds,
|
||||
UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds,
|
||||
};
|
||||
upvar_kinds.iter().map(|t| {
|
||||
if let GenericArgKind::Type(ty) = t.unpack() {
|
||||
@ -2109,7 +2109,8 @@ impl<'tcx> TyS<'tcx> {
|
||||
pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
|
||||
match self.kind {
|
||||
TyKind::Adt(adt, _) => Some(adt.variant_range()),
|
||||
TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)),
|
||||
TyKind::Generator(def_id, substs, _) =>
|
||||
Some(substs.as_generator().variant_range(def_id, tcx)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -2126,7 +2127,7 @@ impl<'tcx> TyS<'tcx> {
|
||||
match self.kind {
|
||||
TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)),
|
||||
TyKind::Generator(def_id, substs, _) =>
|
||||
Some(substs.discriminant_for_variant(def_id, tcx, variant_index)),
|
||||
Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -2149,7 +2150,7 @@ impl<'tcx> TyS<'tcx> {
|
||||
out.extend(substs.regions())
|
||||
}
|
||||
Closure(_, ref substs ) |
|
||||
Generator(_, GeneratorSubsts { ref substs }, _) => {
|
||||
Generator(_, ref substs, _) => {
|
||||
out.extend(substs.regions())
|
||||
}
|
||||
Projection(ref data) | UnnormalizedProjection(ref data) => {
|
||||
|
@ -5,7 +5,7 @@ use crate::infer::canonical::Canonical;
|
||||
use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst};
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use crate::ty::sty::ClosureSubsts;
|
||||
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
|
||||
|
||||
use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
@ -194,6 +194,14 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Interpret these substitutions as the substitutions of a generator type.
|
||||
/// Closure substitutions have a particular structure controlled by the
|
||||
/// compiler that encodes information like the signature and generator kind;
|
||||
/// see `ty::GeneratorSubsts` struct for more comments.
|
||||
pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> {
|
||||
GeneratorSubsts { substs: self }
|
||||
}
|
||||
|
||||
/// Creates a `InternalSubsts` that maps each generic parameter to itself.
|
||||
pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
|
||||
Self::for_item(tcx, def_id, |param, _| {
|
||||
|
@ -110,12 +110,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
|
||||
ty::Adt(_, substs) | ty::Opaque(_, substs) => {
|
||||
stack.extend(substs.types().rev());
|
||||
}
|
||||
ty::Closure(_, ref substs) => {
|
||||
ty::Closure(_, ref substs)
|
||||
| ty::Generator(_, ref substs, _) => {
|
||||
stack.extend(substs.types().rev());
|
||||
}
|
||||
ty::Generator(_, ref substs, _) => {
|
||||
stack.extend(substs.substs.types().rev());
|
||||
}
|
||||
ty::GeneratorWitness(ts) => {
|
||||
stack.extend(ts.skip_binder().iter().cloned().rev());
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
|
||||
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx,
|
||||
llfn,
|
||||
"entry\0".as_ptr() as *const _);
|
||||
"entry\0".as_ptr().cast());
|
||||
|
||||
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
||||
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
||||
@ -80,7 +80,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
|
||||
args.as_ptr(),
|
||||
args.len() as c_uint,
|
||||
None,
|
||||
"\0".as_ptr() as *const _);
|
||||
"\0".as_ptr().cast());
|
||||
llvm::LLVMSetTailCall(ret, True);
|
||||
if output.is_some() {
|
||||
llvm::LLVMBuildRet(llbuilder, ret);
|
||||
|
@ -546,7 +546,7 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
llvm::LLVMRustAddAnalysisPasses(module.module_llvm.tm, pm, module.module_llvm.llmod());
|
||||
|
||||
if config.verify_llvm_ir {
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
|
||||
llvm::LLVMRustAddPass(pm, pass.unwrap());
|
||||
}
|
||||
|
||||
@ -581,12 +581,12 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
// We always generate bitcode through ThinLTOBuffers,
|
||||
// which do not support anonymous globals
|
||||
if config.bitcode_needed() {
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr() as *const _);
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast());
|
||||
llvm::LLVMRustAddPass(pm, pass.unwrap());
|
||||
}
|
||||
|
||||
if config.verify_llvm_ir {
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
|
||||
let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
|
||||
llvm::LLVMRustAddPass(pm, pass.unwrap());
|
||||
}
|
||||
|
||||
|
@ -221,8 +221,8 @@ impl<'a> DiagnosticHandlers<'a> {
|
||||
llcx: &'a llvm::Context) -> Self {
|
||||
let data = Box::into_raw(Box::new((cgcx, handler)));
|
||||
unsafe {
|
||||
llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _);
|
||||
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data as *mut _);
|
||||
llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast());
|
||||
llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast());
|
||||
}
|
||||
DiagnosticHandlers { data, llcx }
|
||||
}
|
||||
@ -672,7 +672,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
"rustc.embedded.module\0".as_ptr() as *const _,
|
||||
"rustc.embedded.module\0".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
|
||||
@ -684,7 +684,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
} else {
|
||||
".llvmbc\0"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
|
||||
@ -692,7 +692,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
"rustc.embedded.cmdline\0".as_ptr() as *const _,
|
||||
"rustc.embedded.cmdline\0".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if is_apple {
|
||||
@ -700,7 +700,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
} else {
|
||||
".llvmcmd\0"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
}
|
||||
|
||||
@ -842,7 +842,7 @@ fn create_msvc_imps(
|
||||
for (imp_name, val) in globals {
|
||||
let imp = llvm::LLVMAddGlobal(llmod,
|
||||
i8p_ty,
|
||||
imp_name.as_ptr() as *const _);
|
||||
imp_name.as_ptr().cast());
|
||||
llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty));
|
||||
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
|
||||
}
|
||||
|
@ -488,7 +488,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
||||
if let Some(section) = attrs.link_section {
|
||||
let section = llvm::LLVMMDStringInContext(
|
||||
self.llcx,
|
||||
section.as_str().as_ptr() as *const _,
|
||||
section.as_str().as_ptr().cast(),
|
||||
section.as_str().len() as c_uint,
|
||||
);
|
||||
assert!(alloc.relocations().is_empty());
|
||||
@ -500,14 +500,14 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
||||
0..alloc.len());
|
||||
let alloc = llvm::LLVMMDStringInContext(
|
||||
self.llcx,
|
||||
bytes.as_ptr() as *const _,
|
||||
bytes.as_ptr().cast(),
|
||||
bytes.len() as c_uint,
|
||||
);
|
||||
let data = [section, alloc];
|
||||
let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
self.llmod,
|
||||
"wasm.custom_sections\0".as_ptr() as *const _,
|
||||
"wasm.custom_sections\0".as_ptr().cast(),
|
||||
meta,
|
||||
);
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ pub unsafe fn create_module(
|
||||
// If skipping the PLT is enabled, we need to add some module metadata
|
||||
// to ensure intrinsic calls don't use it.
|
||||
if !sess.needs_plt() {
|
||||
let avoid_plt = "RtLibUseGOT\0".as_ptr() as *const _;
|
||||
let avoid_plt = "RtLibUseGOT\0".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
|
||||
|
||||
let section_var = unsafe {
|
||||
llvm::LLVMGetNamedGlobal(cx.llmod,
|
||||
c_section_var_name.as_ptr() as *const _)
|
||||
c_section_var_name.as_ptr().cast())
|
||||
};
|
||||
|
||||
section_var.unwrap_or_else(|| {
|
||||
@ -52,7 +52,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>)
|
||||
llvm_type).unwrap_or_else(||{
|
||||
bug!("symbol `{}` is already defined", section_var_name)
|
||||
});
|
||||
llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
|
||||
llvm::LLVMSetSection(section_var, section_name.as_ptr().cast());
|
||||
llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
|
||||
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
||||
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
|
||||
|
@ -30,7 +30,7 @@ use rustc::ty::Instance;
|
||||
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf,
|
||||
PrimitiveExt, Size, TyLayout, VariantIdx};
|
||||
use rustc::ty::subst::GenericArgKind;
|
||||
use rustc::ty::subst::{GenericArgKind, SubstsRef};
|
||||
use rustc::session::config::{self, DebugInfo};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_fs_util::path_to_c_string;
|
||||
@ -692,9 +692,10 @@ pub fn type_metadata(
|
||||
Some(containing_scope)).finalize(cx)
|
||||
}
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
let upvar_tys : Vec<_> = substs.prefix_tys(def_id, cx.tcx).map(|t| {
|
||||
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
|
||||
}).collect();
|
||||
let upvar_tys : Vec<_> = substs
|
||||
.as_generator().prefix_tys(def_id, cx.tcx).map(|t| {
|
||||
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
|
||||
}).collect();
|
||||
prepare_enum_metadata(cx,
|
||||
t,
|
||||
def_id,
|
||||
@ -960,9 +961,9 @@ pub fn compile_unit_metadata(
|
||||
file_metadata,
|
||||
producer.as_ptr(),
|
||||
tcx.sess.opts.optimize != config::OptLevel::No,
|
||||
flags.as_ptr() as *const _,
|
||||
flags.as_ptr().cast(),
|
||||
0,
|
||||
split_name.as_ptr() as *const _,
|
||||
split_name.as_ptr().cast(),
|
||||
kind);
|
||||
|
||||
if tcx.sess.opts.debugging_opts.profile {
|
||||
@ -991,7 +992,7 @@ pub fn compile_unit_metadata(
|
||||
if tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
|
||||
let name_metadata = llvm::LLVMMDStringInContext(
|
||||
debug_context.llcontext,
|
||||
rustc_producer.as_ptr() as *const _,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
rustc_producer.as_bytes().len() as c_uint,
|
||||
);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
@ -1338,7 +1339,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]),
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
let generator_layout = cx.tcx.generator_layout(*def_id);
|
||||
VariantInfo::Generator(*substs, generator_layout, index)
|
||||
VariantInfo::Generator(substs, generator_layout, index)
|
||||
}
|
||||
_ => bug!(),
|
||||
}
|
||||
@ -1611,7 +1612,7 @@ enum EnumDiscriminantInfo<'ll> {
|
||||
#[derive(Copy, Clone)]
|
||||
enum VariantInfo<'tcx> {
|
||||
Adt(&'tcx ty::VariantDef),
|
||||
Generator(ty::GeneratorSubsts<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx),
|
||||
Generator(SubstsRef<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx),
|
||||
}
|
||||
|
||||
impl<'tcx> VariantInfo<'tcx> {
|
||||
@ -1619,7 +1620,7 @@ impl<'tcx> VariantInfo<'tcx> {
|
||||
match self {
|
||||
VariantInfo::Adt(variant) => f(&variant.ident.as_str()),
|
||||
VariantInfo::Generator(substs, _, variant_index) =>
|
||||
f(&substs.variant_name(*variant_index)),
|
||||
f(&substs.as_generator().variant_name(*variant_index)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1763,9 +1764,10 @@ fn prepare_enum_metadata(
|
||||
})
|
||||
.collect(),
|
||||
ty::Generator(_, substs, _) => substs
|
||||
.as_generator()
|
||||
.variant_range(enum_def_id, cx.tcx)
|
||||
.map(|variant_index| {
|
||||
let name = SmallCStr::new(&substs.variant_name(variant_index));
|
||||
let name = SmallCStr::new(&substs.as_generator().variant_name(variant_index));
|
||||
unsafe {
|
||||
Some(llvm::LLVMRustDIBuilderCreateEnumerator(
|
||||
DIB(cx),
|
||||
|
@ -127,20 +127,20 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
|
||||
if cx.sess().target.target.options.is_like_osx ||
|
||||
cx.sess().target.target.options.is_like_android {
|
||||
llvm::LLVMRustAddModuleFlag(cx.llmod,
|
||||
"Dwarf Version\0".as_ptr() as *const _,
|
||||
"Dwarf Version\0".as_ptr().cast(),
|
||||
2)
|
||||
}
|
||||
|
||||
// Indicate that we want CodeView debug information on MSVC
|
||||
if cx.sess().target.target.options.is_like_msvc {
|
||||
llvm::LLVMRustAddModuleFlag(cx.llmod,
|
||||
"CodeView\0".as_ptr() as *const _,
|
||||
"CodeView\0".as_ptr().cast(),
|
||||
1)
|
||||
}
|
||||
|
||||
// Prevent bitcode readers from deleting the debug info.
|
||||
let ptr = "Debug Info Version\0".as_ptr();
|
||||
llvm::LLVMRustAddModuleFlag(cx.llmod, ptr as *const _,
|
||||
llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(),
|
||||
llvm::LLVMRustDebugMetadataVersion());
|
||||
};
|
||||
}
|
||||
|
@ -257,7 +257,8 @@ pub fn target_feature_whitelist(sess: &Session)
|
||||
"hexagon" => HEXAGON_WHITELIST,
|
||||
"mips" | "mips64" => MIPS_WHITELIST,
|
||||
"powerpc" | "powerpc64" => POWERPC_WHITELIST,
|
||||
"wasm32" => WASM_WHITELIST,
|
||||
// wasm32 on emscripten does not support these target features
|
||||
"wasm32" if !sess.target.target.options.is_like_emscripten => WASM_WHITELIST,
|
||||
_ => &[],
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
if let (&ty::Generator(_, substs, _), &layout::Variants::Single { index })
|
||||
= (&layout.ty.kind, &layout.variants)
|
||||
{
|
||||
write!(&mut name, "::{}", substs.variant_name(index)).unwrap();
|
||||
write!(&mut name, "::{}", substs.as_generator().variant_name(index)).unwrap();
|
||||
}
|
||||
Some(name)
|
||||
}
|
||||
|
@ -142,12 +142,15 @@ impl ModuleConfig {
|
||||
// Copy what clang does by turning on loop vectorization at O2 and
|
||||
// slp vectorization at O3. Otherwise configure other optimization aspects
|
||||
// of this pass manager builder.
|
||||
// Turn off vectorization for emscripten, as it's not very well supported.
|
||||
self.vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
|
||||
(sess.opts.optimize == config::OptLevel::Default ||
|
||||
sess.opts.optimize == config::OptLevel::Aggressive);
|
||||
sess.opts.optimize == config::OptLevel::Aggressive) &&
|
||||
!sess.target.target.options.is_like_emscripten;
|
||||
|
||||
self.vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
|
||||
sess.opts.optimize == config::OptLevel::Aggressive;
|
||||
sess.opts.optimize == config::OptLevel::Aggressive &&
|
||||
!sess.target.target.options.is_like_emscripten;
|
||||
|
||||
// Some targets (namely, NVPTX) interact badly with the MergeFunctions
|
||||
// pass. This is because MergeFunctions can generate new function calls
|
||||
|
@ -636,7 +636,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
ty::Generator(def_id, substs, _) => (def_id, substs),
|
||||
_ => bug!("generator layout without generator substs"),
|
||||
};
|
||||
let state_tys = gen_substs.state_tys(def_id, tcx);
|
||||
let state_tys = gen_substs.as_generator().state_tys(def_id, tcx);
|
||||
|
||||
generator_layout.variant_fields.iter()
|
||||
.zip(state_tys)
|
||||
|
@ -225,7 +225,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> {
|
||||
ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) |
|
||||
ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) |
|
||||
ty::Closure(def_id, substs) |
|
||||
ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
self.print_def_path(def_id, substs)
|
||||
}
|
||||
_ => self.pretty_print_type(ty),
|
||||
|
@ -415,7 +415,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) |
|
||||
ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) |
|
||||
ty::Closure(def_id, substs) |
|
||||
ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
self = self.print_def_path(def_id, substs)?;
|
||||
}
|
||||
ty::Foreign(def_id) => {
|
||||
|
@ -298,9 +298,31 @@ impl Diagnostic {
|
||||
/// * may contain a name of a function, variable, or type, but not whole expressions
|
||||
///
|
||||
/// See `CodeSuggestion` for more information.
|
||||
pub fn span_suggestion(&mut self, sp: Span, msg: &str,
|
||||
suggestion: String,
|
||||
applicability: Applicability) -> &mut Self {
|
||||
pub fn span_suggestion(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
msg: &str,
|
||||
suggestion: String,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self {
|
||||
self.span_suggestion_with_style(
|
||||
sp,
|
||||
msg,
|
||||
suggestion,
|
||||
applicability,
|
||||
SuggestionStyle::ShowCode,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn span_suggestion_with_style(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
msg: &str,
|
||||
suggestion: String,
|
||||
applicability: Applicability,
|
||||
style: SuggestionStyle,
|
||||
) -> &mut Self {
|
||||
self.suggestions.push(CodeSuggestion {
|
||||
substitutions: vec![Substitution {
|
||||
parts: vec![SubstitutionPart {
|
||||
@ -309,16 +331,37 @@ impl Diagnostic {
|
||||
}],
|
||||
}],
|
||||
msg: msg.to_owned(),
|
||||
style: SuggestionStyle::ShowCode,
|
||||
style,
|
||||
applicability,
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
pub fn span_suggestion_verbose(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
msg: &str,
|
||||
suggestion: String,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self {
|
||||
self.span_suggestion_with_style(
|
||||
sp,
|
||||
msg,
|
||||
suggestion,
|
||||
applicability,
|
||||
SuggestionStyle::ShowAlways,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
/// Prints out a message with multiple suggested edits of the code.
|
||||
pub fn span_suggestions(&mut self, sp: Span, msg: &str,
|
||||
suggestions: impl Iterator<Item = String>, applicability: Applicability) -> &mut Self
|
||||
{
|
||||
pub fn span_suggestions(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
msg: &str,
|
||||
suggestions: impl Iterator<Item = String>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self {
|
||||
self.suggestions.push(CodeSuggestion {
|
||||
substitutions: suggestions.map(|snippet| Substitution {
|
||||
parts: vec![SubstitutionPart {
|
||||
@ -340,17 +383,13 @@ impl Diagnostic {
|
||||
pub fn span_suggestion_short(
|
||||
&mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability
|
||||
) -> &mut Self {
|
||||
self.suggestions.push(CodeSuggestion {
|
||||
substitutions: vec![Substitution {
|
||||
parts: vec![SubstitutionPart {
|
||||
snippet: suggestion,
|
||||
span: sp,
|
||||
}],
|
||||
}],
|
||||
msg: msg.to_owned(),
|
||||
style: SuggestionStyle::HideCodeInline,
|
||||
self.span_suggestion_with_style(
|
||||
sp,
|
||||
msg,
|
||||
suggestion,
|
||||
applicability,
|
||||
});
|
||||
SuggestionStyle::HideCodeInline,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
@ -363,17 +402,13 @@ impl Diagnostic {
|
||||
pub fn span_suggestion_hidden(
|
||||
&mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability
|
||||
) -> &mut Self {
|
||||
self.suggestions.push(CodeSuggestion {
|
||||
substitutions: vec![Substitution {
|
||||
parts: vec![SubstitutionPart {
|
||||
snippet: suggestion,
|
||||
span: sp,
|
||||
}],
|
||||
}],
|
||||
msg: msg.to_owned(),
|
||||
style: SuggestionStyle::HideCodeAlways,
|
||||
self.span_suggestion_with_style(
|
||||
sp,
|
||||
msg,
|
||||
suggestion,
|
||||
applicability,
|
||||
});
|
||||
SuggestionStyle::HideCodeAlways,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
@ -384,17 +419,13 @@ impl Diagnostic {
|
||||
pub fn tool_only_span_suggestion(
|
||||
&mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability
|
||||
) -> &mut Self {
|
||||
self.suggestions.push(CodeSuggestion {
|
||||
substitutions: vec![Substitution {
|
||||
parts: vec![SubstitutionPart {
|
||||
snippet: suggestion,
|
||||
span: sp,
|
||||
}],
|
||||
}],
|
||||
msg: msg.to_owned(),
|
||||
style: SuggestionStyle::CompletelyHidden,
|
||||
self.span_suggestion_with_style(
|
||||
sp,
|
||||
msg,
|
||||
suggestion,
|
||||
applicability,
|
||||
});
|
||||
SuggestionStyle::CompletelyHidden,
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -218,10 +218,14 @@ pub trait Emitter {
|
||||
sugg.msg.split_whitespace().count() < 10 &&
|
||||
// don't display multiline suggestions as labels
|
||||
!sugg.substitutions[0].parts[0].snippet.contains('\n') &&
|
||||
// when this style is set we want the suggestion to be a message, not inline
|
||||
sugg.style != SuggestionStyle::HideCodeAlways &&
|
||||
// trivial suggestion for tooling's sake, never shown
|
||||
sugg.style != SuggestionStyle::CompletelyHidden
|
||||
![
|
||||
// when this style is set we want the suggestion to be a message, not inline
|
||||
SuggestionStyle::HideCodeAlways,
|
||||
// trivial suggestion for tooling's sake, never shown
|
||||
SuggestionStyle::CompletelyHidden,
|
||||
// subtle suggestion, never shown inline
|
||||
SuggestionStyle::ShowAlways,
|
||||
].contains(&sugg.style)
|
||||
{
|
||||
let substitution = &sugg.substitutions[0].parts[0].snippet.trim();
|
||||
let msg = if substitution.len() == 0 || sugg.style.hide_inline() {
|
||||
|
@ -81,6 +81,8 @@ pub enum SuggestionStyle {
|
||||
/// This will *not* show the code if the suggestion is inline *and* the suggested code is
|
||||
/// empty.
|
||||
ShowCode,
|
||||
/// Always show the suggested code independently.
|
||||
ShowAlways,
|
||||
}
|
||||
|
||||
impl SuggestionStyle {
|
||||
|
@ -780,13 +780,10 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
|
||||
ty::provide(providers);
|
||||
traits::provide(providers);
|
||||
stability::provide(providers);
|
||||
middle::intrinsicck::provide(providers);
|
||||
middle::liveness::provide(providers);
|
||||
reachable::provide(providers);
|
||||
rustc_passes::provide(providers);
|
||||
rustc_traits::provide(providers);
|
||||
middle::region::provide(providers);
|
||||
middle::entry::provide(providers);
|
||||
cstore::provide(providers);
|
||||
lint::provide(providers);
|
||||
rustc_lint::provide(providers);
|
||||
@ -892,7 +889,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
|
||||
time(sess, "misc checking 1", || {
|
||||
parallel!({
|
||||
entry_point = time(sess, "looking for entry point", || {
|
||||
middle::entry::find_entry_point(tcx)
|
||||
rustc_passes::entry::find_entry_point(tcx)
|
||||
});
|
||||
|
||||
time(sess, "looking for plugin registrar", || {
|
||||
@ -973,7 +970,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
|
||||
tcx.ensure().check_private_in_public(LOCAL_CRATE);
|
||||
});
|
||||
}, {
|
||||
time(sess, "death checking", || middle::dead::check_crate(tcx));
|
||||
time(sess, "death checking", || rustc_passes::dead::check_crate(tcx));
|
||||
}, {
|
||||
time(sess, "unused lib feature checking", || {
|
||||
stability::check_unused_or_stable_features(tcx)
|
||||
|
@ -631,6 +631,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
};
|
||||
}
|
||||
|
||||
let is_non_exhaustive =
|
||||
def.non_enum_variant().is_field_list_non_exhaustive();
|
||||
if is_non_exhaustive && !def.did.is_local() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "this struct is non-exhaustive",
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
|
||||
if def.non_enum_variant().fields.is_empty() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
@ -730,8 +740,25 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
if def.is_variant_list_non_exhaustive() && !def.did.is_local() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "this enum is non-exhaustive",
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
|
||||
// Check the contained variants.
|
||||
for variant in &def.variants {
|
||||
let is_non_exhaustive = variant.is_field_list_non_exhaustive();
|
||||
if is_non_exhaustive && !variant.def_id.is_local() {
|
||||
return FfiUnsafe {
|
||||
ty,
|
||||
reason: "this enum has non-exhaustive variants",
|
||||
help: None,
|
||||
};
|
||||
}
|
||||
|
||||
for field in &variant.fields {
|
||||
let field_ty = cx.normalize_erasing_regions(
|
||||
ParamEnv::reveal_all(),
|
||||
|
@ -919,7 +919,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
self.entry_unless_proc_macro(id)
|
||||
.and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx))))
|
||||
.unwrap_or_else(|| {
|
||||
bug!("get_optimized_mir: missing MIR for `{:?}", self.local_def_id(id))
|
||||
bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1944,14 +1944,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
self.is_mutable(place.as_ref(), is_local_mutation_allowed),
|
||||
self.errors_buffer.is_empty()
|
||||
) {
|
||||
// rust-lang/rust#46908: In pure NLL mode this code path should
|
||||
// be unreachable (and thus we signal an ICE in the else branch here).
|
||||
span_bug!(
|
||||
span,
|
||||
// rust-lang/rust#46908: In pure NLL mode this code path should be
|
||||
// unreachable, but we use `delay_span_bug` because we can hit this when
|
||||
// dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug`
|
||||
// enabled. We don't want to ICE for that case, as other errors will have
|
||||
// been emitted (#52262).
|
||||
self.infcx.tcx.sess.delay_span_bug(span, &format!(
|
||||
"Accessing `{:?}` with the kind `{:?}` shouldn't be possible",
|
||||
place,
|
||||
kind,
|
||||
);
|
||||
));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use rustc::mir::{
|
||||
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
|
||||
};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty};
|
||||
use rustc::ty::{self, RegionVid, Ty};
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
|
||||
pub(super) fn generate_constraints<'cx, 'tcx>(
|
||||
@ -91,13 +91,6 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
|
||||
self.super_ty(ty);
|
||||
}
|
||||
|
||||
/// We sometimes have `generator_substs` within an rvalue, or within a
|
||||
/// call. Make them live at the location where they appear.
|
||||
fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
|
||||
self.add_regular_live_constraint(*substs, location);
|
||||
self.super_generator_substs(substs);
|
||||
}
|
||||
|
||||
fn visit_statement(
|
||||
&mut self,
|
||||
statement: &Statement<'tcx>,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
use rustc::ty::{self, GeneratorSubsts, Ty, TypeFoldable};
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use rustc::mir::{Location, Body, Promoted};
|
||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
@ -82,18 +82,4 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
|
||||
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) {
|
||||
*constant = self.renumber_regions(&*constant);
|
||||
}
|
||||
|
||||
fn visit_generator_substs(&mut self,
|
||||
substs: &mut GeneratorSubsts<'tcx>,
|
||||
location: Location) {
|
||||
debug!(
|
||||
"visit_generator_substs(substs={:?}, location={:?})",
|
||||
substs,
|
||||
location,
|
||||
);
|
||||
|
||||
*substs = self.renumber_regions(substs);
|
||||
|
||||
debug!("visit_generator_substs: substs={:?}", substs);
|
||||
}
|
||||
}
|
||||
|
@ -759,13 +759,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
PlaceTy { ty, variant_index: Some(variant_index) } => match ty.kind {
|
||||
ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
let mut variants = substs.state_tys(def_id, tcx);
|
||||
let mut variants = substs.as_generator().state_tys(def_id, tcx);
|
||||
let mut variant = match variants.nth(variant_index.into()) {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
bug!("variant_index of generator out of range: {:?}/{:?}",
|
||||
variant_index,
|
||||
substs.state_tys(def_id, tcx).count())
|
||||
substs.as_generator().state_tys(def_id, tcx).count())
|
||||
}
|
||||
};
|
||||
return match variant.nth(field.index()) {
|
||||
@ -791,10 +791,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
// Only prefix fields (upvars and current state) are
|
||||
// accessible without a variant index.
|
||||
return match substs.prefix_tys(def_id, tcx).nth(field.index()) {
|
||||
return match substs.as_generator().prefix_tys(def_id, tcx).nth(field.index()) {
|
||||
Some(ty) => Ok(ty),
|
||||
None => Err(FieldAccessError::OutOfRange {
|
||||
field_count: substs.prefix_tys(def_id, tcx).count(),
|
||||
field_count: substs.as_generator().prefix_tys(def_id, tcx).count(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -1963,10 +1963,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// It doesn't make sense to look at a field beyond the prefix;
|
||||
// these require a variant index, and are not initialized in
|
||||
// aggregate rvalues.
|
||||
match substs.prefix_tys(def_id, tcx).nth(field_index) {
|
||||
match substs.as_generator().prefix_tys(def_id, tcx).nth(field_index) {
|
||||
Some(ty) => Ok(ty),
|
||||
None => Err(FieldAccessError::OutOfRange {
|
||||
field_count: substs.prefix_tys(def_id, tcx).count(),
|
||||
field_count: substs.as_generator().prefix_tys(def_id, tcx).count(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -2541,7 +2541,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// these extra requirements are basically like where
|
||||
// clauses on the struct.
|
||||
AggregateKind::Closure(def_id, substs)
|
||||
| AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
|
||||
| AggregateKind::Generator(def_id, substs, _) => {
|
||||
self.prove_closure_bounds(tcx, *def_id, substs, location)
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::subst::{InternalSubsts, SubstsRef, Subst};
|
||||
use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty, TyCtxt};
|
||||
use rustc::ty::{self, RegionVid, Ty, TyCtxt};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
@ -90,7 +90,7 @@ pub enum DefiningTy<'tcx> {
|
||||
/// The MIR is a generator. The signature is that generators take
|
||||
/// no parameters and return the result of
|
||||
/// `ClosureSubsts::generator_return_ty`.
|
||||
Generator(DefId, ty::GeneratorSubsts<'tcx>, hir::GeneratorMovability),
|
||||
Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability),
|
||||
|
||||
/// The MIR is a fn item with the given `DefId` and substs. The signature
|
||||
/// of the function can be bound then with the `fn_sig` query.
|
||||
@ -113,7 +113,7 @@ impl<'tcx> DefiningTy<'tcx> {
|
||||
substs.as_closure().upvar_tys(def_id, tcx)
|
||||
),
|
||||
DefiningTy::Generator(def_id, substs, _) => {
|
||||
Either::Right(Either::Left(substs.upvar_tys(def_id, tcx)))
|
||||
Either::Right(Either::Left(substs.as_generator().upvar_tys(def_id, tcx)))
|
||||
}
|
||||
DefiningTy::FnDef(..) | DefiningTy::Const(..) => {
|
||||
Either::Right(Either::Right(iter::empty()))
|
||||
@ -334,7 +334,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
||||
err.note(&format!(
|
||||
"defining type: {:?} with generator substs {:#?}",
|
||||
def_id,
|
||||
&substs.substs[..]
|
||||
&substs[..]
|
||||
));
|
||||
|
||||
// FIXME: As above, we'd like to print out the region
|
||||
@ -470,7 +470,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
|
||||
let yield_ty = match defining_ty {
|
||||
DefiningTy::Generator(def_id, substs, _) => {
|
||||
Some(substs.yield_ty(def_id, self.infcx.tcx))
|
||||
Some(substs.as_generator().yield_ty(def_id, self.infcx.tcx))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
@ -549,7 +549,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id);
|
||||
let fr_substs = match defining_ty {
|
||||
DefiningTy::Closure(_, ref substs)
|
||||
| DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => {
|
||||
| DefiningTy::Generator(_, ref substs, _) => {
|
||||
// In the case of closures, we rely on the fact that
|
||||
// the first N elements in the ClosureSubsts are
|
||||
// inherited from the `closure_base_def_id`.
|
||||
@ -612,7 +612,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
|
||||
DefiningTy::Generator(def_id, substs, movability) => {
|
||||
assert_eq!(self.mir_def_id, def_id);
|
||||
let output = substs.return_ty(def_id, tcx);
|
||||
let output = substs.as_generator().return_ty(def_id, tcx);
|
||||
let generator_ty = tcx.mk_generator(def_id, substs, movability);
|
||||
let inputs_and_output = self.infcx.tcx.intern_type_list(&[generator_ty, output]);
|
||||
ty::Binder::dummy(inputs_and_output)
|
||||
|
@ -146,7 +146,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
|
||||
let (yield_ty, return_ty) = if body.generator_kind.is_some() {
|
||||
let gen_sig = match ty.kind {
|
||||
ty::Generator(gen_def_id, gen_substs, ..) =>
|
||||
gen_substs.sig(gen_def_id, tcx),
|
||||
gen_substs.as_generator().sig(gen_def_id, tcx),
|
||||
_ =>
|
||||
span_bug!(tcx.hir().span(id),
|
||||
"generator w/o generator type: {:?}", ty),
|
||||
|
@ -68,8 +68,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||
| ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs })
|
||||
| ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs })
|
||||
| ty::Closure(def_id, substs)
|
||||
| ty::Generator(def_id, ty::GeneratorSubsts { substs }, _)
|
||||
=> self.print_def_path(def_id, substs),
|
||||
| ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
|
||||
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
|
||||
|
||||
ty::GeneratorWitness(_) => {
|
||||
|
@ -664,14 +664,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
bits_discr
|
||||
};
|
||||
// Make sure we catch invalid discriminants
|
||||
let index = match &rval.layout.ty.kind {
|
||||
let index = match rval.layout.ty.kind {
|
||||
ty::Adt(adt, _) => adt
|
||||
.discriminants(self.tcx.tcx)
|
||||
.find(|(_, var)| var.val == real_discr),
|
||||
ty::Generator(def_id, substs, _) => substs
|
||||
.discriminants(*def_id, self.tcx.tcx)
|
||||
.find(|(_, var)| var.val == real_discr),
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
let substs = substs.as_generator();
|
||||
substs
|
||||
.discriminants(def_id, self.tcx.tcx)
|
||||
.find(|(_, var)| var.val == real_discr)
|
||||
}
|
||||
_ => bug!("tagged layout for non-adt non-generator"),
|
||||
|
||||
}.ok_or_else(
|
||||
|| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag()))
|
||||
)?;
|
||||
|
@ -594,6 +594,13 @@ where
|
||||
StaticKind::Promoted(promoted, promoted_substs) => {
|
||||
let substs = self.subst_from_frame_and_normalize_erasing_regions(promoted_substs);
|
||||
let instance = ty::Instance::new(place_static.def_id, substs);
|
||||
|
||||
// Even after getting `substs` from the frame, this instance may still be
|
||||
// polymorphic because `ConstProp` will try to promote polymorphic MIR.
|
||||
if instance.needs_subst() {
|
||||
throw_inval!(TooGeneric);
|
||||
}
|
||||
|
||||
self.const_eval_raw(GlobalId {
|
||||
instance,
|
||||
promoted: Some(promoted),
|
||||
|
@ -169,7 +169,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||
// Check if this is a generator, if so, return the drop glue for it
|
||||
if let Some(&ty::TyS { kind: ty::Generator(gen_def_id, substs, _), .. }) = ty {
|
||||
let body = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap();
|
||||
return body.subst(tcx, substs.substs);
|
||||
return body.subst(tcx, substs);
|
||||
}
|
||||
|
||||
let substs = if let Some(ty) = ty {
|
||||
|
@ -39,12 +39,6 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> {
|
||||
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) {
|
||||
*substs = self.tcx.erase_regions(substs);
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self,
|
||||
statement: &mut Statement<'tcx>,
|
||||
location: Location) {
|
||||
self.super_statement(statement, location);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EraseRegions;
|
||||
|
@ -1126,6 +1126,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
|
||||
// Get the interior types and substs which typeck computed
|
||||
let (upvars, interior, discr_ty, movable) = match gen_ty.kind {
|
||||
ty::Generator(_, substs, movability) => {
|
||||
let substs = substs.as_generator();
|
||||
(substs.upvar_tys(def_id, tcx).collect(),
|
||||
substs.witness(def_id, tcx),
|
||||
substs.discr_ty(tcx),
|
||||
|
@ -798,7 +798,7 @@ where
|
||||
// It effetively only contains upvars until the generator transformation runs.
|
||||
// See librustc_body/transform/generator.rs for more details.
|
||||
ty::Generator(def_id, substs, _) => {
|
||||
let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
|
||||
let tys : Vec<_> = substs.as_generator().upvar_tys(def_id, self.tcx()).collect();
|
||||
self.open_drop_for_tuple(&tys)
|
||||
}
|
||||
ty::Tuple(..) => {
|
||||
|
@ -15,3 +15,5 @@ rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
errors = { path = "../librustc_errors", package = "rustc_errors" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_index = { path = "../librustc_index" }
|
||||
|
@ -2,18 +2,18 @@
|
||||
// closely. The idea is that all reachable symbols are live, codes called
|
||||
// from live codes are live, and everything else is dead.
|
||||
|
||||
use crate::hir::Node;
|
||||
use crate::hir::{self, PatKind, TyKind};
|
||||
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use crate::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir::Node;
|
||||
use rustc::hir::{self, PatKind, TyKind};
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
|
||||
use crate::hir::def::{CtorOf, Res, DefKind};
|
||||
use crate::hir::CodegenFnAttrFlags;
|
||||
use crate::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use crate::lint;
|
||||
use crate::middle::privacy;
|
||||
use crate::ty::{self, DefIdTree, TyCtxt};
|
||||
use crate::util::nodemap::FxHashSet;
|
||||
use rustc::hir::def::{CtorOf, Res, DefKind};
|
||||
use rustc::hir::CodegenFnAttrFlags;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::lint;
|
||||
use rustc::middle::privacy;
|
||||
use rustc::ty::{self, DefIdTree, TyCtxt};
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -1,15 +1,15 @@
|
||||
use crate::hir::map as hir_map;
|
||||
use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
|
||||
use crate::session::{config, Session};
|
||||
use crate::session::config::EntryFnType;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
|
||||
use rustc::session::{config, Session};
|
||||
use rustc::session::config::EntryFnType;
|
||||
use syntax::attr;
|
||||
use syntax::entry::EntryPointType;
|
||||
use syntax::symbol::sym;
|
||||
use syntax_pos::Span;
|
||||
use crate::hir::{HirId, Item, ItemKind, ImplItem, TraitItem};
|
||||
use crate::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use crate::ty::TyCtxt;
|
||||
use crate::ty::query::Providers;
|
||||
use rustc::hir::{HirId, Item, ItemKind, ImplItem, TraitItem};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::query::Providers;
|
||||
|
||||
struct EntryContext<'a, 'tcx> {
|
||||
session: &'a Session,
|
@ -319,6 +319,188 @@ async fn foo() {}
|
||||
|
||||
Switch to the Rust 2018 edition to use `async fn`.
|
||||
"##,
|
||||
|
||||
// This shouldn't really ever trigger since the repeated value error comes first
|
||||
E0136: r##"
|
||||
A binary can only have one entry point, and by default that entry point is the
|
||||
function `main()`. If there are multiple such functions, please rename one.
|
||||
"##,
|
||||
|
||||
E0137: r##"
|
||||
More than one function was declared with the `#[main]` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0137
|
||||
#![feature(main)]
|
||||
|
||||
#[main]
|
||||
fn foo() {}
|
||||
|
||||
#[main]
|
||||
fn f() {} // error: multiple functions with a `#[main]` attribute
|
||||
```
|
||||
|
||||
This error indicates that the compiler found multiple functions with the
|
||||
`#[main]` attribute. This is an error because there must be a unique entry
|
||||
point into a Rust program. Example:
|
||||
|
||||
```
|
||||
#![feature(main)]
|
||||
|
||||
#[main]
|
||||
fn f() {} // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0138: r##"
|
||||
More than one function was declared with the `#[start]` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0138
|
||||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize {}
|
||||
|
||||
#[start]
|
||||
fn f(argc: isize, argv: *const *const u8) -> isize {}
|
||||
// error: multiple 'start' functions
|
||||
```
|
||||
|
||||
This error indicates that the compiler found multiple functions with the
|
||||
`#[start]` attribute. This is an error because there must be a unique entry
|
||||
point into a Rust program. Example:
|
||||
|
||||
```
|
||||
#![feature(start)]
|
||||
|
||||
#[start]
|
||||
fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0601: r##"
|
||||
No `main` function was found in a binary crate. To fix this error, add a
|
||||
`main` function. For example:
|
||||
|
||||
```
|
||||
fn main() {
|
||||
// Your program will start here.
|
||||
println!("Hello world!");
|
||||
}
|
||||
```
|
||||
|
||||
If you don't know the basics of Rust, you can go look to the Rust Book to get
|
||||
started: https://doc.rust-lang.org/book/
|
||||
"##,
|
||||
|
||||
E0591: r##"
|
||||
Per [RFC 401][rfc401], if you have a function declaration `foo`:
|
||||
|
||||
```
|
||||
// For the purposes of this explanation, all of these
|
||||
// different kinds of `fn` declarations are equivalent:
|
||||
struct S;
|
||||
fn foo(x: S) { /* ... */ }
|
||||
# #[cfg(for_demonstration_only)]
|
||||
extern "C" { fn foo(x: S); }
|
||||
# #[cfg(for_demonstration_only)]
|
||||
impl S { fn foo(self) { /* ... */ } }
|
||||
```
|
||||
|
||||
the type of `foo` is **not** `fn(S)`, as one might expect.
|
||||
Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`.
|
||||
However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`,
|
||||
so you rarely notice this:
|
||||
|
||||
```
|
||||
# struct S;
|
||||
# fn foo(_: S) {}
|
||||
let x: fn(S) = foo; // OK, coerces
|
||||
```
|
||||
|
||||
The reason that this matter is that the type `fn(S)` is not specific to
|
||||
any particular function: it's a function _pointer_. So calling `x()` results
|
||||
in a virtual call, whereas `foo()` is statically dispatched, because the type
|
||||
of `foo` tells us precisely what function is being called.
|
||||
|
||||
As noted above, coercions mean that most code doesn't have to be
|
||||
concerned with this distinction. However, you can tell the difference
|
||||
when using **transmute** to convert a fn item into a fn pointer.
|
||||
|
||||
This is sometimes done as part of an FFI:
|
||||
|
||||
```compile_fail,E0591
|
||||
extern "C" fn foo(userdata: Box<i32>) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
# fn callback(_: extern "C" fn(*mut i32)) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo);
|
||||
callback(f);
|
||||
# }
|
||||
```
|
||||
|
||||
Here, transmute is being used to convert the types of the fn arguments.
|
||||
This pattern is incorrect because, because the type of `foo` is a function
|
||||
**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
|
||||
is a function pointer, which is not zero-sized.
|
||||
This pattern should be rewritten. There are a few possible ways to do this:
|
||||
|
||||
- change the original fn declaration to match the expected signature,
|
||||
and do the cast in the fn body (the preferred option)
|
||||
- cast the fn item fo a fn pointer before calling transmute, as shown here:
|
||||
|
||||
```
|
||||
# extern "C" fn foo(_: Box<i32>) {}
|
||||
# use std::mem::transmute;
|
||||
# unsafe {
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_));
|
||||
let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too
|
||||
# }
|
||||
```
|
||||
|
||||
The same applies to transmutes to `*mut fn()`, which were observed in practice.
|
||||
Note though that use of this type is generally incorrect.
|
||||
The intention is typically to describe a function pointer, but just `fn()`
|
||||
alone suffices for that. `*mut fn()` is a pointer to a fn pointer.
|
||||
(Since these values are typically just passed to C code, however, this rarely
|
||||
makes a difference in practice.)
|
||||
|
||||
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
|
||||
"##,
|
||||
|
||||
E0512: r##"
|
||||
Transmute with two differently sized types was attempted. Erroneous code
|
||||
example:
|
||||
|
||||
```compile_fail,E0512
|
||||
fn takes_u8(_: u8) {}
|
||||
|
||||
fn main() {
|
||||
unsafe { takes_u8(::std::mem::transmute(0u16)); }
|
||||
// error: cannot transmute between types of different sizes,
|
||||
// or dependently-sized types
|
||||
}
|
||||
```
|
||||
|
||||
Please use types with same size or use the expected type directly. Example:
|
||||
|
||||
```
|
||||
fn takes_u8(_: u8) {}
|
||||
|
||||
fn main() {
|
||||
unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok!
|
||||
// or:
|
||||
unsafe { takes_u8(0u8); } // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
;
|
||||
E0226, // only a single explicit lifetime bound is permitted
|
||||
E0472, // asm! is unsupported on this target
|
||||
|
@ -1,14 +1,14 @@
|
||||
use crate::hir::def::{Res, DefKind};
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::ty::{self, Ty, TyCtxt};
|
||||
use crate::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
|
||||
use crate::ty::query::Providers;
|
||||
use rustc::hir::def::{Res, DefKind};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
|
||||
use rustc::ty::query::Providers;
|
||||
|
||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||
use rustc_index::vec::Idx;
|
||||
use syntax_pos::{Span, sym};
|
||||
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use crate::hir;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir;
|
||||
|
||||
fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
|
||||
tcx.hir().visit_item_likes_in_module(
|
@ -13,6 +13,10 @@
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate syntax;
|
||||
|
||||
use rustc::ty::query::Providers;
|
||||
|
||||
@ -22,7 +26,14 @@ pub mod ast_validation;
|
||||
pub mod hir_stats;
|
||||
pub mod layout_test;
|
||||
pub mod loops;
|
||||
pub mod dead;
|
||||
pub mod entry;
|
||||
mod liveness;
|
||||
mod intrinsicck;
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
entry::provide(providers);
|
||||
loops::provide(providers);
|
||||
liveness::provide(providers);
|
||||
intrinsicck::provide(providers);
|
||||
}
|
||||
|
@ -96,17 +96,17 @@
|
||||
use self::LiveNodeKind::*;
|
||||
use self::VarKind::*;
|
||||
|
||||
use crate::hir;
|
||||
use crate::hir::{Expr, HirId};
|
||||
use crate::hir::def::*;
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
|
||||
use crate::hir::Node;
|
||||
use crate::hir::ptr::P;
|
||||
use crate::ty::{self, TyCtxt};
|
||||
use crate::ty::query::Providers;
|
||||
use crate::lint;
|
||||
use crate::util::nodemap::{HirIdMap, HirIdSet};
|
||||
use rustc::hir;
|
||||
use rustc::hir::{Expr, HirId};
|
||||
use rustc::hir::def::*;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
|
||||
use rustc::hir::Node;
|
||||
use rustc::hir::ptr::P;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::lint;
|
||||
use rustc::util::nodemap::{HirIdMap, HirIdSet};
|
||||
|
||||
use errors::Applicability;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
@ -373,7 +373,7 @@ fn visit_fn<'tcx>(
|
||||
|
||||
for param in &body.params {
|
||||
let is_shorthand = match param.pat.kind {
|
||||
crate::hir::PatKind::Struct(..) => true,
|
||||
rustc::hir::PatKind::Struct(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
param.pat.each_binding(|_bm, hir_id, _x, ident| {
|
||||
@ -411,7 +411,7 @@ fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P<hir::Pat>) {
|
||||
let mut pats = VecDeque::new();
|
||||
pats.push_back(pat);
|
||||
while let Some(pat) = pats.pop_front() {
|
||||
use crate::hir::PatKind::*;
|
||||
use rustc::hir::PatKind::*;
|
||||
match &pat.kind {
|
||||
Binding(.., inner_pat) => {
|
||||
pats.extend(inner_pat.iter());
|
@ -9,7 +9,6 @@
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(inner_deref)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(label_break_value)]
|
||||
#![feature(mem_take)]
|
||||
|
@ -1,6 +1,5 @@
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![feature(nll)]
|
||||
#![feature(inner_deref)]
|
||||
|
||||
#![recursion_limit="256"]
|
||||
|
||||
|
47
src/librustc_target/abi/call/asmjs.rs
Normal file
47
src/librustc_target/abi/call/asmjs.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use crate::abi::call::{FnType, ArgType, Uniform};
|
||||
use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
|
||||
// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
|
||||
|
||||
// See the https://github.com/kripken/emscripten-fastcomp-clang repository.
|
||||
// The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.
|
||||
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if ret.layout.is_aggregate() {
|
||||
if let Some(unit) = ret.layout.homogeneous_aggregate(cx).unit() {
|
||||
let size = ret.layout.size;
|
||||
if unit.size == size {
|
||||
ret.cast_to(Uniform {
|
||||
unit,
|
||||
total: size
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ret.make_indirect();
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<'_, Ty>) {
|
||||
if arg.layout.is_aggregate() {
|
||||
arg.make_indirect_byval();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
if arg.is_ignore() { continue; }
|
||||
classify_arg_ty(arg);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ use crate::spec::{self, HasTargetSpec};
|
||||
mod aarch64;
|
||||
mod amdgpu;
|
||||
mod arm;
|
||||
mod asmjs;
|
||||
mod hexagon;
|
||||
mod mips;
|
||||
mod mips64;
|
||||
@ -21,7 +22,6 @@ mod x86;
|
||||
mod x86_64;
|
||||
mod x86_win64;
|
||||
mod wasm32;
|
||||
mod wasm32_bindgen_compat;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum PassMode {
|
||||
@ -557,6 +557,14 @@ impl<'a, Ty> FnType<'a, Ty> {
|
||||
"powerpc" => powerpc::compute_abi_info(cx, self),
|
||||
"powerpc64" => powerpc64::compute_abi_info(cx, self),
|
||||
"s390x" => s390x::compute_abi_info(cx, self),
|
||||
"asmjs" => asmjs::compute_abi_info(cx, self),
|
||||
"wasm32" => {
|
||||
if cx.target_spec().llvm_target.contains("emscripten") {
|
||||
asmjs::compute_abi_info(cx, self)
|
||||
} else {
|
||||
wasm32::compute_abi_info(self)
|
||||
}
|
||||
}
|
||||
"msp430" => msp430::compute_abi_info(self),
|
||||
"sparc" => sparc::compute_abi_info(cx, self),
|
||||
"sparc64" => sparc64::compute_abi_info(cx, self),
|
||||
@ -565,9 +573,6 @@ impl<'a, Ty> FnType<'a, Ty> {
|
||||
"hexagon" => hexagon::compute_abi_info(self),
|
||||
"riscv32" => riscv::compute_abi_info(self, 32),
|
||||
"riscv64" => riscv::compute_abi_info(self, 64),
|
||||
"wasm32" if cx.target_spec().target_os != "emscripten"
|
||||
=> wasm32_bindgen_compat::compute_abi_info(self),
|
||||
"wasm32" | "asmjs" => wasm32::compute_abi_info(cx, self),
|
||||
a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
|
||||
}
|
||||
|
||||
|
@ -1,60 +1,20 @@
|
||||
use crate::abi::call::{FnType, ArgType, Uniform};
|
||||
use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
use crate::abi::call::{FnType, ArgType};
|
||||
|
||||
fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgType<'a, Ty>) -> bool
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if val.layout.is_aggregate() {
|
||||
if let Some(unit) = val.layout.homogeneous_aggregate(cx).unit() {
|
||||
let size = val.layout.size;
|
||||
if unit.size == size {
|
||||
val.cast_to(Uniform {
|
||||
unit,
|
||||
total: size
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
fn classify_ret_ty<Ty>(ret: &mut ArgType<'_, Ty>) {
|
||||
ret.extend_integer_width_to(32);
|
||||
if ret.layout.is_aggregate() {
|
||||
if !unwrap_trivial_aggregate(cx, ret) {
|
||||
ret.make_indirect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<'_, Ty>) {
|
||||
arg.extend_integer_width_to(32);
|
||||
if arg.layout.is_aggregate() {
|
||||
if !unwrap_trivial_aggregate(cx, arg) {
|
||||
arg.make_indirect_byval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<'_, Ty>) {
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret);
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
if arg.is_ignore() { continue; }
|
||||
classify_arg_ty(cx, arg);
|
||||
classify_arg_ty(arg);
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
// This is not and has never been a correct C ABI for WebAssembly, but
|
||||
// for a long time this was the C ABI that Rust used. wasm-bindgen
|
||||
// depends on ABI details for this ABI and is incompatible with the
|
||||
// correct C ABI, so this ABI is being kept around until wasm-bindgen
|
||||
// can be fixed to work with the correct ABI. See #63649 for further
|
||||
// discussion.
|
||||
|
||||
use crate::abi::call::{FnType, ArgType};
|
||||
|
||||
fn classify_ret_ty<Ty>(ret: &mut ArgType<'_, Ty>) {
|
||||
ret.extend_integer_width_to(32);
|
||||
}
|
||||
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<'_, Ty>) {
|
||||
arg.extend_integer_width_to(32);
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<'_, Ty>) {
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
||||
if arg.is_ignore() { continue; }
|
||||
classify_arg_ty(arg);
|
||||
}
|
||||
}
|
@ -1,10 +1,40 @@
|
||||
use super::{LinkerFlavor, Target, wasm32_unknown_emscripten};
|
||||
use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let mut target = wasm32_unknown_emscripten::target()?;
|
||||
target.options.post_link_args
|
||||
.entry(LinkerFlavor::Em)
|
||||
.or_default()
|
||||
.extend(vec!["-s".to_string(), "WASM=0".to_string()]);
|
||||
Ok(target)
|
||||
let mut args = LinkArgs::new();
|
||||
args.insert(LinkerFlavor::Em,
|
||||
vec!["-s".to_string(),
|
||||
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"ABORTING_MALLOC=0".to_string(),
|
||||
"-s".to_string(),
|
||||
"WASM=0".to_string()]);
|
||||
|
||||
let opts = TargetOptions {
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
exe_suffix: ".js".to_string(),
|
||||
linker_is_gnu: true,
|
||||
allow_asm: false,
|
||||
obj_is_bitcode: true,
|
||||
is_like_emscripten: true,
|
||||
max_atomic_width: Some(32),
|
||||
post_link_args: args,
|
||||
target_family: Some("unix".to_string()),
|
||||
codegen_backend: "emscripten".to_string(),
|
||||
.. Default::default()
|
||||
};
|
||||
Ok(Target {
|
||||
llvm_target: "asmjs-unknown-emscripten".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "32".to_string(),
|
||||
target_c_int_width: "32".to_string(),
|
||||
target_os: "emscripten".to_string(),
|
||||
target_env: String::new(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
|
||||
arch: "asmjs".to_string(),
|
||||
linker_flavor: LinkerFlavor::Em,
|
||||
options: opts,
|
||||
})
|
||||
}
|
||||
|
@ -462,6 +462,7 @@ supported_targets! {
|
||||
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
|
||||
("wasm32-unknown-unknown", wasm32_unknown_unknown),
|
||||
("wasm32-wasi", wasm32_wasi),
|
||||
("wasm32-experimental-emscripten", wasm32_experimental_emscripten),
|
||||
|
||||
("thumbv6m-none-eabi", thumbv6m_none_eabi),
|
||||
("thumbv7m-none-eabi", thumbv7m_none_eabi),
|
||||
|
44
src/librustc_target/spec/wasm32_experimental_emscripten.rs
Normal file
44
src/librustc_target/spec/wasm32_experimental_emscripten.rs
Normal file
@ -0,0 +1,44 @@
|
||||
use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let mut post_link_args = LinkArgs::new();
|
||||
post_link_args.insert(LinkerFlavor::Em,
|
||||
vec!["-s".to_string(),
|
||||
"WASM=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"ASSERTIONS=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
|
||||
"-g3".to_string()]);
|
||||
|
||||
let opts = TargetOptions {
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
// Today emcc emits two files - a .js file to bootstrap and
|
||||
// possibly interpret the wasm, and a .wasm file
|
||||
exe_suffix: ".js".to_string(),
|
||||
linker_is_gnu: true,
|
||||
link_env: vec![("EMCC_WASM_BACKEND".to_string(), "1".to_string())],
|
||||
allow_asm: false,
|
||||
obj_is_bitcode: true,
|
||||
is_like_emscripten: true,
|
||||
max_atomic_width: Some(32),
|
||||
post_link_args,
|
||||
limit_rdylib_exports: false,
|
||||
target_family: Some("unix".to_string()),
|
||||
.. Default::default()
|
||||
};
|
||||
Ok(Target {
|
||||
llvm_target: "wasm32-unknown-unknown".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "32".to_string(),
|
||||
target_c_int_width: "32".to_string(),
|
||||
target_os: "emscripten".to_string(),
|
||||
target_env: String::new(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
|
||||
arch: "wasm32".to_string(),
|
||||
linker_flavor: LinkerFlavor::Em,
|
||||
options: opts,
|
||||
})
|
||||
}
|
@ -1,46 +1,45 @@
|
||||
use super::wasm32_base;
|
||||
use super::{LinkArgs, LinkerFlavor, Target, TargetOptions, PanicStrategy};
|
||||
use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
// FIXME(nikic) BINARYEN_TRAP_MODE=clamp is needed to avoid trapping in our
|
||||
// -Zsaturating-float-casts implementation. This can be dropped if/when
|
||||
// we have native fpto[su]i.sat intrinsics, or the implementation otherwise
|
||||
// stops relying on non-trapping fpto[su]i.
|
||||
let mut post_link_args = LinkArgs::new();
|
||||
post_link_args.insert(LinkerFlavor::Em,
|
||||
vec!["-s".to_string(),
|
||||
"BINARYEN=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"ASSERTIONS=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"DISABLE_EXCEPTION_CATCHING=1".to_string(),
|
||||
"-s".to_string(),
|
||||
"ABORTING_MALLOC=0".to_string(),
|
||||
// FIXME(tlively): Enable this linker option once libc type errors
|
||||
// are resolved. See https://github.com/rust-lang/libc/pull/1478.
|
||||
// "-Wl,--fatal-warnings".to_string(),
|
||||
]);
|
||||
"BINARYEN_TRAP_MODE='clamp'".to_string()]);
|
||||
|
||||
let opts = TargetOptions {
|
||||
// emcc emits two files - a .js file to instantiate the wasm and supply platform
|
||||
// functionality, and a .wasm file.
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
// Today emcc emits two files - a .js file to bootstrap and
|
||||
// possibly interpret the wasm, and a .wasm file
|
||||
exe_suffix: ".js".to_string(),
|
||||
linker: None,
|
||||
linker_is_gnu: true,
|
||||
allow_asm: false,
|
||||
obj_is_bitcode: true,
|
||||
is_like_emscripten: true,
|
||||
// FIXME(tlively): Emscripten supports unwinding, but we would have to pass
|
||||
// -enable-emscripten-cxx-exceptions to LLVM at codegen time and merge
|
||||
// https://reviews.llvm.org/rG5c3cdef84b82464756bb571c13c31cf7773860c3to use it.
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
max_atomic_width: Some(32),
|
||||
post_link_args,
|
||||
limit_rdylib_exports: false,
|
||||
target_family: Some("unix".to_string()),
|
||||
.. wasm32_base::options()
|
||||
codegen_backend: "emscripten".to_string(),
|
||||
.. Default::default()
|
||||
};
|
||||
Ok(Target {
|
||||
llvm_target: "wasm32-unknown-emscripten".to_string(),
|
||||
llvm_target: "asmjs-unknown-emscripten".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "32".to_string(),
|
||||
target_c_int_width: "32".to_string(),
|
||||
target_os: "emscripten".to_string(),
|
||||
target_env: String::new(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
|
||||
data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
|
||||
arch: "wasm32".to_string(),
|
||||
linker_flavor: LinkerFlavor::Em,
|
||||
options: opts,
|
||||
|
@ -223,7 +223,7 @@ fn dtorck_constraint_for_ty<'tcx>(
|
||||
// *do* incorporate the upvars here.
|
||||
|
||||
let constraint = DtorckConstraint {
|
||||
outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(),
|
||||
outlives: substs.as_generator().upvar_tys(def_id, tcx).map(|t| t.into()).collect(),
|
||||
dtorck_types: vec![],
|
||||
overflows: vec![],
|
||||
};
|
||||
|
@ -73,7 +73,9 @@ crate fn closure(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
|
||||
}
|
||||
|
||||
crate fn generator(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
|
||||
tcx.mk_generator(def_id, ty::GeneratorSubsts {
|
||||
substs: InternalSubsts::bound_vars_for_item(tcx, def_id),
|
||||
}, hir::GeneratorMovability::Movable)
|
||||
tcx.mk_generator(
|
||||
def_id,
|
||||
InternalSubsts::bound_vars_for_item(tcx, def_id),
|
||||
hir::GeneratorMovability::Movable
|
||||
)
|
||||
}
|
||||
|
@ -113,21 +113,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
});
|
||||
if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types {
|
||||
let substs = ty::GeneratorSubsts { substs };
|
||||
let generator_substs = substs.as_generator();
|
||||
self.demand_eqtype(
|
||||
expr.span,
|
||||
yield_ty,
|
||||
substs.yield_ty(expr_def_id, self.tcx),
|
||||
generator_substs.yield_ty(expr_def_id, self.tcx),
|
||||
);
|
||||
self.demand_eqtype(
|
||||
expr.span,
|
||||
liberated_sig.output(),
|
||||
substs.return_ty(expr_def_id, self.tcx),
|
||||
generator_substs.return_ty(expr_def_id, self.tcx),
|
||||
);
|
||||
self.demand_eqtype(
|
||||
expr.span,
|
||||
interior,
|
||||
substs.witness(expr_def_id, self.tcx),
|
||||
generator_substs.witness(expr_def_id, self.tcx),
|
||||
);
|
||||
return self.tcx.mk_generator(expr_def_id, substs, movability);
|
||||
}
|
||||
|
@ -67,7 +67,6 @@ This API is completely unstable and subject to change.
|
||||
#![feature(nll)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(never_type)]
|
||||
#![feature(inner_deref)]
|
||||
#![feature(mem_take)]
|
||||
|
||||
#![recursion_limit="256"]
|
||||
|
@ -360,7 +360,7 @@ impl<'a> fmt::Display for Html<'a> {
|
||||
("target_arch", Some(arch)) => match &*arch.as_str() {
|
||||
"aarch64" => "AArch64",
|
||||
"arm" => "ARM",
|
||||
"asmjs" => "JavaScript",
|
||||
"asmjs" => "asm.js",
|
||||
"mips" => "MIPS",
|
||||
"mips64" => "MIPS-64",
|
||||
"msp430" => "MSP430",
|
||||
|
@ -14,7 +14,6 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(inner_deref)]
|
||||
#![feature(never_type)]
|
||||
#![feature(mem_take)]
|
||||
#![feature(unicode_internals)]
|
||||
|
@ -185,7 +185,6 @@ impl UdpSocket {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(udp_peer_addr)]
|
||||
/// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
@ -199,14 +198,13 @@ impl UdpSocket {
|
||||
/// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(udp_peer_addr)]
|
||||
/// use std::net::UdpSocket;
|
||||
///
|
||||
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
|
||||
/// assert_eq!(socket.peer_addr().unwrap_err().kind(),
|
||||
/// ::std::io::ErrorKind::NotConnected);
|
||||
/// ```
|
||||
#[unstable(feature = "udp_peer_addr", issue = "59127")]
|
||||
#[stable(feature = "udp_peer_addr", since = "1.40.0")]
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.0.peer_addr()
|
||||
}
|
||||
|
@ -15,9 +15,11 @@ use crate::intrinsics;
|
||||
use crate::mem;
|
||||
use crate::ptr;
|
||||
use crate::raw;
|
||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||
use crate::sys::stdio::panic_output;
|
||||
use crate::sys_common::rwlock::RWLock;
|
||||
use crate::sys_common::{thread_info, util, backtrace};
|
||||
use crate::sys_common::{thread_info, util};
|
||||
use crate::sys_common::backtrace::{self, RustBacktrace};
|
||||
use crate::thread;
|
||||
|
||||
#[cfg(not(test))]
|
||||
@ -158,16 +160,10 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
|
||||
fn default_hook(info: &PanicInfo<'_>) {
|
||||
// If this is a double panic, make sure that we print a backtrace
|
||||
// for this panic. Otherwise only print it if logging is enabled.
|
||||
let log_backtrace = if cfg!(feature = "backtrace") {
|
||||
let panics = update_panic_count(0);
|
||||
|
||||
if panics >= 2 {
|
||||
Some(backtrace_rs::PrintFmt::Full)
|
||||
} else {
|
||||
backtrace::log_enabled()
|
||||
}
|
||||
let backtrace_env = if update_panic_count(0) >= 2 {
|
||||
RustBacktrace::Print(backtrace_rs::PrintFmt::Full)
|
||||
} else {
|
||||
None
|
||||
backtrace::rust_backtrace_env()
|
||||
};
|
||||
|
||||
// The current implementation always returns `Some`.
|
||||
@ -187,16 +183,16 @@ fn default_hook(info: &PanicInfo<'_>) {
|
||||
let _ = writeln!(err, "thread '{}' panicked at '{}', {}",
|
||||
name, msg, location);
|
||||
|
||||
if cfg!(feature = "backtrace") {
|
||||
use crate::sync::atomic::{AtomicBool, Ordering};
|
||||
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
if let Some(format) = log_backtrace {
|
||||
let _ = backtrace::print(err, format);
|
||||
} else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) {
|
||||
let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \
|
||||
environment variable to display a backtrace.");
|
||||
match backtrace_env {
|
||||
RustBacktrace::Print(format) => drop(backtrace::print(err, format)),
|
||||
RustBacktrace::Disabled => {}
|
||||
RustBacktrace::RuntimeDisabled => {
|
||||
if FIRST_PANIC.swap(false, Ordering::SeqCst) {
|
||||
let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \
|
||||
environment variable to display a backtrace.");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -44,12 +44,9 @@ fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindS
|
||||
sys::args::init(argc, argv);
|
||||
|
||||
// Let's run some code!
|
||||
#[cfg(feature = "backtrace")]
|
||||
let exit_code = panic::catch_unwind(|| {
|
||||
sys_common::backtrace::__rust_begin_short_backtrace(move || main())
|
||||
});
|
||||
#[cfg(not(feature = "backtrace"))]
|
||||
let exit_code = panic::catch_unwind(move || main());
|
||||
|
||||
sys_common::cleanup();
|
||||
exit_code.unwrap_or(101) as isize
|
||||
|
@ -10,8 +10,7 @@
|
||||
// fallback implementation to use as well.
|
||||
//
|
||||
// Due to rust-lang/rust#18804, make sure this is not generic!
|
||||
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox",
|
||||
target_os = "emscripten"))]
|
||||
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox"))]
|
||||
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
|
||||
use crate::mem;
|
||||
use crate::sys_common::thread_local::register_dtor_fallback;
|
||||
|
@ -7,6 +7,7 @@ use crate::io;
|
||||
use crate::borrow::Cow;
|
||||
use crate::io::prelude::*;
|
||||
use crate::path::{self, Path, PathBuf};
|
||||
use crate::sync::atomic::{self, Ordering};
|
||||
use crate::sys::mutex::Mutex;
|
||||
|
||||
use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt};
|
||||
@ -115,8 +116,10 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
|
||||
#[inline(never)]
|
||||
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
|
||||
/// this is only inline(never) when backtraces in libstd are enabled, otherwise
|
||||
/// it's fine to optimize away.
|
||||
#[cfg_attr(feature = "backtrace", inline(never))]
|
||||
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
@ -126,42 +129,49 @@ where
|
||||
f()
|
||||
}
|
||||
|
||||
pub enum RustBacktrace {
|
||||
Print(PrintFmt),
|
||||
Disabled,
|
||||
RuntimeDisabled,
|
||||
}
|
||||
|
||||
// For now logging is turned off by default, and this function checks to see
|
||||
// whether the magical environment variable is present to see if it's turned on.
|
||||
pub fn log_enabled() -> Option<PrintFmt> {
|
||||
use crate::sync::atomic::{self, Ordering};
|
||||
pub fn rust_backtrace_env() -> RustBacktrace {
|
||||
// If the `backtrace` feature of this crate isn't enabled quickly return
|
||||
// `None` so this can be constant propagated all over the place to turn
|
||||
// optimize away callers.
|
||||
if !cfg!(feature = "backtrace") {
|
||||
return RustBacktrace::Disabled;
|
||||
}
|
||||
|
||||
// Setting environment variables for Fuchsia components isn't a standard
|
||||
// or easily supported workflow. For now, always display backtraces.
|
||||
if cfg!(target_os = "fuchsia") {
|
||||
return Some(PrintFmt::Full);
|
||||
return RustBacktrace::Print(PrintFmt::Full);
|
||||
}
|
||||
|
||||
static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0);
|
||||
match ENABLED.load(Ordering::SeqCst) {
|
||||
0 => {}
|
||||
1 => return None,
|
||||
2 => return Some(PrintFmt::Short),
|
||||
_ => return Some(PrintFmt::Full),
|
||||
1 => return RustBacktrace::RuntimeDisabled,
|
||||
2 => return RustBacktrace::Print(PrintFmt::Short),
|
||||
_ => return RustBacktrace::Print(PrintFmt::Full),
|
||||
}
|
||||
|
||||
let val = env::var_os("RUST_BACKTRACE").and_then(|x| {
|
||||
if &x == "0" {
|
||||
None
|
||||
} else if &x == "full" {
|
||||
Some(PrintFmt::Full)
|
||||
} else {
|
||||
Some(PrintFmt::Short)
|
||||
}
|
||||
});
|
||||
ENABLED.store(
|
||||
match val {
|
||||
Some(v) => v as isize,
|
||||
None => 1,
|
||||
},
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
val
|
||||
let (format, cache) = env::var_os("RUST_BACKTRACE")
|
||||
.map(|x| {
|
||||
if &x == "0" {
|
||||
(RustBacktrace::RuntimeDisabled, 1)
|
||||
} else if &x == "full" {
|
||||
(RustBacktrace::Print(PrintFmt::Full), 3)
|
||||
} else {
|
||||
(RustBacktrace::Print(PrintFmt::Short), 2)
|
||||
}
|
||||
})
|
||||
.unwrap_or((RustBacktrace::RuntimeDisabled, 1));
|
||||
ENABLED.store(cache, Ordering::SeqCst);
|
||||
format
|
||||
}
|
||||
|
||||
/// Prints the filename of the backtrace frame.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user