]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #55101 - alexreg:trait-aliases, r=nikomatsakis
authorbors <bors@rust-lang.org>
Sat, 3 Nov 2018 17:30:37 +0000 (17:30 +0000)
committerbors <bors@rust-lang.org>
Sat, 3 Nov 2018 17:30:37 +0000 (17:30 +0000)
Implement trait aliases (RFC 1733)

Extends groundwork done in https://github.com/rust-lang/rust/pull/45047, and fully implements https://github.com/rust-lang/rfcs/pull/1733.

CC @durka @nikomatsakis

150 files changed:
.gitmodules
.travis.yml
config.toml.example
src/Cargo.lock
src/bootstrap/bootstrap.py
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/lib.rs
src/bootstrap/sanity.rs
src/bootstrap/test.rs
src/ci/docker/dist-i686-linux/Dockerfile
src/ci/docker/dist-x86_64-linux/Dockerfile
src/jemalloc [deleted submodule]
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/liballoc/rc.rs
src/liballoc/sync.rs
src/liballoc/tests/heap.rs
src/liballoc_jemalloc/Cargo.toml [deleted file]
src/liballoc_jemalloc/build.rs [deleted file]
src/liballoc_jemalloc/lib.rs [deleted file]
src/liballoc_jemalloc/pthread_atfork_dummy.c [deleted file]
src/libcore/nonzero.rs
src/libcore/ops/mod.rs
src/libcore/ops/unsize.rs
src/libcore/pin.rs
src/libcore/ptr.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/canonical/canonicalizer.rs
src/librustc/infer/canonical/mod.rs
src/librustc/infer/canonical/query_response.rs
src/librustc/infer/canonical/substitute.rs
src/librustc/infer/combine.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/freshen.rs
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/infer/outlives/obligations.rs
src/librustc/infer/outlives/verify.rs
src/librustc/infer/region_constraints/mod.rs
src/librustc/infer/sub.rs
src/librustc/middle/lang_items.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/project.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/query/normalize.rs
src/librustc/traits/query/outlives_bounds.rs
src/librustc/traits/select.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/instance.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/callee.rs
src/librustc_codegen_llvm/debuginfo/type_names.rs
src/librustc_codegen_llvm/mir/block.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_lint/types.rs
src/librustc_metadata/decoder.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/lower_128bit.rs
src/librustc_target/Cargo.toml
src/librustc_target/spec/apple_base.rs
src/librustc_target/spec/apple_ios_base.rs
src/librustc_target/spec/arm_linux_androideabi.rs
src/librustc_target/spec/cloudabi_base.rs
src/librustc_target/spec/dragonfly_base.rs
src/librustc_target/spec/freebsd_base.rs
src/librustc_target/spec/linux_base.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/solaris_base.rs
src/librustc_traits/chalk_context.rs
src/librustc_traits/dropck_outlives.rs
src/librustc_traits/implied_outlives_bounds.rs
src/librustc_traits/lowering/environment.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/outlives/utils.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/storage.js
src/libstd/Cargo.toml
src/libstd/alloc.rs
src/libstd/lib.rs
src/rustc/Cargo.toml
src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs [new file with mode: 0644]
src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs [new file with mode: 0644]
src/test/rustdoc/assoc-consts.rs
src/test/rustdoc/auxiliary/enum_primitive.rs [new file with mode: 0644]
src/test/rustdoc/manual_impl.rs
src/test/rustdoc/no-stack-overflow-25295.rs [new file with mode: 0644]
src/test/ui/arbitrary-self-types-not-object-safe.rs
src/test/ui/arbitrary-self-types-not-object-safe.stderr
src/test/ui/derive-uninhabited-enum-38885.rs [new file with mode: 0644]
src/test/ui/derive-uninhabited-enum-38885.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0375.stderr
src/test/ui/invalid_dispatch_from_dyn_impls.rs [new file with mode: 0644]
src/test/ui/invalid_dispatch_from_dyn_impls.stderr [new file with mode: 0644]
src/test/ui/issues/issue-26905.stderr
src/test/ui/traits/trait-item-privacy.rs
src/test/ui/traits/trait-item-privacy.stderr
src/test/ui/traits/trait-test-2.rs
src/test/ui/traits/trait-test-2.stderr
src/tools/publish_toolstate.py
src/tools/tidy/src/cargo.rs
src/tools/tidy/src/lib.rs
src/tools/tidy/src/pal.rs

index 038237aa179a9b421aab40eb989f03d1679a073f..bf9bdd9a5b4b0a25fce4a97707f1a875ec1d97f0 100644 (file)
@@ -2,9 +2,6 @@
        path = src/llvm
        url = https://github.com/rust-lang/llvm.git
        branch = master
-[submodule "src/jemalloc"]
-       path = src/jemalloc
-       url = https://github.com/rust-lang/jemalloc.git
 [submodule "src/rust-installer"]
        path = src/tools/rust-installer
        url = https://github.com/rust-lang/rust-installer.git
@@ -64,4 +61,4 @@
        path = src/tools/clang
        url = https://github.com/rust-lang-nursery/clang.git
        branch = rust-release-80-v1
-  
\ No newline at end of file
+
index 3d8918095accbe6cb88f90788bceccef7244aa54..b208e760d95c672b1a60891970bd7d0cb7a77f01 100644 (file)
@@ -30,7 +30,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb"
+        RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb --set rust.jemalloc"
         SRC=.
         DEPLOY_ALT=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -53,7 +53,7 @@ matrix:
     # version that we're using, 8.2, cannot compile LLVM for OSX 10.7.
     - env: >
         RUST_CHECK_TARGET=check
-        RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler"
+        RUST_CONFIGURE_ARGS="--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
         SRC=.
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
         MACOSX_DEPLOYMENT_TARGET=10.8
@@ -67,7 +67,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=check
-        RUST_CONFIGURE_ARGS=--build=i686-apple-darwin
+        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --set rust.jemalloc"
         SRC=.
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
         MACOSX_DEPLOYMENT_TARGET=10.8
@@ -87,7 +87,7 @@ matrix:
     # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7.
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb"
+        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -102,7 +102,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb"
+        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
index 093b8f9e526eca8778e43293a3614e0bc70f1fae..8b11014edae795c1a4638680d475e16247c5b056 100644 (file)
 # Adding debuginfo makes them several times larger.
 #debuginfo-tools = false
 
-# Whether or not jemalloc is built and enabled
-#use-jemalloc = true
-
-# Whether or not jemalloc is built with its debug option set
-#debug-jemalloc = false
-
 # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
 #backtrace = true
 
 # generally only set for releases
 #remap-debuginfo = false
 
+# Link the compiler against `jemalloc`, where on Linux and OSX it should
+# override the default allocator for rustc and LLVM.
+#jemalloc = false
+
 # =============================================================================
 # Options for specific targets
 #
 # not, you can specify an explicit file name for it.
 #llvm-filecheck = "/path/to/FileCheck"
 
-# Path to the custom jemalloc static library to link into the standard library
-# by default. This is only used if jemalloc is still enabled above
-#jemalloc = "/path/to/jemalloc/libjemalloc_pic.a"
-
 # If this target is for Android, this option will be required to specify where
 # the NDK for the target lives. This is used to find the C compiler to link and
 # build native code.
index db111b5d2b524ccdd281ed21a9a11ad1b18b42e6..2b00cde7f19d056193759d9ff84d5091e41e761e 100644 (file)
@@ -15,17 +15,6 @@ dependencies = [
  "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "alloc_jemalloc"
-version = "0.0.0"
-dependencies = [
- "build_helper 0.1.0",
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "compiler_builtins 0.0.0",
- "core 0.0.0",
- "libc 0.0.0",
-]
-
 [[package]]
 name = "alloc_system"
 version = "0.0.0"
@@ -785,6 +774,11 @@ dependencies = [
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "fs_extra"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "fst"
 version = "0.3.0"
@@ -996,6 +990,16 @@ name = "itoa"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "jemalloc-sys"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "jobserver"
 version = "0.1.11"
@@ -2181,6 +2185,7 @@ dependencies = [
  "arena 0.0.0",
  "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
+ "jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2680,7 +2685,6 @@ name = "std"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "alloc_jemalloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3237,6 +3241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
 "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
 "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
 "checksum fst 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d94485a00b1827b861dd9d1a2cc9764f9044d4c535514c0760a5a2012ef3399f"
 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
@@ -3259,6 +3264,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
 "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
 "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
+"checksum jemalloc-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc62c8e50e381768ce8ee0428ee53741929f7ebd73e4d83f669bcf7693e00ae"
 "checksum jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "60af5f849e1981434e4a31d3d782c4774ae9b434ce55b101a96ecfd09147e8be"
 "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be"
 "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c"
index b5dc0090c8b9ce2652fe5862ce2d2103b3b06cb4..fdd8784453bdb8c509b8bf4824921e327fb2246e 100644 (file)
@@ -715,11 +715,6 @@ class RustBuild(object):
                 backends = self.get_toml('codegen-backends')
                 if backends is None or not 'emscripten' in backends:
                     continue
-            if module.endswith("jemalloc"):
-                if self.get_toml('use-jemalloc') == 'false':
-                    continue
-                if self.get_toml('jemalloc'):
-                    continue
             if module.endswith("lld"):
                 config = self.get_toml('lld')
                 if config is None or config == 'false':
index d009d9645c35aa388ebf7f639f533984491b7de5..885ad07e0873604adb3b420b6eff5cee74f6ad98 100644 (file)
@@ -158,16 +158,7 @@ pub fn std_cargo(builder: &Builder,
             .arg("--manifest-path")
             .arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml"));
     } else {
-        let mut features = builder.std_features();
-
-        // When doing a local rebuild we tell cargo that we're stage1 rather than
-        // stage0. This works fine if the local rust and being-built rust have the
-        // same view of what the default allocator is, but fails otherwise. Since
-        // we don't have a way to express an allocator preference yet, work
-        // around the issue in the case of a local rebuild with jemalloc disabled.
-        if compiler.stage == 0 && builder.local_rebuild && !builder.config.use_jemalloc {
-            features.push_str(" force_alloc_system");
-        }
+        let features = builder.std_features();
 
         if compiler.stage != 0 && builder.config.sanitizers {
             // This variable is used by the sanitizer runtime crates, e.g.
@@ -188,11 +179,6 @@ pub fn std_cargo(builder: &Builder,
             .arg("--manifest-path")
             .arg(builder.src.join("src/libstd/Cargo.toml"));
 
-        if let Some(target) = builder.config.target_config.get(&target) {
-            if let Some(ref jemalloc) = target.jemalloc {
-                cargo.env("JEMALLOC_OVERRIDE", jemalloc);
-            }
-        }
         if target.contains("musl") {
             if let Some(p) = builder.musl_root(target) {
                 cargo.env("MUSL_ROOT", p);
index 3eb6e8d84e877fdfe8a4665b72718a7141b8498d..0f249eee000224a9f0b8d1ff48878dae20e0551b 100644 (file)
@@ -116,6 +116,7 @@ pub struct Config {
     pub hosts: Vec<Interned<String>>,
     pub targets: Vec<Interned<String>>,
     pub local_rebuild: bool,
+    pub jemalloc: bool,
 
     // dist misc
     pub dist_sign_folder: Option<PathBuf>,
@@ -123,8 +124,6 @@ pub struct Config {
     pub dist_gpg_password_file: Option<PathBuf>,
 
     // libstd features
-    pub debug_jemalloc: bool,
-    pub use_jemalloc: bool,
     pub backtrace: bool, // support for RUST_BACKTRACE
     pub wasm_syscall: bool,
 
@@ -166,7 +165,6 @@ pub struct Target {
     pub llvm_config: Option<PathBuf>,
     /// Some(path to FileCheck) if one was specified.
     pub llvm_filecheck: Option<PathBuf>,
-    pub jemalloc: Option<PathBuf>,
     pub cc: Option<PathBuf>,
     pub cxx: Option<PathBuf>,
     pub ar: Option<PathBuf>,
@@ -263,7 +261,7 @@ struct Llvm {
     link_jobs: Option<u32>,
     link_shared: Option<bool>,
     version_suffix: Option<String>,
-    clang_cl: Option<String>
+    clang_cl: Option<String>,
 }
 
 #[derive(Deserialize, Default, Clone)]
@@ -302,8 +300,6 @@ struct Rust {
     debuginfo_only_std: Option<bool>,
     debuginfo_tools: Option<bool>,
     experimental_parallel_queries: Option<bool>,
-    debug_jemalloc: Option<bool>,
-    use_jemalloc: Option<bool>,
     backtrace: Option<bool>,
     default_linker: Option<String>,
     channel: Option<String>,
@@ -329,6 +325,7 @@ struct Rust {
     backtrace_on_ice: Option<bool>,
     verify_llvm_ir: Option<bool>,
     remap_debuginfo: Option<bool>,
+    jemalloc: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -337,7 +334,6 @@ struct Rust {
 struct TomlTarget {
     llvm_config: Option<String>,
     llvm_filecheck: Option<String>,
-    jemalloc: Option<String>,
     cc: Option<String>,
     cxx: Option<String>,
     ar: Option<String>,
@@ -363,7 +359,6 @@ pub fn default_opts() -> Config {
         config.llvm_enabled = true;
         config.llvm_optimize = true;
         config.llvm_version_check = true;
-        config.use_jemalloc = true;
         config.backtrace = true;
         config.rust_optimize = true;
         config.rust_optimize_tests = true;
@@ -499,7 +494,6 @@ pub fn parse(args: &[String]) -> Config {
         let mut debuginfo_only_std = None;
         let mut debuginfo_tools = None;
         let mut debug = None;
-        let mut debug_jemalloc = None;
         let mut debuginfo = None;
         let mut debug_assertions = None;
         let mut optimize = None;
@@ -541,12 +535,11 @@ pub fn parse(args: &[String]) -> Config {
             debuginfo_tools = rust.debuginfo_tools;
             optimize = rust.optimize;
             ignore_git = rust.ignore_git;
-            debug_jemalloc = rust.debug_jemalloc;
             set(&mut config.rust_optimize_tests, rust.optimize_tests);
             set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
             set(&mut config.codegen_tests, rust.codegen_tests);
             set(&mut config.rust_rpath, rust.rpath);
-            set(&mut config.use_jemalloc, rust.use_jemalloc);
+            set(&mut config.jemalloc, rust.jemalloc);
             set(&mut config.backtrace, rust.backtrace);
             set(&mut config.channel, rust.channel.clone());
             set(&mut config.rust_dist_src, rust.dist_src);
@@ -596,9 +589,6 @@ pub fn parse(args: &[String]) -> Config {
                 if let Some(ref s) = cfg.llvm_filecheck {
                     target.llvm_filecheck = Some(config.src.join(s));
                 }
-                if let Some(ref s) = cfg.jemalloc {
-                    target.jemalloc = Some(config.src.join(s));
-                }
                 if let Some(ref s) = cfg.android_ndk {
                     target.ndk = Some(config.src.join(s));
                 }
@@ -644,7 +634,6 @@ pub fn parse(args: &[String]) -> Config {
         config.rust_debuginfo_tools = debuginfo_tools.unwrap_or(false);
 
         let default = debug == Some(true);
-        config.debug_jemalloc = debug_jemalloc.unwrap_or(default);
         config.rust_debuginfo = debuginfo.unwrap_or(default);
         config.rust_debug_assertions = debug_assertions.unwrap_or(default);
 
index d5f8d9d27d95632b8d6fc9fc799323fcb5423b8c..c69e9a1d9dcf0794eb62c0eee1c22a69d0fffe0d 100755 (executable)
@@ -82,7 +82,6 @@ o("debuginfo", "rust.debuginfo", "build with debugger metadata")
 o("debuginfo-lines", "rust.debuginfo-lines", "build with line number debugger metadata")
 o("debuginfo-only-std", "rust.debuginfo-only-std", "build only libstd with debugging information")
 o("debuginfo-tools", "rust.debuginfo-tools", "build extended tools with debugging information")
-o("debug-jemalloc", "rust.debug-jemalloc", "build jemalloc with --enable-debug --enable-fill")
 v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file")
 
 v("prefix", "install.prefix", "set installation prefix")
@@ -99,7 +98,6 @@ v("llvm-root", None, "set LLVM root")
 v("llvm-config", None, "set path to llvm-config")
 v("llvm-filecheck", None, "set path to LLVM's FileCheck utility")
 v("python", "build.python", "set path to python")
-v("jemalloc-root", None, "set directory where libjemalloc_pic.a is located")
 v("android-cross-path", "target.arm-linux-androideabi.android-ndk",
   "Android NDK standalone path (deprecated)")
 v("i686-linux-android-ndk", "target.i686-linux-android.android-ndk",
@@ -148,7 +146,6 @@ v("default-linker", "rust.default-linker", "the default linker")
 # Many of these are saved below during the "writing configuration" step
 # (others are conditionally saved).
 o("manage-submodules", "build.submodules", "let the build manage the git submodules")
-o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc")
 o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two")
 o("extended", "build.extended", "build an extended rust tool set")
 
@@ -330,8 +327,6 @@ for key in known_args:
         set('target.{}.llvm-config'.format(build()), value)
     elif option.name == 'llvm-filecheck':
         set('target.{}.llvm-filecheck'.format(build()), value)
-    elif option.name == 'jemalloc-root':
-        set('target.{}.jemalloc'.format(build()), value + '/libjemalloc_pic.a')
     elif option.name == 'tools':
         set('build.tools', value.split(','))
     elif option.name == 'host':
index 6d40575352418d45456ac7bde1b7e114cb47f770..567b47a70a12cc52143c3c534e2ce45d1dff4529 100644 (file)
@@ -859,7 +859,6 @@ fn run(self, builder: &Builder) -> PathBuf {
             "src/build_helper",
             "src/dlmalloc",
             "src/liballoc",
-            "src/liballoc_jemalloc",
             "src/liballoc_system",
             "src/libbacktrace",
             "src/libcompiler_builtins",
@@ -878,14 +877,12 @@ fn run(self, builder: &Builder) -> PathBuf {
             "src/rustc/dlmalloc_shim",
             "src/libtest",
             "src/libterm",
-            "src/jemalloc",
             "src/libprofiler_builtins",
             "src/stdsimd",
             "src/libproc_macro",
         ];
         let std_src_dirs_exclude = [
             "src/libcompiler_builtins/compiler-rt/test",
-            "src/jemalloc/test/unit",
         ];
 
         copy_src_dirs(builder, &std_src_dirs[..], &std_src_dirs_exclude[..], &dst_src);
@@ -912,7 +909,7 @@ fn run(self, builder: &Builder) -> PathBuf {
     }
 }
 
-const CARGO_VENDOR_VERSION: &str = "0.1.4";
+const CARGO_VENDOR_VERSION: &str = "0.1.19";
 
 #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct PlainSourceTarball;
index ba601249ea895fb7f43afd08322d06270f111288..8159fb182a18d05575704723c6646cea9eff3eeb 100644 (file)
@@ -516,12 +516,6 @@ fn clear_if_dirty(&self, dir: &Path, input: &Path) -> bool {
     fn std_features(&self) -> String {
         let mut features = "panic-unwind".to_string();
 
-        if self.config.debug_jemalloc {
-            features.push_str(" debug-jemalloc");
-        }
-        if self.config.use_jemalloc {
-            features.push_str(" jemalloc");
-        }
         if self.config.backtrace {
             features.push_str(" backtrace");
         }
@@ -537,8 +531,8 @@ fn std_features(&self) -> String {
     /// Get the space-separated set of activated features for the compiler.
     fn rustc_features(&self) -> String {
         let mut features = String::new();
-        if self.config.use_jemalloc {
-            features.push_str(" jemalloc");
+        if self.config.jemalloc {
+            features.push_str("jemalloc");
         }
         features
     }
@@ -791,7 +785,7 @@ fn cflags(&self, target: Interned<String>, which: GitRepo) -> Vec<String> {
         // If we're compiling on macOS then we add a few unconditional flags
         // indicating that we want libc++ (more filled out than libstdc++) and
         // we want to compile for 10.7. This way we can ensure that
-        // LLVM/jemalloc/etc are all properly compiled.
+        // LLVM/etc are all properly compiled.
         if target.contains("apple-darwin") {
             base.push("-stdlib=libc++".into());
         }
index 2eb11b06e4e08acaa0e614495643c50b9f2b3fb1..15d3bccba09cc6e448b63240d0cefc0259a79460 100644 (file)
@@ -152,12 +152,6 @@ pub fn check(build: &mut Build) {
         if !build.config.dry_run {
             cmd_finder.must_have(build.cxx(*host).unwrap());
         }
-
-        // The msvc hosts don't use jemalloc, turn it off globally to
-        // avoid packaging the dummy liballoc_jemalloc on that platform.
-        if host.contains("msvc") {
-            build.config.use_jemalloc = false;
-        }
     }
 
     // Externally configured LLVM requires FileCheck to exist
index e411e0d17342ef66e092c6aaead0bd95e1510349..e55773011df8eb41f157e3959fbbc5254ac33308 100644 (file)
@@ -1504,8 +1504,7 @@ impl Step for CrateNotDefault {
     type Output = ();
 
     fn should_run(run: ShouldRun) -> ShouldRun {
-        run.path("src/liballoc_jemalloc")
-            .path("src/librustc_asan")
+        run.path("src/librustc_asan")
             .path("src/librustc_lsan")
             .path("src/librustc_msan")
             .path("src/librustc_tsan")
@@ -1522,7 +1521,6 @@ fn make_run(run: RunConfig) {
             target: run.target,
             test_kind,
             krate: match run.path {
-                _ if run.path.ends_with("src/liballoc_jemalloc") => "alloc_jemalloc",
                 _ if run.path.ends_with("src/librustc_asan") => "rustc_asan",
                 _ if run.path.ends_with("src/librustc_lsan") => "rustc_lsan",
                 _ if run.path.ends_with("src/librustc_msan") => "rustc_msan",
@@ -1561,7 +1559,6 @@ fn should_run(mut run: ShouldRun) -> ShouldRun {
         run = run.krate("test");
         for krate in run.builder.in_tree_crates("std") {
             if krate.is_local(&run.builder)
-                && !krate.name.contains("jemalloc")
                 && !(krate.name.starts_with("rustc_") && krate.name.ends_with("san"))
                 && krate.name != "dlmalloc"
             {
index d99e409e42671f3acafbecc4f52c8726fbf0df48..8df49f364a372eb50d6b9edbd7d9e850652ffc37 100644 (file)
@@ -98,7 +98,8 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-sanitizers \
       --enable-profiler \
       --set target.i686-unknown-linux-gnu.linker=clang \
-      --build=i686-unknown-linux-gnu
+      --build=i686-unknown-linux-gnu \
+      --set rust.jemalloc
 ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS
 ENV CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER=clang
 
index 8696f72e0e3881004fcaa77b4a576c714a1d30ed..0a2dae72f73828d7497625f6de96c1efdf2a67c8 100644 (file)
@@ -101,7 +101,8 @@ ENV RUST_CONFIGURE_ARGS \
       --set target.x86_64-unknown-linux-gnu.linker=clang \
       --set target.x86_64-unknown-linux-gnu.ar=/rustroot/bin/llvm-ar \
       --set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \
-      --set llvm.thin-lto=true
+      --set llvm.thin-lto=true \
+      --set rust.jemalloc
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
 ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
 
diff --git a/src/jemalloc b/src/jemalloc
deleted file mode 160000 (submodule)
index 1f5a287..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 1f5a28755e301ac581e2048011e4e0ff3da482ef
index f989e701913a573750578d0a32bab6a6598f60fc..74354f605e5370d1824dc58d03d0b4266e4ce23a 100644 (file)
@@ -77,7 +77,7 @@
 use core::marker::{Unpin, Unsize};
 use core::mem;
 use core::pin::Pin;
-use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
+use core::ops::{CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Generator, GeneratorState};
 use core::ptr::{self, NonNull, Unique};
 use core::task::{LocalWaker, Poll};
 
@@ -696,6 +696,9 @@ extern "rust-call" fn call_once(self, args: A) -> R {
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
 
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
+
 #[stable(feature = "box_slice_clone", since = "1.3.0")]
 impl<T: Clone> Clone for Box<[T]> {
     fn clone(&self) -> Self {
index 7db6261a01c0b0324180c59b08b0064731e6a22f..ad6e594c884af9674c7311ffcd0200bac1fd79da 100644 (file)
@@ -86,6 +86,7 @@
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
+#![feature(dispatch_from_dyn)]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
 #![feature(dropck_eyepatch)]
index 3e8dfd105de2ecf0dde779bdf38727fd8cd71321..be452ebb45a3cae2b2ad54c04b2d5c38aa0dd65b 100644 (file)
 use core::marker::{Unpin, Unsize, PhantomData};
 use core::mem::{self, align_of_val, forget, size_of_val};
 use core::ops::Deref;
-use core::ops::CoerceUnsized;
+use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
 use core::convert::From;
@@ -297,6 +297,9 @@ impl<T: ?Sized> !marker::Sync for Rc<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
 
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
+
 impl<T> Rc<T> {
     /// Constructs a new `Rc<T>`.
     ///
@@ -1176,6 +1179,9 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
+
 impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
     /// Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`].
index bcf5212f1ff6f2afb5b934cd6b64aee976e9e909..d388f76d8e84c1686ff2dd5a5482a5bffdcdce9a 100644 (file)
@@ -25,7 +25,7 @@
 use core::intrinsics::abort;
 use core::mem::{self, align_of_val, size_of_val};
 use core::ops::Deref;
-use core::ops::CoerceUnsized;
+use core::ops::{CoerceUnsized, DispatchFromDyn};
 use core::pin::Pin;
 use core::ptr::{self, NonNull};
 use core::marker::{Unpin, Unsize, PhantomData};
@@ -214,6 +214,9 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Arc<U>> for Arc<T> {}
+
 /// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
 /// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
 /// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
@@ -254,6 +257,8 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Weak<U>> for Weak<T> {}
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
index 6fa88ce969a0e4866941b80337bd2c5841d31a06..b6be38107da7f33eefd4607b3cd6c3f145a5de7f 100644 (file)
@@ -12,9 +12,6 @@
 use std::alloc::{Global, Alloc, Layout};
 
 /// https://github.com/rust-lang/rust/issues/45955
-///
-/// Note that `#[global_allocator]` is not used,
-/// so `liballoc_jemalloc` is linked (on some platforms).
 #[test]
 fn alloc_system_overaligned_request() {
     check_overalign_requests(System)
diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml
deleted file mode 100644 (file)
index 7986d5d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "alloc_jemalloc"
-version = "0.0.0"
-build = "build.rs"
-links = "jemalloc"
-
-[lib]
-name = "alloc_jemalloc"
-path = "lib.rs"
-test = false
-doc = false
-
-[dependencies]
-core = { path = "../libcore" }
-libc = { path = "../rustc/libc_shim" }
-compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
-
-[build-dependencies]
-build_helper = { path = "../build_helper" }
-cc = "1.0.1"
-
-[features]
-debug = []
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
deleted file mode 100644 (file)
index fbda425..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![deny(warnings)]
-
-extern crate build_helper;
-extern crate cc;
-
-use std::env;
-use std::path::PathBuf;
-use std::process::Command;
-use build_helper::{run, native_lib_boilerplate};
-
-fn main() {
-    // FIXME: This is a hack to support building targets that don't
-    // support jemalloc alongside hosts that do. The jemalloc build is
-    // controlled by a feature of the std crate, and if that feature
-    // changes between targets, it invalidates the fingerprint of
-    // std's build script (this is a cargo bug); so we must ensure
-    // that the feature set used by std is the same across all
-    // targets, which means we have to build the alloc_jemalloc crate
-    // for targets like emscripten, even if we don't use it.
-    let target = env::var("TARGET").expect("TARGET was not set");
-    let host = env::var("HOST").expect("HOST was not set");
-    if target.contains("bitrig") || target.contains("emscripten") || target.contains("fuchsia") ||
-       target.contains("msvc") || target.contains("openbsd") || target.contains("redox") ||
-       target.contains("rumprun") || target.contains("wasm32") {
-        println!("cargo:rustc-cfg=dummy_jemalloc");
-        return;
-    }
-
-    // CloudABI ships with a copy of jemalloc that has been patched to
-    // work well with sandboxing. Don't attempt to build our own copy,
-    // as it won't build.
-    if target.contains("cloudabi") {
-        return;
-    }
-
-    if target.contains("android") {
-        println!("cargo:rustc-link-lib=gcc");
-    } else if !target.contains("windows") && !target.contains("musl") {
-        println!("cargo:rustc-link-lib=pthread");
-    }
-
-    if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") {
-        let jemalloc = PathBuf::from(jemalloc);
-        println!("cargo:rustc-link-search=native={}",
-                 jemalloc.parent().unwrap().display());
-        let stem = jemalloc.file_stem().unwrap().to_str().unwrap();
-        let name = jemalloc.file_name().unwrap().to_str().unwrap();
-        let kind = if name.ends_with(".a") {
-            "static"
-        } else {
-            "dylib"
-        };
-        println!("cargo:rustc-link-lib={}={}", kind, &stem[3..]);
-        return;
-    }
-
-    let link_name = if target.contains("windows") { "jemalloc" } else { "jemalloc_pic" };
-    let native = match native_lib_boilerplate("jemalloc", "jemalloc", link_name, "lib") {
-        Ok(native) => native,
-        _ => return,
-    };
-
-    let mut cmd = Command::new("sh");
-    cmd.arg(native.src_dir.join("configure")
-                          .to_str()
-                          .unwrap()
-                          .replace("C:\\", "/c/")
-                          .replace("\\", "/"))
-       .current_dir(&native.out_dir)
-       // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
-       // that GCC will run the preprocessor, and only the preprocessor, over
-       // jemalloc's source files. If we don't specify CPPFLAGS, then at least
-       // on ARM that step fails with a "Missing implementation for 32-bit
-       // atomic operations" error. This is because no "-march" flag will be
-       // passed to GCC, and then GCC won't define the
-       // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
-       // select an atomic operation implementation.
-       .env("CPPFLAGS", env::var_os("CFLAGS").unwrap_or_default());
-
-    if target.contains("ios") {
-        cmd.arg("--disable-tls");
-    } else if target.contains("android") {
-        // We force android to have prefixed symbols because apparently
-        // replacement of the libc allocator doesn't quite work. When this was
-        // tested (unprefixed symbols), it was found that the `realpath`
-        // function in libc would allocate with libc malloc (not jemalloc
-        // malloc), and then the standard library would free with jemalloc free,
-        // causing a segfault.
-        //
-        // If the test suite passes, however, without symbol prefixes then we
-        // should be good to go!
-        cmd.arg("--with-jemalloc-prefix=je_");
-        cmd.arg("--disable-tls");
-    } else if target.contains("dragonfly") || target.contains("musl") {
-        cmd.arg("--with-jemalloc-prefix=je_");
-    }
-
-    if cfg!(feature = "debug") {
-        // Enable jemalloc assertions.
-        cmd.arg("--enable-debug");
-    }
-
-    cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
-    cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
-
-    // for some reason, jemalloc configure doesn't detect this value
-    // automatically for this target
-    if target == "sparc64-unknown-linux-gnu" {
-        cmd.arg("--with-lg-quantum=4");
-    }
-
-    run(&mut cmd);
-
-    let mut make = Command::new(build_helper::make(&host));
-    make.current_dir(&native.out_dir)
-        .arg("build_lib_static");
-
-    // These are intended for mingw32-make which we don't use
-    if cfg!(windows) {
-        make.env_remove("MAKEFLAGS").env_remove("MFLAGS");
-    }
-
-    // mingw make seems... buggy? unclear...
-    if !host.contains("windows") {
-        make.arg("-j")
-            .arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set"));
-    }
-
-    run(&mut make);
-
-    // The pthread_atfork symbols is used by jemalloc on android but the really
-    // old android we're building on doesn't have them defined, so just make
-    // sure the symbols are available.
-    if target.contains("androideabi") {
-        println!("cargo:rerun-if-changed=pthread_atfork_dummy.c");
-        cc::Build::new()
-            .flag("-fvisibility=hidden")
-            .file("pthread_atfork_dummy.c")
-            .compile("pthread_atfork_dummy");
-    }
-}
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
deleted file mode 100644 (file)
index 0065e84..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![no_std]
-#![allow(unused_attributes)]
-#![unstable(feature = "alloc_jemalloc",
-            reason = "implementation detail of std, does not provide any public API",
-            issue = "0")]
-#![feature(core_intrinsics)]
-#![feature(libc)]
-#![feature(linkage)]
-#![feature(nll)]
-#![feature(staged_api)]
-#![feature(rustc_attrs)]
-#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
-#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
-#![rustc_alloc_kind = "exe"]
-
-extern crate libc;
-
-#[cfg(not(dummy_jemalloc))]
-pub use contents::*;
-#[cfg(not(dummy_jemalloc))]
-mod contents {
-    use libc::{c_int, c_void, size_t};
-
-    // Note that the symbols here are prefixed by default on macOS and Windows (we
-    // don't explicitly request it), and on Android and DragonFly we explicitly
-    // request it as unprefixing cause segfaults (mismatches in allocators).
-    extern "C" {
-        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
-                   link_name = "je_mallocx")]
-        fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
-        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
-                   link_name = "je_calloc")]
-        fn calloc(size: size_t, flags: c_int) -> *mut c_void;
-        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
-                   link_name = "je_rallocx")]
-        fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
-        #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
-                       target_os = "dragonfly", target_os = "windows", target_env = "musl"),
-                   link_name = "je_sdallocx")]
-        fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
-    }
-
-    const MALLOCX_ZERO: c_int = 0x40;
-
-    // The minimum alignment guaranteed by the architecture. This value is used to
-    // add fast paths for low alignment values.
-    #[cfg(all(any(target_arch = "arm",
-                  target_arch = "mips",
-                  target_arch = "powerpc")))]
-    const MIN_ALIGN: usize = 8;
-    #[cfg(all(any(target_arch = "x86",
-                  target_arch = "x86_64",
-                  target_arch = "aarch64",
-                  target_arch = "powerpc64",
-                  target_arch = "mips64",
-                  target_arch = "s390x",
-                  target_arch = "sparc64")))]
-    const MIN_ALIGN: usize = 16;
-
-    // MALLOCX_ALIGN(a) macro
-    fn mallocx_align(a: usize) -> c_int {
-        a.trailing_zeros() as c_int
-    }
-
-    fn align_to_flags(align: usize, size: usize) -> c_int {
-        if align <= MIN_ALIGN && align <= size {
-            0
-        } else {
-            mallocx_align(align)
-        }
-    }
-
-    // for symbol names src/librustc/middle/allocator.rs
-    // for signatures src/librustc_allocator/lib.rs
-
-    // linkage directives are provided as part of the current compiler allocator
-    // ABI
-
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
-        let flags = align_to_flags(align, size);
-        let ptr = mallocx(size as size_t, flags) as *mut u8;
-        ptr
-    }
-
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
-                                       size: usize,
-                                       align: usize) {
-        let flags = align_to_flags(align, size);
-        sdallocx(ptr as *mut c_void, size, flags);
-    }
-
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_realloc(ptr: *mut u8,
-                                       _old_size: usize,
-                                       align: usize,
-                                       new_size: usize) -> *mut u8 {
-        let flags = align_to_flags(align, new_size);
-        let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
-        ptr
-    }
-
-    #[rustc_std_internal_symbol]
-    pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
-        let ptr = if align <= MIN_ALIGN && align <= size {
-            calloc(size as size_t, 1) as *mut u8
-        } else {
-            let flags = align_to_flags(align, size) | MALLOCX_ZERO;
-            mallocx(size as size_t, flags) as *mut u8
-        };
-        ptr
-    }
-}
diff --git a/src/liballoc_jemalloc/pthread_atfork_dummy.c b/src/liballoc_jemalloc/pthread_atfork_dummy.c
deleted file mode 100644 (file)
index 4e3df0a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// See comments in build.rs for why this exists
-int pthread_atfork(void* prefork,
-                   void* postfork_parent,
-                   void* postfork_child) {
-  return 0;
-}
index 118e75e1ee70469bb275185650ab904a0effc251..436cd1fc0572837e408407e9d0bb7b310eea92b2 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Exposes the NonZero lang item which provides optimization hints.
 
-use ops::CoerceUnsized;
+use ops::{CoerceUnsized, DispatchFromDyn};
 
 /// A wrapper type for raw pointers and integers that will never be
 /// NULL or 0 that might allow certain optimizations.
@@ -20,3 +20,5 @@
 pub(crate) struct NonZero<T>(pub(crate) T);
 
 impl<T: CoerceUnsized<U>, U> CoerceUnsized<NonZero<U>> for NonZero<T> {}
+
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<NonZero<U>> for NonZero<T> {}
index ce4f45762de48d3571a3f8e68660262c6d844a75..edfa6df11aceb6e958273084271ccf87762d20e9 100644 (file)
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 pub use self::unsize::CoerceUnsized;
+
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+pub use self::unsize::DispatchFromDyn;
index da72f3748425d9f1e77b54c837dddf9a339b9a28..4d9a40a1b9089b078ee08dc453d9d16870ada099 100644 (file)
@@ -43,7 +43,7 @@
 /// [nomicon-coerce]: ../../nomicon/coercions.html
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 #[lang = "coerce_unsized"]
-pub trait CoerceUnsized<T> {
+pub trait CoerceUnsized<T: ?Sized> {
     // Empty.
 }
 
@@ -77,3 +77,37 @@ impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
 // *const T -> *const U
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
+
+
+/// This is used for object safety, to check that a method's receiver type can be dispatched on.
+///
+/// example impl:
+///
+/// ```
+/// # #![feature(dispatch_from_dyn, unsize)]
+/// # use std::{ops::DispatchFromDyn, marker::Unsize};
+/// # struct Rc<T: ?Sized>(::std::rc::Rc<T>);
+/// impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T>
+/// where
+///     T: Unsize<U>,
+/// {}
+/// ```
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+#[cfg_attr(not(stage0), lang = "dispatch_from_dyn")]
+pub trait DispatchFromDyn<T> {
+    // Empty.
+}
+
+// &T -> &U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
+// &mut T -> &mut U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
+// *const T -> *const U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
+// *mut T -> *mut U
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
+
index a03c080fb3f3418fad92dba5a06c1390f168de3a..68de82d294529e5cefa0d3eae3159a00674849f3 100644 (file)
@@ -91,7 +91,7 @@
 
 use fmt;
 use marker::Sized;
-use ops::{Deref, DerefMut, CoerceUnsized};
+use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn};
 
 #[doc(inline)]
 pub use marker::Unpin;
@@ -324,5 +324,11 @@ impl<P, U> CoerceUnsized<Pin<U>> for Pin<P>
     P: CoerceUnsized<U>,
 {}
 
+#[unstable(feature = "pin", issue = "49150")]
+impl<'a, P, U> DispatchFromDyn<Pin<U>> for Pin<P>
+where
+    P: DispatchFromDyn<U>,
+{}
+
 #[unstable(feature = "pin", issue = "49150")]
 impl<P> Unpin for Pin<P> {}
index 36852b10facde2a2222d6b933d78bf8f4578a503..62ccf6c865cd96735a92bf30969e5be5de08f815 100644 (file)
@@ -75,7 +75,7 @@
 
 use convert::From;
 use intrinsics;
-use ops::CoerceUnsized;
+use ops::{CoerceUnsized, DispatchFromDyn};
 use fmt;
 use hash;
 use marker::{PhantomData, Unsize};
@@ -2795,6 +2795,9 @@ impl<T: ?Sized> Copy for Unique<T> { }
 #[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
 
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
+
 #[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> fmt::Pointer for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -2951,6 +2954,9 @@ impl<T: ?Sized> Copy for NonNull<T> { }
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
 
+#[unstable(feature = "dispatch_from_dyn", issue = "0")]
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
+
 #[stable(feature = "nonnull", since = "1.25.0")]
 impl<T: ?Sized> fmt::Debug for NonNull<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
index 091ea9f52ff6249047c9d446d37e07df53b6f251..7d25ecedb4e046de7389bc32359f47dbd45dfc5f 100644 (file)
@@ -100,9 +100,6 @@ fn hash_stable<W: StableHasherResult>(&self,
             ty::ReEmpty => {
                 // No variant fields to hash for these ...
             }
-            ty::ReCanonical(c) => {
-                c.hash_stable(hcx, hasher);
-            }
             ty::ReLateBound(db, ty::BrAnon(i)) => {
                 db.hash_stable(hcx, hasher);
                 i.hash_stable(hcx, hasher);
@@ -147,7 +144,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
-impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundTyIndex {
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundVar {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
@@ -852,6 +849,9 @@ fn hash_stable<W: StableHasherResult>(&self,
             Param(param_ty) => {
                 param_ty.hash_stable(hcx, hasher);
             }
+            Bound(bound_ty) => {
+                bound_ty.hash_stable(hcx, hasher);
+            }
             Foreign(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
@@ -869,7 +869,6 @@ fn hash_stable<W: StableHasherResult>(&self,
     FreshTy(a),
     FreshIntTy(a),
     FreshFloatTy(a),
-    BoundTy(a),
 });
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
index cc6e4df07103307c72730fb6865b1ad7ffffc944..61a861a8a1cd8b193a08c3a269c1641973498d31 100644 (file)
@@ -23,7 +23,7 @@
 use std::sync::atomic::Ordering;
 use ty::fold::{TypeFoldable, TypeFolder};
 use ty::subst::Kind;
-use ty::{self, BoundTy, BoundTyIndex, Lift, List, Ty, TyCtxt, TypeFlags};
+use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
@@ -277,9 +277,11 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     query_state: &'cx mut OriginalQueryValues<'tcx>,
     // Note that indices is only used once `var_values` is big enough to be
     // heap-allocated.
-    indices: FxHashMap<Kind<'tcx>, BoundTyIndex>,
+    indices: FxHashMap<Kind<'tcx>, BoundVar>,
     canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
     needs_canonical_flags: TypeFlags,
+
+    binder_index: ty::DebruijnIndex,
 }
 
 impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx> {
@@ -287,11 +289,23 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
         self.tcx
     }
 
+    fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
+        where T: TypeFoldable<'tcx>
+    {
+        self.binder_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.binder_index.shift_out(1);
+        t
+    }
+
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
-            ty::ReLateBound(..) => {
-                // leave bound regions alone
-                r
+            ty::ReLateBound(index, ..) => {
+                if index >= self.binder_index {
+                    bug!("escaping late bound region during canonicalization")
+                } else {
+                    r
+                }
             }
 
             ty::ReVar(vid) => {
@@ -317,8 +331,8 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             | ty::ReErased => self.canonicalize_region_mode
                 .canonicalize_free_region(self, r),
 
-            ty::ReClosureBound(..) | ty::ReCanonical(_) => {
-                bug!("canonical region encountered during canonicalization")
+            ty::ReClosureBound(..) => {
+                bug!("closure bound region encountered during canonicalization")
             }
         }
     }
@@ -337,8 +351,12 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 bug!("encountered a fresh type during canonicalization")
             }
 
-            ty::Infer(ty::BoundTy(_)) => {
-                bug!("encountered a canonical type during canonicalization")
+            ty::Bound(bound_ty) => {
+                if bound_ty.index >= self.binder_index {
+                    bug!("escaping bound type during canonicalization")
+                } else {
+                    t
+                }
             }
 
             ty::Closure(..)
@@ -389,12 +407,6 @@ fn canonicalize<V>(
     where
         V: TypeFoldable<'tcx> + Lift<'gcx>,
     {
-        debug_assert!(
-            !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS),
-            "canonicalizing a canonical value: {:?}",
-            value,
-        );
-
         let needs_canonical_flags = if canonicalize_region_mode.any() {
             TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX
         } else {
@@ -422,6 +434,7 @@ fn canonicalize<V>(
             variables: SmallVec::new(),
             query_state,
             indices: FxHashMap::default(),
+            binder_index: ty::INNERMOST,
         };
         let out_value = value.fold_with(&mut canonicalizer);
 
@@ -455,7 +468,7 @@ fn canonicalize<V>(
     /// or returns an existing variable if `kind` has already been
     /// seen. `kind` is expected to be an unbound variable (or
     /// potentially a free region).
-    fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy {
+    fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundVar {
         let Canonicalizer {
             variables,
             query_state,
@@ -475,7 +488,7 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy
             // direct linear search of `var_values`.
             if let Some(idx) = var_values.iter().position(|&k| k == kind) {
                 // `kind` is already present in `var_values`.
-                BoundTyIndex::new(idx)
+                BoundVar::new(idx)
             } else {
                 // `kind` isn't present in `var_values`. Append it. Likewise
                 // for `info` and `variables`.
@@ -490,11 +503,11 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy
                     *indices = var_values
                         .iter()
                         .enumerate()
-                        .map(|(i, &kind)| (kind, BoundTyIndex::new(i)))
+                        .map(|(i, &kind)| (kind, BoundVar::new(i)))
                         .collect();
                 }
                 // The cv is the index of the appended element.
-                BoundTyIndex::new(var_values.len() - 1)
+                BoundVar::new(var_values.len() - 1)
             }
         } else {
             // `var_values` is large. Do a hashmap search via `indices`.
@@ -502,14 +515,11 @@ fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy
                 variables.push(info);
                 var_values.push(kind);
                 assert_eq!(variables.len(), var_values.len());
-                BoundTyIndex::new(variables.len() - 1)
+                BoundVar::new(variables.len() - 1)
             })
         };
 
-        BoundTy {
-            level: ty::INNERMOST,
-            var,
-        }
+        var
     }
 
     /// Shorthand helper that creates a canonical region variable for
@@ -552,9 +562,12 @@ fn canonical_var_for_region(
         info: CanonicalVarInfo,
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
-        let b = self.canonical_var(info, r.into());
-        debug_assert_eq!(ty::INNERMOST, b.level);
-        self.tcx().mk_region(ty::ReCanonical(b.var))
+        let var = self.canonical_var(info, r.into());
+        let region = ty::ReLateBound(
+            self.binder_index,
+            ty::BoundRegion::BrAnon(var.as_u32())
+        );
+        self.tcx().mk_region(region)
     }
 
     /// Given a type variable `ty_var` of the given kind, first check
@@ -570,9 +583,8 @@ fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>)
             let info = CanonicalVarInfo {
                 kind: CanonicalVarKind::Ty(ty_kind),
             };
-            let b = self.canonical_var(info, ty_var.into());
-            debug_assert_eq!(ty::INNERMOST, b.level);
-            self.tcx().mk_infer(ty::InferTy::BoundTy(b))
+            let var = self.canonical_var(info, ty_var.into());
+            self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
         }
     }
 }
index f2b7c6e0d0d986760762fae0e4f42cf39f654ee6..f7eb7118f412f6f0c55676c6966eff30628f8104 100644 (file)
@@ -20,7 +20,7 @@
 //! - a map M (of type `CanonicalVarValues`) from those canonical
 //!   variables back to the original.
 //!
-//! We can then do queries using T2. These will give back constriants
+//! We can then do queries using T2. These will give back constraints
 //! on the canonical variables which can be translated, using the map
 //! M, into constraints in our source context. This process of
 //! translating the results back is done by the
@@ -40,7 +40,7 @@
 use syntax::source_map::Span;
 use ty::fold::TypeFoldable;
 use ty::subst::Kind;
-use ty::{self, BoundTyIndex, Lift, List, Region, TyCtxt};
+use ty::{self, BoundVar, Lift, List, Region, TyCtxt};
 
 mod canonicalizer;
 
@@ -73,7 +73,7 @@ impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {}
 /// canonicalized query response.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
 pub struct CanonicalVarValues<'tcx> {
-    pub var_values: IndexVec<BoundTyIndex, Kind<'tcx>>,
+    pub var_values: IndexVec<BoundVar, Kind<'tcx>>,
 }
 
 /// When we canonicalize a value to form a query, we wind up replacing
@@ -337,7 +337,7 @@ fn instantiate_canonical_vars(
         variables: &List<CanonicalVarInfo>,
         universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
     ) -> CanonicalVarValues<'tcx> {
-        let var_values: IndexVec<BoundTyIndex, Kind<'tcx>> = variables
+        let var_values: IndexVec<BoundVar, Kind<'tcx>> = variables
             .iter()
             .map(|info| self.instantiate_canonical_var(span, *info, &universe_map))
             .collect();
@@ -456,10 +456,10 @@ impl<'a, 'tcx, R> Lift<'tcx> for QueryResponse<'a, R> {
     } where R: Lift<'tcx>
 }
 
-impl<'tcx> Index<BoundTyIndex> for CanonicalVarValues<'tcx> {
+impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
     type Output = Kind<'tcx>;
 
-    fn index(&self, value: BoundTyIndex) -> &Kind<'tcx> {
+    fn index(&self, value: BoundVar) -> &Kind<'tcx> {
         &self.var_values[value]
     }
 }
index b3ce5eb7e56c26dee4fac39f0f845186b99824e2..f4607f7a9092f4ee01bd6a31b534bc06a88a1d84 100644 (file)
@@ -35,7 +35,7 @@
 use traits::{Obligation, ObligationCause, PredicateObligation};
 use ty::fold::TypeFoldable;
 use ty::subst::{Kind, UnpackedKind};
-use ty::{self, BoundTyIndex, Lift, Ty, TyCtxt};
+use ty::{self, BoundVar, Lift, Ty, TyCtxt};
 
 impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
     /// The "main method" for a canonicalized trait query. Given the
@@ -273,7 +273,7 @@ pub fn instantiate_nll_query_response_and_region_obligations<R>(
         for (index, original_value) in original_values.var_values.iter().enumerate() {
             // ...with the value `v_r` of that variable from the query.
             let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| {
-                &v.var_values[BoundTyIndex::new(index)]
+                &v.var_values[BoundVar::new(index)]
             });
             match (original_value.unpack(), result_value.unpack()) {
                 (UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => {
@@ -308,11 +308,14 @@ pub fn instantiate_nll_query_response_and_region_obligations<R>(
         // ...also include the other query region constraints from the query.
         output_query_region_constraints.extend(
             query_response.value.region_constraints.iter().filter_map(|r_c| {
-                let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
-                let k1 = substitute_value(self.tcx, &result_subst, &k1);
-                let r2 = substitute_value(self.tcx, &result_subst, &r2);
+                let r_c = substitute_value(self.tcx, &result_subst, r_c);
+
+                // Screen out `'a: 'a` cases -- we skip the binder here but
+                // only care the inner values to one another, so they are still at
+                // consistent binding levels.
+                let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder();
                 if k1 != r2.into() {
-                    Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)))
+                    Some(r_c)
                 } else {
                     None
                 }
@@ -423,7 +426,7 @@ fn query_response_substitution_guess<R>(
         // is directly equal to one of the canonical variables in the
         // result, then we can type the corresponding value from the
         // input. See the example above.
-        let mut opt_values: IndexVec<BoundTyIndex, Option<Kind<'tcx>>> =
+        let mut opt_values: IndexVec<BoundVar, Option<Kind<'tcx>>> =
             IndexVec::from_elem_n(None, query_response.variables.len());
 
         // In terms of our example above, we are iterating over pairs like:
@@ -432,16 +435,22 @@ fn query_response_substitution_guess<R>(
             match result_value.unpack() {
                 UnpackedKind::Type(result_value) => {
                     // e.g., here `result_value` might be `?0` in the example above...
-                    if let ty::Infer(ty::InferTy::BoundTy(b)) = result_value.sty {
-                        // in which case we would set `canonical_vars[0]` to `Some(?U)`.
+                    if let ty::Bound(b) = result_value.sty {
+                        // ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
+
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(b.index, ty::INNERMOST);
                         opt_values[b.var] = Some(*original_value);
                     }
                 }
                 UnpackedKind::Lifetime(result_value) => {
                     // e.g., here `result_value` might be `'?1` in the example above...
-                    if let &ty::RegionKind::ReCanonical(index) = result_value {
-                        // in which case we would set `canonical_vars[0]` to `Some('static)`.
-                        opt_values[index] = Some(*original_value);
+                    if let &ty::RegionKind::ReLateBound(index, br) = result_value {
+                        // ... in which case we would set `canonical_vars[0]` to `Some('static)`.
+
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(index, ty::INNERMOST);
+                        opt_values[br.assert_bound_var()] = Some(*original_value);
                     }
                 }
             }
@@ -457,7 +466,7 @@ fn query_response_substitution_guess<R>(
                 .enumerate()
                 .map(|(index, info)| {
                     if info.is_existential() {
-                        match opt_values[BoundTyIndex::new(index)] {
+                        match opt_values[BoundVar::new(index)] {
                             Some(k) => k,
                             None => self.instantiate_canonical_var(cause.span, *info, |u| {
                                 universe_map[u.as_usize()]
@@ -496,7 +505,7 @@ fn unify_query_response_substitution_guess<R>(
         // canonical variable; this is taken from
         // `query_response.var_values` after applying the substitution
         // `result_subst`.
-        let substituted_query_response = |index: BoundTyIndex| -> Kind<'tcx> {
+        let substituted_query_response = |index: BoundVar| -> Kind<'tcx> {
             query_response.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
         };
 
@@ -523,22 +532,23 @@ fn query_region_constraints_into_obligations<'a>(
             unsubstituted_region_constraints
                 .iter()
                 .map(move |constraint| {
-                    let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
-                    let k1 = substitute_value(self.tcx, result_subst, k1);
-                    let r2 = substitute_value(self.tcx, result_subst, r2);
+                    let constraint = substitute_value(self.tcx, result_subst, constraint);
+                    let &ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
 
                     Obligation::new(
                         cause.clone(),
                         param_env,
                         match k1.unpack() {
                             UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
-                                ty::Binder::dummy(
+                                ty::Binder::bind(
                                     ty::OutlivesPredicate(r1, r2)
-                            )),
+                                )
+                            ),
                             UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
-                                ty::Binder::dummy(ty::OutlivesPredicate(
-                                    t1, r2
-                            )))
+                                ty::Binder::bind(
+                                    ty::OutlivesPredicate(t1, r2)
+                                )
+                            ),
                         }
                     )
                 })
@@ -552,12 +562,12 @@ fn unify_canonical_vars(
         cause: &ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         variables1: &OriginalQueryValues<'tcx>,
-        variables2: impl Fn(BoundTyIndex) -> Kind<'tcx>,
+        variables2: impl Fn(BoundVar) -> Kind<'tcx>,
     ) -> InferResult<'tcx, ()> {
         self.commit_if_ok(|_| {
             let mut obligations = vec![];
             for (index, value1) in variables1.var_values.iter().enumerate() {
-                let value2 = variables2(BoundTyIndex::new(index));
+                let value2 = variables2(BoundVar::new(index));
 
                 match (value1.unpack(), value2.unpack()) {
                     (UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => {
@@ -620,11 +630,11 @@ pub fn make_query_outlives<'tcx>(
             }
             Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
         })
-        .map(ty::Binder::dummy) // no bound regions in the code above
+        .map(ty::Binder::dummy) // no bound vars in the code above
         .chain(
             outlives_obligations
                 .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
-                .map(ty::Binder::dummy), // no bound regions in the code above
+                .map(ty::Binder::dummy) // no bound vars in the code above
         )
         .collect();
 
index 03441c3dee35e2ba40c49fb6b7e12bbe19fa3afa..b8c1ed236c0ba17aededa8aff24c46641052eb22 100644 (file)
@@ -17,9 +17,9 @@
 //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
 
 use infer::canonical::{Canonical, CanonicalVarValues};
-use ty::fold::{TypeFoldable, TypeFolder};
+use ty::fold::TypeFoldable;
 use ty::subst::UnpackedKind;
-use ty::{self, Ty, TyCtxt, TypeFlags};
+use ty::{self, TyCtxt};
 
 impl<'tcx, V> Canonical<'tcx, V> {
     /// Instantiate the wrapped value, replacing each canonical value
@@ -64,51 +64,22 @@ pub(super) fn substitute_value<'a, 'tcx, T>(
     T: TypeFoldable<'tcx>,
 {
     if var_values.var_values.is_empty() {
-        debug_assert!(!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS));
-        value.clone()
-    } else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
         value.clone()
     } else {
-        value.fold_with(&mut CanonicalVarValuesSubst { tcx, var_values })
-    }
-}
-
-struct CanonicalVarValuesSubst<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
-    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-    var_values: &'cx CanonicalVarValues<'tcx>,
-}
-
-impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'gcx, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx> {
-        self.tcx
-    }
-
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        match t.sty {
-            ty::Infer(ty::InferTy::BoundTy(b)) => {
-                debug_assert_eq!(ty::INNERMOST, b.level);
-                match self.var_values.var_values[b.var].unpack() {
-                    UnpackedKind::Type(ty) => ty,
-                    r => bug!("{:?} is a type but value is {:?}", b, r),
-                }
+        let fld_r = |br: ty::BoundRegion| {
+            match var_values.var_values[br.assert_bound_var()].unpack() {
+                UnpackedKind::Lifetime(l) => l,
+                r => bug!("{:?} is a region but value is {:?}", br, r),
             }
-            _ => {
-                if !t.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
-                    t
-                } else {
-                    t.super_fold_with(self)
-                }
+        };
+
+        let fld_t = |bound_ty: ty::BoundTy| {
+            match var_values.var_values[bound_ty.var].unpack() {
+                UnpackedKind::Type(ty) => ty,
+                r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
             }
-        }
-    }
+        };
 
-    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match r {
-            ty::RegionKind::ReCanonical(c) => match self.var_values.var_values[*c].unpack() {
-                UnpackedKind::Lifetime(l) => l,
-                r => bug!("{:?} is a region but value is {:?}", c, r),
-            },
-            _ => r.super_fold_with(self),
-        }
+        tcx.replace_escaping_bound_vars(value, fld_r, fld_t)
     }
 }
index 0ee03bc4c6e00902d0026a78e23b8be1c63a0a5d..f13210926a79b77361e21c83c2d5f3b814b7d88f 100644 (file)
@@ -485,7 +485,6 @@ fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>)
                 }
             }
 
-            ty::ReCanonical(..) |
             ty::ReClosureBound(..) => {
                 span_bug!(
                     self.span,
index d19c495af3b9685c11240ace5d55bfc4dcc9b4ad..1963d366e7a66d5d5daa5ba3111852663416bd6c 100644 (file)
@@ -152,7 +152,7 @@ pub fn note_and_explain_region(
             }
 
             // We shouldn't encounter an error message with ReClosureBound.
-            ty::ReCanonical(..) | ty::ReClosureBound(..) => {
+            ty::ReClosureBound(..) => {
                 bug!("encountered unexpected ReClosureBound: {:?}", region,);
             }
         };
index 1647f259db9fb27e855ae0db4fe08cdb39480104..b53444992fa216972d4e32b36bbdabd7d36e27d4 100644 (file)
@@ -114,7 +114,6 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 self.tcx().types.re_erased
             }
 
-            ty::ReCanonical(..) |
             ty::ReClosureBound(..) => {
                 bug!(
                     "encountered unexpected region: {:?}",
@@ -171,8 +170,8 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 t
             }
 
-            ty::Infer(ty::BoundTy(..)) =>
-                bug!("encountered canonical ty during freshening"),
+            ty::Bound(..) =>
+                bug!("encountered bound ty during freshening"),
 
             ty::Generator(..) |
             ty::Bool |
index 8f28e9a320df24854af4fb9088387a458310da74..75f503d3bcfb4b331780bcd1e50cc6177f564c9b 100644 (file)
@@ -260,9 +260,7 @@ fn expand_node(
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
         let tcx = self.tcx();
         match (a, b) {
-            (&ty::ReCanonical(..), _)
-            | (_, &ty::ReCanonical(..))
-            | (&ty::ReClosureBound(..), _)
+            (&ty::ReClosureBound(..), _)
             | (_, &ty::ReClosureBound(..))
             | (&ReLateBound(..), _)
             | (_, &ReLateBound(..))
index 5db850f1588b6a24bd4c784d56a28e64751a95a6..523f03c2cfc4773afc81f9c008a0fa7294bb5f92 100644 (file)
@@ -305,7 +305,7 @@ pub fn type_must_outlive(
             ty, region, origin
         );
 
-        assert!(!ty.has_escaping_regions());
+        assert!(!ty.has_escaping_bound_vars());
 
         let components = self.tcx.outlives_components(ty);
         self.components_must_outlive(origin, components, region);
index e1db295b7e14d6e10dcfa3fd006ccbb5ff3b1403..88d45671b9afdfab86538d6a1b6d6345cfeed3ba 100644 (file)
@@ -323,7 +323,7 @@ fn collect_outlives_from_predicate_list(
         predicates
             .into_iter()
             .filter_map(|p| p.as_ref().to_opt_type_outlives())
-            .filter_map(|p| p.no_late_bound_regions())
+            .filter_map(|p| p.no_bound_vars())
             .filter(move |p| compare_ty(p.0))
     }
 }
index c82603bf5605788cbd6db75fb9708df35087c6cc..46b12d01829e7089835c2090715878efd39a79f9 100644 (file)
@@ -833,10 +833,6 @@ fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
             ty::RePlaceholder(placeholder) => placeholder.universe,
             ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid),
             ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
-            ty::ReCanonical(..) => bug!(
-                "region_universe(): encountered canonical region {:?}",
-                region
-            ),
         }
     }
 
index 048810c042722f552de6844b3e5862f1d13b9a53..3b0f9a5e545fde48e157985c952b8b510f9cb83a 100644 (file)
@@ -84,8 +84,8 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 // Shouldn't have any LBR here, so we can safely put
                 // this under a binder below without fear of accidental
                 // capture.
-                assert!(!a.has_escaping_regions());
-                assert!(!b.has_escaping_regions());
+                assert!(!a.has_escaping_bound_vars());
+                assert!(!b.has_escaping_bound_vars());
 
                 // can't make progress on `A <: B` if both A and B are
                 // type variables, so record an obligation. We also
index 45de958e72eba419259b67436915d0e1a2b41d71..cce8081daf28e5b397cd3edb7350e0f1b2309c6b 100644 (file)
@@ -271,6 +271,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     DropTraitLangItem,           "drop",               drop_trait,              Target::Trait;
 
     CoerceUnsizedTraitLangItem,  "coerce_unsized",     coerce_unsized_trait,    Target::Trait;
+    DispatchFromDynTraitLangItem,"dispatch_from_dyn",  dispatch_from_dyn_trait, Target::Trait;
 
     AddTraitLangItem,            "add",                add_trait,               Target::Trait;
     SubTraitLangItem,            "sub",                sub_trait,               Target::Trait;
index 50ca6ca78ab3aa5b81dd85670bf025e8101673e2..e87e425762d56eaf96399c1468eb1250f04f9eb4 100644 (file)
@@ -683,8 +683,8 @@ pub fn evaluate_nested_obligations<
                 }
                 &ty::Predicate::TypeOutlives(ref binder) => {
                     match (
-                        binder.no_late_bound_regions(),
-                        binder.map_bound_ref(|pred| pred.0).no_late_bound_regions(),
+                        binder.no_bound_vars(),
+                        binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
                     ) {
                         (None, Some(t_a)) => {
                             select.infcx().register_region_obligation_with_cause(
index 817e9ffcbb55d786bbcb9ab7f56269472241d038..71b77909b82a8e3de49c1cfbdc483a1c9822232b 100644 (file)
@@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
             false
         }
 
-        ty::Infer(..) => match in_crate {
+        ty::Bound(..) | ty::Infer(..) => match in_crate {
             InCrate::Local => false,
             // The inference variable might be unified with a local
             // type in that remote crate.
index b463faef1921ad966b24a97ac3b4e0494074d6c4..e6ae0557c33af04c46663da4809ed645f544cfac 100644 (file)
@@ -280,7 +280,7 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
                 ty::Generator(..) => Some(18),
                 ty::Foreign(..) => Some(19),
                 ty::GeneratorWitness(..) => Some(20),
-                ty::Infer(..) | ty::Error => None,
+                ty::Bound(..) | ty::Infer(..) | ty::Error => None,
                 ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
             }
         }
@@ -754,7 +754,8 @@ pub fn report_selection_error(&self,
                     }
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = self.tcx.object_safety_violations(trait_def_id);
+                        let violations = self.tcx.global_tcx()
+                            .object_safety_violations(trait_def_id);
                         self.tcx.report_object_safety_error(span,
                                                             trait_def_id,
                                                             violations)
@@ -875,7 +876,7 @@ pub fn report_selection_error(&self,
             }
 
             TraitNotObjectSafe(did) => {
-                let violations = self.tcx.object_safety_violations(did);
+                let violations = self.tcx.global_tcx().object_safety_violations(did);
                 self.tcx.report_object_safety_error(span, did, violations)
             }
 
index cfa77b210e857769f2a3e8f58640bc11367bffab..aea956461f27bea7252ff69d43a72af19d10d377 100644 (file)
@@ -143,7 +143,7 @@ fn normalize_projection_type<'a, 'gcx>(&mut self,
         debug!("normalize_projection_type(projection_ty={:?})",
                projection_ty);
 
-        debug_assert!(!projection_ty.has_escaping_regions());
+        debug_assert!(!projection_ty.has_escaping_bound_vars());
 
         // FIXME(#20304) -- cache
 
@@ -349,15 +349,15 @@ fn process_obligation(&mut self,
             }
 
             ty::Predicate::TypeOutlives(ref binder) => {
-                // Check if there are higher-ranked regions.
-                match binder.no_late_bound_regions() {
+                // Check if there are higher-ranked vars.
+                match binder.no_bound_vars() {
                     // If there are, inspect the underlying type further.
                     None => {
                         // Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
                         let binder = binder.map_bound_ref(|pred| pred.0);
 
-                        // Check if the type has any bound regions.
-                        match binder.no_late_bound_regions() {
+                        // Check if the type has any bound vars.
+                        match binder.no_bound_vars() {
                             // If so, this obligation is an error (for now). Eventually we should be
                             // able to support additional cases here, like `for<'a> &'a str: 'a`.
                             // NOTE: this is duplicate-implemented between here and fulfillment.
index 6b8d66c6fc6298f3b48354f494ea9cff07da1515..b7512790bfb6913414c2e4d34c618b56c9012f19 100644 (file)
@@ -352,7 +352,7 @@ pub fn from_poly_domain_goal<'a>(
         domain_goal: PolyDomainGoal<'tcx>,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ) -> GoalKind<'tcx> {
-        match domain_goal.no_late_bound_regions() {
+        match domain_goal.no_bound_vars() {
             Some(p) => p.into_goal(),
             None => GoalKind::Quantified(
                 QuantifierKind::Universal,
index d5942e738fdd9ad6a334e9b9ed69eea92b10defd..1d76ccdca3161b33a2f6b7cb6b447159f955314d 100644 (file)
@@ -13,7 +13,8 @@
 //! object if all of their methods meet certain criteria. In particular,
 //! they must:
 //!
-//!   - have a suitable receiver from which we can extract a vtable;
+//!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
+//!     that doesn't contain the vtable;
 //!   - not reference the erased type `Self` except for in this receiver;
 //!   - not have generic type parameters
 
 
 use hir::def_id::DefId;
 use lint;
-use traits;
-use ty::{self, Ty, TyCtxt, TypeFoldable};
-use ty::util::ExplicitSelf;
+use traits::{self, Obligation, ObligationCause};
+use ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate};
+use ty::subst::{Subst, Substs};
 use std::borrow::Cow;
-use syntax::ast;
+use std::iter::{self};
+use syntax::ast::{self, Name};
 use syntax_pos::Span;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -62,8 +64,8 @@ pub fn error_msg(&self) -> Cow<'static, str> {
                 format!("method `{}` references the `Self` type in where clauses", name).into(),
             ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
                 format!("method `{}` has generic type parameters", name).into(),
-            ObjectSafetyViolation::Method(name, MethodViolationCode::NonStandardSelfType) =>
-                format!("method `{}` has a non-standard `self` type", name).into(),
+            ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
+                format!("method `{}`'s receiver cannot be dispatched on", name).into(),
             ObjectSafetyViolation::AssociatedConst(name) =>
                 format!("the trait cannot contain associated consts like `{}`", name).into(),
         }
@@ -85,11 +87,11 @@ pub enum MethodViolationCode {
     /// e.g., `fn foo<A>()`
     Generic,
 
-    /// arbitrary `self` type, e.g. `self: Rc<Self>`
-    NonStandardSelfType,
+    /// the method's receiver (`self` argument) can't be dispatched on
+    UndispatchableReceiver,
 }
 
-impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 
     /// Returns the object safety violations that affect
     /// astconv - currently, Self in supertraits. This is needed
@@ -113,6 +115,8 @@ pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
     pub fn object_safety_violations(self, trait_def_id: DefId)
                                     -> Vec<ObjectSafetyViolation>
     {
+        debug!("object_safety_violations: {:?}", trait_def_id);
+
         traits::supertrait_def_ids(self, trait_def_id)
             .flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
             .collect()
@@ -277,23 +281,13 @@ fn virtual_call_violation_for_method(self,
                                          method: &ty::AssociatedItem)
                                          -> Option<MethodViolationCode>
     {
-        // The method's first parameter must be something that derefs (or
-        // autorefs) to `&self`. For now, we only accept `self`, `&self`
-        // and `Box<Self>`.
+        // The method's first parameter must be named `self`
         if !method.method_has_self_argument {
             return Some(MethodViolationCode::StaticMethod);
         }
 
         let sig = self.fn_sig(method.def_id);
 
-        let self_ty = self.mk_self_type();
-        let self_arg_ty = sig.skip_binder().inputs()[0];
-        if let ExplicitSelf::Other = ExplicitSelf::determine(self_arg_ty, |ty| ty == self_ty) {
-            return Some(MethodViolationCode::NonStandardSelfType);
-        }
-
-        // The `Self` type is erased, so it should not appear in list of
-        // arguments or return type apart from the receiver.
         for input_ty in &sig.skip_binder().inputs()[1..] {
             if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
                 return Some(MethodViolationCode::ReferencesSelf);
@@ -320,9 +314,254 @@ fn virtual_call_violation_for_method(self,
             return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
         }
 
+        let receiver_ty = self.liberate_late_bound_regions(
+            method.def_id,
+            &sig.map_bound(|sig| sig.inputs()[0]),
+        );
+
+        // until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
+        // However, this is already considered object-safe. We allow it as a special case here.
+        // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows
+        // `Receiver: Unsize<Receiver[Self => dyn Trait]>`
+        if receiver_ty != self.mk_self_type() {
+            if !self.receiver_is_dispatchable(method, receiver_ty) {
+                return Some(MethodViolationCode::UndispatchableReceiver);
+            } else {
+                // sanity check to make sure the receiver actually has the layout of a pointer
+
+                use ty::layout::Abi;
+
+                let param_env = self.param_env(method.def_id);
+
+                let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
+                    match self.layout_of(param_env.and(ty)) {
+                        Ok(layout) => &layout.abi,
+                        Err(err) => bug!(
+                            "Error: {}\n while computing layout for type {:?}", err, ty
+                        )
+                    }
+                };
+
+                // e.g. Rc<()>
+                let unit_receiver_ty = self.receiver_for_self_ty(
+                    receiver_ty, self.mk_unit(), method.def_id
+                );
+
+                match abi_of_ty(unit_receiver_ty) {
+                    &Abi::Scalar(..) => (),
+                    abi => bug!("Receiver when Self = () should have a Scalar ABI, found {:?}", abi)
+                }
+
+                let trait_object_ty = self.object_ty_for_trait(
+                    trait_def_id, self.mk_region(ty::ReStatic)
+                );
+
+                // e.g. Rc<dyn Trait>
+                let trait_object_receiver = self.receiver_for_self_ty(
+                    receiver_ty, trait_object_ty, method.def_id
+                );
+
+                match abi_of_ty(trait_object_receiver) {
+                    &Abi::ScalarPair(..) => (),
+                    abi => bug!(
+                        "Receiver when Self = {} should have a ScalarPair ABI, found {:?}",
+                        trait_object_ty, abi
+                    )
+                }
+            }
+        }
+
         None
     }
 
+    /// performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
+    /// e.g. for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`
+    fn receiver_for_self_ty(
+        self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
+    ) -> Ty<'tcx> {
+        let substs = Substs::for_item(self, method_def_id, |param, _| {
+            if param.index == 0 {
+                self_ty.into()
+            } else {
+                self.mk_param_from_def(param)
+            }
+        });
+
+        receiver_ty.subst(self, substs)
+    }
+
+    /// creates the object type for the current trait. For example,
+    /// if the current trait is `Deref`, then this will be
+    /// `dyn Deref<Target=Self::Target> + 'static`
+    fn object_ty_for_trait(self, trait_def_id: DefId, lifetime: ty::Region<'tcx>) -> Ty<'tcx> {
+        debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
+
+        let trait_ref = ty::TraitRef::identity(self, trait_def_id);
+
+        let trait_predicate = ty::ExistentialPredicate::Trait(
+            ty::ExistentialTraitRef::erase_self_ty(self, trait_ref)
+        );
+
+        let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
+            .flat_map(|trait_ref| self.associated_items(trait_ref.def_id()))
+            .filter(|item| item.kind == ty::AssociatedKind::Type)
+            .collect::<Vec<_>>();
+
+        // existential predicates need to be in a specific order
+        associated_types.sort_by_key(|item| self.def_path_hash(item.def_id));
+
+        let projection_predicates = associated_types.into_iter().map(|item| {
+            ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
+                ty: self.mk_projection(item.def_id, trait_ref.substs),
+                item_def_id: item.def_id,
+                substs: trait_ref.substs,
+            })
+        });
+
+        let existential_predicates = self.mk_existential_predicates(
+            iter::once(trait_predicate).chain(projection_predicates)
+        );
+
+        let object_ty = self.mk_dynamic(
+            ty::Binder::dummy(existential_predicates),
+            lifetime,
+        );
+
+        debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
+
+        object_ty
+    }
+
+    /// checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
+    /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
+    /// in the following way:
+    /// - let `Receiver` be the type of the `self` argument, i.e `Self`, `&Self`, `Rc<Self>`
+    /// - require the following bound:
+    ///
+    ///        Receiver[Self => T]: DispatchFromDyn<Receiver[Self => dyn Trait]>
+    ///
+    ///    where `Foo[X => Y]` means "the same type as `Foo`, but with `X` replaced with `Y`"
+    ///   (substitution notation).
+    ///
+    /// some examples of receiver types and their required obligation
+    /// - `&'a mut self` requires `&'a mut Self: DispatchFromDyn<&'a mut dyn Trait>`
+    /// - `self: Rc<Self>` requires `Rc<Self>: DispatchFromDyn<Rc<dyn Trait>>`
+    /// - `self: Pin<Box<Self>>` requires `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<dyn Trait>>>`
+    ///
+    /// The only case where the receiver is not dispatchable, but is still a valid receiver
+    /// type (just not object-safe), is when there is more than one level of pointer indirection.
+    /// e.g. `self: &&Self`, `self: &Rc<Self>`, `self: Box<Box<Self>>`. In these cases, there
+    /// is no way, or at least no inexpensive way, to coerce the receiver from the version where
+    /// `Self = dyn Trait` to the version where `Self = T`, where `T` is the unknown erased type
+    /// contained by the trait object, because the object that needs to be coerced is behind
+    /// a pointer.
+    ///
+    /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
+    /// in a new check that `Trait` is object safe, creating a cycle. So instead, we fudge a little
+    /// by introducing a new type parameter `U` such that `Self: Unsize<U>` and `U: Trait + ?Sized`,
+    /// and use `U` in place of `dyn Trait`. Written as a chalk-style query:
+    ///
+    ///     forall (U: Trait + ?Sized) {
+    ///         if (Self: Unsize<U>) {
+    ///             Receiver: DispatchFromDyn<Receiver[Self => U]>
+    ///         }
+    ///     }
+    ///
+    /// for `self: &'a mut Self`, this means `&'a mut Self: DispatchFromDyn<&'a mut U>`
+    /// for `self: Rc<Self>`, this means `Rc<Self>: DispatchFromDyn<Rc<U>>`
+    /// for `self: Pin<Box<Self>>, this means `Pin<Box<Self>>: DispatchFromDyn<Pin<Box<U>>>`
+    //
+    // FIXME(mikeyhew) when unsized receivers are implemented as part of unsized rvalues, add this
+    // fallback query: `Receiver: Unsize<Receiver[Self => U]>` to support receivers like
+    // `self: Wrapper<Self>`.
+    #[allow(dead_code)]
+    fn receiver_is_dispatchable(
+        self,
+        method: &ty::AssociatedItem,
+        receiver_ty: Ty<'tcx>,
+    ) -> bool {
+        debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
+
+        let traits = (self.lang_items().unsize_trait(),
+                      self.lang_items().dispatch_from_dyn_trait());
+        let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
+            (u, cu)
+        } else {
+            debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
+            return false;
+        };
+
+        // the type `U` in the query
+        // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now.
+        // FIXME(mikeyhew) this is a total hack, and we should replace it when real forall queries
+        // are implemented
+        let unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
+            ::std::u32::MAX,
+            Name::intern("RustaceansAreAwesome").as_interned_str(),
+        );
+
+        // `Receiver[Self => U]`
+        let unsized_receiver_ty = self.receiver_for_self_ty(
+            receiver_ty, unsized_self_ty, method.def_id
+        );
+
+        // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
+        // `U: ?Sized` is already implied here
+        let param_env = {
+            let mut param_env = self.param_env(method.def_id);
+
+            // Self: Unsize<U>
+            let unsize_predicate = ty::TraitRef {
+                def_id: unsize_did,
+                substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]),
+            }.to_predicate();
+
+            // U: Trait<Arg1, ..., ArgN>
+            let trait_predicate = {
+                let substs = Substs::for_item(self, method.container.assert_trait(), |param, _| {
+                    if param.index == 0 {
+                        unsized_self_ty.into()
+                    } else {
+                        self.mk_param_from_def(param)
+                    }
+                });
+
+                ty::TraitRef {
+                    def_id: unsize_did,
+                    substs,
+                }.to_predicate()
+            };
+
+            let caller_bounds: Vec<Predicate<'tcx>> = param_env.caller_bounds.iter().cloned()
+                .chain(iter::once(unsize_predicate))
+                .chain(iter::once(trait_predicate))
+                .collect();
+
+            param_env.caller_bounds = self.intern_predicates(&caller_bounds);
+
+            param_env
+        };
+
+        // Receiver: DispatchFromDyn<Receiver[Self => U]>
+        let obligation = {
+            let predicate = ty::TraitRef {
+                def_id: dispatch_from_dyn_did,
+                substs: self.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
+            }.to_predicate();
+
+            Obligation::new(
+                ObligationCause::dummy(),
+                param_env,
+                predicate,
+            )
+        };
+
+        self.infer_ctxt().enter(|ref infcx| {
+            // the receiver is dispatchable iff the obligation holds
+            infcx.predicate_must_hold(&obligation)
+        })
+    }
+
     fn contains_illegal_self_type_reference(self,
                                             trait_def_id: DefId,
                                             ty: Ty<'tcx>)
index b7754ae4fc58df9edeb39e4356b06452f5ebd831..a388c7eeb7e49ede897bbe130ffc07ffd4071d93 100644 (file)
@@ -363,7 +363,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*)
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
                     Reveal::UserFacing => ty,
@@ -390,7 +390,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::Projection(ref data) if !data.has_escaping_regions() => { // (*)
+            ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*)
 
                 // (*) This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
@@ -1618,7 +1618,7 @@ pub fn from_poly_projection_predicate(selcx: &mut SelectionContext<'cx, 'gcx, 't
         let infcx = selcx.infcx();
         // We don't do cross-snapshot caching of obligations with escaping regions,
         // so there's no cache key to use
-        predicate.no_late_bound_regions()
+        predicate.no_bound_vars()
             .map(|predicate| ProjectionCacheKey {
                 // We don't attempt to match up with a specific type-variable state
                 // from a specific call to `opt_normalize_projection_type` - if
index 8f7b0df8b95aa74f157d7cab5b1e42da2bb915d9..62317f074764f67248c11feff2203734d46e45a4 100644 (file)
@@ -252,6 +252,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         | ty::Param(_)
         | ty::Opaque(..)
         | ty::Infer(_)
+        | ty::Bound(..)
         | ty::Generator(..) => false,
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
index 4adb65dc58d917de255d7779c109a241ad676b12..59b086e35de310a0ae189d841b8e7270c007fec7 100644 (file)
@@ -100,7 +100,7 @@ fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'tcx> {
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => {
+            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
                 // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
@@ -138,7 +138,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 }
             }
 
-            ty::Projection(ref data) if !data.has_escaping_regions() => {
+            ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
                 // (*)
                 // (*) This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
index 99f557d44d9aa4e085cad074ed573aa4db34ad72..b3fae3bab347199ad0d95dd3d9d326725d53f056 100644 (file)
@@ -164,7 +164,7 @@ pub fn explicit_outlives_bounds<'tcx>(
             ty::Predicate::ClosureKind(..) |
             ty::Predicate::TypeOutlives(..) |
             ty::Predicate::ConstEvaluatable(..) => None,
-            ty::Predicate::RegionOutlives(ref data) => data.no_late_bound_regions().map(
+            ty::Predicate::RegionOutlives(ref data) => data.no_bound_vars().map(
                 |ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a),
             ),
         })
index 4b41831afbb3323b667b62655aa796061531f607..312cd66dcc75c229b78b1d9d7a4d2b537b7eb55b 100644 (file)
@@ -590,7 +590,7 @@ pub fn select(
         obligation: &TraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, Selection<'tcx>> {
         debug!("select({:?})", obligation);
-        debug_assert!(!obligation.predicate.has_escaping_regions());
+        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
 
@@ -693,7 +693,7 @@ fn evaluate_predicate_recursively<'o>(
 
         match obligation.predicate {
             ty::Predicate::Trait(ref t) => {
-                debug_assert!(!t.has_escaping_regions());
+                debug_assert!(!t.has_escaping_bound_vars());
                 let obligation = obligation.with(t.clone());
                 self.evaluate_trait_predicate_recursively(previous_stack, obligation)
             }
@@ -725,9 +725,9 @@ fn evaluate_predicate_recursively<'o>(
             },
 
             ty::Predicate::TypeOutlives(ref binder) => {
-                assert!(!binder.has_escaping_regions());
-                // Check if the type has higher-ranked regions.
-                if binder.skip_binder().0.has_escaping_regions() {
+                assert!(!binder.has_escaping_bound_vars());
+                // Check if the type has higher-ranked vars.
+                if binder.skip_binder().0.has_escaping_bound_vars() {
                     // If so, this obligation is an error (for now). Eventually we should be
                     // able to support additional cases here, like `for<'a> &'a str: 'a`.
 
@@ -743,7 +743,7 @@ fn evaluate_predicate_recursively<'o>(
                         Ok(EvaluatedToErr)
                     }
                 } else {
-                    // If the type has no late bound regions, then if we assign all
+                    // If the type has no late bound vars, then if we assign all
                     // the inference variables in it to be 'static, then the type
                     // will be 'static itself.
                     //
@@ -1202,7 +1202,7 @@ fn candidate_from_obligation<'o>(
             "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
             cache_fresh_trait_pred, stack
         );
-        debug_assert!(!stack.obligation.predicate.has_escaping_regions());
+        debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
 
         if let Some(c) =
             self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
@@ -1806,7 +1806,7 @@ fn match_projection(
         placeholder_map: &infer::PlaceholderMap<'tcx>,
         snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
     ) -> bool {
-        debug_assert!(!skol_trait_ref.has_escaping_regions());
+        debug_assert!(!skol_trait_ref.has_escaping_bound_vars());
         if self.infcx
             .at(&obligation.cause, obligation.param_env)
             .sup(ty::Binder::dummy(skol_trait_ref), trait_bound)
@@ -2096,18 +2096,6 @@ fn assemble_candidates_from_object_ty(
             obligation.self_ty().skip_binder()
         );
 
-        // Object-safety candidates are only applicable to object-safe
-        // traits. Including this check is useful because it helps
-        // inference in cases of traits like `BorrowFrom`, which are
-        // not object-safe, and which rely on being able to infer the
-        // self-type from one of the other inputs. Without this check,
-        // these cases wind up being considered ambiguous due to a
-        // (spurious) ambiguity introduced here.
-        let predicate_trait_ref = obligation.predicate.to_poly_trait_ref();
-        if !self.tcx().is_object_safe(predicate_trait_ref.def_id()) {
-            return;
-        }
-
         self.probe(|this, _snapshot| {
             // the code below doesn't care about regions, and the
             // self-ty here doesn't escape this probe, so just erase
@@ -2185,7 +2173,7 @@ fn assemble_candidates_for_unsizing(
         //     T: Trait
         // so it seems ok if we (conservatively) fail to accept that `Unsize`
         // obligation above. Should be possible to extend this in the future.
-        let source = match obligation.self_ty().no_late_bound_regions() {
+        let source = match obligation.self_ty().no_bound_vars() {
             Some(t) => t,
             None => {
                 // Don't add any candidates if there are bound regions.
@@ -2482,7 +2470,7 @@ fn sized_conditions(
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
             ty::UnnormalizedProjection(..)
-            | ty::Infer(ty::BoundTy(_))
+            | ty::Bound(_)
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
             | ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2567,7 +2555,7 @@ fn copy_clone_conditions(
             }
 
             ty::UnnormalizedProjection(..)
-            | ty::Infer(ty::BoundTy(_))
+            | ty::Bound(_)
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
             | ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2610,7 +2598,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
             | ty::Param(..)
             | ty::Foreign(..)
             | ty::Projection(..)
-            | ty::Infer(ty::BoundTy(_))
+            | ty::Bound(_)
             | ty::Infer(ty::TyVar(_))
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
@@ -3317,7 +3305,7 @@ fn confirm_builtin_unsize_candidate(
         // assemble_candidates_for_unsizing should ensure there are no late bound
         // regions here. See the comment there for more details.
         let source = self.infcx
-            .shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap());
+            .shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
         let target = obligation
             .predicate
             .skip_binder()
index 409665e47774529149696bc7423e70df2f0bf0b0..05d9d4bc37d79f540e3c887feb5fcc82ae099be7 100644 (file)
@@ -2243,7 +2243,7 @@ pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
             Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
-            Generator, GeneratorWitness, Dynamic, Closure, Tuple,
+            Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound,
             Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
index 855983042c026cec3b38f9d37029e052c0b3c72b..4737c72b1ef0f75bcc2c0ca382ef69c4b769ea54 100644 (file)
@@ -212,7 +212,7 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> Cow<'static, str> {
             ty::Infer(ty::TyVar(_)) => "inferred type".into(),
             ty::Infer(ty::IntVar(_)) => "integral variable".into(),
             ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(),
-            ty::Infer(ty::BoundTy(_)) |
+            ty::Bound(_) |
             ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
index e6aaf8b1bb20604a7046b991d1f520b0afccc27a..380f95993f8fbab345f51c0c1a93e55ec70b425b 100644 (file)
@@ -122,7 +122,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::Foreign(def_id) => {
             Some(ForeignSimplifiedType(def_id))
         }
-        ty::Infer(_) | ty::Error => None,
+        ty::Bound(..) | ty::Infer(_) | ty::Error => None,
     }
 }
 
index a7b21688fbeb3ab1f0e3a4dc6db32a9da5318e39..0764f363250dd8be56b0b7d846ff529fa0b2caca 100644 (file)
@@ -115,15 +115,17 @@ fn add_sty(&mut self, st: &ty::TyKind<'_>) {
                 self.add_substs(&substs.substs);
             }
 
+            &ty::Bound(bound_ty) => {
+                self.add_binder(bound_ty.index);
+            }
+
             &ty::Infer(infer) => {
                 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
                 self.add_flags(TypeFlags::HAS_TY_INFER);
                 match infer {
                     ty::FreshTy(_) |
                     ty::FreshIntTy(_) |
-                    ty::FreshFloatTy(_) |
-                    ty::BoundTy(_) => {
-                        self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
+                    ty::FreshFloatTy(_) => {
                     }
 
                     ty::TyVar(_) |
@@ -141,7 +143,7 @@ fn add_sty(&mut self, st: &ty::TyKind<'_>) {
             &ty::Projection(ref data) => {
                 // currently we can't normalize projections that
                 // include bound regions, so track those separately.
-                if !data.has_escaping_regions() {
+                if !data.has_escaping_bound_vars() {
                     self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
                 }
                 self.add_flags(TypeFlags::HAS_PROJECTION);
index 80dfd263af9af99e6dfe8d6753dc70e10d94f47b..8c822adf7b0236bd39b829d1cae1335f7a8c7169 100644 (file)
@@ -67,18 +67,18 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     /// bound by `binder` or bound by some binder outside of `binder`.
     /// If `binder` is `ty::INNERMOST`, this indicates whether
     /// there are any late-bound regions that appear free.
-    fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
-        self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder })
+    fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
+        self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder })
     }
 
     /// True if this `self` has any regions that escape `binder` (and
     /// hence are not bound by it).
-    fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
-        self.has_regions_bound_at_or_above(binder.shifted_in(1))
+    fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
+        self.has_vars_bound_at_or_above(binder.shifted_in(1))
     }
 
-    fn has_escaping_regions(&self) -> bool {
-        self.has_regions_bound_at_or_above(ty::INNERMOST)
+    fn has_escaping_bound_vars(&self) -> bool {
+        self.has_vars_bound_at_or_above(ty::INNERMOST)
     }
 
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
@@ -416,11 +416,10 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// Late-bound region replacer
+// Bound vars replacer
 
-// Replaces the escaping regions in a type.
-
-struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+/// Replaces the escaping bound vars (late bound regions or bound types) in a type.
+struct BoundVarReplacer<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
     /// As with `RegionFolder`, represents the index of a binder *just outside*
@@ -428,7 +427,82 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     current_index: ty::DebruijnIndex,
 
     fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
-    map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>
+    fld_t: &'a mut (dyn FnMut(ty::BoundTy) -> ty::Ty<'tcx> + 'a),
+}
+
+impl<'a, 'gcx, 'tcx> BoundVarReplacer<'a, 'gcx, 'tcx> {
+    fn new<F, G>(
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        fld_r: &'a mut F,
+        fld_t: &'a mut G
+    ) -> Self
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>
+    {
+        BoundVarReplacer {
+            tcx,
+            current_index: ty::INNERMOST,
+            fld_r,
+            fld_t,
+        }
+    }
+}
+
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
+
+    fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
+        self.current_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.current_index.shift_out(1);
+        t
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        match t.sty {
+            ty::Bound(bound_ty) => {
+                if bound_ty.index == self.current_index {
+                    let fld_t = &mut self.fld_t;
+                    let ty = fld_t(bound_ty);
+                    ty::fold::shift_vars(
+                        self.tcx,
+                        &ty,
+                        self.current_index.as_u32()
+                    )
+                } else {
+                    t
+                }
+            }
+            _ => {
+                if !t.has_vars_bound_at_or_above(self.current_index) {
+                    // Nothing more to substitute.
+                    t
+                } else {
+                    t.super_fold_with(self)
+                }
+            }
+        }
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match *r {
+            ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
+                let fld_r = &mut self.fld_r;
+                let region = fld_r(br);
+                if let ty::ReLateBound(debruijn1, br) = *region {
+                    // If the callback returns a late-bound region,
+                    // that region should always use the INNERMOST
+                    // debruijn index. Then we adjust it to the
+                    // correct depth.
+                    assert_eq!(debruijn1, ty::INNERMOST);
+                    self.tcx.mk_region(ty::ReLateBound(debruijn, br))
+                } else {
+                    region
+                }
+            }
+            _ => r
+        }
+    }
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
@@ -440,16 +514,65 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// same `BoundRegion` will reuse the previous result.  A map is
     /// returned at the end with each bound region and the free region
     /// that replaced it.
-    pub fn replace_late_bound_regions<T,F>(self,
+    ///
+    /// This method only replaces late bound regions and the result may still
+    /// contain escaping bound types.
+    pub fn replace_late_bound_regions<T, F>(
+        self,
         value: &Binder<T>,
-        mut f: F)
-        -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
-        where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
-              T : TypeFoldable<'tcx>,
+        mut fld_r: F
+    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              T: TypeFoldable<'tcx>
     {
-        let mut replacer = RegionReplacer::new(self, &mut f);
+        let mut map = BTreeMap::new();
+        let mut real_fldr = |br| {
+            *map.entry(br).or_insert_with(|| fld_r(br))
+        };
+
+        // identity for bound types
+        let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
+
+        let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t);
         let result = value.skip_binder().fold_with(&mut replacer);
-        (result, replacer.map)
+        (result, map)
+    }
+
+    /// Replace all escaping bound vars. The `fld_r` closure replaces escaping
+    /// bound regions while the `fld_t` closure replaces escaping bound types.
+    pub fn replace_escaping_bound_vars<T, F, G>(
+        self,
+        value: &T,
+        mut fld_r: F,
+        mut fld_t: G
+    ) -> T
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
+              T: TypeFoldable<'tcx>
+    {
+        if !value.has_escaping_bound_vars() {
+            value.clone()
+        } else {
+            let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t);
+            let result = value.fold_with(&mut replacer);
+            result
+        }
+    }
+
+    /// Replace all types or regions bound by the given `Binder`. The `fld_r`
+    /// closure replaces bound regions while the `fld_t` closure replaces bound
+    /// types.
+    pub fn replace_bound_vars<T, F, G>(
+        self,
+        value: &Binder<T>,
+        fld_r: F,
+        fld_t: G
+    ) -> T
+        where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
+              G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
+              T: TypeFoldable<'tcx>
+    {
+        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
     }
 
     /// Replace any late-bound regions bound in `value` with
@@ -549,21 +672,33 @@ pub fn anonymize_late_bound_regions<T>(self, sig: &Binder<T>) -> Binder<T>
     }
 }
 
-impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> {
-    fn new<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>, fld_r: &'a mut F)
-              -> RegionReplacer<'a, 'gcx, 'tcx>
-        where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>
-    {
-        RegionReplacer {
+///////////////////////////////////////////////////////////////////////////
+// Shifter
+//
+// Shifts the De Bruijn indices on all escaping bound vars by a
+// fixed amount. Useful in substitution or when otherwise introducing
+// a binding level that is not intended to capture the existing bound
+// vars. See comment on `shift_vars_through_binders` method in
+// `subst.rs` for more details.
+
+struct Shifter<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+
+    current_index: ty::DebruijnIndex,
+    amount: u32,
+}
+
+impl Shifter<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, amount: u32) -> Self {
+        Shifter {
             tcx,
             current_index: ty::INNERMOST,
-            fld_r,
-            map: BTreeMap::default()
+            amount,
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
@@ -573,64 +708,48 @@ fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binde
         t
     }
 
-    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.has_regions_bound_at_or_above(self.current_index) {
-            return t;
-        }
-
-        t.super_fold_with(self)
-    }
-
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
-            ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
-                let fld_r = &mut self.fld_r;
-                let region = *self.map.entry(br).or_insert_with(|| fld_r(br));
-                if let ty::ReLateBound(debruijn1, br) = *region {
-                    // If the callback returns a late-bound region,
-                    // that region should always use the INNERMOST
-                    // debruijn index. Then we adjust it to the
-                    // correct depth.
-                    assert_eq!(debruijn1, ty::INNERMOST);
-                    self.tcx.mk_region(ty::ReLateBound(debruijn, br))
+            ty::ReLateBound(debruijn, br) => {
+                if self.amount == 0 || debruijn < self.current_index {
+                    r
                 } else {
-                    region
+                    let shifted = ty::ReLateBound(debruijn.shifted_in(self.amount), br);
+                    self.tcx.mk_region(shifted)
                 }
             }
             _ => r
         }
     }
-}
 
-///////////////////////////////////////////////////////////////////////////
-// Region shifter
-//
-// Shifts the De Bruijn indices on all escaping bound regions by a
-// fixed amount. Useful in substitution or when otherwise introducing
-// a binding level that is not intended to capture the existing bound
-// regions. See comment on `shift_regions_through_binders` method in
-// `subst.rs` for more details.
+    fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
+        match ty.sty {
+            ty::Bound(bound_ty) => {
+                if self.amount == 0 || bound_ty.index < self.current_index {
+                    ty
+                } else {
+                    let shifted = ty::BoundTy {
+                        index: bound_ty.index.shifted_in(self.amount),
+                        var: bound_ty.var,
+                        kind: bound_ty.kind,
+                    };
+                    self.tcx.mk_ty(ty::Bound(shifted))
+                }
+            }
 
-pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
-    match region {
-        ty::ReLateBound(debruijn, br) => {
-            ty::ReLateBound(debruijn.shifted_in(amount), br)
-        }
-        _ => {
-            region
+            _ => ty.super_fold_with(self),
         }
     }
 }
 
-pub fn shift_region_ref<'a, 'gcx, 'tcx>(
+pub fn shift_region<'a, 'gcx, 'tcx>(
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     region: ty::Region<'tcx>,
-    amount: u32)
-    -> ty::Region<'tcx>
-{
+    amount: u32
+) -> ty::Region<'tcx> {
     match region {
-        &ty::ReLateBound(debruijn, br) if amount > 0 => {
-            tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), br))
+        ty::ReLateBound(debruijn, br) if amount > 0 => {
+            tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br))
         }
         _ => {
             region
@@ -638,20 +757,19 @@ pub fn shift_region_ref<'a, 'gcx, 'tcx>(
     }
 }
 
-pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                        amount: u32,
-                                        value: &T) -> T
-    where T: TypeFoldable<'tcx>
-{
-    debug!("shift_regions(value={:?}, amount={})",
+pub fn shift_vars<'a, 'gcx, 'tcx, T>(
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    value: &T,
+    amount: u32
+) -> T where T: TypeFoldable<'tcx> {
+    debug!("shift_vars(value={:?}, amount={})",
            value, amount);
 
-    value.fold_with(&mut RegionFolder::new(tcx, &mut false, &mut |region, _current_depth| {
-        shift_region_ref(tcx, region, amount)
-    }))
+    value.fold_with(&mut Shifter::new(tcx, amount))
 }
 
-/// An "escaping region" is a bound region whose binder is not part of `t`.
+/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
+/// bound region or a bound type.
 ///
 /// So, for example, consider a type like the following, which has two binders:
 ///
@@ -663,24 +781,24 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
 /// fn type*, that type has an escaping region: `'a`.
 ///
-/// Note that what I'm calling an "escaping region" is often just called a "free region". However,
-/// we already use the term "free region". It refers to the regions that we use to represent bound
-/// regions on a fn definition while we are typechecking its body.
+/// Note that what I'm calling an "escaping var" is often just called a "free var". However,
+/// we already use the term "free var". It refers to the regions or types that we use to represent
+/// bound regions or type params on a fn definition while we are typechecking its body.
 ///
 /// To clarify, conceptually there is no particular difference between
-/// an "escaping" region and a "free" region. However, there is a big
+/// an "escaping" var and a "free" var. However, there is a big
 /// difference in practice. Basically, when "entering" a binding
 /// level, one is generally required to do some sort of processing to
-/// a bound region, such as replacing it with a fresh/placeholder
-/// region, or making an entry in the environment to represent the
-/// scope to which it is attached, etc. An escaping region represents
-/// a bound region for which this processing has not yet been done.
-struct HasEscapingRegionsVisitor {
+/// a bound var, such as replacing it with a fresh/placeholder
+/// var, or making an entry in the environment to represent the
+/// scope to which it is attached, etc. An escaping var represents
+/// a bound var for which this processing has not yet been done.
+struct HasEscapingVarsVisitor {
     /// Anything bound by `outer_index` or "above" is escaping
     outer_index: ty::DebruijnIndex,
 }
 
-impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor {
+impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
         self.outer_index.shift_in(1);
         let result = t.super_visit_with(self);
@@ -693,7 +811,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         // `outer_index`, that means that `t` contains some content
         // bound at `outer_index` or above (because
         // `outer_exclusive_binder` is always 1 higher than the
-        // content in `t`). Therefore, `t` has some escaping regions.
+        // content in `t`). Therefore, `t` has some escaping vars.
         t.outer_exclusive_binder > self.outer_index
     }
 
index 1627f9a766c4e02c52c41fbd91e8321cd503a399..b6691df39c120ccebeee7eef6692e609802447ab 100644 (file)
@@ -213,7 +213,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl<'a, 'b, 'tcx> Instance<'tcx> {
     pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
                -> Instance<'tcx> {
-        assert!(!substs.has_escaping_regions(),
+        assert!(!substs.has_escaping_bound_vars(),
                 "substs of instance {:?} not normalized for codegen: {:?}",
                 def_id, substs);
         Instance { def: InstanceDef::Item(def_id), substs: substs }
index 7153c729d1542b439d8dcec805ca5a8cccf0a37c..d44ba03084159ebe6a320e1e41d8f75a77f6b421 100644 (file)
@@ -519,6 +519,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         ty::Param(_) |
         ty::Opaque(..) |
         ty::Infer(_) |
+        ty::Bound(..) |
         ty::Error |
         ty::GeneratorWitness(..) |
         ty::Never |
index 05d4aeb6ddec4b0fa2964e409f52860a50d623bf..55005721617350f9ac9a1be12c3fc0cb98f4e6ce 100644 (file)
@@ -1124,9 +1124,14 @@ enum StructKind {
                 }
                 tcx.layout_raw(param_env.and(normalized))?
             }
-            ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
+
+            ty::Bound(..) |
+            ty::UnnormalizedProjection(..) |
+            ty::GeneratorWitness(..) |
+            ty::Infer(_) => {
                 bug!("LayoutDetails::compute: unexpected type `{}`", ty)
             }
+
             ty::Param(_) | ty::Error => {
                 return Err(LayoutError::Unknown(ty));
             }
@@ -1703,7 +1708,7 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
                 }
             }
 
-            ty::Projection(_) | ty::UnnormalizedProjection(..) |
+            ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) |
             ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => {
                 bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
index 3d9ec7245f9d6382badb60bd61dac16ff3e29e24..c7c197d11c03beb112b95d85933d45b9d6acc1ef 100644 (file)
@@ -63,7 +63,7 @@
 
 use hir;
 
-pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST};
+pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST};
 pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig};
 pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
@@ -463,13 +463,9 @@ pub struct TypeFlags: u32 {
         // Currently we can't normalize projections w/ bound regions.
         const HAS_NORMALIZABLE_PROJECTION = 1 << 12;
 
-        // Set if this includes a "canonical" type or region var --
-        // ought to be true only for the results of canonicalization.
-        const HAS_CANONICAL_VARS = 1 << 13;
-
         /// Does this have any `ReLateBound` regions? Used to check
         /// if a global bound is safe to evaluate.
-        const HAS_RE_LATE_BOUND = 1 << 14;
+        const HAS_RE_LATE_BOUND = 1 << 13;
 
         const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
                                    TypeFlags::HAS_SELF.bits |
@@ -490,7 +486,6 @@ pub struct TypeFlags: u32 {
                                   TypeFlags::HAS_TY_CLOSURE.bits |
                                   TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
                                   TypeFlags::KEEP_IN_LOCAL_TCX.bits |
-                                  TypeFlags::HAS_CANONICAL_VARS.bits |
                                   TypeFlags::HAS_RE_LATE_BOUND.bits;
     }
 }
@@ -2378,6 +2373,7 @@ fn sized_constraint_for_ty(&self,
                 }
             }
 
+            Bound(..) |
             Infer(..) => {
                 bug!("unexpected type `{:?}` in sized_constraint_for_ty",
                      ty)
index b49664b6247332a16e7c799a43428ad2fd6bd8ac..449730c9d0601d6c991e7705131b3eb71ed122fe 100644 (file)
@@ -106,7 +106,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             // we simply fallback to the most restrictive rule, which
             // requires that `Pi: 'a` for all `i`.
             ty::Projection(ref data) => {
-                if !data.has_escaping_regions() {
+                if !data.has_escaping_bound_vars() {
                     // best case: no escaping regions, so push the
                     // projection and skip the subtree (thus generating no
                     // constraints for Pi). This defers the choice between
@@ -156,6 +156,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             ty::FnDef(..) |       // OutlivesFunction (*)
             ty::FnPtr(_) |        // OutlivesFunction (*)
             ty::Dynamic(..) |       // OutlivesObject, OutlivesFragment (*)
+            ty::Bound(..) |
             ty::Error => {
                 // (*) Bare functions and traits are both binders. In the
                 // RFC, this means we would add the bound regions to the
index 05f5f923557ec7ea3dfcb1f07660dddb0971bb9f..59a66513eef0558a274c023b34e3169eeb183bd0 100644 (file)
@@ -734,9 +734,19 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 ty::UnnormalizedProjection(data.fold_with(folder))
             }
             ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
-            ty::Bool | ty::Char | ty::Str | ty::Int(_) |
-            ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
-            ty::Param(..) | ty::Never | ty::Foreign(..) => return self
+
+            ty::Bool |
+            ty::Char |
+            ty::Str |
+            ty::Int(_) |
+            ty::Uint(_) |
+            ty::Float(_) |
+            ty::Error |
+            ty::Infer(_) |
+            ty::Param(..) |
+            ty::Bound(..) |
+            ty::Never |
+            ty::Foreign(..) => return self
         };
 
         if self.sty == sty {
@@ -771,9 +781,19 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
                 data.visit_with(visitor)
             }
             ty::Opaque(_, ref substs) => substs.visit_with(visitor),
-            ty::Bool | ty::Char | ty::Str | ty::Int(_) |
-            ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
-            ty::Param(..) | ty::Never | ty::Foreign(..) => false,
+
+            ty::Bool |
+            ty::Char |
+            ty::Str |
+            ty::Int(_) |
+            ty::Uint(_) |
+            ty::Float(_) |
+            ty::Error |
+            ty::Infer(_) |
+            ty::Bound(..) |
+            ty::Param(..) |
+            ty::Never |
+            ty::Foreign(..) => false,
         }
     }
 
index 49cd87e2dc54ecc665f64863bc8c55e3ba4f88e2..28b58d62175bc21f270ef57a38d478c2df832c54 100644 (file)
@@ -77,6 +77,17 @@ pub fn is_named(&self) -> bool {
             _ => false,
         }
     }
+
+    /// When canonicalizing, we replace unbound inference variables and free
+    /// regions with anonymous late bound regions. This method asserts that
+    /// we have an anonymous late bound region, which hence may refer to
+    /// a canonical variable.
+    pub fn assert_bound_var(&self) -> BoundVar {
+        match *self {
+            BoundRegion::BrAnon(var) => BoundVar::from_u32(var),
+            _ => bug!("bound region is not anonymous"),
+        }
+    }
 }
 
 /// N.B., If you change this, you'll probably want to change the corresponding
@@ -188,6 +199,9 @@ pub enum TyKind<'tcx> {
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
     Param(ParamTy),
 
+    /// Bound type variable, used only when preparing a trait query.
+    Bound(BoundTy),
+
     /// A type variable used during type checking.
     Infer(InferTy),
 
@@ -727,8 +741,8 @@ pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     /// or some placeholder type.
     pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
         -> ty::TraitRef<'tcx>  {
-        // otherwise the escaping regions would be captured by the binder
-        // debug_assert!(!self_ty.has_escaping_regions());
+        // otherwise the escaping vars would be captured by the binder
+        // debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ty::TraitRef {
             def_id: self.def_id,
@@ -755,11 +769,11 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>,
     }
 }
 
-/// Binder is a binder for higher-ranked lifetimes. It is part of the
+/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
 /// (which would be represented by the type `PolyTraitRef ==
 /// Binder<TraitRef>`). Note that when we instantiate,
-/// erase, or otherwise "discharge" these bound regions, we change the
+/// erase, or otherwise "discharge" these bound vars, we change the
 /// type from `Binder<T>` to just `T` (see
 /// e.g. `liberate_late_bound_regions`).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@@ -767,29 +781,28 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>,
 
 impl<T> Binder<T> {
     /// Wraps `value` in a binder, asserting that `value` does not
-    /// contain any bound regions that would be bound by the
+    /// contain any bound vars that would be bound by the
     /// binder. This is commonly used to 'inject' a value T into a
     /// different binding level.
     pub fn dummy<'tcx>(value: T) -> Binder<T>
         where T: TypeFoldable<'tcx>
     {
-        debug_assert!(!value.has_escaping_regions());
+        debug_assert!(!value.has_escaping_bound_vars());
         Binder(value)
     }
 
-    /// Wraps `value` in a binder, binding late-bound regions (if any).
-    pub fn bind<'tcx>(value: T) -> Binder<T>
-    {
+    /// Wraps `value` in a binder, binding higher-ranked vars (if any).
+    pub fn bind<'tcx>(value: T) -> Binder<T> {
         Binder(value)
     }
 
     /// Skips the binder and returns the "bound" value. This is a
     /// risky thing to do because it's easy to get confused about
     /// debruijn indices and the like. It is usually better to
-    /// discharge the binder using `no_late_bound_regions` or
+    /// discharge the binder using `no_bound_vars` or
     /// `replace_late_bound_regions` or something like
     /// that. `skip_binder` is only valid when you are either
-    /// extracting data that has nothing to do with bound regions, you
+    /// extracting data that has nothing to do with bound vars, you
     /// are doing some sort of test that does not involve bound
     /// regions, or you are being very careful about your depth
     /// accounting.
@@ -798,7 +811,7 @@ pub fn bind<'tcx>(value: T) -> Binder<T>
     ///
     /// - extracting the def-id from a PolyTraitRef;
     /// - comparing the self type of a PolyTraitRef to see if it is equal to
-    ///   a type parameter `X`, since the type `X`  does not reference any regions
+    ///   a type parameter `X`, since the type `X` does not reference any regions
     pub fn skip_binder(&self) -> &T {
         &self.0
     }
@@ -820,19 +833,19 @@ pub fn map_bound<F, U>(self, f: F) -> Binder<U>
     }
 
     /// Unwraps and returns the value within, but only if it contains
-    /// no bound regions at all. (In other words, if this binder --
+    /// no bound vars at all. (In other words, if this binder --
     /// and indeed any enclosing binder -- doesn't bind anything at
     /// all.) Otherwise, returns `None`.
     ///
     /// (One could imagine having a method that just unwraps a single
-    /// binder, but permits late-bound regions bound by enclosing
+    /// binder, but permits late-bound vars bound by enclosing
     /// binders, but that would require adjusting the debruijn
     /// indices, and given the shallow binding structure we often use,
     /// would not be that useful.)
-    pub fn no_late_bound_regions<'tcx>(self) -> Option<T>
-        where T : TypeFoldable<'tcx>
+    pub fn no_bound_vars<'tcx>(self) -> Option<T>
+        where T: TypeFoldable<'tcx>
     {
-        if self.skip_binder().has_escaping_regions() {
+        if self.skip_binder().has_escaping_bound_vars() {
             None
         } else {
             Some(self.skip_binder().clone())
@@ -1166,9 +1179,6 @@ pub enum RegionKind {
     /// `ClosureRegionRequirements` that are produced by MIR borrowck.
     /// See `ClosureRegionRequirements` for more details.
     ReClosureBound(RegionVid),
-
-    /// Canonicalized region, used only when preparing a trait query.
-    ReCanonical(BoundTyIndex),
 }
 
 impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
@@ -1219,22 +1229,37 @@ pub enum InferTy {
     FreshTy(u32),
     FreshIntTy(u32),
     FreshFloatTy(u32),
-
-    /// Bound type variable, used only when preparing a trait query.
-    BoundTy(BoundTy),
 }
 
 newtype_index! {
-    pub struct BoundTyIndex { .. }
+    pub struct BoundVar { .. }
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct BoundTy {
-    pub level: DebruijnIndex,
-    pub var: BoundTyIndex,
+    pub index: DebruijnIndex,
+    pub var: BoundVar,
+    pub kind: BoundTyKind,
 }
 
-impl_stable_hash_for!(struct BoundTy { level, var });
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub enum BoundTyKind {
+    Anon,
+    Param(InternedString),
+}
+
+impl_stable_hash_for!(struct BoundTy { index, var, kind });
+impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) });
+
+impl BoundTy {
+    pub fn new(index: DebruijnIndex, var: BoundVar) -> Self {
+        BoundTy {
+            index,
+            var,
+            kind: BoundTyKind::Anon,
+        }
+    }
+}
 
 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@@ -1264,7 +1289,7 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         -> ty::ProjectionPredicate<'tcx>
     {
         // otherwise the escaping regions would be captured by the binders
-        debug_assert!(!self_ty.has_escaping_regions());
+        debug_assert!(!self_ty.has_escaping_bound_vars());
 
         ty::ProjectionPredicate {
             projection_ty: ty::ProjectionTy {
@@ -1363,7 +1388,6 @@ pub fn has_name(&self) -> bool {
             RegionKind::ReEmpty => false,
             RegionKind::ReErased => false,
             RegionKind::ReClosureBound(..) => false,
-            RegionKind::ReCanonical(..) => false,
         }
     }
 
@@ -1450,10 +1474,6 @@ pub fn type_flags(&self) -> TypeFlags {
             }
             ty::ReErased => {
             }
-            ty::ReCanonical(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_CANONICAL_VARS;
-            }
             ty::ReClosureBound(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
             }
@@ -1865,6 +1885,7 @@ pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
             Tuple(..) |
             Foreign(..) |
             Param(_) |
+            Bound(..) |
             Infer(_) |
             Error => {
                 vec![]
@@ -1930,7 +1951,7 @@ pub fn is_trivially_sized(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> bool {
 
             ty::Infer(ty::TyVar(_)) => false,
 
-            ty::Infer(ty::BoundTy(_)) |
+            ty::Bound(_) |
             ty::Infer(ty::FreshTy(_)) |
             ty::Infer(ty::FreshIntTy(_)) |
             ty::Infer(ty::FreshFloatTy(_)) =>
index 02b5d36ecce6ea0dab9088b61e202d5438116a64..c1aed36c92ddf3bfd60170781ea85bf88ff9bb82 100644 (file)
@@ -12,7 +12,7 @@
 
 use hir::def_id::DefId;
 use infer::canonical::Canonical;
-use ty::{self, BoundTyIndex, Lift, List, Ty, TyCtxt};
+use ty::{self, BoundVar, Lift, List, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 
 use serialize::{self, Encodable, Encoder, Decodable, Decoder};
@@ -355,7 +355,7 @@ fn subst_spanned<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                        span,
                                        root_ty: None,
                                        ty_stack_depth: 0,
-                                       region_binders_passed: 0 };
+                                       binders_passed: 0 };
         (*self).fold_with(&mut folder)
     }
 }
@@ -377,16 +377,16 @@ struct SubstFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     ty_stack_depth: usize,
 
     // Number of region binders we have passed through while doing the substitution
-    region_binders_passed: u32,
+    binders_passed: u32,
 }
 
 impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
-        self.region_binders_passed += 1;
+        self.binders_passed += 1;
         let t = t.super_fold_with(self);
-        self.region_binders_passed -= 1;
+        self.binders_passed -= 1;
         t
     }
 
@@ -471,12 +471,12 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
             }
         };
 
-        self.shift_regions_through_binders(ty)
+        self.shift_vars_through_binders(ty)
     }
 
     /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs
-    /// when we are substituting a type with escaping regions into a context where we have passed
-    /// through region binders. That's quite a mouthful. Let's see an example:
+    /// when we are substituting a type with escaping bound vars into a context where we have
+    /// passed through binders. That's quite a mouthful. Let's see an example:
     ///
     /// ```
     /// type Func<A> = fn(A);
@@ -516,25 +516,25 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
     /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
     /// first case we do not increase the Debruijn index and in the second case we do. The reason
     /// is that only in the second case have we passed through a fn binder.
-    fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        debug!("shift_regions(ty={:?}, region_binders_passed={:?}, has_escaping_regions={:?})",
-               ty, self.region_binders_passed, ty.has_escaping_regions());
+    fn shift_vars_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        debug!("shift_vars(ty={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})",
+               ty, self.binders_passed, ty.has_escaping_bound_vars());
 
-        if self.region_binders_passed == 0 || !ty.has_escaping_regions() {
+        if self.binders_passed == 0 || !ty.has_escaping_bound_vars() {
             return ty;
         }
 
-        let result = ty::fold::shift_regions(self.tcx(), self.region_binders_passed, &ty);
-        debug!("shift_regions: shifted result = {:?}", result);
+        let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed);
+        debug!("shift_vars: shifted result = {:?}", result);
 
         result
     }
 
     fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        if self.region_binders_passed == 0 || !region.has_escaping_regions() {
+        if self.binders_passed == 0 || !region.has_escaping_bound_vars() {
             return region;
         }
-        self.tcx().mk_region(ty::fold::shift_region(*region, self.region_binders_passed))
+        ty::fold::shift_region(self.tcx, region, self.binders_passed)
     }
 }
 
@@ -553,15 +553,23 @@ pub fn is_identity(&self) -> bool {
             return false;
         }
 
-        self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| {
+        self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
             match kind.unpack() {
                 UnpackedKind::Type(ty) => match ty.sty {
-                    ty::Infer(ty::BoundTy(ref b)) => cvar == b.var,
+                    ty::Bound(b) => {
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(b.index, ty::INNERMOST);
+                        cvar == b.var
+                    }
                     _ => false,
                 },
 
                 UnpackedKind::Lifetime(r) => match r {
-                    ty::ReCanonical(cvar1) => cvar == *cvar1,
+                    ty::ReLateBound(index, br) => {
+                        // We only allow a `ty::INNERMOST` index in substitutions.
+                        assert_eq!(*index, ty::INNERMOST);
+                        cvar == br.assert_bound_var()
+                    }
                     _ => false,
                 },
             }
index a6997260784d38e0083b6cf5ce81af24e0167729..9ba5bf9add110292760dd536f0b43b1157632aa5 100644 (file)
@@ -363,7 +363,7 @@ pub fn required_region_bounds(self,
                erased_self_ty,
                predicates);
 
-        assert!(!erased_self_ty.has_escaping_regions());
+        assert!(!erased_self_ty.has_escaping_bound_vars());
 
         traits::elaborate_predicates(self, predicates)
             .filter_map(|predicate| {
@@ -389,7 +389,7 @@ pub fn required_region_bounds(self,
                         // construct such an object, but this seems
                         // correct even if that code changes).
                         let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
-                        if t == &erased_self_ty && !r.has_escaping_regions() {
+                        if t == &erased_self_ty && !r.has_escaping_bound_vars() {
                             Some(*r)
                         } else {
                             None
@@ -951,7 +951,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Can refer to a type which may drop.
         // FIXME(eddyb) check this against a ParamEnv.
-        ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) |
+        ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) |
         ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
index 47fbfba87748ba073270d06b01e64e0db7ce2cb2..284c595ee2d965ed6177317bf611106f97725934 100644 (file)
@@ -82,7 +82,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
     match parent_ty.sty {
         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) |
         ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error |
-        ty::Foreign(..) => {
+        ty::Bound(..) | ty::Foreign(..) => {
         }
         ty::Array(ty, len) => {
             push_const(stack, len);
index 27747970f76b2ca74caf955f9198ba8a85baa647..1336eac63f880514902cac8abb1e8b298beb40a7 100644 (file)
@@ -158,7 +158,7 @@ fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
         let infcx = &mut self.infcx;
         let param_env = self.param_env;
         self.out.iter()
-                .inspect(|pred| assert!(!pred.has_escaping_regions()))
+                .inspect(|pred| assert!(!pred.has_escaping_bound_vars()))
                 .flat_map(|pred| {
                     let mut selcx = traits::SelectionContext::new(infcx);
                     let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
@@ -190,7 +190,7 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
 
         self.out.extend(
             trait_ref.substs.types()
-                            .filter(|ty| !ty.has_escaping_regions())
+                            .filter(|ty| !ty.has_escaping_bound_vars())
                             .map(|ty| traits::Obligation::new(cause.clone(),
                                                               param_env,
                                                               ty::Predicate::WellFormed(ty))));
@@ -205,7 +205,7 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
         let trait_ref = data.trait_ref(self.infcx.tcx);
         self.compute_trait_ref(&trait_ref, Elaborate::None);
 
-        if !data.has_escaping_regions() {
+        if !data.has_escaping_bound_vars() {
             let predicate = trait_ref.to_predicate();
             let cause = self.cause(traits::ProjectionWf(data));
             self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
@@ -229,7 +229,7 @@ fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) {
     }
 
     fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
-        if !subty.has_escaping_regions() {
+        if !subty.has_escaping_bound_vars() {
             let cause = self.cause(cause);
             let trait_ref = ty::TraitRef {
                 def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
@@ -258,6 +258,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                 ty::GeneratorWitness(..) |
                 ty::Never |
                 ty::Param(_) |
+                ty::Bound(..) |
                 ty::Foreign(..) => {
                     // WfScalar, WfParameter, etc
                 }
@@ -299,7 +300,7 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
 
                 ty::Ref(r, rty, _) => {
                     // WfReference
-                    if !r.has_escaping_regions() && !rty.has_escaping_regions() {
+                    if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
                         let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                         self.out.push(
                             traits::Obligation::new(
@@ -450,7 +451,7 @@ fn nominal_obligations(&mut self,
                   .map(|pred| traits::Obligation::new(cause.clone(),
                                                       self.param_env,
                                                       pred))
-                  .filter(|pred| !pred.has_escaping_regions())
+                  .filter(|pred| !pred.has_escaping_bound_vars())
                   .collect()
     }
 
@@ -489,7 +490,7 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>,
         // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
         // am looking forward to the future here.
 
-        if !data.has_escaping_regions() {
+        if !data.has_escaping_bound_vars() {
             let implicit_bounds =
                 object_region_bounds(self.infcx.tcx, data);
 
index abdd7fd8d40bf0d220ad2022d1fa47d6f12eb243..5ec4f55b142ebbfcac4c74ae4f0eb63de550c5dd 100644 (file)
@@ -16,7 +16,7 @@
 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
 use ty::{Bool, Char, Adt};
 use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
-use ty::{Param, RawPtr, Ref, Never, Tuple};
+use ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
 use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
 use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer};
 use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
@@ -790,9 +790,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 ty::ReEarlyBound(ref data) => {
                     write!(f, "{}", data.name)
                 }
-                ty::ReCanonical(_) => {
-                    write!(f, "'_")
-                }
                 ty::ReLateBound(_, br) |
                 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
                 ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
@@ -860,10 +857,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     write!(f, "{:?}", vid)
                 }
 
-                ty::ReCanonical(c) => {
-                    write!(f, "'?{}", c.index())
-                }
-
                 ty::RePlaceholder(placeholder) => {
                     write!(f, "RePlaceholder({:?})", placeholder)
                 }
@@ -976,7 +969,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     ty::TyVar(_) => write!(f, "_"),
                     ty::IntVar(_) => write!(f, "{}", "{integer}"),
                     ty::FloatVar(_) => write!(f, "{}", "{float}"),
-                    ty::BoundTy(_) => write!(f, "_"),
                     ty::FreshTy(v) => write!(f, "FreshTy({})", v),
                     ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
                     ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
@@ -988,7 +980,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 ty::TyVar(ref v) => write!(f, "{:?}", v),
                 ty::IntVar(ref v) => write!(f, "{:?}", v),
                 ty::FloatVar(ref v) => write!(f, "{:?}", v),
-                ty::BoundTy(v) => write!(f, "?{:?}", v.var.index()),
                 ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
                 ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
                 ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
@@ -1119,6 +1110,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 Infer(infer_ty) => write!(f, "{}", infer_ty),
                 Error => write!(f, "[type error]"),
                 Param(ref param_ty) => write!(f, "{}", param_ty),
+                Bound(bound_ty) => {
+                    match bound_ty.kind {
+                        ty::BoundTyKind::Anon => {
+                            if bound_ty.index == ty::INNERMOST {
+                                write!(f, "?{}", bound_ty.var.index())
+                            } else {
+                                write!(f, "?{}_{}", bound_ty.index.index(), bound_ty.var.index())
+                            }
+                        }
+
+                        ty::BoundTyKind::Param(p) => write!(f, "{}", p),
+                    }
+                }
                 Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
                 Dynamic(data, r) => {
                     let r = r.print_to_string(cx);
index 1fc9ee07a1ae49e03aac74689c59cfa858871359..a802729e3fbdbfe24317565dc98ffc9d35e51d80 100644 (file)
@@ -426,7 +426,6 @@ pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
 
             // These cannot exist in borrowck
             RegionKind::ReVar(..) |
-            RegionKind::ReCanonical(..) |
             RegionKind::RePlaceholder(..) |
             RegionKind::ReClosureBound(..) |
             RegionKind::ReErased => span_bug!(borrow_span,
index 1f83c30a3876a215b7a9c8fa584bc334bea2496a..78a31ed668fcae090b32f31f3fee1e1bd71fbeea 100644 (file)
@@ -363,7 +363,6 @@ fn guarantee_valid(&mut self,
 
                     ty::ReStatic => self.item_ub,
 
-                    ty::ReCanonical(_) |
                     ty::ReEmpty |
                     ty::ReClosureBound(..) |
                     ty::ReLateBound(..) |
index 7c7662a88de535a1af92a71c40a0617a185fa058..e50534a4e1dc95fc7d19eaf5f3c6d4f0e691046c 100644 (file)
@@ -19,7 +19,7 @@
 use type_of::{LayoutLlvmExt, PointerKind};
 use value::Value;
 
-use rustc_target::abi::{LayoutOf, Size, TyLayout};
+use rustc_target::abi::{LayoutOf, Size, TyLayout, Abi as LayoutAbi};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout;
 
@@ -302,21 +302,49 @@ fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
         FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
             let mut layout = cx.layout_of(ty);
             // Don't pass the vtable, it's not an argument of the virtual fn.
-            // Instead, pass just the (thin pointer) first field of `*dyn Trait`.
+            // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
+            // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
             if arg_idx == Some(0) {
-                // FIXME(eddyb) `layout.field(cx, 0)` is not enough because e.g.
-                // `Box<dyn Trait>` has a few newtype wrappers around the raw
-                // pointer, so we'd have to "dig down" to find `*dyn Trait`.
-                let pointee = if layout.is_unsized() {
-                    layout.ty
+                let fat_pointer_ty = if layout.is_unsized() {
+                    // unsized `self` is passed as a pointer to `self`
+                    // FIXME (mikeyhew) change this to use &own if it is ever added to the language
+                    cx.tcx.mk_mut_ptr(layout.ty)
                 } else {
-                    layout.ty.builtin_deref(true)
-                        .unwrap_or_else(|| {
-                            bug!("FnType::new_vtable: non-pointer self {:?}", layout)
-                        }).ty
+                    match layout.abi {
+                        LayoutAbi::ScalarPair(..) => (),
+                        _ => bug!("receiver type has unsupported layout: {:?}", layout)
+                    }
+
+                    // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
+                    // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
+                    // elsewhere in the compiler as a method on a `dyn Trait`.
+                    // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
+                    // get a built-in pointer type
+                    let mut fat_pointer_layout = layout;
+                    'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
+                        && !fat_pointer_layout.ty.is_region_ptr()
+                    {
+                        'iter_fields: for i in 0..fat_pointer_layout.fields.count() {
+                            let field_layout = fat_pointer_layout.field(cx, i);
+
+                            if !field_layout.is_zst() {
+                                fat_pointer_layout = field_layout;
+                                continue 'descend_newtypes
+                            }
+                        }
+
+                        bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
+                    }
+
+                    fat_pointer_layout.ty
                 };
-                let fat_ptr_ty = cx.tcx.mk_mut_ptr(pointee);
-                layout = cx.layout_of(fat_ptr_ty).field(cx, 0);
+
+                // we now have a type like `*mut RcBox<dyn Trait>`
+                // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
+                // this is understood as a special case elsewhere in the compiler
+                let unit_pointer_ty = cx.tcx.mk_mut_ptr(cx.tcx.mk_unit());
+                layout = cx.layout_of(unit_pointer_ty);
+                layout.ty = fat_pointer_ty;
             }
             ArgType::new(layout)
         })
index 81619c219757b4a11a43e627e7b5cca698b1b8c1..b5ed256cef6fd24371f85dc54c60e2056f5ec4f3 100644 (file)
@@ -1508,6 +1508,7 @@ enum Message {
     },
     CodegenComplete,
     CodegenItem,
+    CodegenAborted,
 }
 
 struct Diagnostic {
@@ -1788,6 +1789,7 @@ fn start_executing_work(tcx: TyCtxt,
         let mut needs_lto = Vec::new();
         let mut lto_import_only_modules = Vec::new();
         let mut started_lto = false;
+        let mut codegen_aborted = false;
 
         // This flag tracks whether all items have gone through codegens
         let mut codegen_done = false;
@@ -1805,13 +1807,19 @@ fn start_executing_work(tcx: TyCtxt,
         let mut llvm_start_time = None;
 
         // Run the message loop while there's still anything that needs message
-        // processing:
+        // processing. Note that as soon as codegen is aborted we simply want to
+        // wait for all existing work to finish, so many of the conditions here
+        // only apply if codegen hasn't been aborted as they represent pending
+        // work to be done.
         while !codegen_done ||
-              work_items.len() > 0 ||
               running > 0 ||
-              needs_lto.len() > 0 ||
-              lto_import_only_modules.len() > 0 ||
-              main_thread_worker_state != MainThreadWorkerState::Idle {
+              (!codegen_aborted && (
+                  work_items.len() > 0 ||
+                  needs_lto.len() > 0 ||
+                  lto_import_only_modules.len() > 0 ||
+                  main_thread_worker_state != MainThreadWorkerState::Idle
+              ))
+        {
 
             // While there are still CGUs to be codegened, the coordinator has
             // to decide how to utilize the compiler processes implicit Token:
@@ -1840,6 +1848,9 @@ fn start_executing_work(tcx: TyCtxt,
                         spawn_work(cgcx, item);
                     }
                 }
+            } else if codegen_aborted {
+                // don't queue up any more work if codegen was aborted, we're
+                // just waiting for our existing children to finish
             } else {
                 // If we've finished everything related to normal codegen
                 // then it must be the case that we've got some LTO work to do.
@@ -1904,7 +1915,7 @@ fn start_executing_work(tcx: TyCtxt,
 
             // Spin up what work we can, only doing this while we've got available
             // parallelism slots and work left to spawn.
-            while work_items.len() > 0 && running < tokens.len() {
+            while !codegen_aborted && work_items.len() > 0 && running < tokens.len() {
                 let (item, _) = work_items.pop().unwrap();
 
                 maybe_start_llvm_timer(cgcx.config(item.module_kind()),
@@ -1969,6 +1980,7 @@ fn start_executing_work(tcx: TyCtxt,
                     if !cgcx.opts.debugging_opts.no_parallel_llvm {
                         helper.request_token();
                     }
+                    assert!(!codegen_aborted);
                     assert_eq!(main_thread_worker_state,
                                MainThreadWorkerState::Codegenning);
                     main_thread_worker_state = MainThreadWorkerState::Idle;
@@ -1976,11 +1988,26 @@ fn start_executing_work(tcx: TyCtxt,
 
                 Message::CodegenComplete => {
                     codegen_done = true;
+                    assert!(!codegen_aborted);
                     assert_eq!(main_thread_worker_state,
                                MainThreadWorkerState::Codegenning);
                     main_thread_worker_state = MainThreadWorkerState::Idle;
                 }
 
+                // If codegen is aborted that means translation was aborted due
+                // to some normal-ish compiler error. In this situation we want
+                // to exit as soon as possible, but we want to make sure all
+                // existing work has finished. Flag codegen as being done, and
+                // then conditions above will ensure no more work is spawned but
+                // we'll keep executing this loop until `running` hits 0.
+                Message::CodegenAborted => {
+                    assert!(!codegen_aborted);
+                    codegen_done = true;
+                    codegen_aborted = true;
+                    assert_eq!(main_thread_worker_state,
+                               MainThreadWorkerState::Codegenning);
+                }
+
                 // If a thread exits successfully then we drop a token associated
                 // with that worker and update our `running` count. We may later
                 // re-acquire a token to continue running more work. We may also not
@@ -2446,6 +2473,19 @@ pub fn codegen_finished(&self, tcx: TyCtxt) {
         drop(self.coordinator_send.send(Box::new(Message::CodegenComplete)));
     }
 
+    /// Consume this context indicating that codegen was entirely aborted, and
+    /// we need to exit as quickly as possible.
+    ///
+    /// This method blocks the current thread until all worker threads have
+    /// finished, and all worker threads should have exited or be real close to
+    /// exiting at this point.
+    pub fn codegen_aborted(self) {
+        // Signal to the coordinator it should spawn no more work and start
+        // shutdown.
+        drop(self.coordinator_send.send(Box::new(Message::CodegenAborted)));
+        drop(self.future.join());
+    }
+
     pub fn check_for_errors(&self, sess: &Session) {
         self.shared_emitter_main.check(sess, false);
     }
@@ -2464,6 +2504,11 @@ pub fn wait_for_signal_to_codegen_item(&self) {
     }
 }
 
+// impl Drop for OngoingCodegen {
+//     fn drop(&mut self) {
+//     }
+// }
+
 pub(crate) fn submit_codegened_module_to_llvm(tcx: TyCtxt,
                                               module: ModuleCodegen,
                                               cost: u64) {
index a4c7a7123b9647d1745728eadc1edcfce50a3f76..876fa993e1293e6c84f509eb715ba893b3b6697b 100644 (file)
 use rustc_data_structures::sync::Lrc;
 
 use std::any::Any;
+use std::cmp;
 use std::ffi::CString;
-use std::sync::Arc;
-use std::time::{Instant, Duration};
 use std::i32;
-use std::cmp;
+use std::ops::{Deref, DerefMut};
+use std::sync::Arc;
 use std::sync::mpsc;
+use std::time::{Instant, Duration};
 use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
 use syntax::attr;
@@ -557,7 +558,7 @@ fn create_entry_fn(
         // regions must appear in the argument
         // listing.
         let main_ret_ty = cx.tcx.erase_regions(
-            &main_ret_ty.no_late_bound_regions().unwrap(),
+            &main_ret_ty.no_bound_vars().unwrap(),
         );
 
         if declare::get_defined_value(cx, "main").is_some() {
@@ -820,6 +821,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         metadata,
         rx,
         codegen_units.len());
+    let ongoing_codegen = AbortCodegenOnDrop(Some(ongoing_codegen));
 
     // Codegen an allocator shim, if necessary.
     //
@@ -949,7 +951,54 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     ongoing_codegen.check_for_errors(tcx.sess);
 
     assert_and_save_dep_graph(tcx);
-    ongoing_codegen
+    ongoing_codegen.into_inner()
+}
+
+/// A curious wrapper structure whose only purpose is to call `codegen_aborted`
+/// when it's dropped abnormally.
+///
+/// In the process of working on rust-lang/rust#55238 a mysterious segfault was
+/// stumbled upon. The segfault was never reproduced locally, but it was
+/// suspected to be releated to the fact that codegen worker threads were
+/// sticking around by the time the main thread was exiting, causing issues.
+///
+/// This structure is an attempt to fix that issue where the `codegen_aborted`
+/// message will block until all workers have finished. This should ensure that
+/// even if the main codegen thread panics we'll wait for pending work to
+/// complete before returning from the main thread, hopefully avoiding
+/// segfaults.
+///
+/// If you see this comment in the code, then it means that this workaround
+/// worked! We may yet one day track down the mysterious cause of that
+/// segfault...
+struct AbortCodegenOnDrop(Option<OngoingCodegen>);
+
+impl AbortCodegenOnDrop {
+    fn into_inner(mut self) -> OngoingCodegen {
+        self.0.take().unwrap()
+    }
+}
+
+impl Deref for AbortCodegenOnDrop {
+    type Target = OngoingCodegen;
+
+    fn deref(&self) -> &OngoingCodegen {
+        self.0.as_ref().unwrap()
+    }
+}
+
+impl DerefMut for AbortCodegenOnDrop {
+    fn deref_mut(&mut self) -> &mut OngoingCodegen {
+        self.0.as_mut().unwrap()
+    }
+}
+
+impl Drop for AbortCodegenOnDrop {
+    fn drop(&mut self) {
+        if let Some(codegen) = self.0.take() {
+            codegen.codegen_aborted();
+        }
+    }
 }
 
 fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
index 7300bac96182b53bbdd6ddfc9e6d48e05dc9d1a4..c8c693257d52f410261bd223c7d2872dc50b475a 100644 (file)
@@ -44,7 +44,7 @@ pub fn get_fn(
     debug!("get_fn(instance={:?})", instance);
 
     assert!(!instance.substs.needs_infer());
-    assert!(!instance.substs.has_escaping_regions());
+    assert!(!instance.substs.has_escaping_bound_vars());
     assert!(!instance.substs.has_param_types());
 
     let sig = instance.fn_sig(cx.tcx);
index f5abb527e430fa91c41a6ce4f6c12c9c3a9b21d1..eb5ae81b2184024ad6191c52580dc348466a87a2 100644 (file)
@@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::Infer(_) |
         ty::UnnormalizedProjection(..) |
         ty::Projection(..) |
+        ty::Bound(..) |
         ty::Opaque(..) |
         ty::GeneratorWitness(..) |
         ty::Param(_) => {
index d98b7869ae98e3dfa9a54b8895a5390559db503f..a7f4c48c89bd6c99ef8e7a559e702f14d0033b26 100644 (file)
@@ -642,14 +642,46 @@ fn codegen_terminator(&mut self,
                     (&args[..], None)
                 };
 
-                for (i, arg) in first_args.iter().enumerate() {
+                'make_args: for (i, arg) in first_args.iter().enumerate() {
                     let mut op = self.codegen_operand(&bx, arg);
+
                     if let (0, Some(ty::InstanceDef::Virtual(_, idx))) = (i, def) {
-                        if let Pair(data_ptr, meta) = op.val {
-                            llfn = Some(meth::VirtualIndex::from_index(idx)
-                                .get_fn(&bx, meta, &fn_ty));
-                            llargs.push(data_ptr);
-                            continue;
+                        if let Pair(..) = op.val {
+                            // In the case of Rc<Self>, we need to explicitly pass a
+                            // *mut RcBox<Self> with a Scalar (not ScalarPair) ABI. This is a hack
+                            // that is understood elsewhere in the compiler as a method on
+                            // `dyn Trait`.
+                            // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
+                            // we get a value of a built-in pointer type
+                            'descend_newtypes: while !op.layout.ty.is_unsafe_ptr()
+                                            && !op.layout.ty.is_region_ptr()
+                            {
+                                'iter_fields: for i in 0..op.layout.fields.count() {
+                                    let field = op.extract_field(&bx, i);
+                                    if !field.layout.is_zst() {
+                                        // we found the one non-zero-sized field that is allowed
+                                        // now find *its* non-zero-sized field, or stop if it's a
+                                        // pointer
+                                        op = field;
+                                        continue 'descend_newtypes
+                                    }
+                                }
+
+                                span_bug!(span, "receiver has no non-zero-sized fields {:?}", op);
+                            }
+
+                            // now that we have `*dyn Trait` or `&dyn Trait`, split it up into its
+                            // data pointer and vtable. Look up the method in the vtable, and pass
+                            // the data pointer as the first argument
+                            match op.val {
+                                Pair(data_ptr, meta) => {
+                                    llfn = Some(meth::VirtualIndex::from_index(idx)
+                                        .get_fn(&bx, meta, &fn_ty));
+                                    llargs.push(data_ptr);
+                                    continue 'make_args
+                                }
+                                other => bug!("expected a Pair, got {:?}", other)
+                            }
                         } else if let Ref(data_ptr, Some(meta), _) = op.val {
                             // by-value dynamic dispatch
                             llfn = Some(meth::VirtualIndex::from_index(idx)
index 03ded64e642355706e8c7b5471028a0ec8a5e30e..b01d7e3a776f7145b791bfe7670db6f55636f6f4 100644 (file)
@@ -285,7 +285,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
 
         debug!("llvm_type({:#?})", self);
 
-        assert!(!self.ty.has_escaping_regions(), "{:?} has escaping regions", self.ty);
+        assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty);
 
         // Make sure lifetimes are erased, to avoid generating distinct LLVM
         // types for Rust types that only differ in the choice of lifetimes.
index 470c8b03d0bca212282d8bc9c4185eb58418f5e7..1e32f5ef6f0b61c82a92249497fa2c40aa86048c 100644 (file)
@@ -38,3 +38,8 @@ syntax = { path = "../libsyntax" }
 smallvec = { version = "0.6.5", features = ["union"] }
 syntax_ext = { path = "../libsyntax_ext" }
 syntax_pos = { path = "../libsyntax_pos" }
+
+[dependencies.jemalloc-sys]
+version = '0.1.8'
+optional = true
+features = ['unprefixed_malloc_on_supported_platforms']
index 276b7290c2ef012de4ac7e0c83b48a1a77702232..e8fdaddaeb89cd5a3e654f196c3dd9007030707f 100644 (file)
 extern crate syntax_ext;
 extern crate syntax_pos;
 
+// Note that the linkage here should be all that we need, on Linux we're not
+// prefixing the symbols here so this should naturally override our default
+// allocator. On OSX it should override via the zone allocator. We shouldn't
+// enable this by default on other platforms, so other platforms aren't handled
+// here yet.
+#[cfg(feature = "jemalloc-sys")]
+extern crate jemalloc_sys;
+
 use driver::CompileController;
 use pretty::{PpMode, UserIdentifiedItem};
 
index f18f40bf7a1448851a6bc44b398673d86a8eb76b..28b7c610a91c0f8a9d2ccf728c9d1f854d9b6ee9 100644 (file)
@@ -616,22 +616,22 @@ fn escaping() {
         // Theta = [A -> &'a foo]
         env.create_simple_region_hierarchy();
 
-        assert!(!env.t_nil().has_escaping_regions());
+        assert!(!env.t_nil().has_escaping_bound_vars());
 
         let t_rptr_free1 = env.t_rptr_free(1);
-        assert!(!t_rptr_free1.has_escaping_regions());
+        assert!(!t_rptr_free1.has_escaping_bound_vars());
 
         let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, d1());
-        assert!(t_rptr_bound1.has_escaping_regions());
+        assert!(t_rptr_bound1.has_escaping_bound_vars());
 
         let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, d2());
-        assert!(t_rptr_bound2.has_escaping_regions());
+        assert!(t_rptr_bound2.has_escaping_bound_vars());
 
         // t_fn = fn(A)
         let t_param = env.t_param(0);
-        assert!(!t_param.has_escaping_regions());
+        assert!(!t_param.has_escaping_bound_vars());
         let t_fn = env.t_fn(&[t_param], env.t_nil());
-        assert!(!t_fn.has_escaping_regions());
+        assert!(!t_fn.has_escaping_bound_vars());
     })
 }
 
index 5197876f921973ce7d38770eeea3beb2ede7e744..2e19b441d0e3915a0917577692eab39b1e9b8c5c 100644 (file)
@@ -718,6 +718,7 @@ fn check_type_for_ffi(&self,
 
             ty::Param(..) |
             ty::Infer(..) |
+            ty::Bound(..) |
             ty::Error |
             ty::Closure(..) |
             ty::Generator(..) |
index 9864c1f3d7c686dca4c69c3b88c2a68be731138f..0854df5d1269f36679846fd387347d1c1c59128b 100644 (file)
@@ -400,7 +400,7 @@ pub fn list_crate_metadata(&self,
         for (i, dep) in root.crate_deps
                             .decode(self)
                             .enumerate() {
-            write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?;
+            write!(out, "{} {}{}\n", i + 1, dep.name, dep.extra_filename)?;
         }
         write!(out, "\n")?;
         Ok(())
index 2b671891fca6dd00736c2b1257fda7f1b467300b..99372a511a9de5e2c2307b83255c68c7d38bff93 100644 (file)
@@ -277,8 +277,7 @@ fn give_name_from_error_region(
             | ty::RePlaceholder(..)
             | ty::ReEmpty
             | ty::ReErased
-            | ty::ReClosureBound(..)
-            | ty::ReCanonical(..) => None,
+            | ty::ReClosureBound(..) => None,
         }
     }
 
index 5904138ef603ac03df58ffe06f7df786c5425cb1..35ec478143546d90177a81c7f41efb2eebdcf5f8 100644 (file)
@@ -82,9 +82,9 @@ pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>)
         // when we move to universes, we will, and this assertion
         // will start to fail.
         let ty::OutlivesPredicate(k1, r2) =
-            query_constraint.no_late_bound_regions().unwrap_or_else(|| {
+            query_constraint.no_bound_vars().unwrap_or_else(|| {
                 bug!(
-                    "query_constraint {:?} contained bound regions",
+                    "query_constraint {:?} contained bound vars",
                     query_constraint,
                 );
             });
index aa9564bdcaf030f21b4e2c3451857b8ae4075e45..734ddbc3ab9a72af39babca2f7080aac3e3577c9 100644 (file)
@@ -359,7 +359,7 @@ fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if ty.has_escaping_regions() || ty.references_error() {
+        if ty.has_escaping_bound_vars() || ty.references_error() {
             span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
         } else {
             ty
@@ -2214,8 +2214,8 @@ fn prove_closure_bounds(
                     .enumerate()
                     .filter_map(|(idx, constraint)| {
                         let ty::OutlivesPredicate(k1, r2) =
-                            constraint.no_late_bound_regions().unwrap_or_else(|| {
-                                bug!("query_constraint {:?} contained bound regions", constraint,);
+                            constraint.no_bound_vars().unwrap_or_else(|| {
+                                bug!("query_constraint {:?} contained bound vars", constraint,);
                             });
 
                         match k1.unpack() {
index 8c6966691328a44029a83cf9378dec343482d07d..8e27635dee8c13868c3d5e9a04cd1bf3289a83f0 100644 (file)
@@ -905,12 +905,12 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                   trait_ty: Ty<'tcx>,
                                                   impl_ty: Ty<'tcx>,
                                                   output: &mut Vec<MonoItem<'tcx>>) {
-    assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
-            !impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
+    assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_bound_vars() &&
+            !impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars());
 
     if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
         let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty);
-        assert!(!poly_trait_ref.has_escaping_regions());
+        assert!(!poly_trait_ref.has_escaping_bound_vars());
 
         // Walk all methods of the trait, including those of its supertraits
         let methods = tcx.vtable_methods(poly_trait_ref);
@@ -1082,7 +1082,7 @@ fn push_extra_entry_roots(&mut self) {
         // regions must appear in the argument
         // listing.
         let main_ret_ty = self.tcx.erase_regions(
-            &main_ret_ty.no_late_bound_regions().unwrap(),
+            &main_ret_ty.no_bound_vars().unwrap(),
         );
 
         let start_instance = Instance::resolve(
index 4c4d56c8938386af83b716168b4c2ea82f12f9cf..9d69a5669b1c0a85cd8971579b93c849d359371a 100644 (file)
@@ -382,6 +382,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                 self.push_type_params(substs, iter::empty(), output);
             }
             ty::Error |
+            ty::Bound(..) |
             ty::Infer(_) |
             ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
index 7061504cd0ae74b7708565116e645667d2dca047..76a8501fb177a89c4375e3c99fa175a8da097aaf 100644 (file)
@@ -844,7 +844,9 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
     let param_env = gcx.param_env(def_id);
 
     // Normalize the sig.
-    let sig = gcx.fn_sig(def_id).no_late_bound_regions().expect("LBR in ADT constructor signature");
+    let sig = gcx.fn_sig(def_id)
+        .no_bound_vars()
+        .expect("LBR in ADT constructor signature");
     let sig = gcx.normalize_erasing_regions(param_env, sig);
 
     let (adt_def, substs) = match sig.output().sty {
index bd7d9d367618be73f1bc77ce12513fae40d64087..80072153167f3c2eb6115cbfaef6905cc4b66220 100644 (file)
@@ -143,7 +143,7 @@ fn check_lang_item_type<'a, 'tcx, D>(
 {
     let did = tcx.require_lang_item(lang_item);
     let poly_sig = tcx.fn_sig(did);
-    let sig = poly_sig.no_late_bound_regions().unwrap();
+    let sig = poly_sig.no_bound_vars().unwrap();
     let lhs_ty = lhs.ty(local_decls, tcx);
     let rhs_ty = rhs.ty(local_decls, tcx);
     let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
index bb686e914a0486c098e6fea02d4541ecb6c24717..684ea4c78978cc2b9a79f5a45c448bf4508d8318 100644 (file)
@@ -13,6 +13,3 @@ bitflags = "1.0"
 log = "0.4"
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 serialize = { path = "../libserialize" }
-
-[features]
-jemalloc = []
index 38b3f2528fe8694bb922d8657760173a935444e7..8774c15ff01211b1dc6f30b95fcaa23f7fef057f 100644 (file)
@@ -44,7 +44,6 @@ pub fn opts() -> TargetOptions {
         dll_suffix: ".dylib".to_string(),
         archive_format: "bsd".to_string(),
         pre_link_args: LinkArgs::new(),
-        exe_allocation_crate: super::maybe_jemalloc(),
         has_elf_tls: version >= (10, 7),
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
index 296eaca7c7df013dac7c7cd23cf7cc6a74a2484a..e926e4913d634801a0b1fac235f461fb01ddc0fb 100644 (file)
@@ -99,10 +99,6 @@ pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
         pre_link_args,
         has_elf_tls: false,
         eliminate_frame_pointer: false,
-        // The following line is a workaround for jemalloc 4.5 being broken on
-        // ios. jemalloc 5.0 is supposed to fix this.
-        // see https://github.com/rust-lang/rust/issues/45262
-        exe_allocation_crate: None,
         .. super::apple_base::opts()
     })
 }
index c5e3385a91ca1bd70853c4fd1ba4414e78c7f4d4..055bca6c34848621d11685de781c6c8db554b216 100644 (file)
@@ -14,7 +14,7 @@ pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
     // https://developer.android.com/ndk/guides/abis.html#armeabi
     base.features = "+strict-align,+v5te".to_string();
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(32);
 
     Ok(Target {
         llvm_target: "arm-linux-androideabi".to_string(),
index 2ffa74e737fd5244e664dfa9c3b98b2bce67c511..fb78cf495e22ac2caf3db616db59cbfc531c0e07 100644 (file)
@@ -38,7 +38,6 @@ pub fn opts() -> TargetOptions {
         // dynamic linking.
         tls_model: "local-exec".to_string(),
         relro_level: RelroLevel::Full,
-        exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
     }
 }
index 32eac8663afac78f84b975b55884a3705368cfca..a9e317b7cb8a74d5f8ab907b8c8c2bcd9ab552fd 100644 (file)
@@ -33,7 +33,6 @@ pub fn opts() -> TargetOptions {
         pre_link_args: args,
         position_independent_executables: true,
         relro_level: RelroLevel::Full,
-        exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
     }
 }
index 04b8a6e706064f1a570364528e076e686a74dc46..c8a2946da50a50f7582f12faac6fd296862c303e 100644 (file)
@@ -34,7 +34,6 @@ pub fn opts() -> TargetOptions {
         position_independent_executables: true,
         eliminate_frame_pointer: false, // FIXME 43575
         relro_level: RelroLevel::Full,
-        exe_allocation_crate: super::maybe_jemalloc(),
         abi_return_struct_as_int: true,
         .. Default::default()
     }
index 4a9cd9e2f3233614e91537026f261ec275234c93..01f65d573632242ea0cbf2eab54343716efa00cb 100644 (file)
@@ -36,7 +36,6 @@ pub fn opts() -> TargetOptions {
         pre_link_args: args,
         position_independent_executables: true,
         relro_level: RelroLevel::Full,
-        exe_allocation_crate: super::maybe_jemalloc(),
         has_elf_tls: true,
         .. Default::default()
     }
index d43d45f64a55c8fc57b46218d79cfa9abbe2a275..49b4d6ec0f9549e32fe6d3b084ad5521147ca72c 100644 (file)
@@ -1270,14 +1270,6 @@ macro_rules! target_option_val {
     }
 }
 
-fn maybe_jemalloc() -> Option<String> {
-    if cfg!(feature = "jemalloc") {
-        Some("alloc_jemalloc".to_string())
-    } else {
-        None
-    }
-}
-
 /// Either a target triple string or a path to a JSON file.
 #[derive(PartialEq, Clone, Debug, Hash, RustcEncodable, RustcDecodable)]
 pub enum TargetTriple {
index c14cc3f5bc3befd3420d50edcf9d531807271e97..93b889d5d399ee12032fd31a1343b4ba40ad85c7 100644 (file)
@@ -18,7 +18,6 @@ pub fn opts() -> TargetOptions {
         has_rpath: true,
         target_family: Some("unix".to_string()),
         is_like_solaris: true,
-        exe_allocation_crate: super::maybe_jemalloc(),
 
         .. Default::default()
     }
index 5d6badf120286c42d5be864cae36f6efb33cc71c..bf252053199f8df143035e1b6bfa4c8dcfd4fe0d 100644 (file)
@@ -506,6 +506,7 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
                     ty::GeneratorWitness(..) |
                     ty::UnnormalizedProjection(..) |
                     ty::Infer(..) |
+                    ty::Bound(..) |
                     ty::Error => {
                         bug!("unexpected type {:?}", ty)
                     }
index 2ad7ab7c4d92753bb4c073f61933743cf3370980..af64522f18398a4a646f88d460e8489263380f41 100644 (file)
@@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
 
-        ty::Infer(..) | ty::Error => {
+        ty::Bound(..) | ty::Infer(..) | ty::Error => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
             Err(NoSolution)
index cde08f6832ace274442b89c18e51996c782ed491..7cc064f9c3d3d81906ad96caaa92a9e4c5e79a23 100644 (file)
@@ -108,7 +108,7 @@ fn compute_implied_outlives_bounds<'tcx>(
         // From the full set of obligations, just filter down to the
         // region relationships.
         implied_bounds.extend(obligations.into_iter().flat_map(|obligation| {
-            assert!(!obligation.has_escaping_regions());
+            assert!(!obligation.has_escaping_bound_vars());
             match obligation.predicate {
                 ty::Predicate::Trait(..) |
                 ty::Predicate::Subtype(..) |
@@ -122,14 +122,14 @@ fn compute_implied_outlives_bounds<'tcx>(
                     vec![]
                 }
 
-                ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
+                ty::Predicate::RegionOutlives(ref data) => match data.no_bound_vars() {
                     None => vec![],
                     Some(ty::OutlivesPredicate(r_a, r_b)) => {
                         vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
                     }
                 },
 
-                ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
+                ty::Predicate::TypeOutlives(ref data) => match data.no_bound_vars() {
                     None => vec![],
                     Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                         let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
index c71898f73ecad69267aa9f0b395ba479d47f411a..052ca37b313717fa7123762068df759a37a3558c 100644 (file)
@@ -93,6 +93,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
             ty::GeneratorWitness(..) |
             ty::UnnormalizedProjection(..) |
             ty::Infer(..) |
+            ty::Bound(..) |
             ty::Error => {
                 bug!("unexpected type {:?}", ty);
             }
index e44cfec82ad642f624d224b6e7920c3f372b0977..18f8473b5b56d7d88fb600878aaa16ff8fbbe0b3 100644 (file)
@@ -1013,7 +1013,7 @@ fn conv_object_ty_poly_trait_ref(&self,
         // most importantly, that the supertraits don't contain Self,
         // to avoid ICEs.
         let object_safety_violations =
-            tcx.astconv_object_safety_violations(principal.def_id());
+            tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
         if !object_safety_violations.is_empty() {
             tcx.report_object_safety_error(
                 span, principal.def_id(), object_safety_violations)
@@ -1748,7 +1748,7 @@ pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
             self.region_bounds.iter().map(|&(region_bound, span)| {
                 // account for the binder being introduced below; no need to shift `param_ty`
                 // because, at present at least, it can only refer to early-bound regions
-                let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
+                let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
                 let outlives = ty::OutlivesPredicate(param_ty, region_bound);
                 (ty::Binder::dummy(outlives).to_predicate(), span)
             }).chain(
index 3204ef556f5ddc3b1beac7f5e897407bf3ded8e7..40f2072079a5a1ba203536b642b3f3d14ea8c53c 100644 (file)
@@ -816,7 +816,7 @@ fn check_pat_tuple_struct(&self,
         }
         // Replace constructor type with constructed type for tuple struct patterns.
         let pat_ty = pat_ty.fn_sig(tcx).output();
-        let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type");
+        let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
 
         self.demand_eqtype(pat.span, expected, pat_ty);
 
index e0ee26cba082842aab75d16aa133f5b5f0a903d3..3f0a3531244424c68a7e2b99e4adcb9e2f0ae564 100644 (file)
@@ -128,7 +128,7 @@ fn pointer_kind(&self, t: Ty<'tcx>, span: Span) ->
             ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
             ty::Param(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
-            ty::Infer(_) => None,
+            ty::Bound(..) | ty::Infer(_) => None,
 
             ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
             ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) |
index fb7c237a536bdd70cb1be8fae07dd5a82f67d452..010561d1001e5ad61cc4cf0af5da187681e0a8a6 100644 (file)
@@ -460,7 +460,7 @@ fn sig_of_closure_with_expectation(
         // Create a `PolyFnSig`. Note the oddity that late bound
         // regions appearing free in `expected_sig` are now bound up
         // in this binder we are creating.
-        assert!(!expected_sig.sig.has_regions_bound_above(ty::INNERMOST));
+        assert!(!expected_sig.sig.has_vars_bound_above(ty::INNERMOST));
         let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
             expected_sig.sig.inputs().iter().cloned(),
             expected_sig.sig.output(),
index da96d4f0cba42ce97df75969fcd74e060dd7d655..3156458b4aa4abe0690057c9cbfccfadb98e72a0 100644 (file)
@@ -419,7 +419,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let mut structural_to_nomimal = FxHashMap::default();
 
                     let sig = tcx.fn_sig(def_id);
-                    let sig = sig.no_late_bound_regions().unwrap();
+                    let sig = sig.no_bound_vars().unwrap();
                     if intr.inputs.len() != sig.inputs().len() {
                         span_err!(tcx.sess, it.span, E0444,
                                   "platform-specific intrinsic has invalid number of \
index 04c32fa88271ad24c7a4c45bafeac4c63c222951..11448750618e218252dd96cb040609c91127dac6 100644 (file)
@@ -331,7 +331,7 @@ pub fn lookup_method_in_trait(&self,
                 value
             }
         };
-        assert!(!bounds.has_escaping_regions());
+        assert!(!bounds.has_escaping_bound_vars());
 
         let cause = traits::ObligationCause::misc(span, self.body_id);
         obligations.extend(traits::predicates_for_generics(cause.clone(),
index 5a8a9632350f2621959bd8d811a3a36b98574c24..305efd0d75af6ed89b0fc26cbb2cac3d10733c48 100644 (file)
@@ -1374,7 +1374,7 @@ fn xform_method_sig(&self,
                fn_sig,
                substs);
 
-        assert!(!substs.has_escaping_regions());
+        assert!(!substs.has_escaping_bound_vars());
 
         // It is possible for type parameters or early-bound lifetimes
         // to appear in the signature of `self`. The substitutions we
index 9ac733b159ba66d6953810a70dc7915e1fd3e69f..791b5a0bdd92abebb5025afe718f7791612c8e68 100644 (file)
@@ -653,8 +653,8 @@ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
 
     fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
         debug!("register_predicate({:?})", obligation);
-        if obligation.has_escaping_regions() {
-            span_bug!(obligation.cause.span, "escaping regions in predicate {:?}",
+        if obligation.has_escaping_bound_vars() {
+            span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}",
                       obligation);
         }
         self.fulfillment_cx
@@ -1928,7 +1928,7 @@ fn projected_ty_from_poly_trait_ref(&self,
     }
 
     fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        if ty.has_escaping_regions() {
+        if ty.has_escaping_bound_vars() {
             ty // FIXME: normalization and escaping regions
         } else {
             self.normalize_associated_types_in(span, &ty)
@@ -2431,7 +2431,7 @@ pub fn add_obligations_for_parameters(&self,
                                           cause: traits::ObligationCause<'tcx>,
                                           predicates: &ty::InstantiatedPredicates<'tcx>)
     {
-        assert!(!predicates.has_escaping_regions());
+        assert!(!predicates.has_escaping_bound_vars());
 
         debug!("add_obligations_for_parameters(predicates={:?})",
                predicates);
@@ -5188,8 +5188,8 @@ pub fn instantiate_value_path(&self,
                 }
             },
         );
-        assert!(!substs.has_escaping_regions());
-        assert!(!ty.has_escaping_regions());
+        assert!(!substs.has_escaping_bound_vars());
+        assert!(!ty.has_escaping_bound_vars());
 
         // Write the "user substs" down first thing for later.
         let hir_id = self.tcx.hir.node_to_hir_id(node_id);
index 05a83dd307c38047e7bb2e76a6f7dab2603f6388..a5ad31e0b6b5f0de5e1abc1821522935186383ff 100644 (file)
@@ -31,8 +31,9 @@ pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
         .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
         .check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
-        .check(tcx.lang_items().coerce_unsized_trait(),
-               visit_implementation_of_coerce_unsized);
+        .check(tcx.lang_items().coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
+        .check(tcx.lang_items().dispatch_from_dyn_trait(),
+            visit_implementation_of_dispatch_from_dyn);
 }
 
 struct Checker<'a, 'tcx: 'a> {
@@ -98,7 +99,7 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_did:
 
     let span = tcx.hir.span(impl_node_id);
     let param_env = tcx.param_env(impl_did);
-    assert!(!self_type.has_escaping_regions());
+    assert!(!self_type.has_escaping_bound_vars());
 
     debug!("visit_implementation_of_copy: self_type={:?} (free)",
            self_type);
@@ -162,6 +163,174 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    impl_did: DefId,
+) {
+    debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}",
+           impl_did);
+    if impl_did.is_local() {
+        let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap();
+
+        let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap();
+        let span = tcx.hir.span(impl_node_id);
+
+        let source = tcx.type_of(impl_did);
+        assert!(!source.has_escaping_bound_vars());
+        let target = {
+            let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+            assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
+
+            trait_ref.substs.type_at(1)
+        };
+
+        debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}",
+            source,
+            target);
+
+        let param_env = tcx.param_env(impl_did);
+
+        let create_err = |msg: &str| {
+            struct_span_err!(tcx.sess, span, E0378, "{}", msg)
+        };
+
+        tcx.infer_ctxt().enter(|infcx| {
+            let cause = ObligationCause::misc(span, impl_node_id);
+
+            use ty::TyKind::*;
+            match (&source.sty, &target.sty) {
+                (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
+                    if infcx.at(&cause, param_env).eq(r_a, r_b).is_ok()
+                    && mutbl_a == *mutbl_b => (),
+                (&RawPtr(tm_a), &RawPtr(tm_b))
+                    if tm_a.mutbl == tm_b.mutbl => (),
+                (&Adt(def_a, substs_a), &Adt(def_b, substs_b))
+                    if def_a.is_struct() && def_b.is_struct() =>
+                {
+                    if def_a != def_b {
+                        let source_path = tcx.item_path_str(def_a.did);
+                        let target_path = tcx.item_path_str(def_b.did);
+
+                        create_err(
+                            &format!(
+                                "the trait `DispatchFromDyn` may only be implemented \
+                                for a coercion between structures with the same \
+                                definition; expected `{}`, found `{}`",
+                                source_path, target_path,
+                            )
+                        ).emit();
+
+                        return
+                    }
+
+                    if def_a.repr.c() || def_a.repr.packed() {
+                        create_err(
+                            "structs implementing `DispatchFromDyn` may not have \
+                             `#[repr(packed)]` or `#[repr(C)]`"
+                        ).emit();
+                    }
+
+                    let fields = &def_a.non_enum_variant().fields;
+
+                    let coerced_fields = fields.iter().filter_map(|field| {
+                        if tcx.type_of(field.did).is_phantom_data() {
+                            // ignore PhantomData fields
+                            return None
+                        }
+
+                        let ty_a = field.ty(tcx, substs_a);
+                        let ty_b = field.ty(tcx, substs_b);
+                        if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
+                            if ok.obligations.is_empty() {
+                                create_err(
+                                    "the trait `DispatchFromDyn` may only be implemented \
+                                     for structs containing the field being coerced, \
+                                     `PhantomData` fields, and nothing else"
+                                ).note(
+                                    &format!(
+                                        "extra field `{}` of type `{}` is not allowed",
+                                        field.ident, ty_a,
+                                    )
+                                ).emit();
+
+                                return None;
+                            }
+                        }
+
+                        Some(field)
+                    }).collect::<Vec<_>>();
+
+                    if coerced_fields.is_empty() {
+                        create_err(
+                            "the trait `DispatchFromDyn` may only be implemented \
+                            for a coercion between structures with a single field \
+                            being coerced, none found"
+                        ).emit();
+                    } else if coerced_fields.len() > 1 {
+                        create_err(
+                            "implementing the `DispatchFromDyn` trait requires multiple coercions",
+                        ).note(
+                            "the trait `DispatchFromDyn` may only be implemented \
+                                for a coercion between structures with a single field \
+                                being coerced"
+                        ).note(
+                            &format!(
+                                "currently, {} fields need coercions: {}",
+                                coerced_fields.len(),
+                                coerced_fields.iter().map(|field| {
+                                    format!("`{}` (`{}` to `{}`)",
+                                        field.ident,
+                                        field.ty(tcx, substs_a),
+                                        field.ty(tcx, substs_b),
+                                    )
+                                }).collect::<Vec<_>>()
+                                .join(", ")
+                            )
+                        ).emit();
+                    } else {
+                        let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+
+                        for field in coerced_fields {
+
+                            let predicate = tcx.predicate_for_trait_def(
+                                param_env,
+                                cause.clone(),
+                                dispatch_from_dyn_trait,
+                                0,
+                                field.ty(tcx, substs_a),
+                                &[field.ty(tcx, substs_b).into()]
+                            );
+
+                            fulfill_cx.register_predicate_obligation(&infcx, predicate);
+                        }
+
+                        // Check that all transitive obligations are satisfied.
+                        if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
+                            infcx.report_fulfillment_errors(&errors, None, false);
+                        }
+
+                        // Finally, resolve all regions.
+                        let region_scope_tree = region::ScopeTree::default();
+                        let outlives_env = OutlivesEnvironment::new(param_env);
+                        infcx.resolve_regions_and_report_errors(
+                            impl_did,
+                            &region_scope_tree,
+                            &outlives_env,
+                            SuppressRegionErrors::default(),
+                        );
+                    }
+                }
+                _ => {
+                    create_err(
+                        "the trait `DispatchFromDyn` may only be implemented \
+                        for a coercion between structures"
+                    ).emit();
+                }
+            }
+        })
+    }
+}
+
 pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                                      impl_did: DefId)
                                      -> CoerceUnsizedInfo {
@@ -187,7 +356,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
 
     let span = gcx.hir.span(impl_node_id);
     let param_env = gcx.param_env(impl_did);
-    assert!(!source.has_escaping_regions());
+    assert!(!source.has_escaping_bound_vars());
 
     let err_info = CoerceUnsizedInfo { custom_kind: None };
 
@@ -236,7 +405,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                               E0377,
                               "the trait `CoerceUnsized` may only be implemented \
                                for a coercion between structures with the same \
-                               definition; expected {}, found {}",
+                               definition; expected `{}`, found `{}`",
                               source_path,
                               target_path);
                     return err_info;
@@ -341,7 +510,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>,
                                       diff_fields.len(),
                                       diff_fields.iter()
                                           .map(|&(i, a, b)| {
-                                              format!("{} ({} to {})", fields[i].ident, a, b)
+                                              format!("`{}` (`{}` to `{}`)", fields[i].ident, a, b)
                                           })
                                           .collect::<Vec<_>>()
                                           .join(", ")));
index c136d76e358d38b54309450a41c5b8d0597ca20d..74dea7fe411ad0e710a016afd5fabc6bb39089e3 100644 (file)
@@ -210,7 +210,7 @@ fn projected_ty_from_poly_trait_ref(
         item_def_id: DefId,
         poly_trait_ref: ty::PolyTraitRef<'tcx>,
     ) -> Ty<'tcx> {
-        if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() {
+        if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
             self.tcx().mk_projection(item_def_id, trait_ref.substs)
         } else {
             // no late-bound regions, we can just ignore the binder
index f57d050fa2d77641e9cdef52b34d0d4cb75182ac..c81aea2465b7be40b39d5840be6c07bbeb915061 100644 (file)
@@ -3084,6 +3084,66 @@ impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> where T: CoerceUnsized<U> {}
 struct.
 "##,
 
+E0378: r##"
+The `DispatchFromDyn` trait currently can only be implemented for
+builtin pointer types and structs that are newtype wrappers around them
+— that is, the struct must have only one field (except for`PhantomData`),
+and that field must itself implement `DispatchFromDyn`.
+
+Examples:
+
+```
+#![feature(dispatch_from_dyn, unsize)]
+use std::{
+    marker::Unsize,
+    ops::DispatchFromDyn,
+};
+
+struct Ptr<T: ?Sized>(*const T);
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T>
+where
+    T: Unsize<U>,
+{}
+```
+
+```
+#![feature(dispatch_from_dyn)]
+use std::{
+    ops::DispatchFromDyn,
+    marker::PhantomData,
+};
+
+struct Wrapper<T> {
+    ptr: T,
+    _phantom: PhantomData<()>,
+}
+
+impl<T, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T>
+where
+    T: DispatchFromDyn<U>,
+{}
+```
+
+Example of illegal `DispatchFromDyn` implementation
+(illegal because of extra field)
+
+```compile-fail,E0378
+#![feature(dispatch_from_dyn)]
+use std::ops::DispatchFromDyn;
+
+struct WrapperExtraField<T> {
+    ptr: T,
+    extra_stuff: i32,
+}
+
+impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T>
+where
+    T: DispatchFromDyn<U>,
+{}
+```
+"##,
+
 E0390: r##"
 You tried to implement methods for a primitive type. Erroneous code example:
 
index 96b75c4792d759486f8966789592149271d3a2d3..d748d93d8988e63470b142ac6381cf7f01f9285b 100644 (file)
@@ -167,7 +167,6 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool
         RegionKind::ReEmpty
         | RegionKind::ReErased
         | RegionKind::ReClosureBound(..)
-        | RegionKind::ReCanonical(..)
         | RegionKind::ReScope(..)
         | RegionKind::ReVar(..)
         | RegionKind::RePlaceholder(..)
index 3e523c0c7f559c1481e400ea98c9c2f4a72fa011..47d34c909961e16e53a4a0d79e12a40b4a2e5aac 100644 (file)
@@ -338,6 +338,7 @@ fn add_constraints_from_ty(&mut self,
 
             ty::UnnormalizedProjection(..) |
             ty::GeneratorWitness(..) |
+            ty::Bound(..) |
             ty::Infer(..) => {
                 bug!("unexpected type encountered in \
                       variance inference: {}",
@@ -426,7 +427,6 @@ fn add_constraints_from_region(&mut self,
                 // way early-bound regions do, so we skip them here.
             }
 
-            ty::ReCanonical(_) |
             ty::ReFree(..) |
             ty::ReClosureBound(..) |
             ty::ReScope(..) |
index 88240e844edc23887fb5f66d4b4416854b8937f4..9f68fd56c5e04512d023436a9f7b0f5c47479914 100644 (file)
@@ -552,6 +552,14 @@ pub fn generics(&self) -> Option<&Generics> {
             _ => return None,
         })
     }
+
+    pub fn is_associated(&self) -> bool {
+        match *self {
+            ItemEnum::TypedefItem(_, _) |
+            ItemEnum::AssociatedTypeItem(_, _) => true,
+            _ => false,
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -1260,7 +1268,6 @@ fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
             ty::RePlaceholder(..) |
             ty::ReEmpty |
             ty::ReClosureBound(_) |
-            ty::ReCanonical(_) |
             ty::ReErased => None
         }
     }
@@ -2733,6 +2740,7 @@ fn clean(&self, cx: &DocContext) -> Type {
 
             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
 
+            ty::Bound(..) => panic!("Bound"),
             ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
             ty::Infer(..) => panic!("Infer"),
index 3f0ef61f375c09d2f21cf723be7ff1ad3353f110..8ba299d229885932e10da7ca1be49c3891178f7e 100644 (file)
@@ -2322,8 +2322,8 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
     if let Some(ref name) = item.name {
         info!("Documenting {}", name);
     }
-    document_stability(w, cx, item)?;
-    document_full(w, item, cx, "")?;
+    document_stability(w, cx, item, false)?;
+    document_full(w, item, cx, "", false)?;
     Ok(())
 }
 
@@ -2332,15 +2332,19 @@ fn render_markdown(w: &mut fmt::Formatter,
                    cx: &Context,
                    md_text: &str,
                    links: Vec<(String, String)>,
-                   prefix: &str)
+                   prefix: &str,
+                   is_hidden: bool)
                    -> fmt::Result {
     let mut ids = cx.id_map.borrow_mut();
-    write!(w, "<div class='docblock'>{}{}</div>",
-        prefix, Markdown(md_text, &links, RefCell::new(&mut ids), cx.codes))
+    write!(w, "<div class='docblock{}'>{}{}</div>",
+           if is_hidden { " hidden" } else { "" },
+           prefix,
+           Markdown(md_text, &links, RefCell::new(&mut ids),
+           cx.codes))
 }
 
 fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink,
-                  prefix: &str) -> fmt::Result {
+                  prefix: &str, is_hidden: bool) -> fmt::Result {
     if let Some(s) = item.doc_value() {
         let markdown = if s.contains('\n') {
             format!("{} [Read more]({})",
@@ -2348,28 +2352,33 @@ fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link
         } else {
             plain_summary_line(Some(s))
         };
-        render_markdown(w, cx, &markdown, item.links(), prefix)?;
+        render_markdown(w, cx, &markdown, item.links(), prefix, is_hidden)?;
     } else if !prefix.is_empty() {
-        write!(w, "<div class='docblock'>{}</div>", prefix)?;
+        write!(w, "<div class='docblock{}'>{}</div>",
+               if is_hidden { " hidden" } else { "" },
+               prefix)?;
     }
     Ok(())
 }
 
 fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
-                 cx: &Context, prefix: &str) -> fmt::Result {
+                 cx: &Context, prefix: &str, is_hidden: bool) -> fmt::Result {
     if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
         debug!("Doc block: =====\n{}\n=====", s);
-        render_markdown(w, cx, &*s, item.links(), prefix)?;
+        render_markdown(w, cx, &*s, item.links(), prefix, is_hidden)?;
     } else if !prefix.is_empty() {
-        write!(w, "<div class='docblock'>{}</div>", prefix)?;
+        write!(w, "<div class='docblock{}'>{}</div>",
+               if is_hidden { " hidden" } else { "" },
+               prefix)?;
     }
     Ok(())
 }
 
-fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
+fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
+                      is_hidden: bool) -> fmt::Result {
     let stabilities = short_stability(item, cx, true);
     if !stabilities.is_empty() {
-        write!(w, "<div class='stability'>")?;
+        write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" })?;
         for stability in stabilities {
             write!(w, "{}", stability)?;
         }
@@ -3934,14 +3943,21 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             RenderMode::ForDeref { mut_: deref_mut_ } => should_render_item(&item, deref_mut_),
         };
 
+        let (is_hidden, extra_class) = if trait_.is_none() ||
+                                          item.doc_value().is_some() ||
+                                          item.inner.is_associated() {
+            (false, "")
+        } else {
+            (true, " hidden")
+        };
         match item.inner {
             clean::MethodItem(clean::Method { ref decl, .. }) |
-            clean::TyMethodItem(clean::TyMethod{ ref decl, .. }) => {
+            clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
                 // Only render when the method is not static or we allow static methods
                 if render_method_item {
                     let id = cx.derive_id(format!("{}.{}", item_type, name));
                     let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                    write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                    write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                     write!(w, "{}", spotlight_decl(decl)?)?;
                     write!(w, "<span id='{}' class='invisible'>", ns_id)?;
                     write!(w, "<table class='table-display'><tbody><tr><td><code>")?;
@@ -3963,7 +3979,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             clean::TypedefItem(ref tydef, _) => {
                 let id = cx.derive_id(format!("{}.{}", ItemType::AssociatedType, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
                 write!(w, "</code></span></h4>\n")?;
@@ -3971,7 +3987,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             clean::AssociatedConstItem(ref ty, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
                 let src = if let Some(l) = (Item { cx, item }).src_href() {
@@ -3985,7 +4001,7 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
             clean::AssociatedTypeItem(ref bounds, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-                write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
+                write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
                 assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
                 write!(w, "</code></span></h4>\n")?;
@@ -4002,25 +4018,25 @@ fn doc_impl_item(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item,
                     if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
                         // We need the stability of the item from the trait
                         // because impls can't have a stability.
-                        document_stability(w, cx, it)?;
+                        document_stability(w, cx, it, is_hidden)?;
                         if item.doc_value().is_some() {
-                            document_full(w, item, cx, "")?;
+                            document_full(w, item, cx, "", is_hidden)?;
                         } else if show_def_docs {
                             // In case the item isn't documented,
                             // provide short documentation from the trait.
-                            document_short(w, cx, it, link, "")?;
+                            document_short(w, cx, it, link, "", is_hidden)?;
                         }
                     }
                 } else {
-                    document_stability(w, cx, item)?;
+                    document_stability(w, cx, item, is_hidden)?;
                     if show_def_docs {
-                        document_full(w, item, cx, "")?;
+                        document_full(w, item, cx, "", is_hidden)?;
                     }
                 }
             } else {
-                document_stability(w, cx, item)?;
+                document_stability(w, cx, item, is_hidden)?;
                 if show_def_docs {
-                    document_short(w, cx, item, link, "")?;
+                    document_short(w, cx, item, link, "", is_hidden)?;
                 }
             }
         }
index b31100716397b81e581e0b94ac195a82967953b4..4425712eed7a15aaf9fecc4ae761453769f31aac 100644 (file)
     onEach(document.getElementsByClassName('method'), func);
     onEach(document.getElementsByClassName('associatedconstant'), func);
     onEach(document.getElementsByClassName('impl'), func);
+    onEach(document.getElementsByClassName('impl-items'), function(e) {
+        onEach(e.getElementsByClassName('associatedconstant'), func);
+        var hiddenElems = e.getElementsByClassName('hidden');
+        var needToggle = false;
+
+        for (var i = 0; i < hiddenElems.length; ++i) {
+            if (hasClass(hiddenElems[i], "content") === false &&
+                hasClass(hiddenElems[i], "docblock") === false) {
+                needToggle = true;
+                break;
+            }
+        }
+        if (needToggle === true) {
+            var newToggle = document.createElement('a');
+            newToggle.href = 'javascript:void(0)';
+            newToggle.className = 'collapse-toggle hidden-default collapsed';
+            newToggle.innerHTML = "[<span class='inner'>" + labelForToggleButton(true) + "</span>" +
+                                  "] Show hidden undocumented items";
+            newToggle.onclick = function() {
+                if (hasClass(this, "collapsed")) {
+                    removeClass(this, "collapsed");
+                    onEach(this.parentNode.getElementsByClassName("hidden"), function(x) {
+                        if (hasClass(x, "content") === false) {
+                            removeClass(x, "hidden");
+                            addClass(x, "x");
+                        }
+                    }, true);
+                    this.innerHTML = "[<span class='inner'>" + labelForToggleButton(false) +
+                                     "</span>] Hide undocumented items"
+                } else {
+                    addClass(this, "collapsed");
+                    onEach(this.parentNode.getElementsByClassName("x"), function(x) {
+                        if (hasClass(x, "content") === false) {
+                            addClass(x, "hidden");
+                            removeClass(x, "x");
+                        }
+                    }, true);
+                    this.innerHTML = "[<span class='inner'>" + labelForToggleButton(true) +
+                                     "</span>] Show hidden undocumented items";
+                }
+            };
+            e.insertBefore(newToggle, e.firstChild);
+        }
+    });
 
     function createToggle(otherMessage, fontSize, extraClass, show) {
         var span = document.createElement('span');
index ad6cdfd3e733b131b13f7c9891629f490c40ebbc..8f679b4d22b25d51f292e0b278f7ae7578e66e2f 100644 (file)
@@ -479,17 +479,6 @@ h4 > code, h3 > code, .invisible > code {
        margin-bottom: 15px;
 }
 
-.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant {
-       margin-left: 20px;
-}
-.content .impl-items .docblock, .content .impl-items .stability {
-       margin-bottom: .6em;
-}
-
-.content .impl-items > .stability {
-       margin-left: 40px;
-}
-
 .content .docblock > .impl-items {
        margin-left: 20px;
        margin-top: -34px;
@@ -531,7 +520,20 @@ h4 > code, h3 > code, .invisible > code {
        top: -9px;
        left: -13px;
 }
-.methods > .stability {
+
+.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant {
+       margin-left: 20px;
+}
+
+.content .impl-items .docblock, .content .impl-items .stability {
+       margin-bottom: .6em;
+}
+
+.content .impl-items > .stability {
+       margin-left: 40px;
+}
+
+.methods > .stability, .content .impl-items > .stability {
        margin-top: -8px;
 }
 
@@ -839,6 +841,11 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
        text-align: center;
 }
 
+.collapse-toggle.hidden-default {
+       position: relative;
+       margin-left: 20px;
+}
+
 .ghost {
        display: none;
 }
index e10e330402f5edf3ca56fae7f527ab7bad8cdcb2..5f7a8c75d3c5f6973775c2a09fd98b1af6e4693c 100644 (file)
@@ -15,11 +15,19 @@ var mainTheme = document.getElementById("mainThemeStyle");
 
 var savedHref = [];
 
-function onEach(arr, func) {
+function onEach(arr, func, reversed) {
     if (arr && arr.length > 0 && func) {
-        for (var i = 0; i < arr.length; i++) {
-            if (func(arr[i]) === true) {
-                return true;
+        if (reversed !== true) {
+            for (var i = 0; i < arr.length; ++i) {
+                if (func(arr[i]) === true) {
+                    return true;
+                }
+            }
+        } else {
+            for (var i = arr.length - 1; i >= 0; --i) {
+                if (func(arr[i]) === true) {
+                    return true;
+                }
             }
         }
     }
index cd1e3438fc372f1d6726344e3510bbdb1ede821f..0f22459b34349fe79a22a8a3f9e5a33e4aa03cf7 100644 (file)
@@ -14,7 +14,6 @@ crate-type = ["dylib", "rlib"]
 
 [dependencies]
 alloc = { path = "../liballoc" }
-alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true }
 alloc_system = { path = "../liballoc_system" }
 panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
@@ -43,9 +42,6 @@ build_helper = { path = "../build_helper" }
 
 [features]
 backtrace = []
-debug-jemalloc = ["alloc_jemalloc/debug"]
-jemalloc = ["alloc_jemalloc"]
-force_alloc_system = []
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
 
index 31fc9ed3f772d3e254a4f103866a072a9ae1d098..1ff342fa7a7bea25213c1bb5bf4d4ea8a374dc90 100644 (file)
 //! In a given program, the standard library has one “global” memory allocator
 //! that is used for example by `Box<T>` and `Vec<T>`.
 //!
-//! Currently the default global allocator is unspecified.
-//! The compiler may link to a version of [jemalloc] on some platforms,
-//! but this is not guaranteed.
-//! Libraries, however, like `cdylib`s and `staticlib`s are guaranteed
-//! to use the [`System`] by default.
+//! Currently the default global allocator is unspecified. Libraries, however,
+//! like `cdylib`s and `staticlib`s are guaranteed to use the [`System`] by
+//! default.
 //!
-//! [jemalloc]: https://github.com/jemalloc/jemalloc
 //! [`System`]: struct.System.html
 //!
 //! # The `#[global_allocator]` attribute
index ab3e97d1d9241fd52186a8963bf3261f1970a185..b55d12e4c8dc96693dc81493fc9e7d8a94995bfa 100644 (file)
 
 #![default_lib_allocator]
 
-// Always use alloc_system during stage0 since we don't know if the alloc_*
-// crate the stage0 compiler will pick by default is enabled (e.g.
-// if the user has disabled jemalloc in `./configure`).
-// `force_alloc_system` is *only* intended as a workaround for local rebuilds
-// with a rustc without jemalloc.
-// FIXME(#44236) shouldn't need MSVC logic
-#[cfg(all(not(target_env = "msvc"),
-          any(all(stage0, not(test)), feature = "force_alloc_system")))]
+#[cfg(stage0)]
 #[global_allocator]
 static ALLOC: alloc_system::System = alloc_system::System;
 
index 9ccd37a6a45924fb1e4ecf88795d62e277311e44..ec822fddef3eba1b2638f82869d131a2b8ec9e46 100644 (file)
@@ -12,4 +12,4 @@ rustc_target = { path = "../librustc_target" }
 rustc_driver = { path = "../librustc_driver" }
 
 [features]
-jemalloc = ["rustc_target/jemalloc"]
+jemalloc = ['rustc_driver/jemalloc-sys']
diff --git a/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs b/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs
new file mode 100644 (file)
index 0000000..e166356
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
+#![feature(rustc_attrs)]
+
+use std::{
+    ops::{Deref, CoerceUnsized, DispatchFromDyn},
+    marker::Unsize,
+};
+
+struct Ptr<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized> Deref for Ptr<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &*self.0
+    }
+}
+
+impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
+impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}
+
+struct Wrapper<T: ?Sized>(T);
+
+impl<T: ?Sized> Deref for Wrapper<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
+impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}
+
+
+trait Trait {
+    // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable
+    // without unsized_locals), but wrappers arond `Self` currently are not.
+    // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented
+    // fn wrapper(self: Wrapper<Self>) -> i32;
+    fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
+    fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
+    fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32;
+}
+
+impl Trait for i32 {
+    fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
+        **self
+    }
+    fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32 {
+        **self
+    }
+    fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 {
+        ***self
+    }
+}
+
+fn main() {
+    let pw = Ptr(Box::new(Wrapper(5))) as Ptr<Wrapper<dyn Trait>>;
+    assert_eq!(pw.ptr_wrapper(), 5);
+
+    let wp = Wrapper(Ptr(Box::new(6))) as Wrapper<Ptr<dyn Trait>>;
+    assert_eq!(wp.wrapper_ptr(), 6);
+
+    let wpw = Wrapper(Ptr(Box::new(Wrapper(7)))) as Wrapper<Ptr<Wrapper<dyn Trait>>>;
+    assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
+}
diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs
new file mode 100644 (file)
index 0000000..80a7ce9
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(arbitrary_self_types)]
+#![feature(pin)]
+#![feature(rustc_attrs)]
+
+use std::{
+    rc::Rc,
+    sync::Arc,
+    pin::Pin,
+};
+
+trait Trait {
+    fn by_rc(self: Rc<Self>) -> i64;
+    fn by_arc(self: Arc<Self>) -> i64;
+    fn by_pin_mut(self: Pin<&mut Self>) -> i64;
+    fn by_pin_box(self: Pin<Box<Self>>) -> i64;
+}
+
+impl Trait for i64 {
+    fn by_rc(self: Rc<Self>) -> i64 {
+        *self
+    }
+    fn by_arc(self: Arc<Self>) -> i64 {
+        *self
+    }
+    fn by_pin_mut(self: Pin<&mut Self>) -> i64 {
+        *self
+    }
+    fn by_pin_box(self: Pin<Box<Self>>) -> i64 {
+        *self
+    }
+}
+
+fn main() {
+    let rc = Rc::new(1i64) as Rc<dyn Trait>;
+    assert_eq!(1, rc.by_rc());
+
+    let arc = Arc::new(2i64) as Arc<dyn Trait>;
+    assert_eq!(2, arc.by_arc());
+
+    let mut value = 3i64;
+    let pin_mut = Pin::new(&mut value) as Pin<&mut dyn Trait>;
+    assert_eq!(3, pin_mut.by_pin_mut());
+
+    let pin_box = Into::<Pin<Box<i64>>>::into(Box::new(4i64)) as Pin<Box<dyn Trait>>;
+    assert_eq!(4, pin_box.by_pin_box());
+}
index cbb2a00214a5a30458589108ebba6ad49bc05323..9ace8714918248c619b2c7c8a46be0e4f01540dc 100644 (file)
@@ -75,8 +75,8 @@ pub trait Qux {
     /// Docs for QUX1 in trait.
     const QUX1: i8;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
-    // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait."
-    /// Docs for QUX_DEFAULT0 in trait.
+    // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT12 in trait."
+    /// Docs for QUX_DEFAULT12 in trait.
     const QUX_DEFAULT0: u16 = 1;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
     // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in trait."
@@ -99,7 +99,7 @@ impl Qux for Bar {
     /// Docs for QUX1 in impl.
     const QUX1: i8 = 5;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT0"]' 'const QUX_DEFAULT0: u16'
-    // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT0 in trait."
+    // @has - '//*[@class="docblock hidden"]' "Docs for QUX_DEFAULT12 in trait."
     const QUX_DEFAULT0: u16 = 6;
     // @has - '//*[@id="associatedconstant.QUX_DEFAULT1"]' 'const QUX_DEFAULT1: i16'
     // @has - '//*[@class="docblock"]' "Docs for QUX_DEFAULT1 in impl."
diff --git a/src/test/rustdoc/auxiliary/enum_primitive.rs b/src/test/rustdoc/auxiliary/enum_primitive.rs
new file mode 100644 (file)
index 0000000..c265ae4
--- /dev/null
@@ -0,0 +1,210 @@
+// Copyright (c) 2015 Anders Kaseorg <andersk@mit.edu>
+
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// “Software”), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+//! This crate exports a macro `enum_from_primitive!` that wraps an
+//! `enum` declaration and automatically adds an implementation of
+//! `num::FromPrimitive` (reexported here), to allow conversion from
+//! primitive integers to the enum.  It therefore provides an
+//! alternative to the built-in `#[derive(FromPrimitive)]`, which
+//! requires the unstable `std::num::FromPrimitive` and is disabled in
+//! Rust 1.0.
+//!
+//! # Example
+//!
+//! ```
+//! #[macro_use] extern crate enum_primitive;
+//! extern crate num_traits;
+//! use num_traits::FromPrimitive;
+//!
+//! enum_from_primitive! {
+//! #[derive(Debug, PartialEq)]
+//! enum FooBar {
+//!     Foo = 17,
+//!     Bar = 42,
+//!     Baz,
+//! }
+//! }
+//!
+//! fn main() {
+//!     assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
+//!     assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
+//!     assert_eq!(FooBar::from_i32(43), Some(FooBar::Baz));
+//!     assert_eq!(FooBar::from_i32(91), None);
+//! }
+//! ```
+
+
+pub mod num_traits {
+    pub trait FromPrimitive: Sized {
+        fn from_i64(n: i64) -> Option<Self>;
+        fn from_u64(n: u64) -> Option<Self>;
+    }
+}
+
+pub use std::option::Option;
+pub use num_traits::FromPrimitive;
+
+/// Helper macro for internal use by `enum_from_primitive!`.
+#[macro_export]
+macro_rules! enum_from_primitive_impl_ty {
+    ($meth:ident, $ty:ty, $name:ident, $( $variant:ident )*) => {
+        #[allow(non_upper_case_globals, unused)]
+        fn $meth(n: $ty) -> $crate::Option<Self> {
+            $( if n == $name::$variant as $ty {
+                $crate::Option::Some($name::$variant)
+            } else )* {
+                $crate::Option::None
+            }
+        }
+    };
+}
+
+/// Helper macro for internal use by `enum_from_primitive!`.
+#[macro_export]
+#[macro_use(enum_from_primitive_impl_ty)]
+macro_rules! enum_from_primitive_impl {
+    ($name:ident, $( $variant:ident )*) => {
+        impl $crate::FromPrimitive for $name {
+            enum_from_primitive_impl_ty! { from_i64, i64, $name, $( $variant )* }
+            enum_from_primitive_impl_ty! { from_u64, u64, $name, $( $variant )* }
+        }
+    };
+}
+
+/// Wrap this macro around an `enum` declaration to get an
+/// automatically generated implementation of `num::FromPrimitive`.
+#[macro_export]
+#[macro_use(enum_from_primitive_impl)]
+macro_rules! enum_from_primitive {
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( #[$variant_attr:meta] )* $variant:ident ),+
+            $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( #[$variant_attr] )* $variant ),+
+            $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
+        }
+        enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
+    };
+
+    (
+        $( #[$enum_attr:meta] )*
+        pub enum $name:ident {
+            $( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
+        }
+    ) => {
+        $( #[$enum_attr] )*
+        pub enum $name {
+            $( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
+        }
+        enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
+    };
+}
+
index db48a6525230cb8e9cf9a0ff3f4df63801274bee..949ef1182889730f580ce65f67a7e77f6ab818e9 100644 (file)
@@ -73,7 +73,7 @@ fn c_method(&self) -> usize {
 // @has manual_impl/struct.S3.html '//*[@class="trait"]' 'T'
 // @has  - '//*[@class="docblock"]' 'Docs associated with the S3 trait implementation.'
 // @has  - '//*[@class="docblock"]' 'Docs associated with the S3 trait b_method implementation.'
-// @has - '//*[@class="docblock"]' 'Docs associated with the trait a_method definition.'
+// @has - '//*[@class="docblock hidden"]' 'Docs associated with the trait a_method definition.'
 pub struct S3(usize);
 
 /// Docs associated with the S3 trait implementation.
diff --git a/src/test/rustdoc/no-stack-overflow-25295.rs b/src/test/rustdoc/no-stack-overflow-25295.rs
new file mode 100644 (file)
index 0000000..37b0aca
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ensure this code doesn't stack overflow
+// aux-build:enum_primitive.rs
+
+#[macro_use] extern crate enum_primitive;
+
+enum_from_primitive! {
+    pub enum Test {
+        A1,A2,A3,A4,A5,A6,
+        B1,B2,B3,B4,B5,B6,
+        C1,C2,C3,C4,C5,C6,
+        D1,D2,D3,D4,D5,D6,
+        E1,E2,E3,E4,E5,E6,
+        F1,F2,F3,F4,F5,F6,
+        G1,G2,G3,G4,G5,G6,
+        H1,H2,H3,H4,H5,H6,
+        I1,I2,I3,I4,I5,I6,
+        J1,J2,J3,J4,J5,J6,
+        K1,K2,K3,K4,K5,K6,
+        L1,L2,L3,L4,L5,L6,
+        M1,M2,M3,M4,M5,M6,
+        N1,N2,N3,N4,N5,N6,
+        O1,O2,O3,O4,O5,O6,
+        P1,P2,P3,P4,P5,P6,
+        Q1,Q2,Q3,Q4,Q5,Q6,
+        R1,R2,R3,R4,R5,R6,
+        S1,S2,S3,S4,S5,S6,
+        T1,T2,T3,T4,T5,T6,
+        U1,U2,U3,U4,U5,U6,
+        V1,V2,V3,V4,V5,V6,
+        W1,W2,W3,W4,W5,W6,
+        X1,X2,X3,X4,X5,X6,
+        Y1,Y2,Y3,Y4,Y5,Y6,
+        Z1,Z2,Z3,Z4,Z5,Z6,
+    }
+}
+
index 48918b996ef5989aa9e9b67d10a805295fea5d26..4dc481174a45d4ac94a5690a256b5df4bd3f1435 100644 (file)
 use std::rc::Rc;
 
 trait Foo {
-    fn foo(self: Rc<Self>) -> usize;
+    fn foo(self: &Rc<Self>) -> usize;
 }
 
 trait Bar {
-    fn foo(self: Rc<Self>) -> usize where Self: Sized;
-    fn bar(self: Box<Self>) -> usize;
+    fn foo(self: &Rc<Self>) -> usize where Self: Sized;
+    fn bar(self: Rc<Self>) -> usize;
 }
 
 impl Foo for usize {
-    fn foo(self: Rc<Self>) -> usize {
-        *self
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
     }
 }
 
 impl Bar for usize {
-    fn foo(self: Rc<Self>) -> usize {
-        *self
+    fn foo(self: &Rc<Self>) -> usize {
+        **self
     }
 
-    fn bar(self: Box<Self>) -> usize {
+    fn bar(self: Rc<Self>) -> usize {
         *self
     }
 }
 
 fn make_foo() {
-    let x = Box::new(5usize) as Box<Foo>;
+    let x = Rc::new(5usize) as Rc<Foo>;
     //~^ ERROR E0038
     //~| ERROR E0038
 }
 
 fn make_bar() {
-    let x = Box::new(5usize) as Box<Bar>;
+    let x = Rc::new(5usize) as Rc<Bar>;
     x.bar();
 }
 
index ec9e65fc4c62d3fb8717c1886e4a5d13bfdf4a76..77ca118471db5d6d75c506c69902cbce7f35e8f0 100644 (file)
@@ -1,19 +1,19 @@
 error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/arbitrary-self-types-not-object-safe.rs:40:33
+  --> $DIR/arbitrary-self-types-not-object-safe.rs:40:32
    |
-LL |     let x = Box::new(5usize) as Box<Foo>;
-   |                                 ^^^^^^^^ the trait `Foo` cannot be made into an object
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |                                ^^^^^^^ the trait `Foo` cannot be made into an object
    |
-   = note: method `foo` has a non-standard `self` type
+   = note: method `foo`'s receiver cannot be dispatched on
 
 error[E0038]: the trait `Foo` cannot be made into an object
   --> $DIR/arbitrary-self-types-not-object-safe.rs:40:13
    |
-LL |     let x = Box::new(5usize) as Box<Foo>;
-   |             ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
+LL |     let x = Rc::new(5usize) as Rc<Foo>;
+   |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
    |
-   = note: method `foo` has a non-standard `self` type
-   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<usize>`
+   = note: method `foo`'s receiver cannot be dispatched on
+   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/derive-uninhabited-enum-38885.rs b/src/test/ui/derive-uninhabited-enum-38885.rs
new file mode 100644 (file)
index 0000000..dc7f5d6
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// compile-flags: -Wunused
+
+// ensure there are no special warnings about uninhabited types
+// when deriving Debug on an empty enum
+
+#[derive(Debug)]
+enum Void {} //~ WARN never used
+
+#[derive(Debug)]
+enum Foo { //~ WARN never used
+    Bar(u8),
+    Void(Void),
+}
+
+fn main() {}
+
diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr
new file mode 100644 (file)
index 0000000..11032ab
--- /dev/null
@@ -0,0 +1,14 @@
+warning: enum is never used: `Void`
+  --> $DIR/derive-uninhabited-enum-38885.rs:18:1
+   |
+LL | enum Void {} //~ WARN never used
+   | ^^^^^^^^^
+   |
+   = note: `-W dead-code` implied by `-W unused`
+
+warning: enum is never used: `Foo`
+  --> $DIR/derive-uninhabited-enum-38885.rs:21:1
+   |
+LL | enum Foo { //~ WARN never used
+   | ^^^^^^^^
+
index 3ffd25084b8296dc9ae53541bff20ed81330d5af..f3db697790c5e26e246ea59b4be0bdb3fa26414d 100644 (file)
@@ -5,7 +5,7 @@ LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
    |
    = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
-   = note: currently, 2 fields need coercions: b (T to U), c (U to T)
+   = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.rs b/src/test/ui/invalid_dispatch_from_dyn_impls.rs
new file mode 100644 (file)
index 0000000..1cf5c73
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unsize, dispatch_from_dyn)]
+
+use std::{
+    ops::DispatchFromDyn,
+    marker::{Unsize, PhantomData},
+};
+
+struct WrapperWithExtraField<T>(T, i32);
+
+impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
+where
+    T: DispatchFromDyn<U>,
+{} //~^^^ ERROR [E0378]
+
+
+struct MultiplePointers<T: ?Sized>{
+    ptr1: *const T,
+    ptr2: *const T,
+}
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
+where
+    T: Unsize<U>,
+{} //~^^^ ERROR [E0378]
+
+
+struct NothingToCoerce<T: ?Sized> {
+    data: PhantomData<T>,
+}
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
+//~^ ERROR [E0378]
+
+#[repr(C)]
+struct HasReprC<T: ?Sized>(Box<T>);
+
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
+where
+    T: Unsize<U>,
+{} //~^^^ ERROR [E0378]
+
+fn main() {}
diff --git a/src/test/ui/invalid_dispatch_from_dyn_impls.stderr b/src/test/ui/invalid_dispatch_from_dyn_impls.stderr
new file mode 100644 (file)
index 0000000..82186b6
--- /dev/null
@@ -0,0 +1,41 @@
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, `PhantomData` fields, and nothing else
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:20:1
+   |
+LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
+LL | | where
+LL | |     T: DispatchFromDyn<U>,
+LL | | {} //~^^^ ERROR [E0378]
+   | |__^
+   |
+   = note: extra field `1` of type `i32` is not allowed
+
+error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1
+   |
+LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
+LL | | where
+LL | |     T: Unsize<U>,
+LL | | {} //~^^^ ERROR [E0378]
+   | |__^
+   |
+   = note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
+   = note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`)
+
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced, none found
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:41:1
+   |
+LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
+  --> $DIR/invalid_dispatch_from_dyn_impls.rs:47:1
+   |
+LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
+LL | | where
+LL | |     T: Unsize<U>,
+LL | | {} //~^^^ ERROR [E0378]
+   | |__^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0378`.
index f18b58a8330e032e8a2db500a82314f61ae14d33..7feabef56609a054c9e3334fe9072d450cc8ec2a 100644 (file)
@@ -5,7 +5,7 @@ LL | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{
    |                                        ^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
    |
    = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
-   = note: currently, 2 fields need coercions: _ptr (*const T to *const U), _boo (NotPhantomData<T> to NotPhantomData<U>)
+   = note: currently, 2 fields need coercions: `_ptr` (`*const T` to `*const U`), `_boo` (`NotPhantomData<T>` to `NotPhantomData<U>`)
 
 error: aborting due to previous error
 
index f8e4f0d596e20d3a005514552b5ea0eecaa42e64..1db5ec097376cd95f6b1ebb138b97009e26601ea 100644 (file)
@@ -110,9 +110,7 @@ fn check_assoc_const() {
     // A, B, C are resolved as inherent items, their traits don't need to be in scope
     C::A; //~ ERROR associated constant `A` is private
           //~^ ERROR the trait `assoc_const::C` cannot be made into an object
-          //~| ERROR the trait bound `dyn assoc_const::C: assoc_const::A` is not satisfied
     C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
-          //~^ ERROR the trait bound `dyn assoc_const::C: assoc_const::B` is not satisfied
     C::C; // OK
 }
 
index fc14ae91d7b36c3464d4ed1cbb86256c16a54487..4ede83d5d73627e3a68e20777e9ce401abc7c153 100644 (file)
@@ -100,30 +100,6 @@ error[E0624]: associated constant `A` is private
 LL |     C::A; //~ ERROR associated constant `A` is private
    |     ^^^^
 
-error[E0277]: the trait bound `dyn assoc_const::C: assoc_const::A` is not satisfied
-  --> $DIR/trait-item-privacy.rs:111:5
-   |
-LL |     C::A; //~ ERROR associated constant `A` is private
-   |     ^^^^ the trait `assoc_const::A` is not implemented for `dyn assoc_const::C`
-   |
-note: required by `assoc_const::A::A`
-  --> $DIR/trait-item-privacy.rs:35:9
-   |
-LL |         const A: u8 = 0;
-   |         ^^^^^^^^^^^^^^^^
-
-error[E0277]: the trait bound `dyn assoc_const::C: assoc_const::B` is not satisfied
-  --> $DIR/trait-item-privacy.rs:114:5
-   |
-LL |     C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
-   |     ^^^^ the trait `assoc_const::B` is not implemented for `dyn assoc_const::C`
-   |
-note: required by `assoc_const::B::B`
-  --> $DIR/trait-item-privacy.rs:39:9
-   |
-LL |         const B: u8 = 0;
-   |         ^^^^^^^^^^^^^^^^
-
 error[E0038]: the trait `assoc_const::C` cannot be made into an object
   --> $DIR/trait-item-privacy.rs:111:5
    |
@@ -135,36 +111,36 @@ LL |     C::A; //~ ERROR associated constant `A` is private
    = note: the trait cannot contain associated consts like `A`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/trait-item-privacy.rs:127:12
+  --> $DIR/trait-item-privacy.rs:125:12
    |
 LL |     let _: S::A; //~ ERROR ambiguous associated type
    |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::A`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/trait-item-privacy.rs:128:12
+  --> $DIR/trait-item-privacy.rs:126:12
    |
 LL |     let _: S::B; //~ ERROR ambiguous associated type
    |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::B`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/trait-item-privacy.rs:129:12
+  --> $DIR/trait-item-privacy.rs:127:12
    |
 LL |     let _: S::C; //~ ERROR ambiguous associated type
    |            ^^^^ help: use fully-qualified syntax: `<S as Trait>::C`
 
 error: associated type `A` is private
-  --> $DIR/trait-item-privacy.rs:131:12
+  --> $DIR/trait-item-privacy.rs:129:12
    |
 LL |     let _: T::A; //~ ERROR associated type `A` is private
    |            ^^^^
 
 error: associated type `A` is private
-  --> $DIR/trait-item-privacy.rs:140:9
+  --> $DIR/trait-item-privacy.rs:138:9
    |
 LL |         A = u8, //~ ERROR associated type `A` is private
    |         ^^^^^^
 
-error: aborting due to 17 previous errors
+error: aborting due to 15 previous errors
 
-Some errors occurred: E0038, E0223, E0277, E0599, E0624.
+Some errors occurred: E0038, E0223, E0599, E0624.
 For more information about an error, try `rustc --explain E0038`.
index dac76fb57fd7c3a3b4592b596222fd5009d261d9..01d7e89847a89fa454cd5d4bfbfc07174086e2c4 100644 (file)
@@ -20,5 +20,4 @@ fn main() {
     (box 10 as Box<bar>).dup();
     //~^ ERROR E0038
     //~| ERROR E0038
-    //~| ERROR E0277
 }
index 1e1fcbe340e58259430f1901be149585f8f2a507..db0cd38cb6a682fe256b5370c0fc64900d70badc 100644 (file)
@@ -10,12 +10,6 @@ error[E0107]: wrong number of type arguments: expected 1, found 2
 LL |     10.blah::<i32, i32>(); //~ ERROR wrong number of type arguments: expected 1, found 2
    |                    ^^^ unexpected type argument
 
-error[E0277]: the trait bound `dyn bar: bar` is not satisfied
-  --> $DIR/trait-test-2.rs:20:26
-   |
-LL |     (box 10 as Box<bar>).dup();
-   |                          ^^^ the trait `bar` is not implemented for `dyn bar`
-
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/trait-test-2.rs:20:16
    |
@@ -35,7 +29,7 @@ LL |     (box 10 as Box<bar>).dup();
    = note: method `blah` has generic type parameters
    = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn bar>>` for `std::boxed::Box<{integer}>`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0038, E0107, E0277.
+Some errors occurred: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.
index c794e169fca3322f58ac72e99ca5fb34f34d823c..4ade87f5d65bd2c167175bcf27ca178a28df1b50 100755 (executable)
@@ -26,7 +26,7 @@ except ImportError:
 MAINTAINERS = {
     'miri': '@oli-obk @RalfJung @eddyb',
     'clippy-driver': '@Manishearth @llogiq @mcarton @oli-obk',
-    'rls': '@nrc',
+    'rls': '@nrc @Xanewok',
     'rustfmt': '@nrc',
     'book': '@carols10cents @steveklabnik',
     'nomicon': '@frewsxcv @Gankro',
@@ -81,8 +81,8 @@ def update_latest(
                 status[os] = new
                 if new > old:
                     changed = True
-                    message += '🎉 {} on {}: {} → {}.\n' \
-                        .format(tool, os, old, new)
+                    message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
+                        .format(tool, os, old, new, MAINTAINERS.get(tool))
                 elif new < old:
                     changed = True
                     message += '💔 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \
index 69f61bc248dbb5e6a0633799e5c5e8de4b309d41..466d2fa0d2bd627b4461c52158dc7e8cdc30a8ed 100644 (file)
@@ -84,8 +84,7 @@ fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) {
 
         // This is intentional, this dependency just makes the crate available
         // for others later on. Cover cases
-        let whitelisted = krate == "alloc_jemalloc";
-        let whitelisted = whitelisted || krate.starts_with("panic");
+        let whitelisted = krate.starts_with("panic");
         if toml.contains("name = \"std\"") && whitelisted {
             continue
         }
index c5f5896d286c32480689b704ec9e27274b1121e5..e235de9c5e138d619b2ef38f0915025086d1fd31 100644 (file)
@@ -57,7 +57,6 @@ macro_rules! tidy_error {
 fn filter_dirs(path: &Path) -> bool {
     let skip = [
         "src/dlmalloc",
-        "src/jemalloc",
         "src/llvm",
         "src/llvm-emscripten",
         "src/libbacktrace",
index 3d5e18e37b070c1aeaa93a693639bbf4bce68cf9..e8f197ba78afe1f83d4f7a158d1443ed2efa0a6c 100644 (file)
@@ -28,7 +28,6 @@
 //! - core may not have platform-specific code
 //! - libcompiler_builtins may have platform-specific code
 //! - liballoc_system may have platform-specific code
-//! - liballoc_jemalloc may have platform-specific code
 //! - libpanic_abort may have platform-specific code
 //! - libpanic_unwind may have platform-specific code
 //! - libunwind may have platform-specific code
@@ -52,7 +51,6 @@
 // Paths that may contain platform-specific code
 const EXCEPTION_PATHS: &[&str] = &[
     // std crates
-    "src/liballoc_jemalloc",
     "src/liballoc_system",
     "src/libcompiler_builtins",
     "src/liblibc",