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:
bors 2019-10-06 04:59:16 +00:00
commit 5a8fb7c24d
240 changed files with 1600 additions and 965 deletions

View File

@ -3613,6 +3613,8 @@ dependencies = [
"rustc",
"rustc_data_structures",
"rustc_errors",
"rustc_index",
"rustc_target",
"syntax",
"syntax_pos",
]

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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

View 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

View 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" "$@"

View 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

View 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

View File

@ -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

View File

@ -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)]

View File

@ -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 {

View File

@ -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 {

View File

@ -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;

View File

@ -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 \

View File

@ -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
}
}

View File

@ -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())
}

View File

@ -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 {

View File

@ -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)]

View File

@ -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.

View File

@ -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(..) => {

View File

@ -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;

View File

@ -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)]

View File

@ -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

View File

@ -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) {

View File

@ -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:

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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) => {

View File

@ -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) => {

View File

@ -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()
}
}
}

View File

@ -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);
}

View File

@ -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));

View File

@ -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 {

View File

@ -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) => {

View File

@ -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, _| {

View File

@ -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());
}

View File

@ -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);

View File

@ -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());
}

View File

@ -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);
}

View File

@ -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,
);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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),

View File

@ -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());
};
}

View File

@ -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,
_ => &[],
}
}

View File

@ -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)
}

View File

@ -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

View File

@ -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)

View File

@ -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),

View File

@ -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) => {

View File

@ -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
}

View File

@ -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() {

View File

@ -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 {

View File

@ -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)

View File

@ -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(),

View File

@ -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))
})
}

View File

@ -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;
}

View File

@ -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>,

View File

@ -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);
}
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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),

View File

@ -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(_) => {

View File

@ -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()))
)?;

View File

@ -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),

View File

@ -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 {

View File

@ -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;

View File

@ -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),

View File

@ -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(..) => {

View File

@ -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" }

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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(

View File

@ -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);
}

View File

@ -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());

View File

@ -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)]

View File

@ -1,6 +1,5 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(nll)]
#![feature(inner_deref)]
#![recursion_limit="256"]

View 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);
}
}

View File

@ -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))
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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,
})
}

View File

@ -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),

View 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,
})
}

View File

@ -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,

View File

@ -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![],
};

View File

@ -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
)
}

View File

@ -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);
}

View File

@ -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"]

View File

@ -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",

View File

@ -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)]

View File

@ -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()
}

View File

@ -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.");
}
}
}
};

View File

@ -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

View File

@ -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;

View File

@ -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