]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #50134 - andjo403:jobserver, r=michaelwoerister
authorbors <bors@rust-lang.org>
Wed, 25 Apr 2018 11:40:18 +0000 (11:40 +0000)
committerbors <bors@rust-lang.org>
Wed, 25 Apr 2018 11:40:18 +0000 (11:40 +0000)
make rustdoc test follow the jobserver limit of threads

fix that to many threads is executing at the same time
when rustdoc test is executed.

349 files changed:
CONTRIBUTING.md
src/Cargo.lock
src/bootstrap/test.rs
src/ci/docker/x86_64-gnu-tools/checktools.sh
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/language-features/doc-alias.md [new file with mode: 0644]
src/liballoc/alloc.rs
src/liballoc/arc.rs
src/liballoc/heap.rs
src/liballoc/lib.rs
src/liballoc/raw_vec.rs
src/liballoc/rc.rs
src/liballoc/repeat-generic-slice.rs [new file with mode: 0644]
src/liballoc/slice.rs
src/liballoc/str.rs
src/liballoc/tests/str.rs
src/liballoc/vec.rs
src/liballoc_jemalloc/Cargo.toml
src/liballoc_jemalloc/lib.rs
src/liballoc_system/lib.rs
src/libcore/alloc.rs
src/libcore/array.rs
src/libcore/cell.rs
src/libcore/char/convert.rs
src/libcore/char/decode.rs
src/libcore/char/mod.rs
src/libcore/clone.rs
src/libcore/cmp.rs
src/libcore/convert.rs
src/libcore/fmt/mod.rs
src/libcore/hint.rs [new file with mode: 0644]
src/libcore/internal_macros.rs
src/libcore/intrinsics.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/num/mod.rs
src/libcore/ops/arith.rs
src/libcore/ops/index.rs
src/libcore/ops/try.rs
src/libcore/prelude/v1.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/tests/cell.rs
src/libcore/tests/char.rs
src/libcore/tests/lib.rs
src/libcore/tests/num/int_macros.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/canonical.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/region.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/context.rs
src/librustc/ty/item_path.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/keys.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/util/ppaux.rs
src/librustc_allocator/expand.rs
src/librustc_allocator/lib.rs
src/librustc_apfloat/lib.rs
src/librustc_back/target/android_base.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/windows_msvc_base.rs
src/librustc_driver/driver.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_metadata/encoder.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_traits/lib.rs
src/librustc_traits/lowering.rs
src/librustc_traits/util.rs
src/librustc_trans/allocator.rs
src/librustc_trans/base.rs
src/librustc_trans/mir/operand.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/core.rs
src/librustdoc/html/item_type.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/settings.css [new file with mode: 0644]
src/librustdoc/html/static/settings.js [new file with mode: 0644]
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/html/static/wheel.svg [new file with mode: 0644]
src/librustdoc/test.rs
src/libstd/alloc.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/table.rs
src/libstd/error.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/io/buffered.rs
src/libstd/io/cursor.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/os/android/fs.rs
src/libstd/os/bitrig/fs.rs
src/libstd/os/dragonfly/fs.rs
src/libstd/os/emscripten/fs.rs
src/libstd/os/freebsd/fs.rs
src/libstd/os/fuchsia/fs.rs
src/libstd/os/haiku/fs.rs
src/libstd/os/ios/fs.rs
src/libstd/os/linux/fs.rs
src/libstd/os/macos/fs.rs
src/libstd/os/netbsd/fs.rs
src/libstd/os/openbsd/fs.rs
src/libstd/os/solaris/fs.rs
src/libstd/path.rs
src/libstd/primitive_docs.rs
src/libstd/process.rs
src/libstd/sys/redox/ext/ffi.rs
src/libstd/sys/redox/ext/fs.rs
src/libstd/sys/redox/ext/process.rs
src/libstd/sys/redox/ext/thread.rs
src/libstd/sys/unix/ext/ffi.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/ext/net.rs
src/libstd/sys/unix/ext/process.rs
src/libstd/sys/unix/ext/thread.rs
src/libstd/sys/windows/ext/ffi.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/sys/windows/ext/process.rs
src/libstd/sys_common/wtf8.rs
src/libsyntax/edition.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/parser.rs
src/libsyntax/test.rs
src/libsyntax_ext/deriving/cmp/ord.rs
src/libsyntax_ext/deriving/cmp/partial_eq.rs
src/libsyntax_ext/deriving/cmp/partial_ord.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/decodable.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/hash.rs
src/libsyntax_ext/format.rs
src/libsyntax_pos/symbol.rs
src/test/codegen/nounwind.rs
src/test/compile-fail-fulldeps/proc-macro/attr-invalid-exprs.rs
src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs
src/test/compile-fail-fulldeps/proc-macro/attributes-included.rs
src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs
src/test/compile-fail-fulldeps/proc-macro/macro-use-bang.rs
src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs [new file with mode: 0644]
src/test/compile-fail/allocator/not-an-allocator.rs
src/test/compile-fail/array_const_index-0.rs
src/test/compile-fail/array_const_index-1.rs
src/test/compile-fail/call-fn-never-arg-wrong-type.rs
src/test/compile-fail/coerce-to-bang-cast.rs
src/test/compile-fail/coerce-to-bang.rs
src/test/compile-fail/const-err-early.rs
src/test/compile-fail/const-err-multi.rs
src/test/compile-fail/const-eval-overflow2.rs
src/test/compile-fail/const-eval-overflow2b.rs
src/test/compile-fail/const-eval-overflow2c.rs
src/test/compile-fail/const-slice-oob.rs
src/test/compile-fail/defaulted-never-note.rs
src/test/compile-fail/edition-raw-pointer-method-2015.rs
src/test/compile-fail/edition-raw-pointer-method-2018.rs
src/test/compile-fail/extern-macro.rs
src/test/compile-fail/inhabitedness-infinite-loop.rs
src/test/compile-fail/issue-44578.rs [deleted file]
src/test/compile-fail/loop-break-value.rs
src/test/compile-fail/macro-with-seps-err-msg.rs
src/test/compile-fail/macros-nonfatal-errors.rs
src/test/compile-fail/match-privately-empty.rs
src/test/compile-fail/never-assign-dead-code.rs
src/test/compile-fail/never-assign-wrong-type.rs
src/test/compile-fail/privacy/associated-item-privacy-inherent.rs
src/test/compile-fail/privacy/associated-item-privacy-trait.rs
src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs
src/test/compile-fail/private-inferred-type-3.rs
src/test/compile-fail/private-inferred-type.rs
src/test/compile-fail/single-primitive-inherent-impl.rs
src/test/compile-fail/uninhabited-irrefutable.rs
src/test/compile-fail/uninhabited-patterns.rs
src/test/compile-fail/unreachable-loop-patterns.rs
src/test/compile-fail/unreachable-try-pattern.rs
src/test/run-fail/adjust_never.rs
src/test/run-fail/call-fn-never-arg.rs
src/test/run-fail/cast-never.rs
src/test/run-fail/never-associated-type.rs
src/test/run-fail/never-type-arg.rs
src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs
src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs
src/test/run-pass-fulldeps/auxiliary/hello_macro.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/deriving-hygiene.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/macro-quote-cond.rs
src/test/run-pass-fulldeps/macro-quote-test.rs
src/test/run-pass-fulldeps/proc-macro/attr-args.rs
src/test/run-pass-fulldeps/proc-macro/attr-on-trait.rs
src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/attr-args.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/bang-macro.rs
src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/derive-b.rs
src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs
src/test/run-pass-fulldeps/proc-macro/issue-42708.rs
src/test/run-pass-fulldeps/proc-macro/issue-50061.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/negative-token.rs
src/test/run-pass-fulldeps/proc_macro.rs
src/test/run-pass/allocator-alloc-one.rs
src/test/run-pass/auxiliary/using-target-feature-unstable.rs [new file with mode: 0644]
src/test/run-pass/diverging-fallback-control-flow.rs
src/test/run-pass/empty-types-in-patterns.rs
src/test/run-pass/format-hygiene.rs [new file with mode: 0644]
src/test/run-pass/hygiene/issue-47311.rs
src/test/run-pass/hygiene/issue-47312.rs
src/test/run-pass/hygiene/legacy_interaction.rs
src/test/run-pass/hygiene/lexical.rs
src/test/run-pass/hygiene/wrap_unhygienic_example.rs
src/test/run-pass/hygiene/xcrate.rs
src/test/run-pass/impl-for-never.rs
src/test/run-pass/issue-44402.rs
src/test/run-pass/loop-break-value.rs
src/test/run-pass/mir_calls_to_shims.rs
src/test/run-pass/never-result.rs
src/test/run-pass/paths-in-macro-invocations.rs
src/test/run-pass/realloc-16687.rs
src/test/run-pass/regions-mock-trans.rs
src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs [deleted file]
src/test/run-pass/type-sizes.rs
src/test/run-pass/using-target-feature-unstable.rs [new file with mode: 0644]
src/test/rustdoc-js/alias-1.js [new file with mode: 0644]
src/test/rustdoc-js/alias-2.js [new file with mode: 0644]
src/test/rustdoc-js/alias-3.js [new file with mode: 0644]
src/test/rustdoc-js/alias.js [new file with mode: 0644]
src/test/rustdoc-js/never.js [new file with mode: 0644]
src/test/rustdoc/issue-23511.rs
src/test/ui-fulldeps/proc-macro/parent-source-spans.rs
src/test/ui-fulldeps/proc-macro/three-equals.rs
src/test/ui/associated-types-ICE-when-projecting-out-of-err.rs
src/test/ui/associated-types-ICE-when-projecting-out-of-err.stderr
src/test/ui/chalkify/lower_env1.rs [new file with mode: 0644]
src/test/ui/chalkify/lower_env1.stderr [new file with mode: 0644]
src/test/ui/chalkify/lower_impl.rs
src/test/ui/chalkify/lower_impl.stderr
src/test/ui/chalkify/lower_trait.rs
src/test/ui/chalkify/lower_trait.stderr
src/test/ui/chalkify/lower_trait_higher_rank.rs
src/test/ui/chalkify/lower_trait_higher_rank.stderr
src/test/ui/chalkify/lower_trait_where_clause.rs
src/test/ui/chalkify/lower_trait_where_clause.stderr
src/test/ui/const-eval/conditional_array_execution.rs
src/test/ui/const-eval/conditional_array_execution.stderr
src/test/ui/const-eval/issue-43197.rs
src/test/ui/const-eval/issue-43197.stderr
src/test/ui/const-eval/issue-44578.rs [new file with mode: 0644]
src/test/ui/const-eval/issue-44578.stderr [new file with mode: 0644]
src/test/ui/const-eval/promoted_errors.rs [new file with mode: 0644]
src/test/ui/const-eval/promoted_errors.stderr [new file with mode: 0644]
src/test/ui/const-eval/pub_const_err.rs
src/test/ui/const-eval/pub_const_err.stderr
src/test/ui/const-eval/pub_const_err_bin.rs [new file with mode: 0644]
src/test/ui/const-eval/pub_const_err_bin.stderr [new file with mode: 0644]
src/test/ui/e0119/conflict-with-std.rs
src/test/ui/e0119/conflict-with-std.stderr
src/test/ui/edition-lint-paths.rs [new file with mode: 0644]
src/test/ui/edition-lint-paths.stderr [new file with mode: 0644]
src/test/ui/feature-gate-doc_alias.rs [new file with mode: 0644]
src/test/ui/feature-gate-doc_alias.stderr [new file with mode: 0644]
src/test/ui/feature-gate-exhaustive-patterns.rs
src/test/ui/feature-gate-generic_associated_types.rs
src/test/ui/feature-gate-generic_associated_types.stderr
src/test/ui/feature-gate-never_type.rs [new file with mode: 0644]
src/test/ui/feature-gate-never_type.stderr [new file with mode: 0644]
src/test/ui/feature-gate/issue-49983-see-issue-0.rs [new file with mode: 0644]
src/test/ui/feature-gate/issue-49983-see-issue-0.stderr [new file with mode: 0644]
src/test/ui/hygiene/fields.rs
src/test/ui/hygiene/globs.rs
src/test/ui/hygiene/impl_items.rs
src/test/ui/hygiene/intercrate.rs
src/test/ui/hygiene/no_implicit_prelude.rs
src/test/ui/hygiene/privacy.rs
src/test/ui/hygiene/trait_items.rs
src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
src/test/ui/imports/macro-paths.rs
src/test/ui/imports/shadow_builtin_macros.rs
src/test/ui/issue-48636.rs [new file with mode: 0644]
src/test/ui/issue-48636.stderr [new file with mode: 0644]
src/test/ui/macros/macro-backtrace-invalid-internals.rs
src/test/ui/macros/macro-backtrace-invalid-internals.stderr
src/test/ui/print_type_sizes/uninhabited.rs
src/test/ui/reachable/expr_add.rs
src/test/ui/reachable/expr_assign.rs
src/test/ui/reachable/expr_call.rs
src/test/ui/reachable/expr_cast.rs
src/test/ui/reachable/expr_method.rs
src/test/ui/reachable/expr_type.rs
src/test/ui/reachable/expr_unary.rs
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs [new file with mode: 0644]
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr [new file with mode: 0644]
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs [new file with mode: 0644]
src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
src/test/ui/update-references.sh
src/tools/cargo
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/rustbook/Cargo.toml
src/tools/rustdoc-js/tester.js
src/tools/tidy/src/ui_tests.rs

index c5dd3cd720548c8ea1ca9a3b7b3035ac099d7df8..e7041dcddc42c1e222b3b5a8b8e7d23f188ae2c0 100644 (file)
@@ -47,6 +47,12 @@ as it's possible that someone else has already reported your error. This doesn't
 always work, and sometimes it's hard to know what to search for, so consider this
 extra credit. We won't mind if you accidentally file a duplicate report.
 
+Similarly, to help others who encountered the bug find your issue,
+consider filing an issue with with a descriptive title, which contains information that might be unique to it.
+This can be the language or compiler feature used, the conditions that trigger the bug,
+or part of the error message if there is any.
+An example could be: **"impossible case reached" on lifetime inference for impl Trait in return position**.
+
 Opening an issue is as easy as following [this
 link](https://github.com/rust-lang/rust/issues/new) and filling out the fields.
 Here's a template that you can use to file a bug, though it's not necessary to
index d7d23f0fa80b879d50fd6170554eeee57bf618e3..5fd8334e8ed9a6808f3a4b9547c6e613d382783e 100644 (file)
@@ -19,7 +19,6 @@ dependencies = [
 name = "alloc_jemalloc"
 version = "0.0.0"
 dependencies = [
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
@@ -223,16 +222,6 @@ dependencies = [
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "cargo_metadata"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "cargo_metadata"
 version = "0.5.4"
@@ -579,16 +568,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "elasticlunr-rs"
-version = "1.0.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strum_macros 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1127,13 +1116,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mdbook"
-version = "0.1.5"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ammonia 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "elasticlunr-rs 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1148,7 +1137,7 @@ dependencies = [
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1189,9 +1178,11 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1542,7 +1533,7 @@ dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1690,7 +1681,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2423,6 +2414,20 @@ name = "strsim"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "strum"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "strum_macros"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "syn"
 version = "0.11.11"
@@ -2910,7 +2915,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
-"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
 "checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3"
 "checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
@@ -2936,7 +2940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
-"checksum elasticlunr-rs 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19ab5f8db0ffb76b5d87454566ceb502c3650e29057c053f93e884d3b884e344"
+"checksum elasticlunr-rs 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4511b63d69dd5d31e8e29aed2c132c413f87acea8035d0584801feaab9dd1f0f"
 "checksum ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f8b449f3b18c89d2dbe40548d2ee4fa58ea0a08b761992da6ecb9788e4688834"
 "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
@@ -2992,7 +2996,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
-"checksum mdbook 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "326d0861da5681a13c19a00952a56c254dd04f00eb944e506fdb36e93ae6f1ca"
+"checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
@@ -3076,6 +3080,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
+"checksum strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "099e21b5dd6dd07b5adcf8c4b723a7c0b7efd7a9359bf963d58c0caae8532545"
+"checksum strum_macros 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd9bd569e88028750e3ae5c25616b8278ac16a8e61aba4339195c72396d49e1"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
 "checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5"
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
index ca18604e6d1f8b31686ccbb00b87217fcdec48e8..08bbd68c756b40063e8982265f3a3d7d69020154 100644 (file)
@@ -241,7 +241,16 @@ fn run(self, builder: &Builder) {
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        builder.ensure(tool::Rls { compiler, target: self.host, extra_features: Vec::new() });
+        let build_result = builder.ensure(tool::Rls {
+            compiler,
+            target: self.host,
+            extra_features: Vec::new(),
+        });
+        if build_result.is_none() {
+            eprintln!("failed to test rls: could not build");
+            return;
+        }
+
         let mut cargo = tool::prepare_tool_cargo(builder,
                                                  compiler,
                                                  host,
@@ -286,7 +295,16 @@ fn run(self, builder: &Builder) {
         let host = self.host;
         let compiler = builder.compiler(stage, host);
 
-        builder.ensure(tool::Rustfmt { compiler, target: self.host, extra_features: Vec::new() });
+        let build_result = builder.ensure(tool::Rustfmt {
+            compiler,
+            target: self.host,
+            extra_features: Vec::new(),
+        });
+        if build_result.is_none() {
+            eprintln!("failed to test rustfmt: could not build");
+            return;
+        }
+
         let mut cargo = tool::prepare_tool_cargo(builder,
                                                  compiler,
                                                  host,
index da89aa9423b2daa18cf9a9bc500fd63c717ecc64..3fed0175371a7d494ec1d1bdaf790a7e73b4588d 100755 (executable)
@@ -67,7 +67,7 @@ verify_status rust-by-example src/doc/rust-by-example
 verify_status rls src/tool/rls
 verify_status rustfmt src/tool/rustfmt
 verify_status clippy-driver src/tool/clippy
-#verify_status miri src/tool/miri
+verify_status miri src/tool/miri
 
 if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
     . "$(dirname $0)/repo.sh"
index bf97fb4686180f981f7c9e4983606f9910455f1b..7f110d6a3d22c20e4550047121fad058f565312e 100644 (file)
@@ -373,3 +373,19 @@ This is an internal flag intended for the standard library and compiler that app
 `#[unstable]` attribute to any dependent crate that doesn't have another stability attribute. This
 allows `rustdoc` to be able to generate documentation for the compiler crates and the standard
 library, as an equivalent command-line argument is provided to `rustc` when building those crates.
+
+### `doc_alias` feature
+
+This feature allows you to add alias(es) to an item when using the `rustdoc` search through the
+`doc(alias)` attribute. Example:
+
+```rust,no_run
+#![feature(doc_alias)]
+
+#[doc(alias = "x")]
+#[doc(alias = "big")]
+pub struct BigX;
+```
+
+Then, when looking for it through the `rustdoc` search, if you enter "x" or
+"big", search will show the `BigX` struct first.
diff --git a/src/doc/unstable-book/src/language-features/doc-alias.md b/src/doc/unstable-book/src/language-features/doc-alias.md
new file mode 100644 (file)
index 0000000..647ac0c
--- /dev/null
@@ -0,0 +1,23 @@
+# `doc_alias`
+
+The tracking issue for this feature is: [#50146]
+
+[#50146]: https://github.com/rust-lang/rust/issues/50146
+
+------------------------
+
+You can add alias(es) to an item when using the `rustdoc` search through the
+`doc(alias)` attribute. Example:
+
+```rust,no_run
+#![feature(doc_alias)]
+
+#[doc(alias = "x")]
+#[doc(alias = "big")]
+pub struct BigX;
+```
+
+Then, when looking for it through the `rustdoc` search, if you enter "x" or
+"big", search will show the `BigX` struct first.
+
+Note that this feature is currently hidden behind the `feature(doc_alias)` gate.
index 68a617e0ffed4371e21570a16d975e2c964fc02f..c0372d24ed50151f87e617c385a8d27a79e2f5bc 100644 (file)
@@ -48,9 +48,6 @@ fn __rust_realloc(ptr: *mut u8,
     #[allocator]
     #[rustc_allocator_nounwind]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
-    #[cold]
-    #[rustc_allocator_nounwind]
-    fn __rust_oom() -> !;
     #[rustc_allocator_nounwind]
     fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
     #[rustc_allocator_nounwind]
@@ -107,16 +104,6 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut Opaque {
         let ptr = __rust_alloc_zeroed(layout.size(), layout.align(), &mut 0);
         ptr as *mut Opaque
     }
-
-    #[inline]
-    fn oom(&self) -> ! {
-        unsafe {
-            #[cfg(not(stage0))]
-            __rust_oom();
-            #[cfg(stage0)]
-            __rust_oom(&mut 0);
-        }
-    }
 }
 
 unsafe impl Alloc for Global {
@@ -144,11 +131,6 @@ unsafe fn realloc(&mut self,
     unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        GlobalAlloc::oom(self)
-    }
 }
 
 /// The allocator for unique pointers.
@@ -165,7 +147,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
         if !ptr.is_null() {
             ptr as *mut u8
         } else {
-            Global.oom()
+            oom()
         }
     }
 }
@@ -182,19 +164,33 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
     }
 }
 
+#[cfg(stage0)]
+pub fn oom() -> ! {
+    unsafe { ::core::intrinsics::abort() }
+}
+
+#[cfg(not(stage0))]
+pub fn oom() -> ! {
+    extern {
+        #[lang = "oom"]
+        fn oom_impl() -> !;
+    }
+    unsafe { oom_impl() }
+}
+
 #[cfg(test)]
 mod tests {
     extern crate test;
     use self::test::Bencher;
     use boxed::Box;
-    use alloc::{Global, Alloc, Layout};
+    use alloc::{Global, Alloc, Layout, oom};
 
     #[test]
     fn allocate_zeroed() {
         unsafe {
             let layout = Layout::from_size_align(1024, 1).unwrap();
             let ptr = Global.alloc_zeroed(layout.clone())
-                .unwrap_or_else(|_| Global.oom());
+                .unwrap_or_else(|_| oom());
 
             let mut i = ptr.cast::<u8>().as_ptr();
             let end = i.offset(layout.size() as isize);
index 225b055d8ee8296129faae4ddacef105172a1186..f5980f4599e45ea8906263819e177dfe233eae41 100644 (file)
@@ -31,7 +31,7 @@
 use core::{isize, usize};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, box_free};
+use alloc::{Global, Alloc, Layout, box_free, oom};
 use boxed::Box;
 use string::String;
 use vec::Vec;
@@ -553,7 +553,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         // Initialize the real ArcInner
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
index faac38ca7ce15d5a35fe1e09f06f4b223b009fc7..16f0630b91134dd62965aa04d75663b98cc402f6 100644 (file)
@@ -59,7 +59,7 @@ unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
     }
 
     fn oom(&mut self, _: AllocErr) -> ! {
-        CoreAlloc::oom(self)
+        unsafe { ::core::intrinsics::abort() }
     }
 
     fn usable_size(&self, layout: &Layout) -> (usize, usize) {
index 163aef61b43628746a9e2f6f2dabf9f1062e3e44..6399be98cd5197f9d3d2eae08d30ae746c35c9ce 100644 (file)
@@ -75,7 +75,7 @@
 #![deny(missing_debug_implementations)]
 
 #![cfg_attr(test, allow(deprecated))] // rand
-#![cfg_attr(not(test), feature(core_float))]
+#![cfg_attr(all(not(test), stage0), feature(float_internals))]
 #![cfg_attr(not(test), feature(exact_size_is_empty))]
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(test, feature(rand, test))]
@@ -90,6 +90,8 @@
 #![feature(collections_range)]
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
+#![cfg_attr(stage0, feature(core_slice_ext))]
+#![cfg_attr(stage0, feature(core_str_ext))]
 #![feature(custom_attribute)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
index 24b7cd3db0cc67e27569fcc4bf821f808abee812..7ef0a27fc7258876768fb3abfaac3396e9ff8da4 100644 (file)
@@ -14,7 +14,7 @@
 use core::ptr::{self, NonNull, Unique};
 use core::slice;
 
-use alloc::{Alloc, Layout, Global};
+use alloc::{Alloc, Layout, Global, oom};
 use alloc::CollectionAllocErr;
 use alloc::CollectionAllocErr::*;
 use boxed::Box;
@@ -101,7 +101,7 @@ fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self {
                 };
                 match result {
                     Ok(ptr) => ptr,
-                    Err(_) => a.oom(),
+                    Err(_) => oom(),
                 }
             };
 
@@ -316,7 +316,7 @@ pub fn double(&mut self) {
                                                  new_size);
                     match ptr_res {
                         Ok(ptr) => (new_cap, ptr.cast().into()),
-                        Err(_) => self.a.oom(),
+                        Err(_) => oom(),
                     }
                 }
                 None => {
@@ -325,7 +325,7 @@ pub fn double(&mut self) {
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
                         Ok(ptr) => (new_cap, ptr.into()),
-                        Err(_) => self.a.oom(),
+                        Err(_) => oom(),
                     }
                 }
             };
@@ -442,7 +442,7 @@ pub fn try_reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize)
     pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve_exact(used_cap, needed_extra_cap) {
             Err(CapacityOverflow) => capacity_overflow(),
-            Err(AllocErr) => self.a.oom(),
+            Err(AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -552,7 +552,7 @@ pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize)
     pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
         match self.try_reserve(used_cap, needed_extra_cap) {
             Err(CapacityOverflow) => capacity_overflow(),
-            Err(AllocErr) => self.a.oom(),
+            Err(AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
      }
@@ -667,7 +667,7 @@ pub fn shrink_to_fit(&mut self, amount: usize) {
                                      old_layout,
                                      new_size) {
                     Ok(p) => self.ptr = p.cast().into(),
-                    Err(_) => self.a.oom(),
+                    Err(_) => oom(),
                 }
             }
             self.cap = amount;
index de0422d82bb76aaa77fce3a616e60e461b18a555..8fb8e111754a903e49819309c66c9004e0224e11 100644 (file)
 use core::ptr::{self, NonNull};
 use core::convert::From;
 
-use alloc::{Global, Alloc, Layout, Opaque, box_free};
+use alloc::{Global, Alloc, Layout, Opaque, box_free, oom};
 use string::String;
 use vec::Vec;
 
@@ -668,7 +668,7 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
         let layout = Layout::for_value(&*fake_ptr);
 
         let mem = Global.alloc(layout)
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         // Initialize the real RcBox
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
diff --git a/src/liballoc/repeat-generic-slice.rs b/src/liballoc/repeat-generic-slice.rs
new file mode 100644 (file)
index 0000000..5c14ee4
--- /dev/null
@@ -0,0 +1,19 @@
+// 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(repeat_generic_slice)]
+
+fn main() {
+    assert_eq!([1, 2].repeat(2), vec![1, 2, 1, 2]);
+    assert_eq!([1, 2, 3, 4].repeat(0), vec![]);
+    assert_eq!([1, 2, 3, 4].repeat(1), vec![1, 2, 3, 4]);
+    assert_eq!([1, 2, 3, 4].repeat(3),
+               vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]);
+}
index 33e652856e816f2122b9dc5db91856b940c5c7ee..d50a3458f20d1cee5043b226801193a4998872ac 100644 (file)
 use core::mem::size_of;
 use core::mem;
 use core::ptr;
-use core::slice as core_slice;
+#[cfg(stage0)] use core::slice::SliceExt;
 use core::{u8, u16, u32};
 
 use borrow::{Borrow, BorrowMut, ToOwned};
@@ -171,1059 +171,12 @@ pub fn to_vec<T>(s: &[T]) -> Vec<T>
     }
 }
 
-#[lang = "slice"]
+#[cfg_attr(stage0, lang = "slice")]
+#[cfg_attr(not(stage0), lang = "slice_alloc")]
 #[cfg(not(test))]
 impl<T> [T] {
-    /// Returns the number of elements in the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let a = [1, 2, 3];
-    /// assert_eq!(a.len(), 3);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn len(&self) -> usize {
-        core_slice::SliceExt::len(self)
-    }
-
-    /// Returns `true` if the slice has a length of 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let a = [1, 2, 3];
-    /// assert!(!a.is_empty());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        core_slice::SliceExt::is_empty(self)
-    }
-
-    /// Returns the first element of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&10), v.first());
-    ///
-    /// let w: &[i32] = &[];
-    /// assert_eq!(None, w.first());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn first(&self) -> Option<&T> {
-        core_slice::SliceExt::first(self)
-    }
-
-    /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some(first) = x.first_mut() {
-    ///     *first = 5;
-    /// }
-    /// assert_eq!(x, &[5, 1, 2]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn first_mut(&mut self) -> Option<&mut T> {
-        core_slice::SliceExt::first_mut(self)
-    }
-
-    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[0, 1, 2];
-    ///
-    /// if let Some((first, elements)) = x.split_first() {
-    ///     assert_eq!(first, &0);
-    ///     assert_eq!(elements, &[1, 2]);
-    /// }
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_first(&self) -> Option<(&T, &[T])> {
-        core_slice::SliceExt::split_first(self)
-    }
-
-    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some((first, elements)) = x.split_first_mut() {
-    ///     *first = 3;
-    ///     elements[0] = 4;
-    ///     elements[1] = 5;
-    /// }
-    /// assert_eq!(x, &[3, 4, 5]);
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        core_slice::SliceExt::split_first_mut(self)
-    }
-
-    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[0, 1, 2];
-    ///
-    /// if let Some((last, elements)) = x.split_last() {
-    ///     assert_eq!(last, &2);
-    ///     assert_eq!(elements, &[0, 1]);
-    /// }
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_last(&self) -> Option<(&T, &[T])> {
-        core_slice::SliceExt::split_last(self)
-
-    }
-
-    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some((last, elements)) = x.split_last_mut() {
-    ///     *last = 3;
-    ///     elements[0] = 4;
-    ///     elements[1] = 5;
-    /// }
-    /// assert_eq!(x, &[4, 5, 3]);
-    /// ```
-    #[stable(feature = "slice_splits", since = "1.5.0")]
-    #[inline]
-    pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
-        core_slice::SliceExt::split_last_mut(self)
-    }
-
-    /// Returns the last element of the slice, or `None` if it is empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&30), v.last());
-    ///
-    /// let w: &[i32] = &[];
-    /// assert_eq!(None, w.last());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn last(&self) -> Option<&T> {
-        core_slice::SliceExt::last(self)
-    }
-
-    /// Returns a mutable pointer to the last item in the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some(last) = x.last_mut() {
-    ///     *last = 10;
-    /// }
-    /// assert_eq!(x, &[0, 1, 10]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn last_mut(&mut self) -> Option<&mut T> {
-        core_slice::SliceExt::last_mut(self)
-    }
-
-    /// Returns a reference to an element or subslice depending on the type of
-    /// index.
-    ///
-    /// - If given a position, returns a reference to the element at that
-    ///   position or `None` if out of bounds.
-    /// - If given a range, returns the subslice corresponding to that range,
-    ///   or `None` if out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert_eq!(Some(&40), v.get(1));
-    /// assert_eq!(Some(&[10, 40][..]), v.get(0..2));
-    /// assert_eq!(None, v.get(3));
-    /// assert_eq!(None, v.get(0..4));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn get<I>(&self, index: I) -> Option<&I::Output>
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get(self, index)
-    }
-
-    /// Returns a mutable reference to an element or subslice depending on the
-    /// type of index (see [`get`]) or `None` if the index is out of bounds.
-    ///
-    /// [`get`]: #method.get
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [0, 1, 2];
-    ///
-    /// if let Some(elem) = x.get_mut(1) {
-    ///     *elem = 42;
-    /// }
-    /// assert_eq!(x, &[0, 42, 2]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get_mut(self, index)
-    }
-
-    /// Returns a reference to an element or subslice, without doing bounds
-    /// checking.
-    ///
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`get`].
-    ///
-    /// [`get`]: #method.get
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[1, 2, 4];
-    ///
-    /// unsafe {
-    ///     assert_eq!(x.get_unchecked(1), &2);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get_unchecked(self, index)
-    }
-
-    /// Returns a mutable reference to an element or subslice, without doing
-    /// bounds checking.
-    ///
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`get_mut`].
-    ///
-    /// [`get_mut`]: #method.get_mut
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [1, 2, 4];
-    ///
-    /// unsafe {
-    ///     let elem = x.get_unchecked_mut(1);
-    ///     *elem = 13;
-    /// }
-    /// assert_eq!(x, &[1, 13, 4]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
-        where I: SliceIndex<Self>
-    {
-        core_slice::SliceExt::get_unchecked_mut(self, index)
-    }
-
-    /// Returns a raw pointer to the slice's buffer.
-    ///
-    /// The caller must ensure that the slice outlives the pointer this
-    /// function returns, or else it will end up pointing to garbage.
-    ///
-    /// Modifying the container referenced by this slice may cause its buffer
-    /// to be reallocated, which would also make any pointers to it invalid.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[1, 2, 4];
-    /// let x_ptr = x.as_ptr();
-    ///
-    /// unsafe {
-    ///     for i in 0..x.len() {
-    ///         assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize));
-    ///     }
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_ptr(&self) -> *const T {
-        core_slice::SliceExt::as_ptr(self)
-    }
-
-    /// Returns an unsafe mutable pointer to the slice's buffer.
-    ///
-    /// The caller must ensure that the slice outlives the pointer this
-    /// function returns, or else it will end up pointing to garbage.
-    ///
-    /// Modifying the container referenced by this slice may cause its buffer
-    /// to be reallocated, which would also make any pointers to it invalid.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [1, 2, 4];
-    /// let x_ptr = x.as_mut_ptr();
-    ///
-    /// unsafe {
-    ///     for i in 0..x.len() {
-    ///         *x_ptr.offset(i as isize) += 2;
-    ///     }
-    /// }
-    /// assert_eq!(x, &[3, 4, 6]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_mut_ptr(&mut self) -> *mut T {
-        core_slice::SliceExt::as_mut_ptr(self)
-    }
-
-    /// Swaps two elements in the slice.
-    ///
-    /// # Arguments
-    ///
-    /// * a - The index of the first element
-    /// * b - The index of the second element
-    ///
-    /// # Panics
-    ///
-    /// Panics if `a` or `b` are out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = ["a", "b", "c", "d"];
-    /// v.swap(1, 3);
-    /// assert!(v == ["a", "d", "c", "b"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn swap(&mut self, a: usize, b: usize) {
-        core_slice::SliceExt::swap(self, a, b)
-    }
-
-    /// Reverses the order of elements in the slice, in place.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [1, 2, 3];
-    /// v.reverse();
-    /// assert!(v == [3, 2, 1]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn reverse(&mut self) {
-        core_slice::SliceExt::reverse(self)
-    }
-
-    /// Returns an iterator over the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &[1, 2, 4];
-    /// let mut iterator = x.iter();
-    ///
-    /// assert_eq!(iterator.next(), Some(&1));
-    /// assert_eq!(iterator.next(), Some(&2));
-    /// assert_eq!(iterator.next(), Some(&4));
-    /// assert_eq!(iterator.next(), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn iter(&self) -> Iter<T> {
-        core_slice::SliceExt::iter(self)
-    }
-
-    /// Returns an iterator that allows modifying each value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let x = &mut [1, 2, 4];
-    /// for elem in x.iter_mut() {
-    ///     *elem += 2;
-    /// }
-    /// assert_eq!(x, &[3, 4, 6]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn iter_mut(&mut self) -> IterMut<T> {
-        core_slice::SliceExt::iter_mut(self)
-    }
-
-    /// Returns an iterator over all contiguous windows of length
-    /// `size`. The windows overlap. If the slice is shorter than
-    /// `size`, the iterator returns no values.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let slice = ['r', 'u', 's', 't'];
-    /// let mut iter = slice.windows(2);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'u']);
-    /// assert_eq!(iter.next().unwrap(), &['u', 's']);
-    /// assert_eq!(iter.next().unwrap(), &['s', 't']);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// If the slice is shorter than `size`:
-    ///
-    /// ```
-    /// let slice = ['f', 'o', 'o'];
-    /// let mut iter = slice.windows(4);
-    /// assert!(iter.next().is_none());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn windows(&self, size: usize) -> Windows<T> {
-        core_slice::SliceExt::windows(self, size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a
-    /// time. The chunks are slices and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last chunk will
-    /// not have length `chunk_size`.
-    ///
-    /// See [`exact_chunks`] for a variant of this iterator that returns chunks
-    /// of always exactly `chunk_size` elements.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let slice = ['l', 'o', 'r', 'e', 'm'];
-    /// let mut iter = slice.chunks(2);
-    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
-    /// assert_eq!(iter.next().unwrap(), &['m']);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// [`exact_chunks`]: #method.exact_chunks
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
-        core_slice::SliceExt::chunks(self, chunk_size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a
-    /// time. The chunks are slices and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last up to `chunk_size-1`
-    /// elements will be omitted.
-    ///
-    /// Due to each chunk having exactly `chunk_size` elements, the compiler
-    /// can often optimize the resulting code better than in the case of
-    /// [`chunks`].
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(exact_chunks)]
-    ///
-    /// let slice = ['l', 'o', 'r', 'e', 'm'];
-    /// let mut iter = slice.exact_chunks(2);
-    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
-    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// [`chunks`]: #method.chunks
-    #[unstable(feature = "exact_chunks", issue = "47115")]
-    #[inline]
-    pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
-        core_slice::SliceExt::exact_chunks(self, chunk_size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a time.
-    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last chunk will not
-    /// have length `chunk_size`.
-    ///
-    /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
-    /// of always exactly `chunk_size` elements.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = &mut [0, 0, 0, 0, 0];
-    /// let mut count = 1;
-    ///
-    /// for chunk in v.chunks_mut(2) {
-    ///     for elem in chunk.iter_mut() {
-    ///         *elem += count;
-    ///     }
-    ///     count += 1;
-    /// }
-    /// assert_eq!(v, &[1, 1, 2, 2, 3]);
-    /// ```
-    ///
-    /// [`exact_chunks_mut`]: #method.exact_chunks_mut
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
-        core_slice::SliceExt::chunks_mut(self, chunk_size)
-    }
-
-    /// Returns an iterator over `chunk_size` elements of the slice at a time.
-    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
-    /// not divide the length of the slice, then the last up to `chunk_size-1`
-    /// elements will be omitted.
-    ///
-    ///
-    /// Due to each chunk having exactly `chunk_size` elements, the compiler
-    /// can often optimize the resulting code better than in the case of
-    /// [`chunks_mut`].
-    ///
-    /// # Panics
-    ///
-    /// Panics if `chunk_size` is 0.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(exact_chunks)]
-    ///
-    /// let v = &mut [0, 0, 0, 0, 0];
-    /// let mut count = 1;
-    ///
-    /// for chunk in v.exact_chunks_mut(2) {
-    ///     for elem in chunk.iter_mut() {
-    ///         *elem += count;
-    ///     }
-    ///     count += 1;
-    /// }
-    /// assert_eq!(v, &[1, 1, 2, 2, 0]);
-    /// ```
-    ///
-    /// [`chunks_mut`]: #method.chunks_mut
-    #[unstable(feature = "exact_chunks", issue = "47115")]
-    #[inline]
-    pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
-        core_slice::SliceExt::exact_chunks_mut(self, chunk_size)
-    }
-
-    /// Divides one slice into two at an index.
-    ///
-    /// The first will contain all indices from `[0, mid)` (excluding
-    /// the index `mid` itself) and the second will contain all
-    /// indices from `[mid, len)` (excluding the index `len` itself).
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid > len`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [1, 2, 3, 4, 5, 6];
-    ///
-    /// {
-    ///    let (left, right) = v.split_at(0);
-    ///    assert!(left == []);
-    ///    assert!(right == [1, 2, 3, 4, 5, 6]);
-    /// }
-    ///
-    /// {
-    ///     let (left, right) = v.split_at(2);
-    ///     assert!(left == [1, 2]);
-    ///     assert!(right == [3, 4, 5, 6]);
-    /// }
-    ///
-    /// {
-    ///     let (left, right) = v.split_at(6);
-    ///     assert!(left == [1, 2, 3, 4, 5, 6]);
-    ///     assert!(right == []);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
-        core_slice::SliceExt::split_at(self, mid)
-    }
-
-    /// Divides one mutable slice into two at an index.
-    ///
-    /// The first will contain all indices from `[0, mid)` (excluding
-    /// the index `mid` itself) and the second will contain all
-    /// indices from `[mid, len)` (excluding the index `len` itself).
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid > len`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [1, 0, 3, 0, 5, 6];
-    /// // scoped to restrict the lifetime of the borrows
-    /// {
-    ///     let (left, right) = v.split_at_mut(2);
-    ///     assert!(left == [1, 0]);
-    ///     assert!(right == [3, 0, 5, 6]);
-    ///     left[1] = 2;
-    ///     right[1] = 4;
-    /// }
-    /// assert!(v == [1, 2, 3, 4, 5, 6]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
-        core_slice::SliceExt::split_at_mut(self, mid)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`. The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let slice = [10, 40, 33, 20];
-    /// let mut iter = slice.split(|num| num % 3 == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
-    /// assert_eq!(iter.next().unwrap(), &[20]);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// If the first element is matched, an empty slice will be the first item
-    /// returned by the iterator. Similarly, if the last element in the slice
-    /// is matched, an empty slice will be the last item returned by the
-    /// iterator:
-    ///
-    /// ```
-    /// let slice = [10, 40, 33];
-    /// let mut iter = slice.split(|num| num % 3 == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
-    /// assert_eq!(iter.next().unwrap(), &[]);
-    /// assert!(iter.next().is_none());
-    /// ```
-    ///
-    /// If two matched elements are directly adjacent, an empty slice will be
-    /// present between them:
-    ///
-    /// ```
-    /// let slice = [10, 6, 33, 20];
-    /// let mut iter = slice.split(|num| num % 3 == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[10]);
-    /// assert_eq!(iter.next().unwrap(), &[]);
-    /// assert_eq!(iter.next().unwrap(), &[20]);
-    /// assert!(iter.next().is_none());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split<F>(&self, pred: F) -> Split<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::split(self, pred)
-    }
-
-    /// Returns an iterator over mutable subslices separated by elements that
-    /// match `pred`. The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.split_mut(|num| *num % 3 == 0) {
-    ///     group[0] = 1;
-    /// }
-    /// assert_eq!(v, [1, 40, 30, 1, 60, 1]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::split_mut(self, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, starting at the end of the slice and working backwards.
-    /// The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    ///
-    /// let slice = [11, 22, 33, 0, 44, 55];
-    /// let mut iter = slice.rsplit(|num| *num == 0);
-    ///
-    /// assert_eq!(iter.next().unwrap(), &[44, 55]);
-    /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
-    /// assert_eq!(iter.next(), None);
-    /// ```
-    ///
-    /// As with `split()`, if the first or last element is matched, an empty
-    /// slice will be the first (or last) item returned by the iterator.
-    ///
-    /// ```
-    /// let v = &[0, 1, 1, 2, 3, 5, 8];
-    /// let mut it = v.rsplit(|n| *n % 2 == 0);
-    /// assert_eq!(it.next().unwrap(), &[]);
-    /// assert_eq!(it.next().unwrap(), &[3, 5]);
-    /// assert_eq!(it.next().unwrap(), &[1, 1]);
-    /// assert_eq!(it.next().unwrap(), &[]);
-    /// assert_eq!(it.next(), None);
-    /// ```
-    #[stable(feature = "slice_rsplit", since = "1.27.0")]
-    #[inline]
-    pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplit(self, pred)
-    }
-
-    /// Returns an iterator over mutable subslices separated by elements that
-    /// match `pred`, starting at the end of the slice and working
-    /// backwards. The matched element is not contained in the subslices.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [100, 400, 300, 200, 600, 500];
-    ///
-    /// let mut count = 0;
-    /// for group in v.rsplit_mut(|num| *num % 3 == 0) {
-    ///     count += 1;
-    ///     group[0] = count;
-    /// }
-    /// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
-    /// ```
-    ///
-    #[stable(feature = "slice_rsplit", since = "1.27.0")]
-    #[inline]
-    pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplit_mut(self, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to returning at most `n` items. The matched element is
-    /// not contained in the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
-    /// `[20, 60, 50]`):
-    ///
-    /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.splitn(2, |num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::splitn(self, n, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to returning at most `n` items. The matched element is
-    /// not contained in the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.splitn_mut(2, |num| *num % 3 == 0) {
-    ///     group[0] = 1;
-    /// }
-    /// assert_eq!(v, [1, 40, 30, 1, 60, 50]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::splitn_mut(self, n, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to returning at most `n` items. This starts at the end of
-    /// the slice and works backwards.  The matched element is not contained in
-    /// the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// Print the slice split once, starting from the end, by numbers divisible
-    /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`):
-    ///
-    /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplitn(self, n, pred)
-    }
-
-    /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to returning at most `n` items. This starts at the end of
-    /// the slice and works backwards. The matched element is not contained in
-    /// the subslices.
-    ///
-    /// The last element returned, if any, will contain the remainder of the
-    /// slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut s = [10, 40, 30, 20, 60, 50];
-    ///
-    /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) {
-    ///     group[0] = 1;
-    /// }
-    /// assert_eq!(s, [1, 40, 30, 20, 60, 1]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F>
-        where F: FnMut(&T) -> bool
-    {
-        core_slice::SliceExt::rsplitn_mut(self, n, pred)
-    }
-
-    /// Returns `true` if the slice contains an element with the given value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.contains(&30));
-    /// assert!(!v.contains(&50));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn contains(&self, x: &T) -> bool
-        where T: PartialEq
-    {
-        core_slice::SliceExt::contains(self, x)
-    }
-
-    /// Returns `true` if `needle` is a prefix of the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.starts_with(&[10]));
-    /// assert!(v.starts_with(&[10, 40]));
-    /// assert!(!v.starts_with(&[50]));
-    /// assert!(!v.starts_with(&[10, 50]));
-    /// ```
-    ///
-    /// Always returns `true` if `needle` is an empty slice:
-    ///
-    /// ```
-    /// let v = &[10, 40, 30];
-    /// assert!(v.starts_with(&[]));
-    /// let v: &[u8] = &[];
-    /// assert!(v.starts_with(&[]));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn starts_with(&self, needle: &[T]) -> bool
-        where T: PartialEq
-    {
-        core_slice::SliceExt::starts_with(self, needle)
-    }
-
-    /// Returns `true` if `needle` is a suffix of the slice.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = [10, 40, 30];
-    /// assert!(v.ends_with(&[30]));
-    /// assert!(v.ends_with(&[40, 30]));
-    /// assert!(!v.ends_with(&[50]));
-    /// assert!(!v.ends_with(&[50, 30]));
-    /// ```
-    ///
-    /// Always returns `true` if `needle` is an empty slice:
-    ///
-    /// ```
-    /// let v = &[10, 40, 30];
-    /// assert!(v.ends_with(&[]));
-    /// let v: &[u8] = &[];
-    /// assert!(v.ends_with(&[]));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn ends_with(&self, needle: &[T]) -> bool
-        where T: PartialEq
-    {
-        core_slice::SliceExt::ends_with(self, needle)
-    }
-
-    /// Binary searches this sorted slice for a given element.
-    ///
-    /// If the value is found then `Ok` is returned, containing the
-    /// index of the matching element; if the value is not found then
-    /// `Err` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
-    ///
-    /// # Examples
-    ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1, 4]`.
-    ///
-    /// ```
-    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    ///
-    /// assert_eq!(s.binary_search(&13),  Ok(9));
-    /// assert_eq!(s.binary_search(&4),   Err(7));
-    /// assert_eq!(s.binary_search(&100), Err(13));
-    /// let r = s.binary_search(&1);
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn binary_search(&self, x: &T) -> Result<usize, usize>
-        where T: Ord
-    {
-        core_slice::SliceExt::binary_search(self, x)
-    }
-
-    /// Binary searches this sorted slice with a comparator function.
-    ///
-    /// The comparator function should implement an order consistent
-    /// with the sort order of the underlying slice, returning an
-    /// order code that indicates whether its argument is `Less`,
-    /// `Equal` or `Greater` the desired target.
-    ///
-    /// If a matching value is found then returns `Ok`, containing
-    /// the index for the matched element; if no match is found then
-    /// `Err` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
-    ///
-    /// # Examples
-    ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1, 4]`.
-    ///
-    /// ```
-    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    ///
-    /// let seek = 13;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
-    /// let seek = 4;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
-    /// let seek = 100;
-    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
-    /// let seek = 1;
-    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
-        where F: FnMut(&'a T) -> Ordering
-    {
-        core_slice::SliceExt::binary_search_by(self, f)
-    }
-
-    /// Binary searches this sorted slice with a key extraction function.
-    ///
-    /// Assumes that the slice is sorted by the key, for instance with
-    /// [`sort_by_key`] using the same key extraction function.
-    ///
-    /// If a matching value is found then returns `Ok`, containing the
-    /// index for the matched element; if no match is found then `Err`
-    /// is returned, containing the index where a matching element could
-    /// be inserted while maintaining sorted order.
-    ///
-    /// [`sort_by_key`]: #method.sort_by_key
-    ///
-    /// # Examples
-    ///
-    /// Looks up a series of four elements in a slice of pairs sorted by
-    /// their second elements. The first is found, with a uniquely
-    /// determined position; the second and third are not found; the
-    /// fourth could match any position in `[1, 4]`.
-    ///
-    /// ```
-    /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
-    ///          (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
-    ///          (1, 21), (2, 34), (4, 55)];
-    ///
-    /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
-    /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
-    /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
-    /// let r = s.binary_search_by_key(&1, |&(a,b)| b);
-    /// assert!(match r { Ok(1...4) => true, _ => false, });
-    /// ```
-    #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
-    #[inline]
-    pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
-        where F: FnMut(&'a T) -> B,
-              B: Ord
-    {
-        core_slice::SliceExt::binary_search_by_key(self, b, f)
-    }
+    #[cfg(stage0)]
+    slice_core_methods!();
 
     /// Sorts the slice.
     ///
@@ -1402,345 +355,6 @@ macro_rules! sort_by_key {
         sort_by_key!(usize, self, f)
     }
 
-    /// Sorts the slice, but may not preserve the order of equal elements.
-    ///
-    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
-    /// and `O(n log n)` worst-case.
-    ///
-    /// # Current implementation
-    ///
-    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
-    /// which combines the fast average case of randomized quicksort with the fast worst case of
-    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
-    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
-    /// deterministic behavior.
-    ///
-    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
-    /// slice consists of several concatenated sorted sequences.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [-5, 4, 1, -3, 2];
-    ///
-    /// v.sort_unstable();
-    /// assert!(v == [-5, -3, 1, 2, 4]);
-    /// ```
-    ///
-    /// [pdqsort]: https://github.com/orlp/pdqsort
-    #[stable(feature = "sort_unstable", since = "1.20.0")]
-    #[inline]
-    pub fn sort_unstable(&mut self)
-        where T: Ord
-    {
-        core_slice::SliceExt::sort_unstable(self);
-    }
-
-    /// Sorts the slice with a comparator function, but may not preserve the order of equal
-    /// elements.
-    ///
-    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
-    /// and `O(n log n)` worst-case.
-    ///
-    /// # Current implementation
-    ///
-    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
-    /// which combines the fast average case of randomized quicksort with the fast worst case of
-    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
-    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
-    /// deterministic behavior.
-    ///
-    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
-    /// slice consists of several concatenated sorted sequences.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [5, 4, 1, 3, 2];
-    /// v.sort_unstable_by(|a, b| a.cmp(b));
-    /// assert!(v == [1, 2, 3, 4, 5]);
-    ///
-    /// // reverse sorting
-    /// v.sort_unstable_by(|a, b| b.cmp(a));
-    /// assert!(v == [5, 4, 3, 2, 1]);
-    /// ```
-    ///
-    /// [pdqsort]: https://github.com/orlp/pdqsort
-    #[stable(feature = "sort_unstable", since = "1.20.0")]
-    #[inline]
-    pub fn sort_unstable_by<F>(&mut self, compare: F)
-        where F: FnMut(&T, &T) -> Ordering
-    {
-        core_slice::SliceExt::sort_unstable_by(self, compare);
-    }
-
-    /// Sorts the slice with a key extraction function, but may not preserve the order of equal
-    /// elements.
-    ///
-    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
-    /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`.
-    ///
-    /// # Current implementation
-    ///
-    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
-    /// which combines the fast average case of randomized quicksort with the fast worst case of
-    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
-    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
-    /// deterministic behavior.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = [-5i32, 4, 1, -3, 2];
-    ///
-    /// v.sort_unstable_by_key(|k| k.abs());
-    /// assert!(v == [1, 2, -3, 4, -5]);
-    /// ```
-    ///
-    /// [pdqsort]: https://github.com/orlp/pdqsort
-    #[stable(feature = "sort_unstable", since = "1.20.0")]
-    #[inline]
-    pub fn sort_unstable_by_key<K, F>(&mut self, f: F)
-        where F: FnMut(&T) -> K, K: Ord
-    {
-        core_slice::SliceExt::sort_unstable_by_key(self, f);
-    }
-
-    /// Rotates the slice in-place such that the first `mid` elements of the
-    /// slice move to the end while the last `self.len() - mid` elements move to
-    /// the front. After calling `rotate_left`, the element previously at index
-    /// `mid` will become the first element in the slice.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `mid` is greater than the length of the
-    /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op
-    /// rotation.
-    ///
-    /// # Complexity
-    ///
-    /// Takes linear (in `self.len()`) time.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a.rotate_left(2);
-    /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
-    /// ```
-    ///
-    /// Rotating a subslice:
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a[1..5].rotate_left(1);
-    /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
-   /// ```
-    #[stable(feature = "slice_rotate", since = "1.26.0")]
-    pub fn rotate_left(&mut self, mid: usize) {
-        core_slice::SliceExt::rotate_left(self, mid);
-    }
-
-    /// Rotates the slice in-place such that the first `self.len() - k`
-    /// elements of the slice move to the end while the last `k` elements move
-    /// to the front. After calling `rotate_right`, the element previously at
-    /// index `self.len() - k` will become the first element in the slice.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `k` is greater than the length of the
-    /// slice. Note that `k == self.len()` does _not_ panic and is a no-op
-    /// rotation.
-    ///
-    /// # Complexity
-    ///
-    /// Takes linear (in `self.len()`) time.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a.rotate_right(2);
-    /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
-    /// ```
-    ///
-    /// Rotate a subslice:
-    ///
-    /// ```
-    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
-    /// a[1..5].rotate_right(1);
-    /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
-    /// ```
-    #[stable(feature = "slice_rotate", since = "1.26.0")]
-    pub fn rotate_right(&mut self, k: usize) {
-        core_slice::SliceExt::rotate_right(self, k);
-    }
-
-    /// Copies the elements from `src` into `self`.
-    ///
-    /// The length of `src` must be the same as `self`.
-    ///
-    /// If `src` implements `Copy`, it can be more performant to use
-    /// [`copy_from_slice`].
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths.
-    ///
-    /// # Examples
-    ///
-    /// Cloning two elements from a slice into another:
-    ///
-    /// ```
-    /// let src = [1, 2, 3, 4];
-    /// let mut dst = [0, 0];
-    ///
-    /// dst.clone_from_slice(&src[2..]);
-    ///
-    /// assert_eq!(src, [1, 2, 3, 4]);
-    /// assert_eq!(dst, [3, 4]);
-    /// ```
-    ///
-    /// Rust enforces that there can only be one mutable reference with no
-    /// immutable references to a particular piece of data in a particular
-    /// scope. Because of this, attempting to use `clone_from_slice` on a
-    /// single slice will result in a compile failure:
-    ///
-    /// ```compile_fail
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// slice[..2].clone_from_slice(&slice[3..]); // compile fail!
-    /// ```
-    ///
-    /// To work around this, we can use [`split_at_mut`] to create two distinct
-    /// sub-slices from a slice:
-    ///
-    /// ```
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// {
-    ///     let (left, right) = slice.split_at_mut(2);
-    ///     left.clone_from_slice(&right[1..]);
-    /// }
-    ///
-    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
-    /// ```
-    ///
-    /// [`copy_from_slice`]: #method.copy_from_slice
-    /// [`split_at_mut`]: #method.split_at_mut
-    #[stable(feature = "clone_from_slice", since = "1.7.0")]
-    pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
-        core_slice::SliceExt::clone_from_slice(self, src)
-    }
-
-    /// Copies all elements from `src` into `self`, using a memcpy.
-    ///
-    /// The length of `src` must be the same as `self`.
-    ///
-    /// If `src` does not implement `Copy`, use [`clone_from_slice`].
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths.
-    ///
-    /// # Examples
-    ///
-    /// Copying two elements from a slice into another:
-    ///
-    /// ```
-    /// let src = [1, 2, 3, 4];
-    /// let mut dst = [0, 0];
-    ///
-    /// dst.copy_from_slice(&src[2..]);
-    ///
-    /// assert_eq!(src, [1, 2, 3, 4]);
-    /// assert_eq!(dst, [3, 4]);
-    /// ```
-    ///
-    /// Rust enforces that there can only be one mutable reference with no
-    /// immutable references to a particular piece of data in a particular
-    /// scope. Because of this, attempting to use `copy_from_slice` on a
-    /// single slice will result in a compile failure:
-    ///
-    /// ```compile_fail
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// slice[..2].copy_from_slice(&slice[3..]); // compile fail!
-    /// ```
-    ///
-    /// To work around this, we can use [`split_at_mut`] to create two distinct
-    /// sub-slices from a slice:
-    ///
-    /// ```
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// {
-    ///     let (left, right) = slice.split_at_mut(2);
-    ///     left.copy_from_slice(&right[1..]);
-    /// }
-    ///
-    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
-    /// ```
-    ///
-    /// [`clone_from_slice`]: #method.clone_from_slice
-    /// [`split_at_mut`]: #method.split_at_mut
-    #[stable(feature = "copy_from_slice", since = "1.9.0")]
-    pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
-        core_slice::SliceExt::copy_from_slice(self, src)
-    }
-
-    /// Swaps all elements in `self` with those in `other`.
-    ///
-    /// The length of `other` must be the same as `self`.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the two slices have different lengths.
-    ///
-    /// # Example
-    ///
-    /// Swapping two elements across slices:
-    ///
-    /// ```
-    /// let mut slice1 = [0, 0];
-    /// let mut slice2 = [1, 2, 3, 4];
-    ///
-    /// slice1.swap_with_slice(&mut slice2[2..]);
-    ///
-    /// assert_eq!(slice1, [3, 4]);
-    /// assert_eq!(slice2, [1, 2, 0, 0]);
-    /// ```
-    ///
-    /// Rust enforces that there can only be one mutable reference to a
-    /// particular piece of data in a particular scope. Because of this,
-    /// attempting to use `swap_with_slice` on a single slice will result in
-    /// a compile failure:
-    ///
-    /// ```compile_fail
-    /// let mut slice = [1, 2, 3, 4, 5];
-    /// slice[..2].swap_with_slice(&mut slice[3..]); // compile fail!
-    /// ```
-    ///
-    /// To work around this, we can use [`split_at_mut`] to create two distinct
-    /// mutable sub-slices from a slice:
-    ///
-    /// ```
-    /// let mut slice = [1, 2, 3, 4, 5];
-    ///
-    /// {
-    ///     let (left, right) = slice.split_at_mut(2);
-    ///     left.swap_with_slice(&mut right[1..]);
-    /// }
-    ///
-    /// assert_eq!(slice, [4, 5, 3, 1, 2]);
-    /// ```
-    ///
-    /// [`split_at_mut`]: #method.split_at_mut
-    #[stable(feature = "swap_with_slice", since = "1.27.0")]
-    pub fn swap_with_slice(&mut self, other: &mut [T]) {
-        core_slice::SliceExt::swap_with_slice(self, other)
-    }
-
     /// Copies `self` into a new `Vec`.
     ///
     /// # Examples
@@ -1780,18 +394,83 @@ pub fn into_vec(self: Box<Self>) -> Vec<T> {
         // NB see hack module in this file
         hack::into_vec(self)
     }
+
+    /// Creates a vector by repeating a slice `n` times.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(repeat_generic_slice)]
+    ///
+    /// fn main() {
+    ///     assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]);
+    /// }
+    /// ```
+    #[unstable(feature = "repeat_generic_slice",
+               reason = "it's on str, why not on slice?",
+               issue = "48784")]
+    pub fn repeat(&self, n: usize) -> Vec<T> where T: Copy {
+        if n == 0 {
+            return Vec::new();
+        }
+
+        // If `n` is larger than zero, it can be split as
+        // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
+        // `2^expn` is the number represented by the leftmost '1' bit of `n`,
+        // and `rem` is the remaining part of `n`.
+
+        // Using `Vec` to access `set_len()`.
+        let mut buf = Vec::with_capacity(self.len() * n);
+
+        // `2^expn` repetition is done by doubling `buf` `expn`-times.
+        buf.extend(self);
+        {
+            let mut m = n >> 1;
+            // If `m > 0`, there are remaining bits up to the leftmost '1'.
+            while m > 0 {
+                // `buf.extend(buf)`:
+                unsafe {
+                    ptr::copy_nonoverlapping(
+                        buf.as_ptr(),
+                        (buf.as_mut_ptr() as *mut T).add(buf.len()),
+                        buf.len(),
+                    );
+                    // `buf` has capacity of `self.len() * n`.
+                    let buf_len = buf.len();
+                    buf.set_len(buf_len * 2);
+                }
+
+                m >>= 1;
+            }
+        }
+
+        // `rem` (`= n - 2^expn`) repetition is done by copying
+        // first `rem` repetitions from `buf` itself.
+        let rem_len = self.len() * n - buf.len(); // `self.len() * rem`
+        if rem_len > 0 {
+            // `buf.extend(buf[0 .. rem_len])`:
+            unsafe {
+                // This is non-overlapping since `2^expn > rem`.
+                ptr::copy_nonoverlapping(
+                    buf.as_ptr(),
+                    (buf.as_mut_ptr() as *mut T).add(buf.len()),
+                    rem_len,
+                );
+                // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
+                let buf_cap = buf.capacity();
+                buf.set_len(buf_cap);
+            }
+        }
+        buf
+    }
 }
 
-#[lang = "slice_u8"]
+#[cfg_attr(stage0, lang = "slice_u8")]
+#[cfg_attr(not(stage0), lang = "slice_u8_alloc")]
 #[cfg(not(test))]
 impl [u8] {
-    /// Checks if all bytes in this slice are within the ASCII range.
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn is_ascii(&self) -> bool {
-        self.iter().all(|b| b.is_ascii())
-    }
-
     /// Returns a vector containing a copy of this slice where each byte
     /// is mapped to its ASCII upper case equivalent.
     ///
@@ -1826,52 +505,8 @@ pub fn to_ascii_lowercase(&self) -> Vec<u8> {
         me
     }
 
-    /// Checks that two slices are an ASCII case-insensitive match.
-    ///
-    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
-    /// but without allocating and copying temporaries.
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
-        self.len() == other.len() &&
-            self.iter().zip(other).all(|(a, b)| {
-                a.eq_ignore_ascii_case(b)
-            })
-    }
-
-    /// Converts this slice to its ASCII upper case equivalent in-place.
-    ///
-    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new uppercased value without modifying the existing one, use
-    /// [`to_ascii_uppercase`].
-    ///
-    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn make_ascii_uppercase(&mut self) {
-        for byte in self {
-            byte.make_ascii_uppercase();
-        }
-    }
-
-    /// Converts this slice to its ASCII lower case equivalent in-place.
-    ///
-    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new lowercased value without modifying the existing one, use
-    /// [`to_ascii_lowercase`].
-    ///
-    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn make_ascii_lowercase(&mut self) {
-        for byte in self {
-            byte.make_ascii_lowercase();
-        }
-    }
+    #[cfg(stage0)]
+    slice_u8_core_methods!();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index 686a0408a7cf9de2003d1f2340b804d99f3afb1f..cac94edf6494783e4c64a96230f2adcab71a9ca9 100644 (file)
@@ -40,6 +40,7 @@
 
 use core::fmt;
 use core::str as core_str;
+#[cfg(stage0)] use core::str::StrExt;
 use core::str::pattern::Pattern;
 use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 use core::mem;
@@ -76,7 +77,8 @@
 pub use core::str::SplitWhitespace;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::pattern;
-
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+pub use core::str::EncodeUtf16;
 
 #[unstable(feature = "slice_concat_ext",
            reason = "trait should not have to exist",
@@ -86,1733 +88,82 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
 
     fn concat(&self) -> String {
         if self.is_empty() {
-            return String::new();
-        }
-
-        // `len` calculation may overflow but push_str will check boundaries
-        let len = self.iter().map(|s| s.borrow().len()).sum();
-        let mut result = String::with_capacity(len);
-
-        for s in self {
-            result.push_str(s.borrow())
-        }
-
-        result
-    }
-
-    fn join(&self, sep: &str) -> String {
-        if self.is_empty() {
-            return String::new();
-        }
-
-        // concat is faster
-        if sep.is_empty() {
-            return self.concat();
-        }
-
-        // this is wrong without the guarantee that `self` is non-empty
-        // `len` calculation may overflow but push_str but will check boundaries
-        let len = sep.len() * (self.len() - 1) +
-                  self.iter().map(|s| s.borrow().len()).sum::<usize>();
-        let mut result = String::with_capacity(len);
-        let mut first = true;
-
-        for s in self {
-            if first {
-                first = false;
-            } else {
-                result.push_str(sep);
-            }
-            result.push_str(s.borrow());
-        }
-        result
-    }
-
-    fn connect(&self, sep: &str) -> String {
-        self.join(sep)
-    }
-}
-
-/// An iterator of [`u16`] over the string encoded as UTF-16.
-///
-/// [`u16`]: ../../std/primitive.u16.html
-///
-/// This struct is created by the [`encode_utf16`] method on [`str`].
-/// See its documentation for more.
-///
-/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16
-/// [`str`]: ../../std/primitive.str.html
-#[derive(Clone)]
-#[stable(feature = "encode_utf16", since = "1.8.0")]
-pub struct EncodeUtf16<'a> {
-    chars: Chars<'a>,
-    extra: u16,
-}
-
-#[stable(feature = "collection_debug", since = "1.17.0")]
-impl<'a> fmt::Debug for EncodeUtf16<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("EncodeUtf16 { .. }")
-    }
-}
-
-#[stable(feature = "encode_utf16", since = "1.8.0")]
-impl<'a> Iterator for EncodeUtf16<'a> {
-    type Item = u16;
-
-    #[inline]
-    fn next(&mut self) -> Option<u16> {
-        if self.extra != 0 {
-            let tmp = self.extra;
-            self.extra = 0;
-            return Some(tmp);
-        }
-
-        let mut buf = [0; 2];
-        self.chars.next().map(|ch| {
-            let n = ch.encode_utf16(&mut buf).len();
-            if n == 2 {
-                self.extra = buf[1];
-            }
-            buf[0]
-        })
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (low, high) = self.chars.size_hint();
-        // every char gets either one u16 or two u16,
-        // so this iterator is between 1 or 2 times as
-        // long as the underlying iterator.
-        (low, high.and_then(|n| n.checked_mul(2)))
-    }
-}
-
-#[stable(feature = "fused", since = "1.26.0")]
-impl<'a> FusedIterator for EncodeUtf16<'a> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Borrow<str> for String {
-    #[inline]
-    fn borrow(&self) -> &str {
-        &self[..]
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl ToOwned for str {
-    type Owned = String;
-    fn to_owned(&self) -> String {
-        unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
-    }
-
-    fn clone_into(&self, target: &mut String) {
-        let mut b = mem::replace(target, String::new()).into_bytes();
-        self.as_bytes().clone_into(&mut b);
-        *target = unsafe { String::from_utf8_unchecked(b) }
-    }
-}
-
-/// Methods for string slices.
-#[lang = "str"]
-#[cfg(not(test))]
-impl str {
-    /// Returns the length of `self`.
-    ///
-    /// This length is in bytes, not [`char`]s or graphemes. In other words,
-    /// it may not be what a human considers the length of the string.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let len = "foo".len();
-    /// assert_eq!(3, len);
-    ///
-    /// let len = "ƒoo".len(); // fancy f!
-    /// assert_eq!(4, len);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn len(&self) -> usize {
-        core_str::StrExt::len(self)
-    }
-
-    /// Returns `true` if `self` has a length of zero bytes.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "";
-    /// assert!(s.is_empty());
-    ///
-    /// let s = "not empty";
-    /// assert!(!s.is_empty());
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool {
-        core_str::StrExt::is_empty(self)
-    }
-
-    /// Checks that `index`-th byte lies at the start and/or end of a
-    /// UTF-8 code point sequence.
-    ///
-    /// The start and end of the string (when `index == self.len()`) are
-    /// considered to be
-    /// boundaries.
-    ///
-    /// Returns `false` if `index` is greater than `self.len()`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// assert!(s.is_char_boundary(0));
-    /// // start of `老`
-    /// assert!(s.is_char_boundary(6));
-    /// assert!(s.is_char_boundary(s.len()));
-    ///
-    /// // second byte of `ö`
-    /// assert!(!s.is_char_boundary(2));
-    ///
-    /// // third byte of `老`
-    /// assert!(!s.is_char_boundary(8));
-    /// ```
-    #[stable(feature = "is_char_boundary", since = "1.9.0")]
-    #[inline]
-    pub fn is_char_boundary(&self, index: usize) -> bool {
-        core_str::StrExt::is_char_boundary(self, index)
-    }
-
-    /// Converts a string slice to a byte slice. To convert the byte slice back
-    /// into a string slice, use the [`str::from_utf8`] function.
-    ///
-    /// [`str::from_utf8`]: ./str/fn.from_utf8.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bytes = "bors".as_bytes();
-    /// assert_eq!(b"bors", bytes);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline(always)]
-    pub fn as_bytes(&self) -> &[u8] {
-        core_str::StrExt::as_bytes(self)
-    }
-
-    /// Converts a mutable string slice to a mutable byte slice. To convert the
-    /// mutable byte slice back into a mutable string slice, use the
-    /// [`str::from_utf8_mut`] function.
-    ///
-    /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut s = String::from("Hello");
-    /// let bytes = unsafe { s.as_bytes_mut() };
-    ///
-    /// assert_eq!(b"Hello", bytes);
-    /// ```
-    ///
-    /// Mutability:
-    ///
-    /// ```
-    /// let mut s = String::from("🗻∈🌏");
-    ///
-    /// unsafe {
-    ///     let bytes = s.as_bytes_mut();
-    ///
-    ///     bytes[0] = 0xF0;
-    ///     bytes[1] = 0x9F;
-    ///     bytes[2] = 0x8D;
-    ///     bytes[3] = 0x94;
-    /// }
-    ///
-    /// assert_eq!("🍔∈🌏", s);
-    /// ```
-    #[stable(feature = "str_mut_extras", since = "1.20.0")]
-    #[inline(always)]
-    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
-        core_str::StrExt::as_bytes_mut(self)
-    }
-
-    /// Converts a string slice to a raw pointer.
-    ///
-    /// As string slices are a slice of bytes, the raw pointer points to a
-    /// [`u8`]. This pointer will be pointing to the first byte of the string
-    /// slice.
-    ///
-    /// [`u8`]: primitive.u8.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "Hello";
-    /// let ptr = s.as_ptr();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn as_ptr(&self) -> *const u8 {
-        core_str::StrExt::as_ptr(self)
-    }
-
-    /// Returns a subslice of `str`.
-    ///
-    /// This is the non-panicking alternative to indexing the `str`. Returns
-    /// [`None`] whenever equivalent indexing operation would panic.
-    ///
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = String::from("🗻∈🌏");
-    ///
-    /// assert_eq!(Some("🗻"), v.get(0..4));
-    ///
-    /// // indices not on UTF-8 sequence boundaries
-    /// assert!(v.get(1..).is_none());
-    /// assert!(v.get(..8).is_none());
-    ///
-    /// // out of bounds
-    /// assert!(v.get(..42).is_none());
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
-        core_str::StrExt::get(self, i)
-    }
-
-    /// Returns a mutable subslice of `str`.
-    ///
-    /// This is the non-panicking alternative to indexing the `str`. Returns
-    /// [`None`] whenever equivalent indexing operation would panic.
-    ///
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = String::from("hello");
-    /// // correct length
-    /// assert!(v.get_mut(0..5).is_some());
-    /// // out of bounds
-    /// assert!(v.get_mut(..42).is_none());
-    /// assert_eq!(Some("he"), v.get_mut(0..2).map(|v| &*v));
-    ///
-    /// assert_eq!("hello", v);
-    /// {
-    ///     let s = v.get_mut(0..2);
-    ///     let s = s.map(|s| {
-    ///         s.make_ascii_uppercase();
-    ///         &*s
-    ///     });
-    ///     assert_eq!(Some("HE"), s);
-    /// }
-    /// assert_eq!("HEllo", v);
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
-        core_str::StrExt::get_mut(self, i)
-    }
-
-    /// Returns a unchecked subslice of `str`.
-    ///
-    /// This is the unchecked alternative to indexing the `str`.
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that these preconditions are
-    /// satisfied:
-    ///
-    /// * The starting index must come before the ending index;
-    /// * Indexes must be within bounds of the original slice;
-    /// * Indexes must lie on UTF-8 sequence boundaries.
-    ///
-    /// Failing that, the returned string slice may reference invalid memory or
-    /// violate the invariants communicated by the `str` type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = "🗻∈🌏";
-    /// unsafe {
-    ///     assert_eq!("🗻", v.get_unchecked(0..4));
-    ///     assert_eq!("∈", v.get_unchecked(4..7));
-    ///     assert_eq!("🌏", v.get_unchecked(7..11));
-    /// }
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
-        core_str::StrExt::get_unchecked(self, i)
-    }
-
-    /// Returns a mutable, unchecked subslice of `str`.
-    ///
-    /// This is the unchecked alternative to indexing the `str`.
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that these preconditions are
-    /// satisfied:
-    ///
-    /// * The starting index must come before the ending index;
-    /// * Indexes must be within bounds of the original slice;
-    /// * Indexes must lie on UTF-8 sequence boundaries.
-    ///
-    /// Failing that, the returned string slice may reference invalid memory or
-    /// violate the invariants communicated by the `str` type.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut v = String::from("🗻∈🌏");
-    /// unsafe {
-    ///     assert_eq!("🗻", v.get_unchecked_mut(0..4));
-    ///     assert_eq!("∈", v.get_unchecked_mut(4..7));
-    ///     assert_eq!("🌏", v.get_unchecked_mut(7..11));
-    /// }
-    /// ```
-    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
-    #[inline]
-    pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
-        core_str::StrExt::get_unchecked_mut(self, i)
-    }
-
-    /// Creates a string slice from another string slice, bypassing safety
-    /// checks.
-    ///
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`str`] and [`Index`].
-    ///
-    /// [`str`]: primitive.str.html
-    /// [`Index`]: ops/trait.Index.html
-    ///
-    /// This new slice goes from `begin` to `end`, including `begin` but
-    /// excluding `end`.
-    ///
-    /// To get a mutable string slice instead, see the
-    /// [`slice_mut_unchecked`] method.
-    ///
-    /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that three preconditions are
-    /// satisfied:
-    ///
-    /// * `begin` must come before `end`.
-    /// * `begin` and `end` must be byte positions within the string slice.
-    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// unsafe {
-    ///     assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21));
-    /// }
-    ///
-    /// let s = "Hello, world!";
-    ///
-    /// unsafe {
-    ///     assert_eq!("world", s.slice_unchecked(7, 12));
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
-        core_str::StrExt::slice_unchecked(self, begin, end)
-    }
-
-    /// Creates a string slice from another string slice, bypassing safety
-    /// checks.
-    /// This is generally not recommended, use with caution! For a safe
-    /// alternative see [`str`] and [`IndexMut`].
-    ///
-    /// [`str`]: primitive.str.html
-    /// [`IndexMut`]: ops/trait.IndexMut.html
-    ///
-    /// This new slice goes from `begin` to `end`, including `begin` but
-    /// excluding `end`.
-    ///
-    /// To get an immutable string slice instead, see the
-    /// [`slice_unchecked`] method.
-    ///
-    /// [`slice_unchecked`]: #method.slice_unchecked
-    ///
-    /// # Safety
-    ///
-    /// Callers of this function are responsible that three preconditions are
-    /// satisfied:
-    ///
-    /// * `begin` must come before `end`.
-    /// * `begin` and `end` must be byte positions within the string slice.
-    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
-    #[stable(feature = "str_slice_mut", since = "1.5.0")]
-    #[inline]
-    pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
-        core_str::StrExt::slice_mut_unchecked(self, begin, end)
-    }
-
-    /// Divide one string slice into two at an index.
-    ///
-    /// The argument, `mid`, should be a byte offset from the start of the
-    /// string. It must also be on the boundary of a UTF-8 code point.
-    ///
-    /// The two slices returned go from the start of the string slice to `mid`,
-    /// and from `mid` to the end of the string slice.
-    ///
-    /// To get mutable string slices instead, see the [`split_at_mut`]
-    /// method.
-    ///
-    /// [`split_at_mut`]: #method.split_at_mut
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = "Per Martin-Löf";
-    ///
-    /// let (first, last) = s.split_at(3);
-    ///
-    /// assert_eq!("Per", first);
-    /// assert_eq!(" Martin-Löf", last);
-    /// ```
-    #[inline]
-    #[stable(feature = "str_split_at", since = "1.4.0")]
-    pub fn split_at(&self, mid: usize) -> (&str, &str) {
-        core_str::StrExt::split_at(self, mid)
-    }
-
-    /// Divide one mutable string slice into two at an index.
-    ///
-    /// The argument, `mid`, should be a byte offset from the start of the
-    /// string. It must also be on the boundary of a UTF-8 code point.
-    ///
-    /// The two slices returned go from the start of the string slice to `mid`,
-    /// and from `mid` to the end of the string slice.
-    ///
-    /// To get immutable string slices instead, see the [`split_at`] method.
-    ///
-    /// [`split_at`]: #method.split_at
-    ///
-    /// # Panics
-    ///
-    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
-    /// beyond the last code point of the string slice.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut s = "Per Martin-Löf".to_string();
-    /// {
-    ///     let (first, last) = s.split_at_mut(3);
-    ///     first.make_ascii_uppercase();
-    ///     assert_eq!("PER", first);
-    ///     assert_eq!(" Martin-Löf", last);
-    /// }
-    /// assert_eq!("PER Martin-Löf", s);
-    /// ```
-    #[inline]
-    #[stable(feature = "str_split_at", since = "1.4.0")]
-    pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
-        core_str::StrExt::split_at_mut(self, mid)
-    }
-
-    /// Returns an iterator over the [`char`]s of a string slice.
-    ///
-    /// As a string slice consists of valid UTF-8, we can iterate through a
-    /// string slice by [`char`]. This method returns such an iterator.
-    ///
-    /// It's important to remember that [`char`] represents a Unicode Scalar
-    /// Value, and may not match your idea of what a 'character' is. Iteration
-    /// over grapheme clusters may be what you actually want.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let word = "goodbye";
-    ///
-    /// let count = word.chars().count();
-    /// assert_eq!(7, count);
-    ///
-    /// let mut chars = word.chars();
-    ///
-    /// assert_eq!(Some('g'), chars.next());
-    /// assert_eq!(Some('o'), chars.next());
-    /// assert_eq!(Some('o'), chars.next());
-    /// assert_eq!(Some('d'), chars.next());
-    /// assert_eq!(Some('b'), chars.next());
-    /// assert_eq!(Some('y'), chars.next());
-    /// assert_eq!(Some('e'), chars.next());
-    ///
-    /// assert_eq!(None, chars.next());
-    /// ```
-    ///
-    /// Remember, [`char`]s may not match your human intuition about characters:
-    ///
-    /// ```
-    /// let y = "y̆";
-    ///
-    /// let mut chars = y.chars();
-    ///
-    /// assert_eq!(Some('y'), chars.next()); // not 'y̆'
-    /// assert_eq!(Some('\u{0306}'), chars.next());
-    ///
-    /// assert_eq!(None, chars.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn chars(&self) -> Chars {
-        core_str::StrExt::chars(self)
-    }
-    /// Returns an iterator over the [`char`]s of a string slice, and their
-    /// positions.
-    ///
-    /// As a string slice consists of valid UTF-8, we can iterate through a
-    /// string slice by [`char`]. This method returns an iterator of both
-    /// these [`char`]s, as well as their byte positions.
-    ///
-    /// The iterator yields tuples. The position is first, the [`char`] is
-    /// second.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let word = "goodbye";
-    ///
-    /// let count = word.char_indices().count();
-    /// assert_eq!(7, count);
-    ///
-    /// let mut char_indices = word.char_indices();
-    ///
-    /// assert_eq!(Some((0, 'g')), char_indices.next());
-    /// assert_eq!(Some((1, 'o')), char_indices.next());
-    /// assert_eq!(Some((2, 'o')), char_indices.next());
-    /// assert_eq!(Some((3, 'd')), char_indices.next());
-    /// assert_eq!(Some((4, 'b')), char_indices.next());
-    /// assert_eq!(Some((5, 'y')), char_indices.next());
-    /// assert_eq!(Some((6, 'e')), char_indices.next());
-    ///
-    /// assert_eq!(None, char_indices.next());
-    /// ```
-    ///
-    /// Remember, [`char`]s may not match your human intuition about characters:
-    ///
-    /// ```
-    /// let yes = "y̆es";
-    ///
-    /// let mut char_indices = yes.char_indices();
-    ///
-    /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
-    /// assert_eq!(Some((1, '\u{0306}')), char_indices.next());
-    ///
-    /// // note the 3 here - the last character took up two bytes
-    /// assert_eq!(Some((3, 'e')), char_indices.next());
-    /// assert_eq!(Some((4, 's')), char_indices.next());
-    ///
-    /// assert_eq!(None, char_indices.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn char_indices(&self) -> CharIndices {
-        core_str::StrExt::char_indices(self)
-    }
-
-    /// An iterator over the bytes of a string slice.
-    ///
-    /// As a string slice consists of a sequence of bytes, we can iterate
-    /// through a string slice by byte. This method returns such an iterator.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut bytes = "bors".bytes();
-    ///
-    /// assert_eq!(Some(b'b'), bytes.next());
-    /// assert_eq!(Some(b'o'), bytes.next());
-    /// assert_eq!(Some(b'r'), bytes.next());
-    /// assert_eq!(Some(b's'), bytes.next());
-    ///
-    /// assert_eq!(None, bytes.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn bytes(&self) -> Bytes {
-        core_str::StrExt::bytes(self)
-    }
-
-    /// Split a string slice by whitespace.
-    ///
-    /// The iterator returned will return string slices that are sub-slices of
-    /// the original string slice, separated by any amount of whitespace.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let mut iter = "A few words".split_whitespace();
-    ///
-    /// assert_eq!(Some("A"), iter.next());
-    /// assert_eq!(Some("few"), iter.next());
-    /// assert_eq!(Some("words"), iter.next());
-    ///
-    /// assert_eq!(None, iter.next());
-    /// ```
-    ///
-    /// All kinds of whitespace are considered:
-    ///
-    /// ```
-    /// let mut iter = " Mary   had\ta\u{2009}little  \n\t lamb".split_whitespace();
-    /// assert_eq!(Some("Mary"), iter.next());
-    /// assert_eq!(Some("had"), iter.next());
-    /// assert_eq!(Some("a"), iter.next());
-    /// assert_eq!(Some("little"), iter.next());
-    /// assert_eq!(Some("lamb"), iter.next());
-    ///
-    /// assert_eq!(None, iter.next());
-    /// ```
-    #[stable(feature = "split_whitespace", since = "1.1.0")]
-    #[inline]
-    pub fn split_whitespace(&self) -> SplitWhitespace {
-        StrExt::split_whitespace(self)
-    }
-
-    /// An iterator over the lines of a string, as string slices.
-    ///
-    /// Lines are ended with either a newline (`\n`) or a carriage return with
-    /// a line feed (`\r\n`).
-    ///
-    /// The final line ending is optional.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let text = "foo\r\nbar\n\nbaz\n";
-    /// let mut lines = text.lines();
-    ///
-    /// assert_eq!(Some("foo"), lines.next());
-    /// assert_eq!(Some("bar"), lines.next());
-    /// assert_eq!(Some(""), lines.next());
-    /// assert_eq!(Some("baz"), lines.next());
-    ///
-    /// assert_eq!(None, lines.next());
-    /// ```
-    ///
-    /// The final line ending isn't required:
-    ///
-    /// ```
-    /// let text = "foo\nbar\n\r\nbaz";
-    /// let mut lines = text.lines();
-    ///
-    /// assert_eq!(Some("foo"), lines.next());
-    /// assert_eq!(Some("bar"), lines.next());
-    /// assert_eq!(Some(""), lines.next());
-    /// assert_eq!(Some("baz"), lines.next());
-    ///
-    /// assert_eq!(None, lines.next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn lines(&self) -> Lines {
-        core_str::StrExt::lines(self)
-    }
-
-    /// An iterator over the lines of a string.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")]
-    #[inline]
-    #[allow(deprecated)]
-    pub fn lines_any(&self) -> LinesAny {
-        core_str::StrExt::lines_any(self)
-    }
-
-    /// Returns an iterator of `u16` over the string encoded as UTF-16.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let text = "Zażółć gęślą jaźń";
-    ///
-    /// let utf8_len = text.len();
-    /// let utf16_len = text.encode_utf16().count();
-    ///
-    /// assert!(utf16_len <= utf8_len);
-    /// ```
-    #[stable(feature = "encode_utf16", since = "1.8.0")]
-    pub fn encode_utf16(&self) -> EncodeUtf16 {
-        EncodeUtf16 { chars: self[..].chars(), extra: 0 }
-    }
-
-    /// Returns `true` if the given pattern matches a sub-slice of
-    /// this string slice.
-    ///
-    /// Returns `false` if it does not.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bananas = "bananas";
-    ///
-    /// assert!(bananas.contains("nana"));
-    /// assert!(!bananas.contains("apples"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-        core_str::StrExt::contains(self, pat)
-    }
-
-    /// Returns `true` if the given pattern matches a prefix of this
-    /// string slice.
-    ///
-    /// Returns `false` if it does not.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bananas = "bananas";
-    ///
-    /// assert!(bananas.starts_with("bana"));
-    /// assert!(!bananas.starts_with("nana"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-        core_str::StrExt::starts_with(self, pat)
-    }
-
-    /// Returns `true` if the given pattern matches a suffix of this
-    /// string slice.
-    ///
-    /// Returns `false` if it does not.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let bananas = "bananas";
-    ///
-    /// assert!(bananas.ends_with("anas"));
-    /// assert!(!bananas.ends_with("nana"));
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::ends_with(self, pat)
-    }
-
-    /// Returns the byte index of the first character of this string slice that
-    /// matches the pattern.
-    ///
-    /// Returns [`None`] if the pattern doesn't match.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.find('L'), Some(0));
-    /// assert_eq!(s.find('é'), Some(14));
-    /// assert_eq!(s.find("Léopard"), Some(13));
-    /// ```
-    ///
-    /// More complex patterns using point-free style and closures:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.find(char::is_whitespace), Some(5));
-    /// assert_eq!(s.find(char::is_lowercase), Some(1));
-    /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1));
-    /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4));
-    /// ```
-    ///
-    /// Not finding the pattern:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// let x: &[_] = &['1', '2'];
-    ///
-    /// assert_eq!(s.find(x), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
-        core_str::StrExt::find(self, pat)
-    }
-
-    /// Returns the byte index of the last character of this string slice that
-    /// matches the pattern.
-    ///
-    /// Returns [`None`] if the pattern doesn't match.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    /// [`None`]: option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.rfind('L'), Some(13));
-    /// assert_eq!(s.rfind('é'), Some(14));
-    /// ```
-    ///
-    /// More complex patterns with closures:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.rfind(char::is_whitespace), Some(12));
-    /// assert_eq!(s.rfind(char::is_lowercase), Some(20));
-    /// ```
-    ///
-    /// Not finding the pattern:
-    ///
-    /// ```
-    /// let s = "Löwe 老虎 Léopard";
-    /// let x: &[_] = &['1', '2'];
-    ///
-    /// assert_eq!(s.rfind(x), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rfind(self, pat)
-    }
-
-    /// An iterator over substrings of this string slice, separated by
-    /// characters matched by a pattern.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rsplit`] method can be used.
-    ///
-    /// [`char`]: primitive.char.html
-    /// [`rsplit`]: #method.rsplit
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
-    ///
-    /// let v: Vec<&str> = "".split('X').collect();
-    /// assert_eq!(v, [""]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
-    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
-    ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
-    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
-    ///
-    /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect();
-    /// assert_eq!(v, ["abc", "def", "ghi"]);
-    ///
-    /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect();
-    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["abc", "def", "ghi"]);
-    /// ```
-    ///
-    /// If a string contains multiple contiguous separators, you will end up
-    /// with empty strings in the output:
-    ///
-    /// ```
-    /// let x = "||||a||b|c".to_string();
-    /// let d: Vec<_> = x.split('|').collect();
-    ///
-    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
-    /// ```
-    ///
-    /// Contiguous separators are separated by the empty string.
-    ///
-    /// ```
-    /// let x = "(///)".to_string();
-    /// let d: Vec<_> = x.split('/').collect();
-    ///
-    /// assert_eq!(d, &["(", "", "", ")"]);
-    /// ```
-    ///
-    /// Separators at the start or end of a string are neighbored
-    /// by empty strings.
-    ///
-    /// ```
-    /// let d: Vec<_> = "010".split("0").collect();
-    /// assert_eq!(d, &["", "1", ""]);
-    /// ```
-    ///
-    /// When the empty string is used as a separator, it separates
-    /// every character in the string, along with the beginning
-    /// and end of the string.
-    ///
-    /// ```
-    /// let f: Vec<_> = "rust".split("").collect();
-    /// assert_eq!(f, &["", "r", "u", "s", "t", ""]);
-    /// ```
-    ///
-    /// Contiguous separators can lead to possibly surprising behavior
-    /// when whitespace is used as the separator. This code is correct:
-    ///
-    /// ```
-    /// let x = "    a  b c".to_string();
-    /// let d: Vec<_> = x.split(' ').collect();
-    ///
-    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
-    /// ```
-    ///
-    /// It does _not_ give you:
-    ///
-    /// ```,ignore
-    /// assert_eq!(d, &["a", "b", "c"]);
-    /// ```
-    ///
-    /// Use [`split_whitespace`] for this behavior.
-    ///
-    /// [`split_whitespace`]: #method.split_whitespace
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
-        core_str::StrExt::split(self, pat)
-    }
-
-    /// An iterator over substrings of the given string slice, separated by
-    /// characters matched by a pattern and yielded in reverse order.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a reverse
-    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// For iterating from the front, the [`split`] method can be used.
-    ///
-    /// [`split`]: #method.split
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
-    /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
-    ///
-    /// let v: Vec<&str> = "".rsplit('X').collect();
-    /// assert_eq!(v, [""]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect();
-    /// assert_eq!(v, ["leopard", "tiger", "", "lion"]);
-    ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["ghi", "def", "abc"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplit(self, pat)
-    }
-
-    /// An iterator over substrings of the given string slice, separated by
-    /// characters matched by a pattern.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// Equivalent to [`split`], except that the trailing substring
-    /// is skipped if empty.
-    ///
-    /// [`split`]: #method.split
-    ///
-    /// This method can be used for string data that is _terminated_,
-    /// rather than _separated_ by a pattern.
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    /// [`char`]: primitive.char.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rsplit_terminator`] method can be used.
-    ///
-    /// [`rsplit_terminator`]: #method.rsplit_terminator
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
-    /// assert_eq!(v, ["A", "B"]);
-    ///
-    /// let v: Vec<&str> = "A..B..".split_terminator(".").collect();
-    /// assert_eq!(v, ["A", "", "B", ""]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
-        core_str::StrExt::split_terminator(self, pat)
-    }
-
-    /// An iterator over substrings of `self`, separated by characters
-    /// matched by a pattern and yielded in reverse order.
-    ///
-    /// The pattern can be a simple `&str`, [`char`], or a closure that
-    /// determines the split.
-    /// Additional libraries might provide more complex patterns like
-    /// regular expressions.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// Equivalent to [`split`], except that the trailing substring is
-    /// skipped if empty.
-    ///
-    /// [`split`]: #method.split
-    ///
-    /// This method can be used for string data that is _terminated_,
-    /// rather than _separated_ by a pattern.
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a
-    /// reverse search, and it will be double ended if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// For iterating from the front, the [`split_terminator`] method can be
-    /// used.
-    ///
-    /// [`split_terminator`]: #method.split_terminator
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect();
-    /// assert_eq!(v, ["B", "A"]);
-    ///
-    /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
-    /// assert_eq!(v, ["", "B", "", "A"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplit_terminator(self, pat)
-    }
-
-    /// An iterator over substrings of the given string slice, separated by a
-    /// pattern, restricted to returning at most `n` items.
-    ///
-    /// If `n` substrings are returned, the last substring (the `n`th substring)
-    /// will contain the remainder of the string.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines the
-    /// split.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will not be double ended, because it is
-    /// not efficient to support.
-    ///
-    /// If the pattern allows a reverse search, the [`rsplitn`] method can be
-    /// used.
-    ///
-    /// [`rsplitn`]: #method.rsplitn
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect();
-    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
-    ///
-    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
-    /// assert_eq!(v, ["abcXdef"]);
-    ///
-    /// let v: Vec<&str> = "".splitn(1, 'X').collect();
-    /// assert_eq!(v, [""]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["abc", "defXghi"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
-        core_str::StrExt::splitn(self, n, pat)
-    }
-
-    /// An iterator over substrings of this string slice, separated by a
-    /// pattern, starting from the end of the string, restricted to returning
-    /// at most `n` items.
-    ///
-    /// If `n` substrings are returned, the last substring (the `n`th substring)
-    /// will contain the remainder of the string.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that
-    /// determines the split.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will not be double ended, because it is not
-    /// efficient to support.
-    ///
-    /// For splitting from the front, the [`splitn`] method can be used.
-    ///
-    /// [`splitn`]: #method.splitn
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
-    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
-    ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
-    ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
-    /// assert_eq!(v, ["leopard", "lion::tiger"]);
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect();
-    /// assert_eq!(v, ["ghi", "abc1def"]);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rsplitn(self, n, pat)
-    }
-
-    /// An iterator over the disjoint matches of a pattern within the given string
-    /// slice.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that
-    /// determines if a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    /// [`char`]: primitive.char.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rmatches`] method can be used.
-    ///
-    /// [`rmatches`]: #method.rmatches
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
-    /// assert_eq!(v, ["abc", "abc", "abc"]);
-    ///
-    /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
-    /// assert_eq!(v, ["1", "2", "3"]);
-    /// ```
-    #[stable(feature = "str_matches", since = "1.2.0")]
-    #[inline]
-    pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
-        core_str::StrExt::matches(self, pat)
-    }
-
-    /// An iterator over the disjoint matches of a pattern within this string slice,
-    /// yielded in reverse order.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a reverse
-    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// For iterating from the front, the [`matches`] method can be used.
-    ///
-    /// [`matches`]: #method.matches
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
-    /// assert_eq!(v, ["abc", "abc", "abc"]);
-    ///
-    /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
-    /// assert_eq!(v, ["3", "2", "1"]);
-    /// ```
-    #[stable(feature = "str_matches", since = "1.2.0")]
-    #[inline]
-    pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rmatches(self, pat)
-    }
+            return String::new();
+        }
 
-    /// An iterator over the disjoint matches of a pattern within this string
-    /// slice as well as the index that the match starts at.
-    ///
-    /// For matches of `pat` within `self` that overlap, only the indices
-    /// corresponding to the first match are returned.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines
-    /// if a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
-    /// allows a reverse search and forward/reverse search yields the same
-    /// elements. This is true for, eg, [`char`] but not for `&str`.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// If the pattern allows a reverse search but its results might differ
-    /// from a forward search, the [`rmatch_indices`] method can be used.
-    ///
-    /// [`rmatch_indices`]: #method.rmatch_indices
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
-    /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
-    ///
-    /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
-    /// assert_eq!(v, [(1, "abc"), (4, "abc")]);
-    ///
-    /// let v: Vec<_> = "ababa".match_indices("aba").collect();
-    /// assert_eq!(v, [(0, "aba")]); // only the first `aba`
-    /// ```
-    #[stable(feature = "str_match_indices", since = "1.5.0")]
-    #[inline]
-    pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
-        core_str::StrExt::match_indices(self, pat)
-    }
+        // `len` calculation may overflow but push_str will check boundaries
+        let len = self.iter().map(|s| s.borrow().len()).sum();
+        let mut result = String::with_capacity(len);
 
-    /// An iterator over the disjoint matches of a pattern within `self`,
-    /// yielded in reverse order along with the index of the match.
-    ///
-    /// For matches of `pat` within `self` that overlap, only the indices
-    /// corresponding to the last match are returned.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if a
-    /// character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Iterator behavior
-    ///
-    /// The returned iterator requires that the pattern supports a reverse
-    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
-    /// search yields the same elements.
-    ///
-    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
-    ///
-    /// For iterating from the front, the [`match_indices`] method can be used.
-    ///
-    /// [`match_indices`]: #method.match_indices
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
-    ///
-    /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(4, "abc"), (1, "abc")]);
-    ///
-    /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
-    /// assert_eq!(v, [(2, "aba")]); // only the last `aba`
-    /// ```
-    #[stable(feature = "str_match_indices", since = "1.5.0")]
-    #[inline]
-    pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::rmatch_indices(self, pat)
-    }
+        for s in self {
+            result.push_str(s.borrow())
+        }
 
-    /// Returns a string slice with leading and trailing whitespace removed.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = " Hello\tworld\t";
-    ///
-    /// assert_eq!("Hello\tworld", s.trim());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim(&self) -> &str {
-        StrExt::trim(self)
+        result
     }
 
-    /// Returns a string slice with leading whitespace removed.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Left' in this context means the first
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _right_ side, not the left.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = " Hello\tworld\t";
-    ///
-    /// assert_eq!("Hello\tworld\t", s.trim_left());
-    /// ```
-    ///
-    /// Directionality:
-    ///
-    /// ```
-    /// let s = "  English";
-    /// assert!(Some('E') == s.trim_left().chars().next());
-    ///
-    /// let s = "  עברית";
-    /// assert!(Some('ע') == s.trim_left().chars().next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_left(&self) -> &str {
-        StrExt::trim_left(self)
-    }
+    fn join(&self, sep: &str) -> String {
+        if self.is_empty() {
+            return String::new();
+        }
 
-    /// Returns a string slice with trailing whitespace removed.
-    ///
-    /// 'Whitespace' is defined according to the terms of the Unicode Derived
-    /// Core Property `White_Space`.
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Right' in this context means the last
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _left_ side, not the right.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// let s = " Hello\tworld\t";
-    ///
-    /// assert_eq!(" Hello\tworld", s.trim_right());
-    /// ```
-    ///
-    /// Directionality:
-    ///
-    /// ```
-    /// let s = "English  ";
-    /// assert!(Some('h') == s.trim_right().chars().rev().next());
-    ///
-    /// let s = "עברית  ";
-    /// assert!(Some('ת') == s.trim_right().chars().rev().next());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_right(&self) -> &str {
-        StrExt::trim_right(self)
+        // concat is faster
+        if sep.is_empty() {
+            return self.concat();
+        }
+
+        // this is wrong without the guarantee that `self` is non-empty
+        // `len` calculation may overflow but push_str but will check boundaries
+        let len = sep.len() * (self.len() - 1) +
+                  self.iter().map(|s| s.borrow().len()).sum::<usize>();
+        let mut result = String::with_capacity(len);
+        let mut first = true;
+
+        for s in self {
+            if first {
+                first = false;
+            } else {
+                result.push_str(sep);
+            }
+            result.push_str(s.borrow());
+        }
+        result
     }
 
-    /// Returns a string slice with all prefixes and suffixes that match a
-    /// pattern repeatedly removed.
-    ///
-    /// The pattern can be a [`char`] or a closure that determines if a
-    /// character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
-    /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar");
-    ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
-        where P::Searcher: DoubleEndedSearcher<'a>
-    {
-        core_str::StrExt::trim_matches(self, pat)
+    fn connect(&self, sep: &str) -> String {
+        self.join(sep)
     }
+}
 
-    /// Returns a string slice with all prefixes that match a pattern
-    /// repeatedly removed.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that determines if
-    /// a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Left' in this context means the first
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _right_ side, not the left.
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
-    /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
-    ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
-        core_str::StrExt::trim_left_matches(self, pat)
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Borrow<str> for String {
+    #[inline]
+    fn borrow(&self) -> &str {
+        &self[..]
     }
+}
 
-    /// Returns a string slice with all suffixes that match a pattern
-    /// repeatedly removed.
-    ///
-    /// The pattern can be a `&str`, [`char`], or a closure that
-    /// determines if a character matches.
-    ///
-    /// [`char`]: primitive.char.html
-    ///
-    /// # Text directionality
-    ///
-    /// A string is a sequence of bytes. 'Right' in this context means the last
-    /// position of that byte string; for a language like Arabic or Hebrew
-    /// which are 'right to left' rather than 'left to right', this will be
-    /// the _left_ side, not the right.
-    ///
-    /// # Examples
-    ///
-    /// Simple patterns:
-    ///
-    /// ```
-    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
-    /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
-    ///
-    /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
-    /// ```
-    ///
-    /// A more complex pattern, using a closure:
-    ///
-    /// ```
-    /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
-        where P::Searcher: ReverseSearcher<'a>
-    {
-        core_str::StrExt::trim_right_matches(self, pat)
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ToOwned for str {
+    type Owned = String;
+    fn to_owned(&self) -> String {
+        unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) }
     }
 
-    /// Parses this string slice into another type.
-    ///
-    /// Because `parse` is so general, it can cause problems with type
-    /// inference. As such, `parse` is one of the few times you'll see
-    /// the syntax affectionately known as the 'turbofish': `::<>`. This
-    /// helps the inference algorithm understand specifically which type
-    /// you're trying to parse into.
-    ///
-    /// `parse` can parse any type that implements the [`FromStr`] trait.
-    ///
-    /// [`FromStr`]: str/trait.FromStr.html
-    ///
-    /// # Errors
-    ///
-    /// Will return [`Err`] if it's not possible to parse this string slice into
-    /// the desired type.
-    ///
-    /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
-    ///
-    /// # Examples
-    ///
-    /// Basic usage
-    ///
-    /// ```
-    /// let four: u32 = "4".parse().unwrap();
-    ///
-    /// assert_eq!(4, four);
-    /// ```
-    ///
-    /// Using the 'turbofish' instead of annotating `four`:
-    ///
-    /// ```
-    /// let four = "4".parse::<u32>();
-    ///
-    /// assert_eq!(Ok(4), four);
-    /// ```
-    ///
-    /// Failing to parse:
-    ///
-    /// ```
-    /// let nope = "j".parse::<u32>();
-    ///
-    /// assert!(nope.is_err());
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
-        core_str::StrExt::parse(self)
+    fn clone_into(&self, target: &mut String) {
+        let mut b = mem::replace(target, String::new()).into_bytes();
+        self.as_bytes().clone_into(&mut b);
+        *target = unsafe { String::from_utf8_unchecked(b) }
     }
+}
+
+/// Methods for string slices.
+#[cfg_attr(stage0, lang = "str")]
+#[cfg_attr(not(stage0), lang = "str_alloc")]
+#[cfg(not(test))]
+impl str {
+    #[cfg(stage0)]
+    str_core_methods!();
 
     /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
     ///
@@ -2085,79 +436,7 @@ pub fn into_string(self: Box<str>) -> String {
     /// ```
     #[stable(feature = "repeat_str", since = "1.16.0")]
     pub fn repeat(&self, n: usize) -> String {
-        if n == 0 {
-            return String::new();
-        }
-
-        // If `n` is larger than zero, it can be split as
-        // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
-        // `2^expn` is the number represented by the leftmost '1' bit of `n`,
-        // and `rem` is the remaining part of `n`.
-
-        // Using `Vec` to access `set_len()`.
-        let mut buf = Vec::with_capacity(self.len() * n);
-
-        // `2^expn` repetition is done by doubling `buf` `expn`-times.
-        buf.extend(self.as_bytes());
-        {
-            let mut m = n >> 1;
-            // If `m > 0`, there are remaining bits up to the leftmost '1'.
-            while m > 0 {
-                // `buf.extend(buf)`:
-                unsafe {
-                    ptr::copy_nonoverlapping(
-                        buf.as_ptr(),
-                        (buf.as_mut_ptr() as *mut u8).add(buf.len()),
-                        buf.len(),
-                    );
-                    // `buf` has capacity of `self.len() * n`.
-                    let buf_len = buf.len();
-                    buf.set_len(buf_len * 2);
-                }
-
-                m >>= 1;
-            }
-        }
-
-        // `rem` (`= n - 2^expn`) repetition is done by copying
-        // first `rem` repetitions from `buf` itself.
-        let rem_len = self.len() * n - buf.len(); // `self.len() * rem`
-        if rem_len > 0 {
-            // `buf.extend(buf[0 .. rem_len])`:
-            unsafe {
-                // This is non-overlapping since `2^expn > rem`.
-                ptr::copy_nonoverlapping(
-                    buf.as_ptr(),
-                    (buf.as_mut_ptr() as *mut u8).add(buf.len()),
-                    rem_len,
-                );
-                // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
-                let buf_cap = buf.capacity();
-                buf.set_len(buf_cap);
-            }
-        }
-
-        unsafe { String::from_utf8_unchecked(buf) }
-    }
-
-    /// Checks if all characters in this string are within the ASCII range.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let ascii = "hello!\n";
-    /// let non_ascii = "Grüße, Jürgen ❤";
-    ///
-    /// assert!(ascii.is_ascii());
-    /// assert!(!non_ascii.is_ascii());
-    /// ```
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn is_ascii(&self) -> bool {
-        // We can treat each byte as character here: all multibyte characters
-        // start with a byte that is not in the ascii range, so we will stop
-        // there already.
-        self.bytes().all(|b| b.is_ascii())
+        unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
     }
 
     /// Returns a copy of this string where each character is mapped to its
@@ -2219,54 +498,6 @@ pub fn to_ascii_lowercase(&self) -> String {
         // make_ascii_lowercase() preserves the UTF-8 invariant.
         unsafe { String::from_utf8_unchecked(bytes) }
     }
-
-    /// Checks that two strings are an ASCII case-insensitive match.
-    ///
-    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
-    /// but without allocating and copying temporaries.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert!("Ferris".eq_ignore_ascii_case("FERRIS"));
-    /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS"));
-    /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
-    /// ```
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
-        self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
-    }
-
-    /// Converts this string to its ASCII upper case equivalent in-place.
-    ///
-    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new uppercased value without modifying the existing one, use
-    /// [`to_ascii_uppercase`].
-    ///
-    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    pub fn make_ascii_uppercase(&mut self) {
-        let me = unsafe { self.as_bytes_mut() };
-        me.make_ascii_uppercase()
-    }
-
-    /// Converts this string to its ASCII lower case equivalent in-place.
-    ///
-    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
-    /// but non-ASCII letters are unchanged.
-    ///
-    /// To return a new lowercased value without modifying the existing one, use
-    /// [`to_ascii_lowercase`].
-    ///
-    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
-    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
-    pub fn make_ascii_lowercase(&mut self) {
-        let me = unsafe { self.as_bytes_mut() };
-        me.make_ascii_lowercase()
-    }
 }
 
 /// Converts a boxed slice of bytes to a boxed string slice without checking
index a3f4c385fe23b731b52f329312790a1ba494253b..a03b61ec97e51c71210cc43ef10487266f3ca2e0 100644 (file)
@@ -401,6 +401,36 @@ fn test_str_get_maxinclusive() {
     }
 }
 
+#[test]
+fn test_str_slice_rangetoinclusive_ok() {
+    let s = "abcαβγ";
+    assert_eq!(&s[..=2], "abc");
+    assert_eq!(&s[..=4], "abcα");
+}
+
+#[test]
+#[should_panic]
+fn test_str_slice_rangetoinclusive_notok() {
+    let s = "abcαβγ";
+    &s[..=3];
+}
+
+#[test]
+fn test_str_slicemut_rangetoinclusive_ok() {
+    let mut s = "abcαβγ".to_owned();
+    let s: &mut str = &mut s;
+    assert_eq!(&mut s[..=2], "abc");
+    assert_eq!(&mut s[..=4], "abcα");
+}
+
+#[test]
+#[should_panic]
+fn test_str_slicemut_rangetoinclusive_notok() {
+    let mut s = "abcαβγ".to_owned();
+    let s: &mut str = &mut s;
+    &mut s[..=3];
+}
+
 #[test]
 fn test_is_char_boundary() {
     let s = "ศไทย中华Việt Nam β-release 🐱123";
index 7d1b2ed85c7e13655e871cdaff00be37796788d8..b184404c15bfd6c050b99252db3c15e41b2d00a2 100644 (file)
@@ -74,6 +74,7 @@
 use core::marker::PhantomData;
 use core::mem;
 #[cfg(not(test))]
+#[cfg(stage0)]
 use core::num::Float;
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{Index, IndexMut, RangeBounds};
index 02435170374c503c81b7111974ebfc0266e2d3a1..7986d5dd2eb54b69a12990dc83891ba320a7e838 100644 (file)
@@ -12,7 +12,6 @@ test = false
 doc = false
 
 [dependencies]
-alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 2b66c293f21a025b16075103a640fa36c61b7d29..4b8755877de4bf7e044d8047054f076e0e4d3984 100644 (file)
@@ -14,7 +14,7 @@
             reason = "this library is unlikely to be stabilized in its current \
                       form or name",
             issue = "27783")]
-#![feature(alloc_system)]
+#![feature(core_intrinsics)]
 #![feature(libc)]
 #![feature(linkage)]
 #![feature(staged_api)]
 #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
 #![rustc_alloc_kind = "exe"]
 
-extern crate alloc_system;
 extern crate libc;
 
 #[cfg(not(dummy_jemalloc))]
 pub use contents::*;
 #[cfg(not(dummy_jemalloc))]
 mod contents {
-    use core::alloc::GlobalAlloc;
-    use alloc_system::System;
     use libc::{c_int, c_void, size_t};
 
     // Note that the symbols here are prefixed by default on macOS and Windows (we
@@ -100,10 +97,11 @@ fn align_to_flags(align: usize, size: usize) -> c_int {
         ptr
     }
 
+    #[cfg(stage0)]
     #[no_mangle]
     #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_oom() -> ! {
-        System.oom()
+        ::core::intrinsics::abort();
     }
 
     #[no_mangle]
index fd8109e2a4aab3d72d280c6fbab55bb44d9f611a..7376ac0f15dd0fd7a61b62e2826bca468008c8e5 100644 (file)
@@ -71,11 +71,6 @@ unsafe fn realloc(&mut self,
                       new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        ::oom()
-    }
 }
 
 #[cfg(stage0)]
@@ -103,11 +98,6 @@ unsafe fn realloc(&mut self,
                       new_size: usize) -> Result<NonNull<Opaque>, AllocErr> {
         NonNull::new(GlobalAlloc::realloc(*self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
     }
-
-    #[inline]
-    fn oom(&mut self) -> ! {
-        ::oom()
-    }
 }
 
 #[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))]
@@ -366,63 +356,3 @@ unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *
         }
     }
 }
-
-#[inline]
-fn oom() -> ! {
-    write_to_stderr("fatal runtime error: memory allocation failed");
-    unsafe {
-        ::core::intrinsics::abort();
-    }
-}
-
-#[cfg(any(unix, target_os = "redox"))]
-#[inline]
-fn write_to_stderr(s: &str) {
-    extern crate libc;
-
-    unsafe {
-        libc::write(libc::STDERR_FILENO,
-                    s.as_ptr() as *const libc::c_void,
-                    s.len());
-    }
-}
-
-#[cfg(windows)]
-#[inline]
-fn write_to_stderr(s: &str) {
-    use core::ptr;
-
-    type LPVOID = *mut u8;
-    type HANDLE = LPVOID;
-    type DWORD = u32;
-    type BOOL = i32;
-    type LPDWORD = *mut DWORD;
-    type LPOVERLAPPED = *mut u8;
-
-    const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
-
-    extern "system" {
-        fn WriteFile(hFile: HANDLE,
-                     lpBuffer: LPVOID,
-                     nNumberOfBytesToWrite: DWORD,
-                     lpNumberOfBytesWritten: LPDWORD,
-                     lpOverlapped: LPOVERLAPPED)
-                     -> BOOL;
-        fn GetStdHandle(which: DWORD) -> HANDLE;
-    }
-
-    unsafe {
-        // WriteFile silently fails if it is passed an invalid
-        // handle, so there is no need to check the result of
-        // GetStdHandle.
-        WriteFile(GetStdHandle(STD_ERROR_HANDLE),
-                  s.as_ptr() as LPVOID,
-                  s.len() as DWORD,
-                  ptr::null_mut(),
-                  ptr::null_mut());
-    }
-}
-
-#[cfg(not(any(windows, unix, target_os = "redox")))]
-#[inline]
-fn write_to_stderr(_: &str) {}
index f08baa3dd71c3146ec312b325b66eff00761f6df..674c4fb57c7f03de938288d6550d632e22484355 100644 (file)
@@ -63,7 +63,7 @@ fn size_align<T>() -> (usize, usize) {
 /// requests have positive size. A caller to the `Alloc::alloc`
 /// method must either ensure that conditions like this are met, or
 /// use specific allocators with looser requirements.)
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct Layout {
     // size of the requested block of memory, measured in bytes.
     size: usize,
@@ -451,17 +451,6 @@ unsafe fn realloc(&self, ptr: *mut Opaque, layout: Layout, new_size: usize) -> *
         }
         new_ptr
     }
-
-    /// Aborts the thread or process, optionally performing
-    /// cleanup or logging diagnostic information before panicking or
-    /// aborting.
-    ///
-    /// `oom` is meant to be used by clients unable to cope with an
-    /// unsatisfied allocation request, and wish to abandon
-    /// computation rather than attempt to recover locally.
-    fn oom(&self) -> ! {
-        unsafe { ::intrinsics::abort() }
-    }
 }
 
 /// An implementation of `Alloc` can allocate, reallocate, and
@@ -614,32 +603,6 @@ pub unsafe trait Alloc {
     ///   to allocate that block of memory.
     unsafe fn dealloc(&mut self, ptr: NonNull<Opaque>, layout: Layout);
 
-    /// Allocator-specific method for signaling an out-of-memory
-    /// condition.
-    ///
-    /// `oom` aborts the thread or process, optionally performing
-    /// cleanup or logging diagnostic information before panicking or
-    /// aborting.
-    ///
-    /// `oom` is meant to be used by clients unable to cope with an
-    /// unsatisfied allocation request, and wish to abandon
-    /// computation rather than attempt to recover locally.
-    ///
-    /// Implementations of the `oom` method are discouraged from
-    /// infinitely regressing in nested calls to `oom`. In
-    /// practice this means implementors should eschew allocating,
-    /// especially from `self` (directly or indirectly).
-    ///
-    /// Implementations of the allocation and reallocation methods
-    /// (e.g. `alloc`, `alloc_one`, `realloc`) are discouraged from
-    /// panicking (or aborting) in the event of memory exhaustion;
-    /// instead they should return an appropriate error from the
-    /// invoked method, and let the client decide whether to invoke
-    /// this `oom` method in response.
-    fn oom(&mut self) -> ! {
-        unsafe { ::intrinsics::abort() }
-    }
-
     // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS ==
     // usable_size
 
index 87144c27c9e11b1b71749f832c354cba97ff59f6..3d24f8902bd83827be8aee45f393f9cf9f9e33a6 100644 (file)
@@ -59,7 +59,7 @@ fn as_mut_slice(&mut self) -> &mut [T] {
 }
 
 /// The error type returned when a conversion from a slice to an array fails.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 #[derive(Debug, Copy, Clone)]
 pub struct TryFromSliceError(());
 
@@ -148,7 +148,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
                 }
             }
 
-            #[stable(feature = "try_from", since = "1.26.0")]
+            #[unstable(feature = "try_from", issue = "33417")]
             impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
                 type Error = TryFromSliceError;
 
@@ -162,7 +162,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
                 }
             }
 
-            #[stable(feature = "try_from", since = "1.26.0")]
+            #[unstable(feature = "try_from", issue = "33417")]
             impl<'a, T> TryFrom<&'a mut [T]> for &'a mut [T; $N] {
                 type Error = TryFromSliceError;
 
index c8ee166fee3e9240383a7ff37c77a0c2e15be536..1ff187ed3f109722f397f705ce728e886494c87e 100644 (file)
@@ -256,6 +256,33 @@ impl<T:Copy> Cell<T> {
     pub fn get(&self) -> T {
         unsafe{ *self.value.get() }
     }
+
+    /// Updates the contained value using a function and returns the new value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_update)]
+    ///
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    /// let new = c.update(|x| x + 1);
+    ///
+    /// assert_eq!(new, 6);
+    /// assert_eq!(c.get(), 6);
+    /// ```
+    #[inline]
+    #[unstable(feature = "cell_update", issue = "50186")]
+    pub fn update<F>(&self, f: F) -> T
+    where
+        F: FnOnce(T) -> T,
+    {
+        let old = self.get();
+        let new = f(old);
+        self.set(new);
+        new
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 150562a4a9b290019c62835286f05573291b345c..803a924eb3a469f49b20f21ccbe55bd81176dd3c 100644 (file)
@@ -204,7 +204,7 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
 }
 
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl TryFrom<u32> for char {
     type Error = CharTryFromError;
 
@@ -219,11 +219,11 @@ fn try_from(i: u32) -> Result<Self, Self::Error> {
 }
 
 /// The error type returned when a conversion from u32 to char fails.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct CharTryFromError(());
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl fmt::Display for CharTryFromError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         "converted integer out of range for `char`".fmt(f)
index 48b531104f8829f4986ccc56985a486e31d789fc..45a73191db2f2cfc0004644c2fdd2954c716d31f 100644 (file)
 /// An iterator over an iterator of bytes of the characters the bytes represent
 /// as UTF-8
 #[unstable(feature = "decode_utf8", issue = "33906")]
+#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
+    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
 #[derive(Clone, Debug)]
+#[allow(deprecated)]
 pub struct DecodeUtf8<I: Iterator<Item = u8>>(::iter::Peekable<I>);
 
 /// Decodes an `Iterator` of bytes as UTF-8.
 #[unstable(feature = "decode_utf8", issue = "33906")]
+#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
+    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
+#[allow(deprecated)]
 #[inline]
 pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> {
     DecodeUtf8(i.into_iter().peekable())
@@ -29,10 +35,14 @@ pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter>
 
 /// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence.
 #[unstable(feature = "decode_utf8", issue = "33906")]
+#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
+    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
 #[derive(PartialEq, Eq, Debug)]
+#[allow(deprecated)]
 pub struct InvalidSequence(());
 
 #[unstable(feature = "decode_utf8", issue = "33906")]
+#[allow(deprecated)]
 impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
     type Item = Result<char, InvalidSequence>;
     #[inline]
@@ -127,6 +137,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[unstable(feature = "decode_utf8", issue = "33906")]
+#[allow(deprecated)]
 impl<I: FusedIterator<Item = u8>> FusedIterator for DecodeUtf8<I> {}
 
 /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
index 9edc0c88756b3c74073dad9e512c512d1a096521..4f6c302247dd2034864f3cbaf9c53bf4fa2e5b3f 100644 (file)
@@ -40,7 +40,7 @@
 pub use self::convert::from_u32_unchecked;
 #[stable(feature = "char_from_str", since = "1.20.0")]
 pub use self::convert::ParseCharError;
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 pub use self::convert::CharTryFromError;
 #[stable(feature = "decode_utf16", since = "1.9.0")]
 pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};
@@ -51,6 +51,9 @@
 #[unstable(feature = "unicode_version", issue = "49726")]
 pub use unicode::version::UnicodeVersion;
 #[unstable(feature = "decode_utf8", issue = "33906")]
+#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
+    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
+#[allow(deprecated)]
 pub use self::decode::{decode_utf8, DecodeUtf8, InvalidSequence};
 
 use fmt::{self, Write};
index 58a8439162c118586033a21603889c32ed6bed7e..f79f73516989f1597f4a55b425bd33009daddd66 100644 (file)
@@ -179,7 +179,7 @@ fn clone(&self) -> Self {
         bool char
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Clone for ! {
         #[inline]
         fn clone(&self) -> Self {
index 3ae9b05b865386563ee9e78764e5a7a18fb61ba7..c91aa06609dd7a5bf4c019ba3d12eb1d0e7d0013 100644 (file)
@@ -881,24 +881,24 @@ fn cmp(&self, other: &bool) -> Ordering {
 
     ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl PartialEq for ! {
         fn eq(&self, _: &!) -> bool {
             *self
         }
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Eq for ! {}
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl PartialOrd for ! {
         fn partial_cmp(&self, _: &!) -> Option<Ordering> {
             *self
         }
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Ord for ! {
         fn cmp(&self, _: &!) -> Ordering {
             *self
index 637213957848c6b7c01bf35fb791a96356669a76..7324df95bc5d5691306ba78924148e593abb4ed4 100644 (file)
@@ -322,26 +322,22 @@ pub trait From<T>: Sized {
 ///
 /// [`TryFrom`]: trait.TryFrom.html
 /// [`Into`]: trait.Into.html
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 pub trait TryInto<T>: Sized {
     /// The type returned in the event of a conversion error.
-    #[stable(feature = "try_from", since = "1.26.0")]
     type Error;
 
     /// Performs the conversion.
-    #[stable(feature = "try_from", since = "1.26.0")]
     fn try_into(self) -> Result<T, Self::Error>;
 }
 
 /// Attempt to construct `Self` via a conversion.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 pub trait TryFrom<T>: Sized {
     /// The type returned in the event of a conversion error.
-    #[stable(feature = "try_from", since = "1.26.0")]
     type Error;
 
     /// Performs the conversion.
-    #[stable(feature = "try_from", since = "1.26.0")]
     fn try_from(value: T) -> Result<Self, Self::Error>;
 }
 
@@ -409,7 +405,7 @@ fn from(t: T) -> T { t }
 
 
 // TryFrom implies TryInto
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl<T, U> TryInto<U> for T where U: TryFrom<T>
 {
     type Error = U::Error;
@@ -421,7 +417,7 @@ fn try_into(self) -> Result<U, U::Error> {
 
 // Infallible conversions are semantically equivalent to fallible conversions
 // with an uninhabited error type.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl<T, U> TryFrom<U> for T where T: From<U> {
     type Error = !;
 
index 277bef2bf661a6488a8321d00429da8c73e77250..a8430f14410e6aef368198e038840f4177214371 100644 (file)
@@ -1780,14 +1780,14 @@ fn fmt(&self, f: &mut Formatter) -> Result { $tr::fmt(&**self, f) }
 
 fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
 
-#[stable(feature = "never_type", since = "1.26.0")]
+#[unstable(feature = "never_type", issue = "35121")]
 impl Debug for ! {
     fn fmt(&self, _: &mut Formatter) -> Result {
         *self
     }
 }
 
-#[stable(feature = "never_type", since = "1.26.0")]
+#[unstable(feature = "never_type", issue = "35121")]
 impl Display for ! {
     fn fmt(&self, _: &mut Formatter) -> Result {
         *self
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
new file mode 100644 (file)
index 0000000..f4e96e6
--- /dev/null
@@ -0,0 +1,61 @@
+// 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.
+
+#![stable(feature = "core_hint", since = "1.27.0")]
+
+//! Hints to compiler that affects how code should be emitted or optimized.
+
+use intrinsics;
+
+/// Informs the compiler that this point in the code is not reachable, enabling
+/// further optimizations.
+///
+/// # Safety
+///
+/// Reaching this function is completely *undefined behavior* (UB). In
+/// particular, the compiler assumes that all UB must never happen, and
+/// therefore will eliminate all branches that reach to a call to
+/// `unreachable_unchecked()`.
+///
+/// Like all instances of UB, if this assumption turns out to be wrong, i.e. the
+/// `unreachable_unchecked()` call is actually reachable among all possible
+/// control flow, the compiler will apply the wrong optimization strategy, and
+/// may sometimes even corrupt seemingly unrelated code, causing
+/// difficult-to-debug problems.
+///
+/// Use this function only when you can prove that the code will never call it.
+///
+/// The [`unreachable!()`] macro is the safe counterpart of this function, which
+/// will panic instead when executed.
+///
+/// [`unreachable!()`]: ../macro.unreachable.html
+///
+/// # Example
+///
+/// ```
+/// fn div_1(a: u32, b: u32) -> u32 {
+///     use std::hint::unreachable_unchecked;
+///
+///     // `b.saturating_add(1)` is always positive (not zero),
+///     // hence `checked_div` will never return None.
+///     // Therefore, the else branch is unreachable.
+///     a.checked_div(b.saturating_add(1))
+///         .unwrap_or_else(|| unsafe { unreachable_unchecked() })
+/// }
+///
+/// assert_eq!(div_1(7, 0), 7);
+/// assert_eq!(div_1(9, 1), 4);
+/// assert_eq!(div_1(11, std::u32::MAX), 0);
+/// ```
+#[inline]
+#[stable(feature = "unreachable", since = "1.27.0")]
+pub unsafe fn unreachable_unchecked() -> ! {
+    intrinsics::unreachable()
+}
index cb215a38e5356247808236b1286732338a53ebc9..58eef6492877a4b0d6430d614eb119498289a6ce 100644 (file)
@@ -87,3 +87,16 @@ fn $method(&mut self, other: &'a $u) {
     }
 }
 
+#[cfg(stage0)]
+macro_rules! public_in_stage0 {
+    ( { $(#[$attr:meta])* } $($Item: tt)*) => {
+        $(#[$attr])* pub $($Item)*
+    }
+}
+
+#[cfg(not(stage0))]
+macro_rules! public_in_stage0 {
+    ( { $(#[$attr:meta])* } $($Item: tt)*) => {
+        $(#[$attr])* pub(crate) $($Item)*
+    }
+}
index 83274682250b0911f2e41b61c43894dbe4bed4fd..fb0d2d9c882196da3d7189d234ad7a9a992e5c93 100644 (file)
     /// NB: This is very different from the `unreachable!()` macro: Unlike the
     /// macro, which panics when it is executed, it is *undefined behavior* to
     /// reach code marked with this function.
+    ///
+    /// The stabilized version of this intrinsic is
+    /// [`std::hint::unreachable_unchecked`](../../std/hint/fn.unreachable_unchecked.html).
     pub fn unreachable() -> !;
 
     /// Informs the optimizer that a condition is always true.
index ea7a46f44ae0f31cb16fa752bcd80debde88afb1..0e21a3327fddf471f6a486fb9e1f222f5e545981 100644 (file)
@@ -71,6 +71,7 @@
 #![feature(cfg_target_has_atomic)]
 #![feature(concat_idents)]
 #![feature(const_fn)]
+#![feature(core_float)]
 #![feature(custom_attribute)]
 #![feature(doc_cfg)]
 #![feature(doc_spotlight)]
@@ -82,6 +83,7 @@
 #![feature(iterator_repeat_with)]
 #![feature(lang_items)]
 #![feature(link_llvm_intrinsics)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(macro_at_most_once_rep)]
 #![feature(no_core)]
 #![feature(rustc_attrs)]
 #![feature(rustc_const_unstable)]
 #![feature(simd_ffi)]
+#![feature(core_slice_ext)]
+#![feature(core_str_ext)]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(stmt_expr_attributes)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
+#![feature(doc_alias)]
 
 #![cfg_attr(not(stage0), feature(mmx_target_feature))]
 #![cfg_attr(not(stage0), feature(tbm_target_feature))]
 pub mod mem;
 pub mod nonzero;
 pub mod ptr;
+pub mod hint;
 
 /* Core language traits */
 
@@ -228,7 +234,7 @@ pub mod heap {
 #[allow(unused_macros)]
 macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*);)* } }
 #[path = "../stdsimd/coresimd/mod.rs"]
-#[allow(missing_docs, missing_debug_implementations, dead_code)]
+#[allow(missing_docs, missing_debug_implementations, dead_code, unused_imports)]
 #[unstable(feature = "stdsimd", issue = "48556")]
 #[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
 mod coresimd;
index 90a9cb3379b82ed8d8b4da3811df406cf540feef..f9371ed0575e49782f7471320d83c5b852d663a1 100644 (file)
@@ -295,6 +295,7 @@ macro_rules! debug_assert_ne {
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "?")]
 macro_rules! try {
     ($expr:expr) => (match $expr {
         $crate::result::Result::Ok(val) => val,
@@ -420,13 +421,13 @@ macro_rules! writeln {
 /// * Iterators that dynamically terminate.
 ///
 /// If the determination that the code is unreachable proves incorrect, the
-/// program immediately terminates with a [`panic!`].  The function [`unreachable`],
-/// which belongs to the [`std::intrinsics`] module, informs the compilier to
+/// program immediately terminates with a [`panic!`].  The function [`unreachable_unchecked`],
+/// which belongs to the [`std::hint`] module, informs the compilier to
 /// optimize the code out of the release version entirely.
 ///
 /// [`panic!`]:  ../std/macro.panic.html
-/// [`unreachable`]: ../std/intrinsics/fn.unreachable.html
-/// [`std::intrinsics`]: ../std/intrinsics/index.html
+/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html
+/// [`std::hint`]: ../std/hint/index.html
 ///
 /// # Panics
 ///
index 885aabe08069d4e064cbebd9183819fe799084e8..feb689dbc1fe8c525282b83ea0fda8ceeef46515 100644 (file)
@@ -630,7 +630,7 @@ impl Copy for $t {}
         bool char
     }
 
-    #[stable(feature = "never_type", since = "1.26.0")]
+    #[unstable(feature = "never_type", issue = "35121")]
     impl Copy for ! {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
index e3f08926610f69592ecb583a7165b05d5fc0ddad..10efab82ddff586d6c44671388968ecf8e8a318f 100644 (file)
@@ -1094,18 +1094,6 @@ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
     }
 }
 
-/// Tells LLVM that this point in the code is not reachable, enabling further
-/// optimizations.
-///
-/// NB: This is very different from the `unreachable!()` macro: Unlike the
-/// macro, which panics when it is executed, it is *undefined behavior* to
-/// reach code marked with this function.
-#[inline]
-#[unstable(feature = "unreachable", issue = "43751")]
-pub unsafe fn unreachable() -> ! {
-    intrinsics::unreachable()
-}
-
 /// A pinned reference.
 ///
 /// A pinned reference is a lot like a mutable reference, except that it is not
index 3586fa5442fb44a1712882cbc8864570fa5ea04a..8d5f6f601daf8a3c0eebc46cadc9124c7219700c 100644 (file)
@@ -17,9 +17,9 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use intrinsics;
 use mem;
 use num::Float;
+#[cfg(not(stage0))] use num::FpCategory;
 use num::FpCategory as Fp;
 
 /// The radix or base of the internal representation of `f32`.
@@ -188,27 +188,6 @@ fn classify(self) -> Fp {
         }
     }
 
-    /// Computes the absolute value of `self`. Returns `Float::nan()` if the
-    /// number is `Float::nan()`.
-    #[inline]
-    fn abs(self) -> f32 {
-        unsafe { intrinsics::fabsf32(self) }
-    }
-
-    /// Returns a number that represents the sign of `self`.
-    ///
-    /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
-    /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
-    /// - `Float::nan()` if the number is `Float::nan()`
-    #[inline]
-    fn signum(self) -> f32 {
-        if self.is_nan() {
-            NAN
-        } else {
-            unsafe { intrinsics::copysignf32(1.0, self) }
-        }
-    }
-
     /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
     /// positive sign bit and positive infinity.
     #[inline]
@@ -231,11 +210,6 @@ fn recip(self) -> f32 {
         1.0 / self
     }
 
-    #[inline]
-    fn powi(self, n: i32) -> f32 {
-        unsafe { intrinsics::powif32(self, n) }
-    }
-
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f32 {
@@ -292,3 +266,286 @@ fn from_bits(v: u32) -> Self {
         unsafe { mem::transmute(v) }
     }
 }
+
+// FIXME: remove (inline) this macro and the Float trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_float", issue = "32110")]
+macro_rules! f32_core_methods { () => {
+    /// Returns `true` if this value is `NaN` and false otherwise.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let nan = f32::NAN;
+    /// let f = 7.0_f32;
+    ///
+    /// assert!(nan.is_nan());
+    /// assert!(!f.is_nan());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_nan(self) -> bool { Float::is_nan(self) }
+
+    /// Returns `true` if this value is positive infinity or negative infinity and
+    /// false otherwise.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let f = 7.0f32;
+    /// let inf = f32::INFINITY;
+    /// let neg_inf = f32::NEG_INFINITY;
+    /// let nan = f32::NAN;
+    ///
+    /// assert!(!f.is_infinite());
+    /// assert!(!nan.is_infinite());
+    ///
+    /// assert!(inf.is_infinite());
+    /// assert!(neg_inf.is_infinite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
+
+    /// Returns `true` if this number is neither infinite nor `NaN`.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let f = 7.0f32;
+    /// let inf = f32::INFINITY;
+    /// let neg_inf = f32::NEG_INFINITY;
+    /// let nan = f32::NAN;
+    ///
+    /// assert!(f.is_finite());
+    ///
+    /// assert!(!nan.is_finite());
+    /// assert!(!inf.is_finite());
+    /// assert!(!neg_inf.is_finite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_finite(self) -> bool { Float::is_finite(self) }
+
+    /// Returns `true` if the number is neither zero, infinite,
+    /// [subnormal][subnormal], or `NaN`.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
+    /// let max = f32::MAX;
+    /// let lower_than_min = 1.0e-40_f32;
+    /// let zero = 0.0_f32;
+    ///
+    /// assert!(min.is_normal());
+    /// assert!(max.is_normal());
+    ///
+    /// assert!(!zero.is_normal());
+    /// assert!(!f32::NAN.is_normal());
+    /// assert!(!f32::INFINITY.is_normal());
+    /// // Values between `0` and `min` are Subnormal.
+    /// assert!(!lower_than_min.is_normal());
+    /// ```
+    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_normal(self) -> bool { Float::is_normal(self) }
+
+    /// Returns the floating point category of the number. If only one property
+    /// is going to be tested, it is generally faster to use the specific
+    /// predicate instead.
+    ///
+    /// ```
+    /// use std::num::FpCategory;
+    /// use std::f32;
+    ///
+    /// let num = 12.4_f32;
+    /// let inf = f32::INFINITY;
+    ///
+    /// assert_eq!(num.classify(), FpCategory::Normal);
+    /// assert_eq!(inf.classify(), FpCategory::Infinite);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn classify(self) -> FpCategory { Float::classify(self) }
+
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
+    ///
+    /// ```
+    /// let f = 7.0_f32;
+    /// let g = -7.0_f32;
+    ///
+    /// assert!(f.is_sign_positive());
+    /// assert!(!g.is_sign_positive());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
+
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
+    ///
+    /// ```
+    /// let f = 7.0f32;
+    /// let g = -7.0f32;
+    ///
+    /// assert!(!f.is_sign_negative());
+    /// assert!(g.is_sign_negative());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
+
+    /// Takes the reciprocal (inverse) of a number, `1/x`.
+    ///
+    /// ```
+    /// use std::f32;
+    ///
+    /// let x = 2.0_f32;
+    /// let abs_difference = (x.recip() - (1.0/x)).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn recip(self) -> f32 { Float::recip(self) }
+
+    /// Converts radians to degrees.
+    ///
+    /// ```
+    /// use std::f32::{self, consts};
+    ///
+    /// let angle = consts::PI;
+    ///
+    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
+    #[inline]
+    pub fn to_degrees(self) -> f32 { Float::to_degrees(self) }
+
+    /// Converts degrees to radians.
+    ///
+    /// ```
+    /// use std::f32::{self, consts};
+    ///
+    /// let angle = 180.0f32;
+    ///
+    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
+    #[inline]
+    pub fn to_radians(self) -> f32 { Float::to_radians(self) }
+
+    /// Returns the maximum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0f32;
+    /// let y = 2.0f32;
+    ///
+    /// assert_eq!(x.max(y), y);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn max(self, other: f32) -> f32 {
+        Float::max(self, other)
+    }
+
+    /// Returns the minimum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0f32;
+    /// let y = 2.0f32;
+    ///
+    /// assert_eq!(x.min(y), x);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn min(self, other: f32) -> f32 {
+        Float::min(self, other)
+    }
+
+    /// Raw transmutation to `u32`.
+    ///
+    /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
+    ///
+    /// See `from_bits` for some discussion of the portability of this operation
+    /// (there are almost no issues).
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
+    /// assert_eq!((12.5f32).to_bits(), 0x41480000);
+    ///
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn to_bits(self) -> u32 {
+        Float::to_bits(self)
+    }
+
+    /// Raw transmutation from `u32`.
+    ///
+    /// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
+    /// It turns out this is incredibly portable, for two reasons:
+    ///
+    /// * Floats and Ints have the same endianness on all supported platforms.
+    /// * IEEE-754 very precisely specifies the bit layout of floats.
+    ///
+    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
+    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
+    /// (notably x86 and ARM) picked the interpretation that was ultimately
+    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
+    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
+    ///
+    /// Rather than trying to preserve signaling-ness cross-platform, this
+    /// implementation favours preserving the exact bits. This means that
+    /// any payloads encoded in NaNs will be preserved even if the result of
+    /// this method is sent over the network from an x86 machine to a MIPS one.
+    ///
+    /// If the results of this method are only manipulated by the same
+    /// architecture that produced them, then there is no portability concern.
+    ///
+    /// If the input isn't NaN, then there is no portability concern.
+    ///
+    /// If you don't care about signalingness (very likely), then there is no
+    /// portability concern.
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::f32;
+    /// let v = f32::from_bits(0x41480000);
+    /// let difference = (v - 12.5).abs();
+    /// assert!(difference <= 1e-5);
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn from_bits(v: u32) -> Self {
+        Float::from_bits(v)
+    }
+}}
+
+#[lang = "f32"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl f32 {
+    f32_core_methods!();
+}
index 64c0d508b388cf6b41b8a3df3e0567af55092822..08b869734d49627099a649553567dd660159b4ca 100644 (file)
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use intrinsics;
 use mem;
-use num::FpCategory as Fp;
 use num::Float;
+#[cfg(not(stage0))] use num::FpCategory;
+use num::FpCategory as Fp;
 
 /// The radix or base of the internal representation of `f64`.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -188,27 +188,6 @@ fn classify(self) -> Fp {
         }
     }
 
-    /// Computes the absolute value of `self`. Returns `Float::nan()` if the
-    /// number is `Float::nan()`.
-    #[inline]
-    fn abs(self) -> f64 {
-        unsafe { intrinsics::fabsf64(self) }
-    }
-
-    /// Returns a number that represents the sign of `self`.
-    ///
-    /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
-    /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
-    /// - `Float::nan()` if the number is `Float::nan()`
-    #[inline]
-    fn signum(self) -> f64 {
-        if self.is_nan() {
-            NAN
-        } else {
-            unsafe { intrinsics::copysignf64(1.0, self) }
-        }
-    }
-
     /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
     /// positive sign bit and positive infinity.
     #[inline]
@@ -229,11 +208,6 @@ fn recip(self) -> f64 {
         1.0 / self
     }
 
-    #[inline]
-    fn powi(self, n: i32) -> f64 {
-        unsafe { intrinsics::powif64(self, n) }
-    }
-
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f64 {
@@ -291,3 +265,296 @@ fn from_bits(v: u64) -> Self {
         unsafe { mem::transmute(v) }
     }
 }
+
+// FIXME: remove (inline) this macro and the Float trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_float", issue = "32110")]
+macro_rules! f64_core_methods { () => {
+    /// Returns `true` if this value is `NaN` and false otherwise.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let nan = f64::NAN;
+    /// let f = 7.0_f64;
+    ///
+    /// assert!(nan.is_nan());
+    /// assert!(!f.is_nan());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_nan(self) -> bool { Float::is_nan(self) }
+
+    /// Returns `true` if this value is positive infinity or negative infinity and
+    /// false otherwise.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let f = 7.0f64;
+    /// let inf = f64::INFINITY;
+    /// let neg_inf = f64::NEG_INFINITY;
+    /// let nan = f64::NAN;
+    ///
+    /// assert!(!f.is_infinite());
+    /// assert!(!nan.is_infinite());
+    ///
+    /// assert!(inf.is_infinite());
+    /// assert!(neg_inf.is_infinite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_infinite(self) -> bool { Float::is_infinite(self) }
+
+    /// Returns `true` if this number is neither infinite nor `NaN`.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let f = 7.0f64;
+    /// let inf: f64 = f64::INFINITY;
+    /// let neg_inf: f64 = f64::NEG_INFINITY;
+    /// let nan: f64 = f64::NAN;
+    ///
+    /// assert!(f.is_finite());
+    ///
+    /// assert!(!nan.is_finite());
+    /// assert!(!inf.is_finite());
+    /// assert!(!neg_inf.is_finite());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_finite(self) -> bool { Float::is_finite(self) }
+
+    /// Returns `true` if the number is neither zero, infinite,
+    /// [subnormal][subnormal], or `NaN`.
+    ///
+    /// ```
+    /// use std::f64;
+    ///
+    /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
+    /// let max = f64::MAX;
+    /// let lower_than_min = 1.0e-308_f64;
+    /// let zero = 0.0f64;
+    ///
+    /// assert!(min.is_normal());
+    /// assert!(max.is_normal());
+    ///
+    /// assert!(!zero.is_normal());
+    /// assert!(!f64::NAN.is_normal());
+    /// assert!(!f64::INFINITY.is_normal());
+    /// // Values between `0` and `min` are Subnormal.
+    /// assert!(!lower_than_min.is_normal());
+    /// ```
+    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_normal(self) -> bool { Float::is_normal(self) }
+
+    /// Returns the floating point category of the number. If only one property
+    /// is going to be tested, it is generally faster to use the specific
+    /// predicate instead.
+    ///
+    /// ```
+    /// use std::num::FpCategory;
+    /// use std::f64;
+    ///
+    /// let num = 12.4_f64;
+    /// let inf = f64::INFINITY;
+    ///
+    /// assert_eq!(num.classify(), FpCategory::Normal);
+    /// assert_eq!(inf.classify(), FpCategory::Infinite);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn classify(self) -> FpCategory { Float::classify(self) }
+
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
+    ///
+    /// ```
+    /// let f = 7.0_f64;
+    /// let g = -7.0_f64;
+    ///
+    /// assert!(f.is_sign_positive());
+    /// assert!(!g.is_sign_positive());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_positive(self) -> bool { Float::is_sign_positive(self) }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
+    #[inline]
+    #[doc(hidden)]
+    pub fn is_positive(self) -> bool { Float::is_sign_positive(self) }
+
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
+    ///
+    /// ```
+    /// let f = 7.0_f64;
+    /// let g = -7.0_f64;
+    ///
+    /// assert!(!f.is_sign_negative());
+    /// assert!(g.is_sign_negative());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_sign_negative(self) -> bool { Float::is_sign_negative(self) }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
+    #[inline]
+    #[doc(hidden)]
+    pub fn is_negative(self) -> bool { Float::is_sign_negative(self) }
+
+    /// Takes the reciprocal (inverse) of a number, `1/x`.
+    ///
+    /// ```
+    /// let x = 2.0_f64;
+    /// let abs_difference = (x.recip() - (1.0/x)).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn recip(self) -> f64 { Float::recip(self) }
+
+    /// Converts radians to degrees.
+    ///
+    /// ```
+    /// use std::f64::consts;
+    ///
+    /// let angle = consts::PI;
+    ///
+    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn to_degrees(self) -> f64 { Float::to_degrees(self) }
+
+    /// Converts degrees to radians.
+    ///
+    /// ```
+    /// use std::f64::consts;
+    ///
+    /// let angle = 180.0_f64;
+    ///
+    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn to_radians(self) -> f64 { Float::to_radians(self) }
+
+    /// Returns the maximum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0_f64;
+    /// let y = 2.0_f64;
+    ///
+    /// assert_eq!(x.max(y), y);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn max(self, other: f64) -> f64 {
+        Float::max(self, other)
+    }
+
+    /// Returns the minimum of the two numbers.
+    ///
+    /// ```
+    /// let x = 1.0_f64;
+    /// let y = 2.0_f64;
+    ///
+    /// assert_eq!(x.min(y), x);
+    /// ```
+    ///
+    /// If one of the arguments is NaN, then the other argument is returned.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn min(self, other: f64) -> f64 {
+        Float::min(self, other)
+    }
+
+    /// Raw transmutation to `u64`.
+    ///
+    /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
+    ///
+    /// See `from_bits` for some discussion of the portability of this operation
+    /// (there are almost no issues).
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
+    /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
+    ///
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn to_bits(self) -> u64 {
+        Float::to_bits(self)
+    }
+
+    /// Raw transmutation from `u64`.
+    ///
+    /// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
+    /// It turns out this is incredibly portable, for two reasons:
+    ///
+    /// * Floats and Ints have the same endianness on all supported platforms.
+    /// * IEEE-754 very precisely specifies the bit layout of floats.
+    ///
+    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
+    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
+    /// (notably x86 and ARM) picked the interpretation that was ultimately
+    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
+    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
+    ///
+    /// Rather than trying to preserve signaling-ness cross-platform, this
+    /// implementation favours preserving the exact bits. This means that
+    /// any payloads encoded in NaNs will be preserved even if the result of
+    /// this method is sent over the network from an x86 machine to a MIPS one.
+    ///
+    /// If the results of this method are only manipulated by the same
+    /// architecture that produced them, then there is no portability concern.
+    ///
+    /// If the input isn't NaN, then there is no portability concern.
+    ///
+    /// If you don't care about signalingness (very likely), then there is no
+    /// portability concern.
+    ///
+    /// Note that this function is distinct from `as` casting, which attempts to
+    /// preserve the *numeric* value, and not the bitwise value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::f64;
+    /// let v = f64::from_bits(0x4029000000000000);
+    /// let difference = (v - 12.5).abs();
+    /// assert!(difference <= 1e-5);
+    /// ```
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
+    #[inline]
+    pub fn from_bits(v: u64) -> Self {
+        Float::from_bits(v)
+    }
+}}
+
+#[lang = "f64"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl f64 {
+    f64_core_methods!();
+}
index f2e8caaad1485ac00e78b0629da906ffd3df866c..a062fbda5bad0bcd0add87188743a596f2679a5b 100644 (file)
@@ -1765,7 +1765,11 @@ pub fn div_euc(self, rhs: Self) -> Self {
             pub fn mod_euc(self, rhs: Self) -> Self {
                 let r = self % rhs;
                 if r < 0 {
-                    r + rhs.abs()
+                    if rhs < 0 {
+                        r - rhs
+                    } else {
+                        r + rhs
+                    }
                 } else {
                     r
                 }
@@ -4098,83 +4102,58 @@ pub enum FpCategory {
     Normal,
 }
 
-/// A built-in floating point number.
+// Technically private and only exposed for coretests:
 #[doc(hidden)]
-#[unstable(feature = "core_float",
-           reason = "stable interface is via `impl f{32,64}` in later crates",
-           issue = "32110")]
+#[unstable(feature = "float_internals",
+           reason = "internal routines only exposed for testing",
+           issue = "0")]
 pub trait Float: Sized {
     /// Type used by `to_bits` and `from_bits`.
-    #[stable(feature = "core_float_bits", since = "1.25.0")]
     type Bits;
 
     /// Returns `true` if this value is NaN and false otherwise.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_nan(self) -> bool;
+
     /// Returns `true` if this value is positive infinity or negative infinity and
     /// false otherwise.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_infinite(self) -> bool;
+
     /// Returns `true` if this number is neither infinite nor NaN.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_finite(self) -> bool;
+
     /// Returns `true` if this number is neither zero, infinite, denormal, or NaN.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_normal(self) -> bool;
+
     /// Returns the category that this number falls into.
-    #[stable(feature = "core", since = "1.6.0")]
     fn classify(self) -> FpCategory;
 
-    /// Computes the absolute value of `self`. Returns `Float::nan()` if the
-    /// number is `Float::nan()`.
-    #[stable(feature = "core", since = "1.6.0")]
-    fn abs(self) -> Self;
-    /// Returns a number that represents the sign of `self`.
-    ///
-    /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
-    /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
-    /// - `Float::nan()` if the number is `Float::nan()`
-    #[stable(feature = "core", since = "1.6.0")]
-    fn signum(self) -> Self;
-
     /// Returns `true` if `self` is positive, including `+0.0` and
     /// `Float::infinity()`.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_sign_positive(self) -> bool;
+
     /// Returns `true` if `self` is negative, including `-0.0` and
     /// `Float::neg_infinity()`.
-    #[stable(feature = "core", since = "1.6.0")]
     fn is_sign_negative(self) -> bool;
 
     /// Take the reciprocal (inverse) of a number, `1/x`.
-    #[stable(feature = "core", since = "1.6.0")]
     fn recip(self) -> Self;
 
-    /// Raise a number to an integer power.
-    ///
-    /// Using this function is generally faster than using `powf`
-    #[stable(feature = "core", since = "1.6.0")]
-    fn powi(self, n: i32) -> Self;
-
     /// Convert radians to degrees.
-    #[stable(feature = "deg_rad_conversions", since="1.7.0")]
     fn to_degrees(self) -> Self;
+
     /// Convert degrees to radians.
-    #[stable(feature = "deg_rad_conversions", since="1.7.0")]
     fn to_radians(self) -> Self;
 
     /// Returns the maximum of the two numbers.
-    #[stable(feature = "core_float_min_max", since="1.20.0")]
     fn max(self, other: Self) -> Self;
+
     /// Returns the minimum of the two numbers.
-    #[stable(feature = "core_float_min_max", since="1.20.0")]
     fn min(self, other: Self) -> Self;
 
     /// Raw transmutation to integer.
-    #[stable(feature = "core_float_bits", since="1.25.0")]
     fn to_bits(self) -> Self::Bits;
+
     /// Raw transmutation from integer.
-    #[stable(feature = "core_float_bits", since="1.25.0")]
     fn from_bits(v: Self::Bits) -> Self;
 }
 
@@ -4192,7 +4171,7 @@ fn from_str(src: &str) -> Result<Self, ParseIntError> {
 from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
 
 /// The error type returned when a checked integral type conversion fails.
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 #[derive(Debug, Copy, Clone)]
 pub struct TryFromIntError(());
 
@@ -4207,14 +4186,14 @@ pub fn __description(&self) -> &str {
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl fmt::Display for TryFromIntError {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         self.__description().fmt(fmt)
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl From<!> for TryFromIntError {
     fn from(never: !) -> TryFromIntError {
         never
@@ -4224,7 +4203,7 @@ fn from(never: !) -> TryFromIntError {
 // only negative bounds
 macro_rules! try_from_lower_bounded {
     ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.26.0")]
+        #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -4243,7 +4222,7 @@ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
 // unsigned to signed (only positive bound)
 macro_rules! try_from_upper_bounded {
     ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.26.0")]
+        #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
@@ -4262,7 +4241,7 @@ fn try_from(u: $source) -> Result<$target, TryFromIntError> {
 // all other cases
 macro_rules! try_from_both_bounded {
     ($source:ty, $($target:ty),*) => {$(
-        #[stable(feature = "try_from", since = "1.26.0")]
+        #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
             type Error = TryFromIntError;
 
index 88db019b02f0789fd8175a1b6623a3c5b7b678e4..a1f6030428f1ef073b7d95d8fe4fa9ca37e01291 100644 (file)
@@ -87,6 +87,7 @@
     message="cannot add `{RHS}` to `{Self}`",
     label="no implementation for `{Self} + {RHS}`",
 )]
+#[doc(alias = "+")]
 pub trait Add<RHS=Self> {
     /// The resulting type after applying the `+` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -183,6 +184,7 @@ fn add(self, other: $t) -> $t { self + other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot subtract `{RHS}` from `{Self}`",
                          label="no implementation for `{Self} - {RHS}`")]
+#[doc(alias = "-")]
 pub trait Sub<RHS=Self> {
     /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -301,6 +303,7 @@ fn sub(self, other: $t) -> $t { self - other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot multiply `{RHS}` to `{Self}`",
                          label="no implementation for `{Self} * {RHS}`")]
+#[doc(alias = "*")]
 pub trait Mul<RHS=Self> {
     /// The resulting type after applying the `*` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -423,6 +426,7 @@ fn mul(self, other: $t) -> $t { self * other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot divide `{Self}` by `{RHS}`",
                          label="no implementation for `{Self} / {RHS}`")]
+#[doc(alias = "/")]
 pub trait Div<RHS=Self> {
     /// The resulting type after applying the `/` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -506,6 +510,7 @@ fn div(self, other: $t) -> $t { self / other }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(message="cannot mod `{Self}` by `{RHS}`",
                          label="no implementation for `{Self} % {RHS}`")]
+#[doc(alias = "%")]
 pub trait Rem<RHS=Self> {
     /// The resulting type after applying the `%` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -589,6 +594,7 @@ fn rem(self, other: $t) -> $t { self % other }
 /// ```
 #[lang = "neg"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "-")]
 pub trait Neg {
     /// The resulting type after applying the `-` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -664,6 +670,8 @@ macro_rules! neg_impl_unsigned {
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`",
                          label="no implementation for `{Self} += {Rhs}`")]
+#[doc(alias = "+")]
+#[doc(alias = "+=")]
 pub trait AddAssign<Rhs=Self> {
     /// Performs the `+=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -718,6 +726,8 @@ fn add_assign(&mut self, other: $t) { *self += other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot subtract-assign `{Rhs}` from `{Self}`",
                          label="no implementation for `{Self} -= {Rhs}`")]
+#[doc(alias = "-")]
+#[doc(alias = "-=")]
 pub trait SubAssign<Rhs=Self> {
     /// Performs the `-=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -763,6 +773,8 @@ fn sub_assign(&mut self, other: $t) { *self -= other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`",
                          label="no implementation for `{Self} *= {Rhs}`")]
+#[doc(alias = "*")]
+#[doc(alias = "*=")]
 pub trait MulAssign<Rhs=Self> {
     /// Performs the `*=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -808,6 +820,8 @@ fn mul_assign(&mut self, other: $t) { *self *= other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`",
                          label="no implementation for `{Self} /= {Rhs}`")]
+#[doc(alias = "/")]
+#[doc(alias = "/=")]
 pub trait DivAssign<Rhs=Self> {
     /// Performs the `/=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
@@ -856,6 +870,8 @@ fn div_assign(&mut self, other: $t) { *self /= other }
 #[stable(feature = "op_assign_traits", since = "1.8.0")]
 #[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``",
                          label="no implementation for `{Self} %= {Rhs}`")]
+#[doc(alias = "%")]
+#[doc(alias = "%=")]
 pub trait RemAssign<Rhs=Self> {
     /// Performs the `%=` operation.
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
index d65c0aba5048103fe80c67056102347f876ee742..0a0e92a91800614a75608bd7099eb2e4fe79ab54 100644 (file)
@@ -62,6 +62,9 @@
 #[lang = "index"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "]")]
+#[doc(alias = "[")]
+#[doc(alias = "[]")]
 pub trait Index<Idx: ?Sized> {
     /// The returned type after indexing.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -146,6 +149,9 @@ pub trait Index<Idx: ?Sized> {
 #[lang = "index_mut"]
 #[rustc_on_unimplemented = "the type `{Self}` cannot be mutably indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
 pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
     /// Performs the mutable indexing (`container[index]`) operation.
     #[stable(feature = "rust1", since = "1.0.0")]
index ef6a8fb6a61c105686f26cef42068178ab4e46b1..4f2d30aa6a8a77b79fe8401f7acfed8904c38b86 100644 (file)
@@ -28,6 +28,7 @@
                that implement `{Try}`",
       label="the `?` operator cannot be applied to type `{Self}`")
 )]
+#[doc(alias = "?")]
 pub trait Try {
     /// The type of this value when viewed as successful.
     #[unstable(feature = "try_trait", issue = "42327")]
index cc3ad71117a5d34d268811adec3ddb72b372019d..8212648f2d8fb308f054ea49e2f94b9c70eb9250 100644 (file)
@@ -58,7 +58,9 @@
 // Re-exported extension traits for primitive types
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
+#[cfg(stage0)]
 pub use slice::SliceExt;
 #[stable(feature = "core_prelude", since = "1.4.0")]
 #[doc(no_inline)]
+#[cfg(stage0)]
 pub use str::StrExt;
index afb149f29977c018cf82459893a4de64747128c8..cc42acd77aed1c29b6ed847b4cbc53e344d15fcb 100644 (file)
@@ -68,12 +68,15 @@ struct Repr<T> {
 // Extension traits
 //
 
+public_in_stage0! {
+{
 /// Extension methods for slices.
 #[unstable(feature = "core_slice_ext",
            reason = "stable interface provided by `impl [T]` in later crates",
            issue = "32110")]
 #[allow(missing_docs)] // documented elsewhere
-pub trait SliceExt {
+}
+trait SliceExt {
     type Item;
 
     #[stable(feature = "core", since = "1.6.0")]
@@ -238,7 +241,7 @@ fn sort_unstable_by<F>(&mut self, compare: F)
     fn sort_unstable_by_key<B, F>(&mut self, f: F)
         where F: FnMut(&Self::Item) -> B,
               B: Ord;
-}
+}}
 
 // Use macros to be generic over const/mut
 macro_rules! slice_offset {
@@ -755,6 +758,1475 @@ fn sort_unstable_by_key<B, F>(&mut self, mut f: F)
     }
 }
 
+// FIXME: remove (inline) this macro and the SliceExt trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_slice_ext", issue = "32110")]
+macro_rules! slice_core_methods { () => {
+    /// Returns the number of elements in the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let a = [1, 2, 3];
+    /// assert_eq!(a.len(), 3);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn len(&self) -> usize {
+        SliceExt::len(self)
+    }
+
+    /// Returns `true` if the slice has a length of 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let a = [1, 2, 3];
+    /// assert!(!a.is_empty());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        SliceExt::is_empty(self)
+    }
+
+    /// Returns the first element of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&10), v.first());
+    ///
+    /// let w: &[i32] = &[];
+    /// assert_eq!(None, w.first());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn first(&self) -> Option<&T> {
+        SliceExt::first(self)
+    }
+
+    /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(first) = x.first_mut() {
+    ///     *first = 5;
+    /// }
+    /// assert_eq!(x, &[5, 1, 2]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn first_mut(&mut self) -> Option<&mut T> {
+        SliceExt::first_mut(self)
+    }
+
+    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first() {
+    ///     assert_eq!(first, &0);
+    ///     assert_eq!(elements, &[1, 2]);
+    /// }
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_first(&self) -> Option<(&T, &[T])> {
+        SliceExt::split_first(self)
+    }
+
+    /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((first, elements)) = x.split_first_mut() {
+    ///     *first = 3;
+    ///     elements[0] = 4;
+    ///     elements[1] = 5;
+    /// }
+    /// assert_eq!(x, &[3, 4, 5]);
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+        SliceExt::split_first_mut(self)
+    }
+
+    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last() {
+    ///     assert_eq!(last, &2);
+    ///     assert_eq!(elements, &[0, 1]);
+    /// }
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_last(&self) -> Option<(&T, &[T])> {
+        SliceExt::split_last(self)
+
+    }
+
+    /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some((last, elements)) = x.split_last_mut() {
+    ///     *last = 3;
+    ///     elements[0] = 4;
+    ///     elements[1] = 5;
+    /// }
+    /// assert_eq!(x, &[4, 5, 3]);
+    /// ```
+    #[stable(feature = "slice_splits", since = "1.5.0")]
+    #[inline]
+    pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+        SliceExt::split_last_mut(self)
+    }
+
+    /// Returns the last element of the slice, or `None` if it is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&30), v.last());
+    ///
+    /// let w: &[i32] = &[];
+    /// assert_eq!(None, w.last());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn last(&self) -> Option<&T> {
+        SliceExt::last(self)
+    }
+
+    /// Returns a mutable pointer to the last item in the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(last) = x.last_mut() {
+    ///     *last = 10;
+    /// }
+    /// assert_eq!(x, &[0, 1, 10]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn last_mut(&mut self) -> Option<&mut T> {
+        SliceExt::last_mut(self)
+    }
+
+    /// Returns a reference to an element or subslice depending on the type of
+    /// index.
+    ///
+    /// - If given a position, returns a reference to the element at that
+    ///   position or `None` if out of bounds.
+    /// - If given a range, returns the subslice corresponding to that range,
+    ///   or `None` if out of bounds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert_eq!(Some(&40), v.get(1));
+    /// assert_eq!(Some(&[10, 40][..]), v.get(0..2));
+    /// assert_eq!(None, v.get(3));
+    /// assert_eq!(None, v.get(0..4));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn get<I>(&self, index: I) -> Option<&I::Output>
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get(self, index)
+    }
+
+    /// Returns a mutable reference to an element or subslice depending on the
+    /// type of index (see [`get`]) or `None` if the index is out of bounds.
+    ///
+    /// [`get`]: #method.get
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [0, 1, 2];
+    ///
+    /// if let Some(elem) = x.get_mut(1) {
+    ///     *elem = 42;
+    /// }
+    /// assert_eq!(x, &[0, 42, 2]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get_mut(self, index)
+    }
+
+    /// Returns a reference to an element or subslice, without doing bounds
+    /// checking.
+    ///
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`get`].
+    ///
+    /// [`get`]: #method.get
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    ///
+    /// unsafe {
+    ///     assert_eq!(x.get_unchecked(1), &2);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get_unchecked(self, index)
+    }
+
+    /// Returns a mutable reference to an element or subslice, without doing
+    /// bounds checking.
+    ///
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`get_mut`].
+    ///
+    /// [`get_mut`]: #method.get_mut
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    ///
+    /// unsafe {
+    ///     let elem = x.get_unchecked_mut(1);
+    ///     *elem = 13;
+    /// }
+    /// assert_eq!(x, &[1, 13, 4]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
+        where I: SliceIndex<Self>
+    {
+        SliceExt::get_unchecked_mut(self, index)
+    }
+
+    /// Returns a raw pointer to the slice's buffer.
+    ///
+    /// The caller must ensure that the slice outlives the pointer this
+    /// function returns, or else it will end up pointing to garbage.
+    ///
+    /// Modifying the container referenced by this slice may cause its buffer
+    /// to be reallocated, which would also make any pointers to it invalid.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    /// let x_ptr = x.as_ptr();
+    ///
+    /// unsafe {
+    ///     for i in 0..x.len() {
+    ///         assert_eq!(x.get_unchecked(i), &*x_ptr.offset(i as isize));
+    ///     }
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn as_ptr(&self) -> *const T {
+        SliceExt::as_ptr(self)
+    }
+
+    /// Returns an unsafe mutable pointer to the slice's buffer.
+    ///
+    /// The caller must ensure that the slice outlives the pointer this
+    /// function returns, or else it will end up pointing to garbage.
+    ///
+    /// Modifying the container referenced by this slice may cause its buffer
+    /// to be reallocated, which would also make any pointers to it invalid.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    /// let x_ptr = x.as_mut_ptr();
+    ///
+    /// unsafe {
+    ///     for i in 0..x.len() {
+    ///         *x_ptr.offset(i as isize) += 2;
+    ///     }
+    /// }
+    /// assert_eq!(x, &[3, 4, 6]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn as_mut_ptr(&mut self) -> *mut T {
+        SliceExt::as_mut_ptr(self)
+    }
+
+    /// Swaps two elements in the slice.
+    ///
+    /// # Arguments
+    ///
+    /// * a - The index of the first element
+    /// * b - The index of the second element
+    ///
+    /// # Panics
+    ///
+    /// Panics if `a` or `b` are out of bounds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = ["a", "b", "c", "d"];
+    /// v.swap(1, 3);
+    /// assert!(v == ["a", "d", "c", "b"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn swap(&mut self, a: usize, b: usize) {
+        SliceExt::swap(self, a, b)
+    }
+
+    /// Reverses the order of elements in the slice, in place.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [1, 2, 3];
+    /// v.reverse();
+    /// assert!(v == [3, 2, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn reverse(&mut self) {
+        SliceExt::reverse(self)
+    }
+
+    /// Returns an iterator over the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &[1, 2, 4];
+    /// let mut iterator = x.iter();
+    ///
+    /// assert_eq!(iterator.next(), Some(&1));
+    /// assert_eq!(iterator.next(), Some(&2));
+    /// assert_eq!(iterator.next(), Some(&4));
+    /// assert_eq!(iterator.next(), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn iter(&self) -> Iter<T> {
+        SliceExt::iter(self)
+    }
+
+    /// Returns an iterator that allows modifying each value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x = &mut [1, 2, 4];
+    /// for elem in x.iter_mut() {
+    ///     *elem += 2;
+    /// }
+    /// assert_eq!(x, &[3, 4, 6]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn iter_mut(&mut self) -> IterMut<T> {
+        SliceExt::iter_mut(self)
+    }
+
+    /// Returns an iterator over all contiguous windows of length
+    /// `size`. The windows overlap. If the slice is shorter than
+    /// `size`, the iterator returns no values.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = ['r', 'u', 's', 't'];
+    /// let mut iter = slice.windows(2);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'u']);
+    /// assert_eq!(iter.next().unwrap(), &['u', 's']);
+    /// assert_eq!(iter.next().unwrap(), &['s', 't']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If the slice is shorter than `size`:
+    ///
+    /// ```
+    /// let slice = ['f', 'o', 'o'];
+    /// let mut iter = slice.windows(4);
+    /// assert!(iter.next().is_none());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn windows(&self, size: usize) -> Windows<T> {
+        SliceExt::windows(self, size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a
+    /// time. The chunks are slices and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last chunk will
+    /// not have length `chunk_size`.
+    ///
+    /// See [`exact_chunks`] for a variant of this iterator that returns chunks
+    /// of always exactly `chunk_size` elements.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.chunks(2);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+    /// assert_eq!(iter.next().unwrap(), &['m']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// [`exact_chunks`]: #method.exact_chunks
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
+        SliceExt::chunks(self, chunk_size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a
+    /// time. The chunks are slices and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last up to `chunk_size-1`
+    /// elements will be omitted.
+    ///
+    /// Due to each chunk having exactly `chunk_size` elements, the compiler
+    /// can often optimize the resulting code better than in the case of
+    /// [`chunks`].
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(exact_chunks)]
+    ///
+    /// let slice = ['l', 'o', 'r', 'e', 'm'];
+    /// let mut iter = slice.exact_chunks(2);
+    /// assert_eq!(iter.next().unwrap(), &['l', 'o']);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// [`chunks`]: #method.chunks
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    #[inline]
+    pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
+        SliceExt::exact_chunks(self, chunk_size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a time.
+    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last chunk will not
+    /// have length `chunk_size`.
+    ///
+    /// See [`exact_chunks_mut`] for a variant of this iterator that returns chunks
+    /// of always exactly `chunk_size` elements.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = &mut [0, 0, 0, 0, 0];
+    /// let mut count = 1;
+    ///
+    /// for chunk in v.chunks_mut(2) {
+    ///     for elem in chunk.iter_mut() {
+    ///         *elem += count;
+    ///     }
+    ///     count += 1;
+    /// }
+    /// assert_eq!(v, &[1, 1, 2, 2, 3]);
+    /// ```
+    ///
+    /// [`exact_chunks_mut`]: #method.exact_chunks_mut
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
+        SliceExt::chunks_mut(self, chunk_size)
+    }
+
+    /// Returns an iterator over `chunk_size` elements of the slice at a time.
+    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
+    /// not divide the length of the slice, then the last up to `chunk_size-1`
+    /// elements will be omitted.
+    ///
+    ///
+    /// Due to each chunk having exactly `chunk_size` elements, the compiler
+    /// can often optimize the resulting code better than in the case of
+    /// [`chunks_mut`].
+    ///
+    /// # Panics
+    ///
+    /// Panics if `chunk_size` is 0.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(exact_chunks)]
+    ///
+    /// let v = &mut [0, 0, 0, 0, 0];
+    /// let mut count = 1;
+    ///
+    /// for chunk in v.exact_chunks_mut(2) {
+    ///     for elem in chunk.iter_mut() {
+    ///         *elem += count;
+    ///     }
+    ///     count += 1;
+    /// }
+    /// assert_eq!(v, &[1, 1, 2, 2, 0]);
+    /// ```
+    ///
+    /// [`chunks_mut`]: #method.chunks_mut
+    #[unstable(feature = "exact_chunks", issue = "47115")]
+    #[inline]
+    pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
+        SliceExt::exact_chunks_mut(self, chunk_size)
+    }
+
+    /// Divides one slice into two at an index.
+    ///
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [1, 2, 3, 4, 5, 6];
+    ///
+    /// {
+    ///    let (left, right) = v.split_at(0);
+    ///    assert!(left == []);
+    ///    assert!(right == [1, 2, 3, 4, 5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.split_at(2);
+    ///     assert!(left == [1, 2]);
+    ///     assert!(right == [3, 4, 5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.split_at(6);
+    ///     assert!(left == [1, 2, 3, 4, 5, 6]);
+    ///     assert!(right == []);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
+        SliceExt::split_at(self, mid)
+    }
+
+    /// Divides one mutable slice into two at an index.
+    ///
+    /// The first will contain all indices from `[0, mid)` (excluding
+    /// the index `mid` itself) and the second will contain all
+    /// indices from `[mid, len)` (excluding the index `len` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [1, 0, 3, 0, 5, 6];
+    /// // scoped to restrict the lifetime of the borrows
+    /// {
+    ///     let (left, right) = v.split_at_mut(2);
+    ///     assert!(left == [1, 0]);
+    ///     assert!(right == [3, 0, 5, 6]);
+    ///     left[1] = 2;
+    ///     right[1] = 4;
+    /// }
+    /// assert!(v == [1, 2, 3, 4, 5, 6]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
+        SliceExt::split_at_mut(self, mid)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`. The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = [10, 40, 33, 20];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
+    /// assert_eq!(iter.next().unwrap(), &[20]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If the first element is matched, an empty slice will be the first item
+    /// returned by the iterator. Similarly, if the last element in the slice
+    /// is matched, an empty slice will be the last item returned by the
+    /// iterator:
+    ///
+    /// ```
+    /// let slice = [10, 40, 33];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
+    /// assert_eq!(iter.next().unwrap(), &[]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If two matched elements are directly adjacent, an empty slice will be
+    /// present between them:
+    ///
+    /// ```
+    /// let slice = [10, 6, 33, 20];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10]);
+    /// assert_eq!(iter.next().unwrap(), &[]);
+    /// assert_eq!(iter.next().unwrap(), &[20]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split<F>(&self, pred: F) -> Split<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::split(self, pred)
+    }
+
+    /// Returns an iterator over mutable subslices separated by elements that
+    /// match `pred`. The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.split_mut(|num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(v, [1, 40, 30, 1, 60, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::split_mut(self, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, starting at the end of the slice and working backwards.
+    /// The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let slice = [11, 22, 33, 0, 44, 55];
+    /// let mut iter = slice.rsplit(|num| *num == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[44, 55]);
+    /// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
+    /// assert_eq!(iter.next(), None);
+    /// ```
+    ///
+    /// As with `split()`, if the first or last element is matched, an empty
+    /// slice will be the first (or last) item returned by the iterator.
+    ///
+    /// ```
+    /// let v = &[0, 1, 1, 2, 3, 5, 8];
+    /// let mut it = v.rsplit(|n| *n % 2 == 0);
+    /// assert_eq!(it.next().unwrap(), &[]);
+    /// assert_eq!(it.next().unwrap(), &[3, 5]);
+    /// assert_eq!(it.next().unwrap(), &[1, 1]);
+    /// assert_eq!(it.next().unwrap(), &[]);
+    /// assert_eq!(it.next(), None);
+    /// ```
+    #[stable(feature = "slice_rsplit", since = "1.27.0")]
+    #[inline]
+    pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplit(self, pred)
+    }
+
+    /// Returns an iterator over mutable subslices separated by elements that
+    /// match `pred`, starting at the end of the slice and working
+    /// backwards. The matched element is not contained in the subslices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [100, 400, 300, 200, 600, 500];
+    ///
+    /// let mut count = 0;
+    /// for group in v.rsplit_mut(|num| *num % 3 == 0) {
+    ///     count += 1;
+    ///     group[0] = count;
+    /// }
+    /// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
+    /// ```
+    ///
+    #[stable(feature = "slice_rsplit", since = "1.27.0")]
+    #[inline]
+    pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplit_mut(self, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, limited to returning at most `n` items. The matched element is
+    /// not contained in the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
+    /// `[20, 60, 50]`):
+    ///
+    /// ```
+    /// let v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.splitn(2, |num| *num % 3 == 0) {
+    ///     println!("{:?}", group);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::splitn(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred`, limited to returning at most `n` items. The matched element is
+    /// not contained in the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.splitn_mut(2, |num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(v, [1, 40, 30, 1, 60, 50]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::splitn_mut(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred` limited to returning at most `n` items. This starts at the end of
+    /// the slice and works backwards.  The matched element is not contained in
+    /// the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// Print the slice split once, starting from the end, by numbers divisible
+    /// by 3 (i.e. `[50]`, `[10, 40, 30, 20]`):
+    ///
+    /// ```
+    /// let v = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
+    ///     println!("{:?}", group);
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplitn<F>(&self, n: usize, pred: F) -> RSplitN<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplitn(self, n, pred)
+    }
+
+    /// Returns an iterator over subslices separated by elements that match
+    /// `pred` limited to returning at most `n` items. This starts at the end of
+    /// the slice and works backwards. The matched element is not contained in
+    /// the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut s = [10, 40, 30, 20, 60, 50];
+    ///
+    /// for group in s.rsplitn_mut(2, |num| *num % 3 == 0) {
+    ///     group[0] = 1;
+    /// }
+    /// assert_eq!(s, [1, 40, 30, 20, 60, 1]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplitn_mut<F>(&mut self, n: usize, pred: F) -> RSplitNMut<T, F>
+        where F: FnMut(&T) -> bool
+    {
+        SliceExt::rsplitn_mut(self, n, pred)
+    }
+
+    /// Returns `true` if the slice contains an element with the given value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.contains(&30));
+    /// assert!(!v.contains(&50));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn contains(&self, x: &T) -> bool
+        where T: PartialEq
+    {
+        SliceExt::contains(self, x)
+    }
+
+    /// Returns `true` if `needle` is a prefix of the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.starts_with(&[10]));
+    /// assert!(v.starts_with(&[10, 40]));
+    /// assert!(!v.starts_with(&[50]));
+    /// assert!(!v.starts_with(&[10, 50]));
+    /// ```
+    ///
+    /// Always returns `true` if `needle` is an empty slice:
+    ///
+    /// ```
+    /// let v = &[10, 40, 30];
+    /// assert!(v.starts_with(&[]));
+    /// let v: &[u8] = &[];
+    /// assert!(v.starts_with(&[]));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn starts_with(&self, needle: &[T]) -> bool
+        where T: PartialEq
+    {
+        SliceExt::starts_with(self, needle)
+    }
+
+    /// Returns `true` if `needle` is a suffix of the slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = [10, 40, 30];
+    /// assert!(v.ends_with(&[30]));
+    /// assert!(v.ends_with(&[40, 30]));
+    /// assert!(!v.ends_with(&[50]));
+    /// assert!(!v.ends_with(&[50, 30]));
+    /// ```
+    ///
+    /// Always returns `true` if `needle` is an empty slice:
+    ///
+    /// ```
+    /// let v = &[10, 40, 30];
+    /// assert!(v.ends_with(&[]));
+    /// let v: &[u8] = &[];
+    /// assert!(v.ends_with(&[]));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn ends_with(&self, needle: &[T]) -> bool
+        where T: PartialEq
+    {
+        SliceExt::ends_with(self, needle)
+    }
+
+    /// Binary searches this sorted slice for a given element.
+    ///
+    /// If the value is found then `Ok` is returned, containing the
+    /// index of the matching element; if the value is not found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    ///
+    /// assert_eq!(s.binary_search(&13),  Ok(9));
+    /// assert_eq!(s.binary_search(&4),   Err(7));
+    /// assert_eq!(s.binary_search(&100), Err(13));
+    /// let r = s.binary_search(&1);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn binary_search(&self, x: &T) -> Result<usize, usize>
+        where T: Ord
+    {
+        SliceExt::binary_search(self, x)
+    }
+
+    /// Binary searches this sorted slice with a comparator function.
+    ///
+    /// The comparator function should implement an order consistent
+    /// with the sort order of the underlying slice, returning an
+    /// order code that indicates whether its argument is `Less`,
+    /// `Equal` or `Greater` the desired target.
+    ///
+    /// If a matching value is found then returns `Ok`, containing
+    /// the index for the matched element; if no match is found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    ///
+    /// let seek = 13;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
+    /// let seek = 4;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
+    /// let seek = 100;
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
+    /// let seek = 1;
+    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
+        where F: FnMut(&'a T) -> Ordering
+    {
+        SliceExt::binary_search_by(self, f)
+    }
+
+    /// Binary searches this sorted slice with a key extraction function.
+    ///
+    /// Assumes that the slice is sorted by the key, for instance with
+    /// [`sort_by_key`] using the same key extraction function.
+    ///
+    /// If a matching value is found then returns `Ok`, containing the
+    /// index for the matched element; if no match is found then `Err`
+    /// is returned, containing the index where a matching element could
+    /// be inserted while maintaining sorted order.
+    ///
+    /// [`sort_by_key`]: #method.sort_by_key
+    ///
+    /// # Examples
+    ///
+    /// Looks up a series of four elements in a slice of pairs sorted by
+    /// their second elements. The first is found, with a uniquely
+    /// determined position; the second and third are not found; the
+    /// fourth could match any position in `[1, 4]`.
+    ///
+    /// ```
+    /// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
+    ///          (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
+    ///          (1, 21), (2, 34), (4, 55)];
+    ///
+    /// assert_eq!(s.binary_search_by_key(&13, |&(a,b)| b),  Ok(9));
+    /// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b),   Err(7));
+    /// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
+    /// let r = s.binary_search_by_key(&1, |&(a,b)| b);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
+    #[inline]
+    pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
+        where F: FnMut(&'a T) -> B,
+              B: Ord
+    {
+        SliceExt::binary_search_by_key(self, b, f)
+    }
+
+    /// Sorts the slice, but may not preserve the order of equal elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(n log n)` worst-case.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
+    /// which combines the fast average case of randomized quicksort with the fast worst case of
+    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
+    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
+    /// deterministic behavior.
+    ///
+    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
+    /// slice consists of several concatenated sorted sequences.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [-5, 4, 1, -3, 2];
+    ///
+    /// v.sort_unstable();
+    /// assert!(v == [-5, -3, 1, 2, 4]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
+    #[inline]
+    pub fn sort_unstable(&mut self)
+        where T: Ord
+    {
+        SliceExt::sort_unstable(self);
+    }
+
+    /// Sorts the slice with a comparator function, but may not preserve the order of equal
+    /// elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(n log n)` worst-case.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
+    /// which combines the fast average case of randomized quicksort with the fast worst case of
+    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
+    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
+    /// deterministic behavior.
+    ///
+    /// It is typically faster than stable sorting, except in a few special cases, e.g. when the
+    /// slice consists of several concatenated sorted sequences.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [5, 4, 1, 3, 2];
+    /// v.sort_unstable_by(|a, b| a.cmp(b));
+    /// assert!(v == [1, 2, 3, 4, 5]);
+    ///
+    /// // reverse sorting
+    /// v.sort_unstable_by(|a, b| b.cmp(a));
+    /// assert!(v == [5, 4, 3, 2, 1]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
+    #[inline]
+    pub fn sort_unstable_by<F>(&mut self, compare: F)
+        where F: FnMut(&T, &T) -> Ordering
+    {
+        SliceExt::sort_unstable_by(self, compare);
+    }
+
+    /// Sorts the slice with a key extraction function, but may not preserve the order of equal
+    /// elements.
+    ///
+    /// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
+    /// and `O(m n log(m n))` worst-case, where the key function is `O(m)`.
+    ///
+    /// # Current implementation
+    ///
+    /// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
+    /// which combines the fast average case of randomized quicksort with the fast worst case of
+    /// heapsort, while achieving linear time on slices with certain patterns. It uses some
+    /// randomization to avoid degenerate cases, but with a fixed seed to always provide
+    /// deterministic behavior.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = [-5i32, 4, 1, -3, 2];
+    ///
+    /// v.sort_unstable_by_key(|k| k.abs());
+    /// assert!(v == [1, 2, -3, 4, -5]);
+    /// ```
+    ///
+    /// [pdqsort]: https://github.com/orlp/pdqsort
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
+    #[inline]
+    pub fn sort_unstable_by_key<K, F>(&mut self, f: F)
+        where F: FnMut(&T) -> K, K: Ord
+    {
+        SliceExt::sort_unstable_by_key(self, f);
+    }
+
+    /// Rotates the slice in-place such that the first `mid` elements of the
+    /// slice move to the end while the last `self.len() - mid` elements move to
+    /// the front. After calling `rotate_left`, the element previously at index
+    /// `mid` will become the first element in the slice.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `mid` is greater than the length of the
+    /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op
+    /// rotation.
+    ///
+    /// # Complexity
+    ///
+    /// Takes linear (in `self.len()`) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a.rotate_left(2);
+    /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
+    /// ```
+    ///
+    /// Rotating a subslice:
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a[1..5].rotate_left(1);
+    /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
+   /// ```
+    #[stable(feature = "slice_rotate", since = "1.26.0")]
+    pub fn rotate_left(&mut self, mid: usize) {
+        SliceExt::rotate_left(self, mid);
+    }
+
+    /// Rotates the slice in-place such that the first `self.len() - k`
+    /// elements of the slice move to the end while the last `k` elements move
+    /// to the front. After calling `rotate_right`, the element previously at
+    /// index `self.len() - k` will become the first element in the slice.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `k` is greater than the length of the
+    /// slice. Note that `k == self.len()` does _not_ panic and is a no-op
+    /// rotation.
+    ///
+    /// # Complexity
+    ///
+    /// Takes linear (in `self.len()`) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a.rotate_right(2);
+    /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
+    /// ```
+    ///
+    /// Rotate a subslice:
+    ///
+    /// ```
+    /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
+    /// a[1..5].rotate_right(1);
+    /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
+    /// ```
+    #[stable(feature = "slice_rotate", since = "1.26.0")]
+    pub fn rotate_right(&mut self, k: usize) {
+        SliceExt::rotate_right(self, k);
+    }
+
+    /// Copies the elements from `src` into `self`.
+    ///
+    /// The length of `src` must be the same as `self`.
+    ///
+    /// If `src` implements `Copy`, it can be more performant to use
+    /// [`copy_from_slice`].
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Examples
+    ///
+    /// Cloning two elements from a slice into another:
+    ///
+    /// ```
+    /// let src = [1, 2, 3, 4];
+    /// let mut dst = [0, 0];
+    ///
+    /// dst.clone_from_slice(&src[2..]);
+    ///
+    /// assert_eq!(src, [1, 2, 3, 4]);
+    /// assert_eq!(dst, [3, 4]);
+    /// ```
+    ///
+    /// Rust enforces that there can only be one mutable reference with no
+    /// immutable references to a particular piece of data in a particular
+    /// scope. Because of this, attempting to use `clone_from_slice` on a
+    /// single slice will result in a compile failure:
+    ///
+    /// ```compile_fail
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// slice[..2].clone_from_slice(&slice[3..]); // compile fail!
+    /// ```
+    ///
+    /// To work around this, we can use [`split_at_mut`] to create two distinct
+    /// sub-slices from a slice:
+    ///
+    /// ```
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// {
+    ///     let (left, right) = slice.split_at_mut(2);
+    ///     left.clone_from_slice(&right[1..]);
+    /// }
+    ///
+    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
+    /// ```
+    ///
+    /// [`copy_from_slice`]: #method.copy_from_slice
+    /// [`split_at_mut`]: #method.split_at_mut
+    #[stable(feature = "clone_from_slice", since = "1.7.0")]
+    pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
+        SliceExt::clone_from_slice(self, src)
+    }
+
+    /// Copies all elements from `src` into `self`, using a memcpy.
+    ///
+    /// The length of `src` must be the same as `self`.
+    ///
+    /// If `src` does not implement `Copy`, use [`clone_from_slice`].
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Examples
+    ///
+    /// Copying two elements from a slice into another:
+    ///
+    /// ```
+    /// let src = [1, 2, 3, 4];
+    /// let mut dst = [0, 0];
+    ///
+    /// dst.copy_from_slice(&src[2..]);
+    ///
+    /// assert_eq!(src, [1, 2, 3, 4]);
+    /// assert_eq!(dst, [3, 4]);
+    /// ```
+    ///
+    /// Rust enforces that there can only be one mutable reference with no
+    /// immutable references to a particular piece of data in a particular
+    /// scope. Because of this, attempting to use `copy_from_slice` on a
+    /// single slice will result in a compile failure:
+    ///
+    /// ```compile_fail
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// slice[..2].copy_from_slice(&slice[3..]); // compile fail!
+    /// ```
+    ///
+    /// To work around this, we can use [`split_at_mut`] to create two distinct
+    /// sub-slices from a slice:
+    ///
+    /// ```
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// {
+    ///     let (left, right) = slice.split_at_mut(2);
+    ///     left.copy_from_slice(&right[1..]);
+    /// }
+    ///
+    /// assert_eq!(slice, [4, 5, 3, 4, 5]);
+    /// ```
+    ///
+    /// [`clone_from_slice`]: #method.clone_from_slice
+    /// [`split_at_mut`]: #method.split_at_mut
+    #[stable(feature = "copy_from_slice", since = "1.9.0")]
+    pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
+        SliceExt::copy_from_slice(self, src)
+    }
+
+    /// Swaps all elements in `self` with those in `other`.
+    ///
+    /// The length of `other` must be the same as `self`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Example
+    ///
+    /// Swapping two elements across slices:
+    ///
+    /// ```
+    /// let mut slice1 = [0, 0];
+    /// let mut slice2 = [1, 2, 3, 4];
+    ///
+    /// slice1.swap_with_slice(&mut slice2[2..]);
+    ///
+    /// assert_eq!(slice1, [3, 4]);
+    /// assert_eq!(slice2, [1, 2, 0, 0]);
+    /// ```
+    ///
+    /// Rust enforces that there can only be one mutable reference to a
+    /// particular piece of data in a particular scope. Because of this,
+    /// attempting to use `swap_with_slice` on a single slice will result in
+    /// a compile failure:
+    ///
+    /// ```compile_fail
+    /// let mut slice = [1, 2, 3, 4, 5];
+    /// slice[..2].swap_with_slice(&mut slice[3..]); // compile fail!
+    /// ```
+    ///
+    /// To work around this, we can use [`split_at_mut`] to create two distinct
+    /// mutable sub-slices from a slice:
+    ///
+    /// ```
+    /// let mut slice = [1, 2, 3, 4, 5];
+    ///
+    /// {
+    ///     let (left, right) = slice.split_at_mut(2);
+    ///     left.swap_with_slice(&mut right[1..]);
+    /// }
+    ///
+    /// assert_eq!(slice, [4, 5, 3, 1, 2]);
+    /// ```
+    ///
+    /// [`split_at_mut`]: #method.split_at_mut
+    #[stable(feature = "swap_with_slice", since = "1.27.0")]
+    pub fn swap_with_slice(&mut self, other: &mut [T]) {
+        SliceExt::swap_with_slice(self, other)
+    }
+}}
+
+#[lang = "slice"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl<T> [T] {
+    slice_core_methods!();
+}
+
+// FIXME: remove (inline) this macro
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_slice_ext", issue = "32110")]
+macro_rules! slice_u8_core_methods { () => {
+    /// Checks if all bytes in this slice are within the ASCII range.
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        self.iter().all(|b| b.is_ascii())
+    }
+
+    /// Checks that two slices are an ASCII case-insensitive match.
+    ///
+    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
+    /// but without allocating and copying temporaries.
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
+        self.len() == other.len() &&
+            self.iter().zip(other).all(|(a, b)| {
+                a.eq_ignore_ascii_case(b)
+            })
+    }
+
+    /// Converts this slice to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        for byte in self {
+            byte.make_ascii_uppercase();
+        }
+    }
+
+    /// Converts this slice to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        for byte in self {
+            byte.make_ascii_lowercase();
+        }
+    }
+}}
+
+#[lang = "slice_u8"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl [u8] {
+    slice_u8_core_methods!();
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
 impl<T, I> ops::Index<I> for [T]
index f1fe23092de93924f2c1549758bcb84462cfc08b..b39d9feb35b7e3294be2b3c50a14afe7ddf72c39 100644 (file)
@@ -2100,31 +2100,28 @@ unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
         fn index(self, slice: &str) -> &Self::Output {
             assert!(self.end != usize::max_value(),
                 "attempted to index str up to maximum usize");
-            let end = self.end + 1;
-            self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
+            (..self.end+1).index(slice)
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
             assert!(self.end != usize::max_value(),
                 "attempted to index str up to maximum usize");
-            if slice.is_char_boundary(self.end) {
-                unsafe { self.get_unchecked_mut(slice) }
-            } else {
-                super::slice_error_fail(slice, 0, self.end + 1)
-            }
+            (..self.end+1).index_mut(slice)
         }
     }
 
 }
 
-
+public_in_stage0! {
+{
 /// Methods for string slices
 #[allow(missing_docs)]
 #[doc(hidden)]
 #[unstable(feature = "core_str_ext",
            reason = "stable interface provided by `impl str` in later crates",
            issue = "32110")]
-pub trait StrExt {
+}
+trait StrExt {
     // NB there are no docs here are they're all located on the StrExt trait in
     // liballoc, not here.
 
@@ -2218,17 +2215,13 @@ fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
     fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
     #[stable(feature = "split_whitespace", since = "1.1.0")]
     fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
-    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
-    fn is_whitespace(&self) -> bool;
-    #[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
-    fn is_alphanumeric(&self) -> bool;
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim(&self) -> &str;
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_left(&self) -> &str;
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_right(&self) -> &str;
-}
+}}
 
 // truncate `&str` to length at most equal to `max`
 // return `true` if it were truncated, and the new str.
@@ -2554,16 +2547,6 @@ fn split_whitespace(&self) -> SplitWhitespace {
         SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
     }
 
-    #[inline]
-    fn is_whitespace(&self) -> bool {
-        self.chars().all(|c| c.is_whitespace())
-    }
-
-    #[inline]
-    fn is_alphanumeric(&self) -> bool {
-        self.chars().all(|c| c.is_alphanumeric())
-    }
-
     #[inline]
     fn trim(&self) -> &str {
         self.trim_matches(|c: char| c.is_whitespace())
@@ -2580,88 +2563,1836 @@ fn trim_right(&self) -> &str {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRef<[u8]> for str {
+// FIXME: remove (inline) this macro and the SliceExt trait
+// when updating to a bootstrap compiler that has the new lang items.
+#[cfg_attr(stage0, macro_export)]
+#[unstable(feature = "core_str_ext", issue = "32110")]
+macro_rules! str_core_methods { () => {
+    /// Returns the length of `self`.
+    ///
+    /// This length is in bytes, not [`char`]s or graphemes. In other words,
+    /// it may not be what a human considers the length of the string.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let len = "foo".len();
+    /// assert_eq!(3, len);
+    ///
+    /// let len = "ƒoo".len(); // fancy f!
+    /// assert_eq!(4, len);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    fn as_ref(&self) -> &[u8] {
-        self.as_bytes()
+    pub fn len(&self) -> usize {
+        StrExt::len(self)
     }
-}
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Default for &'a str {
-    /// Creates an empty str
-    fn default() -> &'a str { "" }
-}
+    /// Returns `true` if `self` has a length of zero bytes.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "";
+    /// assert!(s.is_empty());
+    ///
+    /// let s = "not empty";
+    /// assert!(!s.is_empty());
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn is_empty(&self) -> bool {
+        StrExt::is_empty(self)
+    }
 
-/// An iterator over the non-whitespace substrings of a string,
-/// separated by any amount of whitespace.
-///
-/// This struct is created by the [`split_whitespace`] method on [`str`].
-/// See its documentation for more.
-///
-/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
-/// [`str`]: ../../std/primitive.str.html
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-#[derive(Clone, Debug)]
-pub struct SplitWhitespace<'a> {
-    inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
-}
+    /// Checks that `index`-th byte lies at the start and/or end of a
+    /// UTF-8 code point sequence.
+    ///
+    /// The start and end of the string (when `index == self.len()`) are
+    /// considered to be
+    /// boundaries.
+    ///
+    /// Returns `false` if `index` is greater than `self.len()`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// assert!(s.is_char_boundary(0));
+    /// // start of `老`
+    /// assert!(s.is_char_boundary(6));
+    /// assert!(s.is_char_boundary(s.len()));
+    ///
+    /// // second byte of `ö`
+    /// assert!(!s.is_char_boundary(2));
+    ///
+    /// // third byte of `老`
+    /// assert!(!s.is_char_boundary(8));
+    /// ```
+    #[stable(feature = "is_char_boundary", since = "1.9.0")]
+    #[inline]
+    pub fn is_char_boundary(&self, index: usize) -> bool {
+        StrExt::is_char_boundary(self, index)
+    }
 
-#[derive(Clone)]
-struct IsWhitespace;
+    /// Converts a string slice to a byte slice. To convert the byte slice back
+    /// into a string slice, use the [`str::from_utf8`] function.
+    ///
+    /// [`str::from_utf8`]: ./str/fn.from_utf8.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bytes = "bors".as_bytes();
+    /// assert_eq!(b"bors", bytes);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline(always)]
+    pub fn as_bytes(&self) -> &[u8] {
+        StrExt::as_bytes(self)
+    }
 
-impl FnOnce<(char, )> for IsWhitespace {
-    type Output = bool;
+    /// Converts a mutable string slice to a mutable byte slice. To convert the
+    /// mutable byte slice back into a mutable string slice, use the
+    /// [`str::from_utf8_mut`] function.
+    ///
+    /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut s = String::from("Hello");
+    /// let bytes = unsafe { s.as_bytes_mut() };
+    ///
+    /// assert_eq!(b"Hello", bytes);
+    /// ```
+    ///
+    /// Mutability:
+    ///
+    /// ```
+    /// let mut s = String::from("🗻∈🌏");
+    ///
+    /// unsafe {
+    ///     let bytes = s.as_bytes_mut();
+    ///
+    ///     bytes[0] = 0xF0;
+    ///     bytes[1] = 0x9F;
+    ///     bytes[2] = 0x8D;
+    ///     bytes[3] = 0x94;
+    /// }
+    ///
+    /// assert_eq!("🍔∈🌏", s);
+    /// ```
+    #[stable(feature = "str_mut_extras", since = "1.20.0")]
+    #[inline(always)]
+    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
+        StrExt::as_bytes_mut(self)
+    }
 
+    /// Converts a string slice to a raw pointer.
+    ///
+    /// As string slices are a slice of bytes, the raw pointer points to a
+    /// [`u8`]. This pointer will be pointing to the first byte of the string
+    /// slice.
+    ///
+    /// [`u8`]: primitive.u8.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "Hello";
+    /// let ptr = s.as_ptr();
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
-        self.call_mut(arg)
+    pub fn as_ptr(&self) -> *const u8 {
+        StrExt::as_ptr(self)
     }
-}
 
-impl FnMut<(char, )> for IsWhitespace {
+    /// Returns a subslice of `str`.
+    ///
+    /// This is the non-panicking alternative to indexing the `str`. Returns
+    /// [`None`] whenever equivalent indexing operation would panic.
+    ///
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = String::from("🗻∈🌏");
+    ///
+    /// assert_eq!(Some("🗻"), v.get(0..4));
+    ///
+    /// // indices not on UTF-8 sequence boundaries
+    /// assert!(v.get(1..).is_none());
+    /// assert!(v.get(..8).is_none());
+    ///
+    /// // out of bounds
+    /// assert!(v.get(..42).is_none());
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
-        arg.0.is_whitespace()
+    pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
+        StrExt::get(self, i)
     }
-}
-
-#[derive(Clone)]
-struct IsNotEmpty;
 
-impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
-    type Output = bool;
+    /// Returns a mutable subslice of `str`.
+    ///
+    /// This is the non-panicking alternative to indexing the `str`. Returns
+    /// [`None`] whenever equivalent indexing operation would panic.
+    ///
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = String::from("hello");
+    /// // correct length
+    /// assert!(v.get_mut(0..5).is_some());
+    /// // out of bounds
+    /// assert!(v.get_mut(..42).is_none());
+    /// assert_eq!(Some("he"), v.get_mut(0..2).map(|v| &*v));
+    ///
+    /// assert_eq!("hello", v);
+    /// {
+    ///     let s = v.get_mut(0..2);
+    ///     let s = s.map(|s| {
+    ///         s.make_ascii_uppercase();
+    ///         &*s
+    ///     });
+    ///     assert_eq!(Some("HE"), s);
+    /// }
+    /// assert_eq!("HEllo", v);
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
+    #[inline]
+    pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
+        StrExt::get_mut(self, i)
+    }
 
+    /// Returns a unchecked subslice of `str`.
+    ///
+    /// This is the unchecked alternative to indexing the `str`.
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that these preconditions are
+    /// satisfied:
+    ///
+    /// * The starting index must come before the ending index;
+    /// * Indexes must be within bounds of the original slice;
+    /// * Indexes must lie on UTF-8 sequence boundaries.
+    ///
+    /// Failing that, the returned string slice may reference invalid memory or
+    /// violate the invariants communicated by the `str` type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = "🗻∈🌏";
+    /// unsafe {
+    ///     assert_eq!("🗻", v.get_unchecked(0..4));
+    ///     assert_eq!("∈", v.get_unchecked(4..7));
+    ///     assert_eq!("🌏", v.get_unchecked(7..11));
+    /// }
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     #[inline]
-    extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
-        self.call_mut(arg)
+    pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
+        StrExt::get_unchecked(self, i)
     }
-}
 
-impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
+    /// Returns a mutable, unchecked subslice of `str`.
+    ///
+    /// This is the unchecked alternative to indexing the `str`.
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that these preconditions are
+    /// satisfied:
+    ///
+    /// * The starting index must come before the ending index;
+    /// * Indexes must be within bounds of the original slice;
+    /// * Indexes must lie on UTF-8 sequence boundaries.
+    ///
+    /// Failing that, the returned string slice may reference invalid memory or
+    /// violate the invariants communicated by the `str` type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut v = String::from("🗻∈🌏");
+    /// unsafe {
+    ///     assert_eq!("🗻", v.get_unchecked_mut(0..4));
+    ///     assert_eq!("∈", v.get_unchecked_mut(4..7));
+    ///     assert_eq!("🌏", v.get_unchecked_mut(7..11));
+    /// }
+    /// ```
+    #[stable(feature = "str_checked_slicing", since = "1.20.0")]
     #[inline]
-    extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
-        !arg.0.is_empty()
+    pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
+        StrExt::get_unchecked_mut(self, i)
     }
-}
 
+    /// Creates a string slice from another string slice, bypassing safety
+    /// checks.
+    ///
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`str`] and [`Index`].
+    ///
+    /// [`str`]: primitive.str.html
+    /// [`Index`]: ops/trait.Index.html
+    ///
+    /// This new slice goes from `begin` to `end`, including `begin` but
+    /// excluding `end`.
+    ///
+    /// To get a mutable string slice instead, see the
+    /// [`slice_mut_unchecked`] method.
+    ///
+    /// [`slice_mut_unchecked`]: #method.slice_mut_unchecked
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that three preconditions are
+    /// satisfied:
+    ///
+    /// * `begin` must come before `end`.
+    /// * `begin` and `end` must be byte positions within the string slice.
+    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// unsafe {
+    ///     assert_eq!("Löwe 老虎 Léopard", s.slice_unchecked(0, 21));
+    /// }
+    ///
+    /// let s = "Hello, world!";
+    ///
+    /// unsafe {
+    ///     assert_eq!("world", s.slice_unchecked(7, 12));
+    /// }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
+        StrExt::slice_unchecked(self, begin, end)
+    }
 
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-impl<'a> Iterator for SplitWhitespace<'a> {
-    type Item = &'a str;
+    /// Creates a string slice from another string slice, bypassing safety
+    /// checks.
+    /// This is generally not recommended, use with caution! For a safe
+    /// alternative see [`str`] and [`IndexMut`].
+    ///
+    /// [`str`]: primitive.str.html
+    /// [`IndexMut`]: ops/trait.IndexMut.html
+    ///
+    /// This new slice goes from `begin` to `end`, including `begin` but
+    /// excluding `end`.
+    ///
+    /// To get an immutable string slice instead, see the
+    /// [`slice_unchecked`] method.
+    ///
+    /// [`slice_unchecked`]: #method.slice_unchecked
+    ///
+    /// # Safety
+    ///
+    /// Callers of this function are responsible that three preconditions are
+    /// satisfied:
+    ///
+    /// * `begin` must come before `end`.
+    /// * `begin` and `end` must be byte positions within the string slice.
+    /// * `begin` and `end` must lie on UTF-8 sequence boundaries.
+    #[stable(feature = "str_slice_mut", since = "1.5.0")]
+    #[inline]
+    pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
+        StrExt::slice_mut_unchecked(self, begin, end)
+    }
 
-    fn next(&mut self) -> Option<&'a str> {
-        self.inner.next()
+    /// Divide one string slice into two at an index.
+    ///
+    /// The argument, `mid`, should be a byte offset from the start of the
+    /// string. It must also be on the boundary of a UTF-8 code point.
+    ///
+    /// The two slices returned go from the start of the string slice to `mid`,
+    /// and from `mid` to the end of the string slice.
+    ///
+    /// To get mutable string slices instead, see the [`split_at_mut`]
+    /// method.
+    ///
+    /// [`split_at_mut`]: #method.split_at_mut
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
+    /// beyond the last code point of the string slice.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "Per Martin-Löf";
+    ///
+    /// let (first, last) = s.split_at(3);
+    ///
+    /// assert_eq!("Per", first);
+    /// assert_eq!(" Martin-Löf", last);
+    /// ```
+    #[inline]
+    #[stable(feature = "str_split_at", since = "1.4.0")]
+    pub fn split_at(&self, mid: usize) -> (&str, &str) {
+        StrExt::split_at(self, mid)
     }
-}
 
-#[stable(feature = "split_whitespace", since = "1.1.0")]
-impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
-    fn next_back(&mut self) -> Option<&'a str> {
-        self.inner.next_back()
+    /// Divide one mutable string slice into two at an index.
+    ///
+    /// The argument, `mid`, should be a byte offset from the start of the
+    /// string. It must also be on the boundary of a UTF-8 code point.
+    ///
+    /// The two slices returned go from the start of the string slice to `mid`,
+    /// and from `mid` to the end of the string slice.
+    ///
+    /// To get immutable string slices instead, see the [`split_at`] method.
+    ///
+    /// [`split_at`]: #method.split_at
+    ///
+    /// # Panics
+    ///
+    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
+    /// beyond the last code point of the string slice.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut s = "Per Martin-Löf".to_string();
+    /// {
+    ///     let (first, last) = s.split_at_mut(3);
+    ///     first.make_ascii_uppercase();
+    ///     assert_eq!("PER", first);
+    ///     assert_eq!(" Martin-Löf", last);
+    /// }
+    /// assert_eq!("PER Martin-Löf", s);
+    /// ```
+    #[inline]
+    #[stable(feature = "str_split_at", since = "1.4.0")]
+    pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
+        StrExt::split_at_mut(self, mid)
     }
-}
 
-#[stable(feature = "fused", since = "1.26.0")]
-impl<'a> FusedIterator for SplitWhitespace<'a> {}
+    /// Returns an iterator over the [`char`]s of a string slice.
+    ///
+    /// As a string slice consists of valid UTF-8, we can iterate through a
+    /// string slice by [`char`]. This method returns such an iterator.
+    ///
+    /// It's important to remember that [`char`] represents a Unicode Scalar
+    /// Value, and may not match your idea of what a 'character' is. Iteration
+    /// over grapheme clusters may be what you actually want.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let word = "goodbye";
+    ///
+    /// let count = word.chars().count();
+    /// assert_eq!(7, count);
+    ///
+    /// let mut chars = word.chars();
+    ///
+    /// assert_eq!(Some('g'), chars.next());
+    /// assert_eq!(Some('o'), chars.next());
+    /// assert_eq!(Some('o'), chars.next());
+    /// assert_eq!(Some('d'), chars.next());
+    /// assert_eq!(Some('b'), chars.next());
+    /// assert_eq!(Some('y'), chars.next());
+    /// assert_eq!(Some('e'), chars.next());
+    ///
+    /// assert_eq!(None, chars.next());
+    /// ```
+    ///
+    /// Remember, [`char`]s may not match your human intuition about characters:
+    ///
+    /// ```
+    /// let y = "y̆";
+    ///
+    /// let mut chars = y.chars();
+    ///
+    /// assert_eq!(Some('y'), chars.next()); // not 'y̆'
+    /// assert_eq!(Some('\u{0306}'), chars.next());
+    ///
+    /// assert_eq!(None, chars.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn chars(&self) -> Chars {
+        StrExt::chars(self)
+    }
+    /// Returns an iterator over the [`char`]s of a string slice, and their
+    /// positions.
+    ///
+    /// As a string slice consists of valid UTF-8, we can iterate through a
+    /// string slice by [`char`]. This method returns an iterator of both
+    /// these [`char`]s, as well as their byte positions.
+    ///
+    /// The iterator yields tuples. The position is first, the [`char`] is
+    /// second.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let word = "goodbye";
+    ///
+    /// let count = word.char_indices().count();
+    /// assert_eq!(7, count);
+    ///
+    /// let mut char_indices = word.char_indices();
+    ///
+    /// assert_eq!(Some((0, 'g')), char_indices.next());
+    /// assert_eq!(Some((1, 'o')), char_indices.next());
+    /// assert_eq!(Some((2, 'o')), char_indices.next());
+    /// assert_eq!(Some((3, 'd')), char_indices.next());
+    /// assert_eq!(Some((4, 'b')), char_indices.next());
+    /// assert_eq!(Some((5, 'y')), char_indices.next());
+    /// assert_eq!(Some((6, 'e')), char_indices.next());
+    ///
+    /// assert_eq!(None, char_indices.next());
+    /// ```
+    ///
+    /// Remember, [`char`]s may not match your human intuition about characters:
+    ///
+    /// ```
+    /// let yes = "y̆es";
+    ///
+    /// let mut char_indices = yes.char_indices();
+    ///
+    /// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
+    /// assert_eq!(Some((1, '\u{0306}')), char_indices.next());
+    ///
+    /// // note the 3 here - the last character took up two bytes
+    /// assert_eq!(Some((3, 'e')), char_indices.next());
+    /// assert_eq!(Some((4, 's')), char_indices.next());
+    ///
+    /// assert_eq!(None, char_indices.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn char_indices(&self) -> CharIndices {
+        StrExt::char_indices(self)
+    }
+
+    /// An iterator over the bytes of a string slice.
+    ///
+    /// As a string slice consists of a sequence of bytes, we can iterate
+    /// through a string slice by byte. This method returns such an iterator.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut bytes = "bors".bytes();
+    ///
+    /// assert_eq!(Some(b'b'), bytes.next());
+    /// assert_eq!(Some(b'o'), bytes.next());
+    /// assert_eq!(Some(b'r'), bytes.next());
+    /// assert_eq!(Some(b's'), bytes.next());
+    ///
+    /// assert_eq!(None, bytes.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn bytes(&self) -> Bytes {
+        StrExt::bytes(self)
+    }
+
+    /// Split a string slice by whitespace.
+    ///
+    /// The iterator returned will return string slices that are sub-slices of
+    /// the original string slice, separated by any amount of whitespace.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let mut iter = "A few words".split_whitespace();
+    ///
+    /// assert_eq!(Some("A"), iter.next());
+    /// assert_eq!(Some("few"), iter.next());
+    /// assert_eq!(Some("words"), iter.next());
+    ///
+    /// assert_eq!(None, iter.next());
+    /// ```
+    ///
+    /// All kinds of whitespace are considered:
+    ///
+    /// ```
+    /// let mut iter = " Mary   had\ta\u{2009}little  \n\t lamb".split_whitespace();
+    /// assert_eq!(Some("Mary"), iter.next());
+    /// assert_eq!(Some("had"), iter.next());
+    /// assert_eq!(Some("a"), iter.next());
+    /// assert_eq!(Some("little"), iter.next());
+    /// assert_eq!(Some("lamb"), iter.next());
+    ///
+    /// assert_eq!(None, iter.next());
+    /// ```
+    #[stable(feature = "split_whitespace", since = "1.1.0")]
+    #[inline]
+    pub fn split_whitespace(&self) -> SplitWhitespace {
+        StrExt::split_whitespace(self)
+    }
+
+    /// An iterator over the lines of a string, as string slices.
+    ///
+    /// Lines are ended with either a newline (`\n`) or a carriage return with
+    /// a line feed (`\r\n`).
+    ///
+    /// The final line ending is optional.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let text = "foo\r\nbar\n\nbaz\n";
+    /// let mut lines = text.lines();
+    ///
+    /// assert_eq!(Some("foo"), lines.next());
+    /// assert_eq!(Some("bar"), lines.next());
+    /// assert_eq!(Some(""), lines.next());
+    /// assert_eq!(Some("baz"), lines.next());
+    ///
+    /// assert_eq!(None, lines.next());
+    /// ```
+    ///
+    /// The final line ending isn't required:
+    ///
+    /// ```
+    /// let text = "foo\nbar\n\r\nbaz";
+    /// let mut lines = text.lines();
+    ///
+    /// assert_eq!(Some("foo"), lines.next());
+    /// assert_eq!(Some("bar"), lines.next());
+    /// assert_eq!(Some(""), lines.next());
+    /// assert_eq!(Some("baz"), lines.next());
+    ///
+    /// assert_eq!(None, lines.next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn lines(&self) -> Lines {
+        StrExt::lines(self)
+    }
+
+    /// An iterator over the lines of a string.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.4.0", reason = "use lines() instead now")]
+    #[inline]
+    #[allow(deprecated)]
+    pub fn lines_any(&self) -> LinesAny {
+        StrExt::lines_any(self)
+    }
+
+    /// Returns an iterator of `u16` over the string encoded as UTF-16.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let text = "Zażółć gęślą jaźń";
+    ///
+    /// let utf8_len = text.len();
+    /// let utf16_len = text.encode_utf16().count();
+    ///
+    /// assert!(utf16_len <= utf8_len);
+    /// ```
+    #[stable(feature = "encode_utf16", since = "1.8.0")]
+    pub fn encode_utf16(&self) -> EncodeUtf16 {
+        EncodeUtf16::new(self)
+    }
+
+    /// Returns `true` if the given pattern matches a sub-slice of
+    /// this string slice.
+    ///
+    /// Returns `false` if it does not.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bananas = "bananas";
+    ///
+    /// assert!(bananas.contains("nana"));
+    /// assert!(!bananas.contains("apples"));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        StrExt::contains(self, pat)
+    }
+
+    /// Returns `true` if the given pattern matches a prefix of this
+    /// string slice.
+    ///
+    /// Returns `false` if it does not.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bananas = "bananas";
+    ///
+    /// assert!(bananas.starts_with("bana"));
+    /// assert!(!bananas.starts_with("nana"));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        StrExt::starts_with(self, pat)
+    }
+
+    /// Returns `true` if the given pattern matches a suffix of this
+    /// string slice.
+    ///
+    /// Returns `false` if it does not.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let bananas = "bananas";
+    ///
+    /// assert!(bananas.ends_with("anas"));
+    /// assert!(!bananas.ends_with("nana"));
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::ends_with(self, pat)
+    }
+
+    /// Returns the byte index of the first character of this string slice that
+    /// matches the pattern.
+    ///
+    /// Returns [`None`] if the pattern doesn't match.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.find('L'), Some(0));
+    /// assert_eq!(s.find('é'), Some(14));
+    /// assert_eq!(s.find("Léopard"), Some(13));
+    /// ```
+    ///
+    /// More complex patterns using point-free style and closures:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.find(char::is_whitespace), Some(5));
+    /// assert_eq!(s.find(char::is_lowercase), Some(1));
+    /// assert_eq!(s.find(|c: char| c.is_whitespace() || c.is_lowercase()), Some(1));
+    /// assert_eq!(s.find(|c: char| (c < 'o') && (c > 'a')), Some(4));
+    /// ```
+    ///
+    /// Not finding the pattern:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// let x: &[_] = &['1', '2'];
+    ///
+    /// assert_eq!(s.find(x), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
+        StrExt::find(self, pat)
+    }
+
+    /// Returns the byte index of the last character of this string slice that
+    /// matches the pattern.
+    ///
+    /// Returns [`None`] if the pattern doesn't match.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    /// [`None`]: option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.rfind('L'), Some(13));
+    /// assert_eq!(s.rfind('é'), Some(14));
+    /// ```
+    ///
+    /// More complex patterns with closures:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// assert_eq!(s.rfind(char::is_whitespace), Some(12));
+    /// assert_eq!(s.rfind(char::is_lowercase), Some(20));
+    /// ```
+    ///
+    /// Not finding the pattern:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// let x: &[_] = &['1', '2'];
+    ///
+    /// assert_eq!(s.rfind(x), None);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rfind(self, pat)
+    }
+
+    /// An iterator over substrings of this string slice, separated by
+    /// characters matched by a pattern.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rsplit`] method can be used.
+    ///
+    /// [`char`]: primitive.char.html
+    /// [`rsplit`]: #method.rsplit
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
+    ///
+    /// let v: Vec<&str> = "".split('X').collect();
+    /// assert_eq!(v, [""]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
+    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
+    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
+    ///
+    /// let v: Vec<&str> = "abc1def2ghi".split(char::is_numeric).collect();
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
+    ///
+    /// let v: Vec<&str> = "lionXtigerXleopard".split(char::is_uppercase).collect();
+    /// assert_eq!(v, ["lion", "tiger", "leopard"]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".split(|c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
+    /// ```
+    ///
+    /// If a string contains multiple contiguous separators, you will end up
+    /// with empty strings in the output:
+    ///
+    /// ```
+    /// let x = "||||a||b|c".to_string();
+    /// let d: Vec<_> = x.split('|').collect();
+    ///
+    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
+    /// ```
+    ///
+    /// Contiguous separators are separated by the empty string.
+    ///
+    /// ```
+    /// let x = "(///)".to_string();
+    /// let d: Vec<_> = x.split('/').collect();
+    ///
+    /// assert_eq!(d, &["(", "", "", ")"]);
+    /// ```
+    ///
+    /// Separators at the start or end of a string are neighbored
+    /// by empty strings.
+    ///
+    /// ```
+    /// let d: Vec<_> = "010".split("0").collect();
+    /// assert_eq!(d, &["", "1", ""]);
+    /// ```
+    ///
+    /// When the empty string is used as a separator, it separates
+    /// every character in the string, along with the beginning
+    /// and end of the string.
+    ///
+    /// ```
+    /// let f: Vec<_> = "rust".split("").collect();
+    /// assert_eq!(f, &["", "r", "u", "s", "t", ""]);
+    /// ```
+    ///
+    /// Contiguous separators can lead to possibly surprising behavior
+    /// when whitespace is used as the separator. This code is correct:
+    ///
+    /// ```
+    /// let x = "    a  b c".to_string();
+    /// let d: Vec<_> = x.split(' ').collect();
+    ///
+    /// assert_eq!(d, &["", "", "", "", "a", "", "b", "c"]);
+    /// ```
+    ///
+    /// It does _not_ give you:
+    ///
+    /// ```,ignore
+    /// assert_eq!(d, &["a", "b", "c"]);
+    /// ```
+    ///
+    /// Use [`split_whitespace`] for this behavior.
+    ///
+    /// [`split_whitespace`]: #method.split_whitespace
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
+        StrExt::split(self, pat)
+    }
+
+    /// An iterator over substrings of the given string slice, separated by
+    /// characters matched by a pattern and yielded in reverse order.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a reverse
+    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// For iterating from the front, the [`split`] method can be used.
+    ///
+    /// [`split`]: #method.split
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
+    ///
+    /// let v: Vec<&str> = "".rsplit('X').collect();
+    /// assert_eq!(v, [""]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplit('X').collect();
+    /// assert_eq!(v, ["leopard", "tiger", "", "lion"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
+    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".rsplit(|c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["ghi", "def", "abc"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rsplit(self, pat)
+    }
+
+    /// An iterator over substrings of the given string slice, separated by
+    /// characters matched by a pattern.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// Equivalent to [`split`], except that the trailing substring
+    /// is skipped if empty.
+    ///
+    /// [`split`]: #method.split
+    ///
+    /// This method can be used for string data that is _terminated_,
+    /// rather than _separated_ by a pattern.
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    /// [`char`]: primitive.char.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rsplit_terminator`] method can be used.
+    ///
+    /// [`rsplit_terminator`]: #method.rsplit_terminator
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
+    /// assert_eq!(v, ["A", "B"]);
+    ///
+    /// let v: Vec<&str> = "A..B..".split_terminator(".").collect();
+    /// assert_eq!(v, ["A", "", "B", ""]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
+        StrExt::split_terminator(self, pat)
+    }
+
+    /// An iterator over substrings of `self`, separated by characters
+    /// matched by a pattern and yielded in reverse order.
+    ///
+    /// The pattern can be a simple `&str`, [`char`], or a closure that
+    /// determines the split.
+    /// Additional libraries might provide more complex patterns like
+    /// regular expressions.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// Equivalent to [`split`], except that the trailing substring is
+    /// skipped if empty.
+    ///
+    /// [`split`]: #method.split
+    ///
+    /// This method can be used for string data that is _terminated_,
+    /// rather than _separated_ by a pattern.
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a
+    /// reverse search, and it will be double ended if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// For iterating from the front, the [`split_terminator`] method can be
+    /// used.
+    ///
+    /// [`split_terminator`]: #method.split_terminator
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v: Vec<&str> = "A.B.".rsplit_terminator('.').collect();
+    /// assert_eq!(v, ["B", "A"]);
+    ///
+    /// let v: Vec<&str> = "A..B..".rsplit_terminator(".").collect();
+    /// assert_eq!(v, ["", "B", "", "A"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rsplit_terminator(self, pat)
+    }
+
+    /// An iterator over substrings of the given string slice, separated by a
+    /// pattern, restricted to returning at most `n` items.
+    ///
+    /// If `n` substrings are returned, the last substring (the `n`th substring)
+    /// will contain the remainder of the string.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines the
+    /// split.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will not be double ended, because it is
+    /// not efficient to support.
+    ///
+    /// If the pattern allows a reverse search, the [`rsplitn`] method can be
+    /// used.
+    ///
+    /// [`rsplitn`]: #method.rsplitn
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lambda".splitn(3, ' ').collect();
+    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(3, "X").collect();
+    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
+    ///
+    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
+    /// assert_eq!(v, ["abcXdef"]);
+    ///
+    /// let v: Vec<&str> = "".splitn(1, 'X').collect();
+    /// assert_eq!(v, [""]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".splitn(2, |c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["abc", "defXghi"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
+        StrExt::splitn(self, n, pat)
+    }
+
+    /// An iterator over substrings of this string slice, separated by a
+    /// pattern, starting from the end of the string, restricted to returning
+    /// at most `n` items.
+    ///
+    /// If `n` substrings are returned, the last substring (the `n`th substring)
+    /// will contain the remainder of the string.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that
+    /// determines the split.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will not be double ended, because it is not
+    /// efficient to support.
+    ///
+    /// For splitting from the front, the [`splitn`] method can be used.
+    ///
+    /// [`splitn`]: #method.splitn
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
+    ///
+    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(3, 'X').collect();
+    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
+    /// assert_eq!(v, ["leopard", "lion::tiger"]);
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1defXghi".rsplitn(2, |c| c == '1' || c == 'X').collect();
+    /// assert_eq!(v, ["ghi", "abc1def"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rsplitn(self, n, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within the given string
+    /// slice.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that
+    /// determines if a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    /// [`char`]: primitive.char.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rmatches`] method can be used.
+    ///
+    /// [`rmatches`]: #method.rmatches
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abcXXXabcYYYabc".matches("abc").collect();
+    /// assert_eq!(v, ["abc", "abc", "abc"]);
+    ///
+    /// let v: Vec<&str> = "1abc2abc3".matches(char::is_numeric).collect();
+    /// assert_eq!(v, ["1", "2", "3"]);
+    /// ```
+    #[stable(feature = "str_matches", since = "1.2.0")]
+    #[inline]
+    pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
+        StrExt::matches(self, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within this string slice,
+    /// yielded in reverse order.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a reverse
+    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// For iterating from the front, the [`matches`] method can be used.
+    ///
+    /// [`matches`]: #method.matches
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abcXXXabcYYYabc".rmatches("abc").collect();
+    /// assert_eq!(v, ["abc", "abc", "abc"]);
+    ///
+    /// let v: Vec<&str> = "1abc2abc3".rmatches(char::is_numeric).collect();
+    /// assert_eq!(v, ["3", "2", "1"]);
+    /// ```
+    #[stable(feature = "str_matches", since = "1.2.0")]
+    #[inline]
+    pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rmatches(self, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within this string
+    /// slice as well as the index that the match starts at.
+    ///
+    /// For matches of `pat` within `self` that overlap, only the indices
+    /// corresponding to the first match are returned.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines
+    /// if a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
+    /// allows a reverse search and forward/reverse search yields the same
+    /// elements. This is true for, eg, [`char`] but not for `&str`.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// If the pattern allows a reverse search but its results might differ
+    /// from a forward search, the [`rmatch_indices`] method can be used.
+    ///
+    /// [`rmatch_indices`]: #method.rmatch_indices
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
+    /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
+    ///
+    /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
+    /// assert_eq!(v, [(1, "abc"), (4, "abc")]);
+    ///
+    /// let v: Vec<_> = "ababa".match_indices("aba").collect();
+    /// assert_eq!(v, [(0, "aba")]); // only the first `aba`
+    /// ```
+    #[stable(feature = "str_match_indices", since = "1.5.0")]
+    #[inline]
+    pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
+        StrExt::match_indices(self, pat)
+    }
+
+    /// An iterator over the disjoint matches of a pattern within `self`,
+    /// yielded in reverse order along with the index of the match.
+    ///
+    /// For matches of `pat` within `self` that overlap, only the indices
+    /// corresponding to the last match are returned.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if a
+    /// character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Iterator behavior
+    ///
+    /// The returned iterator requires that the pattern supports a reverse
+    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
+    /// search yields the same elements.
+    ///
+    /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
+    ///
+    /// For iterating from the front, the [`match_indices`] method can be used.
+    ///
+    /// [`match_indices`]: #method.match_indices
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
+    ///
+    /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(4, "abc"), (1, "abc")]);
+    ///
+    /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
+    /// assert_eq!(v, [(2, "aba")]); // only the last `aba`
+    /// ```
+    #[stable(feature = "str_match_indices", since = "1.5.0")]
+    #[inline]
+    pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::rmatch_indices(self, pat)
+    }
+
+    /// Returns a string slice with leading and trailing whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    ///
+    /// assert_eq!("Hello\tworld", s.trim());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim(&self) -> &str {
+        StrExt::trim(self)
+    }
+
+    /// Returns a string slice with leading whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Left' in this context means the first
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _right_ side, not the left.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    ///
+    /// assert_eq!("Hello\tworld\t", s.trim_left());
+    /// ```
+    ///
+    /// Directionality:
+    ///
+    /// ```
+    /// let s = "  English";
+    /// assert!(Some('E') == s.trim_left().chars().next());
+    ///
+    /// let s = "  עברית";
+    /// assert!(Some('ע') == s.trim_left().chars().next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_left(&self) -> &str {
+        StrExt::trim_left(self)
+    }
+
+    /// Returns a string slice with trailing whitespace removed.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived
+    /// Core Property `White_Space`.
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Right' in this context means the last
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _left_ side, not the right.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    ///
+    /// assert_eq!(" Hello\tworld", s.trim_right());
+    /// ```
+    ///
+    /// Directionality:
+    ///
+    /// ```
+    /// let s = "English  ";
+    /// assert!(Some('h') == s.trim_right().chars().rev().next());
+    ///
+    /// let s = "עברית  ";
+    /// assert!(Some('ת') == s.trim_right().chars().rev().next());
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_right(&self) -> &str {
+        StrExt::trim_right(self)
+    }
+
+    /// Returns a string slice with all prefixes and suffixes that match a
+    /// pattern repeatedly removed.
+    ///
+    /// The pattern can be a [`char`] or a closure that determines if a
+    /// character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
+    /// assert_eq!("123foo1bar123".trim_matches(char::is_numeric), "foo1bar");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// assert_eq!("1foo1barXX".trim_matches(|c| c == '1' || c == 'X'), "foo1bar");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: DoubleEndedSearcher<'a>
+    {
+        StrExt::trim_matches(self, pat)
+    }
+
+    /// Returns a string slice with all prefixes that match a pattern
+    /// repeatedly removed.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that determines if
+    /// a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Left' in this context means the first
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _right_ side, not the left.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+    /// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
+        StrExt::trim_left_matches(self, pat)
+    }
+
+    /// Returns a string slice with all suffixes that match a pattern
+    /// repeatedly removed.
+    ///
+    /// The pattern can be a `&str`, [`char`], or a closure that
+    /// determines if a character matches.
+    ///
+    /// [`char`]: primitive.char.html
+    ///
+    /// # Text directionality
+    ///
+    /// A string is a sequence of bytes. 'Right' in this context means the last
+    /// position of that byte string; for a language like Arabic or Hebrew
+    /// which are 'right to left' rather than 'left to right', this will be
+    /// the _left_ side, not the right.
+    ///
+    /// # Examples
+    ///
+    /// Simple patterns:
+    ///
+    /// ```
+    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
+    /// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
+    ///
+    /// let x: &[_] = &['1', '2'];
+    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+    /// ```
+    ///
+    /// A more complex pattern, using a closure:
+    ///
+    /// ```
+    /// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        StrExt::trim_right_matches(self, pat)
+    }
+
+    /// Parses this string slice into another type.
+    ///
+    /// Because `parse` is so general, it can cause problems with type
+    /// inference. As such, `parse` is one of the few times you'll see
+    /// the syntax affectionately known as the 'turbofish': `::<>`. This
+    /// helps the inference algorithm understand specifically which type
+    /// you're trying to parse into.
+    ///
+    /// `parse` can parse any type that implements the [`FromStr`] trait.
+    ///
+    /// [`FromStr`]: str/trait.FromStr.html
+    ///
+    /// # Errors
+    ///
+    /// Will return [`Err`] if it's not possible to parse this string slice into
+    /// the desired type.
+    ///
+    /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
+    ///
+    /// # Examples
+    ///
+    /// Basic usage
+    ///
+    /// ```
+    /// let four: u32 = "4".parse().unwrap();
+    ///
+    /// assert_eq!(4, four);
+    /// ```
+    ///
+    /// Using the 'turbofish' instead of annotating `four`:
+    ///
+    /// ```
+    /// let four = "4".parse::<u32>();
+    ///
+    /// assert_eq!(Ok(4), four);
+    /// ```
+    ///
+    /// Failing to parse:
+    ///
+    /// ```
+    /// let nope = "j".parse::<u32>();
+    ///
+    /// assert!(nope.is_err());
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
+        StrExt::parse(self)
+    }
+
+    /// Checks if all characters in this string are within the ASCII range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = "hello!\n";
+    /// let non_ascii = "Grüße, Jürgen ❤";
+    ///
+    /// assert!(ascii.is_ascii());
+    /// assert!(!non_ascii.is_ascii());
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        // We can treat each byte as character here: all multibyte characters
+        // start with a byte that is not in the ascii range, so we will stop
+        // there already.
+        self.bytes().all(|b| b.is_ascii())
+    }
+
+    /// Checks that two strings are an ASCII case-insensitive match.
+    ///
+    /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
+    /// but without allocating and copying temporaries.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert!("Ferris".eq_ignore_ascii_case("FERRIS"));
+    /// assert!("Ferrös".eq_ignore_ascii_case("FERRöS"));
+    /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
+        self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
+    }
+
+    /// Converts this string to its ASCII upper case equivalent in-place.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new uppercased value without modifying the existing one, use
+    /// [`to_ascii_uppercase`].
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    pub fn make_ascii_uppercase(&mut self) {
+        let me = unsafe { self.as_bytes_mut() };
+        me.make_ascii_uppercase()
+    }
+
+    /// Converts this string to its ASCII lower case equivalent in-place.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To return a new lowercased value without modifying the existing one, use
+    /// [`to_ascii_lowercase`].
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    pub fn make_ascii_lowercase(&mut self) {
+        let me = unsafe { self.as_bytes_mut() };
+        me.make_ascii_lowercase()
+    }
+}}
+
+#[lang = "str"]
+#[cfg(not(test))]
+#[cfg(not(stage0))]
+impl str {
+    str_core_methods!();
+}
+
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<[u8]> for str {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        self.as_bytes()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> Default for &'a str {
+    /// Creates an empty str
+    fn default() -> &'a str { "" }
+}
+
+/// An iterator over the non-whitespace substrings of a string,
+/// separated by any amount of whitespace.
+///
+/// This struct is created by the [`split_whitespace`] method on [`str`].
+/// See its documentation for more.
+///
+/// [`split_whitespace`]: ../../std/primitive.str.html#method.split_whitespace
+/// [`str`]: ../../std/primitive.str.html
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+#[derive(Clone, Debug)]
+pub struct SplitWhitespace<'a> {
+    inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
+}
+
+#[derive(Clone)]
+struct IsWhitespace;
+
+impl FnOnce<(char, )> for IsWhitespace {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (char, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl FnMut<(char, )> for IsWhitespace {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (char, )) -> bool {
+        arg.0.is_whitespace()
+    }
+}
+
+#[derive(Clone)]
+struct IsNotEmpty;
+
+impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
+    type Output = bool;
+
+    #[inline]
+    extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
+        self.call_mut(arg)
+    }
+}
+
+impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
+        !arg.0.is_empty()
+    }
+}
+
+
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+impl<'a> Iterator for SplitWhitespace<'a> {
+    type Item = &'a str;
+
+    fn next(&mut self) -> Option<&'a str> {
+        self.inner.next()
+    }
+}
+
+#[stable(feature = "split_whitespace", since = "1.1.0")]
+impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
+    fn next_back(&mut self) -> Option<&'a str> {
+        self.inner.next_back()
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<'a> FusedIterator for SplitWhitespace<'a> {}
+
+/// An iterator of [`u16`] over the string encoded as UTF-16.
+///
+/// [`u16`]: ../../std/primitive.u16.html
+///
+/// This struct is created by the [`encode_utf16`] method on [`str`].
+/// See its documentation for more.
+///
+/// [`encode_utf16`]: ../../std/primitive.str.html#method.encode_utf16
+/// [`str`]: ../../std/primitive.str.html
+#[derive(Clone)]
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+pub struct EncodeUtf16<'a> {
+    chars: Chars<'a>,
+    extra: u16,
+}
+
+// FIXME: remove (inline) this method
+// when updating to a bootstrap compiler that has the new lang items.
+// For grepping purpose: #[cfg(stage0)]
+impl<'a> EncodeUtf16<'a> {
+    #[unstable(feature = "core_str_ext", issue = "32110")]
+    #[doc(hidden)]
+    pub fn new(s: &'a str) -> Self {
+        EncodeUtf16 { chars: s.chars(), extra: 0 }
+    }
+}
+
+#[stable(feature = "collection_debug", since = "1.17.0")]
+impl<'a> fmt::Debug for EncodeUtf16<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("EncodeUtf16 { .. }")
+    }
+}
+
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+impl<'a> Iterator for EncodeUtf16<'a> {
+    type Item = u16;
+
+    #[inline]
+    fn next(&mut self) -> Option<u16> {
+        if self.extra != 0 {
+            let tmp = self.extra;
+            self.extra = 0;
+            return Some(tmp);
+        }
+
+        let mut buf = [0; 2];
+        self.chars.next().map(|ch| {
+            let n = ch.encode_utf16(&mut buf).len();
+            if n == 2 {
+                self.extra = buf[1];
+            }
+            buf[0]
+        })
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (low, high) = self.chars.size_hint();
+        // every char gets either one u16 or two u16,
+        // so this iterator is between 1 or 2 times as
+        // long as the underlying iterator.
+        (low, high.and_then(|n| n.checked_mul(2)))
+    }
+}
+
+#[stable(feature = "fused", since = "1.26.0")]
+impl<'a> FusedIterator for EncodeUtf16<'a> {}
index cc0ef6a6f17e04b5e7358040d0ef689cb73ea871..962fb2f0e027b3924507205b43145beccef82485 100644 (file)
@@ -26,6 +26,17 @@ fn smoketest_cell() {
     assert!(y.get() == (30, 40));
 }
 
+#[test]
+fn cell_update() {
+    let x = Cell::new(10);
+
+    assert_eq!(x.update(|x| x + 5), 15);
+    assert_eq!(x.get(), 15);
+
+    assert_eq!(x.update(|x| x / 3), 5);
+    assert_eq!(x.get(), 5);
+}
+
 #[test]
 fn cell_has_sensible_show() {
     let x = Cell::new("foo bar");
index 4e10ceac878b6a4c5669d49a2b7fd9838efb4ca8..ab90763abf8d5ef8ad335e7cf97058b23c406920 100644 (file)
@@ -364,6 +364,7 @@ fn check(c: char) {
 }
 
 #[test]
+#[allow(deprecated)]
 fn test_decode_utf8() {
     macro_rules! assert_decode_utf8 {
         ($input_bytes: expr, $expected_str: expr) => {
index bb875c7219a6bef1db86b75905b2350fdd17808d..e4d277179382f3e522259bbc67abebafaab8b3d4 100644 (file)
 
 #![feature(ascii_ctype)]
 #![feature(box_syntax)]
+#![feature(cell_update)]
 #![feature(core_float)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(dec2flt)]
 #![feature(decode_utf8)]
+#![feature(euclidean_division)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
+#![feature(float_internals)]
 #![feature(flt2dec)]
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
@@ -36,6 +39,7 @@
 #![feature(str_internals)]
 #![feature(test)]
 #![feature(trusted_len)]
+#![feature(try_from)]
 #![feature(try_trait)]
 #![feature(exact_chunks)]
 #![cfg_attr(stage0, feature(atomic_nand))]
index 8d791283ab87ebd22846667445f7414dc53a60b9..71d2e7945389ba63aac87a3844a1d55344821d1f 100644 (file)
@@ -30,6 +30,11 @@ fn test_num() {
         num::test_num(10 as $T, 2 as $T);
     }
 
+    #[test]
+    fn test_mod_euc() {
+        assert!((-1 as $T).mod_euc(MIN) == MAX);
+    }
+
     #[test]
     pub fn test_abs() {
         assert!((1 as $T).abs() == 1 as $T);
index b4f39439d5b4d4d93c4b36bee707a1775650bd6a..18bf54297afc6b3d100e6835c5baf647a0aa0819 100644 (file)
@@ -655,6 +655,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [input] Features,
 
     [] ProgramClausesFor(DefId),
+    [] ProgramClausesForEnv(ParamEnv<'tcx>),
     [] WasmImportModuleMap(CrateNum),
     [] ForeignModules(CrateNum),
 
index 4bd857c73e6cf6d50e73961d5b90542d2028e3d8..bfe21549e453d3358ca606b702b13ba80dfb6287 100644 (file)
@@ -107,8 +107,9 @@ fn visit_item(&mut self, i: &'a Item) {
         // information we encapsulate into
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
+            ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
-            ItemKind::Trait(..) | ItemKind::TraitAlias(..) |
+            ItemKind::TraitAlias(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
                 DefPathData::TypeNs(i.ident.name.as_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
@@ -222,7 +223,7 @@ fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         let def_data = match ti.node {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
                 DefPathData::ValueNs(ti.ident.name.as_str()),
-            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
+            TraitItemKind::Type(..) => DefPathData::AssocTypeInTrait(ti.ident.name.as_str()),
             TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
         };
 
@@ -240,7 +241,7 @@ fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
                 DefPathData::ValueNs(ii.ident.name.as_str()),
-            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
+            ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_str()),
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
         };
 
index 1a2840de447de75d3d157288c0074610294d7002..12f146ef49115f0ce99f1110034745790f468d45 100644 (file)
@@ -212,6 +212,9 @@ fn compute_stable_hash(&self, parent_hash: DefPathHash) -> DefPathHash {
         ::std::mem::discriminant(data).hash(&mut hasher);
         match *data {
             DefPathData::TypeNs(name) |
+            DefPathData::Trait(name) |
+            DefPathData::AssocTypeInTrait(name) |
+            DefPathData::AssocTypeInImpl(name) |
             DefPathData::ValueNs(name) |
             DefPathData::Module(name) |
             DefPathData::MacroDef(name) |
@@ -358,6 +361,12 @@ pub enum DefPathData {
     // Different kinds of items and item-like things:
     /// An impl
     Impl,
+    /// A trait
+    Trait(InternedString),
+    /// An associated type **declaration** (i.e., in a trait)
+    AssocTypeInTrait(InternedString),
+    /// An associated type **value** (i.e., in an impl)
+    AssocTypeInImpl(InternedString),
     /// Something in the type NS
     TypeNs(InternedString),
     /// Something in the value NS
@@ -639,6 +648,9 @@ pub fn get_opt_name(&self) -> Option<InternedString> {
         use self::DefPathData::*;
         match *self {
             TypeNs(name) |
+            Trait(name) |
+            AssocTypeInTrait(name) |
+            AssocTypeInImpl(name) |
             ValueNs(name) |
             Module(name) |
             MacroDef(name) |
@@ -663,6 +675,9 @@ pub fn as_interned_str(&self) -> InternedString {
         use self::DefPathData::*;
         let s = match *self {
             TypeNs(name) |
+            Trait(name) |
+            AssocTypeInTrait(name) |
+            AssocTypeInImpl(name) |
             ValueNs(name) |
             Module(name) |
             MacroDef(name) |
index 70c152b40c0d25fdbc77561268c46efa6c192459..322cfd55510bb84d9687d3365d0d47ca885869f3 100644 (file)
@@ -1352,10 +1352,6 @@ impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
     }
 );
 
-impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
-    region_outlives, ty_outlives
-});
-
 impl_stable_hash_for!(enum infer::canonical::Certainty {
     Proven, Ambiguous
 });
@@ -1417,6 +1413,7 @@ fn hash_stable<W: StableHasherResult>(&self,
                 quantifier.hash_stable(hcx, hasher);
                 goal.hash_stable(hcx, hasher);
             },
+            CannotProve => { },
         }
     }
 }
index 8ea6eb005a140b0eb105e7fbbc839074fccd2837..25f8b5d8c9cc0422f1c7fd288e3fd359bcf116c0 100644 (file)
@@ -42,7 +42,6 @@
 use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags};
 use ty::subst::{Kind, UnpackedKind};
 use ty::fold::{TypeFoldable, TypeFolder};
-use util::captures::Captures;
 
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
@@ -121,7 +120,7 @@ pub enum CanonicalTyVarKind {
 #[derive(Clone, Debug)]
 pub struct QueryResult<'tcx, R> {
     pub var_values: CanonicalVarValues<'tcx>,
-    pub region_constraints: QueryRegionConstraints<'tcx>,
+    pub region_constraints: Vec<QueryRegionConstraint<'tcx>>,
     pub certainty: Certainty,
     pub value: R,
 }
@@ -181,12 +180,7 @@ pub fn is_ambiguous(&self) -> bool {
     }
 }
 
-/// Subset of `RegionConstraintData` produced by trait query.
-#[derive(Clone, Debug, Default)]
-pub struct QueryRegionConstraints<'tcx> {
-    pub region_outlives: Vec<(Region<'tcx>, Region<'tcx>)>,
-    pub ty_outlives: Vec<(Ty<'tcx>, Region<'tcx>)>,
-}
+pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
 
 /// Trait implemented by values that can be canonicalized. It mainly
 /// serves to identify the interning table we will use.
@@ -382,35 +376,29 @@ fn query_region_constraints_into_obligations<'a>(
         &'a self,
         cause: &'a ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>,
+        unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + Captures<'gcx> + 'a {
-        let QueryRegionConstraints {
-            region_outlives,
-            ty_outlives,
-        } = unsubstituted_region_constraints;
-
-        let region_obligations = region_outlives.iter().map(move |(r1, r2)| {
-            let r1 = substitute_value(self.tcx, result_subst, r1);
-            let r2 = substitute_value(self.tcx, result_subst, r2);
-            Obligation::new(
-                cause.clone(),
-                param_env,
-                ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
-            )
-        });
-
-        let ty_obligations = ty_outlives.iter().map(move |(t1, r2)| {
-            let t1 = substitute_value(self.tcx, result_subst, t1);
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
+        Box::new(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);
-            Obligation::new(
-                cause.clone(),
-                param_env,
-                ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
-            )
-        });
-
-        region_obligations.chain(ty_obligations)
+            match k1.unpack() {
+                UnpackedKind::Lifetime(r1) =>
+                    Obligation::new(
+                        cause.clone(),
+                        param_env,
+                        ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
+                    ),
+
+                UnpackedKind::Type(t1) =>
+                    Obligation::new(
+                        cause.clone(),
+                        param_env,
+                        ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
+                    ),
+            }
+        })) as Box<dyn Iterator<Item = _>>
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
@@ -913,19 +901,6 @@ impl<'tcx> TypeFoldable<'tcx> for CanonicalVarValues<'tcx> {
     }
 }
 
-BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> {
-        region_outlives, ty_outlives
-    }
-}
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
-        type Lifted = QueryRegionConstraints<'tcx>;
-        region_outlives, ty_outlives
-    }
-}
-
 BraceStructTypeFoldableImpl! {
     impl<'tcx, R> TypeFoldable<'tcx> for QueryResult<'tcx, R> {
         var_values, region_constraints, certainty, value
index a2cefe488c68ac53767b9ec0727a3750d1a10779..bb495049483ac3c0d2b95671655be1dd47eefc3f 100644 (file)
@@ -52,6 +52,7 @@
 #![cfg_attr(windows, feature(libc))]
 #![feature(macro_lifetime_matcher)]
 #![feature(macro_vis_matcher)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(non_exhaustive)]
 #![feature(nonzero)]
index 97cfcf0f60795a07080b82d196a545aee8e14db9..109edffcde38a5d3cc9a22804c6b6e3b47ed5d7f 100644 (file)
     "suggest using `dyn Trait` for trait objects"
 }
 
+declare_lint! {
+    pub ABSOLUTE_PATH_STARTING_WITH_MODULE,
+    Allow,
+    "fully qualified paths that start with a module name \
+     instead of `crate`, `self`, or an extern crate name"
+}
+
 declare_lint! {
     pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
     Warn,
@@ -314,6 +321,7 @@ fn get_lints(&self) -> LintArray {
             TYVAR_BEHIND_RAW_POINTER,
             ELIDED_LIFETIME_IN_PATH,
             BARE_TRAIT_OBJECT,
+            ABSOLUTE_PATH_STARTING_WITH_MODULE,
             UNSTABLE_NAME_COLLISION,
         )
     }
@@ -324,7 +332,8 @@ fn get_lints(&self) -> LintArray {
 #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
 pub enum BuiltinLintDiagnostics {
     Normal,
-    BareTraitObject(Span, /* is_global */ bool)
+    BareTraitObject(Span, /* is_global */ bool),
+    AbsPathWithModule(Span),
 }
 
 impl BuiltinLintDiagnostics {
@@ -339,6 +348,23 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
                 };
                 db.span_suggestion(span, "use `dyn`", sugg);
             }
+            BuiltinLintDiagnostics::AbsPathWithModule(span) => {
+                let sugg = match sess.codemap().span_to_snippet(span) {
+                    Ok(ref s) => {
+                        // FIXME(Manishearth) ideally the emitting code
+                        // can tell us whether or not this is global
+                        let opt_colon = if s.trim_left().starts_with("::") {
+                            ""
+                        } else {
+                            "::"
+                        };
+
+                        format!("crate{}{}", opt_colon, s)
+                    }
+                    Err(_) => format!("crate::<path>")
+                };
+                db.span_suggestion(span, "use `crate`", sugg);
+            }
         }
     }
 }
index 3b37031cf461452978a78fa6a4760262543b4514..95e92e21b09dcdd50129bad5151257cbe62bb725 100644 (file)
@@ -214,6 +214,9 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     StrImplItem,                     "str",                     str_impl;
     SliceImplItem,                   "slice",                   slice_impl;
     SliceU8ImplItem,                 "slice_u8",                slice_u8_impl;
+    StrAllocImplItem,                "str_alloc",               str_alloc_impl;
+    SliceAllocImplItem,              "slice_alloc",             slice_alloc_impl;
+    SliceU8AllocImplItem,            "slice_u8_alloc",          slice_u8_alloc_impl;
     ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
     MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
     I8ImplItem,                      "i8",                      i8_impl;
@@ -230,6 +233,8 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     UsizeImplItem,                   "usize",                   usize_impl;
     F32ImplItem,                     "f32",                     f32_impl;
     F64ImplItem,                     "f64",                     f64_impl;
+    F32RuntimeImplItem,              "f32_runtime",             f32_runtime_impl;
+    F64RuntimeImplItem,              "f64_runtime",             f64_runtime_impl;
 
     SizedTraitLangItem,              "sized",                   sized_trait;
     UnsizeTraitLangItem,             "unsize",                  unsize_trait;
@@ -298,7 +303,8 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
     BoxFreeFnLangItem,               "box_free",                box_free_fn;
-    DropInPlaceFnLangItem,             "drop_in_place",           drop_in_place_fn;
+    DropInPlaceFnLangItem,           "drop_in_place",           drop_in_place_fn;
+    OomLangItem,                     "oom",                     oom;
 
     StartFnLangItem,                 "start",                   start_fn;
 
index 11dc2a8188505119ac6a3a4d9ca58ec7ffff00ce..17c114bc3b3c0f3beff9483681aa136d30f6b221 100644 (file)
@@ -184,6 +184,7 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
                 b: hir::BodyId, s: Span, id: NodeId) {
         visit_fn(self, fk, fd, b, s, id);
     }
+
     fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); }
     fn visit_expr(&mut self, ex: &'tcx Expr) { visit_expr(self, ex); }
     fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); }
@@ -361,6 +362,16 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
     // swap in a new set of IR maps for this function body:
     let mut fn_maps = IrMaps::new(ir.tcx);
 
+    // Don't run unused pass for #[derive()]
+    if let FnKind::Method(..) = fk {
+        let parent = ir.tcx.hir.get_parent(id);
+        if let Some(hir::map::Node::NodeItem(i)) = ir.tcx.hir.find(parent) {
+            if i.attrs.iter().any(|a| a.check_name("automatically_derived")) {
+                return;
+            }
+        }
+    }
+
     debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps);
 
     let body = ir.tcx.hir.body(body_id);
index 42483c83f4ba27f4b277133da09ba329bb7dd2ab..5f4efbeeaa8762da80ffc0cf8119189a29e418d7 100644 (file)
@@ -22,6 +22,7 @@
 
 use std::fmt;
 use std::mem;
+use rustc_data_structures::small_vec::SmallVec;
 use rustc_data_structures::sync::Lrc;
 use syntax::codemap;
 use syntax::ast;
@@ -677,96 +678,75 @@ pub fn nearest_common_ancestor(&self,
                                    -> Scope {
         if scope_a == scope_b { return scope_a; }
 
-        // [1] The initial values for `a_buf` and `b_buf` are not used.
-        // The `ancestors_of` function will return some prefix that
-        // is re-initialized with new values (or else fallback to a
-        // heap-allocated vector).
-        let mut a_buf: [Scope; 32] = [scope_a /* [1] */; 32];
-        let mut a_vec: Vec<Scope> = vec![];
-        let mut b_buf: [Scope; 32] = [scope_b /* [1] */; 32];
-        let mut b_vec: Vec<Scope> = vec![];
-        let parent_map = &self.parent_map;
-        let a_ancestors = ancestors_of(parent_map, scope_a, &mut a_buf, &mut a_vec);
-        let b_ancestors = ancestors_of(parent_map, scope_b, &mut b_buf, &mut b_vec);
-        let mut a_index = a_ancestors.len() - 1;
-        let mut b_index = b_ancestors.len() - 1;
-
-        // Here, [ab]_ancestors is a vector going from narrow to broad.
-        // The end of each vector will be the item where the scope is
-        // defined; if there are any common ancestors, then the tails of
-        // the vector will be the same.  So basically we want to walk
-        // backwards from the tail of each vector and find the first point
-        // where they diverge.  If one vector is a suffix of the other,
-        // then the corresponding scope is a superscope of the other.
-
-        if a_ancestors[a_index] != b_ancestors[b_index] {
-            // In this case, the two regions belong to completely
-            // different functions.  Compare those fn for lexical
-            // nesting. The reasoning behind this is subtle.  See the
-            // "Modeling closures" section of the README in
-            // infer::region_constraints for more details.
-            let a_root_scope = a_ancestors[a_index];
-            let b_root_scope = a_ancestors[a_index];
-            return match (a_root_scope.data(), b_root_scope.data()) {
-                (ScopeData::Destruction(a_root_id),
-                 ScopeData::Destruction(b_root_id)) => {
-                    if self.closure_is_enclosed_by(a_root_id, b_root_id) {
-                        // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
-                        scope_b
-                    } else if self.closure_is_enclosed_by(b_root_id, a_root_id) {
-                        // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
-                        scope_a
-                    } else {
-                        // neither fn encloses the other
-                        bug!()
-                    }
+        // Process the lists in tandem from the innermost scope, recording the
+        // scopes seen so far. The first scope that comes up for a second time
+        // is the nearest common ancestor.
+        //
+        // Note: another way to compute the nearest common ancestor is to get
+        // the full scope chain for both scopes and then compare the chains to
+        // find the first scope in a common tail. But getting a parent scope
+        // requires a hash table lookup, and we often have very long scope
+        // chains (10s or 100s of scopes) that only differ by a few elements at
+        // the start. So this algorithm is faster.
+        let mut ma = Some(scope_a);
+        let mut mb = Some(scope_b);
+        let mut seen: SmallVec<[Scope; 32]> = SmallVec::new();
+        loop {
+            if let Some(a) = ma {
+                if seen.iter().position(|s| *s == a).is_some() {
+                    return a;
                 }
-                _ => {
-                    // root ids are always Node right now
-                    bug!()
+                seen.push(a);
+                ma = self.parent_map.get(&a).map(|s| *s);
+            }
+
+            if let Some(b) = mb {
+                if seen.iter().position(|s| *s == b).is_some() {
+                    return b;
                 }
-            };
-        }
+                seen.push(b);
+                mb = self.parent_map.get(&b).map(|s| *s);
+            }
 
-        loop {
-            // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index]
-            // for all indices between a_index and the end of the array
-            if a_index == 0 { return scope_a; }
-            if b_index == 0 { return scope_b; }
-            a_index -= 1;
-            b_index -= 1;
-            if a_ancestors[a_index] != b_ancestors[b_index] {
-                return a_ancestors[a_index + 1];
+            if ma.is_none() && mb.is_none() {
+                break;
             }
-        }
+        };
 
-        fn ancestors_of<'a, 'tcx>(parent_map: &FxHashMap<Scope, Scope>,
-                                  scope: Scope,
-                                  buf: &'a mut [Scope; 32],
-                                  vec: &'a mut Vec<Scope>)
-                                  -> &'a [Scope] {
-            // debug!("ancestors_of(scope={:?})", scope);
+        fn outermost_scope(parent_map: &FxHashMap<Scope, Scope>, scope: Scope) -> Scope {
             let mut scope = scope;
-
-            let mut i = 0;
-            while i < 32 {
-                buf[i] = scope;
-                match parent_map.get(&scope) {
-                    Some(&superscope) => scope = superscope,
-                    _ => return &buf[..i+1]
-                }
-                i += 1;
+            loop {
+               match parent_map.get(&scope) {
+                   Some(&superscope) => scope = superscope,
+                   None => break scope,
+               }
             }
+        }
 
-            *vec = Vec::with_capacity(64);
-            vec.extend_from_slice(buf);
-            loop {
-                vec.push(scope);
-                match parent_map.get(&scope) {
-                    Some(&superscope) => scope = superscope,
-                    _ => return &*vec
+        // In this (rare) case, the two regions belong to completely different
+        // functions. Compare those fn for lexical nesting. The reasoning
+        // behind this is subtle. See the "Modeling closures" section of the
+        // README in infer::region_constraints for more details.
+        let a_root_scope = outermost_scope(&self.parent_map, scope_a);
+        let b_root_scope = outermost_scope(&self.parent_map, scope_b);
+        match (a_root_scope.data(), b_root_scope.data()) {
+            (ScopeData::Destruction(a_root_id),
+             ScopeData::Destruction(b_root_id)) => {
+                if self.closure_is_enclosed_by(a_root_id, b_root_id) {
+                    // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
+                    scope_b
+                } else if self.closure_is_enclosed_by(b_root_id, a_root_id) {
+                    // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
+                    scope_a
+                } else {
+                    // neither fn encloses the other
+                    bug!()
                 }
             }
+            _ => {
+                // root ids are always Node right now
+                bug!()
+            }
         }
     }
 
index e19f4483f6569f536549ef57501d9bcebe13e025..a2bceb191022165f2ff59c10760ac7bfd8474671 100644 (file)
@@ -151,4 +151,5 @@ fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
     panic_fmt,          PanicFmtLangItem,           rust_begin_unwind;
     eh_personality,     EhPersonalityLangItem,      rust_eh_personality;
     eh_unwind_resume,   EhUnwindResumeLangItem,     rust_eh_unwind_resume;
+    oom,                OomLangItem,                rust_oom;
 }
index 2e6689efee572358b3279373b6759a1fd89b9261..456e83f4700e400b4c7a2e47e1c27a2a0cbc02bb 100644 (file)
@@ -16,6 +16,8 @@
 pub use self::Passes::*;
 pub use self::DebugInfoLevel::*;
 
+use std::str::FromStr;
+
 use session::{early_error, early_warn, Session};
 use session::search_paths::SearchPaths;
 
@@ -28,7 +30,7 @@
 
 use syntax::ast::{self, IntTy, UintTy};
 use syntax::codemap::{FileName, FilePathMapping};
-use syntax::edition::Edition;
+use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
 use syntax::parse::token;
 use syntax::parse;
 use syntax::symbol::Symbol;
@@ -410,6 +412,7 @@ pub struct Options {
 
         // Remap source path prefixes in all output (messages, object files, debug, etc)
         remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
+        edition: Edition [TRACKED],
     }
 );
 
@@ -589,6 +592,7 @@ pub fn basic_options() -> Options {
         cli_forced_codegen_units: None,
         cli_forced_thinlto_off: false,
         remap_path_prefix: Vec::new(),
+        edition: DEFAULT_EDITION,
     }
 }
 
@@ -773,8 +777,6 @@ mod $mod_desc {
             Some("`string` or `string=string`");
         pub const parse_lto: Option<&'static str> =
             Some("one of `thin`, `fat`, or omitted");
-        pub const parse_edition: Option<&'static str> =
-            Some("one of: `2015`, `2018`");
     }
 
     #[allow(dead_code)]
@@ -782,7 +784,6 @@ mod $mod_set {
         use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
         use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
-        use syntax::edition::Edition;
 
         $(
             pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -985,20 +986,6 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
             true
         }
 
-        fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
-            match v {
-                Some(s) => {
-                    let edition = s.parse();
-                    if let Ok(parsed) = edition {
-                        *slot = parsed;
-                        true
-                    } else {
-                        false
-                    }
-                }
-                _ => false,
-            }
-        }
     }
 ) }
 
@@ -1292,10 +1279,6 @@ fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
         `everybody_loops` (all function bodies replaced with `loop {}`),
         `hir` (the HIR), `hir,identified`, or
         `hir,typed` (HIR with types for each node)."),
-    edition: Edition = (Edition::Edition2015, parse_edition, [TRACKED],
-        "The edition to build Rust with. Newer editions may include features
-         that require breaking changes. The default edition is 2015 (the first
-         edition). Crates compiled with different editions can be linked together."),
     run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
           "run `dsymutil` and delete intermediate object files"),
     ui_testing: bool = (false, parse_bool, [UNTRACKED],
@@ -1306,6 +1289,8 @@ fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
         "tell the linker to strip debuginfo when building without debuginfo enabled."),
     share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
           "make the current crate share its generic instantiations"),
+    chalk: bool = (false, parse_bool, [TRACKED],
+          "enable the experimental Chalk-based trait solving engine"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -1656,6 +1641,12 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                   `expanded,identified` (fully parenthesized, AST nodes with IDs).",
             "TYPE",
         ),
+        opt::opt_s(
+            "",
+            "edition",
+            "Specify which edition of the compiler to use when compiling code.",
+            EDITION_NAME_LIST,
+        ),
         opt::multi_s(
             "",
             "remap-path-prefix",
@@ -1715,6 +1706,34 @@ pub fn build_session_options_and_crate_config(
         ),
     };
 
+    let edition = match matches.opt_str("edition") {
+        Some(arg) => match Edition::from_str(&arg){
+            Ok(edition) => edition,
+            Err(_) => early_error(
+                ErrorOutputType::default(),
+                &format!(
+                    "argument for --edition must be one of: \
+                    {}. (instead was `{}`)",
+                    EDITION_NAME_LIST,
+                    arg
+                ),
+            ),
+        }
+        None => DEFAULT_EDITION,
+    };
+
+    if !edition.is_stable() && !nightly_options::is_nightly_build() {
+        early_error(
+                ErrorOutputType::default(),
+                &format!(
+                    "Edition {} is unstable an only\
+                    available for nightly builds of rustc.",
+                    edition,
+                )
+        )
+    }
+
+
     // We need the opts_present check because the driver will send us Matches
     // with only stable options if no unstable options are used. Since error-format
     // is unstable, it will not be present. We have to use opts_present not
@@ -2171,6 +2190,7 @@ pub fn build_session_options_and_crate_config(
             cli_forced_codegen_units: codegen_units,
             cli_forced_thinlto_off: disable_thinlto,
             remap_path_prefix,
+            edition,
         },
         cfg,
     )
@@ -2300,11 +2320,12 @@ mod dep_tracking {
     use std::hash::Hash;
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
-    use super::{CrateType, DebugInfoLevel, Edition, ErrorOutputType, Lto, OptLevel, OutputTypes,
+    use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes,
                 Passes, Sanitizer};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_back::{PanicStrategy, RelroLevel};
     use rustc_back::target::TargetTriple;
+    use syntax::edition::Edition;
 
     pub trait DepTrackingHash {
         fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
@@ -2363,8 +2384,8 @@ fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
     impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
     impl_dep_tracking_hash_via_hash!(Sanitizer);
     impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
-    impl_dep_tracking_hash_via_hash!(Edition);
     impl_dep_tracking_hash_via_hash!(TargetTriple);
+    impl_dep_tracking_hash_via_hash!(Edition);
 
     impl_dep_tracking_hash_for_sortable_vec_of!(String);
     impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
@@ -2437,6 +2458,7 @@ mod tests {
     use super::{Externs, OutputType, OutputTypes};
     use rustc_back::{PanicStrategy, RelroLevel};
     use syntax::symbol::Symbol;
+    use syntax::edition::{Edition, DEFAULT_EDITION};
     use syntax;
 
     fn optgroups() -> getopts::Options {
@@ -3081,4 +3103,17 @@ fn test_debugging_options_tracking_hash() {
         opts.debugging_opts.relro_level = Some(RelroLevel::Full);
         assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
     }
+
+    #[test]
+    fn test_edition_parsing() {
+        // test default edition
+        let options = super::basic_options();
+        assert!(options.edition == DEFAULT_EDITION);
+
+        let matches = optgroups()
+            .parse(&["--edition=2018".to_string()])
+            .unwrap();
+        let (sessopts, _) = build_session_options_and_crate_config(&matches);
+        assert!(sessopts.edition == Edition::Edition2018)
+    }
 }
index e2be51b552ae8c639548b12e9360fa9d21d8502d..3bd2bb3c8beb0d10bfdde8b60fd2246e0acba3c9 100644 (file)
@@ -934,11 +934,11 @@ pub fn teach(&self, code: &DiagnosticId) -> bool {
 
     /// Are we allowed to use features from the Rust 2018 edition?
     pub fn rust_2018(&self) -> bool {
-        self.opts.debugging_opts.edition >= Edition::Edition2018
+        self.opts.edition >= Edition::Edition2018
     }
 
     pub fn edition(&self) -> Edition {
-        self.opts.debugging_opts.edition
+        self.opts.edition
     }
 }
 
index 8d2398d34090d8d6f8ddc327150ef42466141217..5bfea1631894b172f6516bfe88ed51b6365b0d63 100644 (file)
@@ -282,13 +282,16 @@ pub enum QuantifierKind {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum Goal<'tcx> {
-    Implies(&'tcx Slice<Clause<'tcx>>, &'tcx Goal<'tcx>),
+    Implies(Clauses<'tcx>, &'tcx Goal<'tcx>),
     And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>),
     Not(&'tcx Goal<'tcx>),
     DomainGoal(DomainGoal<'tcx>),
-    Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>)
+    Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>),
+    CannotProve,
 }
 
+pub type Goals<'tcx> = &'tcx Slice<Goal<'tcx>>;
+
 impl<'tcx> Goal<'tcx> {
     pub fn from_poly_domain_goal<'a>(
         domain_goal: PolyDomainGoal<'tcx>,
@@ -318,6 +321,9 @@ pub enum Clause<'tcx> {
     ForAll(ty::Binder<ProgramClause<'tcx>>),
 }
 
+/// Multiple clauses.
+pub type Clauses<'tcx> = &'tcx Slice<Clause<'tcx>>;
+
 /// A "program clause" has the form `D :- G1, ..., Gn`. It is saying
 /// that the domain goal `D` is true if `G1...Gn` are provable. This
 /// is equivalent to the implication `G1..Gn => D`; we usually write
@@ -330,7 +336,7 @@ pub struct ProgramClause<'tcx> {
     pub goal: DomainGoal<'tcx>,
 
     /// ...if we can prove these hypotheses (there may be no hypotheses at all):
-    pub hypotheses: &'tcx Slice<Goal<'tcx>>,
+    pub hypotheses: Goals<'tcx>,
 }
 
 pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
index 31c5bf1bbad84fd45870dd2b302f4b283d4e72bb..1e3e4160de1963b611897a9df1a4dcebe780e33d 100644 (file)
@@ -491,6 +491,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                 // FIXME: appropriate binder names
                 write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder())
             }
+            CannotProve => write!(fmt, "CannotProve"),
         }
     }
 }
@@ -557,6 +558,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
         (traits::Goal::Not)(goal),
         (traits::Goal::DomainGoal)(domain_goal),
         (traits::Goal::Quantified)(qkind, goal),
+        (traits::Goal::CannotProve),
     }
 }
 
index 28ad5edbd2db7ad376e1c7d3adace5694f62bb7b..56669243f273a071cffefb80062dde2157a2f459 100644 (file)
@@ -38,7 +38,7 @@
 use ty::ReprOptions;
 use ty::Instance;
 use traits;
-use traits::{Clause, Goal};
+use traits::{Clause, Clauses, Goal, Goals};
 use ty::{self, Ty, TypeAndMut};
 use ty::{TyS, TypeVariants, Slice};
 use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region, Const};
@@ -2374,6 +2374,14 @@ pub fn mk_nil(self) -> Ty<'tcx> {
         self.intern_tup(&[])
     }
 
+    pub fn mk_diverging_default(self) -> Ty<'tcx> {
+        if self.features().never_type {
+            self.types.never
+        } else {
+            self.intern_tup(&[])
+        }
+    }
+
     pub fn mk_bool(self) -> Ty<'tcx> {
         self.mk_ty(TyBool)
     }
@@ -2509,7 +2517,7 @@ pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVar
         }
     }
 
-    pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> &'tcx Slice<Clause<'tcx>> {
+    pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> {
         if ts.len() == 0 {
             Slice::empty()
         } else {
@@ -2517,7 +2525,7 @@ pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> &'tcx Slice<Clause<'tcx>> {
         }
     }
 
-    pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> &'tcx Slice<Goal<'tcx>> {
+    pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> Goals<'tcx> {
         if ts.len() == 0 {
             Slice::empty()
         } else {
@@ -2571,13 +2579,11 @@ pub fn mk_substs_trait(self,
         self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
     }
 
-    pub fn mk_clauses<I: InternAs<[Clause<'tcx>],
-        &'tcx Slice<Clause<'tcx>>>>(self, iter: I) -> I::Output {
+    pub fn mk_clauses<I: InternAs<[Clause<'tcx>], Clauses<'tcx>>>(self, iter: I) -> I::Output {
         iter.intern_with(|xs| self.intern_clauses(xs))
     }
 
-    pub fn mk_goals<I: InternAs<[Goal<'tcx>],
-        &'tcx Slice<Goal<'tcx>>>>(self, iter: I) -> I::Output {
+    pub fn mk_goals<I: InternAs<[Goal<'tcx>], Goals<'tcx>>>(self, iter: I) -> I::Output {
         iter.intern_with(|xs| self.intern_goals(xs))
     }
 
index 8189064db6968eeecfcc353eeb03ee8326b419c6..2819141c81be25888c1f13de987625ecc121c65b 100644 (file)
@@ -204,6 +204,9 @@ pub fn push_item_path<T>(self, buffer: &mut T, def_id: DefId)
             // finer-grained distinctions, e.g. between enum/struct).
             data @ DefPathData::Misc |
             data @ DefPathData::TypeNs(..) |
+            data @ DefPathData::Trait(..) |
+            data @ DefPathData::AssocTypeInTrait(..) |
+            data @ DefPathData::AssocTypeInImpl(..) |
             data @ DefPathData::ValueNs(..) |
             data @ DefPathData::Module(..) |
             data @ DefPathData::TypeParam(..) |
index fea7de955e0bfdc72fa713bd0c94a321010ac785..735fe06560f5f3a765fbc561bc7085c0859a489f 100644 (file)
@@ -717,6 +717,12 @@ fn describe(_tcx: TyCtxt, _: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> {
+    fn describe(_tcx: TyCtxt, _: ty::ParamEnv<'tcx>) -> String {
+        format!("generating chalk-style clauses for param env")
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> {
     fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
         format!("wasm import module map")
index b8167ec918638be880a6bc0351e98c105208dd01..72f2cb49abc0e73f837476907d7331f1a55ba656 100644 (file)
@@ -154,6 +154,15 @@ fn default_span(&self, _: TyCtxt) -> Span {
     }
 }
 
+impl<'tcx> Key for ty::ParamEnv<'tcx> {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
     fn map_crate(&self) -> CrateNum {
         self.value.map_crate()
index 0ab9f16dab481064f7b8b6330a2b5be32fb24eb1..92d23d4338f9d904a31332bd782dd01a2b773330 100644 (file)
@@ -37,8 +37,8 @@
 use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use traits::query::normalize::NormalizationResult;
 use traits::specialization_graph;
-use traits::Clause;
-use ty::{self, CrateInherentImpls, ParamEnvAnd, Slice, Ty, TyCtxt};
+use traits::Clauses;
+use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use ty::steal::Steal;
 use ty::subst::Substs;
 use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
 
     [] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
 
-    [] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice<Clause<'tcx>>>,
+    [] fn program_clauses_for: ProgramClausesFor(DefId) -> Clauses<'tcx>,
+
+    [] fn program_clauses_for_env: ProgramClausesForEnv(
+        ty::ParamEnv<'tcx>
+    ) -> Clauses<'tcx>,
 
     [] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
     [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
index 8d6c7474a9f94f495569460e2938754f7651caba..70fbd17e6cbb0fbce9b04dc3ed5d02c62543a301 100644 (file)
@@ -978,6 +978,7 @@ macro_rules! force {
         DepKind::DropckOutlives |
         DepKind::SubstituteNormalizeAndTestPredicates |
         DepKind::InstanceDefSizeEstimate |
+        DepKind::ProgramClausesForEnv |
 
         // This one should never occur in this context
         DepKind::Null => {
index c3d2d5675de0544de65a577b3c0f62b4ed9b974c..1524d4b9e7f62bd44411b8f9280c09cef9147145 100644 (file)
@@ -1138,6 +1138,11 @@ pub struct ProjectionPredicate<'tcx> {
 pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
+    /// Returns the def-id of the associated item being projected.
+    pub fn item_def_id(&self) -> DefId {
+        self.skip_binder().projection_ty.item_def_id
+    }
+
     pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> {
         // Note: unlike with TraitRef::to_poly_trait_ref(),
         // self.0.trait_ref is permitted to have escaping regions.
index dd478967b185a3539762868eb3f91beb6c979771..84e3358ff13897f5ec0b3449c41ea29ea9602aac 100644 (file)
@@ -268,14 +268,31 @@ fn parameterized<F: fmt::Write>(&mut self,
             loop {
                 let key = tcx.def_key(item_def_id);
                 match key.disambiguated_data.data {
+                    DefPathData::AssocTypeInTrait(_) |
+                    DefPathData::AssocTypeInImpl(_) |
+                    DefPathData::Trait(_) |
                     DefPathData::TypeNs(_) => {
                         break;
                     }
-                    DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => {
+                    DefPathData::ValueNs(_) |
+                    DefPathData::EnumVariant(_) => {
                         is_value_path = true;
                         break;
                     }
-                    _ => {
+                    DefPathData::CrateRoot |
+                    DefPathData::Misc |
+                    DefPathData::Impl |
+                    DefPathData::Module(_) |
+                    DefPathData::MacroDef(_) |
+                    DefPathData::ClosureExpr |
+                    DefPathData::TypeParam(_) |
+                    DefPathData::LifetimeDef(_) |
+                    DefPathData::Field(_) |
+                    DefPathData::StructCtor |
+                    DefPathData::Initializer |
+                    DefPathData::ImplTrait |
+                    DefPathData::Typeof |
+                    DefPathData::GlobalMetaData(_) => {
                         // if we're making a symbol for something, there ought
                         // to be a value or type-def or something in there
                         // *somewhere*
index ffd02108c270e4352ba97ecb342cc85038c59030..9338d000c1291aeb24dff3b95cf3e29499b66630 100644 (file)
@@ -245,7 +245,7 @@ fn arg_ty(
                 self.cx.expr_ident(self.span, ident)
             }
 
-            AllocatorTy::ResultPtr | AllocatorTy::Bang | AllocatorTy::Unit => {
+            AllocatorTy::ResultPtr | AllocatorTy::Unit => {
                 panic!("can't convert AllocatorTy to an argument")
             }
         }
@@ -262,8 +262,6 @@ fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
                 (self.ptr_u8(), expr)
             }
 
-            AllocatorTy::Bang => (self.cx.ty(self.span, TyKind::Never), expr),
-
             AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),
 
             AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
index 706eab72d44cc8af296a9fec233d3bf5babeb347..969086815ded4777c3cc6939d9e3be4fc58be6b0 100644 (file)
         inputs: &[AllocatorTy::Layout],
         output: AllocatorTy::ResultPtr,
     },
-    AllocatorMethod {
-        name: "oom",
-        inputs: &[],
-        output: AllocatorTy::Bang,
-    },
     AllocatorMethod {
         name: "dealloc",
         inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
@@ -52,7 +47,6 @@ pub struct AllocatorMethod {
 }
 
 pub enum AllocatorTy {
-    Bang,
     Layout,
     Ptr,
     ResultPtr,
index 0f051ea5981ca4eefe254c264a179b4343640ad0..08438805a703e759f5823ab6b4a1a7b830dc616b 100644 (file)
@@ -45,6 +45,7 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![forbid(unsafe_code)]
 
+#![feature(try_from)]
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
 extern crate rustc_cratesio_shim;
index 49baa1b96cee3b4bdf61dec87801898f386f7ea1..3660bf7bea917fe7cda7b3c90ba5cc9b794fdce1 100644 (file)
@@ -20,5 +20,6 @@ pub fn opts() -> TargetOptions {
     base.is_like_android = true;
     base.position_independent_executables = true;
     base.has_elf_tls = false;
+    base.requires_uwtable = true;
     base
 }
index 592b27ac641b5204d2af6ec4a16cce4d625e938c..e46266b576e244e5a90bf089d9708735a3f063c5 100644 (file)
@@ -481,6 +481,11 @@ pub struct TargetOptions {
 
     /// Whether a .debug_gdb_scripts section will be added to the output object file
     pub emit_debug_gdb_scripts: bool,
+
+    /// Whether or not to unconditionally `uwtable` attributes on functions,
+    /// typically because the platform needs to unwind for things like stack
+    /// unwinders.
+    pub requires_uwtable: bool,
 }
 
 impl Default for TargetOptions {
@@ -554,6 +559,7 @@ fn default() -> TargetOptions {
             default_hidden_visibility: false,
             embed_bitcode: false,
             emit_debug_gdb_scripts: true,
+            requires_uwtable: false,
         }
     }
 }
@@ -804,6 +810,7 @@ macro_rules! key {
         key!(default_hidden_visibility, bool);
         key!(embed_bitcode, bool);
         key!(emit_debug_gdb_scripts, bool);
+        key!(requires_uwtable, bool);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1008,6 +1015,7 @@ macro_rules! target_option_val {
         target_option_val!(default_hidden_visibility);
         target_option_val!(embed_bitcode);
         target_option_val!(emit_debug_gdb_scripts);
+        target_option_val!(requires_uwtable);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
index 971b21e062f69415d858743eff0d3187cb86f993..4b4fb27caa839baa4d498deab92fe561c2f2b5fd 100644 (file)
@@ -103,6 +103,7 @@ pub fn opts() -> TargetOptions {
         custom_unwind_resume: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
+        requires_uwtable: true,
 
         .. Default::default()
     }
index 06e879bec3492310184cce57472dfef0e0b2e535..fee5a0284c80610993a0f7df8946ff222022b140 100644 (file)
@@ -35,6 +35,7 @@ pub fn opts() -> TargetOptions {
         crt_static_respected: true,
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
+        requires_uwtable: true,
 
         .. Default::default()
     }
index f8c0289cc98c870269fa62bc9a34073a635f028b..2fb811eba1e9a197eb6ec0cae4edb099b0a74723 100644 (file)
@@ -691,7 +691,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
         krate,
         &sess.parse_sess,
         sess.opts.test,
-        sess.opts.debugging_opts.edition,
+        sess.edition(),
     );
     // these need to be set "early" so that expansion sees `quote` if enabled.
     sess.init_features(features);
@@ -1155,6 +1155,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(
                 }
             });
 
+            time(sess, "dumping chalk-like clauses", || {
+                rustc_traits::lowering::dump_program_clauses(tcx);
+            });
+
             time(sess, "MIR effect checking", || {
                 for def_id in tcx.body_owners() {
                     mir::transform::check_unsafety::check_unsafety(tcx, def_id)
@@ -1178,10 +1182,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(
 
             time(sess, "lint checking", || lint::check_crate(tcx));
 
-            time(sess, "dumping chalk-like clauses", || {
-                rustc_traits::lowering::dump_program_clauses(tcx)
-            });
-
             return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
         },
     )
index 6f2c51b0f1899afaadaf2dcb99e6e43859819878..af0620b00051f901e6f6ebf6e5ad8a30a4eb3cfb 100644 (file)
@@ -1441,3 +1441,71 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         }
     }
 }
+
+/// Lint constants that are erroneous.
+/// Without this lint, we might not get any diagnostic if the constant is
+/// unused within this crate, even though downstream crates can't use it
+/// without producing an error.
+pub struct UnusedBrokenConst;
+
+impl LintPass for UnusedBrokenConst {
+    fn get_lints(&self) -> LintArray {
+        lint_array!()
+    }
+}
+
+fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
+    let def_id = cx.tcx.hir.body_owner_def_id(body_id);
+    let param_env = cx.tcx.param_env(def_id);
+    let cid = ::rustc::mir::interpret::GlobalId {
+        instance: ty::Instance::mono(cx.tcx, def_id),
+        promoted: None
+    };
+    if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) {
+        let span = cx.tcx.def_span(def_id);
+        let mut diag = cx.struct_span_lint(
+            CONST_ERR,
+            span,
+            &format!("this {} cannot be used", what),
+        );
+        use rustc::middle::const_val::ConstEvalErrDescription;
+        match err.description() {
+            ConstEvalErrDescription::Simple(message) => {
+                diag.span_label(span, message);
+            }
+            ConstEvalErrDescription::Backtrace(miri, frames) => {
+                diag.span_label(span, format!("{}", miri));
+                for frame in frames {
+                    diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
+                }
+            }
+        }
+        diag.emit()
+    }
+}
+
+struct UnusedBrokenConstVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
+
+impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UnusedBrokenConstVisitor<'a, 'tcx> {
+    fn visit_nested_body(&mut self, id: hir::BodyId) {
+        check_const(self.0, id, "array length");
+    }
+    fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'v> {
+        hir::intravisit::NestedVisitorMap::None
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        match it.node {
+            hir::ItemConst(_, body_id) => {
+                check_const(cx, body_id, "constant");
+            },
+            hir::ItemTy(ref ty, _) => hir::intravisit::walk_ty(
+                &mut UnusedBrokenConstVisitor(cx),
+                ty
+            ),
+            _ => {},
+        }
+    }
+}
index 16e8600f2d89bfec62c9bb5eeccdcec779c850fb..889c7d3e34ef96c45d93f3bda047037a3df98dcc 100644 (file)
@@ -40,7 +40,7 @@
 extern crate syntax_pos;
 
 use rustc::lint;
-use rustc::lint::builtin::BARE_TRAIT_OBJECT;
+use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_STARTING_WITH_MODULE};
 use rustc::session;
 use rustc::util;
 
@@ -136,6 +136,7 @@ macro_rules! add_lint_group {
                  UnionsWithDropFields,
                  UnreachablePub,
                  TypeAliasBounds,
+                 UnusedBrokenConst,
                  );
 
     add_builtin_with_new!(sess,
@@ -278,6 +279,11 @@ macro_rules! add_lint_group {
             // Note: this item represents future incompatibility of all unstable functions in the
             //       standard library, and thus should never be removed or changed to an error.
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(ABSOLUTE_PATH_STARTING_WITH_MODULE),
+            reference: "issue TBD",
+            edition: Some(Edition::Edition2018),
+        },
         ]);
 
     // Register renamed and removed lints
index b65e9a715facaa0a42dd70801cbe6b5df74e6bc3..d7a06f7932fef396a8de850578e442efea6435a9 100644 (file)
@@ -925,18 +925,19 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         };
 
         let mir =
-            if let hir::ImplItemKind::Const(..) = ast_item.node {
-                true
-            } else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node {
-                let generics = self.tcx.generics_of(def_id);
-                let types = generics.parent_types as usize + generics.types.len();
-                let needs_inline = (types > 0 || tcx.trans_fn_attrs(def_id).requests_inline()) &&
-                    !self.metadata_output_only();
-                let is_const_fn = sig.constness == hir::Constness::Const;
-                let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
-                needs_inline || is_const_fn || always_encode_mir
-            } else {
-                false
+            match ast_item.node {
+                hir::ImplItemKind::Const(..) => true,
+                hir::ImplItemKind::Method(ref sig, _) => {
+                    let generics = self.tcx.generics_of(def_id);
+                    let types = generics.parent_types as usize + generics.types.len();
+                    let needs_inline =
+                        (types > 0 || tcx.trans_fn_attrs(def_id).requests_inline())
+                            && !self.metadata_output_only();
+                    let is_const_fn = sig.constness == hir::Constness::Const;
+                    let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
+                    needs_inline || is_const_fn || always_encode_mir
+                },
+                hir::ImplItemKind::Type(..) => false,
             };
 
         Entry {
index acd246b7031260ad0bad7304a111fc83714ac218..ec7ee466008a514684ee158e89b78f684f9e6888 100644 (file)
@@ -275,7 +275,7 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                         tcx.predicates_of(def_id).instantiate(tcx, substs);
                     let predicates =
                         type_checker.normalize(&instantiated_predicates.predicates, location);
-                    type_checker.prove_predicates(predicates.iter().cloned(), location);
+                    type_checker.prove_predicates(predicates, location);
                 }
 
                 value.ty
@@ -1516,34 +1516,34 @@ fn prove_aggregate_predicates(
 
         let predicates = self.normalize(&instantiated_predicates.predicates, location);
         debug!("prove_aggregate_predicates: predicates={:?}", predicates);
-        self.prove_predicates(predicates.iter().cloned(), location);
+        self.prove_predicates(predicates, location);
     }
 
     fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) {
         self.prove_predicates(
-            [ty::Predicate::Trait(
+            Some(ty::Predicate::Trait(
                 trait_ref.to_poly_trait_ref().to_poly_trait_predicate(),
-            )].iter()
-                .cloned(),
+            )),
             location,
         );
     }
 
-    fn prove_predicates(
-        &mut self,
-        predicates: impl IntoIterator<Item = ty::Predicate<'tcx>>,
-        location: Location,
-    {
-        let mut predicates_iter = predicates.into_iter();
+    fn prove_predicates<T>(&mut self, predicates: T, location: Location)
+    where
+        T: IntoIterator<Item = ty::Predicate<'tcx>>,
+        T::IntoIter: Clone,
+    {
+        let predicates = predicates.into_iter();
 
         debug!(
             "prove_predicates(predicates={:?}, location={:?})",
-            predicates_iter.by_ref().collect::<Vec<_>>(),
-            location
+            predicates.clone().collect::<Vec<_>>(),
+            location,
         );
         self.fully_perform_op(location.at_self(), |this| {
             let cause = this.misc(this.last_span);
-            let obligations = predicates_iter
+            let obligations = predicates
+                .into_iter()
                 .map(|p| traits::Obligation::new(cause.clone(), this.param_env, p))
                 .collect();
             Ok(InferOk {
index 4e95ee6444dcf956754807bb61380204c2bf9c44..147b8cc2175af9d88de2a6400b16cb5f24c644f1 100644 (file)
@@ -113,6 +113,7 @@ fn simplify_match_pair<'pat>(&mut self,
             PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
                 let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
                     i == variant_index || {
+                        self.hir.tcx().features().never_type &&
                         self.hir.tcx().features().exhaustive_patterns &&
                         self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
                     }
index 9f17af8b16f1d7501cf00a0248c02495aa2509c1..c2da8c11d87e9382339c0eda9e0990cb7a9479cd 100644 (file)
@@ -16,7 +16,7 @@
 pub use self::check_match::check_crate;
 pub(crate) use self::check_match::check_match;
 
-use interpret::{const_val_field, const_discr, self};
+use interpret::{const_val_field, const_variant_index, self};
 
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::{Field, BorrowKind, Mutability};
@@ -835,38 +835,9 @@ fn const_to_pat(
             ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
                 match cv.val {
                     ConstVal::Value(val) => {
-                        let discr_val = const_discr(
+                        let variant_index = const_variant_index(
                             self.tcx, self.param_env, instance, val, cv.ty
-                        ).expect("const_discr failed");
-                        let layout = self
-                            .tcx
-                            .layout_of(self.param_env.and(cv.ty))
-                            .expect("layout of enum not available");
-                        let variant_index = match layout.variants {
-                            ty::layout::Variants::Single { index } => index,
-                            ty::layout::Variants::Tagged { ref discr, .. } => {
-                                // raw discriminants for enums are isize or bigger during
-                                // their computation, but later shrunk to the smallest possible
-                                // representation
-                                let size = discr.value.size(self.tcx).bits();
-                                let amt = 128 - size;
-                                adt_def
-                                    .discriminants(self.tcx)
-                                    .position(|var| ((var.val << amt) >> amt) == discr_val)
-                                    .unwrap_or_else(|| {
-                                        bug!("discriminant {} not found in {:#?}",
-                                            discr_val,
-                                            adt_def
-                                                .discriminants(self.tcx)
-                                                .collect::<Vec<_>>(),
-                                            );
-                                    })
-                            }
-                            ty::layout::Variants::NicheFilling { .. } => {
-                                assert_eq!(discr_val as usize as u128, discr_val);
-                                discr_val as usize
-                            },
-                        };
+                        ).expect("const_variant_index failed");
                         let subpatterns = adt_subpatterns(
                             adt_def.variants[variant_index].fields.len(),
                             Some(variant_index),
index 954a3dbe5b9ab0e78224cb1a508925810b4606a5..a25331f7279fbcf11bcd36c9a0a2ea457627cb36 100644 (file)
@@ -56,7 +56,7 @@ pub fn mk_eval_cx<'a, 'tcx>(
     Ok(ecx)
 }
 
-pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
+pub fn eval_promoted<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cid: GlobalId<'tcx>,
     mir: &'mir mir::Mir<'tcx>,
@@ -66,7 +66,7 @@ pub fn eval_body_with_mir<'a, 'mir, 'tcx>(
     match res {
         Ok(val) => Some(val),
         Err(mut err) => {
-            ecx.report(&mut err, true, None);
+            ecx.report(&mut err, false, None);
             None
         }
     }
@@ -400,14 +400,14 @@ pub fn const_val_field<'a, 'tcx>(
     }
 }
 
-pub fn const_discr<'a, 'tcx>(
+pub fn const_variant_index<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     instance: ty::Instance<'tcx>,
     value: Value,
     ty: Ty<'tcx>,
-) -> EvalResult<'tcx, u128> {
-    trace!("const_discr: {:?}, {:?}, {:?}", instance, value, ty);
+) -> EvalResult<'tcx, usize> {
+    trace!("const_variant_index: {:?}, {:?}, {:?}", instance, value, ty);
     let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let (ptr, align) = match value {
         Value::ByValPair(..) | Value::ByVal(_) => {
@@ -421,7 +421,7 @@ pub fn const_discr<'a, 'tcx>(
         Value::ByRef(ptr, align) => (ptr, align),
     };
     let place = Place::from_primval_ptr(ptr, align);
-    ecx.read_discriminant_value(place, ty)
+    ecx.read_discriminant_as_variant_index(place, ty)
 }
 
 pub fn const_eval_provider<'a, 'tcx>(
index a5ddd50ae10c50f969224c294159aff76e412ba0..b98ab218de5cb5cd7bc1a6b45cb492543d592ac7 100644 (file)
@@ -743,28 +743,8 @@ pub(super) fn eval_rvalue_into_place(
 
             Discriminant(ref place) => {
                 let ty = self.place_ty(place);
-                let layout = self.layout_of(ty)?;
                 let place = self.eval_place(place)?;
                 let discr_val = self.read_discriminant_value(place, ty)?;
-                match layout.variants {
-                    layout::Variants::Single { index } => {
-                        assert_eq!(discr_val, index as u128);
-                    }
-                    layout::Variants::Tagged { .. } |
-                    layout::Variants::NicheFilling { .. } => {
-                        if let ty::TyAdt(adt_def, _) = ty.sty {
-                            trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(*self.tcx).collect::<Vec<_>>());
-                            if adt_def.discriminants(*self.tcx).all(|v| {
-                                discr_val != v.val
-                            })
-                            {
-                                return err!(InvalidDiscriminant);
-                            }
-                        } else {
-                            bug!("rustc only generates Rvalue::Discriminant for enums");
-                        }
-                    }
-                }
                 self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
             }
         }
@@ -837,13 +817,39 @@ pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValT
         }
     }
 
+    /// reads a tag and produces the corresponding variant index
+    pub fn read_discriminant_as_variant_index(
+        &mut self,
+        place: Place,
+        ty: Ty<'tcx>,
+    ) -> EvalResult<'tcx, usize> {
+        let layout = self.layout_of(ty)?;
+        match layout.variants {
+            ty::layout::Variants::Single { index } => Ok(index),
+            ty::layout::Variants::Tagged { .. } => {
+                let discr_val = self.read_discriminant_value(place, ty)?;
+                ty
+                    .ty_adt_def()
+                    .expect("tagged layout for non adt")
+                    .discriminants(self.tcx.tcx)
+                    .position(|var| var.val == discr_val)
+                    .ok_or_else(|| EvalErrorKind::InvalidDiscriminant.into())
+            }
+            ty::layout::Variants::NicheFilling { .. } => {
+                let discr_val = self.read_discriminant_value(place, ty)?;
+                assert_eq!(discr_val as usize as u128, discr_val);
+                Ok(discr_val as usize)
+            },
+        }
+    }
+
     pub fn read_discriminant_value(
         &mut self,
         place: Place,
         ty: Ty<'tcx>,
     ) -> EvalResult<'tcx, u128> {
         let layout = self.layout_of(ty)?;
-        //trace!("read_discriminant_value {:#?}", layout);
+        trace!("read_discriminant_value {:#?}", layout);
 
         match layout.variants {
             layout::Variants::Single { index } => {
@@ -854,13 +860,34 @@ pub fn read_discriminant_value(
         }
 
         let (discr_place, discr) = self.place_field(place, mir::Field::new(0), layout)?;
+        trace!("discr place: {:?}, {:?}", discr_place, discr);
         let raw_discr = self.value_to_primval(ValTy {
             value: self.read_place(discr_place)?,
             ty: discr.ty
         })?;
         let discr_val = match layout.variants {
             layout::Variants::Single { .. } => bug!(),
-            layout::Variants::Tagged { .. } => raw_discr.to_bytes()?,
+            // FIXME: should we catch invalid discriminants here?
+            layout::Variants::Tagged { .. } => {
+                if discr.ty.is_signed() {
+                    let i = raw_discr.to_bytes()? as i128;
+                    // going from layout tag type to typeck discriminant type
+                    // requires first sign extending with the layout discriminant
+                    let amt = 128 - discr.size.bits();
+                    let sexted = (i << amt) >> amt;
+                    // and then zeroing with the typeck discriminant type
+                    let discr_ty = ty
+                        .ty_adt_def().expect("tagged layout corresponds to adt")
+                        .repr
+                        .discr_type();
+                    let discr_ty = layout::Integer::from_attr(self.tcx.tcx, discr_ty);
+                    let amt = 128 - discr_ty.size().bits();
+                    let truncatee = sexted as u128;
+                    (truncatee << amt) >> amt
+                } else {
+                    raw_discr.to_bytes()?
+                }
+            },
             layout::Variants::NicheFilling {
                 dataful_variant,
                 ref niche_variants,
@@ -910,11 +937,18 @@ pub fn write_discriminant_value(
                                layout::Abi::Uninhabited);
                 }
             }
-            layout::Variants::Tagged { .. } => {
+            layout::Variants::Tagged { ref discr, .. } => {
                 let discr_val = dest_ty.ty_adt_def().unwrap()
                     .discriminant_for_variant(*self.tcx, variant_index)
                     .val;
 
+                // raw discriminants for enums are isize or bigger during
+                // their computation, but the in-memory tag is the smallest possible
+                // representation
+                let size = discr.value.size(self.tcx.tcx).bits();
+                let amt = 128 - size;
+                let discr_val = (discr_val << amt) >> amt;
+
                 let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?;
                 self.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?;
             }
@@ -1145,19 +1179,18 @@ pub fn write_value_to_ptr(
                     _ if primval.is_undef() => false,
                     _ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout)
                 };
-                self.memory.write_primval(dest.to_ptr()?, dest_align, primval, layout.size.bytes(), signed)
+                self.memory.write_primval(dest, dest_align, primval, layout.size.bytes(), signed)
             }
             Value::ByValPair(a_val, b_val) => {
-                let ptr = dest.to_ptr()?;
                 trace!("write_value_to_ptr valpair: {:#?}", layout);
                 let (a, b) = match layout.abi {
                     layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
                     _ => bug!("write_value_to_ptr: invalid ByValPair layout: {:#?}", layout)
                 };
                 let (a_size, b_size) = (a.size(&self), b.size(&self));
-                let a_ptr = ptr;
+                let a_ptr = dest;
                 let b_offset = a_size.abi_align(b.align(&self));
-                let b_ptr = ptr.offset(b_offset.bytes(), &self)?.into();
+                let b_ptr = dest.offset(b_offset.bytes(), &self)?.into();
                 // TODO: What about signedess?
                 self.memory.write_primval(a_ptr, dest_align, a_val, a_size.bytes(), false)?;
                 self.memory.write_primval(b_ptr, dest_align, b_val, b_size.bytes(), false)
index dcf97f61545db2ca7a7ebd2d3a7fadc9c7bdbe8d..5e156e9271f57fd85ea69337007bf30d9255f01f 100644 (file)
@@ -691,7 +691,7 @@ pub fn read_ptr_sized(&self, ptr: MemoryPointer, ptr_align: Align) -> EvalResult
         self.read_primval(ptr, ptr_align, self.pointer_size())
     }
 
-    pub fn write_primval(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
+    pub fn write_primval(&mut self, ptr: Pointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
         let endianness = self.endianness();
 
         let bytes = match val {
@@ -703,11 +703,14 @@ pub fn write_primval(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimV
             PrimVal::Bytes(bytes) => bytes,
 
             PrimVal::Undef => {
-                self.mark_definedness(PrimVal::Ptr(ptr).into(), size, false)?;
+                self.check_align(ptr.into(), ptr_align)?;
+                self.mark_definedness(ptr, size, false)?;
                 return Ok(());
             }
         };
 
+        let ptr = ptr.to_ptr()?;
+
         {
             let align = self.int_align(size);
             let dst = self.get_bytes_mut(ptr, size, ptr_align.min(align))?;
@@ -734,7 +737,7 @@ pub fn write_primval(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimV
 
     pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, ptr_align: Align, val: PrimVal) -> EvalResult<'tcx> {
         let ptr_size = self.pointer_size();
-        self.write_primval(ptr, ptr_align, val, ptr_size, false)
+        self.write_primval(ptr.into(), ptr_align, val, ptr_size, false)
     }
 
     fn int_align(&self, size: u64) -> Align {
index 147db3bdc0e7a41f082f167434d61c5ce3a36f1f..1eb131810bdf38d9404a60a6fa16f61c4c3a9c17 100644 (file)
 pub use self::memory::{Memory, MemoryKind, HasMemory};
 
 pub use self::const_eval::{
-    eval_body_with_mir,
+    eval_promoted,
     mk_borrowck_eval_cx,
     eval_body,
     CompileTimeEvaluator,
     const_eval_provider,
     const_val_field,
-    const_discr,
+    const_variant_index,
 };
 
 pub use self::machine::Machine;
index 851fac532e366d9f726727a04c2269c10d88dd46..3360e5b72a7c72c7afbc2a2e59171f37b00a854a 100644 (file)
@@ -37,7 +37,6 @@ pub(super) fn eval_terminator(
                 ref targets,
                 ..
             } => {
-                // FIXME(CTFE): forbid branching
                 let discr_val = self.eval_operand(discr)?;
                 let discr_prim = self.value_to_primval(discr_val)?;
 
@@ -45,8 +44,7 @@ pub(super) fn eval_terminator(
                 let mut target_block = targets[targets.len() - 1];
 
                 for (index, &const_int) in values.iter().enumerate() {
-                    let prim = PrimVal::Bytes(const_int);
-                    if discr_prim.to_bytes()? == prim.to_bytes()? {
+                    if discr_prim.to_bytes()? == const_int {
                         target_block = targets[index];
                         break;
                     }
index de3063a575673bc8b6f88e5f7fe5d78b5624f014..a47b3cacc517e1fc6694c632a9a851349886b4f3 100644 (file)
@@ -33,6 +33,7 @@
 #![feature(nonzero)]
 #![feature(inclusive_range_fields)]
 #![feature(crate_visibility_modifier)]
+#![feature(never_type)]
 #![cfg_attr(stage0, feature(try_trait))]
 
 extern crate arena;
index 008165f33b2bbc69f23fffa1c9a7aac0ae907c5b..610e70b39ccf994e035da02f327858e325e33d3a 100644 (file)
@@ -1177,7 +1177,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         param_substs: instance.substs,
     }.visit_mir(&mir);
     let param_env = ty::ParamEnv::reveal_all();
-    for (i, promoted) in mir.promoted.iter().enumerate() {
+    for i in 0..mir.promoted.len() {
         use rustc_data_structures::indexed_vec::Idx;
         let cid = GlobalId {
             instance,
@@ -1185,9 +1185,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
         match tcx.const_eval(param_env.and(cid)) {
             Ok(val) => collect_const(tcx, val, instance.substs, output),
-            Err(err) => {
-                err.report(tcx, promoted.span, "promoted");
-            }
+            Err(_) => {},
         }
     }
 }
index f133d6e9c6dee847be829b68e1246284cc62091c..a3d96f0c0739d6b0c45191d1ba604e7b2dda155e 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, PrimVal, GlobalId};
-use interpret::{eval_body_with_mir, mk_borrowck_eval_cx, ValTy};
+use interpret::{eval_promoted, mk_borrowck_eval_cx, ValTy};
 use transform::{MirPass, MirSource};
 use syntax::codemap::Span;
 use rustc::ty::subst::Substs;
@@ -161,7 +161,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
                 };
                 // cannot use `const_eval` here, because that would require having the MIR
                 // for the current function available, but we're producing said MIR right now
-                let (value, _, ty) = eval_body_with_mir(self.tcx, cid, self.mir, self.param_env)?;
+                let (value, _, ty) = eval_promoted(self.tcx, cid, self.mir, self.param_env)?;
                 let val = (value, ty, c.span);
                 trace!("evaluated {:?} to {:?}", c, val);
                 Some(val)
index 1866122454c7057cab50c8511a3a1d2775512a0a..6708640379a54d2157a5f5adaba426a4d35c1d76 100644 (file)
@@ -273,7 +273,9 @@ fn visit_item(&mut self, item: &'a Item) {
                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
                 }
                 if defaultness == Defaultness::Default {
-                    self.err_handler().span_err(item.span, "inherent impls cannot be default");
+                    self.err_handler()
+                        .struct_span_err(item.span, "inherent impls cannot be default")
+                        .note("only trait implementations may be annotated with default").emit();
                 }
             }
             ItemKind::ForeignMod(..) => {
index 671856c4e549e34507dc8dbf18d5eaaf83a50e30..7a87a72afc294635476d2041b5761213d4b3e769 100644 (file)
@@ -1654,11 +1654,12 @@ fn resolve_hir_path_cb<F>(&mut self, path: &mut hir::Path, is_value: bool, error
         let path: Vec<Ident> = segments.iter()
             .map(|seg| Ident::new(seg.name, span))
             .collect();
-        match self.resolve_path(&path, Some(namespace), true, span) {
+        // FIXME (Manishearth): Intra doc links won't get warned of epoch changes
+        match self.resolve_path(&path, Some(namespace), true, span, None) {
             PathResult::Module(module) => *def = module.def().unwrap(),
             PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
                 *def = path_res.base_def(),
-            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span) {
+            PathResult::NonModule(..) => match self.resolve_path(&path, None, true, span, None) {
                 PathResult::Failed(span, msg, _) => {
                     error_callback(self, span, ResolutionError::FailedToResolve(&msg));
                 }
@@ -2360,7 +2361,8 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
             if def != Def::Err {
                 new_id = Some(def.def_id());
                 let span = trait_ref.path.span;
-                if let PathResult::Module(module) = self.resolve_path(&path, None, false, span) {
+                if let PathResult::Module(module) = self.resolve_path(&path, None, false, span,
+                                                                      Some(trait_ref.ref_id)) {
                     new_val = Some((module, trait_ref.clone()));
                 }
             }
@@ -2819,7 +2821,8 @@ fn smart_resolve_path_fragment(&mut self,
                     (format!(""), format!("the crate root"))
                 } else {
                     let mod_path = &path[..path.len() - 1];
-                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), false, span) {
+                    let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS),
+                                                             false, span, None) {
                         PathResult::Module(module) => module.def(),
                         _ => None,
                     }.map_or(format!(""), |def| format!("{} ", def.kind_name()));
@@ -3149,7 +3152,7 @@ fn resolve_qpath(&mut self,
             ));
         }
 
-        let result = match self.resolve_path(&path, Some(ns), true, span) {
+        let result = match self.resolve_path(&path, Some(ns), true, span, Some(id)) {
             PathResult::NonModule(path_res) => path_res,
             PathResult::Module(module) if !module.is_normal() => {
                 PathResolution::new(module.def().unwrap())
@@ -3186,7 +3189,7 @@ fn resolve_qpath(&mut self,
            path[0].name != keywords::CrateRoot.name() &&
            path[0].name != keywords::DollarCrate.name() {
             let unqualified_result = {
-                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
+                match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, None) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
                     PathResult::Module(module) => module.def().unwrap(),
                     _ => return Some(result),
@@ -3205,7 +3208,9 @@ fn resolve_path(&mut self,
                     path: &[Ident],
                     opt_ns: Option<Namespace>, // `None` indicates a module path
                     record_used: bool,
-                    path_span: Span)
+                    path_span: Span,
+                    node_id: Option<NodeId>) // None indicates that we don't care about linting
+                                             // `::module` paths
                     -> PathResult<'a> {
         let mut module = None;
         let mut allow_super = true;
@@ -3253,6 +3258,8 @@ fn resolve_path(&mut self,
                     let prev_name = path[0].name;
                     if prev_name == keywords::Extern.name() ||
                        prev_name == keywords::CrateRoot.name() &&
+                       // Note: When this feature stabilizes, this should
+                       // be gated on sess.rust_2018()
                        self.session.features_untracked().extern_absolute_paths {
                         // `::extern_crate::a::b`
                         let crate_id = self.crate_loader.process_path_extern(name, ident.span);
@@ -3324,6 +3331,33 @@ fn resolve_path(&mut self,
                                                   format!("Not a module `{}`", ident),
                                                   is_last);
                     }
+
+                    if let Some(id) = node_id {
+                        if i == 1 && self.session.features_untracked().crate_in_paths
+                                  && !self.session.rust_2018() {
+                            let prev_name = path[0].name;
+                            if prev_name == keywords::Extern.name() ||
+                               prev_name == keywords::CrateRoot.name() {
+                                let mut is_crate = false;
+                                if let NameBindingKind::Import { directive: d, .. } = binding.kind {
+                                    if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass {
+                                        is_crate = true;
+                                    }
+                                }
+
+                                if !is_crate {
+                                    let diag = lint::builtin::BuiltinLintDiagnostics
+                                                   ::AbsPathWithModule(path_span);
+                                    self.session.buffer_lint_with_diagnostic(
+                                        lint::builtin::ABSOLUTE_PATH_STARTING_WITH_MODULE,
+                                        id, path_span,
+                                        "Absolute paths must start with `self`, `super`, \
+                                        `crate`, or an external crate name in the 2018 edition",
+                                        diag);
+                                }
+                            }
+                        }
+                    }
                 }
                 Err(Undetermined) => return PathResult::Indeterminate,
                 Err(Determined) => {
@@ -3571,7 +3605,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
             // Search in module.
             let mod_path = &path[..path.len() - 1];
             if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS),
-                                                                  false, span) {
+                                                                  false, span, None) {
                 add_module_candidates(module, &mut names);
             }
         }
index 0388465b485cb5527727dc50045c16db5ed16351..af1e17cd89c090ee903ac95094a8ee4f96e8caa6 100644 (file)
@@ -397,6 +397,18 @@ fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: b
 
     fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                             -> Result<Def, Determinacy> {
+        if path.segments.len() > 1 {
+            if !self.session.features_untracked().proc_macro_path_invoc {
+                emit_feature_err(
+                    &self.session.parse_sess,
+                    "proc_macro_path_invoc",
+                    path.span,
+                    GateIssue::Language,
+                    "paths of length greater than one in macro invocations are \
+                     currently unstable",
+                );
+            }
+        }
         let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
         if def != Err(Determinacy::Undetermined) {
             // Do not report duplicated errors on every undetermined resolution.
@@ -426,7 +438,7 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
                 return Err(Determinacy::Determined);
             }
 
-            let def = match self.resolve_path(&path, Some(MacroNS), false, span) {
+            let def = match self.resolve_path(&path, Some(MacroNS), false, span, None) {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
                     def @ _ => {
@@ -604,7 +616,7 @@ pub fn resolve_legacy_scope(&mut self,
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
         for &(ref path, span) in module.macro_resolutions.borrow().iter() {
-            match self.resolve_path(&path, Some(MacroNS), true, span) {
+            match self.resolve_path(&path, Some(MacroNS), true, span, None) {
                 PathResult::NonModule(_) => {},
                 PathResult::Failed(span, msg, _) => {
                     resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
index 37c62a7b0b45b276ab49270c3987195583e32123..e2a7f5668d251b535cdf50f152441328a2b16b4f 100644 (file)
@@ -535,7 +535,8 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
             // For better failure detection, pretend that the import will not define any names
             // while resolving its module path.
             directive.vis.set(ty::Visibility::Invisible);
-            let result = self.resolve_path(&directive.module_path[..], None, false, directive.span);
+            let result = self.resolve_path(&directive.module_path[..], None, false,
+                                           directive.span, Some(directive.id));
             directive.vis.set(vis);
 
             match result {
@@ -663,7 +664,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
             }
         }
 
-        let module_result = self.resolve_path(&module_path, None, true, span);
+        let module_result = self.resolve_path(&module_path, None, true, span, Some(directive.id));
         let module = match module_result {
             PathResult::Module(module) => module,
             PathResult::Failed(span, msg, false) => {
@@ -677,7 +678,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                 if !self_path.is_empty() && !is_special(self_path[0]) &&
                    !(self_path.len() > 1 && is_special(self_path[1])) {
                     self_path[0].name = keywords::SelfValue.name();
-                    self_result = Some(self.resolve_path(&self_path, None, false, span));
+                    self_result = Some(self.resolve_path(&self_path, None, false,
+                                                         span, None));
                 }
                 return if let Some(PathResult::Module(..)) = self_result {
                     Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))
index 8136f6857a5c62cc8ff1eacd8a1cb371cb9e2a70..90c870096e179f711af17cac046249fbc2a7d2e5 100644 (file)
@@ -37,6 +37,7 @@ pub fn provide(p: &mut Providers) {
         normalize_ty_after_erasing_regions:
             normalize_erasing_regions::normalize_ty_after_erasing_regions,
         program_clauses_for: lowering::program_clauses_for,
+        program_clauses_for_env: lowering::program_clauses_for_env,
         ..*p
     };
 }
index 36e60cee788dc6ea2f04ad9e947b09d84843804e..b6a086f609d0494245fe883c6cdcf64323b8a889 100644 (file)
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::hir::{self, ImplPolarity};
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::ty::{self, Slice, TyCtxt};
+use rustc::hir::map::definitions::DefPathData;
+use rustc::hir::{self, ImplPolarity};
+use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause,
+                    WhereClauseAtom};
 use rustc::ty::subst::Substs;
-use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause, Goal};
+use rustc::ty::{self, Slice, TyCtxt};
+use rustc_data_structures::fx::FxHashSet;
+use std::mem;
 use syntax::ast;
-use rustc_data_structures::sync::Lrc;
 
 use std::iter;
 
@@ -24,7 +27,10 @@ trait Lower<T> {
     fn lower(&self) -> T;
 }
 
-impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
+impl<T, U> Lower<Vec<U>> for Vec<T>
+where
+    T: Lower<U>,
+{
     fn lower(&self) -> Vec<U> {
         self.iter().map(|item| item.lower()).collect()
     }
@@ -42,7 +48,10 @@ fn lower(&self) -> WhereClauseAtom<'tcx> {
     }
 }
 
-impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
+impl<'tcx, T> Lower<DomainGoal<'tcx>> for T
+where
+    T: Lower<WhereClauseAtom<'tcx>>,
+{
     fn lower(&self) -> DomainGoal<'tcx> {
         DomainGoal::Holds(self.lower())
     }
@@ -67,7 +76,8 @@ fn lower(&self) -> DomainGoal<'tcx> {
 /// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
 /// `Binder<Holds(Implemented(TraitPredicate))>`.
 impl<'tcx, T> Lower<PolyDomainGoal<'tcx>> for ty::Binder<T>
-    where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx>
+where
+    T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx>,
 {
     fn lower(&self) -> PolyDomainGoal<'tcx> {
         self.map_bound_ref(|p| p.lower())
@@ -84,10 +94,9 @@ fn lower(&self) -> PolyDomainGoal<'tcx> {
             TypeOutlives(predicate) => predicate.lower(),
             Projection(predicate) => predicate.lower(),
             WellFormed(ty) => ty::Binder::dummy(DomainGoal::WellFormedTy(*ty)),
-            ObjectSafe(..) |
-            ClosureKind(..) |
-            Subtype(..) |
-            ConstEvaluatable(..) => unimplemented!(),
+            ObjectSafe(..) | ClosureKind(..) | Subtype(..) | ConstEvaluatable(..) => {
+                unimplemented!()
+            }
         }
     }
 }
@@ -104,44 +113,88 @@ fn into_from_env_goal(self) -> DomainGoal<'tcx> {
         use self::DomainGoal::*;
         match self {
             Holds(wc_atom) => FromEnv(wc_atom),
-            WellFormed(..) |
-            FromEnv(..) |
-            WellFormedTy(..) |
-            FromEnvTy(..) |
-            Normalize(..) |
-            RegionOutlives(..) |
-            TypeOutlives(..) => self,
+            WellFormed(..) | FromEnv(..) | WellFormedTy(..) | FromEnvTy(..) | Normalize(..)
+            | RegionOutlives(..) | TypeOutlives(..) => self,
         }
     }
 }
 
-crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                                       -> Lrc<&'tcx Slice<Clause<'tcx>>>
-{
-    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-    let node = tcx.hir.find(node_id).unwrap();
-    match node {
-        hir::map::Node::NodeItem(item) => match item.node {
-            hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
-            hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
-            _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
-        }
-        hir::map::Node::NodeImplItem(item) => {
-            if let hir::ImplItemKind::Type(..) = item.node {
-                program_clauses_for_associated_type_value(tcx, def_id)
-            } else {
-                Lrc::new(tcx.mk_clauses(iter::empty::<Clause>()))
-            }
-        },
+crate fn program_clauses_for<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+) -> Clauses<'tcx> {
+    match tcx.def_key(def_id).disambiguated_data.data {
+        DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
+        DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
+        DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
+        _ => Slice::empty(),
+    }
+}
 
-        // FIXME: other constructions e.g. traits, associated types...
-        _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
+crate fn program_clauses_for_env<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> Clauses<'tcx> {
+    debug!("program_clauses_for_env(param_env={:?})", param_env);
+
+    let mut last_round = FxHashSet();
+    last_round.extend(
+        param_env
+            .caller_bounds
+            .iter()
+            .flat_map(|&p| predicate_def_id(p)),
+    );
+
+    let mut closure = last_round.clone();
+    let mut next_round = FxHashSet();
+    while !last_round.is_empty() {
+        next_round.extend(
+            last_round
+                .drain()
+                .flat_map(|def_id| {
+                    tcx.predicates_of(def_id)
+                        .instantiate_identity(tcx)
+                        .predicates
+                })
+                .flat_map(|p| predicate_def_id(p))
+                .filter(|&def_id| closure.insert(def_id)),
+        );
+        mem::swap(&mut next_round, &mut last_round);
+    }
+
+    debug!("program_clauses_for_env: closure = {:#?}", closure);
+
+    return tcx.mk_clauses(
+        closure
+            .into_iter()
+            .flat_map(|def_id| tcx.program_clauses_for(def_id).iter().cloned()),
+    );
+
+    /// Given that `predicate` is in the environment, returns the
+    /// def-id of something (e.g., a trait, associated item, etc)
+    /// whose predicates can also be assumed to be true. We will
+    /// compute the transitive closure of such things.
+    fn predicate_def_id<'tcx>(predicate: ty::Predicate<'tcx>) -> Option<DefId> {
+        match predicate {
+            ty::Predicate::Trait(predicate) => Some(predicate.def_id()),
+
+            ty::Predicate::Projection(projection) => Some(projection.item_def_id()),
+
+            ty::Predicate::WellFormed(..)
+            | ty::Predicate::RegionOutlives(..)
+            | ty::Predicate::TypeOutlives(..)
+            | ty::Predicate::ObjectSafe(..)
+            | ty::Predicate::ClosureKind(..)
+            | ty::Predicate::Subtype(..)
+            | ty::Predicate::ConstEvaluatable(..) => None,
+        }
     }
 }
 
-fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                                       -> Lrc<&'tcx Slice<Clause<'tcx>>>
-{
+fn program_clauses_for_trait<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+) -> Clauses<'tcx> {
     // `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
 
     // Rule Implemented-From-Env (see rustc guide)
@@ -156,8 +209,8 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
     let trait_pred = ty::TraitPredicate {
         trait_ref: ty::TraitRef {
             def_id,
-            substs: Substs::identity_for_item(tcx, def_id)
-        }
+            substs: Substs::identity_for_item(tcx, def_id),
+        },
     };
     // `FromEnv(Self: Trait<P1..Pn>)`
     let from_env = Goal::from(DomainGoal::FromEnv(trait_pred.lower()));
@@ -169,9 +222,7 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
         goal: impl_trait,
         hypotheses: tcx.mk_goals(iter::once(from_env)),
     };
-    let clauses = iter::once(
-        Clause::ForAll(ty::Binder::dummy(implemented_from_env))
-    );
+    let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env)));
 
     // Rule Implied-Bound-From-Trait
     //
@@ -186,11 +237,11 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
     // FIXME: Remove the [1..] slice; this is a hack because the query
     // predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
     let where_clauses = &tcx.predicates_of(def_id).predicates;
-    let implied_bound_clauses =
-        where_clauses[1..].into_iter()
+    let implied_bound_clauses = where_clauses[1..]
+        .into_iter()
         .map(|wc| implied_bound_from_trait(tcx, trait_pred, wc));
 
-    Lrc::new(tcx.mk_clauses(clauses.chain(implied_bound_clauses)))
+    tcx.mk_clauses(clauses.chain(implied_bound_clauses))
 }
 
 /// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`.
@@ -203,19 +254,15 @@ fn implied_bound_from_trait<'a, 'tcx>(
     let impl_trait = DomainGoal::FromEnv(WhereClauseAtom::Implemented(trait_pred));
 
     // `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
-    Clause::ForAll(
-        where_clause.lower().map_bound(|goal| ProgramClause {
-            goal: goal.into_from_env_goal(),
-            hypotheses: tcx.mk_goals(iter::once(Goal::from(impl_trait))),
-        })
-    )
+    Clause::ForAll(where_clause.lower().map_bound(|goal| ProgramClause {
+        goal: goal.into_from_env_goal(),
+        hypotheses: tcx.mk_goals(iter::once(Goal::from(impl_trait))),
+    }))
 }
 
-fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                                      -> Lrc<&'tcx Slice<Clause<'tcx>>>
-{
+fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Clauses<'tcx> {
     if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
-        return Lrc::new(tcx.mk_clauses(iter::empty::<Clause>()));
+        return Slice::empty();
     }
 
     // Rule Implemented-From-Impl (see rustc guide)
@@ -231,23 +278,25 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
     let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
     // `Implemented(A0: Trait<A1..An>)`
     let trait_pred = ty::TraitPredicate { trait_ref }.lower();
-     // `WC`
+    // `WC`
     let where_clauses = tcx.predicates_of(def_id).predicates.lower();
 
-     // `Implemented(A0: Trait<A1..An>) :- WC`
+    // `Implemented(A0: Trait<A1..An>) :- WC`
     let clause = ProgramClause {
         goal: trait_pred,
         hypotheses: tcx.mk_goals(
-            where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx))
-        )
+            where_clauses
+                .into_iter()
+                .map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
+        ),
     };
-    Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))))
+    tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
 }
 
 pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     item_id: DefId,
-) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
+) -> Clauses<'tcx> {
     // Rule Normalize-From-Impl (see rustc guide)
     //
     // ```impl<P0..Pn> Trait<A1..An> for A0
@@ -290,10 +339,12 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
     let clause = ProgramClause {
         goal: normalize_goal,
         hypotheses: tcx.mk_goals(
-            where_clauses.into_iter().map(|wc| Goal::from_poly_domain_goal(wc, tcx))
+            where_clauses
+                .into_iter()
+                .map(|wc| Goal::from_poly_domain_goal(wc, tcx)),
         ),
     };
-    Lrc::new(tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))))
+    tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
 }
 
 pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -302,27 +353,54 @@ pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     }
 
     let mut visitor = ClauseDumper { tcx };
-    tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+    tcx.hir
+        .krate()
+        .visit_all_item_likes(&mut visitor.as_deep_visitor());
 }
 
 struct ClauseDumper<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
-impl<'a, 'tcx> ClauseDumper<'a, 'tcx > {
+impl<'a, 'tcx> ClauseDumper<'a, 'tcx> {
     fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
         let def_id = self.tcx.hir.local_def_id(node_id);
         for attr in attrs {
+            let mut clauses = None;
+
             if attr.check_name("rustc_dump_program_clauses") {
-                let clauses = self.tcx.program_clauses_for(def_id);
-                for clause in *clauses {
-                    // Skip the top-level binder for a less verbose output
-                    let program_clause = match clause {
-                        Clause::Implies(program_clause) => program_clause,
-                        Clause::ForAll(program_clause) => program_clause.skip_binder(),
-                    };
-                    self.tcx.sess.struct_span_err(attr.span, &format!("{}", program_clause)).emit();
+                clauses = Some(self.tcx.program_clauses_for(def_id));
+            }
+
+            if attr.check_name("rustc_dump_env_program_clauses") {
+                let param_env = self.tcx.param_env(def_id);
+                clauses = Some(self.tcx.program_clauses_for_env(param_env));
+            }
+
+            if let Some(clauses) = clauses {
+                let mut err = self.tcx
+                    .sess
+                    .struct_span_err(attr.span, "program clause dump");
+
+                let mut strings: Vec<_> = clauses
+                    .iter()
+                    .map(|clause| {
+                        // Skip the top-level binder for a less verbose output
+                        let program_clause = match clause {
+                            Clause::Implies(program_clause) => program_clause,
+                            Clause::ForAll(program_clause) => program_clause.skip_binder(),
+                        };
+                        format!("{}", program_clause)
+                    })
+                    .collect();
+
+                strings.sort();
+
+                for string in strings {
+                    err.note(&string);
                 }
+
+                err.emit();
             }
         }
     }
index bff070ab73de342f06fab3ac80c225277594057e..f25906a7bcad1593e3fff4e003bf671e4c7241d7 100644 (file)
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 use rustc::infer::InferCtxt;
-use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints,
-                              QueryResult};
+use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult};
 use rustc::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc::traits::{FulfillmentContext, TraitEngine};
 use rustc::traits::query::NoSolution;
@@ -62,7 +61,7 @@
 
     let region_obligations = infcx.take_registered_region_obligations();
 
-    let (region_outlives, ty_outlives) = infcx.with_region_constraints(|region_constraints| {
+    let region_constraints = infcx.with_region_constraints(|region_constraints| {
         let RegionConstraintData {
             constraints,
             verifys,
         assert!(verifys.is_empty());
         assert!(givens.is_empty());
 
-        let region_outlives: Vec<_> = constraints
+        let mut outlives: Vec<_> = constraints
             .into_iter()
             .map(|(k, _)| match *k {
-                Constraint::VarSubVar(v1, v2) => {
-                    (tcx.mk_region(ty::ReVar(v1)), tcx.mk_region(ty::ReVar(v2)))
+                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
+                    tcx.mk_region(ty::ReVar(v1)).into(),
+                    tcx.mk_region(ty::ReVar(v2)),
+                ),
+                Constraint::VarSubReg(v1, r2) => {
+                    ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v1)).into(), r2)
                 }
-                Constraint::VarSubReg(v1, r2) => (tcx.mk_region(ty::ReVar(v1)), r2),
-                Constraint::RegSubVar(r1, v2) => (r1, tcx.mk_region(ty::ReVar(v2))),
-                Constraint::RegSubReg(r1, r2) => (r1, r2),
+                Constraint::RegSubVar(r1, v2) => {
+                    ty::OutlivesPredicate(r1.into(), tcx.mk_region(ty::ReVar(v2)))
+                }
+                Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r1.into(), r2),
             })
+            .map(ty::Binder) // no bound regions in the code above
             .collect();
 
-        let ty_outlives: Vec<_> = region_obligations
-            .into_iter()
-            .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
-            .collect();
+        outlives.extend(
+            region_obligations
+                .into_iter()
+                .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
+                .map(ty::Binder) // no bound regions in the code above
+        );
 
-        (region_outlives, ty_outlives)
+        outlives
     });
 
     let certainty = if ambig_errors.is_empty() {
 
     let (canonical_result, _) = infcx.canonicalize_response(&QueryResult {
         var_values: inference_vars,
-        region_constraints: QueryRegionConstraints {
-            region_outlives,
-            ty_outlives,
-        },
+        region_constraints,
         certainty,
         value: answer,
     });
index f2dd2ed8460ebbfa65d1776cae8d703d1a5c8d1b..ffebb959ebfde494abdd58d680e008da35f76f18 100644 (file)
@@ -43,13 +43,11 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
                 AllocatorTy::Ptr => args.push(i8p),
                 AllocatorTy::Usize => args.push(usize),
 
-                AllocatorTy::Bang |
                 AllocatorTy::ResultPtr |
                 AllocatorTy::Unit => panic!("invalid allocator arg"),
             }
         }
         let output = match method.output {
-            AllocatorTy::Bang => None,
             AllocatorTy::ResultPtr => Some(i8p),
             AllocatorTy::Unit => None,
 
index 1da6f25fd639a0506daac80ef52e1e0d04359e30..a4e1b7f2925dca3f802ff23bc9ada907f3a4f8e6 100644 (file)
@@ -492,7 +492,7 @@ pub fn trans_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tc
     // You can also find more info on why Windows is whitelisted here in:
     //      https://bugzilla.mozilla.org/show_bug.cgi?id=1302078
     if !cx.sess().no_landing_pads() ||
-       cx.sess().target.target.options.is_like_windows {
+       cx.sess().target.target.options.requires_uwtable {
         attributes::emit_uwtable(lldecl, true);
     }
 
index 75df349de41ee9d7075a90c36f407bd3e9157854..656ab95a28cf3e1730c78092260dc9ec40e9fb90 100644 (file)
@@ -399,7 +399,14 @@ pub fn trans_operand(&mut self,
                 self.mir_constant_to_miri_value(bx, constant)
                     .and_then(|c| OperandRef::from_const(bx, c, ty))
                     .unwrap_or_else(|err| {
-                        err.report(bx.tcx(), constant.span, "const operand");
+                        match constant.literal {
+                            mir::Literal::Promoted { .. } => {
+                                // don't report errors inside promoteds, just warnings.
+                            },
+                            mir::Literal::Value { .. } => {
+                                err.report(bx.tcx(), constant.span, "const operand")
+                            },
+                        }
                         // We've errored, so we don't have to produce working code.
                         let layout = bx.cx.layout_of(ty);
                         PlaceRef::new_sized(
index de5709566225c54cc595f7340155edbc9264fdf7..073f36b9f3c505b2000ad42f152211d33d602ce9 100644 (file)
@@ -471,6 +471,9 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
             ty::TyStr => {
                 let lang_def_id = lang_items.str_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.str_alloc_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TySlice(_) => {
                 let lang_def_id = lang_items.slice_impl();
@@ -478,6 +481,12 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
 
                 let lang_def_id = lang_items.slice_u8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.slice_alloc_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.slice_u8_alloc_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 let lang_def_id = lang_items.const_ptr_impl();
@@ -538,10 +547,16 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
             ty::TyFloat(ast::FloatTy::F32) => {
                 let lang_def_id = lang_items.f32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.f32_runtime_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyFloat(ast::FloatTy::F64) => {
                 let lang_def_id = lang_items.f64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.f64_runtime_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             _ => {}
         }
index ca35153d571dbd0048cf8ada21af03d6d5832a04..acde10a6396936b445b83aae2f97e72f40519c1c 100644 (file)
@@ -2217,7 +2217,8 @@ fn resolve_generator_interiors(&self, def_id: DefId) {
     }
 
     // Tries to apply a fallback to `ty` if it is an unsolved variable.
-    // Non-numerics get replaced with !, unconstrained ints with i32,
+    // Non-numerics get replaced with ! or () (depending on whether
+    // feature(never_type) is enabled, unconstrained ints with i32,
     // unconstrained floats with f64.
     // Fallback becomes very dubious if we have encountered type-checking errors.
     // In that case, fallback to TyError.
@@ -2231,7 +2232,7 @@ fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool {
             _ if self.is_tainted_by_errors() => self.tcx().types.err,
             UnconstrainedInt => self.tcx.types.i32,
             UnconstrainedFloat => self.tcx.types.f64,
-            Neither if self.type_var_diverges(ty) => self.tcx.types.never,
+            Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(),
             Neither => return false,
         };
         debug!("default_type_parameters: defaulting `{:?}` to `{:?}`", ty, fallback);
index d43ab0d3713cb93c9dc11b155818ae290cd7402e..532f1da4f301b4201ed6aa7b9b010baa59144631 100644 (file)
@@ -114,6 +114,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyChar => {
                 self.check_primitive_impl(def_id,
                                           lang_items.char_impl(),
+                                          None,
                                           "char",
                                           "char",
                                           item.span);
@@ -121,6 +122,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyStr => {
                 self.check_primitive_impl(def_id,
                                           lang_items.str_impl(),
+                                          lang_items.str_alloc_impl(),
                                           "str",
                                           "str",
                                           item.span);
@@ -128,6 +130,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_u8_impl(),
+                                          lang_items.slice_u8_alloc_impl(),
                                           "slice_u8",
                                           "[u8]",
                                           item.span);
@@ -135,6 +138,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TySlice(_) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_impl(),
+                                          lang_items.slice_alloc_impl(),
                                           "slice",
                                           "[T]",
                                           item.span);
@@ -142,6 +146,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.const_ptr_impl(),
+                                          None,
                                           "const_ptr",
                                           "*const T",
                                           item.span);
@@ -149,6 +154,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.mut_ptr_impl(),
+                                          None,
                                           "mut_ptr",
                                           "*mut T",
                                           item.span);
@@ -156,6 +162,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I8) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i8_impl(),
+                                          None,
                                           "i8",
                                           "i8",
                                           item.span);
@@ -163,6 +170,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I16) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i16_impl(),
+                                          None,
                                           "i16",
                                           "i16",
                                           item.span);
@@ -170,6 +178,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i32_impl(),
+                                          None,
                                           "i32",
                                           "i32",
                                           item.span);
@@ -177,6 +186,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i64_impl(),
+                                          None,
                                           "i64",
                                           "i64",
                                           item.span);
@@ -184,6 +194,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::I128) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.i128_impl(),
+                                          None,
                                           "i128",
                                           "i128",
                                           item.span);
@@ -191,6 +202,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyInt(ast::IntTy::Isize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.isize_impl(),
+                                          None,
                                           "isize",
                                           "isize",
                                           item.span);
@@ -198,6 +210,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U8) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u8_impl(),
+                                          None,
                                           "u8",
                                           "u8",
                                           item.span);
@@ -205,6 +218,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U16) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u16_impl(),
+                                          None,
                                           "u16",
                                           "u16",
                                           item.span);
@@ -212,6 +226,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u32_impl(),
+                                          None,
                                           "u32",
                                           "u32",
                                           item.span);
@@ -219,6 +234,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u64_impl(),
+                                          None,
                                           "u64",
                                           "u64",
                                           item.span);
@@ -226,6 +242,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::U128) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.u128_impl(),
+                                          None,
                                           "u128",
                                           "u128",
                                           item.span);
@@ -233,6 +250,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyUint(ast::UintTy::Usize) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.usize_impl(),
+                                          None,
                                           "usize",
                                           "usize",
                                           item.span);
@@ -240,6 +258,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyFloat(ast::FloatTy::F32) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.f32_impl(),
+                                          lang_items.f32_runtime_impl(),
                                           "f32",
                                           "f32",
                                           item.span);
@@ -247,6 +266,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             ty::TyFloat(ast::FloatTy::F64) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.f64_impl(),
+                                          lang_items.f64_runtime_impl(),
                                           "f64",
                                           "f64",
                                           item.span);
@@ -305,11 +325,15 @@ fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
     fn check_primitive_impl(&self,
                             impl_def_id: DefId,
                             lang_def_id: Option<DefId>,
+                            lang_def_id2: Option<DefId>,
                             lang: &str,
                             ty: &str,
                             span: Span) {
-        match lang_def_id {
-            Some(lang_def_id) if lang_def_id == impl_def_id => {
+        match (lang_def_id, lang_def_id2) {
+            (Some(lang_def_id), _) if lang_def_id == impl_def_id => {
+                // OK
+            }
+            (_, Some(lang_def_id)) if lang_def_id == impl_def_id => {
                 // OK
             }
             _ => {
index 6bd38244e8caf9956f02233c0b518552e2a69fad..a1eb043995abaa2939c135e3868b18f80e19960b 100644 (file)
@@ -1682,6 +1682,7 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 fn from_target_feature(
     tcx: TyCtxt,
+    id: DefId,
     attr: &ast::Attribute,
     whitelist: &FxHashMap<String, Option<String>>,
     target_features: &mut Vec<Symbol>,
@@ -1752,7 +1753,7 @@ fn from_target_feature(
                 Some(name) => bug!("unknown target feature gate {}", name),
                 None => true,
             };
-            if !allowed {
+            if !allowed && id.is_local() {
                 feature_gate::emit_feature_err(
                     &tcx.sess.parse_sess,
                     feature_gate.as_ref().unwrap(),
@@ -1877,7 +1878,7 @@ fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAt
                            `unsafe` function";
                 tcx.sess.span_err(attr.span, msg);
             }
-            from_target_feature(tcx, attr, &whitelist, &mut trans_fn_attrs.target_features);
+            from_target_feature(tcx, id, attr, &whitelist, &mut trans_fn_attrs.target_features);
         } else if attr.check_name("linkage") {
             if let Some(val) = attr.value_str() {
                 trans_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
index ae3b2b22ea114c198218bc5c54d46e1907fe9aa7..e3f7ff5cb3f74406c4bf809adf29e31716e63e28 100644 (file)
@@ -4526,23 +4526,23 @@ fn foo<U: Iterator>(&self, _: &U) { } // error method `foo` has incompatible
 The error happens on numeric literals:
 
 ```compile_fail,E0689
-2.0.powi(2);
+2.0.recip();
 ```
 
 and on numeric bindings without an identified concrete type:
 
 ```compile_fail,E0689
 let x = 2.0;
-x.powi(2);  // same error as above
+x.recip();  // same error as above
 ```
 
 Because of this, you must give the numeric literal or binding a type:
 
 ```
-let _ = 2.0_f32.powi(2);
+let _ = 2.0_f32.recip();
 let x: f32 = 2.0;
-let _ = x.powi(2);
-let _ = (2.0 as f32).powi(2);
+let _ = x.recip();
+let _ = (2.0 as f32).recip();
 ```
 "##,
 
index 4b66939963ed0a37add319284a78a58ae130fb4e..ed0cfe38a7ad95c7d4218d271f45e1ebdeb62f45 100644 (file)
@@ -82,6 +82,7 @@
 #![feature(slice_patterns)]
 #![feature(slice_sort_by_cached_key)]
 #![feature(dyn_trait)]
+#![feature(never_type)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
index 32f23e923d91ba8121caf583fa4d330c7ff747a2..23e0c2625eeeb6b0607d2d7fa8d63cdc1211e251 100644 (file)
@@ -286,10 +286,15 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
         lang_items.u128_impl(),
         lang_items.f32_impl(),
         lang_items.f64_impl(),
+        lang_items.f32_runtime_impl(),
+        lang_items.f64_runtime_impl(),
         lang_items.char_impl(),
         lang_items.str_impl(),
         lang_items.slice_impl(),
         lang_items.slice_u8_impl(),
+        lang_items.str_alloc_impl(),
+        lang_items.slice_alloc_impl(),
+        lang_items.slice_u8_alloc_impl(),
         lang_items.const_ptr_impl(),
         lang_items.mut_ptr_impl(),
     ];
index 9fb024fd906099859e86becb2d3136af9fc09736..2bd1e72f0eb173057cdecbf2ac264145bfe6ef64 100644 (file)
@@ -155,10 +155,10 @@ pub fn run_core(search_paths: SearchPaths,
         actually_rustdoc: true,
         debugging_opts: config::DebuggingOptions {
             force_unstable_if_unmarked,
-            edition,
             ..config::basic_debugging_options()
         },
         error_format,
+        edition,
         ..config::basic_options().clone()
     };
 
index e9c6488c49c6cb0f9c90ea74b268fc95b136f28e..537828de2c7f35fd56bdabc7a4e89b5400c60675 100644 (file)
@@ -19,7 +19,7 @@
 /// discriminants. JavaScript then is used to decode them into the original value.
 /// Consequently, every change to this type should be synchronized to
 /// the `itemTypes` mapping table in `static/main.js`.
-#[derive(Copy, PartialEq, Clone)]
+#[derive(Copy, PartialEq, Clone, Debug)]
 pub enum ItemType {
     Module          = 0,
     ExternCrate     = 1,
index 583c9f2b671441f0602e83887071add233727089..fd54e9bd1e06c3ab340cd2ed118537cef3085e74 100644 (file)
@@ -85,6 +85,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
                        autocomplete=\"off\" \
                        placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                        type=\"search\">\
+                <a id=\"settings-menu\" href=\"{root_path}settings.html\">\
+                    <img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\
+                </a>\
             </div>\
         </form>\
     </nav>\
@@ -145,6 +148,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     </script>\
     <script src=\"{root_path}main{suffix}.js\"></script>\
     <script defer src=\"{root_path}search-index.js\"></script>\
+    <script defer src=\"{root_path}aliases.js\"></script>\
 </body>\
 </html>",
     css_extension = if css_file_extension {
@@ -181,9 +185,10 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
     themes = themes.iter()
                    .filter_map(|t| t.file_stem())
                    .filter_map(|t| t.to_str())
-                   .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}">"#,
+                   .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#,
                                     page.root_path,
-                                    t.replace(".css", &format!("{}.css", page.resource_suffix))))
+                                    t,
+                                    page.resource_suffix))
                    .collect::<String>(),
     suffix=page.resource_suffix,
     )
index 651319743aadde640626ca7103e71c01c8c816ee..0ae946c4182864e39111e9a2202e2b769899f987 100644 (file)
@@ -329,6 +329,10 @@ pub struct Cache {
     // yet when its implementation methods are being indexed. Caches such methods
     // and their parent id here and indexes them at the end of crate parsing.
     orphan_impl_items: Vec<(DefId, clean::Item)>,
+
+    /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
+    /// we need the alias element to have an array of items.
+    aliases: FxHashMap<String, Vec<IndexItem>>,
 }
 
 /// Temporary storage for data obtained during `RustdocVisitor::clean()`.
@@ -369,6 +373,7 @@ struct Sidebar<'a> { cx: &'a Context, item: &'a clean::Item, }
 
 /// Struct representing one entry in the JS search index. These are all emitted
 /// by hand to a large JS file at the end of cache-creation.
+#[derive(Debug)]
 struct IndexItem {
     ty: ItemType,
     name: String,
@@ -396,6 +401,7 @@ fn to_json(&self) -> Json {
 }
 
 /// A type used for the search index.
+#[derive(Debug)]
 struct Type {
     name: Option<String>,
     generics: Option<Vec<String>>,
@@ -418,9 +424,10 @@ fn to_json(&self) -> Json {
 }
 
 /// Full type of functions/methods in the search index.
+#[derive(Debug)]
 struct IndexItemFunctionType {
     inputs: Vec<Type>,
-    output: Option<Type>
+    output: Option<Type>,
 }
 
 impl ToJson for IndexItemFunctionType {
@@ -609,6 +616,7 @@ pub fn run(mut krate: clean::Crate,
         owned_box_did,
         masked_crates: mem::replace(&mut krate.masked_crates, FxHashSet()),
         typarams: external_typarams,
+        aliases: FxHashMap(),
     };
 
     // Cache where all our extern crates are located
@@ -742,6 +750,8 @@ fn write_shared(cx: &Context,
 
     write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
           include_bytes!("static/rustdoc.css"))?;
+    write(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
+          include_bytes!("static/settings.css"))?;
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
     // then we'll run over the "official" styles.
@@ -761,6 +771,8 @@ fn write_shared(cx: &Context,
 
     write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
           include_bytes!("static/brush.svg"))?;
+    write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
+          include_bytes!("static/wheel.svg"))?;
     write(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
           include_bytes!("static/themes/light.css"))?;
     themes.insert("light".to_owned());
@@ -794,8 +806,7 @@ fn write_shared(cx: &Context,
         switchTheme(currentTheme, mainTheme, item);
     }};
     themes.appendChild(but);
-}});
-"#,
+}});"#,
                  themes.iter()
                        .map(|s| format!("\"{}\"", s))
                        .collect::<Vec<String>>()
@@ -804,6 +815,8 @@ fn write_shared(cx: &Context,
 
     write(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)),
                       include_bytes!("static/main.js"))?;
+    write(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)),
+                      include_bytes!("static/settings.js"))?;
 
     {
         let mut data = format!("var resourcesSuffix = \"{}\";\n",
@@ -847,8 +860,7 @@ fn write_shared(cx: &Context,
     write(cx.dst.join("COPYRIGHT.txt"),
           include_bytes!("static/COPYRIGHT.txt"))?;
 
-    fn collect(path: &Path, krate: &str,
-               key: &str) -> io::Result<Vec<String>> {
+    fn collect(path: &Path, krate: &str, key: &str) -> io::Result<Vec<String>> {
         let mut ret = Vec::new();
         if path.exists() {
             for line in BufReader::new(File::open(path)?).lines() {
@@ -865,6 +877,40 @@ fn collect(path: &Path, krate: &str,
         Ok(ret)
     }
 
+    fn show_item(item: &IndexItem, krate: &str) -> String {
+        format!("{{'crate':'{}','ty':{},'name':'{}','path':'{}'{}}}",
+                krate, item.ty as usize, item.name, item.path,
+                if let Some(p) = item.parent_idx {
+                    format!(",'parent':{}", p)
+                } else {
+                    String::new()
+                })
+    }
+
+    let dst = cx.dst.join("aliases.js");
+    {
+        let mut all_aliases = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
+        let mut w = try_err!(File::create(&dst), &dst);
+        let mut output = String::with_capacity(100);
+        for (alias, items) in &cache.aliases {
+            if items.is_empty() {
+                continue
+            }
+            output.push_str(&format!("\"{}\":[{}],",
+                                     alias,
+                                     items.iter()
+                                          .map(|v| show_item(v, &krate.name))
+                                          .collect::<Vec<_>>()
+                                          .join(",")));
+        }
+        all_aliases.push(format!("ALIASES['{}'] = {{{}}};", krate.name, output));
+        all_aliases.sort();
+        try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst);
+        for aliases in &all_aliases {
+            try_err!(writeln!(&mut w, "{}", aliases), &dst);
+        }
+    }
+
     // Update the search index
     let dst = cx.dst.join("search-index.js");
     let mut all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
@@ -1251,13 +1297,13 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 // `public_items` map, so we can skip inserting into the
                 // paths map if there was already an entry present and we're
                 // not a public item.
-                if
-                    !self.paths.contains_key(&item.def_id) ||
-                    self.access_levels.is_public(item.def_id)
+                if !self.paths.contains_key(&item.def_id) ||
+                   self.access_levels.is_public(item.def_id)
                 {
                     self.paths.insert(item.def_id,
                                       (self.stack.clone(), item.type_()));
                 }
+                self.add_aliases(&item);
             }
             // Link variants to their parent enum because pages aren't emitted
             // for each variant.
@@ -1268,6 +1314,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             }
 
             clean::PrimitiveItem(..) if item.visibility.is_some() => {
+                self.add_aliases(&item);
                 self.paths.insert(item.def_id, (self.stack.clone(),
                                                 item.type_()));
             }
@@ -1372,6 +1419,36 @@ fn generics(&mut self, generics: &clean::Generics) {
             }
         }
     }
+
+    fn add_aliases(&mut self, item: &clean::Item) {
+        if item.def_id.index == CRATE_DEF_INDEX {
+            return
+        }
+        if let Some(ref item_name) = item.name {
+            let path = self.paths.get(&item.def_id)
+                                 .map(|p| p.0.join("::").to_string())
+                                 .unwrap_or("std".to_owned());
+            for alias in item.attrs.lists("doc")
+                                   .filter(|a| a.check_name("alias"))
+                                   .filter_map(|a| a.value_str()
+                                                    .map(|s| s.to_string().replace("\"", "")))
+                                   .filter(|v| !v.is_empty())
+                                   .collect::<FxHashSet<_>>()
+                                   .into_iter() {
+                self.aliases.entry(alias)
+                            .or_insert(Vec::with_capacity(1))
+                            .push(IndexItem {
+                                ty: item.type_(),
+                                name: item_name.to_string(),
+                                path: path.clone(),
+                                desc: String::new(),
+                                parent: None,
+                                parent_idx: None,
+                                search_type: get_index_search_type(&item),
+                            });
+            }
+        }
+    }
 }
 
 #[derive(Debug, Eq, PartialEq, Hash)]
@@ -1503,6 +1580,51 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+#[derive(Debug)]
+struct Settings<'a> {
+    // (id, explanation, default value)
+    settings: Vec<(&'static str, &'static str, bool)>,
+    root_path: &'a str,
+    suffix: &'a str,
+}
+
+impl<'a> Settings<'a> {
+    pub fn new(root_path: &'a str, suffix: &'a str) -> Settings<'a> {
+        Settings {
+            settings: vec![
+                ("item-declarations", "Auto-hide item declarations.", true),
+                ("item-attributes", "Auto-hide item attributes.", true),
+            ],
+            root_path,
+            suffix,
+        }
+    }
+}
+
+impl<'a> fmt::Display for Settings<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f,
+"<h1 class='fqn'>\
+     <span class='in-band'>Rustdoc settings</span>\
+</h1>\
+<div class='settings'>{}</div>\
+<script src='{}settings{}.js'></script>",
+               self.settings.iter()
+                            .map(|(id, text, enabled)| {
+                                format!("<div class='setting-line'>\
+                                             <label class='toggle'>\
+                                                <input type='checkbox' id='{}' {}>\
+                                                <span class='slider'></span>\
+                                             </label>\
+                                             <div>{}</div>\
+                                         </div>", id, if *enabled { " checked" } else { "" }, text)
+                            })
+                            .collect::<String>(),
+               self.root_path,
+               self.suffix)
+    }
+}
+
 impl Context {
     /// String representation of how to get back to the root path of the 'doc/'
     /// folder in terms of a relative URL.
@@ -1546,6 +1668,8 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
         };
         let final_file = self.dst.join(&krate.name)
                                  .join("all.html");
+        let settings_file = self.dst.join("settings.html");
+
         let crate_name = krate.name.clone();
         item.name = Some(krate.name);
 
@@ -1567,7 +1691,7 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
         if !root_path.ends_with('/') {
             root_path.push('/');
         }
-        let page = layout::Page {
+        let mut page = layout::Page {
             title: "List of all items in this crate",
             css_class: "mod",
             root_path: "../",
@@ -1590,6 +1714,27 @@ fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
                                 self.shared.css_file_extension.is_some(),
                                 &self.shared.themes),
                  &final_file);
+
+        // Generating settings page.
+        let settings = Settings::new("./", &self.shared.resource_suffix);
+        page.title = "Rustdoc settings";
+        page.description = "Settings of Rustdoc";
+        page.root_path = "./";
+
+        let mut w = BufWriter::new(try_err!(File::create(&settings_file), &settings_file));
+        let mut themes = self.shared.themes.clone();
+        let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
+        themes.push(PathBuf::from("settings.css"));
+        let mut layout = self.shared.layout.clone();
+        layout.krate = String::new();
+        layout.logo = String::new();
+        layout.favicon = String::new();
+        try_err!(layout::render(&mut w, &layout,
+                                &page, &sidebar, &settings,
+                                self.shared.css_file_extension.is_some(),
+                                &themes),
+                 &settings_file);
+
         Ok(())
     }
 
index 2546a9410a9f653a44fb12dc37aa80f9ab287a26..ef8bf2244d97763186352b7593fb50a3da93dd4a 100644 (file)
                     return false;
                 }
                 var end = start + className.length;
-                if (end < elemClass.length && elemClass[end] !== ' ') {
-                    return false;
-                }
-                return true;
+                return !(end < elemClass.length && elemClass[end] !== ' ');
             }
             if (start > 0 && elemClass[start - 1] !== ' ') {
                 return false;
             }
             var end = start + className.length;
-            if (end < elemClass.length && elemClass[end] !== ' ') {
-                return false;
-            }
-            return true;
+            return !(end < elemClass.length && elemClass[end] !== ' ');
         }
         return false;
     }
         } else if (ev.target.tagName === 'SPAN' && hasClass(ev.target.parentNode, 'line-numbers')) {
             var prev_id = 0;
 
-            var set_fragment = function (name) {
+            var set_fragment = function(name) {
                 if (browserSupportsHistoryApi()) {
                     history.replaceState(null, null, '#' + name);
                     window.hashchange();
                 query.search = val;
             // searching by type
             } else if (val.search("->") > -1) {
-                var trimmer = function (s) { return s.trim(); };
+                var trimmer = function(s) { return s.trim(); };
                 var parts = val.split("->").map(trimmer);
                 var input = parts[0];
                 // sort inputs so that order does not matter
                 }
             }
 
-            return {
+            var ret = {
                 'in_args': sortResults(results_in_args, true),
                 'returned': sortResults(results_returned, true),
                 'others': sortResults(results),
             };
+            if (ALIASES[window.currentCrate][query.raw]) {
+                var aliases = ALIASES[window.currentCrate][query.raw];
+                for (var i = 0; i < aliases.length; ++i) {
+                    ret['others'].unshift(aliases[i]);
+                    if (ret['others'].length > MAX_RESULTS) {
+                        ret['others'].pop();
+                    }
+                }
+            }
+            return ret;
         }
 
         /**
                 array.forEach(function(item) {
                     var name, type, href, displayPath;
 
-                    if (shown.indexOf(item) !== -1) {
+                    var id_ty = item.ty + item.path + item.name;
+                    if (shown.indexOf(id_ty) !== -1) {
                         return;
                     }
 
-                    shown.push(item);
+                    console.log(item);
+                    shown.push(id_ty);
                     name = item.name;
                     type = itemTypes[item.ty];
 
 
         function search(e) {
             var params = getQueryStringParams();
-            var query = getQuery(document.getElementsByClassName('search-input')[0].value);
+            var search_input = document.getElementsByClassName('search-input')[0];
+            var query = getQuery(search_input.value.trim());
 
             if (e) {
                 e.preventDefault();
             }
 
             if (!query.query || query.id === currentResults) {
+                if (query.query.length > 0) {
+                    putBackSearch(search_input);
+                }
                 return;
             }
 
         startSearch();
 
         // Draw a convenient sidebar of known crates if we have a listing
-        if (rootPath === '../') {
+        if (rootPath === '../' || rootPath === "./") {
             var sidebar = document.getElementsByClassName('sidebar-elems')[0];
             if (sidebar) {
                 var div = document.createElement('div');
                 crates.sort();
                 for (var i = 0; i < crates.length; ++i) {
                     var klass = 'crate';
-                    if (crates[i] === window.currentCrate) {
+                    if (rootPath !== "./" && crates[i] === window.currentCrate) {
                         klass += ' current';
                     }
                     var link = document.createElement('a');
-                    link.href = '../' + crates[i] + '/index.html';
+                    link.href = rootPath + crates[i] + '/index.html';
                     link.title = rawSearchIndex[crates[i]].doc;
                     link.className = klass;
                     link.textContent = crates[i];
                 otherMessage = '&nbsp;Show&nbsp;type&nbsp;declaration';
             }
             e.parentNode.insertBefore(createToggle(otherMessage), e);
-            if (otherMessage) {
+            if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") {
                 collapseDocs(e.previousSibling.childNodes[0], "toggle");
             }
         }
     onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) {
         onEach(e.getElementsByClassName('attributes'), function(i_e) {
             i_e.parentNode.insertBefore(createToggleWrapper(), i_e);
-            collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
+            if (getCurrentValue("rustdoc-item-attributes") !== "false") {
+                collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
+            }
         });
     });
 
         };
     });
 
+    function putBackSearch(search_input) {
+        if (search_input.value !== "") {
+            addClass(document.getElementById("main"), "hidden");
+            removeClass(document.getElementById("search"), "hidden");
+            if (browserSupportsHistoryApi()) {
+                history.replaceState(search_input.value,
+                                     "",
+                                     "?search=" + encodeURIComponent(search_input.value));
+            }
+        }
+    }
+
     var search_input = document.getElementsByClassName("search-input")[0];
 
     if (search_input) {
         search_input.onfocus = function() {
-            if (search_input.value !== "") {
-                addClass(document.getElementById("main"), "hidden");
-                removeClass(document.getElementById("search"), "hidden");
-                if (browserSupportsHistoryApi()) {
-                    history.replaceState(search_input.value,
-                                         "",
-                                         "?search=" + encodeURIComponent(search_input.value));
-                }
-            }
+            putBackSearch(this);
         };
     }
 
index 4c6c8dcfddafc033ba00137fa46cb416ac7396a1..d6b3ab26af8aebf5b7075eb81063744ce95ce744 100644 (file)
@@ -548,8 +548,16 @@ a {
 
 .block a.current.crate { font-weight: 500; }
 
+.search-container {
+       position: relative;
+}
+.search-container > .top-button {
+       position: absolute;
+       right: 0;
+       top: 10px;
+}
 .search-input {
-       width: 100%;
+       width: calc(100% - 34px);
        /* Override Normalize.css: we have margins and do
         not want to overflow - the `moz` attribute is necessary
         until Firefox 29, too early to drop at this point */
@@ -1224,7 +1232,14 @@ kbd {
        outline: none;
 }
 
-#theme-picker {
+#settings-menu {
+       position: absolute;
+       right: 0;
+       top: 10px;
+       outline: none;
+}
+
+#theme-picker, #settings-menu {
        padding: 4px;
        width: 27px;
        height: 29px;
diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/settings.css
new file mode 100644 (file)
index 0000000..34835f3
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * 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.
+ */
+
+.setting-line {
+       padding: 5px;
+}
+
+.setting-line > div {
+       max-width: calc(100% - 74px);
+       display: inline-block;
+       vertical-align: top;
+       font-size: 17px;
+       padding-top: 2px;
+}
+
+.toggle {
+       position: relative;
+       display: inline-block;
+       width: 45px;
+       height: 27px;
+       margin-right: 20px;
+}
+
+.toggle input {
+       display: none;
+}
+
+.slider {
+       position: absolute;
+       cursor: pointer;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 0;
+       background-color: #ccc;
+       -webkit-transition: .3s;
+       transition: .3s;
+}
+
+.slider:before {
+       position: absolute;
+       content: "";
+       height: 19px;
+       width: 19px;
+       left: 4px;
+       bottom: 4px;
+       background-color: white;
+       -webkit-transition: .3s;
+       transition: .3s;
+}
+
+input:checked + .slider {
+       background-color: #2196F3;
+}
+
+input:focus + .slider {
+       box-shadow: 0 0 1px #2196F3;
+}
+
+input:checked + .slider:before {
+       -webkit-transform: translateX(19px);
+       -ms-transform: translateX(19px);
+       transform: translateX(19px);
+}
\ No newline at end of file
diff --git a/src/librustdoc/html/static/settings.js b/src/librustdoc/html/static/settings.js
new file mode 100644 (file)
index 0000000..cc7c600
--- /dev/null
@@ -0,0 +1,41 @@
+/*!
+ * 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.
+ */
+
+(function () {
+    function changeSetting(settingName, isEnabled) {
+        updateLocalStorage('rustdoc-' + settingName, isEnabled);
+    }
+
+    function getSettingValue(settingName) {
+        return getCurrentValue('rustdoc-' + settingName);
+    }
+
+    function setEvents() {
+        var elems = document.getElementsByClassName("slider");
+        if (!elems || elems.length === 0) {
+            return;
+        }
+        for (var i = 0; i < elems.length; ++i) {
+            var toggle = elems[i].previousElementSibling;
+            var settingId = toggle.id;
+            var settingValue = getSettingValue(settingId);
+            if (settingValue !== null) {
+                toggle.checked = settingValue === "true";
+            }
+            toggle.onchange = function() {
+                changeSetting(this.id, this.checked);
+            };
+        }
+    }
+
+    setEvents();
+})();
index 93971a205bf35d71d2730370423d1950efbafd11..da4be7db5aa92b43088abbc4db36cba6ffc39431 100644 (file)
@@ -362,12 +362,13 @@ kbd {
        box-shadow-color: #c6cbd1;
 }
 
-#theme-picker {
+#theme-picker, #settings-menu {
        border-color: #e0e0e0;
        background: #f0f0f0;
 }
 
-#theme-picker:hover, #theme-picker:focus {
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus {
        border-color: #ffb900;
 }
 
index e13818b4bd27867fa9bc05f2ec8651378a6f97bd..12af01d2e249809e7cde52f89116c3db8839b1fc 100644 (file)
@@ -356,12 +356,13 @@ kbd {
        box-shadow-color: #c6cbd1;
 }
 
-#theme-picker {
+#theme-picker, #settings-menu {
        border-color: #e0e0e0;
        background-color: #fff;
 }
 
-#theme-picker:hover, #theme-picker:focus {
+#theme-picker:hover, #theme-picker:focus,
+#settings-menu:hover, #settings-menu:focus {
        border-color: #717171;
 }
 
diff --git a/src/librustdoc/html/static/wheel.svg b/src/librustdoc/html/static/wheel.svg
new file mode 100644 (file)
index 0000000..44381a4
--- /dev/null
@@ -0,0 +1 @@
+<?xml version="1.0" ?><!DOCTYPE svg  PUBLIC '-//W3C//DTD SVG 1.1//EN'  'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 27.434 29.5" height="29.5px" id="Capa_1" version="1.1" viewBox="0 0 27.434 29.5" width="27.434px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8   c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476   c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235   c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044   c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721   C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573   C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938   c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786   c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802   C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159   c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043   c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675   c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075   c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032   C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251   c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157   c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888   l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084   c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506   c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812   L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747   c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761   c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775   c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032   c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012   c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085   C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323   s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716   C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956   c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
\ No newline at end of file
index 8cd5f373efe108b7a711beb85b0f4c72338aa2ff..c4eaa48e49db62e47c6bb0bb3c4fc64b32f2871d 100644 (file)
@@ -80,9 +80,9 @@ pub fn run(input_path: &Path,
         lint_cap: Some(::rustc::lint::Level::Allow),
         actually_rustdoc: true,
         debugging_opts: config::DebuggingOptions {
-            edition,
             ..config::basic_debugging_options()
         },
+        edition,
         ..config::basic_options().clone()
     };
 
@@ -223,9 +223,9 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
         test: as_test_harness,
         unstable_features: UnstableFeatures::from_environment(),
         debugging_opts: config::DebuggingOptions {
-            edition,
             ..config::basic_debugging_options()
         },
+        edition,
         ..config::basic_options().clone()
     };
 
index ff578ec42d23088ce2594175b24f3c4aeddce1b8..a8578404467b1d3185b4322abf2eb2ed9374f748 100644 (file)
 #![unstable(issue = "32838", feature = "allocator_api")]
 
 #[doc(inline)] #[allow(deprecated)] pub use alloc_crate::alloc::Heap;
-#[doc(inline)] pub use alloc_crate::alloc::Global;
+#[doc(inline)] pub use alloc_crate::alloc::{Global, oom};
 #[doc(inline)] pub use alloc_system::System;
 #[doc(inline)] pub use core::alloc::*;
 
+#[cfg(not(stage0))]
+#[cfg(not(test))]
+#[doc(hidden)]
+#[lang = "oom"]
+pub extern fn rust_oom() -> ! {
+    rtabort!("memory allocation failed");
+}
+
 #[cfg(not(test))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
@@ -35,10 +43,11 @@ pub mod __default_lib_allocator {
         System.alloc(layout) as *mut u8
     }
 
+    #[cfg(stage0)]
     #[no_mangle]
     #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_oom() -> ! {
-        System.oom()
+        super::oom()
     }
 
     #[no_mangle]
index 4fe5c11beb4d518c9a37a78b80c9c9e0d5740302..a8c70489f443690c3151e0cd67f84a9ad43c324b 100644 (file)
@@ -11,7 +11,7 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
-use alloc::{Global, Alloc, CollectionAllocErr};
+use alloc::{CollectionAllocErr, oom};
 use cell::Cell;
 use borrow::Borrow;
 use cmp::max;
@@ -784,7 +784,7 @@ fn raw_capacity(&self) -> usize {
     pub fn reserve(&mut self, additional: usize) {
         match self.try_reserve(additional) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(()) => { /* yay */ }
          }
     }
index 115f9628a23cc4e6ca7ec5a307a49fb2cedbf49a..52c53dc3b1251a35f83eae4ee14a5ba380243616 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::{Global, Alloc, Layout, CollectionAllocErr};
+use alloc::{Global, Alloc, Layout, CollectionAllocErr, oom};
 use cmp;
 use hash::{BuildHasher, Hash, Hasher};
 use marker;
@@ -770,7 +770,7 @@ unsafe fn try_new_uninitialized(capacity: usize) -> Result<RawTable<K, V>, Colle
     unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
         match Self::try_new_uninitialized(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(table) => { table }
         }
     }
@@ -809,7 +809,7 @@ pub fn try_new(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> {
     pub fn new(capacity: usize) -> RawTable<K, V> {
         match Self::try_new(capacity) {
             Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),
-            Err(CollectionAllocErr::AllocErr) => Global.oom(),
+            Err(CollectionAllocErr::AllocErr) => oom(),
             Ok(table) => { table }
         }
     }
index 3c209928d432aa38a9b5c92995b96cc13fbc4367..749b8ccc13da642c1efca75057f2baa136494e17 100644 (file)
@@ -233,7 +233,7 @@ fn from(err: Cow<'a, str>) -> Box<Error> {
     }
 }
 
-#[stable(feature = "never_type", since = "1.26.0")]
+#[unstable(feature = "never_type", issue = "35121")]
 impl Error for ! {
     fn description(&self) -> &str { *self }
 }
@@ -284,14 +284,14 @@ fn description(&self) -> &str {
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl Error for num::TryFromIntError {
     fn description(&self) -> &str {
         self.__description()
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl Error for array::TryFromSliceError {
     fn description(&self) -> &str {
         self.__description()
@@ -365,7 +365,7 @@ fn description(&self) -> &str {
     }
 }
 
-#[stable(feature = "try_from", since = "1.26.0")]
+#[unstable(feature = "try_from", issue = "33417")]
 impl Error for char::CharTryFromError {
     fn description(&self) -> &str {
         "converted integer out of range for `char`"
index ca39089a9583acf553e6a164e20b71207e34290f..26644c769575c9bde37dd88e9af0a9077e2f54a9 100644 (file)
 #![allow(missing_docs)]
 
 #[cfg(not(test))]
-use core::num;
+#[cfg(stage0)]
+use core::num::Float;
 #[cfg(not(test))]
 use intrinsics;
 #[cfg(not(test))]
+#[cfg(stage0)]
 use num::FpCategory;
 #[cfg(not(test))]
 use sys::cmath;
 pub use core::f32::consts;
 
 #[cfg(not(test))]
-#[lang = "f32"]
+#[cfg_attr(stage0, lang = "f32")]
+#[cfg_attr(not(stage0), lang = "f32_runtime")]
 impl f32 {
-    /// Returns `true` if this value is `NaN` and false otherwise.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
-    /// let f = 7.0_f32;
-    ///
-    /// assert!(nan.is_nan());
-    /// assert!(!f.is_nan());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
-
-    /// Returns `true` if this value is positive infinity or negative infinity and
-    /// false otherwise.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let f = 7.0f32;
-    /// let inf = f32::INFINITY;
-    /// let neg_inf = f32::NEG_INFINITY;
-    /// let nan = f32::NAN;
-    ///
-    /// assert!(!f.is_infinite());
-    /// assert!(!nan.is_infinite());
-    ///
-    /// assert!(inf.is_infinite());
-    /// assert!(neg_inf.is_infinite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
-
-    /// Returns `true` if this number is neither infinite nor `NaN`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let f = 7.0f32;
-    /// let inf = f32::INFINITY;
-    /// let neg_inf = f32::NEG_INFINITY;
-    /// let nan = f32::NAN;
-    ///
-    /// assert!(f.is_finite());
-    ///
-    /// assert!(!nan.is_finite());
-    /// assert!(!inf.is_finite());
-    /// assert!(!neg_inf.is_finite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
-
-    /// Returns `true` if the number is neither zero, infinite,
-    /// [subnormal][subnormal], or `NaN`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
-    /// let max = f32::MAX;
-    /// let lower_than_min = 1.0e-40_f32;
-    /// let zero = 0.0_f32;
-    ///
-    /// assert!(min.is_normal());
-    /// assert!(max.is_normal());
-    ///
-    /// assert!(!zero.is_normal());
-    /// assert!(!f32::NAN.is_normal());
-    /// assert!(!f32::INFINITY.is_normal());
-    /// // Values between `0` and `min` are Subnormal.
-    /// assert!(!lower_than_min.is_normal());
-    /// ```
-    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    ///
-    /// ```
-    /// use std::num::FpCategory;
-    /// use std::f32;
-    ///
-    /// let num = 12.4_f32;
-    /// let inf = f32::INFINITY;
-    ///
-    /// assert_eq!(num.classify(), FpCategory::Normal);
-    /// assert_eq!(inf.classify(), FpCategory::Infinite);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { num::Float::classify(self) }
+    #[cfg(stage0)]
+    f32_core_methods!();
 
     /// Returns the largest integer less than or equal to a number.
     ///
@@ -257,7 +164,9 @@ pub fn fract(self) -> f32 { self - self.trunc() }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn abs(self) -> f32 { num::Float::abs(self) }
+    pub fn abs(self) -> f32 {
+        unsafe { intrinsics::fabsf32(self) }
+    }
 
     /// Returns a number that represents the sign of `self`.
     ///
@@ -277,35 +186,13 @@ pub fn abs(self) -> f32 { num::Float::abs(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn signum(self) -> f32 { num::Float::signum(self) }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f32;
-    /// let g = -7.0_f32;
-    ///
-    /// assert!(f.is_sign_positive());
-    /// assert!(!g.is_sign_positive());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
-
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
-    ///
-    /// ```
-    /// let f = 7.0f32;
-    /// let g = -7.0f32;
-    ///
-    /// assert!(!f.is_sign_negative());
-    /// assert!(g.is_sign_negative());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
+    pub fn signum(self) -> f32 {
+        if self.is_nan() {
+            NAN
+        } else {
+            unsafe { intrinsics::copysignf32(1.0, self) }
+        }
+    }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error. This produces a more accurate result with better performance than
@@ -380,20 +267,6 @@ pub fn mod_euc(self, rhs: f32) -> f32 {
     }
 
 
-    /// Takes the reciprocal (inverse) of a number, `1/x`.
-    ///
-    /// ```
-    /// use std::f32;
-    ///
-    /// let x = 2.0_f32;
-    /// let abs_difference = (x.recip() - (1.0/x)).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn recip(self) -> f32 { num::Float::recip(self) }
-
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
@@ -408,7 +281,9 @@ pub fn recip(self) -> f32 { num::Float::recip(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
+    pub fn powi(self, n: i32) -> f32 {
+        unsafe { intrinsics::powif32(self, n) }
+    }
 
     /// Raises a number to a floating point power.
     ///
@@ -584,68 +459,6 @@ pub fn log10(self) -> f32 {
         return unsafe { intrinsics::log10f32(self) };
     }
 
-    /// Converts radians to degrees.
-    ///
-    /// ```
-    /// use std::f32::{self, consts};
-    ///
-    /// let angle = consts::PI;
-    ///
-    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
-    #[inline]
-    pub fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
-
-    /// Converts degrees to radians.
-    ///
-    /// ```
-    /// use std::f32::{self, consts};
-    ///
-    /// let angle = 180.0f32;
-    ///
-    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
-    /// ```
-    #[stable(feature = "f32_deg_rad_conversions", since="1.7.0")]
-    #[inline]
-    pub fn to_radians(self) -> f32 { num::Float::to_radians(self) }
-
-    /// Returns the maximum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0f32;
-    /// let y = 2.0f32;
-    ///
-    /// assert_eq!(x.max(y), y);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn max(self, other: f32) -> f32 {
-        num::Float::max(self, other)
-    }
-
-    /// Returns the minimum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0f32;
-    /// let y = 2.0f32;
-    ///
-    /// assert_eq!(x.min(y), x);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn min(self, other: f32) -> f32 {
-        num::Float::min(self, other)
-    }
-
     /// The positive difference of two numbers.
     ///
     /// * If `self <= other`: `0:0`
@@ -1046,73 +859,6 @@ pub fn acosh(self) -> f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
-
-    /// Raw transmutation to `u32`.
-    ///
-    /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
-    ///
-    /// See `from_bits` for some discussion of the portability of this operation
-    /// (there are almost no issues).
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
-    /// assert_eq!((12.5f32).to_bits(), 0x41480000);
-    ///
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn to_bits(self) -> u32 {
-        num::Float::to_bits(self)
-    }
-
-    /// Raw transmutation from `u32`.
-    ///
-    /// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
-    /// It turns out this is incredibly portable, for two reasons:
-    ///
-    /// * Floats and Ints have the same endianness on all supported platforms.
-    /// * IEEE-754 very precisely specifies the bit layout of floats.
-    ///
-    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
-    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
-    /// (notably x86 and ARM) picked the interpretation that was ultimately
-    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
-    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
-    ///
-    /// Rather than trying to preserve signaling-ness cross-platform, this
-    /// implementation favours preserving the exact bits. This means that
-    /// any payloads encoded in NaNs will be preserved even if the result of
-    /// this method is sent over the network from an x86 machine to a MIPS one.
-    ///
-    /// If the results of this method are only manipulated by the same
-    /// architecture that produced them, then there is no portability concern.
-    ///
-    /// If the input isn't NaN, then there is no portability concern.
-    ///
-    /// If you don't care about signalingness (very likely), then there is no
-    /// portability concern.
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::f32;
-    /// let v = f32::from_bits(0x41480000);
-    /// let difference = (v - 12.5).abs();
-    /// assert!(difference <= 1e-5);
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn from_bits(v: u32) -> Self {
-        num::Float::from_bits(v)
-    }
 }
 
 #[cfg(test)]
index a9585670ad043d4242de60eab2f1e4071adf702b..a7e63f59b1c67369e8bb1b1009bc950c813b95d7 100644 (file)
 #![allow(missing_docs)]
 
 #[cfg(not(test))]
-use core::num;
+#[cfg(stage0)]
+use core::num::Float;
 #[cfg(not(test))]
 use intrinsics;
 #[cfg(not(test))]
+#[cfg(stage0)]
 use num::FpCategory;
 #[cfg(not(test))]
 use sys::cmath;
 pub use core::f64::consts;
 
 #[cfg(not(test))]
-#[lang = "f64"]
+#[cfg_attr(stage0, lang = "f64")]
+#[cfg_attr(not(stage0), lang = "f64_runtime")]
 impl f64 {
-    /// Returns `true` if this value is `NaN` and false otherwise.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let nan = f64::NAN;
-    /// let f = 7.0_f64;
-    ///
-    /// assert!(nan.is_nan());
-    /// assert!(!f.is_nan());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_nan(self) -> bool { num::Float::is_nan(self) }
-
-    /// Returns `true` if this value is positive infinity or negative infinity and
-    /// false otherwise.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let f = 7.0f64;
-    /// let inf = f64::INFINITY;
-    /// let neg_inf = f64::NEG_INFINITY;
-    /// let nan = f64::NAN;
-    ///
-    /// assert!(!f.is_infinite());
-    /// assert!(!nan.is_infinite());
-    ///
-    /// assert!(inf.is_infinite());
-    /// assert!(neg_inf.is_infinite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
-
-    /// Returns `true` if this number is neither infinite nor `NaN`.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let f = 7.0f64;
-    /// let inf: f64 = f64::INFINITY;
-    /// let neg_inf: f64 = f64::NEG_INFINITY;
-    /// let nan: f64 = f64::NAN;
-    ///
-    /// assert!(f.is_finite());
-    ///
-    /// assert!(!nan.is_finite());
-    /// assert!(!inf.is_finite());
-    /// assert!(!neg_inf.is_finite());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_finite(self) -> bool { num::Float::is_finite(self) }
-
-    /// Returns `true` if the number is neither zero, infinite,
-    /// [subnormal][subnormal], or `NaN`.
-    ///
-    /// ```
-    /// use std::f64;
-    ///
-    /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
-    /// let max = f64::MAX;
-    /// let lower_than_min = 1.0e-308_f64;
-    /// let zero = 0.0f64;
-    ///
-    /// assert!(min.is_normal());
-    /// assert!(max.is_normal());
-    ///
-    /// assert!(!zero.is_normal());
-    /// assert!(!f64::NAN.is_normal());
-    /// assert!(!f64::INFINITY.is_normal());
-    /// // Values between `0` and `min` are Subnormal.
-    /// assert!(!lower_than_min.is_normal());
-    /// ```
-    /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_normal(self) -> bool { num::Float::is_normal(self) }
-
-    /// Returns the floating point category of the number. If only one property
-    /// is going to be tested, it is generally faster to use the specific
-    /// predicate instead.
-    ///
-    /// ```
-    /// use std::num::FpCategory;
-    /// use std::f64;
-    ///
-    /// let num = 12.4_f64;
-    /// let inf = f64::INFINITY;
-    ///
-    /// assert_eq!(num.classify(), FpCategory::Normal);
-    /// assert_eq!(inf.classify(), FpCategory::Infinite);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn classify(self) -> FpCategory { num::Float::classify(self) }
+    #[cfg(stage0)]
+    f64_core_methods!();
 
     /// Returns the largest integer less than or equal to a number.
     ///
@@ -235,7 +142,9 @@ pub fn fract(self) -> f64 { self - self.trunc() }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn abs(self) -> f64 { num::Float::abs(self) }
+    pub fn abs(self) -> f64 {
+        unsafe { intrinsics::fabsf64(self) }
+    }
 
     /// Returns a number that represents the sign of `self`.
     ///
@@ -255,45 +164,13 @@ pub fn abs(self) -> f64 { num::Float::abs(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn signum(self) -> f64 { num::Float::signum(self) }
-
-    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
-    /// positive sign bit and positive infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f64;
-    /// let g = -7.0_f64;
-    ///
-    /// assert!(f.is_sign_positive());
-    /// assert!(!g.is_sign_positive());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
-    #[inline]
-    pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
-
-    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
-    /// negative sign bit and negative infinity.
-    ///
-    /// ```
-    /// let f = 7.0_f64;
-    /// let g = -7.0_f64;
-    ///
-    /// assert!(!f.is_sign_negative());
-    /// assert!(g.is_sign_negative());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn is_sign_negative(self) -> bool { num::Float::is_sign_negative(self) }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
-    #[inline]
-    pub fn is_negative(self) -> bool { num::Float::is_sign_negative(self) }
+    pub fn signum(self) -> f64 {
+        if self.is_nan() {
+            NAN
+        } else {
+            unsafe { intrinsics::copysignf64(1.0, self) }
+        }
+    }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error. This produces a more accurate result with better performance than
@@ -365,18 +242,6 @@ pub fn mod_euc(self, rhs: f64) -> f64 {
         }
     }
 
-    /// Takes the reciprocal (inverse) of a number, `1/x`.
-    ///
-    /// ```
-    /// let x = 2.0_f64;
-    /// let abs_difference = (x.recip() - (1.0/x)).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn recip(self) -> f64 { num::Float::recip(self) }
-
     /// Raises a number to an integer power.
     ///
     /// Using this function is generally faster than using `powf`
@@ -389,7 +254,9 @@ pub fn recip(self) -> f64 { num::Float::recip(self) }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
+    pub fn powi(self, n: i32) -> f64 {
+        unsafe { intrinsics::powif64(self, n) }
+    }
 
     /// Raises a number to a floating point power.
     ///
@@ -535,68 +402,6 @@ pub fn log10(self) -> f64 {
         self.log_wrapper(|n| { unsafe { intrinsics::log10f64(n) } })
     }
 
-    /// Converts radians to degrees.
-    ///
-    /// ```
-    /// use std::f64::consts;
-    ///
-    /// let angle = consts::PI;
-    ///
-    /// let abs_difference = (angle.to_degrees() - 180.0).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
-
-    /// Converts degrees to radians.
-    ///
-    /// ```
-    /// use std::f64::consts;
-    ///
-    /// let angle = 180.0_f64;
-    ///
-    /// let abs_difference = (angle.to_radians() - consts::PI).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn to_radians(self) -> f64 { num::Float::to_radians(self) }
-
-    /// Returns the maximum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0_f64;
-    /// let y = 2.0_f64;
-    ///
-    /// assert_eq!(x.max(y), y);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn max(self, other: f64) -> f64 {
-        num::Float::max(self, other)
-    }
-
-    /// Returns the minimum of the two numbers.
-    ///
-    /// ```
-    /// let x = 1.0_f64;
-    /// let y = 2.0_f64;
-    ///
-    /// assert_eq!(x.min(y), x);
-    /// ```
-    ///
-    /// If one of the arguments is NaN, then the other argument is returned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn min(self, other: f64) -> f64 {
-        num::Float::min(self, other)
-    }
-
     /// The positive difference of two numbers.
     ///
     /// * If `self <= other`: `0:0`
@@ -1000,73 +805,6 @@ fn log_wrapper<F: Fn(f64) -> f64>(self, log_fn: F) -> f64 {
             }
         }
     }
-
-    /// Raw transmutation to `u64`.
-    ///
-    /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
-    ///
-    /// See `from_bits` for some discussion of the portability of this operation
-    /// (there are almost no issues).
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
-    /// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
-    ///
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn to_bits(self) -> u64 {
-        num::Float::to_bits(self)
-    }
-
-    /// Raw transmutation from `u64`.
-    ///
-    /// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
-    /// It turns out this is incredibly portable, for two reasons:
-    ///
-    /// * Floats and Ints have the same endianness on all supported platforms.
-    /// * IEEE-754 very precisely specifies the bit layout of floats.
-    ///
-    /// However there is one caveat: prior to the 2008 version of IEEE-754, how
-    /// to interpret the NaN signaling bit wasn't actually specified. Most platforms
-    /// (notably x86 and ARM) picked the interpretation that was ultimately
-    /// standardized in 2008, but some didn't (notably MIPS). As a result, all
-    /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
-    ///
-    /// Rather than trying to preserve signaling-ness cross-platform, this
-    /// implementation favours preserving the exact bits. This means that
-    /// any payloads encoded in NaNs will be preserved even if the result of
-    /// this method is sent over the network from an x86 machine to a MIPS one.
-    ///
-    /// If the results of this method are only manipulated by the same
-    /// architecture that produced them, then there is no portability concern.
-    ///
-    /// If the input isn't NaN, then there is no portability concern.
-    ///
-    /// If you don't care about signalingness (very likely), then there is no
-    /// portability concern.
-    ///
-    /// Note that this function is distinct from `as` casting, which attempts to
-    /// preserve the *numeric* value, and not the bitwise value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::f64;
-    /// let v = f64::from_bits(0x4029000000000000);
-    /// let difference = (v - 12.5).abs();
-    /// assert!(difference <= 1e-5);
-    /// ```
-    #[stable(feature = "float_bits_conv", since = "1.20.0")]
-    #[inline]
-    pub fn from_bits(v: u64) -> Self {
-        num::Float::from_bits(v)
-    }
 }
 
 #[cfg(test)]
index d6eac748334834ccae5136eb19cdc846b36995f9..ee297d3783e522caf24a8ca4b8f79d313770895d 100644 (file)
@@ -1251,6 +1251,7 @@ fn test_short_reads() {
     }
 
     #[test]
+    #[allow(deprecated)]
     fn read_char_buffered() {
         let buf = [195, 159];
         let reader = BufReader::with_capacity(1, &buf[..]);
@@ -1258,6 +1259,7 @@ fn read_char_buffered() {
     }
 
     #[test]
+    #[allow(deprecated)]
     fn test_chars() {
         let buf = [195, 159, b'a'];
         let reader = BufReader::with_capacity(1, &buf[..]);
index 2673f3ccfa3abd9cff77660e554a8938b5330a0d..8ac52572810c6c99e2ce8ccddaa0d1be66174a55 100644 (file)
@@ -566,6 +566,7 @@ fn test_buf_reader() {
     }
 
     #[test]
+    #[allow(deprecated)]
     fn test_read_char() {
         let b = &b"Vi\xE1\xBB\x87t"[..];
         let mut c = Cursor::new(b).chars();
@@ -577,6 +578,7 @@ fn test_read_char() {
     }
 
     #[test]
+    #[allow(deprecated)]
     fn test_read_bad_char() {
         let b = &b"\x80"[..];
         let mut c = Cursor::new(b).chars();
index b02e133ee4dd72176d847361268cc3fd08005cdc..eba4e9fe70368f6de4e853316ede9a6110e43ab1 100644 (file)
@@ -840,6 +840,9 @@ fn bytes(self) -> Bytes<Self> where Self: Sized {
                                          of where errors happen is currently \
                                          unclear and may change",
                issue = "27802")]
+    #[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
+        https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
+    #[allow(deprecated)]
     fn chars(self) -> Chars<Self> where Self: Sized {
         Chars { inner: self }
     }
@@ -2010,16 +2013,22 @@ fn next(&mut self) -> Option<Result<u8>> {
 /// [chars]: trait.Read.html#method.chars
 #[unstable(feature = "io", reason = "awaiting stability of Read::chars",
            issue = "27802")]
+#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
+    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
 #[derive(Debug)]
+#[allow(deprecated)]
 pub struct Chars<R> {
     inner: R,
 }
 
 /// An enumeration of possible errors that can be generated from the `Chars`
 /// adapter.
-#[derive(Debug)]
 #[unstable(feature = "io", reason = "awaiting stability of Read::chars",
            issue = "27802")]
+#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
+    https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
+#[derive(Debug)]
+#[allow(deprecated)]
 pub enum CharsError {
     /// Variant representing that the underlying stream was read successfully
     /// but it did not contain valid utf8 data.
@@ -2031,6 +2040,7 @@ pub enum CharsError {
 
 #[unstable(feature = "io", reason = "awaiting stability of Read::chars",
            issue = "27802")]
+#[allow(deprecated)]
 impl<R: Read> Iterator for Chars<R> {
     type Item = result::Result<char, CharsError>;
 
@@ -2063,6 +2073,7 @@ fn next(&mut self) -> Option<result::Result<char, CharsError>> {
 
 #[unstable(feature = "io", reason = "awaiting stability of Read::chars",
            issue = "27802")]
+#[allow(deprecated)]
 impl std_error::Error for CharsError {
     fn description(&self) -> &str {
         match *self {
@@ -2080,6 +2091,7 @@ fn cause(&self) -> Option<&std_error::Error> {
 
 #[unstable(feature = "io", reason = "awaiting stability of Read::chars",
            issue = "27802")]
+#[allow(deprecated)]
 impl fmt::Display for CharsError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
index 7d8966953114e9a8fe15c17c4c00e75398bac5d2..419921931350906e5c9223ace3e19de4d80a63c0 100644 (file)
 #![feature(collections_range)]
 #![feature(compiler_builtins_lib)]
 #![feature(const_fn)]
-#![feature(core_float)]
+#![cfg_attr(stage0, feature(core_float))]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
 #![feature(fs_read_write)]
 #![feature(fixed_size_array)]
 #![feature(float_from_str_radix)]
+#![cfg_attr(stage0, feature(float_internals))]
 #![feature(fn_traits)]
 #![feature(fnbox)]
 #![cfg_attr(stage0, feature(generic_param_attrs))]
 #![feature(macro_reexport)]
 #![feature(macro_vis_matcher)]
 #![feature(needs_panic_runtime)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(nonzero)]
 #![feature(num_bits_bytes)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
+#![feature(try_from)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(doc_spotlight)]
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
+#![feature(doc_alias)]
 
 #![default_lib_allocator]
 
 pub use core::char;
 #[stable(feature = "i128", since = "1.26.0")]
 pub use core::u128;
+#[stable(feature = "core_hint", since = "1.27.0")]
+pub use core::hint;
 
 pub mod f32;
 pub mod f64;
 pub mod process;
 pub mod sync;
 pub mod time;
-pub mod alloc;
 
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[rustc_deprecated(since = "1.27.0", reason = "module renamed to `alloc`")]
@@ -492,6 +497,8 @@ pub mod heap {
 mod sys_common;
 mod sys;
 
+pub mod alloc;
+
 // Private support modules
 mod panicking;
 mod memchr;
index a51b46559859e67a2d514ca42c2b7a8d77a3a80a..5899dc688e22563bc69dd709f0224dc696b7c9bd 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::android::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index e4f1c9432f3f08f4cc60859c5b6a968330f5f021..24caf326ab0fd2dba4b6cf69242d2f675667c296 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::bitrig::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index db672e5643531181fb59b0759274cc81d74c7e50..6aea450774ffd39d9bb48a3dc04b1386604f09fb 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::dragonfly::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 8056ce4fdc4ee4ba02365682be02ff5f5000acce..e0e197dc122a1d2aaa9f36e02b67d7a0ad30d64f 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::emscripten::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 2f17d2f7409434c568887478bbafaefc2ec702c5..5f24cd636d541ab75611244212d9f86a1ba712f3 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::freebsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index d22f9a628bd1733e7c929546f5f772d66e29cd10..16802576356d192b24d762642d10c6d1c735da52 100644 (file)
@@ -13,7 +13,9 @@
 use fs::Metadata;
 use sys_common::AsInner;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
index 54f8ea1b71b3effa9556cb0cc6672b95579831d0..453136e0ac864afe4cf42f0a875d20ec2e90fb65 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::haiku::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 275daf3d3a0ac5f842c4e6d3db52f07447e01d62..296ce69ff43620e7f0aa70b01879f01ba1362cf3 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::ios::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 2be2fbcb2dbf75900627347081d556cb9754f538..76fb10da850b16b4044cd86fdfc4284d970dea53 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::linux::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 12b44901d03d93b6bb468e205c944b310cb09d6c..0b14c05cb5519bffbaf6481ece1af64d52ae18df 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::macos::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index cd7d5fafd1c85d82afcc92a79bd13bf37d8eedcf..e9cad33fee61d7fceea55e767dff2e1f6081b832 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::netbsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index cc812fcf12cfe5f9061694ff787a871cf584810c..0f6b83b6e324b56cf8e2f68d907fd4093ac279a9 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::openbsd::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index 5dc43d03a866347e82c556fd45723ed80ab5460c..19dce1ba34c76c98482094cec0ea0ccc117bbf22 100644 (file)
@@ -18,7 +18,9 @@
 #[allow(deprecated)]
 use os::solaris::raw;
 
-/// OS-specific extension methods for `fs::Metadata`
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Gain a reference to the underlying `stat` structure which contains
index ec96157547383daa4cbad54658beb78a602fd7bd..955a6af1ae67eaac5a78975499cf329658003667 100644 (file)
@@ -298,10 +298,9 @@ pub fn is_separator(c: char) -> bool {
 // Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
 // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
 // `iter` after having exhausted `prefix`.
-fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>
-    where I: Iterator<Item = A> + Clone,
-          J: Iterator<Item = A>,
-          A: PartialEq
+fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
+    where I: Iterator<Item = Component<'a>> + Clone,
+          J: Iterator<Item = Component<'b>>,
 {
     loop {
         let mut iter_next = iter.clone();
@@ -1967,7 +1966,7 @@ pub fn file_name(&self) -> Option<&OsStr> {
     /// # Examples
     ///
     /// ```
-    /// use std::path::Path;
+    /// use std::path::{Path, PathBuf};
     ///
     /// let path = Path::new("/test/haha/foo.txt");
     ///
@@ -1978,17 +1977,20 @@ pub fn file_name(&self) -> Option<&OsStr> {
     /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
     /// assert_eq!(path.strip_prefix("test").is_ok(), false);
     /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
+    ///
+    /// let prefix = PathBuf::from("/test/");
+    /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
     /// ```
     #[stable(since = "1.7.0", feature = "path_strip_prefix")]
-    pub fn strip_prefix<'a, P: ?Sized>(&'a self, base: &'a P)
-                                       -> Result<&'a Path, StripPrefixError>
+    pub fn strip_prefix<P>(&self, base: P)
+                           -> Result<&Path, StripPrefixError>
         where P: AsRef<Path>
     {
         self._strip_prefix(base.as_ref())
     }
 
-    fn _strip_prefix<'a>(&'a self, base: &'a Path)
-                         -> Result<&'a Path, StripPrefixError> {
+    fn _strip_prefix(&self, base: &Path)
+                     -> Result<&Path, StripPrefixError> {
         iter_after(self.components(), base.components())
             .map(|c| c.as_path())
             .ok_or(StripPrefixError(()))
index ce4bbfffc2e47b0644c11821f7f7e41eba69c79f..919d964829718f0c0653e88086137a579bb317bf 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #[doc(primitive = "bool")]
+#[doc(alias = "true")]
+#[doc(alias = "false")]
 //
 /// The boolean type.
 ///
@@ -68,6 +70,7 @@
 mod prim_bool { }
 
 #[doc(primitive = "never")]
+#[doc(alias = "!")]
 //
 /// The `!` type, also called "never".
 ///
@@ -79,6 +82,7 @@ mod prim_bool { }
 /// write:
 ///
 /// ```
+/// #![feature(never_type)]
 /// # fn foo() -> u32 {
 /// let x: ! = {
 ///     return 123
@@ -155,6 +159,7 @@ mod prim_bool { }
 /// for example:
 ///
 /// ```
+/// #![feature(never_type)]
 /// # use std::fmt;
 /// # trait Debug {
 /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
@@ -499,6 +504,9 @@ mod prim_pointer { }
 mod prim_array { }
 
 #[doc(primitive = "slice")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
 //
 /// A dynamically-sized view into a contiguous sequence, `[T]`.
 ///
@@ -597,6 +605,9 @@ mod prim_slice { }
 mod prim_str { }
 
 #[doc(primitive = "tuple")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
 //
 /// A finite heterogeneous sequence, `(T, U, ..)`.
 ///
@@ -819,6 +830,7 @@ mod prim_isize { }
 mod prim_usize { }
 
 #[doc(primitive = "reference")]
+#[doc(alias = "&")]
 //
 /// References, both shared and mutable.
 ///
index 92f0406c09bb5c752170212e06fe94effebd306a..00051d4487a214eac90bef8a089468bea345b835 100644 (file)
@@ -1121,8 +1121,13 @@ impl ExitCode {
 }
 
 impl Child {
-    /// Forces the child to exit. This is equivalent to sending a
-    /// SIGKILL on unix platforms.
+    /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
+    /// error is returned.
+    ///
+    /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function,
+    /// especially the [`Other`] kind might change to more specific kinds in the future.
+    ///
+    /// This is equivalent to sending a SIGKILL on Unix platforms.
     ///
     /// # Examples
     ///
@@ -1138,6 +1143,10 @@ impl Child {
     ///     println!("yes command didn't start");
     /// }
     /// ```
+    ///
+    /// [`ErrorKind`]: ../io/enum.ErrorKind.html
+    /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
+    /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
     #[stable(feature = "process", since = "1.0.0")]
     pub fn kill(&mut self) -> io::Result<()> {
         self.handle.kill()
index d59b4fc0b70b8032a961d9123da86e7b5c2276ac..cd88c8f46b3c0c6b3ef78a0342306b7b6a0642a9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extension to the primitives in the `std::ffi` module
+//! Redox-specific extension to the primitives in the `std::ffi` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -17,7 +17,9 @@
 use sys::os_str::Buf;
 use sys_common::{FromInner, IntoInner, AsInner};
 
-/// Unix-specific extensions to `OsString`.
+/// Redox-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an `OsString` from a byte vector.
@@ -39,7 +41,9 @@ fn into_vec(self) -> Vec<u8> {
     }
 }
 
-/// Unix-specific extensions to `OsStr`.
+/// Redox-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     #[stable(feature = "rust1", since = "1.0.0")]
index 0f4762aa8810a901490f828bb4975a51e470ec91..c1dba6edda484f66e6f702555d91ce372166f826 100644 (file)
@@ -18,7 +18,9 @@
 use sys;
 use sys_common::{FromInner, AsInner, AsInnerMut};
 
-/// Redox-specific extensions to `Permissions`
+/// Redox-specific extensions to [`fs::Permissions`].
+///
+/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
     /// Returns the underlying raw `mode_t` bits that are the standard Redox
@@ -95,7 +97,9 @@ fn from_mode(mode: u32) -> Permissions {
     }
 }
 
-/// Redox-specific extensions to `OpenOptions`
+/// Redox-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait OpenOptionsExt {
     /// Sets the mode bits that a new file will be created with.
@@ -163,13 +167,9 @@ fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
     }
 }
 
-// Hm, why are there casts here to the returned type, shouldn't the types always
-// be the same? Right you are! Turns out, however, on android at least the types
-// in the raw `stat` structure are not the same as the types being returned. Who
-// knew!
-//
-// As a result to make sure this compiles for all platforms we do the manual
-// casts and rely on manual lowering to `stat` if the raw type is desired.
+/// Redox-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -204,6 +204,13 @@ pub trait MetadataExt {
     fn blocks(&self) -> u64;
 }
 
+// Hm, why are there casts here to the returned type, shouldn't the types always
+// be the same? Right you are! Turns out, however, on android at least the types
+// in the raw `stat` structure are not the same as the types being returned. Who
+// knew!
+//
+// As a result to make sure this compiles for all platforms we do the manual
+// casts and rely on manual lowering to `stat` if the raw type is desired.
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 impl MetadataExt for fs::Metadata {
     fn dev(&self) -> u64 {
@@ -253,7 +260,12 @@ fn blocks(&self) -> u64 {
     }
 }
 
-/// Add special Redox types (block/char device, fifo and socket)
+/// Redox-specific extensions for [`FileType`].
+///
+/// Adds support for special Unix file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
@@ -307,8 +319,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
     sys::fs::symlink(src.as_ref(), dst.as_ref())
 }
 
+/// Redox-specific extensions to [`fs::DirBuilder`].
+///
+/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
 #[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for `fs::DirBuilder` for Redox-specific options.
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
index e68e180acf1c4cdf9a3c3dd5785c20e30af33ee3..cfb6d5fc703a614ef84e1c2b363ed8d7bb8b48c5 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extensions to primitives in the `std::process` module.
+//! Redox-specific extensions to primitives in the `std::process` module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -18,7 +18,9 @@
 use sys;
 use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
 
-/// Unix-specific extensions to the `std::process::Command` builder
+/// Redox-specific extensions to the [`process::Command`] builder,
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
     /// Sets the child process's user id. This translates to a
@@ -107,7 +109,9 @@ fn exec(&mut self) -> io::Error {
     }
 }
 
-/// Unix-specific extensions to `std::process::ExitStatus`
+/// Redox-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
index 52be2ccd9f964b43906c8e935018555cba131760..71ff0d46b91e31f8553689730f1ccc9d2a519e7b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unix-specific extensions to primitives in the `std::thread` module.
+//! Redox-specific extensions to primitives in the `std::thread` module.
 
 #![stable(feature = "thread_extensions", since = "1.9.0")]
 
@@ -19,7 +19,9 @@
 #[allow(deprecated)]
 pub type RawPthread = usize;
 
-/// Unix-specific extensions to `std::thread::JoinHandle`
+/// Redox-specific extensions to [`thread::JoinHandle`].
+///
+/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
 #[stable(feature = "thread_extensions", since = "1.9.0")]
 pub trait JoinHandleExt {
     /// Extracts the raw pthread_t without taking ownership
index fb9984ccbdda5f63444ead83602afbe6e3f384a3..8347145db5aaf493a9c8ad3cf379415c5897a5bd 100644 (file)
@@ -17,7 +17,9 @@
 use sys::os_str::Buf;
 use sys_common::{FromInner, IntoInner, AsInner};
 
-/// Unix-specific extensions to `OsString`.
+/// Unix-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an [`OsString`] from a byte vector.
@@ -66,7 +68,9 @@ fn into_vec(self) -> Vec<u8> {
     }
 }
 
-/// Unix-specific extensions to `OsStr`.
+/// Unix-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     #[stable(feature = "rust1", since = "1.0.0")]
index 3c5b9424fb06ea1688409166891d0356e686d406..4e981012669033ff393d85a44f1511bab82df6a0 100644 (file)
@@ -105,7 +105,9 @@ fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
     }
 }
 
-/// Unix-specific extensions to `Permissions`
+/// Unix-specific extensions to [`fs::Permissions`].
+///
+/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
     /// Returns the underlying raw `st_mode` bits that contain the standard
@@ -180,7 +182,9 @@ fn from_mode(mode: u32) -> Permissions {
     }
 }
 
-/// Unix-specific extensions to `OpenOptions`
+/// Unix-specific extensions to [`fs::OpenOptions`].
+///
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait OpenOptionsExt {
     /// Sets the mode bits that a new file will be created with.
@@ -246,13 +250,9 @@ fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
     }
 }
 
-// Hm, why are there casts here to the returned type, shouldn't the types always
-// be the same? Right you are! Turns out, however, on android at least the types
-// in the raw `stat` structure are not the same as the types being returned. Who
-// knew!
-//
-// As a result to make sure this compiles for all platforms we do the manual
-// casts and rely on manual lowering to `stat` if the raw type is desired.
+/// Unix-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Returns the ID of the device containing the file.
@@ -555,7 +555,12 @@ fn blksize(&self) -> u64 { self.st_blksize() }
     fn blocks(&self) -> u64 { self.st_blocks() }
 }
 
-/// Add support for special unix types (block/char device, fifo and socket).
+/// Unix-specific extensions for [`FileType`].
+///
+/// Adds support for special Unix file types such as block/character devices,
+/// pipes, and sockets.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
@@ -701,10 +706,10 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
     sys::fs::symlink(src.as_ref(), dst.as_ref())
 }
 
-#[stable(feature = "dir_builder", since = "1.6.0")]
-/// An extension trait for [`fs::DirBuilder`] for unix-specific options.
+/// Unix-specific extensions to [`fs::DirBuilder`].
 ///
 /// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
+#[stable(feature = "dir_builder", since = "1.6.0")]
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
index ba80cbe47c824980b1c06a18b48cf4324904b2ca..e277b1aa7b5f99b872c97f737558677d80bd2d76 100644 (file)
@@ -214,7 +214,10 @@ fn address<'a>(&'a self) -> AddressKind<'a> {
         let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
 
         // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
-        if len == 0 || (cfg!(not(target_os = "linux")) && self.addr.sun_path[0] == 0) {
+        if len == 0
+            || (cfg!(not(any(target_os = "linux", target_os = "android")))
+                && self.addr.sun_path[0] == 0)
+        {
             AddressKind::Unnamed
         } else if self.addr.sun_path[0] == 0 {
             AddressKind::Abstract(&path[1..len])
index 7b4ec20d91fb46e80a014cf95b25012f8c816cbf..21630ae9746fcdcca4aa3a4fe97a1e77fa551600 100644 (file)
@@ -18,7 +18,9 @@
 use sys;
 use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
 
-/// Unix-specific extensions to the `std::process::Command` builder
+/// Unix-specific extensions to the [`process::Command`] builder.
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
     /// Sets the child process's user id. This translates to a
@@ -117,7 +119,9 @@ fn exec(&mut self) -> io::Error {
     }
 }
 
-/// Unix-specific extensions to `std::process::ExitStatus`
+/// Unix-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
index fe2a48764dc3a99799373cf3f0878a8b61d6dca7..8dadf29945c1a816a217cfb12f0634bb4189acf5 100644 (file)
@@ -21,7 +21,9 @@
 #[allow(deprecated)]
 pub type RawPthread = pthread_t;
 
-/// Unix-specific extensions to `std::thread::JoinHandle`
+/// Unix-specific extensions to [`thread::JoinHandle`].
+///
+/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
 #[stable(feature = "thread_extensions", since = "1.9.0")]
 pub trait JoinHandleExt {
     /// Extracts the raw pthread_t without taking ownership
index d6b8896ac096d2e8caf3594a9b6459dfae69e8cb..98d4355248990a92ec748b667409e91b1e5a1f2d 100644 (file)
@@ -76,7 +76,9 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use sys_common::wtf8::EncodeWide;
 
-/// Windows-specific extensions to `OsString`.
+/// Windows-specific extensions to [`OsString`].
+///
+/// [`OsString`]: ../../../../std/ffi/struct.OsString.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStringExt {
     /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
@@ -109,7 +111,9 @@ fn from_wide(wide: &[u16]) -> OsString {
     }
 }
 
-/// Windows-specific extensions to `OsStr`.
+/// Windows-specific extensions to [`OsStr`].
+///
+/// [`OsStr`]: ../../../../std/ffi/struct.OsStr.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait OsStrExt {
     /// Re-encodes an `OsStr` as a wide character sequence, i.e. potentially
index e5cd51b6550b161a78902784aac8dc043debc39d..78c9e95a05501d0821602ab330ecc8cde75ff178 100644 (file)
@@ -103,9 +103,9 @@ fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
     }
 }
 
-/// Windows-specific extensions to [`OpenOptions`].
+/// Windows-specific extensions to [`fs::OpenOptions`].
 ///
-/// [`OpenOptions`]: ../../../fs/struct.OpenOptions.html
+/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "open_options_ext", since = "1.10.0")]
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`]
@@ -281,13 +281,12 @@ fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
     }
 }
 
-/// Extension methods for [`fs::Metadata`] to access the raw fields contained
-/// within.
+/// Windows-specific extensions to [`fs::Metadata`].
 ///
 /// The data members that this trait exposes correspond to the members
 /// of the [`BY_HANDLE_FILE_INFORMATION`] structure.
 ///
-/// [`fs::Metadata`]: ../../../fs/struct.Metadata.html
+/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 /// [`BY_HANDLE_FILE_INFORMATION`]:
 ///     https://msdn.microsoft.com/en-us/library/windows/desktop/aa363788.aspx
 #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -445,8 +444,11 @@ fn last_write_time(&self) -> u64 { self.as_inner().modified_u64() }
     fn file_size(&self) -> u64 { self.as_inner().size() }
 }
 
-/// Add support for the Windows specific fact that a symbolic link knows whether it is a file
-/// or directory.
+/// Windows-specific extensions to [`FileType`].
+///
+/// On Windows, a symbolic link knows whether it is a file or directory.
+///
+/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[unstable(feature = "windows_file_type_ext", issue = "0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a symbolic link that is also a directory.
index 759f055c4b1236e4640982e21d4be19fd15b7155..a02bcbe0c87c259ad599c2e0d2dbb2b973fe73fd 100644 (file)
@@ -82,7 +82,9 @@ fn into_raw_handle(self) -> RawHandle {
     }
 }
 
-/// Windows-specific extensions to `std::process::ExitStatus`
+/// Windows-specific extensions to [`process::ExitStatus`].
+///
+/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "exit_status_from", since = "1.12.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `u32` return value of
@@ -98,7 +100,9 @@ fn from_raw(raw: u32) -> Self {
     }
 }
 
-/// Windows-specific extensions to the `std::process::Command` builder
+/// Windows-specific extensions to the [`process::Command`] builder.
+///
+/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "windows_process_extensions", since = "1.16.0")]
 pub trait CommandExt {
     /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
index dda4e1bab3b42f2b916de2ca7c2379443c2b78e4..fe7e058091ed5fe1c6cf871817f879892f5ead2d 100644 (file)
@@ -876,21 +876,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 }
 
 impl Wtf8 {
-    pub fn is_ascii(&self) -> bool {
-        self.bytes.is_ascii()
-    }
-    pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_uppercase() }
-    }
-    pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_lowercase() }
-    }
-    pub fn eq_ignore_ascii_case(&self, other: &Wtf8) -> bool {
-        self.bytes.eq_ignore_ascii_case(&other.bytes)
-    }
-
     pub fn make_ascii_uppercase(&mut self) { self.bytes.make_ascii_uppercase() }
-    pub fn make_ascii_lowercase(&mut self) { self.bytes.make_ascii_lowercase() }
 }
 
 #[cfg(test)]
index e579fc74b42661753386440869b2bc0ac16c213d..3fc1c279f5a22ea971f55be431a2df2a0820e8b2 100644 (file)
@@ -24,20 +24,19 @@ pub enum Edition {
 
     // when adding new editions, be sure to update:
     //
-    // - the list in the `parse_edition` static in librustc::session::config
+    // - Update the `ALL_EDITIONS` const
+    // - Update the EDITION_NAME_LIST const
     // - add a `rust_####()` function to the session
     // - update the enum in Cargo's sources as well
-    //
-    // When -Zedition becomes --edition, there will
-    // also be a check for the edition being nightly-only
-    // somewhere. That will need to be updated
-    // whenever we're stabilizing/introducing a new edition
-    // as well as changing the default Cargo template.
 }
 
 // must be in order from oldest to newest
 pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
 
+pub const EDITION_NAME_LIST: &'static str = "2015|2018";
+
+pub const DEFAULT_EDITION: Edition = Edition::Edition2015;
+
 impl fmt::Display for Edition {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let s = match *self {
@@ -62,6 +61,13 @@ pub fn feature_name(&self) -> &'static str {
             Edition::Edition2018 => "rust_2018_preview",
         }
     }
+
+    pub fn is_stable(&self) -> bool {
+        match *self {
+            Edition::Edition2015 => true,
+            Edition::Edition2018 => false,
+        }
+    }
 }
 
 impl FromStr for Edition {
index 678c20402d6f47aab78e99f35b0234f61d2846eb..1434e5fddeab0eb1a4ce422541fb1287d46a3198 100644 (file)
@@ -514,6 +514,7 @@ fn expand_attr_invoc(&mut self,
                 Some(kind.expect_from_annotatables(items))
             }
             AttrProcMacro(ref mac) => {
+                self.gate_proc_macro_attr_item(attr.span, &item);
                 let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
                     Annotatable::Item(item) => token::NtItem(item),
                     Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
@@ -522,7 +523,8 @@ fn expand_attr_invoc(&mut self,
                     Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                     Annotatable::Expr(expr) => token::NtExpr(expr),
                 })).into();
-                let tok_result = mac.expand(self.cx, attr.span, attr.tokens, item_tok);
+                let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
+                let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
                 self.parse_expansion(tok_result, kind, &attr.path, attr.span)
             }
             ProcMacroDerive(..) | BuiltinDerive(..) => {
@@ -539,6 +541,49 @@ fn expand_attr_invoc(&mut self,
         }
     }
 
+    fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> TokenStream {
+        let mut trees = tokens.trees();
+        match trees.next() {
+            Some(TokenTree::Delimited(_, delim)) => {
+                if trees.next().is_none() {
+                    return delim.tts.into()
+                }
+            }
+            Some(TokenTree::Token(..)) => {}
+            None => return TokenStream::empty(),
+        }
+        self.cx.span_err(span, "custom attribute invocations must be \
+            of the form #[foo] or #[foo(..)], the macro name must only be \
+            followed by a delimiter token");
+        TokenStream::empty()
+    }
+
+    fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
+        let (kind, gate) = match *item {
+            Annotatable::Item(ref item) => {
+                match item.node {
+                    ItemKind::Mod(_) if self.cx.ecfg.proc_macro_mod() => return,
+                    ItemKind::Mod(_) => ("modules", "proc_macro_mod"),
+                    _ => return,
+                }
+            }
+            Annotatable::TraitItem(_) => return,
+            Annotatable::ImplItem(_) => return,
+            Annotatable::ForeignItem(_) => return,
+            Annotatable::Stmt(_) |
+            Annotatable::Expr(_) if self.cx.ecfg.proc_macro_expr() => return,
+            Annotatable::Stmt(_) => ("statements", "proc_macro_expr"),
+            Annotatable::Expr(_) => ("expressions", "proc_macro_expr"),
+        };
+        emit_feature_err(
+            self.cx.parse_sess,
+            gate,
+            span,
+            GateIssue::Language,
+            &format!("custom attributes cannot be applied to {}", kind),
+        );
+    }
+
     /// Expand a macro invocation. Returns the result of expansion.
     fn expand_bang_invoc(&mut self,
                          invoc: Invocation,
@@ -665,6 +710,7 @@ fn expand_bang_invoc(&mut self,
                     self.cx.trace_macros_diag();
                     kind.dummy(span)
                 } else {
+                    self.gate_proc_macro_expansion_kind(span, kind);
                     invoc.expansion_data.mark.set_expn_info(ExpnInfo {
                         call_site: span,
                         callee: NameAndSpan {
@@ -695,6 +741,30 @@ fn expand_bang_invoc(&mut self,
         }
     }
 
+    fn gate_proc_macro_expansion_kind(&self, span: Span, kind: ExpansionKind) {
+        let kind = match kind {
+            ExpansionKind::Expr => "expressions",
+            ExpansionKind::OptExpr => "expressions",
+            ExpansionKind::Pat => "patterns",
+            ExpansionKind::Ty => "types",
+            ExpansionKind::Stmts => "statements",
+            ExpansionKind::Items => return,
+            ExpansionKind::TraitItems => return,
+            ExpansionKind::ImplItems => return,
+            ExpansionKind::ForeignItems => return,
+        };
+        if self.cx.ecfg.proc_macro_non_items() {
+            return
+        }
+        emit_feature_err(
+            self.cx.parse_sess,
+            "proc_macro_non_items",
+            span,
+            GateIssue::Language,
+            &format!("procedural macros cannot be expanded to {}", kind),
+        );
+    }
+
     /// Expand a derive invocation. Returns the result of expansion.
     fn expand_derive_invoc(&mut self,
                            invoc: Invocation,
@@ -1370,6 +1440,9 @@ fn enable_allow_internal_unstable = allow_internal_unstable,
         fn enable_custom_derive = custom_derive,
         fn proc_macro_enabled = proc_macro,
         fn macros_in_extern_enabled = macros_in_extern,
+        fn proc_macro_mod = proc_macro_mod,
+        fn proc_macro_expr = proc_macro_expr,
+        fn proc_macro_non_items = proc_macro_non_items,
     }
 }
 
index 7b7cfe5eea00b72a945a70e0f560de5084e4aa01..39ddb13d347889dbe647fa28cde7e685687f734c 100644 (file)
@@ -272,6 +272,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // Allows cfg(target_has_atomic = "...").
     (active, cfg_target_has_atomic, "1.9.0", Some(32976), None),
 
+    // The `!` type. Does not imply exhaustive_patterns (below) any more.
+    (active, never_type, "1.13.0", Some(35121), None),
+
     // Allows exhaustive pattern matching on types that contain uninhabited types.
     (active, exhaustive_patterns, "1.13.0", None, None),
 
@@ -451,6 +454,18 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (active, mmx_target_feature, "1.27.0", None, None),
     (active, sse4a_target_feature, "1.27.0", None, None),
     (active, tbm_target_feature, "1.27.0", None, None),
+
+    // Allows macro invocations of the form `#[foo::bar]`
+    (active, proc_macro_path_invoc, "1.27.0", None, None),
+
+    // Allows macro invocations on modules expressions and statements and
+    // procedural macros to expand to non-items.
+    (active, proc_macro_mod, "1.27.0", None, None),
+    (active, proc_macro_expr, "1.27.0", None, None),
+    (active, proc_macro_non_items, "1.27.0", None, None),
+
+    // #[doc(alias = "...")]
+    (active, doc_alias, "1.27.0", Some(50146), None),
 );
 
 declare_features! (
@@ -921,7 +936,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                  "the `#[naked]` attribute \
                                   is an experimental feature",
                                  cfg_fn!(naked_functions))),
-    ("target_feature", Normal, Ungated),
+    ("target_feature", Whitelisted, Ungated),
     ("export_name", Whitelisted, Ungated),
     ("inline", Whitelisted, Ungated),
     ("link", Whitelisted, Ungated),
@@ -1227,10 +1242,9 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue
         GateIssue::Library(lib) => lib,
     };
 
-    let explanation = if let Some(n) = issue {
-        format!("{} (see issue #{})", explain, n)
-    } else {
-        explain.to_owned()
+    let explanation = match issue {
+        None | Some(0) => explain.to_owned(),
+        Some(n) => format!("{} (see issue #{})", explain, n)
     };
 
     let mut err = match level {
@@ -1446,6 +1460,10 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
                     gate_feature_post!(&self, doc_spotlight, attr.span,
                         "#[doc(spotlight)] is experimental"
                     );
+                } else if content.iter().any(|c| c.check_name("alias")) {
+                    gate_feature_post!(&self, doc_alias, attr.span,
+                        "#[doc(alias = \"...\")] is experimental"
+                    );
                 }
             }
         }
@@ -1635,6 +1653,10 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
             ast::TyKind::BareFn(ref bare_fn_ty) => {
                 self.check_abi(bare_fn_ty.abi, ty.span);
             }
+            ast::TyKind::Never => {
+                gate_feature_post!(&self, never_type, ty.span,
+                                   "The `!` type is experimental");
+            }
             ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
                 gate_feature_post!(&self, dyn_trait, ty.span,
                                    "`dyn Trait` syntax is unstable");
@@ -1745,8 +1767,8 @@ fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
                 }
             }
             ast::TraitItemKind::Type(_, ref default) => {
-                // We use two if statements instead of something like match guards so that both
-                // of these errors can be emitted if both cases apply.
+                // We use three if statements instead of something like match guards so that all
+                // of these errors can be emitted if all cases apply.
                 if default.is_some() {
                     gate_feature_post!(&self, associated_type_defaults, ti.span,
                                        "associated type defaults are unstable");
@@ -1755,6 +1777,10 @@ fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
                     gate_feature_post!(&self, generic_associated_types, ti.span,
                                        "generic associated types are unstable");
                 }
+                if !ti.generics.where_clause.predicates.is_empty() {
+                    gate_feature_post!(&self, generic_associated_types, ti.span,
+                                       "where clauses on associated types are unstable");
+                }
             }
             _ => {}
         }
index a7a9ce745122c36612eecdbf51ffc331cf1e16e6..9fa3952ca80ca07594dd62ee547794ce204e3cb5 100644 (file)
@@ -589,7 +589,8 @@ fn next_tok(&mut self) -> TokenAndSpan {
             self.token_cursor.next()
         };
         if next.sp == syntax_pos::DUMMY_SP {
-            next.sp = self.prev_span;
+            // Tweak the location for better diagnostics, but keep syntactic context intact.
+            next.sp = self.prev_span.with_ctxt(next.sp.ctxt());
         }
         next
     }
@@ -5758,18 +5759,33 @@ pub fn parse_single_struct_field(&mut self,
                                      vis: Visibility,
                                      attrs: Vec<Attribute> )
                                      -> PResult<'a, StructField> {
+        let mut seen_comma: bool = false;
         let a_var = self.parse_name_and_ty(lo, vis, attrs)?;
+        if self.token == token::Comma {
+            seen_comma = true;
+        }
         match self.token {
             token::Comma => {
                 self.bump();
             }
             token::CloseDelim(token::Brace) => {}
             token::DocComment(_) => {
+                let previous_span = self.prev_span;
                 let mut err = self.span_fatal_err(self.span, Error::UselessDocComment);
                 self.bump(); // consume the doc comment
-                if self.eat(&token::Comma) || self.token == token::CloseDelim(token::Brace) {
+                let comma_after_doc_seen = self.eat(&token::Comma);
+                // `seen_comma` is always false, because we are inside doc block
+                // condition is here to make code more readable
+                if seen_comma == false && comma_after_doc_seen == true {
+                    seen_comma = true;
+                }
+                if comma_after_doc_seen || self.token == token::CloseDelim(token::Brace) {
                     err.emit();
                 } else {
+                    if seen_comma == false {
+                        let sp = self.sess.codemap().next_point(previous_span);
+                        err.span_suggestion(sp, "missing comma here", ",".into());
+                    }
                     return Err(err);
                 }
             }
index fd2e760e9bee0ab5108d76eb779735280dcf909b..325927ed8323788bf0c6013fd3750574d8ccb40c 100644 (file)
@@ -320,37 +320,48 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
 #[derive(PartialEq)]
 enum HasTestSignature {
     Yes,
-    No,
+    No(BadTestSignature),
+}
+
+#[derive(PartialEq)]
+enum BadTestSignature {
     NotEvenAFunction,
+    WrongTypeSignature,
+    NoArgumentsAllowed,
+    ShouldPanicOnlyWithNoArgs,
 }
 
 fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     let has_test_attr = attr::contains_name(&i.attrs, "test");
 
     fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
+        let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic");
         match i.node {
             ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
                 // If the termination trait is active, the compiler will check that the output
                 // type implements the `Termination` trait as `libtest` enforces that.
-                let output_matches = if cx.features.termination_trait_test {
-                    true
-                } else {
-                    let no_output = match decl.output {
-                        ast::FunctionRetTy::Default(..) => true,
-                        ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
-                        _ => false
-                    };
-
-                    no_output && !generics.is_parameterized()
+                let has_output = match decl.output {
+                    ast::FunctionRetTy::Default(..) => false,
+                    ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => false,
+                    _ => true
                 };
 
-                if decl.inputs.is_empty() && output_matches {
-                    Yes
-                } else {
-                    No
+                if !decl.inputs.is_empty() {
+                    return No(BadTestSignature::NoArgumentsAllowed);
+                }
+
+                match (has_output, cx.features.termination_trait_test, has_should_panic_attr) {
+                    (true, true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
+                    (true, true, false) => if generics.is_parameterized() {
+                        No(BadTestSignature::WrongTypeSignature)
+                    } else {
+                        Yes
+                    },
+                    (true, false, _) => No(BadTestSignature::WrongTypeSignature),
+                    (false, _, _) => Yes
                 }
             }
-            _ => NotEvenAFunction,
+            _ => No(BadTestSignature::NotEvenAFunction),
         }
     }
 
@@ -358,18 +369,20 @@ fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
         let diag = cx.span_diagnostic;
         match has_test_signature(cx, i) {
             Yes => true,
-            No => {
-                if cx.features.termination_trait_test {
-                    diag.span_err(i.span, "functions used as tests can not have any arguments");
-                } else {
-                    diag.span_err(i.span, "functions used as tests must have signature fn() -> ()");
+            No(cause) => {
+                match cause {
+                    BadTestSignature::NotEvenAFunction =>
+                        diag.span_err(i.span, "only functions may be used as tests"),
+                    BadTestSignature::WrongTypeSignature =>
+                        diag.span_err(i.span,
+                                      "functions used as tests must have signature fn() -> ()"),
+                    BadTestSignature::NoArgumentsAllowed =>
+                        diag.span_err(i.span, "functions used as tests can not have any arguments"),
+                    BadTestSignature::ShouldPanicOnlyWithNoArgs =>
+                        diag.span_err(i.span, "functions using `#[should_panic]` must return `()`"),
                 }
                 false
-            },
-            NotEvenAFunction => {
-                diag.span_err(i.span, "only functions may be used as tests");
-                false
-            },
+            }
         }
     } else {
         false
@@ -407,7 +420,7 @@ fn has_bench_signature(cx: &TestCtxt, i: &ast::Item) -> bool {
                 // well before resolve, can't get too deep.
                 input_cnt == 1 && output_matches
             }
-          _ => false
+            _ => false
         }
     }
 
index 1a392ac376537b40aba9cd413d6fd02c3ac5c125..99b6f752e9406a48c91e12f1ef8a806897cb9d71 100644 (file)
@@ -38,7 +38,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                           name: "cmp",
                           generics: LifetimeBounds::empty(),
                           explicit_self: borrowed_explicit_self(),
-                          args: vec![borrowed_self()],
+                          args: vec![(borrowed_self(), "other")],
                           ret_ty: Literal(path_std!(cx, cmp::Ordering)),
                           attributes: attrs,
                           is_unsafe: false,
@@ -64,7 +64,7 @@ pub fn ordering_collapsed(cx: &mut ExtCtxt,
 }
 
 pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-    let test_id = cx.ident_of("__cmp");
+    let test_id = cx.ident_of("cmp").gensym();
     let equals_path = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
 
     let cmp_path = cx.std_path(&["cmp", "Ord", "cmp"]);
@@ -77,9 +77,9 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
     // ::std::cmp::Ordering::Equal => {
     // ...
     // }
-    // __cmp => __cmp
+    // cmp => cmp
     // },
-    // __cmp => __cmp
+    // cmp => cmp
     // }
     //
     cs_fold(// foldr nests the if-elses correctly, leaving the first field
@@ -88,7 +88,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
             |cx, span, old, self_f, other_fs| {
         // match new {
         //     ::std::cmp::Ordering::Equal => old,
-        //     __cmp => __cmp
+        //     cmp => cmp
         // }
 
         let new = {
index 81ca7e732283d07b3997627013904f7b15315d57..c259733d81abdc8e8e288b3f7a91c940672b40d5 100644 (file)
@@ -78,7 +78,7 @@ macro_rules! md {
                 name: $name,
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
-                args: vec![borrowed_self()],
+                args: vec![(borrowed_self(), "other")],
                 ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 is_unsafe: false,
index 9560fd0570af7b681153f91e25e10d438f12513f..d71527fd0ed0f960f11502401150d58b1575a74a 100644 (file)
@@ -34,7 +34,7 @@ macro_rules! md {
                 name: $name,
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
-                args: vec![borrowed_self()],
+                args: vec![(borrowed_self(), "other")],
                 ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 is_unsafe: false,
@@ -59,7 +59,7 @@ macro_rules! md {
         name: "partial_cmp",
         generics: LifetimeBounds::empty(),
         explicit_self: borrowed_explicit_self(),
-        args: vec![borrowed_self()],
+        args: vec![(borrowed_self(), "other")],
         ret_ty,
         attributes: attrs,
         is_unsafe: false,
@@ -123,7 +123,7 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt,
 }
 
 pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-    let test_id = cx.ident_of("__cmp");
+    let test_id = cx.ident_of("cmp").gensym();
     let ordering = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
     let ordering_expr = cx.expr_path(ordering.clone());
     let equals_expr = cx.expr_some(span, ordering_expr);
@@ -138,9 +138,9 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
     // ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {
     // ...
     // }
-    // __cmp => __cmp
+    // cmp => cmp
     // },
-    // __cmp => __cmp
+    // cmp => cmp
     // }
     //
     cs_fold(// foldr nests the if-elses correctly, leaving the first field
@@ -149,7 +149,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
             |cx, span, old, self_f, other_fs| {
         // match new {
         //     Some(::std::cmp::Ordering::Equal) => old,
-        //     __cmp => __cmp
+        //     cmp => cmp
         // }
 
         let new = {
index c007285cd85191afdf4eaa0037e3cd5cf7035de1..b546f5df15799467ad2daf2f8dd9408c4692a9e1 100644 (file)
@@ -40,7 +40,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt,
                           name: "fmt",
                           generics: LifetimeBounds::empty(),
                           explicit_self: borrowed_explicit_self(),
-                          args: vec![fmtr],
+                          args: vec![(fmtr, "f")],
                           ret_ty: Literal(path_std!(cx, fmt::Result)),
                           attributes: Vec::new(),
                           is_unsafe: false,
@@ -70,7 +70,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = span.with_ctxt(cx.backtrace());
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
-    let builder = Ident::from_str("__debug_trait_builder");
+    let builder = Ident::from_str("debug_trait_builder").gensym();
     let builder_expr = cx.expr_ident(span, builder.clone());
 
     let fmt = substr.nonself_args[0].clone();
index 46dada256b8208c7d1f5bf2ef9f7277068e0b204..7618fe63ab3354461b499c423792defbe1f3a93b 100644 (file)
@@ -67,8 +67,8 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
                                                             PathKind::Global)])],
                           },
                           explicit_self: None,
-                          args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))),
-                                         Borrowed(None, Mutability::Mutable))],
+                          args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))),
+                                         Borrowed(None, Mutability::Mutable)), "d")],
                           ret_ty:
                               Literal(Path::new_(pathvec_std!(cx, result::Result),
                                                  None,
index d579b3abd45a902b39a947ddc480975717fddcd1..2c6c18cc51cd7daf36067031c163ae580fc4dcc3 100644 (file)
@@ -148,8 +148,8 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
                     ],
                 },
                 explicit_self: borrowed_explicit_self(),
-                args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))),
-                           Borrowed(None, Mutability::Mutable))],
+                args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))),
+                           Borrowed(None, Mutability::Mutable)), "s")],
                 ret_ty: Literal(Path::new_(
                     pathvec_std!(cx, result::Result),
                     None,
index 1f80385cfbd24051b7acf05733918f02ba699a54..1ef0d2b0b4931be33057d9148e21a769696bb846 100644 (file)
@@ -252,7 +252,7 @@ pub struct MethodDef<'a> {
     pub explicit_self: Option<Option<PtrTy<'a>>>,
 
     /// Arguments other than the self argument
-    pub args: Vec<Ty<'a>>,
+    pub args: Vec<(Ty<'a>, &'a str)>,
 
     /// Return type
     pub ret_ty: Ty<'a>,
@@ -915,9 +915,9 @@ fn split_self_nonself_args
             explicit_self
         });
 
-        for (i, ty) in self.args.iter().enumerate() {
+        for (ty, name) in self.args.iter() {
             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = cx.ident_of(&format!("__arg_{}", i));
+            let ident = cx.ident_of(name).gensym();
             arg_tys.push((ident, ast_ty));
 
             let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -1004,10 +1004,10 @@ fn create_method(&self,
     ///
     /// // equivalent to:
     /// impl PartialEq for A {
-    ///     fn eq(&self, __arg_1: &A) -> bool {
+    ///     fn eq(&self, other: &A) -> bool {
     ///         match *self {
     ///             A {x: ref __self_0_0, y: ref __self_0_1} => {
-    ///                 match *__arg_1 {
+    ///                 match *other {
     ///                     A {x: ref __self_1_0, y: ref __self_1_1} => {
     ///                         __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1)
     ///                     }
@@ -1020,10 +1020,10 @@ fn create_method(&self,
     /// // or if A is repr(packed) - note fields are matched by-value
     /// // instead of by-reference.
     /// impl PartialEq for A {
-    ///     fn eq(&self, __arg_1: &A) -> bool {
+    ///     fn eq(&self, other: &A) -> bool {
     ///         match *self {
     ///             A {x: __self_0_0, y: __self_0_1} => {
-    ///                 match __arg_1 {
+    ///                 match other {
     ///                     A {x: __self_1_0, y: __self_1_1} => {
     ///                         __self_0_0.eq(&__self_1_0) && __self_0_1.eq(&__self_1_1)
     ///                     }
@@ -1134,14 +1134,14 @@ fn expand_static_struct_method_body(&self,
     /// // is equivalent to
     ///
     /// impl PartialEq for A {
-    ///     fn eq(&self, __arg_1: &A) -> ::bool {
-    ///         match (&*self, &*__arg_1) {
+    ///     fn eq(&self, other: &A) -> ::bool {
+    ///         match (&*self, &*other) {
     ///             (&A1, &A1) => true,
     ///             (&A2(ref self_0),
     ///              &A2(ref __arg_1_0)) => (*self_0).eq(&(*__arg_1_0)),
     ///             _ => {
     ///                 let __self_vi = match *self { A1(..) => 0, A2(..) => 1 };
-    ///                 let __arg_1_vi = match *__arg_1 { A1(..) => 0, A2(..) => 1 };
+    ///                 let __arg_1_vi = match *other { A1(..) => 0, A2(..) => 1 };
     ///                 false
     ///             }
     ///         }
@@ -1240,7 +1240,7 @@ fn build_enum_match_tuple<'b>(&self,
         let vi_idents: Vec<ast::Ident> = self_arg_names.iter()
             .map(|name| {
                 let vi_suffix = format!("{}_vi", &name[..]);
-                cx.ident_of(&vi_suffix[..])
+                cx.ident_of(&vi_suffix[..]).gensym()
             })
             .collect::<Vec<ast::Ident>>();
 
@@ -1616,7 +1616,7 @@ fn create_struct_pattern
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = struct_field.span.with_ctxt(self.span.ctxt());
-            let ident = cx.ident_of(&format!("{}_{}", prefix, i));
+            let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym();
             paths.push(ident.with_span_pos(sp));
             let val = cx.expr_path(cx.path_ident(sp, ident));
             let val = if use_temporaries {
index b192ab2527e4b8f04319cfb6e006f3665bff8643..67096cdb49a3c5da2d589f47c4978b8a12a9cc3d 100644 (file)
@@ -44,8 +44,8 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                               bounds: vec![(typaram, vec![path_std!(cx, hash::Hasher)])],
                           },
                           explicit_self: borrowed_explicit_self(),
-                          args: vec![Ptr(Box::new(Literal(arg)),
-                                         Borrowed(None, Mutability::Mutable))],
+                          args: vec![(Ptr(Box::new(Literal(arg)),
+                                         Borrowed(None, Mutability::Mutable)), "state")],
                           ret_ty: nil_ty(),
                           attributes: vec![],
                           is_unsafe: false,
index c78decb1eb9d0bc2983a94c75974fe9c8e4a0a22..6b155b6596d08c80cd50d1e09564ceba91ac2aa1 100644 (file)
@@ -543,6 +543,10 @@ fn into_expr(self) -> P<ast::Expr> {
         let mut pats = Vec::new();
         let mut heads = Vec::new();
 
+        let names_pos: Vec<_> = (0..self.args.len()).map(|i| {
+            self.ecx.ident_of(&format!("arg{}", i)).gensym()
+        }).collect();
+
         // First, build up the static array which will become our precompiled
         // format "string"
         let pieces = self.ecx.expr_vec_slice(self.fmtsp, self.str_pieces);
@@ -560,7 +564,7 @@ fn into_expr(self) -> P<ast::Expr> {
         // of each variable because we don't want to move out of the arguments
         // passed to this function.
         for (i, e) in self.args.into_iter().enumerate() {
-            let name = self.ecx.ident_of(&format!("__arg{}", i));
+            let name = names_pos[i];
             let span =
                 DUMMY_SP.with_ctxt(e.span.ctxt().apply_mark(self.ecx.current_expansion.mark));
             pats.push(self.ecx.pat_ident(span, name));
@@ -570,14 +574,12 @@ fn into_expr(self) -> P<ast::Expr> {
             heads.push(self.ecx.expr_addr_of(e.span, e));
         }
         for pos in self.count_args {
-            let name = self.ecx.ident_of(&match pos {
-                Exact(i) => format!("__arg{}", i),
-                _ => panic!("should never happen"),
-            });
-            let span = match pos {
-                Exact(i) => spans_pos[i],
+            let index = match pos {
+                Exact(i) => i,
                 _ => panic!("should never happen"),
             };
+            let name = names_pos[index];
+            let span = spans_pos[index];
             counts.push(Context::format_arg(self.ecx, self.macsp, span, &Count, name));
         }
 
index 50fac600a978d21ab05dc0ae9174120f25621029..556ee162c6ef2974dfc51fe5ef1caf2e98059088 100644 (file)
@@ -15,8 +15,8 @@
 use hygiene::SyntaxContext;
 use {Span, DUMMY_SP, GLOBALS};
 
+use rustc_data_structures::fx::FxHashMap;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::collections::HashMap;
 use std::fmt;
 use std::hash::{Hash, Hasher};
 
@@ -53,6 +53,10 @@ pub fn without_first_quote(self) -> Ident {
     pub fn modern(self) -> Ident {
         Ident::new(self.name, self.span.modern())
     }
+
+    pub fn gensym(self) -> Ident {
+        Ident::new(self.name.gensymed(), self.span)
+    }
 }
 
 impl PartialEq for Ident {
@@ -184,7 +188,7 @@ fn eq(&self, other: &T) -> bool {
 
 #[derive(Default)]
 pub struct Interner {
-    names: HashMap<Box<str>, Symbol>,
+    names: FxHashMap<Box<str>, Symbol>,
     strings: Vec<Box<str>>,
     gensyms: Vec<Symbol>,
 }
index 9fea907d3c884e56f1078e4b197b9dc3df38a8c9..6863b1f2792b919b41cf81b76abaed7faf597f86 100644 (file)
@@ -11,6 +11,7 @@
 // aux-build:nounwind.rs
 // compile-flags: -C no-prepopulate-passes -C panic=abort -C metadata=a
 // ignore-windows
+// ignore-android
 
 #![crate_type = "lib"]
 
index 2f65bd16bb54a1953a0422d57e1ee2c5add15a7b..749d87e37b5599d4d38356e152de48641e5427d8 100644 (file)
@@ -13,7 +13,7 @@
 
 //! Attributes producing expressions in invalid locations
 
-#![feature(proc_macro, stmt_expr_attributes)]
+#![feature(proc_macro, stmt_expr_attributes, proc_macro_expr)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{duplicate, no_output};
index d29bc00c663c8e2788a4884b47a69e5c761b693a..ce04fdfb976d4aa32306a7be25147e056c825a38 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-stmt-expr.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_expr)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};
index 2adbee1d3fbd5b7c23bf58667d33f00e893c1c54..9947e8f66cedac251a2c01506b335b9f585cd07b 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attributes-included.rs
 // ignore-stage1
 
-#![feature(proc_macro, rustc_attrs)]
+#![feature(proc_macro, rustc_attrs, proc_macro_path_invoc)]
 #![warn(unused)]
 
 extern crate attributes_included;
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/proc-macro-gates.rs
new file mode 100644 (file)
index 0000000..25579f1
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.
+
+// no-prefer-dynamic
+// force-host
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn m(a: TokenStream) -> TokenStream {
+    a
+}
+
+#[proc_macro_attribute]
+pub fn a(_a: TokenStream, b: TokenStream) -> TokenStream {
+    b
+}
index 773b16b945f072ff359804c9d5e2c46d6e2be952..c7be316794746c9f04fe63345dcfe03b6213e0a3 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:bang_proc_macro2.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 #![allow(unused_macros)]
 
 extern crate bang_proc_macro2;
index 7ecc685357ee675b0e4235f51756790b25a1c6e3..f16ca79ca9313a9c6dcb4db6c8e589feffc9982e 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:bang_proc_macro.rs
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 #[macro_use]
 extern crate bang_proc_macro;
diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
new file mode 100644 (file)
index 0000000..0dc1c2a
--- /dev/null
@@ -0,0 +1,54 @@
+// 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.
+
+// aux-build:proc-macro-gates.rs
+// gate-test-proc_macro_non_items
+// gate-test-proc_macro_path_invoc
+// gate-test-proc_macro_mod line
+// gate-test-proc_macro_expr
+// gate-test-proc_macro_mod
+
+#![feature(proc_macro, stmt_expr_attributes)]
+
+extern crate proc_macro_gates as foo;
+
+use foo::*;
+
+#[foo::a] //~ ERROR: paths of length greater than one
+fn _test() {}
+
+#[a] //~ ERROR: custom attributes cannot be applied to modules
+mod _test2 {}
+
+#[a = y] //~ ERROR: must only be followed by a delimiter token
+fn _test3() {}
+
+#[a = ] //~ ERROR: must only be followed by a delimiter token
+fn _test4() {}
+
+#[a () = ] //~ ERROR: must only be followed by a delimiter token
+fn _test5() {}
+
+fn main() {
+    #[a] //~ ERROR: custom attributes cannot be applied to statements
+    let _x = 2;
+    let _x = #[a] 2;
+    //~^ ERROR: custom attributes cannot be applied to expressions
+
+    let _x: m!(u32) = 3;
+    //~^ ERROR: procedural macros cannot be expanded to types
+    if let m!(Some(_x)) = Some(3) {
+    //~^ ERROR: procedural macros cannot be expanded to patterns
+    }
+    let _x = m!(3);
+    //~^ ERROR: procedural macros cannot be expanded to expressions
+    m!(let _x = 3;);
+    //~^ ERROR: procedural macros cannot be expanded to statements
+}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates2.rs
new file mode 100644 (file)
index 0000000..a1a15af
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+// aux-build:proc-macro-gates.rs
+
+#![feature(proc_macro, stmt_expr_attributes)]
+
+extern crate proc_macro_gates as foo;
+
+use foo::*;
+
+// NB. these errors aren't the best errors right now, but they're definitely
+// intended to be errors. Somehow using a custom attribute in these positions
+// should either require a feature gate or not be allowed on stable.
+
+fn _test6<#[a] T>() {}
+//~^ ERROR: unknown to the compiler
+
+fn _test7() {
+    match 1 {
+        #[a] //~ ERROR: unknown to the compiler
+        0 => {}
+        _ => {}
+    }
+}
+
+fn main() {
+}
index 1479d0b62642a76cc8267994d270e196ce0eade0..140cad22f34e42ae52b5b94ffe1b071fd9c3ff41 100644 (file)
@@ -16,6 +16,5 @@
 //~| the trait bound `usize:
 //~| the trait bound `usize:
 //~| the trait bound `usize:
-//~| the trait bound `usize:
 
 fn main() {}
index 501c66e75cded115892fddfe02c0be9588b0c9c0..9b9deb4ca8d9d9cbef5304fd34a13d4447a388f0 100644 (file)
@@ -12,6 +12,7 @@
 const B: i32 = (&A)[1];
 //~^ ERROR constant evaluation error
 //~| index out of bounds: the len is 0 but the index is 1
+//~| WARN this constant cannot be used
 
 fn main() {
     let _ = B;
index d3b43e83bfe5218ac914584e6424f6fd4ee4a9d4..46feb20cf11ddbda624db1055b74db74476b9965 100644 (file)
@@ -12,6 +12,7 @@
 const B: i32 = A[1];
 //~^ ERROR constant evaluation error
 //~| index out of bounds: the len is 0 but the index is 1
+//~| WARN this constant cannot be used
 
 fn main() {
     let _ = B;
index c2f157cd35cce82942e077ba8dbf7f63217322a8..583befed1e8287bf8d82f23f38a71f3e24a4a71b 100644 (file)
@@ -10,6 +10,8 @@
 
 // Test that we can't pass other types for !
 
+#![feature(never_type)]
+
 fn foo(x: !) -> ! {
     x
 }
index 5efb4dadc64bdafdcf02482ad3949f5d3e521483..14a06b306d82a93a8dc71a82c5f3cf54b8f43b43 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 fn foo(x: usize, y: !, z: usize) { }
 
 fn cast_a() {
index 15049232a4d3f4450a63795a444f5be2a674b583..62ff09f4616b80c7268bcefeb6aa954c1132a6fc 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 fn foo(x: usize, y: !, z: usize) { }
 
 fn call_foo_a() {
index 3de0f1ff61e1cb4c148ba5ec1a3a7ba99bb7df7d..6caec159d019ce39ce7f9bd1d65f64a561aa9b53 100644 (file)
 
 #![deny(const_err)]
 
-pub const A: i8 = -std::i8::MIN; //~ ERROR E0080
-//~^ ERROR attempt to negate with overflow
+pub const A: i8 = -std::i8::MIN; //~ ERROR const_err
+//~^ ERROR this constant cannot be used
 //~| ERROR constant evaluation error
-pub const B: u8 = 200u8 + 200u8; //~ ERROR E0080
-//~^ ERROR attempt to add with overflow
-pub const C: u8 = 200u8 * 4; //~ ERROR E0080
-//~^ ERROR attempt to multiply with overflow
-pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR E0080
-//~^ ERROR attempt to subtract with overflow
+pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
+//~^ ERROR this constant cannot be used
+pub const C: u8 = 200u8 * 4; //~ ERROR const_err
+//~^ ERROR this constant cannot be used
+pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err
+//~^ ERROR this constant cannot be used
 pub const E: u8 = [5u8][1];
-//~^ ERROR E0080
+//~^ ERROR const_err
 
 fn main() {
     let _a = A;
index d2355f57f17294c5ed97c40a951d97b4de2764d9..6f0281b8bd0ca7382bf595d54137dae3a5b852a7 100644 (file)
 //~^ ERROR E0080
 //~| ERROR attempt to negate with overflow
 //~| ERROR constant evaluation error
+//~| ERROR this constant cannot be used
 pub const B: i8 = A;
-//~^ ERROR E0080
+//~^ ERROR const_err
 pub const C: u8 = A as u8;
-//~^ ERROR E0080
+//~^ ERROR const_err
 pub const D: i8 = 50 - A;
-//~^ ERROR E0080
+//~^ ERROR const_err
 
 fn main() {
     let _ = (A, B, C, D);
index a0d8f9672c05e1519ffb37e72705dae40315ca4e..faa8c3039b78cdfe0aae394a6428ea16b9adc8bd 100644 (file)
 use std::{u8, u16, u32, u64, usize};
 
 const VALS_I8: (i8,) =
+     //~^ ERROR this constant cannot be used
     (
      i8::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I16: (i16,) =
+     //~^ ERROR this constant cannot be used
     (
      i16::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I32: (i32,) =
+     //~^ ERROR this constant cannot be used
     (
      i32::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_I64: (i64,) =
+     //~^ ERROR this constant cannot be used
     (
      i64::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U8: (u8,) =
+     //~^ ERROR this constant cannot be used
     (
      u8::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U16: (u16,) = (
+     //~^ ERROR this constant cannot be used
      u16::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U32: (u32,) = (
+     //~^ ERROR this constant cannot be used
      u32::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 const VALS_U64: (u64,) =
+     //~^ ERROR this constant cannot be used
     (
      u64::MIN - 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to subtract with overflow
+     //~^ ERROR attempt to subtract with overflow
      );
 
 fn main() {
index 08128f90e532f368a16185a155bcbe0b5ac13104..d827e680c5bbbec49cad32f782b1b96cda6764d8 100644 (file)
 use std::{u8, u16, u32, u64, usize};
 
 const VALS_I8: (i8,) =
+     //~^ ERROR this constant cannot be used
     (
      i8::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I16: (i16,) =
+     //~^ ERROR this constant cannot be used
     (
      i16::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I32: (i32,) =
+     //~^ ERROR this constant cannot be used
     (
      i32::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_I64: (i64,) =
+     //~^ ERROR this constant cannot be used
     (
      i64::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U8: (u8,) =
+     //~^ ERROR this constant cannot be used
     (
      u8::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U16: (u16,) = (
+     //~^ ERROR this constant cannot be used
      u16::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U32: (u32,) = (
+     //~^ ERROR this constant cannot be used
      u32::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 const VALS_U64: (u64,) =
+     //~^ ERROR this constant cannot be used
     (
      u64::MAX + 1,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to add with overflow
+     //~^ ERROR attempt to add with overflow
      );
 
 fn main() {
index 31a1638cade170e7fecbf058fd4266937d22093c..2fd46b038ef28d7e62b9f98fcec95e360ba5c119 100644 (file)
 use std::{u8, u16, u32, u64, usize};
 
 const VALS_I8: (i8,) =
+     //~^ ERROR this constant cannot be used
     (
      i8::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I16: (i16,) =
+     //~^ ERROR this constant cannot be used
     (
      i16::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I32: (i32,) =
+     //~^ ERROR this constant cannot be used
     (
      i32::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_I64: (i64,) =
+     //~^ ERROR this constant cannot be used
     (
      i64::MIN * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U8: (u8,) =
+     //~^ ERROR this constant cannot be used
     (
      u8::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U16: (u16,) = (
+     //~^ ERROR this constant cannot be used
      u16::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U32: (u32,) = (
+     //~^ ERROR this constant cannot be used
      u32::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 const VALS_U64: (u64,) =
+     //~^ ERROR this constant cannot be used
     (
      u64::MAX * 2,
-     //~^ ERROR constant evaluation error
-     //~| ERROR attempt to multiply with overflow
+     //~^ ERROR attempt to multiply with overflow
      );
 
 fn main() {
index 179ea9e853f3ad6bd4a4abc7973ee4fb40e7203d..7da5a2f17eaf90960d6339474ec99ddd2a509b47 100644 (file)
@@ -14,6 +14,7 @@
 const BAR: u32 = FOO[5];
 //~^ ERROR constant evaluation error [E0080]
 //~| index out of bounds: the len is 3 but the index is 5
+//~| WARN this constant cannot be used
 
 fn main() {
     let _ = BAR;
index 798544f164932a59f84baab5e8ee6fb21c8f39a1..ac8ac85824edcc34783e3d161d76cdc9280f30f2 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// We need to opt inot the `!` feature in order to trigger the
+// requirement that this is testing.
+#![feature(never_type)]
+
 #![allow(unused)]
 
 trait Deserialize: Sized {
index fdc9b4f704cd16f4c988cb87f198291b3e46d27d..b304443f63145701d2294af7713e685cb6c25fc4 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Zedition=2015 -Zunstable-options
+// compile-flags: --edition=2015 -Zunstable-options
 
 // tests that editions work with the tyvar warning-turned-error
 
index 58b34591029ba98ee18542a695e7e797e1012264..d01cac019e36c8da18b0562a66060ce81e28468c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Zedition=2018 -Zunstable-options
+// compile-flags: --edition=2018 -Zunstable-options
 
 // tests that editions work with the tyvar warning-turned-error
 
index 4267103ab9a3aacae556f5a919e5f9bab8e449af..08269ce5c7ecf0d2083fb483d46868a69915ab7a 100644 (file)
@@ -10,7 +10,7 @@
 
 // #41719
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 fn main() {
     enum Foo {}
index b9741e0add61ce17ea6325257bd474b37121a592..d11aacec1963169919de344b7bd762004d5d3058 100644 (file)
@@ -10,6 +10,7 @@
 
 // error-pattern:reached recursion limit
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 struct Foo<'a, T: 'a> {
diff --git a/src/test/compile-fail/issue-44578.rs b/src/test/compile-fail/issue-44578.rs
deleted file mode 100644 (file)
index 18cfb35..0000000
+++ /dev/null
@@ -1,34 +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.
-
-trait Foo {
-    const AMT: usize;
-}
-
-enum Bar<A, B> {
-    First(A),
-    Second(B),
-}
-
-impl<A: Foo, B: Foo> Foo for Bar<A, B> {
-    const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
-}
-
-impl Foo for u8 {
-    const AMT: usize = 1;
-}
-
-impl Foo for u16 {
-    const AMT: usize = 2;
-}
-
-fn main() {
-    println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ E0080
-}
index 5ef46bb27fd60a4a772978a3abeee3e9e85adc14..938f7fba2a0324320b3616e4b68e8acc66ec5ce9 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 fn main() {
     let val: ! = loop { break break; };
     //~^ ERROR mismatched types
index 0f123997ca1d975560de09c9bcb3cd72f7c19686..6567a100d8c0664caedda024cc8b097dd9489514 100644 (file)
@@ -10,6 +10,8 @@
 
 // gate-test-use_extern_macros
 
+#![feature(proc_macro_path_invoc)]
+
 fn main() {
     globnar::brotz!(); //~ ERROR non-ident macro paths are experimental
     #[derive(foo::Bar)] struct T; //~ ERROR non-ident macro paths are experimental
index 7046ee12b50e563de83d718f08bf88486667e51a..40412087cef97b0e76e8a8f03774a8bc4295269e 100644 (file)
@@ -13,6 +13,7 @@
 
 #![feature(asm)]
 #![feature(trace_macros, concat_idents)]
+#![feature(proc_macro_path_invoc)]
 
 #[derive(Default)] //~ ERROR
 enum OrDeriveThis {}
index e18c7d77ce366ce974dd48046a07e8ed458ac010..8777ef2ffe33c9e5a774024438c9f4262373a56c 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 mod private {
index 4e987d1ddce577a9c7548a76d16cf5e72b6d3c7c..0fb75b535c6bcd5df32de572ee474ba824089747 100644 (file)
@@ -10,6 +10,7 @@
 
 // Test that an assignment of type ! makes the rest of the block dead code.
 
+#![feature(never_type)]
 #![feature(rustc_attrs)]
 #![warn(unused)]
 
index 8c2de7d68d3de334dc849d08b1f0bdc07d0c955a..c0dd2cab749f4a24cf0753689a842b4bd33d9742 100644 (file)
@@ -10,6 +10,7 @@
 
 // Test that we can't use another type in place of !
 
+#![feature(never_type)]
 #![deny(warnings)]
 
 fn main() {
index 63cb6e82c259e0a88488b432b4d425db229bf041..b64829edaa218772d5f9f0404890a60387cbf368 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
+#![feature(proc_macro_path_invoc)]
 
 mod priv_nominal {
     pub struct Pub;
index bdc0c680a92bc161117743a3bd78179bb3219d33..062dc53361703741fcc8287430f2c097ec8ec6a6 100644 (file)
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 
+#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
index c25616c54354d9f0d856927e915e1f383f5c83ba..0dfa61a18ab8299a601cd0ef9d7bb6bbdef321c3 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro, associated_type_defaults)]
 #![allow(unused, private_in_public)]
 
index 0c393f02323ec04a3757f16aa641798c773227bb..97d6b470d33bb88be183cfb8b785eb3c6eec94a9 100644 (file)
@@ -18,6 +18,7 @@
 // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
 // error-pattern:type `for<'r> fn(&'r ext::Pub<u8>) {<ext::Pub<u8>>::priv_method}` is private
 
+#![feature(proc_macro_path_invoc)]
 #![feature(decl_macro)]
 
 extern crate private_inferred_type as ext;
index 5af8b063c1629f12e0fb6c3f348337b1bef51357..dfc0107e07565635686f9562838d427d9bad3e90 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(associated_consts)]
 #![feature(decl_macro)]
 #![allow(private_in_public)]
+#![feature(proc_macro_path_invoc)]
 
 mod m {
     fn priv_fn() {}
index 365387c3e5e2759a51be7fe972a55d1a5fdb6253..0a0f9ce4bd10eb878a4b4a82dafdd4eea0085735 100644 (file)
@@ -15,7 +15,7 @@
 #![no_std]
 
 // OK
-#[lang = "str"]
+#[lang = "str_alloc"]
 impl str {}
 
 impl str {
index 72b0afa6bd3eea8bc04ddc24b49bdaad4c406f79..05a97b855e703e5fcd50b2b6c2567d3aaadb688e 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 mod foo {
index e130df5c845b58fc309e50e3f2b0208e59427f53..2cf4b78bdffe40927b446c817e93fe903bc657c5 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
index dca79bdfb87f755e5d8490b5a23baba83e50776a..cfd829e416e5b6f4cef4c51e30ad6b026521685f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![deny(unreachable_patterns)]
 
index 0caf7d51234918b7c25eb1b148448b1d4ddd2cb6..df340095bb433477cbe3ddef4476a5decc89e70f 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns, rustc_attrs)]
 #![warn(unreachable_code)]
 #![warn(unreachable_patterns)]
index 7a4b5e59eeb75ddad5474202c4af1d1fee0b9fc5..da68dc39f85d752f3273baa6bc6cbe787d37f8d0 100644 (file)
@@ -11,6 +11,9 @@
 // Test that a variable of type ! can coerce to another type.
 
 // error-pattern:explicit
+
+#![feature(never_type)]
+
 fn main() {
     let x: ! = panic!();
     let y: u32 = x;
index 56454586bb95773ef21bd88a848894c0d9812031..95101e70db95192aae510e6593b4a6175cbfa902 100644 (file)
@@ -12,6 +12,7 @@
 
 // error-pattern:wowzers!
 
+#![feature(never_type)]
 #![allow(unreachable_code)]
 
 fn foo(x: !) -> ! {
index 0155332c51d1b374676376aedf87b16de7b94b9c..8f7b0c40538f9dbd1c2a1e0080b28177cb85186b 100644 (file)
@@ -11,6 +11,9 @@
 // Test that we can explicitly cast ! to another type
 
 // error-pattern:explicit
+
+#![feature(never_type)]
+
 fn main() {
     let x: ! = panic!();
     let y: u32 = x as u32;
index d9b8461a1d07c4b2239daf7607d88bf14245dd73..fdd21e08c20f9ac0b3f5fda8935ac2326f37df0f 100644 (file)
@@ -12,6 +12,8 @@
 
 // error-pattern:kapow!
 
+#![feature(never_type)]
+
 trait Foo {
     type Wow;
 
index 0fe10d43910bfbf961e2dd8db234279bc5d114e8..826ca3a08c0e1dc5e67c30aa80b2c30fef3c33ac 100644 (file)
@@ -12,6 +12,8 @@
 
 // error-pattern:oh no!
 
+#![feature(never_type)]
+
 struct Wub;
 
 impl PartialEq<!> for Wub {
index 281ee70815e11c80442dfce57c8735435ef49c9a..9e1ae59c01bc0f5006d21ca85e609a59ce0f11cf 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate proc_macro;
 
index f485982e2d3bc2c1b6eed767e972661e33c88ba6..6d5e82c68cc8ed883c27e7d8bc504e2c681344d8 100644 (file)
@@ -58,7 +58,7 @@ fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
         name: "eq",
         generics: LifetimeBounds::empty(),
         explicit_self: borrowed_explicit_self(),
-        args: vec![borrowed_self()],
+        args: vec![(borrowed_self(), "other")],
         ret_ty: Literal(deriving::generic::ty::Path::new_local("bool")),
         attributes: attrs,
         is_unsafe: false,
index cf6584e961a67a5997525be85d3488dc6dfbe628..a680698df9a2a11cd23b3d637665793ea3f06eac 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro, proc_macro_lib)]
+#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)]
 
 extern crate proc_macro;
 
index d3670ae66feedf01ba43f5870b6b5131d3375afd..a280b3d87c68508262ba481fec353dfed4fc03d3 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro, proc_macro_lib)]
+#![feature(proc_macro, proc_macro_lib, proc_macro_non_items)]
 
 extern crate proc_macro;
 
diff --git a/src/test/run-pass-fulldeps/deriving-hygiene.rs b/src/test/run-pass-fulldeps/deriving-hygiene.rs
new file mode 100644 (file)
index 0000000..532f245
--- /dev/null
@@ -0,0 +1,25 @@
+// 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(rustc_private)]
+extern crate serialize;
+
+pub const other: u8 = 1;
+pub const f: u8 = 1;
+pub const d: u8 = 1;
+pub const s: u8 = 1;
+pub const state: u8 = 1;
+pub const cmp: u8 = 1;
+
+#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,Decodable,Encodable,Hash)]
+struct Foo {}
+
+fn main() {
+}
index cff743bdae6cd485c756a145d2f5ad903a93b9da..52e8e75f2628e2297c238ab48468fc6a7aa98eee 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:cond_plugin.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate cond_plugin;
 
index eb77895e2d7ad6da63429583b983ee4321f19173..9bb8f691915c74fef5bda9d96d22f71e0cf38455 100644 (file)
@@ -13,7 +13,7 @@
 // aux-build:hello_macro.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc, proc_macro_non_items)]
 
 extern crate hello_macro;
 
index 2968cc7871d7e1ac04691b19e98401ec3772ada4..bf7ac507ea5705553ae396f63134a101eacd02b1 100644 (file)
@@ -12,7 +12,7 @@
 // ignore-stage1
 
 #![allow(warnings)]
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc)]
 
 extern crate attr_args;
 use attr_args::attr_with_args;
@@ -20,6 +20,6 @@
 #[attr_with_args(text = "Hello, world!")]
 fn foo() {}
 
-#[::attr_args::identity
-  fn main() { assert_eq!(foo(), "Hello, world!"); }]
+#[::attr_args::identity(
+  fn main() { assert_eq!(foo(), "Hello, world!"); })]
 struct Dummy;
index 52a8652e65bcf1158e556ba7dc8e28e5ae1f70b8..95e4f2211c63769f015b97f88ae45f7fdabb238a 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-on-trait.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc)]
 
 extern crate attr_on_trait;
 
index 98316c62ef135a0bf5dc4c8f4b429b5c230f0bc3..d928f8e557303747cc6f4322a9020acef65b54c4 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-stmt-expr.rs
 // ignore-stage1
 
-#![feature(proc_macro, stmt_expr_attributes)]
+#![feature(proc_macro, stmt_expr_attributes, proc_macro_stmt, proc_macro_expr)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr,
index 93815d16837d30fa40cda8ae9ee2f387ed41e44a..5f12cc96e9fb38ada53013ec5879df46516f7932 100644 (file)
@@ -20,7 +20,7 @@
 pub fn attr_with_args(args: TokenStream, input: TokenStream) -> TokenStream {
     let args = args.to_string();
 
-    assert_eq!(args, r#"( text = "Hello, world!" )"#);
+    assert_eq!(args, r#"text = "Hello, world!""#);
 
     let input = input.to_string();
 
index 063d8dc40536dc5a737ca96020bafc1d8af0e2a9..5376d2740452fb1ae053f21a5162340312c5dcfb 100644 (file)
@@ -10,7 +10,7 @@
 
 // no-prefer-dynamic
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro;
index 055e4e2fad7af52c84f2fc5850ea6fc6969a2b79..b8562ffc344de8f62af03653f0d67f78ad9ef43e 100644 (file)
@@ -10,7 +10,7 @@
 
 // no-prefer-dynamic
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro as proc_macro_renamed; // This does not break `quote!`
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-50061.rs
new file mode 100644 (file)
index 0000000..b3cd375
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+use proc_macro::TokenStream;
+
+#[proc_macro_attribute]
+pub fn check(_a: TokenStream, b: TokenStream) -> TokenStream {
+    b.into_iter().collect()
+}
index ffa4731f1e6371b0153a9929298a8aebc8cdab89..82337022ac3bf4ddf910e92f293b0a21e656b175 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:bang-macro.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate bang_macro;
 use bang_macro::rewrite;
index 00ad0e76ed014c10c2bf8bcf2f1bf9b538d2fcfe..3fbe5366b6a1b839b88656176ed19b9a85c3099f 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:count_compound_ops.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate count_compound_ops;
 use count_compound_ops::count_compound_ops;
index 995dc65729a5059f8719c88ee9b3f7380886cc02..d4176c0efbf104bad6b9424356db2b30152fb658 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:derive-b.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_path_invoc)]
 
 extern crate derive_b;
 
index 4cac7d19b4de8f2472d9fd78d4359bfbce414d61..48de15b934d23d679a2573bf0ca148c9760a87fe 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:hygiene_example.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate hygiene_example;
 use hygiene_example::hello;
index e53e94ae475b25f44dc378bfbf667da7315f9c99..a6b7d93c279d93db2037e3d7d18cca424a823dd2 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-42708.rs
 // ignore-stage1
 
-#![feature(decl_macro, proc_macro)]
+#![feature(decl_macro, proc_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 extern crate issue_42708;
diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs b/src/test/run-pass-fulldeps/proc-macro/issue-50061.rs
new file mode 100644 (file)
index 0000000..03f69c0
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+// aux-build:issue-50061.rs
+// ignore-stage1
+
+#![feature(proc_macro, proc_macro_path_invoc, decl_macro)]
+
+extern crate issue_50061;
+
+macro inner(any_token $v: tt) {
+    $v
+}
+
+macro outer($v: tt) {
+    inner!(any_token $v)
+}
+
+#[issue_50061::check]
+fn main() {
+    //! this doc comment forces roundtrip through a string
+    let checkit = 0;
+    outer!(checkit);
+}
index 418e692fa24ad18105ea64607509766c3e372f74..1cdf1daf560835af0b9775feaeee6a981421619c 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:negative-token.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate negative_token;
 
index cdda723585b7a850bb23de640358c26919ffb8b1..aad94c89f2ae3615c711bc632dd96272c497cb74 100644 (file)
@@ -12,7 +12,7 @@
 // ignore-stage1
 // ignore-cross-compile
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate proc_macro_def;
 
index d4fcdcf743bc676d6f20fa25a9acbea5fda8daed..12b115d09380e3f8a3dd1b0ffdb044dde8668d5d 100644 (file)
 
 #![feature(allocator_api, nonnull)]
 
-use std::alloc::{Alloc, Global};
+use std::alloc::{Alloc, Global, oom};
 
 fn main() {
     unsafe {
-        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| {
-            Global.oom()
-        });
+        let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| oom());
         *ptr.as_ptr() = 4;
         assert_eq!(*ptr.as_ptr(), 4);
         Global.dealloc_one(ptr);
diff --git a/src/test/run-pass/auxiliary/using-target-feature-unstable.rs b/src/test/run-pass/auxiliary/using-target-feature-unstable.rs
new file mode 100644 (file)
index 0000000..8b7d033
--- /dev/null
@@ -0,0 +1,15 @@
+// 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(mmx_target_feature)]
+
+#[inline]
+#[target_feature(enable = "mmx")]
+pub unsafe fn foo() {}
index a96f98b9efda96bed1c5d770d9e0f8c04a091345..723a98bcdfa0d85a894e7aea8d20739afdc0aff0 100644 (file)
@@ -14,6 +14,8 @@
 // These represent current behavior, but are pretty dubious.  I would
 // like to revisit these and potentially change them. --nmatsakis
 
+#![feature(never_type)]
+
 trait BadDefault {
     fn default() -> Self;
 }
index 87db440192984d3ea55709c771a8b0027c9eaf09..86cf9b5ec4783146db47f9b89b1fa0cf8cb15a18 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 #![feature(slice_patterns)]
 #![allow(unreachable_patterns)]
diff --git a/src/test/run-pass/format-hygiene.rs b/src/test/run-pass/format-hygiene.rs
new file mode 100644 (file)
index 0000000..6971f77
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+pub const arg0: u8 = 1;
+
+pub fn main() {
+    format!("{}", 1);
+}
index 3b6890cdce63bf1a1cec52841d502cbfb6453cbf..c4391ad05778a2a539445accf73a28cb53f07c57 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 macro m($S:ident, $x:ident) {
index 5e83f3808d8ccd9699eafa8da0b9f35f55ea248d..0cda0e7c7cce74cacac44747987a2a81a1c7e7fb 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 mod foo {
index 683a15b99aebea3116acb55803ee22c192ff0b8d..5395ef35882827b22c2c8a60c592f9e009f182f5 100644 (file)
@@ -12,7 +12,7 @@
 
 // aux-build:legacy_interaction.rs
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #[allow(unused)]
 
 extern crate legacy_interaction;
index cb02a17fec38a00298c6664ff864019f7f4d1308..73deda0777e50414984e7c89a5310409bba13d3d 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod bar {
     mod baz {
index 5520695021438a8d7f10ff24e7e840fc27bbe8ac..66e83eb7cacd57958205adde7a97365de0f98f39 100644 (file)
@@ -13,7 +13,7 @@
 // aux-build:my_crate.rs
 // aux-build:unhygienic_example.rs
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 extern crate unhygienic_example;
 extern crate my_crate; // (b)
index 6df3a34d3c87f0dd619081ca70db90d84ed63ead..95d7ae6db60ff165f7b91d9d4b95923a8f1281a9 100644 (file)
@@ -12,7 +12,7 @@
 
 // aux-build:xcrate.rs
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 extern crate xcrate;
 
index cf54e1c3bd598d6b4346c92dcc3a4c624b240412..794f5969bff507fbc04b2821e399522a5de85966 100644 (file)
@@ -10,6 +10,8 @@
 
 // Test that we can call static methods on ! both directly and when it appears in a generic
 
+#![feature(never_type)]
+
 trait StringifyType {
     fn stringify_type() -> &'static str;
 }
index a5a0a5a57944782c423033944f566f426ee28166..5cbd3446d9b6fe186bf6198b6f6d708cf7de94f0 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 #![feature(exhaustive_patterns)]
 
 // Regression test for inhabitedness check. The old
index ffdd99ebf6e5cf6688fea86109dd2c5d280866a6..39053769b24b59d9aff3ffb37128675726c760f0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
+
 #[allow(unused)]
 fn never_returns() {
     loop {
index dda7a46f325850fb1e863f5b59e86cf609d14fc8..9641ed282936fafcbb6f178728a2b0a64b58f2d3 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(fn_traits)]
+#![feature(never_type)]
 
 use std::panic;
 
index 8aa2a13ed8c8d810b6a3cdb6ca405de69513cea7..5c0af392f44df27c659d6cebedccf666c1c4dee7 100644 (file)
@@ -10,6 +10,8 @@
 
 // Test that we can extract a ! through pattern matching then use it as several different types.
 
+#![feature(never_type)]
+
 fn main() {
     let x: Result<u32, !> = Ok(123);
     match x {
index 69f8906778a1694875313023aaf40e2896aadb57..2e87809a84ec5a9c82d806fb7baaa19383aeba6a 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 extern crate two_macros;
 
index afa3494c3891941dfdb8ecde5b44b80fe9e53ae0..308792e5d8924782a13a8f812a9ce34465af4616 100644 (file)
@@ -15,7 +15,7 @@
 
 #![feature(heap_api, allocator_api)]
 
-use std::alloc::{Global, Alloc, Layout};
+use std::alloc::{Global, Alloc, Layout, oom};
 use std::ptr::{self, NonNull};
 
 fn main() {
@@ -50,7 +50,7 @@ unsafe fn allocate(layout: Layout) -> *mut u8 {
             println!("allocate({:?})", layout);
         }
 
-        let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| Global.oom());
+        let ret = Global.alloc(layout.clone()).unwrap_or_else(|_| oom());
 
         if PRINT {
             println!("allocate({:?}) = {:?}", layout, ret);
@@ -73,7 +73,7 @@ unsafe fn reallocate(ptr: *mut u8, old: Layout, new: Layout) -> *mut u8 {
         }
 
         let ret = Global.realloc(NonNull::new_unchecked(ptr).as_opaque(), old.clone(), new.size())
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
 
         if PRINT {
             println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
index 44be59f5c5b1a9ea39d3d4bedb21179021e05c4c..60a7f70931d48baf6bd17232fee5c4003d2f80aa 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(allocator_api)]
 
-use std::alloc::{Alloc, Global, Layout};
+use std::alloc::{Alloc, Global, Layout, oom};
 use std::ptr::NonNull;
 
 struct arena(());
@@ -33,7 +33,7 @@ struct Ccx {
 fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
     unsafe {
         let ptr = Global.alloc(Layout::new::<Bcx>())
-            .unwrap_or_else(|_| Global.oom());
+            .unwrap_or_else(|_| oom());
         &*(ptr.as_ptr() as *const _)
     }
 }
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs
deleted file mode 100644 (file)
index 11997eb..0000000
+++ /dev/null
@@ -1,43 +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.
-
-// compile-flags: --test
-
-#![feature(termination_trait_test)]
-#![feature(test)]
-
-extern crate test;
-use std::num::ParseIntError;
-use test::Bencher;
-
-#[test]
-fn is_a_num() -> Result<(), ParseIntError> {
-    let _: u32 = "22".parse()?;
-    Ok(())
-}
-
-#[test]
-#[should_panic]
-fn not_a_num() -> Result<(), ParseIntError> {
-    let _: u32 = "abc".parse()?;
-    Ok(())
-}
-
-#[bench]
-fn test_a_positive_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
-    Ok(())
-}
-
-#[bench]
-#[should_panic]
-fn test_a_neg_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
-    let _: u32 = "abc".parse()?;
-    Ok(())
-}
index 0bb18d8729a97d048bdce4fae8fba6cebb851f45..7bd9a1703ee9413710160c1b8529b64ddda505b9 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(never_type)]
 
 use std::mem::size_of;
 
diff --git a/src/test/run-pass/using-target-feature-unstable.rs b/src/test/run-pass/using-target-feature-unstable.rs
new file mode 100644 (file)
index 0000000..614c8d4
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+// only-x86_64
+// aux-build:using-target-feature-unstable.rs
+
+extern crate using_target_feature_unstable;
+
+fn main() {
+    unsafe {
+        using_target_feature_unstable::foo();
+    }
+}
diff --git a/src/test/rustdoc-js/alias-1.js b/src/test/rustdoc-js/alias-1.js
new file mode 100644 (file)
index 0000000..496bd55
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+const QUERY = '&';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'reference' },
+    ],
+};
diff --git a/src/test/rustdoc-js/alias-2.js b/src/test/rustdoc-js/alias-2.js
new file mode 100644 (file)
index 0000000..f31786d
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+const QUERY = '+';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::ops::AddAssign', 'name': 'AddAssign' },
+        { 'path': 'std::ops::Add', 'name': 'Add' },
+    ],
+};
diff --git a/src/test/rustdoc-js/alias-3.js b/src/test/rustdoc-js/alias-3.js
new file mode 100644 (file)
index 0000000..d9e1ca5
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+const QUERY = '!';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'never' },
+    ],
+};
diff --git a/src/test/rustdoc-js/alias.js b/src/test/rustdoc-js/alias.js
new file mode 100644 (file)
index 0000000..a0500f2
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+const QUERY = '[';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'slice' },
+        { 'path': 'std::ops::IndexMut', 'name': 'IndexMut' },
+        { 'path': 'std::ops::Index', 'name': 'Index' },
+    ],
+};
diff --git a/src/test/rustdoc-js/never.js b/src/test/rustdoc-js/never.js
new file mode 100644 (file)
index 0000000..d9e1ca5
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+const QUERY = '!';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std', 'name': 'never' },
+    ],
+};
index 50c31d309eec1fab7193039b0b27d610fd18630f..ee0a5c1aa1b5eb88e1ee810e56ffbf9f1f9d24cb 100644 (file)
@@ -14,7 +14,7 @@
 pub mod str {
     #![doc(primitive = "str")]
 
-    #[lang = "str"]
+    #[lang = "str_alloc"]
     impl str {
         // @has search-index.js foo
         pub fn foo(&self) {}
index 4c71afbac4df100a84f3ae0bea7ad28920ae4018..f938700e5157a282bf8950612845b07895a24981 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:parent-source-spans.rs
 // ignore-stage1
 
-#![feature(proc_macro, decl_macro)]
+#![feature(proc_macro, decl_macro, proc_macro_non_items)]
 
 extern crate parent_source_spans;
 
index ef2d160529068b76899f850a7d5083961adda5f3..66e34afcb13f92220644a8885f310021369ac1df 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:three-equals.rs
 // ignore-stage1
 
-#![feature(proc_macro)]
+#![feature(proc_macro, proc_macro_non_items)]
 
 extern crate three_equals;
 
index 052575de4c267944372854ee0be5b0d2943aa1d6..75b60aa8d10b7b392033577ec1c78cb197b1969f 100644 (file)
@@ -31,5 +31,5 @@ trait Add<RHS=Self> {
 fn ice<A>(a: A) {
     let r = loop {};
     r = r + a;
-    //~^ ERROR the trait bound `!: Add<A>` is not satisfied
+    //~^ ERROR the trait bound `(): Add<A>` is not satisfied
 }
index c22a645385adede474544b3b89c35359a6c50684..7924ab74444065190b82382e7bf4a606ea90853e 100644 (file)
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `!: Add<A>` is not satisfied
+error[E0277]: the trait bound `(): Add<A>` is not satisfied
   --> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:33:11
    |
 LL |     r = r + a;
-   |           ^ the trait `Add<A>` is not implemented for `!`
+   |           ^ the trait `Add<A>` is not implemented for `()`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs
new file mode 100644 (file)
index 0000000..fc20ad0
--- /dev/null
@@ -0,0 +1,24 @@
+// 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(rustc_attrs)]
+#![allow(dead_code)]
+
+trait Foo { }
+
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
+trait Bar where Self: Foo { }
+
+#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+fn bar<T: Bar>() {
+}
+
+fn main() {
+}
diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr
new file mode 100644 (file)
index 0000000..3a280f8
--- /dev/null
@@ -0,0 +1,24 @@
+error: program clause dump
+  --> $DIR/lower_env1.rs:16:1
+   |
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
+   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
+
+error: program clause dump
+  --> $DIR/lower_env1.rs:19:1
+   |
+LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
+   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
+   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
+   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+
+error: aborting due to 2 previous errors
+
index 671d77efbea3aac7f50850cdfef324cbdb481415..b38b87cdb1236133197e8b42f825d80e258ff70d 100644 (file)
@@ -12,7 +12,7 @@
 
 trait Foo { }
 
-#[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
 impl<T: 'static> Foo for T where T: Iterator<Item = i32> { }
 
 trait Bar {
@@ -20,7 +20,7 @@ trait Bar {
 }
 
 impl<T> Bar for T where T: Iterator<Item = i32> {
-    #[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :-
+    #[rustc_dump_program_clauses] //~ ERROR program clause dump
     type Assoc = Vec<T>;
 }
 
index f253f9847d16294bc9fe39e55bb6c68e9351ee51..c497d76f8d4f964e9bcaed31ca1808e1bc4cd194 100644 (file)
@@ -1,14 +1,18 @@
-error: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
+error: program clause dump
   --> $DIR/lower_impl.rs:15:1
    |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(T: Foo) :-
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
 
-error: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
+error: program clause dump
   --> $DIR/lower_impl.rs:23:5
    |
-LL |     #[rustc_dump_program_clauses] //~ ERROR Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :-
+LL |     #[rustc_dump_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
 
 error: aborting due to 2 previous errors
 
index 74feb0105ccf1ced50accc11a62f8a6c53180a92..7c0f233a645cb00efece3fbe5a2bca54be6e0559 100644 (file)
 
 #![feature(rustc_attrs)]
 
-#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
-                              //~| ERROR FromEnv
-                              //~| ERROR FromEnv
-                              //~| ERROR FromEnv
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
 trait Foo<S, T, U> {
     fn s(S) -> S;
     fn t(T) -> T;
index 45753c3bb90c2977a6b88e17e9fe1d1c43b8d3b2..55cd9699b06164de3fc62518a0c2c3666748d854 100644 (file)
@@ -1,26 +1,13 @@
-error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
+error: program clause dump
   --> $DIR/lower_trait.rs:13:1
    |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
-  --> $DIR/lower_trait.rs:13:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
-  --> $DIR/lower_trait.rs:13:1
    |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
-  --> $DIR/lower_trait.rs:13:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+   = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+   = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
+   = note: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
 
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
index e5eaf4591ece8685d4711f6fdc369374c070c5b6..47e9398d3647eefc2646210fdd7f4f7ff8df0195 100644 (file)
 
 #![feature(rustc_attrs)]
 
-#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
-                              //~| ERROR FromEnv
-                              //~| ERROR FromEnv
-                              //~| ERROR FromEnv
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
 trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
 {
     fn s(F) -> F;
index 9aed0c018c947b9d420352566c5f78541b9b6938..7f6f503c6ff7235fbae3a441abbae71d45f8c6fb 100644 (file)
@@ -1,26 +1,13 @@
-error: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
+error: program clause dump
   --> $DIR/lower_trait_higher_rank.rs:13:1
    |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
-  --> $DIR/lower_trait_higher_rank.rs:13:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
-  --> $DIR/lower_trait_higher_rank.rs:13:1
    |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
-  --> $DIR/lower_trait_higher_rank.rs:13:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
+   = note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
+   = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
+   = note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
 
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
index b2ce3ca48b27af60d20245db38317069576a1f14..67ee7c28b6a4e55941e28ccdd24eb521bd7cb986 100644 (file)
 use std::fmt::{Debug, Display};
 use std::borrow::Borrow;
 
-#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
-                              //~| ERROR FromEnv
-                              //~| ERROR FromEnv
-                              //~| ERROR FromEnv
-                              //~| ERROR FromEnv
-                              //~| ERROR RegionOutlives
-                              //~| ERROR TypeOutlives
+#[rustc_dump_program_clauses] //~ ERROR program clause dump
 trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b {
     fn s(S) -> S;
     fn t(T) -> T;
index a9ecaec3aff9ef2080b9a1ac60fcf2eb30da2d0e..68bc2ddf2930ebf3276b15d7393eba89f6f1fb3f 100644 (file)
@@ -1,44 +1,16 @@
-error: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+error: program clause dump
   --> $DIR/lower_trait_where_clause.rs:16:1
    |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-  --> $DIR/lower_trait_where_clause.rs:16:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-  --> $DIR/lower_trait_where_clause.rs:16:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-  --> $DIR/lower_trait_where_clause.rs:16:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-  --> $DIR/lower_trait_where_clause.rs:16:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-  --> $DIR/lower_trait_where_clause.rs:16:1
    |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-  --> $DIR/lower_trait_where_clause.rs:16:1
-   |
-LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 7 previous errors
+   = note: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+
+error: aborting due to previous error
 
index 324bcf60e8ff60d1c2c117b779712af6ce3db47d..dbddee862e022a87d3521e58ffec761291acf78b 100644 (file)
@@ -8,11 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-pass
+
 const X: u32 = 5;
 const Y: u32 = 6;
 const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
 //~^ WARN attempt to subtract with overflow
+//~| WARN this constant cannot be used
 
 fn main() {
-    println!("{}", FOO); //~ E0080
+    println!("{}", FOO);
+    //~^ WARN constant evaluation error
 }
index 9270dafbe651a4cd6d72220a42cd43cfacf5a841..713b1b36c08b1b0c55f807d0eee174608f2e45a4 100644 (file)
@@ -1,17 +1,20 @@
 warning: attempt to subtract with overflow
-  --> $DIR/conditional_array_execution.rs:13:19
+  --> $DIR/conditional_array_execution.rs:15:19
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ^^^^^
    |
    = note: #[warn(const_err)] on by default
 
-error[E0080]: constant evaluation error
-  --> $DIR/conditional_array_execution.rs:17:20
+warning: this constant cannot be used
+  --> $DIR/conditional_array_execution.rs:15:1
    |
-LL |     println!("{}", FOO); //~ E0080
-   |                    ^^^ referenced constant has errors
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
 
-error: aborting due to previous error
+warning: constant evaluation error
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
 
-For more information about this error, try `rustc --explain E0080`.
index d5c4796d0b497f86d8f98b545291b0e94e2cc2a4..097fba4d3c45094b98152e68372b8878b789539e 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-pass
+
 #![feature(const_fn)]
 
 const fn foo(x: u32) -> u32 {
@@ -17,9 +19,11 @@ const fn foo(x: u32) -> u32 {
 fn main() {
     const X: u32 = 0-1;
     //~^ WARN attempt to subtract with overflow
+    //~| WARN this constant cannot be used
     const Y: u32 = foo(0-1);
     //~^ WARN attempt to subtract with overflow
+    //~| WARN this constant cannot be used
     println!("{} {}", X, Y);
-    //~^ ERROR constant evaluation error
-    //~| ERROR constant evaluation error
+    //~^ WARN constant evaluation error
+    //~| WARN constant evaluation error
 }
index 2d51e6603b59bc335caf86bced103ed26ef44e3c..a22e8016296c4f95a3b2fe53907d52bd39a71db4 100644 (file)
@@ -1,29 +1,38 @@
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:18:20
+  --> $DIR/issue-43197.rs:20:20
    |
 LL |     const X: u32 = 0-1;
    |                    ^^^
    |
    = note: #[warn(const_err)] on by default
 
-error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:22:23
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:20:5
    |
-LL |     println!("{} {}", X, Y);
-   |                       ^ referenced constant has errors
+LL |     const X: u32 = 0-1;
+   |     ^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:20:24
+  --> $DIR/issue-43197.rs:23:24
    |
 LL |     const Y: u32 = foo(0-1);
    |                        ^^^
 
-error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:22:26
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:23:5
+   |
+LL |     const Y: u32 = foo(0-1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+warning: constant evaluation error
+  --> $DIR/issue-43197.rs:26:23
    |
 LL |     println!("{} {}", X, Y);
-   |                          ^ referenced constant has errors
+   |                       ^ referenced constant has errors
 
-error: aborting due to 2 previous errors
+warning: constant evaluation error
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-44578.rs b/src/test/ui/const-eval/issue-44578.rs
new file mode 100644 (file)
index 0000000..765113c
--- /dev/null
@@ -0,0 +1,37 @@
+// 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.
+
+// compile-pass
+
+trait Foo {
+    const AMT: usize;
+}
+
+enum Bar<A, B> {
+    First(A),
+    Second(B),
+}
+
+impl<A: Foo, B: Foo> Foo for Bar<A, B> {
+    const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+}
+
+impl Foo for u8 {
+    const AMT: usize = 1;
+}
+
+impl Foo for u16 {
+    const AMT: usize = 2;
+}
+
+fn main() {
+    println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+    //~^ WARN const_err
+}
diff --git a/src/test/ui/const-eval/issue-44578.stderr b/src/test/ui/const-eval/issue-44578.stderr
new file mode 100644 (file)
index 0000000..01c6fa3
--- /dev/null
@@ -0,0 +1,14 @@
+warning: constant evaluation error
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: #[warn(const_err)] on by default
+
+warning: constant evaluation error
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
diff --git a/src/test/ui/const-eval/promoted_errors.rs b/src/test/ui/const-eval/promoted_errors.rs
new file mode 100644 (file)
index 0000000..dc30c7f
--- /dev/null
@@ -0,0 +1,28 @@
+// 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: -O
+fn main() {
+    println!("{}", 0u32 - 1);
+    //~^ WARN const_err
+    //~| WARN const_err
+    let _x = 0u32 - 1;
+    //~^ WARN const_err
+    println!("{}", 1/(1-1));
+    //~^ WARN const_err
+    //~| WARN const_err
+    let _x = 1/(1-1);
+    //~^ WARN const_err
+    //~| WARN const_err
+    println!("{}", 1/(false as u32));
+    //~^ WARN const_err
+    let _x = 1/(false as u32);
+}
diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr
new file mode 100644 (file)
index 0000000..a5db8cc
--- /dev/null
@@ -0,0 +1,50 @@
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:14:20
+   |
+LL |     println!("{}", 0u32 - 1);
+   |                    ^^^^^^^^ attempted to do overflowing math
+   |
+   = note: #[warn(const_err)] on by default
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:14:20
+   |
+LL |     println!("{}", 0u32 - 1);
+   |                    ^^^^^^^^ attempted to do overflowing math
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:17:14
+   |
+LL |     let _x = 0u32 - 1;
+   |              ^^^^^^^^ attempted to do overflowing math
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:19:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:19:20
+   |
+LL |     println!("{}", 1/(1-1));
+   |                    ^^^^^^^ attempted to do overflowing math
+
+warning: attempt to divide by zero
+  --> $DIR/promoted_errors.rs:22:14
+   |
+LL |     let _x = 1/(1-1);
+   |              ^^^^^^^
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:22:14
+   |
+LL |     let _x = 1/(1-1);
+   |              ^^^^^^^ attempted to do overflowing math
+
+warning: constant evaluation error
+  --> $DIR/promoted_errors.rs:25:20
+   |
+LL |     println!("{}", 1/(false as u32));
+   |                    ^^^^^^^^^^^^^^^^ attempted to do overflowing math
+
index bdb9f5b19a88541088a6cbcce2be7827e721fc24..c6bf07649af38a17dd33964436037a59b06d0493 100644 (file)
@@ -8,9 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(const_err)]
+// compile-pass
 
 #![crate_type = "lib"]
 
 pub const Z: u32 = 0 - 1;
-//~^ ERROR attempt to subtract with overflow
+//~^ WARN attempt to subtract with overflow
+//~| WARN this constant cannot be used
+
+pub type Foo = [i32; 0 - 1];
+//~^ WARN attempt to subtract with overflow
+//~| WARN this array length cannot be used
index b77ec38ca1679869a692892c8d8ed94bf3d795f9..2981ac20cd981d639a426fd082a0486e2e4ff147 100644 (file)
@@ -1,14 +1,26 @@
-error: attempt to subtract with overflow
+warning: attempt to subtract with overflow
   --> $DIR/pub_const_err.rs:15:20
    |
 LL | pub const Z: u32 = 0 - 1;
    |                    ^^^^^
    |
-note: lint level defined here
-  --> $DIR/pub_const_err.rs:11:9
+   = note: #[warn(const_err)] on by default
+
+warning: this constant cannot be used
+  --> $DIR/pub_const_err.rs:15:1
    |
-LL | #![deny(const_err)]
-   |         ^^^^^^^^^
+LL | pub const Z: u32 = 0 - 1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
 
-error: aborting due to previous error
+warning: attempt to subtract with overflow
+  --> $DIR/pub_const_err.rs:19:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^
+
+warning: this array length cannot be used
+  --> $DIR/pub_const_err.rs:19:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^ attempt to subtract with overflow
 
diff --git a/src/test/ui/const-eval/pub_const_err_bin.rs b/src/test/ui/const-eval/pub_const_err_bin.rs
new file mode 100644 (file)
index 0000000..d87cb7e
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// compile-pass
+
+pub const Z: u32 = 0 - 1;
+//~^ WARN attempt to subtract with overflow
+//~| WARN this constant cannot be used
+
+pub type Foo = [i32; 0 - 1];
+//~^ WARN attempt to subtract with overflow
+//~| WARN this array length cannot be used
+
+fn main() {}
diff --git a/src/test/ui/const-eval/pub_const_err_bin.stderr b/src/test/ui/const-eval/pub_const_err_bin.stderr
new file mode 100644 (file)
index 0000000..3e8966d
--- /dev/null
@@ -0,0 +1,26 @@
+warning: attempt to subtract with overflow
+  --> $DIR/pub_const_err_bin.rs:13:20
+   |
+LL | pub const Z: u32 = 0 - 1;
+   |                    ^^^^^
+   |
+   = note: #[warn(const_err)] on by default
+
+warning: this constant cannot be used
+  --> $DIR/pub_const_err_bin.rs:13:1
+   |
+LL | pub const Z: u32 = 0 - 1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+
+warning: attempt to subtract with overflow
+  --> $DIR/pub_const_err_bin.rs:17:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^
+
+warning: this array length cannot be used
+  --> $DIR/pub_const_err_bin.rs:17:22
+   |
+LL | pub type Foo = [i32; 0 - 1];
+   |                      ^^^^^ attempt to subtract with overflow
+
index a9f747d09ec2dd7b4cb15ae8a184ccda312b383d..ed9033ad53d565f0314f1d714004c60226a7da02 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(try_from)]
+
 use std::marker::PhantomData;
 use std::convert::{TryFrom, AsRef};
 
index 417ff1de3f8173ff958459981f405225f673dafa..e8b2c84c0df0bbd11f7db7a7da0e8365168ce2ff 100644 (file)
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `std::convert::AsRef<Q>` for type `std::boxed::Box<Q>`:
-  --> $DIR/conflict-with-std.rs:15:1
+  --> $DIR/conflict-with-std.rs:17:1
    |
 LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | impl AsRef<Q> for Box<Q> { //~ ERROR conflicting implementations
              where T: ?Sized;
 
 error[E0119]: conflicting implementations of trait `std::convert::From<S>` for type `S`:
-  --> $DIR/conflict-with-std.rs:22:1
+  --> $DIR/conflict-with-std.rs:24:1
    |
 LL | impl From<S> for S { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | impl From<S> for S { //~ ERROR conflicting implementations
            - impl<T> std::convert::From<T> for T;
 
 error[E0119]: conflicting implementations of trait `std::convert::TryFrom<X>` for type `X`:
-  --> $DIR/conflict-with-std.rs:29:1
+  --> $DIR/conflict-with-std.rs:31:1
    |
 LL | impl TryFrom<X> for X { //~ ERROR conflicting implementations
    | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/edition-lint-paths.rs b/src/test/ui/edition-lint-paths.rs
new file mode 100644 (file)
index 0000000..0b49e72
--- /dev/null
@@ -0,0 +1,41 @@
+// 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(crate_in_paths)]
+#![deny(absolute_path_starting_with_module)]
+#![allow(unused)]
+
+pub mod foo {
+    use ::bar::Bar;
+    //~^ ERROR Absolute
+    //~| WARN this was previously accepted
+    use super::bar::Bar2;
+    use crate::bar::Bar3;
+}
+
+
+use bar::Bar;
+//~^ ERROR Absolute
+//~| WARN this was previously accepted
+
+pub mod bar {
+    pub struct Bar;
+    pub type Bar2 = Bar;
+    pub type Bar3 = Bar;
+}
+
+fn main() {
+    let x = ::bar::Bar;
+    //~^ ERROR Absolute
+    //~| WARN this was previously accepted
+    let x = bar::Bar;
+    let x = ::crate::bar::Bar;
+    let x = self::bar::Bar;
+}
diff --git a/src/test/ui/edition-lint-paths.stderr b/src/test/ui/edition-lint-paths.stderr
new file mode 100644 (file)
index 0000000..509527e
--- /dev/null
@@ -0,0 +1,34 @@
+error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:16:9
+   |
+LL |     use ::bar::Bar;
+   |         ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+note: lint level defined here
+  --> $DIR/edition-lint-paths.rs:12:9
+   |
+LL | #![deny(absolute_path_starting_with_module)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:24:5
+   |
+LL | use bar::Bar;
+   |     ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+error: Absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-paths.rs:35:13
+   |
+LL |     let x = ::bar::Bar;
+   |             ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue TBD
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/feature-gate-doc_alias.rs b/src/test/ui/feature-gate-doc_alias.rs
new file mode 100644 (file)
index 0000000..1503dfe
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+#[doc(alias = "foo")] //~ ERROR: #[doc(alias = "...")] is experimental
+pub struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-doc_alias.stderr b/src/test/ui/feature-gate-doc_alias.stderr
new file mode 100644 (file)
index 0000000..a987e03
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(alias = "...")] is experimental (see issue #50146)
+  --> $DIR/feature-gate-doc_alias.rs:11:1
+   |
+LL | #[doc(alias = "foo")] //~ ERROR: #[doc(alias = "...")] is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_alias)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index 477dd1b38eb0d7c6e4ca29150935d32f44a4da77..c83d9b56bc39f029a36ab189d9b53c4ae0fce9af 100644 (file)
@@ -7,7 +7,7 @@
 // <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(never_type)]
 fn foo() -> Result<u32, !> {
     Ok(123)
 }
index 724ec2496f24cdc6a342f903b786e68caa392969..347066268664324aebffcbf3f6c254a96fa60e15 100644 (file)
@@ -15,6 +15,7 @@ trait PointerFamily<U> {
     //~^ ERROR generic associated types are unstable
     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
     //~^ ERROR generic associated types are unstable
+    //~| ERROR where clauses on associated types are unstable
 }
 
 struct Foo;
@@ -25,4 +26,10 @@ impl PointerFamily<u32> for Foo {
     //~^ ERROR generic associated types are unstable
 }
 
+trait Bar {
+    type Assoc where Self: Sized;
+    //~^ ERROR where clauses on associated types are unstable
+}
+
+
 fn main() {}
index 5f23def88eb0633f6b4505e9f75ebd012883b125..d7891f13c6b4d9f6f283ecdb16ea2cc69e725502 100644 (file)
@@ -14,8 +14,16 @@ LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:16:5
+   |
+LL |     type Pointer2<T>: Deref<Target = T> where T: Clone, U: Clone;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
 error[E0658]: generic associated types are unstable (see issue #44265)
-  --> $DIR/feature-gate-generic_associated_types.rs:22:5
+  --> $DIR/feature-gate-generic_associated_types.rs:23:5
    |
 LL |     type Pointer<usize> = Box<usize>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,13 +31,21 @@ LL |     type Pointer<usize> = Box<usize>;
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
 error[E0658]: generic associated types are unstable (see issue #44265)
-  --> $DIR/feature-gate-generic_associated_types.rs:24:5
+  --> $DIR/feature-gate-generic_associated_types.rs:25:5
    |
 LL |     type Pointer2<u32> = Box<u32>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(generic_associated_types)] to the crate attributes to enable
 
-error: aborting due to 4 previous errors
+error[E0658]: where clauses on associated types are unstable (see issue #44265)
+  --> $DIR/feature-gate-generic_associated_types.rs:30:5
+   |
+LL |     type Assoc where Self: Sized;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(generic_associated_types)] to the crate attributes to enable
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate-never_type.rs b/src/test/ui/feature-gate-never_type.rs
new file mode 100644 (file)
index 0000000..ebbe17a
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2012 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.
+
+// Test that ! errors when used in illegal positions with feature(never_type) disabled
+
+trait Foo {
+    type Wub;
+}
+
+type Ma = (u32, !, i32); //~ ERROR type is experimental
+type Meeshka = Vec<!>; //~ ERROR type is experimental
+type Mow = &fn(!) -> !; //~ ERROR type is experimental
+type Skwoz = &mut !; //~ ERROR type is experimental
+
+impl Foo for Meeshka {
+    type Wub = !; //~ ERROR type is experimental
+}
+
+fn main() {
+}
diff --git a/src/test/ui/feature-gate-never_type.stderr b/src/test/ui/feature-gate-never_type.stderr
new file mode 100644 (file)
index 0000000..187be6d
--- /dev/null
@@ -0,0 +1,43 @@
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:17:17
+   |
+LL | type Ma = (u32, !, i32); //~ ERROR type is experimental
+   |                 ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:18:20
+   |
+LL | type Meeshka = Vec<!>; //~ ERROR type is experimental
+   |                    ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:19:16
+   |
+LL | type Mow = &fn(!) -> !; //~ ERROR type is experimental
+   |                ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:20:19
+   |
+LL | type Skwoz = &mut !; //~ ERROR type is experimental
+   |                   ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error[E0658]: The `!` type is experimental (see issue #35121)
+  --> $DIR/feature-gate-never_type.rs:23:16
+   |
+LL |     type Wub = !; //~ ERROR type is experimental
+   |                ^
+   |
+   = help: add #![feature(never_type)] to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.rs b/src/test/ui/feature-gate/issue-49983-see-issue-0.rs
new file mode 100644 (file)
index 0000000..1e0039a
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+extern crate core;
+
+// error should not say "(see issue #0)"
+#[allow(unused_imports)] use core::ptr::Unique; //~ ERROR use of unstable library feature
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr b/src/test/ui/feature-gate/issue-49983-see-issue-0.stderr
new file mode 100644 (file)
index 0000000..986a2d8
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'ptr_internals': use NonNull instead and consider PhantomData<T> (if you also use #[may_dangle]), Send, and/or Sync
+  --> $DIR/issue-49983-see-issue-0.rs:14:30
+   |
+LL | #[allow(unused_imports)] use core::ptr::Unique; //~ ERROR use of unstable library feature
+   |                              ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(ptr_internals)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index 64217770b13c9ad278b1381f4697ba86dde7e3ec..ed155b28037a03e5a1558bc5d024e03f6e91b3ee 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     struct S { x: u32 }
index 7ba217061c66ee986911556a844bc7a0a52b94a0..f3f400aafeb2bfae7fd950555a83fd21e8866a12 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     pub fn f() {}
index cdba559445d195be1a4636a496ed0b57fa8467b0..4f997a790e688b058701cc918b90fb8f9895d77b 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     struct S;
index 50fc985ba34faea982f93aa51efb5f468af4f073..20ca918f026f362e19ea70ff24eb3f96293624f0 100644 (file)
@@ -14,7 +14,7 @@
 
 // error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 extern crate intercrate;
 
index c90c7b3093c9f0e5d04a15371b082d4cf05dbf38..ea6a45fba6ac7edb59a15c418b0a99aa24eba513 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     pub macro m() { Vec::new(); ().clone() }
index 987cad187d428c7dcf719df625bc4ec736a3f755..8a392db92f96062f802c74c1edb063f39035803b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     fn f() {}
index 3bd19cbc0ac67cbf48b4138d0118a906bc799d05..d0da6254b9bd01e26162241e4b12c35267c3b65e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(decl_macro)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 
 mod foo {
     pub trait T {
index 438d29f0535363fe1437dee28d4754a3ef62947c..f7aaab4242c0fab7bb6faf104d08cdd58f387df1 100644 (file)
@@ -8,10 +8,8 @@ LL |     foo(|s| s.is_empty());
    |               ^^^^^^^^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the following traits define an item `is_empty`, perhaps you need to implement one of them:
+   = note: the following trait defines an item `is_empty`, perhaps you need to implement it:
            candidate #1: `std::iter::ExactSizeIterator`
-           candidate #2: `core::slice::SliceExt`
-           candidate #3: `core::str::StrExt`
 
 error: aborting due to previous error
 
index e709eeee14a8452e4852ae322a16d7f380210bc0..51e5257be1bc22e65a6cf2b81100e85332cd1ffd 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 extern crate two_macros;
 
index 93de136c4051d6875345c8e420cd38e9048961d7..aad0a43be2696cac6fdae453ba5ccc71c433f761 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:two_macros.rs
 
-#![feature(use_extern_macros)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
 mod foo {
     extern crate two_macros;
diff --git a/src/test/ui/issue-48636.rs b/src/test/ui/issue-48636.rs
new file mode 100644 (file)
index 0000000..03e45d8
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+struct S {
+    x: u8
+    /// The id of the parent core
+    y: u8,
+}
+//~^^^ ERROR found a documentation comment that doesn't document anything
+fn main() {}
diff --git a/src/test/ui/issue-48636.stderr b/src/test/ui/issue-48636.stderr
new file mode 100644 (file)
index 0000000..4e014a5
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0585]: found a documentation comment that doesn't document anything
+  --> $DIR/issue-48636.rs:13:5
+   |
+LL |     x: u8
+   |          - help: missing comma here: `,`
+LL |     /// The id of the parent core
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0585`.
index bff64ad489210a0f1fd33f55194da91921c86624..090ff817eb0f2cf89321767645756f61836cd6ab 100644 (file)
@@ -48,13 +48,13 @@ macro_rules! fake_anon_field_expr {
 
 macro_rules! real_method_stmt {
      () => {
-          2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+          2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
      }
 }
 
 macro_rules! real_method_expr {
      () => {
-          2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+          2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
      }
 }
 
index cb7d422b7f3ed73d3d82339b572cd4fc9dd2cc20..284960d2f6e154135b7fa33dcd5cce1b5a221b5c 100644 (file)
@@ -25,17 +25,17 @@ LL |           (1).0 //~ ERROR doesn't have fields
 LL |     fake_anon_field_stmt!();
    |     ------------------------ in this macro invocation
 
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/macro-backtrace-invalid-internals.rs:51:15
    |
-LL |           2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
-   |               ^^^^
+LL |           2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+   |               ^^^^^
 ...
 LL |     real_method_stmt!();
    |     -------------------- in this macro invocation
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |           2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+LL |           2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
    |           ^^^^^^^
 
 error[E0599]: no method named `fake` found for type `{integer}` in the current scope
@@ -65,17 +65,17 @@ LL |           (1).0 //~ ERROR doesn't have fields
 LL |     let _ = fake_anon_field_expr!();
    |             ----------------------- in this macro invocation
 
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/macro-backtrace-invalid-internals.rs:57:15
    |
-LL |           2.0.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
-   |               ^^^^
+LL |           2.0.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
+   |               ^^^^^
 ...
 LL |     let _ = real_method_expr!();
    |             ------------------- in this macro invocation
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |           2.0_f32.powi(2) //~ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+LL |           2.0_f32.recip() //~ ERROR can't call method `recip` on ambiguous numeric type `{float}`
    |           ^^^^^^^
 
 error: aborting due to 8 previous errors
index 1908ef244cfeaec83dfab2ff8269620c995e8b6c..9ae86136a909170585b9513f41fd35d144858bc0 100644 (file)
@@ -11,6 +11,7 @@
 // compile-flags: -Z print-type-sizes
 // compile-pass
 
+#![feature(never_type)]
 #![feature(start)]
 
 #[start]
index 3e39b75d8c0f33010564f2699e87a188c5bbbba1..26760cfea4478cc1f39abde71abae7d9a1fa6416 100644 (file)
@@ -7,7 +7,7 @@
 // <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(never_type)]
 #![allow(unused_variables)]
 #![deny(unreachable_code)]
 
index 73083af34d97d3ddab8f162a42667273ab050a75..308f2483be50a95b6bc3fc90b53094e85885adff 100644 (file)
@@ -7,7 +7,7 @@
 // <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(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
index 2772dd429d184275d4b97c65892f4d4f4083ce56..9696bdadf87e803cddf70b12033f879f1c061f10 100644 (file)
@@ -7,7 +7,7 @@
 // <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(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
index 88846b638416a5a9da4ea22622003f4fb6365413..fc0041daf7c7c8635a4f433ba4f19b1dcc21c33b 100644 (file)
@@ -12,7 +12,7 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(type_ascription)]
+#![feature(never_type, type_ascription)]
 
 fn a() {
     // the cast is unreachable:
index 7dabb307097622859232eef056fb7d510dcb61ce..c91646cfa1ef119b17fa061f384897268cae6344 100644 (file)
@@ -7,7 +7,7 @@
 // <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(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
index 2381ea2ac7a1b0b727cb2f99e57251e8242e4f5d..ce12412ba7438a6595a64733100a5b6e8be8b0e5 100644 (file)
@@ -12,7 +12,7 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
-#![feature(type_ascription)]
+#![feature(never_type, type_ascription)]
 
 fn a() {
     // the cast is unreachable:
index 4096865f4c6705fb4f0f06552de80f3b3961bde2..5b7ea57b1661a01f21efe9af5ae8781fcf771a30 100644 (file)
@@ -7,7 +7,7 @@
 // <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(never_type)]
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #![allow(dead_code)]
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs
new file mode 100644 (file)
index 0000000..73a0150
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+// compile-flags: --test
+
+#![feature(termination_trait_test)]
+#![feature(test)]
+
+extern crate test;
+use std::num::ParseIntError;
+use test::Bencher;
+
+#[test]
+#[should_panic]
+fn not_a_num() -> Result<(), ParseIntError> {
+    //~^ ERROR functions using `#[should_panic]` must return `()`
+    let _: u32 = "abc".parse()?;
+    Ok(())
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr
new file mode 100644 (file)
index 0000000..e3dab82
--- /dev/null
@@ -0,0 +1,12 @@
+error: functions using `#[should_panic]` must return `()`
+  --> $DIR/termination-trait-in-test-should-panic.rs:22:1
+   |
+LL | / fn not_a_num() -> Result<(), ParseIntError> {
+LL | |     //~^ ERROR functions using `#[should_panic]` must return `()`
+LL | |     let _: u32 = "abc".parse()?;
+LL | |     Ok(())
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
new file mode 100644 (file)
index 0000000..2cb4552
--- /dev/null
@@ -0,0 +1,37 @@
+// 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.
+
+// compile-flags: --test
+// run-pass
+
+#![feature(termination_trait_test)]
+#![feature(test)]
+
+extern crate test;
+use std::num::ParseIntError;
+use test::Bencher;
+
+#[test]
+fn is_a_num() -> Result<(), ParseIntError> {
+    let _: u32 = "22".parse()?;
+    Ok(())
+}
+
+#[bench]
+fn test_a_positive_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+    Ok(())
+}
+
+#[bench]
+#[should_panic]
+fn test_a_neg_bench(_: &mut Bencher) -> Result<(), ParseIntError> {
+    let _: u32 = "abc".parse()?;
+    Ok(())
+}
index fa5bafab8717e82bb018d1fc718cda78ea01e051..2e452f9671f380fd21b3b9e073359a80579c1ba4 100644 (file)
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 fn main() {
-    let x = 2.0.powi(2);
-    //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+    let x = 2.0.recip();
+    //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
     let y = 2.0;
-    let x = y.powi(2);
-    //~^ ERROR can't call method `powi` on ambiguous numeric type `{float}`
+    let x = y.recip();
+    //~^ ERROR can't call method `recip` on ambiguous numeric type `{float}`
     println!("{:?}", x);
 }
index 92ad22806156719623d06222281e96a279bbebfb..477b4c3821d51bc2f9aa5cc982a677a3919d59ee 100644 (file)
@@ -1,18 +1,18 @@
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/method-on-ambiguous-numeric-type.rs:12:17
    |
-LL |     let x = 2.0.powi(2);
-   |                 ^^^^
+LL |     let x = 2.0.recip();
+   |                 ^^^^^
 help: you must specify a concrete type for this numeric value, like `f32`
    |
-LL |     let x = 2.0_f32.powi(2);
+LL |     let x = 2.0_f32.recip();
    |             ^^^^^^^
 
-error[E0689]: can't call method `powi` on ambiguous numeric type `{float}`
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
   --> $DIR/method-on-ambiguous-numeric-type.rs:15:15
    |
-LL |     let x = y.powi(2);
-   |               ^^^^
+LL |     let x = y.recip();
+   |               ^^^^^
 help: you must specify a type for this binding, like `f32`
    |
 LL |     let y: f32 = 2.0;
index cfe9a43707cf614cd7318e004ce30e94d3b5633c..4fc11daaa3afa0de5758d8c046f433467e571299 100755 (executable)
@@ -31,24 +31,17 @@ MYDIR=$(dirname $0)
 BUILD_DIR="$1"
 shift
 
+shopt -s nullglob
+
 while [[ "$1" != "" ]]; do
-    STDERR_NAME="${1/%.rs/.stderr}"
-    STDERR_NLL_NAME="${1/%.rs/.nll.stderr}"
-    STDOUT_NAME="${1/%.rs/.stdout}"
+    for EXT in "stderr" "stdout"; do
+        for OUT_NAME in $BUILD_DIR/${1%.rs}.*$EXT; do
+            OUT_BASE=`basename "$OUT_NAME"`
+            if ! (diff $OUT_NAME $MYDIR/$OUT_BASE >& /dev/null); then
+                echo updating $MYDIR/$OUT_BASE
+                cp $OUT_NAME $MYDIR
+            fi
+        done
+    done
     shift
-    if [ -f $BUILD_DIR/$STDOUT_NAME ] && \
-           ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then
-        echo updating $MYDIR/$STDOUT_NAME
-        cp $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME
-    fi
-    if [ -f $BUILD_DIR/$STDERR_NAME ] && \
-           ! (diff $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME >& /dev/null); then
-        echo updating $MYDIR/$STDERR_NAME
-        cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME
-    fi
-    if [ -f $BUILD_DIR/$STDERR_NLL_NAME ] && \
-           ! (diff $BUILD_DIR/$STDERR_NLL_NAME $MYDIR/$STDERR_NLL_NAME >& /dev/null); then
-        echo updating $MYDIR/$STDERR_NLL_NAME
-        cp $BUILD_DIR/$STDERR_NLL_NAME $MYDIR/$STDERR_NLL_NAME
-    fi
 done
index 5ac4ab14f53fe8210befca9c9178a93f7df70a41..0a1add2d8689ad12a86f6c32d0a5cd0393dc5d80 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5ac4ab14f53fe8210befca9c9178a93f7df70a41
+Subproject commit 0a1add2d8689ad12a86f6c32d0a5cd0393dc5d80
index 0f4d247633a61b46016c27b0b8b860475d3aa19b..aabf2e6f8f0e675c2e918e7491c1cd59546c75d0 100644 (file)
@@ -26,7 +26,7 @@
 use std::collections::HashMap;
 use std::collections::HashSet;
 use std::env;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fs::{self, create_dir_all, File};
 use std::fmt;
 use std::io::prelude::*;
@@ -72,6 +72,26 @@ fn new(line_number: u32) -> Mismatch {
     }
 }
 
+trait PathBufExt {
+    /// Append an extension to the path, even if it already has one.
+    fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf;
+}
+
+impl PathBufExt for PathBuf {
+    fn with_extra_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
+        if extension.as_ref().len() == 0 {
+            self.clone()
+        } else {
+            let mut fname = self.file_name().unwrap().to_os_string();
+            if !extension.as_ref().to_str().unwrap().starts_with(".") {
+                fname.push(".");
+            }
+            fname.push(extension);
+            self.with_file_name(fname)
+        }
+    }
+}
+
 // Produces a diff between the expected output and actual output.
 pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
     let mut line_number = 1;
@@ -1725,20 +1745,14 @@ fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
     }
 
     fn make_exe_name(&self) -> PathBuf {
-        let mut f = self.output_base_name();
+        let mut f = self.output_base_name_stage();
         // FIXME: This is using the host architecture exe suffix, not target!
         if self.config.target.contains("emscripten") {
-            let mut fname = f.file_name().unwrap().to_os_string();
-            fname.push(".js");
-            f.set_file_name(&fname);
+            f = f.with_extra_extension("js");
         } else if self.config.target.contains("wasm32") {
-            let mut fname = f.file_name().unwrap().to_os_string();
-            fname.push(".wasm");
-            f.set_file_name(&fname);
+            f = f.with_extra_extension("wasm");
         } else if !env::consts::EXE_SUFFIX.is_empty() {
-            let mut fname = f.file_name().unwrap().to_os_string();
-            fname.push(env::consts::EXE_SUFFIX);
-            f.set_file_name(&fname);
+            f = f.with_extra_extension(env::consts::EXE_SUFFIX);
         }
         f
     }
@@ -1846,25 +1860,28 @@ fn make_out_name(&self, extension: &str) -> PathBuf {
     }
 
     fn aux_output_dir_name(&self) -> PathBuf {
-        let f = self.output_base_name();
-        let mut fname = f.file_name().unwrap().to_os_string();
-        fname.push(&format!("{}.aux", self.config.mode.disambiguator()));
-        f.with_file_name(&fname)
+        self.output_base_name_stage()
+            .with_extra_extension(self.config.mode.disambiguator())
+            .with_extra_extension(".aux")
     }
 
     fn output_testname(&self, filepath: &Path) -> PathBuf {
         PathBuf::from(filepath.file_stem().unwrap())
     }
 
-    /// Given a test path like `compile-fail/foo/bar.rs` Returns a name like
-    ///
-    ///     <output>/foo/bar-stage1
+    /// Given a test path like `compile-fail/foo/bar.rs` returns a name like
+    /// `/path/to/build/<triple>/test/compile-fail/foo/bar`.
     fn output_base_name(&self) -> PathBuf {
         let dir = self.config.build_base.join(&self.testpaths.relative_dir);
 
         // Note: The directory `dir` is created during `collect_tests_from_dir`
         dir.join(&self.output_testname(&self.testpaths.file))
-            .with_extension(&self.config.stage_id)
+    }
+
+    /// Same as `output_base_name`, but includes the stage ID as an extension,
+    /// such as: `.../compile-fail/foo/bar.stage1-<triple>`
+    fn output_base_name_stage(&self) -> PathBuf {
+        self.output_base_name().with_extension(&self.config.stage_id)
     }
 
     fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
@@ -1989,7 +2006,7 @@ fn charset() -> &'static str {
     fn run_rustdoc_test(&self) {
         assert!(self.revision.is_none(), "revisions not relevant here");
 
-        let out_dir = self.output_base_name();
+        let out_dir = self.output_base_name_stage();
         let _ = fs::remove_dir_all(&out_dir);
         create_dir_all(&out_dir).unwrap();
 
@@ -2391,7 +2408,7 @@ fn run_rmake_test(&self) {
             .unwrap();
         let src_root = cwd.join(&src_root);
 
-        let tmpdir = cwd.join(self.output_base_name());
+        let tmpdir = cwd.join(self.output_base_name_stage());
         if tmpdir.exists() {
             self.aggressive_rm_rf(&tmpdir).unwrap();
         }
@@ -2816,7 +2833,6 @@ fn expected_output_path(&self, kind: &str) -> PathBuf {
                                             self.revision,
                                             &self.config.compare_mode,
                                             kind);
-
         if !path.exists() && self.config.compare_mode.is_some() {
             // fallback!
             path = expected_output_path(&self.testpaths, self.revision, &None, kind);
@@ -2880,10 +2896,12 @@ fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
             }
         }
 
-        let expected_output = self.expected_output_path(kind);
-        // #50113: output is abspath; only want filename component.
-        let expected_output = expected_output.file_name().expect("output path requires file name");
-        let output_file = self.output_base_name().with_file_name(&expected_output);
+        let mode = self.config.compare_mode.as_ref().map_or("", |m| m.to_str());
+        let output_file = self.output_base_name()
+            .with_extra_extension(self.revision.unwrap_or(""))
+            .with_extra_extension(mode)
+            .with_extra_extension(kind);
+
         match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
             Ok(()) => {}
             Err(e) => self.fatal(&format!(
index d4712ca37500f26bbcbf97edcb27820717f769f7..f48fed70d4447445b586a35c4ae88683542ffc72 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d4712ca37500f26bbcbf97edcb27820717f769f7
+Subproject commit f48fed70d4447445b586a35c4ae88683542ffc72
index 554e3c0cd5f0bbd4771d57a69295829fbaba6bb5..5e11646ee4c196046d48da762e27e86b80f7133c 100644 (file)
@@ -8,6 +8,6 @@ license = "MIT/Apache-2.0"
 clap = "2.25.0"
 
 [dependencies.mdbook]
-version = "0.1.5"
+version = "0.1.7"
 default-features = false
 features = ["search"]
index 1e6c4336a9e995cf054399bc5cef863d1f67471e..6992f2ba123378d481baa367a5947e30f8f32d6d 100644 (file)
@@ -144,6 +144,7 @@ function main(argv) {
     var toolchain = argv[2];
 
     var mainJs = readFile("build/" + toolchain + "/doc/main.js");
+    var ALIASES = readFile("build/" + toolchain + "/doc/aliases.js");
     var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n");
     if (searchIndex[searchIndex.length - 1].length === 0) {
         searchIndex.pop();
@@ -161,6 +162,7 @@ function main(argv) {
                            "execSearch"];
 
     finalJS += 'window = { "currentCrate": "std" };\n';
+    finalJS += ALIASES;
     finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs);
     finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs);
     finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs);
index bda58bc09f77625714a23244b2018ebace908ddc..351005ff4b816b3038f4e6d99980f6320dd5d152 100644 (file)
 
 use std::path::Path;
 
-// See rust-lang/rust#48879: In addition to the mapping from `foo.rs`
-// to `foo.stderr`/`foo.stdout`, we also can optionally have
-// `foo.$mode.stderr`, where $mode is one of the strings on this list,
-// as an alternative to use when running under that mode.
-static COMPARE_MODE_NAMES: [&'static str; 1] = ["nll"];
-
 pub fn check(path: &Path, bad: &mut bool) {
     super::walk_many(&[&path.join("test/ui"), &path.join("test/ui-fulldeps")],
                      &mut |_| false,
                      &mut |file_path| {
         if let Some(ext) = file_path.extension() {
-            if (ext == "stderr" || ext == "stdout") && !file_path.with_extension("rs").exists() {
-
-                // rust-lang/rust#48879: this fn used to be beautful
-                // because Path API special-cases replacing
-                // extensions. That works great for ".stderr" but not
-                // so well for ".nll.stderr". To support the latter,
-                // we explicitly search backwards for mode's starting
-                // point and build corresponding source name.
-                let filename = file_path.file_name().expect("need filename")
-                    .to_str().expect("need UTF-8 filename");
-                let found_matching_prefix = COMPARE_MODE_NAMES.iter().any(|mode| {
-                    if let Some(r_idx) = filename.rfind(&format!(".{}", mode)) {
-                        let source_name = format!("{}.rs", &filename[0..r_idx]);
-                        let source_path = file_path.with_file_name(source_name);
-                        source_path.exists()
-                    } else {
-                        false
-                    }
-                });
-
-                if !found_matching_prefix {
+            if ext == "stderr" || ext == "stdout" {
+                // Test output filenames have the format:
+                // $testname.stderr
+                // $testname.$mode.stderr
+                // $testname.$revision.stderr
+                // $testname.$revision.$mode.stderr
+                //
+                // For now, just make sure that there is a corresponding
+                // $testname.rs file.
+                let testname = file_path.file_name().unwrap()
+                                        .to_str().unwrap()
+                                        .splitn(2, '.').next().unwrap();
+                if !file_path.with_file_name(testname)
+                             .with_extension("rs")
+                             .exists() {
                     println!("Stray file with UI testing output: {:?}", file_path);
                     *bad = true;
                 }