]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #45668 - nikomatsakis:nll-free-region, r=arielb1
authorbors <bors@rust-lang.org>
Mon, 6 Nov 2017 23:30:57 +0000 (23:30 +0000)
committerbors <bors@rust-lang.org>
Mon, 6 Nov 2017 23:30:57 +0000 (23:30 +0000)
extend NLL with preliminary support for free regions on functions

This PR extends https://github.com/rust-lang/rust/pull/45538 with support for free regions. This is pretty preliminary and will no doubt want to change in various ways, particularly as we add support for closures, but it's enough to get the basic idea in place:

- We now create specific regions to represent each named lifetime declared on the function.
- Region values can contain references to these regions (represented for now as a `BTreeSet<RegionIndex>`).
- If we wind up trying to infer that `'a: 'b` must hold, but no such relationship was declared, we report an error.

It also does a number of drive-by refactorings.

r? @arielb1

cc @spastorino

277 files changed:
src/Cargo.lock
src/bootstrap/install.rs
src/bootstrap/native.rs
src/bootstrap/tool.rs
src/ci/docker/dist-powerpc64le-linux/build-powerpc64le-toolchain.sh
src/doc/unstable-book/src/language-features/non-exhaustive.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/optin-builtin-traits.md
src/liballoc/benches/str.rs
src/liballoc/borrow.rs
src/liballoc/lib.rs
src/liballoc/raw_vec.rs
src/liballoc/slice.rs
src/liballoc/str.rs
src/liballoc/string.rs
src/liballoc/tests/str.rs
src/liballoc/tests/vec.rs
src/liballoc/vec.rs
src/liballoc_jemalloc/lib.rs
src/libcore/marker.rs
src/libcore/num/mod.rs
src/libcore/ops/deref.rs
src/libcore/sync/atomic.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/hir/def_id.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/README.md
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/higher_ranked/mod.rs
src/librustc/infer/region_inference/graphviz.rs
src/librustc/lint/mod.rs
src/librustc/middle/dead.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/mir/mod.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/traits/structural_impls.rs
src/librustc/traits/trans/mod.rs
src/librustc/ty/instance.rs
src/librustc/ty/item_path.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/trait_def.rs
src/librustc_allocator/expand.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_const_eval/_match.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_driver/test.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/schema.rs
src/librustc_mir/borrow_check.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/no_landing_pads.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/transform/type_check.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/mir_stats.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_save_analysis/span_utils.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/write.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/block.rs
src/librustc_trans_utils/collector.rs
src/librustc_typeck/README.md
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/cfg.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/doctree.rs
src/librustdoc/html/item_type.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/lib.rs
src/librustdoc/passes/mod.rs
src/librustdoc/visit_ast.rs
src/libstd/Cargo.toml
src/libstd/ascii.rs
src/libstd/heap.rs
src/libstd/io/buffered.rs
src/libstd/lib.rs
src/libstd/panic.rs
src/libstd/path.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/path.rs
src/libstd/sys/windows/process.rs
src/libstd_unicode/char.rs
src/libstd_unicode/lib.rs
src/libsyntax/ast.rs
src/libsyntax/codemap.rs
src/libsyntax/diagnostics/macros.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/json.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libsyntax_pos/Cargo.toml
src/libsyntax_pos/lib.rs
src/libsyntax_pos/span_encoding.rs
src/libsyntax_pos/symbol.rs
src/rtstartup/rsbegin.rs
src/rtstartup/rsend.rs
src/test/compile-fail/E0029.rs
src/test/compile-fail/auto-impl-future-compat.rs [new file with mode: 0644]
src/test/compile-fail/auto-trait-validation.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/tdticc_coherence_lib.rs
src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs [new file with mode: 0644]
src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
src/test/compile-fail/closure-expected-type/README.md [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-infer-var-appearing-twice.rs [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs [new file with mode: 0644]
src/test/compile-fail/coherence-default-trait-impl.rs
src/test/compile-fail/feature-gate-match_default_bindings.rs
src/test/compile-fail/feature-gate-non_exhaustive.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-optin-builtin-traits.rs
src/test/compile-fail/issue-16338.rs
src/test/compile-fail/issue-20261.rs
src/test/compile-fail/issue-23080-2.rs
src/test/compile-fail/issue-23080.rs
src/test/compile-fail/keyword-false-as-identifier.rs
src/test/compile-fail/keyword-self-as-identifier.rs
src/test/compile-fail/keyword-super-as-identifier.rs
src/test/compile-fail/keyword-true-as-identifier.rs
src/test/compile-fail/match-range-fail.rs
src/test/compile-fail/match-vec-mismatch.rs
src/test/compile-fail/pat-slice-old-style.rs
src/test/compile-fail/phantom-oibit.rs
src/test/compile-fail/privacy-sanity.rs
src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/enums.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/structs.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/variants.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2008-non-exhaustive/enum.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2008-non-exhaustive/structs.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2008-non-exhaustive/variants.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2008-non-exhaustive/variants_create.rs [new file with mode: 0644]
src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
src/test/compile-fail/specialization/specialization-polarity.rs
src/test/compile-fail/syntaxt-default-trait-impls.rs
src/test/compile-fail/traits-inductive-overflow-supertrait-oibit.rs
src/test/compile-fail/typeck-auto-trait-no-supertraits-2.rs
src/test/compile-fail/typeck-auto-trait-no-supertraits.rs
src/test/compile-fail/typeck-auto-trait-no-typeparams.rs
src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
src/test/compile-fail/typeck-default-trait-impl-negation.rs
src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs
src/test/compile-fail/typeck-default-trait-impl-precedence.rs
src/test/incremental/hashes/trait_defs.rs
src/test/mir-opt/match_false_edges.rs [new file with mode: 0644]
src/test/mir-opt/validate_1.rs
src/test/mir-opt/validate_4.rs
src/test/mir-opt/validate_5.rs
src/test/pretty/auto-trait.rs [new file with mode: 0644]
src/test/pretty/default-trait-impl.rs [deleted file]
src/test/run-make/cdylib-fewer-symbols/Makefile [new file with mode: 0644]
src/test/run-make/cdylib-fewer-symbols/foo.rs [new file with mode: 0644]
src/test/run-make/extra-filename-with-temp-outputs/Makefile
src/test/run-make/save-analysis/foo.rs
src/test/run-make/simd-ffi/simd.rs
src/test/run-make/target-specs/foo.rs
src/test/run-pass/auto-is-contextual.rs [new file with mode: 0644]
src/test/run-pass/auto-traits.rs [new file with mode: 0644]
src/test/run-pass/closure-expected-type/README.md [new file with mode: 0644]
src/test/run-pass/closure-expected-type/expect-infer-supply-two-infers.rs [new file with mode: 0644]
src/test/run-pass/closure-expected-type/issue-38714.rs [new file with mode: 0644]
src/test/run-pass/closure-expected-type/supply-just-return-type.rs [new file with mode: 0644]
src/test/run-pass/closure-expected-type/supply-nothing.rs [new file with mode: 0644]
src/test/run-pass/issue-29516.rs
src/test/run-pass/mir-inlining/ice-issue-45493.rs [new file with mode: 0644]
src/test/run-pass/next-power-of-two-overflow-debug.rs [new file with mode: 0644]
src/test/run-pass/next-power-of-two-overflow-ndebug.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/enums.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/enums_same_crate.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/structs.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/structs_same_crate.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/variants.rs [new file with mode: 0644]
src/test/run-pass/rfc-2008-non-exhaustive/variants_same_crate.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/rustdoc-default-impl.rs
src/test/rustdoc/auxiliary/rustdoc-impl-parts-crosscrate.rs
src/test/rustdoc/impl-parts.rs
src/test/rustdoc/method-list.rs [new file with mode: 0644]
src/test/ui/codemap_tests/unicode.stderr
src/test/ui/codemap_tests/unicode_2.rs [new file with mode: 0644]
src/test/ui/codemap_tests/unicode_2.stderr [new file with mode: 0644]
src/test/ui/codemap_tests/unicode_3.rs [new file with mode: 0644]
src/test/ui/codemap_tests/unicode_3.stderr [new file with mode: 0644]
src/test/ui/deref-suggestion.stderr
src/test/ui/issue-35241.rs [new file with mode: 0644]
src/test/ui/issue-35241.stderr [new file with mode: 0644]
src/test/ui/issue-40782.rs [new file with mode: 0644]
src/test/ui/issue-40782.stderr [new file with mode: 0644]
src/test/ui/issue-44078.stderr
src/test/ui/lint/unreachable_pub-pub_crate.rs [new file with mode: 0644]
src/test/ui/lint/unreachable_pub-pub_crate.stderr [new file with mode: 0644]
src/test/ui/lint/unreachable_pub.rs [new file with mode: 0644]
src/test/ui/lint/unreachable_pub.stderr [new file with mode: 0644]
src/test/ui/lint/unused_parens_json_suggestion.rs
src/test/ui/lint/unused_parens_json_suggestion.stderr
src/test/ui/lint/use_suggestion_json.rs
src/test/ui/lint/use_suggestion_json.stderr
src/test/ui/mismatched_types/closure-arg-count.stderr
src/test/ui/rfc-2005-default-binding-mode/suggestion.rs [new file with mode: 0644]
src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/cargotest/main.rs
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/runtest.rs
src/tools/rls
src/tools/rustfmt

index 70266df79ebb6baae81cf1ecb254b91f5da837b4..c4314b41e39662f7eec614d9f25f6b27cf2ae51a 100644 (file)
@@ -1447,7 +1447,7 @@ version = "0.1.0"
 
 [[package]]
 name = "rls"
-version = "0.122.0"
+version = "0.123.0"
 dependencies = [
  "cargo 0.24.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1456,12 +1456,12 @@ dependencies = [
  "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.2.13",
+ "rustfmt-nightly 0.2.14",
  "serde 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1470,7 +1470,7 @@ dependencies = [
 
 [[package]]
 name = "rls-analysis"
-version = "0.7.1"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1834,6 +1834,7 @@ dependencies = [
  "arena 0.0.0",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -1945,7 +1946,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.2.13"
+version = "0.2.14"
 dependencies = [
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2230,6 +2231,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2721,7 +2723,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum rls-analysis 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3e4c03af262074324e732ba2313ce74968b4262b060367ed4d52940b6586fa1"
+"checksum rls-analysis 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10fbe17ed9da2fa3686ebb018958e194a4a25f0b3a78382bfe334d09d3c641f4"
 "checksum rls-data 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48257ceade23c2e01a3ca8d2fc4226101b107f6a3c868f829cf3fd2f204a1fe6"
 "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
index 608924c9c28d196b623d421a87e185030cbc59d5..5ca9cb5e521f3d276665f9391d40f48f8a667d34 100644 (file)
@@ -27,10 +27,8 @@ pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
     install_sh(builder, "docs", "rust-docs", stage, Some(host));
 }
 
-pub fn install_std(builder: &Builder, stage: u32) {
-    for target in &builder.build.targets {
-        install_sh(builder, "std", "rust-std", stage, Some(*target));
-    }
+pub fn install_std(builder: &Builder, stage: u32, target: Interned<String>) {
+    install_sh(builder, "std", "rust-std", stage, Some(target));
 }
 
 pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
@@ -175,11 +173,13 @@ fn run($sel, $builder: &Builder) {
         install_docs(builder, self.stage, self.target);
     };
     Std, "src/libstd", true, only_hosts: true, {
-        builder.ensure(dist::Std {
-            compiler: builder.compiler(self.stage, self.host),
-            target: self.target
-        });
-        install_std(builder, self.stage);
+        for target in &builder.build.targets {
+            builder.ensure(dist::Std {
+                compiler: builder.compiler(self.stage, self.host),
+                target: *target
+            });
+            install_std(builder, self.stage, *target);
+        }
     };
     Cargo, "cargo", _config.extended, only_hosts: true, {
         builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
index 19409ef779ecc940b61ddd068170fc4acbc7ec5e..fce6755aea920d6cf87de30ddc697b5b05acb7ae 100644 (file)
@@ -323,9 +323,9 @@ fn run(self, builder: &Builder) {
     }
 }
 
-const OPENSSL_VERS: &'static str = "1.0.2k";
+const OPENSSL_VERS: &'static str = "1.0.2m";
 const OPENSSL_SHA256: &'static str =
-    "6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0";
+    "8c6ff15ec6b319b50788f42c7abc2890c08ba5a1cdcd3810eb9092deada37b0f";
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Openssl {
index 688ee6ba295fa286f13ff57c26a21c9c78c9018a..7175fed5410bace13bc25fe55caa7d2e65106079 100644 (file)
@@ -415,7 +415,8 @@ impl Step for Clippy {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun) -> ShouldRun {
-        run.path("src/tools/clippy")
+        let builder = run.builder;
+        run.path("src/tools/clippy").default_condition(builder.build.config.extended)
     }
 
     fn make_run(run: RunConfig) {
index 4d3e638916dbf248b6f52509b4d3f4251acf2d50..f231d20b1975317ed57fdce74c42fa1683b7cc05 100755 (executable)
@@ -23,9 +23,9 @@ SYSROOT=/usr/local/$TARGET/sysroot
 mkdir -p $SYSROOT
 pushd $SYSROOT
 
-centos_base=http://mirror.centos.org/altarch/7.3.1611/os/ppc64le/Packages
-glibc_v=2.17-157.el7
-kernel_v=3.10.0-514.el7
+centos_base=http://mirror.centos.org/altarch/7/os/ppc64le/Packages
+glibc_v=2.17-196.el7
+kernel_v=3.10.0-693.el7
 for package in glibc{,-devel,-headers}-$glibc_v kernel-headers-$kernel_v; do
   curl $centos_base/$package.ppc64le.rpm | \
     rpm2cpio - | cpio -idm
diff --git a/src/doc/unstable-book/src/language-features/non-exhaustive.md b/src/doc/unstable-book/src/language-features/non-exhaustive.md
new file mode 100644 (file)
index 0000000..f9840e1
--- /dev/null
@@ -0,0 +1,75 @@
+# `non_exhaustive`
+
+The tracking issue for this feature is: [#44109]
+
+[#44109]: https://github.com/rust-lang/rust/issues/44109
+
+------------------------
+
+The `non_exhaustive` gate allows you to use the `#[non_exhaustive]` attribute
+on structs and enums. When applied within a crate, users of the crate will need
+to use the `_` pattern when matching enums and use the `..` pattern when
+matching structs. Structs marked as `non_exhaustive` will not be able to be
+created normally outside of the defining crate. This is demonstrated below:
+
+```rust,ignore (pseudo-Rust)
+use std::error::Error as StdError;
+
+#[non_exhaustive]
+pub enum Error {
+    Message(String),
+    Other,
+}
+impl StdError for Error {
+    fn description(&self) -> &str {
+        // This will not error, despite being marked as non_exhaustive, as this
+        // enum is defined within the current crate, it can be matched
+        // exhaustively.
+        match *self {
+            Message(ref s) => s,
+            Other => "other or unknown error",
+        }
+    }
+}
+```
+
+```rust,ignore (pseudo-Rust)
+use mycrate::Error;
+
+// This will not error as the non_exhaustive Error enum has been matched with
+// a wildcard.
+match error {
+    Message(ref s) => ...,
+    Other => ...,
+    _ => ...,
+}
+```
+
+```rust,ignore (pseudo-Rust)
+#[non_exhaustive]
+pub struct Config {
+    pub window_width: u16,
+    pub window_height: u16,
+}
+
+// We can create structs as normal within the defining crate when marked as
+// non_exhaustive.
+let config = Config { window_width: 640, window_height: 480 };
+
+// We can match structs exhaustively when within the defining crate.
+if let Ok(Config { window_width, window_height }) = load_config() {
+    // ...
+}
+```
+
+```rust,ignore (pseudo-Rust)
+use mycrate::Config;
+
+// We cannot create a struct like normal if it has been marked as
+// non_exhaustive.
+let config = Config { window_width: 640, window_height: 480 };
+// By adding the `..` we can match the config as below outside of the crate
+// when marked non_exhaustive.
+let &Config { window_width, window_height, .. } = config;
+```
+
index ee24dd87d90c38a5438f1ec96c1027697c16cb06..97b57c690fcc811286dc6fde743a28eb8ef87929 100644 (file)
@@ -24,9 +24,7 @@ Example:
 ```rust
 #![feature(optin_builtin_traits)]
 
-trait Valid {}
-
-impl Valid for .. {}
+auto trait Valid {}
 
 struct True;
 struct False;
index fc4063fae927754353d5e736099f0a365b0dd2d7..38c94d4d8b5f36a64739c7b2d4192be4876b7e5d 100644 (file)
@@ -272,15 +272,12 @@ mod $name {
 make_test!(split_a_str, s, s.split("a").count());
 
 make_test!(trim_ascii_char, s, {
-    use std::ascii::AsciiExt;
     s.trim_matches(|c: char| c.is_ascii())
 });
 make_test!(trim_left_ascii_char, s, {
-    use std::ascii::AsciiExt;
     s.trim_left_matches(|c: char| c.is_ascii())
 });
 make_test!(trim_right_ascii_char, s, {
-    use std::ascii::AsciiExt;
     s.trim_right_matches(|c: char| c.is_ascii())
 });
 
index a662e4b1f4f931de28292c8ed094f559e4d0b031..e8aff0998715726bc21c4908b790a71f19400535 100644 (file)
@@ -191,7 +191,6 @@ impl<'a, B: ?Sized> Cow<'a, B>
     /// # Examples
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
     /// use std::borrow::Cow;
     ///
     /// let mut cow = Cow::Borrowed("foo");
index f654a6b5ba4713f0ac01637b99f21cc3499180ef..a40ed060604a7b1e4f8e19f30366d2a6fd15413a 100644 (file)
@@ -83,6 +83,7 @@
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(test, feature(rand, test))]
 #![feature(allow_internal_unstable)]
+#![feature(ascii_ctype)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
index 841f9dc64142e3528f01c2cd6b29c6dd5cb6b899..dbf1fb1367dda257ecb88aa7118f0be03f1b0f80 100644 (file)
@@ -114,7 +114,7 @@ fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self {
 impl<T> RawVec<T, Heap> {
     /// Creates the biggest possible RawVec (on the system heap)
     /// without allocating. If T has positive size, then this makes a
-    /// RawVec with capacity 0. If T has 0 size, then it it makes a
+    /// RawVec with capacity 0. If T has 0 size, then it makes a
     /// RawVec with capacity `usize::MAX`. Useful for implementing
     /// delayed allocation.
     pub fn new() -> Self {
index 0c5fec2cf74994379e343a3ac649725b89a257ed..b41cb912fe798d892ad01ba9119f74a469e3f38b 100644 (file)
@@ -1533,6 +1533,215 @@ pub fn into_vec(self: Box<Self>) -> Vec<T> {
     }
 }
 
+// FIXME(LukasKalbertodt): the `not(stage0)` constraint can be removed in the
+// future once the stage0 compiler is new enough to know about the `slice_u8`
+// lang item.
+#[lang = "slice_u8"]
+#[cfg(all(not(stage0), not(test)))]
+impl [u8] {
+    /// Checks if all bytes in this slice are within the ASCII range.
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.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.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_uppercase(&self) -> Vec<u8> {
+        let mut me = self.to_vec();
+        me.make_ascii_uppercase();
+        me
+    }
+
+    /// Returns a vector containing a copy of this slice where each byte
+    /// is mapped to its ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_lowercase(&self) -> Vec<u8> {
+        let mut me = self.to_vec();
+        me.make_ascii_lowercase();
+        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.21.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.21.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.21.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        for byte in self {
+            byte.make_ascii_lowercase();
+        }
+    }
+
+    /// Checks if all bytes of this slice are ASCII alphabetic characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_alphabetic())
+    }
+
+    /// Checks if all bytes of this slice are ASCII uppercase characters:
+    /// U+0041 'A' ... U+005A 'Z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_uppercase())
+    }
+
+    /// Checks if all bytes of this slice are ASCII lowercase characters:
+    /// U+0061 'a' ... U+007A 'z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_lowercase())
+    }
+
+    /// Checks if all bytes of this slice are ASCII alphanumeric characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_alphanumeric())
+    }
+
+    /// Checks if all bytes of this slice are ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_digit())
+    }
+
+    /// Checks if all bytes of this slice are ASCII hexadecimal digits:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_hexdigit())
+    }
+
+    /// Checks if all bytes of this slice are ASCII punctuation characters:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_punctuation())
+    }
+
+    /// Checks if all bytes of this slice are ASCII graphic characters:
+    /// U+0021 '@' ... U+007E '~'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_graphic())
+    }
+
+    /// Checks if all bytes of this slice are ASCII whitespace characters:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_whitespace())
+    }
+
+    /// Checks if all bytes of this slice are ASCII control characters:
+    ///
+    /// - U+0000 NUL ... U+001F UNIT SEPARATOR, or
+    /// - U+007F DELETE.
+    ///
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        self.iter().all(|b| b.is_ascii_control())
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Extension traits for slices over specific kinds of data
 ////////////////////////////////////////////////////////////////////////////////
index 895607ff8d4f0cdd2f85d4f009f419da48ef4dbc..5f0b4088fc07eaa53f5f3962985d53d327610da8 100644 (file)
@@ -390,8 +390,6 @@ pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
     /// # Examples
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut v = String::from("hello");
     /// // correct length
     /// assert!(v.get_mut(0..5).is_some());
@@ -617,8 +615,6 @@ pub fn split_at(&self, mid: usize) -> (&str, &str) {
     /// Basic usage:
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut s = "Per Martin-Löf".to_string();
     /// {
     ///     let (first, last) = s.split_at_mut(3);
@@ -2070,6 +2066,286 @@ pub fn repeat(&self, n: usize) -> String {
         s.extend((0..n).map(|_| self));
         s
     }
+
+    /// 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.21.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())
+    }
+
+    /// Returns a copy of this string where each character is mapped to its
+    /// ASCII upper case equivalent.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// To uppercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Grüße, Jürgen ❤";
+    ///
+    /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
+    /// ```
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    /// [`to_uppercase`]: #method.to_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    #[cfg(not(stage0))]
+    pub fn to_ascii_uppercase(&self) -> String {
+        let mut bytes = self.as_bytes().to_vec();
+        bytes.make_ascii_uppercase();
+        // make_ascii_uppercase() preserves the UTF-8 invariant.
+        unsafe { String::from_utf8_unchecked(bytes) }
+    }
+
+    /// Returns a copy of this string where each character is mapped to its
+    /// ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// To lowercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Grüße, Jürgen ❤";
+    ///
+    /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
+    /// ```
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    /// [`to_lowercase`]: #method.to_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    #[cfg(not(stage0))]
+    pub fn to_ascii_lowercase(&self) -> String {
+        let mut bytes = self.as_bytes().to_vec();
+        bytes.make_ascii_lowercase();
+        // 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.21.0")]
+    #[inline]
+    #[cfg(not(stage0))]
+    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.21.0")]
+    #[cfg(not(stage0))]
+    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.21.0")]
+    #[cfg(not(stage0))]
+    pub fn make_ascii_lowercase(&mut self) {
+        let me = unsafe { self.as_bytes_mut() };
+        me.make_ascii_lowercase()
+    }
+
+    /// Checks if all characters of this string are ASCII alphabetic
+    /// characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_alphabetic())
+    }
+
+    /// Checks if all characters of this string are ASCII uppercase characters:
+    /// U+0041 'A' ... U+005A 'Z'.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// // Only ascii uppercase characters
+    /// assert!("HELLO".is_ascii_uppercase());
+    ///
+    /// // While all characters are ascii, 'y' and 'e' are not uppercase
+    /// assert!(!"Bye".is_ascii_uppercase());
+    ///
+    /// // While all characters are uppercase, 'Ü' is not ascii
+    /// assert!(!"TSCHÜSS".is_ascii_uppercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_uppercase())
+    }
+
+    /// Checks if all characters of this string are ASCII lowercase characters:
+    /// U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// // Only ascii uppercase characters
+    /// assert!("hello".is_ascii_lowercase());
+    ///
+    /// // While all characters are ascii, 'B' is not lowercase
+    /// assert!(!"Bye".is_ascii_lowercase());
+    ///
+    /// // While all characters are lowercase, 'Ü' is not ascii
+    /// assert!(!"tschüss".is_ascii_lowercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_lowercase())
+    }
+
+    /// Checks if all characters of this string are ASCII alphanumeric
+    /// characters:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_alphanumeric())
+    }
+
+    /// Checks if all characters of this string are ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_digit())
+    }
+
+    /// Checks if all characters of this string are ASCII hexadecimal digits:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_hexdigit())
+    }
+
+    /// Checks if all characters of this string are ASCII punctuation
+    /// characters:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_punctuation())
+    }
+
+    /// Checks if all characters of this string are ASCII graphic characters:
+    /// U+0021 '@' ... U+007E '~'.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_graphic())
+    }
+
+    /// Checks if all characters of this string are ASCII whitespace characters:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_whitespace())
+    }
+
+    /// Checks if all characters of this string are ASCII control characters:
+    ///
+    /// - U+0000 NUL ... U+001F UNIT SEPARATOR, or
+    /// - U+007F DELETE.
+    ///
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        self.bytes().all(|b| b.is_ascii_control())
+    }
 }
 
 /// Converts a boxed slice of bytes to a boxed string slice without checking
index 6d0bb264df1863b50264b1f73df9a6d6d683dbe0..25fcc1ccdab589e8c774572c82098967ec58a563 100644 (file)
@@ -773,8 +773,6 @@ pub fn as_str(&self) -> &str {
     /// Basic usage:
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut s = String::from("foobar");
     /// let s_mut_str = s.as_mut_str();
     ///
index b3178064505e8683f0bbeacd77b01b3c36ccca89..6b075e7ac0e0d0f47f1fbd776973306e048abcf6 100644 (file)
@@ -706,7 +706,6 @@ fn test_split_at() {
 
 #[test]
 fn test_split_at_mut() {
-    use std::ascii::AsciiExt;
     let mut s = "Hello World".to_string();
     {
         let (a, b) = s.split_at_mut(5);
index 0e25da5bd3077f099034e6deaaabdba5e7adf5ac..9cfde5dcc73c8433b0f37f030a30b1b0b6fbb9b0 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::ascii::AsciiExt;
 use std::borrow::Cow;
 use std::mem::size_of;
 use std::panic;
@@ -966,5 +965,3 @@ fn drain_filter_complex() {
         assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
     }
 }
-
-
index cf34e195dea76fe1d8262d412eab2823cb965e87..5aca199cf40c068896632a566ab7bd30e0eed334 100644 (file)
@@ -853,8 +853,6 @@ pub fn dedup_by_key<F, K>(&mut self, mut key: F) where F: FnMut(&mut T) -> K, K:
     /// # Examples
     ///
     /// ```
-    /// use std::ascii::AsciiExt;
-    ///
     /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"];
     ///
     /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
index d153f19c4622f021d78dee45d2453b22b10dc9a5..f060f6d79c17aabe2c503730b3a7d11aacc4111c 100644 (file)
@@ -107,7 +107,7 @@ fn align_to_flags(align: usize) -> c_int {
     // ABI
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_alloc(size: usize,
                                      align: usize,
                                      err: *mut u8) -> *mut u8 {
@@ -122,13 +122,13 @@ fn align_to_flags(align: usize) -> c_int {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
         System.oom((*(err as *const AllocErr)).clone())
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
                                        size: usize,
                                        align: usize) {
@@ -137,7 +137,7 @@ fn align_to_flags(align: usize) -> c_int {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_usable_size(layout: *const u8,
                                            min: *mut usize,
                                            max: *mut usize) {
@@ -153,7 +153,7 @@ fn align_to_flags(align: usize) -> c_int {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_realloc(ptr: *mut u8,
                                        _old_size: usize,
                                        old_align: usize,
@@ -177,7 +177,7 @@ fn align_to_flags(align: usize) -> c_int {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_alloc_zeroed(size: usize,
                                             align: usize,
                                             err: *mut u8) -> *mut u8 {
@@ -196,20 +196,21 @@ fn align_to_flags(align: usize) -> c_int {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_alloc_excess(size: usize,
                                             align: usize,
                                             excess: *mut usize,
                                             err: *mut u8) -> *mut u8 {
         let p = __rde_alloc(size, align, err);
         if !p.is_null() {
-            *excess = size;
+            let flags = align_to_flags(align);
+            *excess = nallocx(size, flags) as usize;
         }
         return p
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
                                               old_size: usize,
                                               old_align: usize,
@@ -219,13 +220,14 @@ fn align_to_flags(align: usize) -> c_int {
                                               err: *mut u8) -> *mut u8 {
         let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
         if !p.is_null() {
-            *excess = new_size;
+            let flags = align_to_flags(new_align);
+            *excess = nallocx(new_size, flags) as usize;
         }
-        return p
+        p
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
                                              old_size: usize,
                                              old_align: usize,
@@ -235,7 +237,7 @@ fn align_to_flags(align: usize) -> c_int {
     }
 
     #[no_mangle]
-    #[linkage = "external"]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
                                                _old_size: usize,
                                                old_align: usize,
index f56a9a40332987c804e829fa35d362416c241a53..e47b99ed552d3be974624a6b3a56d367dfe84834 100644 (file)
@@ -46,6 +46,8 @@ pub unsafe trait Send {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 unsafe impl Send for .. { }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -349,6 +351,8 @@ pub unsafe trait Sync {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 unsafe impl Sync for .. { }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -562,6 +566,8 @@ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 #[lang = "freeze"]
 unsafe trait Freeze {}
 
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 unsafe impl Freeze for .. {}
 
 impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
index 5799d37c19cc6f28400fabf3fe1607678e3f862e..7fe0aabeec9e90e4f14f41528a6379232de115cd 100644 (file)
@@ -15,6 +15,7 @@
 use convert::{Infallible, TryFrom};
 use fmt;
 use intrinsics;
+use ops;
 use str::FromStr;
 
 /// Provides intentionally-wrapped arithmetic on `T`.
@@ -2223,7 +2224,8 @@ fn one_less_than_next_power_of_two(self) -> Self {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn next_power_of_two(self) -> Self {
-            self.one_less_than_next_power_of_two() + 1
+            // Call the trait to get overflow checks
+            ops::Add::add(self.one_less_than_next_power_of_two(), 1)
         }
 
         /// Returns the smallest power of two greater than or equal to `n`. If
@@ -2257,6 +2259,547 @@ impl u8 {
         intrinsics::add_with_overflow,
         intrinsics::sub_with_overflow,
         intrinsics::mul_with_overflow }
+
+
+    /// Checks if the value is within the ASCII range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 97u8;
+    /// let non_ascii = 150u8;
+    ///
+    /// assert!(ascii.is_ascii());
+    /// assert!(!non_ascii.is_ascii());
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        *self & 128 == 0
+    }
+
+    /// Makes a copy of the value in its ASCII upper case equivalent.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let lowercase_a = 97u8;
+    ///
+    /// assert_eq!(65, lowercase_a.to_ascii_uppercase());
+    /// ```
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_uppercase(&self) -> u8 {
+        ASCII_UPPERCASE_MAP[*self as usize]
+    }
+
+    /// Makes a copy of the value in its ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let uppercase_a = 65u8;
+    ///
+    /// assert_eq!(97, uppercase_a.to_ascii_lowercase());
+    /// ```
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_lowercase(&self) -> u8 {
+        ASCII_LOWERCASE_MAP[*self as usize]
+    }
+
+    /// Checks that two values are an ASCII case-insensitive match.
+    ///
+    /// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let lowercase_a = 97u8;
+    /// let uppercase_a = 65u8;
+    ///
+    /// assert!(lowercase_a.eq_ignore_ascii_case(&uppercase_a));
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
+        self.to_ascii_lowercase() == other.to_ascii_lowercase()
+    }
+
+    /// Converts this value 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`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut byte = b'a';
+    ///
+    /// byte.make_ascii_uppercase();
+    ///
+    /// assert_eq!(b'A', byte);
+    /// ```
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        *self = self.to_ascii_uppercase();
+    }
+
+    /// Converts this value 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`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut byte = b'A';
+    ///
+    /// byte.make_ascii_lowercase();
+    ///
+    /// assert_eq!(b'a', byte);
+    /// ```
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        *self = self.to_ascii_lowercase();
+    }
+
+    /// Checks if the value is an ASCII alphabetic character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_alphabetic());
+    /// assert!(uppercase_g.is_ascii_alphabetic());
+    /// assert!(a.is_ascii_alphabetic());
+    /// assert!(g.is_ascii_alphabetic());
+    /// assert!(!zero.is_ascii_alphabetic());
+    /// assert!(!percent.is_ascii_alphabetic());
+    /// assert!(!space.is_ascii_alphabetic());
+    /// assert!(!lf.is_ascii_alphabetic());
+    /// assert!(!esc.is_ascii_alphabetic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            L | Lx | U | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII uppercase character:
+    /// U+0041 'A' ... U+005A 'Z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_uppercase());
+    /// assert!(uppercase_g.is_ascii_uppercase());
+    /// assert!(!a.is_ascii_uppercase());
+    /// assert!(!g.is_ascii_uppercase());
+    /// assert!(!zero.is_ascii_uppercase());
+    /// assert!(!percent.is_ascii_uppercase());
+    /// assert!(!space.is_ascii_uppercase());
+    /// assert!(!lf.is_ascii_uppercase());
+    /// assert!(!esc.is_ascii_uppercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            U | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII lowercase character:
+    /// U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_lowercase());
+    /// assert!(!uppercase_g.is_ascii_lowercase());
+    /// assert!(a.is_ascii_lowercase());
+    /// assert!(g.is_ascii_lowercase());
+    /// assert!(!zero.is_ascii_lowercase());
+    /// assert!(!percent.is_ascii_lowercase());
+    /// assert!(!space.is_ascii_lowercase());
+    /// assert!(!lf.is_ascii_lowercase());
+    /// assert!(!esc.is_ascii_lowercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            L | Lx => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII alphanumeric character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_alphanumeric());
+    /// assert!(uppercase_g.is_ascii_alphanumeric());
+    /// assert!(a.is_ascii_alphanumeric());
+    /// assert!(g.is_ascii_alphanumeric());
+    /// assert!(zero.is_ascii_alphanumeric());
+    /// assert!(!percent.is_ascii_alphanumeric());
+    /// assert!(!space.is_ascii_alphanumeric());
+    /// assert!(!lf.is_ascii_alphanumeric());
+    /// assert!(!esc.is_ascii_alphanumeric());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            D | L | Lx | U | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_digit());
+    /// assert!(!uppercase_g.is_ascii_digit());
+    /// assert!(!a.is_ascii_digit());
+    /// assert!(!g.is_ascii_digit());
+    /// assert!(zero.is_ascii_digit());
+    /// assert!(!percent.is_ascii_digit());
+    /// assert!(!space.is_ascii_digit());
+    /// assert!(!lf.is_ascii_digit());
+    /// assert!(!esc.is_ascii_digit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            D => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII hexadecimal digit:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_hexdigit());
+    /// assert!(!uppercase_g.is_ascii_hexdigit());
+    /// assert!(a.is_ascii_hexdigit());
+    /// assert!(!g.is_ascii_hexdigit());
+    /// assert!(zero.is_ascii_hexdigit());
+    /// assert!(!percent.is_ascii_hexdigit());
+    /// assert!(!space.is_ascii_hexdigit());
+    /// assert!(!lf.is_ascii_hexdigit());
+    /// assert!(!esc.is_ascii_hexdigit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            D | Lx | Ux => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII punctuation character:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_punctuation());
+    /// assert!(!uppercase_g.is_ascii_punctuation());
+    /// assert!(!a.is_ascii_punctuation());
+    /// assert!(!g.is_ascii_punctuation());
+    /// assert!(!zero.is_ascii_punctuation());
+    /// assert!(percent.is_ascii_punctuation());
+    /// assert!(!space.is_ascii_punctuation());
+    /// assert!(!lf.is_ascii_punctuation());
+    /// assert!(!esc.is_ascii_punctuation());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        if *self >= 0x80 { return false }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            P => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII graphic character:
+    /// U+0021 '@' ... U+007E '~'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(uppercase_a.is_ascii_graphic());
+    /// assert!(uppercase_g.is_ascii_graphic());
+    /// assert!(a.is_ascii_graphic());
+    /// assert!(g.is_ascii_graphic());
+    /// assert!(zero.is_ascii_graphic());
+    /// assert!(percent.is_ascii_graphic());
+    /// assert!(!space.is_ascii_graphic());
+    /// assert!(!lf.is_ascii_graphic());
+    /// assert!(!esc.is_ascii_graphic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            Ux | U | Lx | L | D | P => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII whitespace character:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_whitespace());
+    /// assert!(!uppercase_g.is_ascii_whitespace());
+    /// assert!(!a.is_ascii_whitespace());
+    /// assert!(!g.is_ascii_whitespace());
+    /// assert!(!zero.is_ascii_whitespace());
+    /// assert!(!percent.is_ascii_whitespace());
+    /// assert!(space.is_ascii_whitespace());
+    /// assert!(lf.is_ascii_whitespace());
+    /// assert!(!esc.is_ascii_whitespace());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            Cw | W => true,
+            _ => false
+        }
+    }
+
+    /// Checks if the value is an ASCII control character:
+    /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = b'A';
+    /// let uppercase_g = b'G';
+    /// let a = b'a';
+    /// let g = b'g';
+    /// let zero = b'0';
+    /// let percent = b'%';
+    /// let space = b' ';
+    /// let lf = b'\n';
+    /// let esc = 0x1b_u8;
+    ///
+    /// assert!(!uppercase_a.is_ascii_control());
+    /// assert!(!uppercase_g.is_ascii_control());
+    /// assert!(!a.is_ascii_control());
+    /// assert!(!g.is_ascii_control());
+    /// assert!(!zero.is_ascii_control());
+    /// assert!(!percent.is_ascii_control());
+    /// assert!(!space.is_ascii_control());
+    /// assert!(lf.is_ascii_control());
+    /// assert!(esc.is_ascii_control());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        if *self >= 0x80 { return false; }
+        match ASCII_CHARACTER_CLASS[*self as usize] {
+            C | Cw => true,
+            _ => false
+        }
+    }
 }
 
 #[lang = "u16"]
@@ -2926,3 +3469,106 @@ fn from(small: $Small) -> $Large {
 
 // Float -> Float
 impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+
+static ASCII_LOWERCASE_MAP: [u8; 256] = [
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
+    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
+    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
+    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
+    b'@',
+
+          b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+    b'x', b'y', b'z',
+
+                      b'[', b'\\', b']', b'^', b'_',
+    b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
+    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
+    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
+    b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+];
+
+static ASCII_UPPERCASE_MAP: [u8; 256] = [
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
+    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
+    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
+    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
+    b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
+    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
+    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
+    b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
+    b'`',
+
+          b'A', b'B', b'C', b'D', b'E', b'F', b'G',
+    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
+    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
+    b'X', b'Y', b'Z',
+
+                      b'{', b'|', b'}', b'~', 0x7f,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+];
+
+enum AsciiCharacterClass {
+    C,  // control
+    Cw, // control whitespace
+    W,  // whitespace
+    D,  // digit
+    L,  // lowercase
+    Lx, // lowercase hex digit
+    U,  // uppercase
+    Ux, // uppercase hex digit
+    P,  // punctuation
+}
+use self::AsciiCharacterClass::*;
+
+static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [
+//  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
+    C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
+    C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_
+    W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_
+    D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_
+    P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_
+    U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_
+    P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_
+    L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_
+];
index 4cb6e8405f398f61e3bd6f334c9081108f750e5a..80c48c7b28efd9dea8f25df881c2f699b7720497 100644 (file)
@@ -18,7 +18,7 @@
 /// Implementing `Deref` for smart pointers makes accessing the data behind them
 /// convenient, which is why they implement `Deref`. On the other hand, the
 /// rules regarding `Deref` and [`DerefMut`] were designed specifically to
-/// accomodate smart pointers. Because of this, **`Deref` should only be
+/// accommodate smart pointers. Because of this, **`Deref` should only be
 /// implemented for smart pointers** to avoid confusion.
 ///
 /// For similar reasons, **this trait should never fail**. Failure during
@@ -103,7 +103,7 @@ fn deref(&self) -> &T { *self }
 /// Implementing `DerefMut` for smart pointers makes mutating the data behind
 /// them convenient, which is why they implement `DerefMut`. On the other hand,
 /// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
-/// accomodate smart pointers. Because of this, **`DerefMut` should only be
+/// accommodate smart pointers. Because of this, **`DerefMut` should only be
 /// implemented for smart pointers** to avoid confusion.
 ///
 /// For similar reasons, **this trait should never fail**. Failure during
index 53b056d2b8b6f849704375513b63330602dcf287..cd3dd9ce1399e2e2f604549b425f8be0df078a2e 100644 (file)
@@ -927,6 +927,12 @@ pub fn compare_exchange_weak(&self,
     }
 }
 
+#[stable(feature = "atomic_from", since = "1.23.0")]
+impl<T> From<*mut T> for AtomicPtr<T> {
+    #[inline]
+    fn from(p: *mut T) -> Self { Self::new(p) }
+}
+
 #[cfg(target_has_atomic = "ptr")]
 macro_rules! atomic_int {
     ($stable:meta, $const_unstable:meta,
@@ -967,6 +973,12 @@ fn default() -> Self {
             }
         }
 
+        #[stable(feature = "atomic_from", since = "1.23.0")]
+        impl From<$int_type> for $atomic_type {
+            #[inline]
+            fn from(v: $int_type) -> Self { Self::new(v) }
+        }
+
         #[$stable_debug]
         impl fmt::Debug for $atomic_type {
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
index 4a763d4144edcbf8a044a2cc5a1b6e2ba9085241..70cfe57d15023b8ba67a38221f116abd6fe443df 100644 (file)
@@ -498,7 +498,7 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] SuperPredicatesOfItem(DefId),
     [] TraitDefOfItem(DefId),
     [] AdtDefOfItem(DefId),
-    [] IsDefaultImpl(DefId),
+    [] IsAutoImpl(DefId),
     [] ImplTraitRef(DefId),
     [] ImplPolarity(DefId),
     [] ClosureKind(DefId),
index 7913ea51df5a923bbf265bd2a611e31beab37426..0fb4e354a52d44b93a5f62a5ac709a0ae5941d15 100644 (file)
@@ -45,25 +45,10 @@ pub struct DepGraph {
 }
 
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct DepNodeIndex {
-    index: u32,
-}
-
-impl Idx for DepNodeIndex {
-    fn new(idx: usize) -> Self {
-        debug_assert!((idx & 0xFFFF_FFFF) == idx);
-        DepNodeIndex { index: idx as u32 }
-    }
-    fn index(self) -> usize {
-        self.index as usize
-    }
-}
+newtype_index!(DepNodeIndex);
 
 impl DepNodeIndex {
-    const INVALID: DepNodeIndex = DepNodeIndex {
-        index: ::std::u32::MAX,
-    };
+    const INVALID: DepNodeIndex = DepNodeIndex(::std::u32::MAX);
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
index 69d23504cdae00a818d855cc5ef5346c53c78ea7..428f154c1b66a98db8fd1ddb801679ebbcf3e945 100644 (file)
 use std::fmt;
 use std::u32;
 
-#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, Hash, Debug)]
-pub struct CrateNum(u32);
+newtype_index!(CrateNum
+    {
+        derive[Debug]
+        ENCODABLE = custom
 
-impl Idx for CrateNum {
-    fn new(value: usize) -> Self {
-        assert!(value < (u32::MAX) as usize);
-        CrateNum(value as u32)
-    }
-
-    fn index(self) -> usize {
-        self.0 as usize
-    }
-}
-
-/// Item definitions in the currently-compiled crate would have the CrateNum
-/// LOCAL_CRATE in their DefId.
-pub const LOCAL_CRATE: CrateNum = CrateNum(0);
+        /// Item definitions in the currently-compiled crate would have the CrateNum
+        /// LOCAL_CRATE in their DefId.
+        const LOCAL_CRATE = 0,
 
-/// Virtual crate for builtin macros
-// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s.
-pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(u32::MAX);
+        /// Virtual crate for builtin macros
+        // FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
+        // `CrateNum`s.
+        const BUILTIN_MACROS_CRATE = u32::MAX,
 
-/// A CrateNum value that indicates that something is wrong.
-pub const INVALID_CRATE: CrateNum = CrateNum(u32::MAX - 1);
+        /// A CrateNum value that indicates that something is wrong.
+        const INVALID_CRATE = u32::MAX - 1,
+    });
 
 impl CrateNum {
     pub fn new(x: usize) -> CrateNum {
@@ -93,20 +86,17 @@ fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
 ///
 /// Since the DefIndex is mostly treated as an opaque ID, you probably
 /// don't have to care about these ranges.
-#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
-           RustcDecodable, Hash, Copy)]
-pub struct DefIndex(u32);
+newtype_index!(DefIndex
+    {
+        DEBUG_FORMAT = custom,
 
-impl Idx for DefIndex {
-    fn new(value: usize) -> Self {
-        assert!(value < (u32::MAX) as usize);
-        DefIndex(value as u32)
-    }
+        /// The start of the "high" range of DefIndexes.
+        const DEF_INDEX_HI_START = 1 << 31,
 
-    fn index(self) -> usize {
-        self.0 as usize
-    }
-}
+        /// The crate root is always assigned index 0 by the AST Map code,
+        /// thanks to `NodeCollector::new`.
+        const CRATE_DEF_INDEX = 0,
+    });
 
 impl fmt::Debug for DefIndex {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -118,12 +108,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl DefIndex {
-    #[inline]
-    pub fn new(x: usize) -> DefIndex {
-        assert!(x < (u32::MAX as usize));
-        DefIndex(x as u32)
-    }
-
     #[inline]
     pub fn from_u32(x: u32) -> DefIndex {
         DefIndex(x)
@@ -162,13 +146,6 @@ pub fn from_array_index(i: usize, address_space: DefIndexAddressSpace) -> DefInd
     }
 }
 
-/// The start of the "high" range of DefIndexes.
-const DEF_INDEX_HI_START: DefIndex = DefIndex(1 << 31);
-
-/// The crate root is always assigned index 0 by the AST Map code,
-/// thanks to `NodeCollector::new`.
-pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
-
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 pub enum DefIndexAddressSpace {
     Low = 0,
index ae25924ab420ce454e996d9b0f5582851f1b0ada..c23a5fb1f7ebba3338c4aeb6343b617445b5cc81 100644 (file)
@@ -503,7 +503,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             // visit_enum_def() takes care of visiting the Item's NodeId
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
-        ItemDefaultImpl(_, ref trait_ref) => {
+        ItemAutoImpl(_, ref trait_ref) => {
             visitor.visit_id(item.id);
             visitor.visit_trait_ref(trait_ref)
         }
@@ -520,7 +520,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
         }
-        ItemTrait(_, ref generics, ref bounds, ref trait_item_refs) => {
+        ItemTrait(.., ref generics, ref bounds, ref trait_item_refs) => {
             visitor.visit_id(item.id);
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
index 3834852cac5a9411132e48c02ab69571eb685be4..a69d41d16033f4a0c5b657c7e92e4faa685b7ac7 100644 (file)
@@ -96,7 +96,7 @@ pub struct LoweringContext<'a> {
     exported_macros: Vec<hir::MacroDef>,
 
     trait_impls: BTreeMap<DefId, Vec<NodeId>>,
-    trait_default_impl: BTreeMap<DefId, NodeId>,
+    trait_auto_impl: BTreeMap<DefId, NodeId>,
 
     is_generator: bool,
 
@@ -146,7 +146,7 @@ pub fn lower_crate(sess: &Session,
         impl_items: BTreeMap::new(),
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
-        trait_default_impl: BTreeMap::new(),
+        trait_auto_impl: BTreeMap::new(),
         exported_macros: Vec::new(),
         catch_scopes: Vec::new(),
         loop_scopes: Vec::new(),
@@ -198,7 +198,7 @@ fn visit_item(&mut self, item: &'lcx Item) {
                     ItemKind::Union(_, ref generics) |
                     ItemKind::Enum(_, ref generics) |
                     ItemKind::Ty(_, ref generics) |
-                    ItemKind::Trait(_, ref generics, ..) => {
+                    ItemKind::Trait(_, _, ref generics, ..) => {
                         let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
                         let count = generics.lifetimes.len();
                         self.lctx.type_def_lifetime_params.insert(def_id, count);
@@ -284,7 +284,7 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
             bodies: self.bodies,
             body_ids,
             trait_impls: self.trait_impls,
-            trait_default_impl: self.trait_default_impl,
+            trait_auto_impl: self.trait_auto_impl,
         }
     }
 
@@ -1479,14 +1479,14 @@ fn lower_item_kind(&mut self,
                 let vdata = self.lower_variant_data(vdata);
                 hir::ItemUnion(vdata, self.lower_generics(generics))
             }
-            ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
+            ItemKind::AutoImpl(unsafety, ref trait_ref) => {
                 let trait_ref = self.lower_trait_ref(trait_ref);
 
                 if let Def::Trait(def_id) = trait_ref.path.def {
-                    self.trait_default_impl.insert(def_id, id);
+                    self.trait_auto_impl.insert(def_id, id);
                 }
 
-                hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
+                hir::ItemAutoImpl(self.lower_unsafety(unsafety),
                                      trait_ref)
             }
             ItemKind::Impl(unsafety,
@@ -1515,10 +1515,11 @@ fn lower_item_kind(&mut self,
                               self.lower_ty(ty),
                               new_impl_items)
             }
-            ItemKind::Trait(unsafety, ref generics, ref bounds, ref items) => {
+            ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_bounds(bounds);
                 let items = items.iter().map(|item| self.lower_trait_item_ref(item)).collect();
-                hir::ItemTrait(self.lower_unsafety(unsafety),
+                hir::ItemTrait(self.lower_is_auto(is_auto),
+                               self.lower_unsafety(unsafety),
                                self.lower_generics(generics),
                                bounds,
                                items)
@@ -1741,6 +1742,13 @@ fn lower_method_sig(&mut self, sig: &MethodSig) -> hir::MethodSig {
         }
     }
 
+    fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
+        match a {
+            IsAuto::Yes => hir::IsAuto::Yes,
+            IsAuto::No => hir::IsAuto::No,
+        }
+    }
+
     fn lower_unsafety(&mut self, u: Unsafety) -> hir::Unsafety {
         match u {
             Unsafety::Unsafe => hir::Unsafety::Unsafe,
index 2f4b62dcbf7824730dcc1b8f2ad1ef111e4271aa..5c1e74dcf43b9771065263be7b92c5452557a474 100644 (file)
@@ -71,7 +71,7 @@ pub(super) fn root(krate: &'hir Crate,
                 impl_items: _,
                 bodies: _,
                 trait_impls: _,
-                trait_default_impl: _,
+                trait_auto_impl: _,
                 body_ids: _,
             } = *krate;
 
index 9d49776749bcb05ce98f3377db7b34f03c5fee48..d8590c1de94e927ce1319b620e3064a21472a18d 100644 (file)
@@ -104,7 +104,7 @@ fn visit_item(&mut self, i: &'a Item) {
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into
         let def_data = match i.node {
-            ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
+            ItemKind::AutoImpl(..) | ItemKind::Impl(..) =>
                 DefPathData::Impl,
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
index 6418df479526c7506ceade48a62a10ad352cff4e..b30cc0b09c9ac6c316cdea2ba34e49ff46cf3c0d 100644 (file)
@@ -19,7 +19,7 @@
                   CRATE_DEF_INDEX};
 use ich::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::indexed_vec::IndexVec;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::stable_hasher::StableHasher;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 use session::CrateDisambiguator;
index a23658664dc6af61c1aba1cc702e197bcc30d0e6..1236602aecf55ab9c04b4e4c856e1fd900c35666 100644 (file)
@@ -474,16 +474,16 @@ pub fn trait_impls(&self, trait_did: DefId) -> &'hir [NodeId] {
         self.forest.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..])
     }
 
-    pub fn trait_default_impl(&self, trait_did: DefId) -> Option<NodeId> {
+    pub fn trait_auto_impl(&self, trait_did: DefId) -> Option<NodeId> {
         self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls));
 
         // NB: intentionally bypass `self.forest.krate()` so that we
         // do not trigger a read of the whole krate here
-        self.forest.krate.trait_default_impl.get(&trait_did).cloned()
+        self.forest.krate.trait_auto_impl.get(&trait_did).cloned()
     }
 
     pub fn trait_is_auto(&self, trait_did: DefId) -> bool {
-        self.trait_default_impl(trait_did).is_some()
+        self.trait_auto_impl(trait_did).is_some()
     }
 
     /// Get the attributes on the krate. This is preferable to
@@ -1140,7 +1140,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemUnion(..) => "union",
                 ItemTrait(..) => "trait",
                 ItemImpl(..) => "impl",
-                ItemDefaultImpl(..) => "default impl",
+                ItemAutoImpl(..) => "default impl",
             };
             format!("{} {}{}", item_str, path_str(), id_str)
         }
index e23e2acefb7328ca5a00e2023781b099c486cf91..c9b1d70e7b60df57d2ebecc1c137384714a6ad97 100644 (file)
@@ -499,7 +499,7 @@ pub struct Crate {
     pub impl_items: BTreeMap<ImplItemId, ImplItem>,
     pub bodies: BTreeMap<BodyId, Body>,
     pub trait_impls: BTreeMap<DefId, Vec<NodeId>>,
-    pub trait_default_impl: BTreeMap<DefId, NodeId>,
+    pub trait_auto_impl: BTreeMap<DefId, NodeId>,
 
     /// A list of the body ids written out in the order in which they
     /// appear in the crate. If you're going to process all the bodies
@@ -1500,6 +1500,13 @@ pub struct FnDecl {
     pub has_implicit_self: bool,
 }
 
+/// Is the trait definition an auto trait?
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAuto {
+    Yes,
+    No
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
@@ -1811,12 +1818,12 @@ pub enum Item_ {
     /// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
     ItemUnion(VariantData, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
+    ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec<TraitItemRef>),
 
-    // Default trait implementations
+    /// Auto trait implementations
     ///
     /// `impl Trait for .. {}`
-    ItemDefaultImpl(Unsafety, TraitRef),
+    ItemAutoImpl(Unsafety, TraitRef),
     /// An implementation, eg `impl<A> Trait for Foo { .. }`
     ItemImpl(Unsafety,
              ImplPolarity,
@@ -1844,7 +1851,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemUnion(..) => "union",
             ItemTrait(..) => "trait",
             ItemImpl(..) |
-            ItemDefaultImpl(..) => "item",
+            ItemAutoImpl(..) => "item",
         }
     }
 
@@ -1864,7 +1871,7 @@ pub fn generics(&self) -> Option<&Generics> {
             ItemEnum(_, ref generics) |
             ItemStruct(_, ref generics) |
             ItemUnion(_, ref generics) |
-            ItemTrait(_, ref generics, _, _) |
+            ItemTrait(_, _, ref generics, _, _) |
             ItemImpl(_, _, _, ref generics, _, _, _)=> generics,
             _ => return None
         })
index 24a0b5fcea9b84909603fed5f0ba4713a2cccfb5..7b4881f5486dc0b756ad233a7a16176a5a10e951 100644 (file)
@@ -660,7 +660,7 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.head(&visibility_qualified(&item.vis, "union"))?;
                 self.print_struct(struct_def, generics, item.name, item.span, true)?;
             }
-            hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
+            hir::ItemAutoImpl(unsafety, ref trait_ref) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
                 self.print_unsafety(unsafety)?;
@@ -717,9 +717,10 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 }
                 self.bclose(item.span)?;
             }
-            hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
+            hir::ItemTrait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
+                self.print_is_auto(is_auto)?;
                 self.print_unsafety(unsafety)?;
                 self.word_nbsp("trait")?;
                 self.print_name(item.name)?;
@@ -2274,6 +2275,13 @@ pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> {
             hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
         }
     }
+
+    pub fn print_is_auto(&mut self, s: hir::IsAuto) -> io::Result<()> {
+        match s {
+            hir::IsAuto::Yes => self.word_nbsp("auto"),
+            hir::IsAuto::No => Ok(()),
+        }
+    }
 }
 
 // Dup'ed from parse::classify, but adapted for the HIR.
index 5a36c42046244e47b7204a62e50281893b287714..f0fe6205fb6d0bfb29624df39c7cd28c64a07103 100644 (file)
@@ -898,7 +898,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             hir::ItemForeignMod(..)  |
             hir::ItemGlobalAsm(..)   |
             hir::ItemMod(..)         |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemTrait(..)       |
             hir::ItemImpl(..)        |
             hir::ItemTy(..)          |
@@ -944,8 +944,8 @@ fn hash_stable<W: StableHasherResult>(&self,
     ItemEnum(enum_def, generics),
     ItemStruct(variant_data, generics),
     ItemUnion(variant_data, generics),
-    ItemTrait(unsafety, generics, bounds, item_refs),
-    ItemDefaultImpl(unsafety, trait_ref),
+    ItemTrait(is_auto, unsafety, generics, bounds, item_refs),
+    ItemAutoImpl(unsafety, trait_ref),
     ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
 });
 
@@ -1126,6 +1126,10 @@ fn hash_stable<W: StableHasherResult>(&self,
     MutImmutable
 });
 
+impl_stable_hash_for!(enum hir::IsAuto {
+    Yes,
+    No
+});
 
 impl_stable_hash_for!(enum hir::Unsafety {
     Unsafe,
index 4bda89690b7a9b8a1c64498e4a6420295babb95c..05436201e7a6e56ab75eca6eb8bd18117cd90ffe 100644 (file)
@@ -62,7 +62,8 @@ fn hash_stable<W: StableHasherResult>(&self,
             mir::TerminatorKind::Drop { .. } |
             mir::TerminatorKind::DropAndReplace { .. } |
             mir::TerminatorKind::Yield { .. } |
-            mir::TerminatorKind::Call { .. } => false,
+            mir::TerminatorKind::Call { .. } |
+            mir::TerminatorKind::FalseEdges { .. } => false,
         };
 
         if hash_spans_unconditionally {
@@ -210,6 +211,12 @@ fn hash_stable<W: StableHasherResult>(&self,
                 target.hash_stable(hcx, hasher);
                 cleanup.hash_stable(hcx, hasher);
             }
+            mir::TerminatorKind::FalseEdges { ref real_target, ref imaginary_targets } => {
+                real_target.hash_stable(hcx, hasher);
+                for target in imaginary_targets {
+                    target.hash_stable(hcx, hasher);
+                }
+            }
         }
     }
 }
index 799e790b85fb576d5f27fbaa94d13276ba1edadf..fea4e283db13f524ba7835f4a5616bbfca8b484d 100644 (file)
@@ -364,6 +364,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             end_pos: _,
             ref lines,
             ref multibyte_chars,
+            ref non_narrow_chars,
         } = *self;
 
         name.hash_stable(hcx, hasher);
@@ -389,6 +390,12 @@ fn hash_stable<W: StableHasherResult>(&self,
         for &char_pos in multibyte_chars.iter() {
             stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
         }
+
+        let non_narrow_chars = non_narrow_chars.borrow();
+        non_narrow_chars.len().hash_stable(hcx, hasher);
+        for &char_pos in non_narrow_chars.iter() {
+            stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
+        }
     }
 }
 
@@ -408,3 +415,12 @@ fn stable_multibyte_char(mbc: ::syntax_pos::MultiByteChar,
 
     (pos.0 - filemap_start.0, bytes as u32)
 }
+
+fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
+                          filemap_start: ::syntax_pos::BytePos)
+                          -> (u32, u32) {
+    let pos = swc.pos();
+    let width = swc.width();
+
+    (pos.0 - filemap_start.0, width as u32)
+}
index 48d3017f5976388c7080ad6b7b8cb3c56c5789dd..e7627b110fae4c3a414958c7d60bd819cf3b20bc 100644 (file)
@@ -731,13 +731,13 @@ fn hash_stable<W: StableHasherResult>(&self,
             def_id: _,
             unsafety,
             paren_sugar,
-            has_default_impl,
+            has_auto_impl,
             def_path_hash,
         } = *self;
 
         unsafety.hash_stable(hcx, hasher);
         paren_sugar.hash_stable(hcx, hasher);
-        has_default_impl.hash_stable(hcx, hasher);
+        has_auto_impl.hash_stable(hcx, hasher);
         def_path_hash.hash_stable(hcx, hasher);
     }
 }
@@ -856,7 +856,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
         match self {
             &VtableImpl(ref table_impl) => table_impl.hash_stable(hcx, hasher),
-            &VtableDefaultImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher),
+            &VtableAutoImpl(ref table_def_impl) => table_def_impl.hash_stable(hcx, hasher),
             &VtableParam(ref table_param) => table_param.hash_stable(hcx, hasher),
             &VtableObject(ref table_obj) => table_obj.hash_stable(hcx, hasher),
             &VtableBuiltin(ref table_builtin) => table_builtin.hash_stable(hcx, hasher),
@@ -884,11 +884,11 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl<'gcx, N> HashStable<StableHashingContext<'gcx>>
-for traits::VtableDefaultImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
+for traits::VtableAutoImplData<N> where N: HashStable<StableHashingContext<'gcx>> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        let traits::VtableDefaultImplData {
+        let traits::VtableAutoImplData {
             trait_def_id,
             ref nested,
         } = *self;
index b4075f6973098eaa185ced9cfc92ac1b0d4e2be3..6c1478531f1472e0363a8d977b71d385a7532c87 100644 (file)
@@ -90,7 +90,7 @@ holds trivially because A==B.  However, we have now lost some
 flexibility, because perhaps the user intended for A and B to end up
 as different types and not the same type.
 
-Pictorally, what this does is to take two distinct variables with
+Pictorially, what this does is to take two distinct variables with
 (hopefully not completely) distinct type ranges and produce one with
 the intersection.
 
index 5d0a6ae98d7a69128805e5f9da48be49a2afa13c..e9916bd77e7582ea59880046bd41e4a0fe468653 100644 (file)
@@ -66,7 +66,7 @@
 use hir::def_id::DefId;
 use middle::region;
 use traits::{ObligationCause, ObligationCauseCode};
-use ty::{self, Region, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Region, Ty, TyCtxt, TypeFoldable, TypeVariants};
 use ty::error::TypeError;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
@@ -694,14 +694,17 @@ pub fn note_type_err(&self,
                          values: Option<ValuePairs<'tcx>>,
                          terr: &TypeError<'tcx>)
     {
-        let (expected_found, is_simple_error) = match values {
-            None => (None, false),
+        let (expected_found, exp_found, is_simple_error) = match values {
+            None => (None, None, false),
             Some(values) => {
-                let is_simple_error = match values {
+                let (is_simple_error, exp_found) = match values {
                     ValuePairs::Types(exp_found) => {
-                        exp_found.expected.is_primitive() && exp_found.found.is_primitive()
+                        let is_simple_err = exp_found.expected.is_primitive()
+                            && exp_found.found.is_primitive();
+
+                        (is_simple_err, Some(exp_found))
                     }
-                    _ => false,
+                    _ => (false, None),
                 };
                 let vals = match self.values_str(&values) {
                     Some((expected, found)) => Some((expected, found)),
@@ -711,12 +714,17 @@ pub fn note_type_err(&self,
                         return
                     }
                 };
-                (vals, is_simple_error)
+                (vals, exp_found, is_simple_error)
             }
         };
 
         let span = cause.span;
 
+        diag.span_label(span, terr.to_string());
+        if let Some((sp, msg)) = secondary_span {
+            diag.span_label(sp, msg);
+        }
+
         if let Some((expected, found)) = expected_found {
             match (terr, is_simple_error, expected == found) {
                 (&TypeError::Sorts(ref values), false, true) => {
@@ -725,18 +733,37 @@ pub fn note_type_err(&self,
                         &format!(" ({})", values.expected.sort_string(self.tcx)),
                         &format!(" ({})", values.found.sort_string(self.tcx)));
                 }
-                (_, false,  _) => {
+                (_, false, _) => {
+                    if let Some(exp_found) = exp_found {
+                        let (def_id, ret_ty) = match exp_found.found.sty {
+                            TypeVariants::TyFnDef(def, _) => {
+                                (Some(def), Some(self.tcx.fn_sig(def).output()))
+                            }
+                            _ => (None, None)
+                        };
+
+                        let exp_is_struct = match exp_found.expected.sty {
+                            TypeVariants::TyAdt(def, _) => def.is_struct(),
+                            _ => false
+                        };
+
+                        if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) {
+                            if exp_is_struct && exp_found.expected == ret_ty.0 {
+                                let message = format!(
+                                    "did you mean `{}(/* fields */)`?",
+                                    self.tcx.item_path_str(def_id)
+                                );
+                                diag.span_label(cause.span, message);
+                            }
+                        }
+                    }
+
                     diag.note_expected_found(&"type", expected, found);
                 }
                 _ => (),
             }
         }
 
-        diag.span_label(span, terr.to_string());
-        if let Some((sp, msg)) = secondary_span {
-            diag.span_label(sp, msg);
-        }
-
         self.note_error_origin(diag, &cause);
         self.check_and_note_conflicting_crates(diag, terr, span);
         self.tcx.note_and_explain_type_err(diag, terr, span);
index 0d02420457e6b76aa31963d6aba895c3aae31a94..6736751a5a2c225065b2c6baf966de387474a60a 100644 (file)
@@ -155,7 +155,10 @@ pub fn higher_ranked_match<T, U>(&mut self,
                                .filter(|&&r| !skol_resolution_map.contains_key(r))
                                .cloned()
                                .next()
-                               .expect("no representative region");
+                               .unwrap_or_else(|| {
+                                   bug!("no representative region for `{:?}` in `{:?}`",
+                                        skol, regions)
+                               });
 
                     (skol, representative)
                 })
index 5cf6aa350bdd547b83d03ae2d3d0d9bb547510e8..49f57d9aef50ec95a2b6a90f63f60d254550d35a 100644 (file)
@@ -19,6 +19,7 @@
 use graphviz as dot;
 
 use hir::def_id::DefIndex;
+use rustc_data_structures::indexed_vec::Idx;
 use ty;
 use middle::free_region::RegionRelations;
 use middle::region;
index 52dcbfdedef5d23a3ceec8af92095fac62e79a51..d648099d74d365e476619744d1462c40d0538448 100644 (file)
 
 use std::rc::Rc;
 
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 use hir::def_id::{CrateNum, LOCAL_CRATE};
 use hir::intravisit::{self, FnKind};
 use hir;
 use session::Session;
+#[cfg(stage0)]
 use std::ascii::AsciiExt;
 use std::hash;
 use syntax::ast;
@@ -463,6 +464,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
         }
     }
 
+    err.code(DiagnosticId::Lint(name));
+
     // Check for future incompatibility lints and issue a stronger warning.
     let lints = sess.lint_store.borrow();
     if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
index 259794e9d0ee4e30bdd1888f02a42f51abb401cd..a42ff543227a8f61e9e055de58fa46c740edf6fa 100644 (file)
@@ -562,7 +562,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
                 hir::ItemTrait(..) |
-                hir::ItemDefaultImpl(..) |
+                hir::ItemAutoImpl(..) |
                 hir::ItemImpl(..) => self.tcx.sess.codemap().def_span(item.span),
                 _ => item.span,
             };
index 679c4f17a6c03f55cc589b0f90604042a0697014..a38b37ff745f7d1b90244358f76ac1fe53518fce 100644 (file)
@@ -211,6 +211,7 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     CharImplItem,                    "char",                    char_impl;
     StrImplItem,                     "str",                     str_impl;
     SliceImplItem,                   "slice",                   slice_impl;
+    SliceU8ImplItem,                 "slice_u8",                slice_u8_impl;
     ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
     MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
     I8ImplItem,                      "i8",                      i8_impl;
index 2037bc01a5bc94a5bfe513a48f1b865e5fb3b0b9..d5f26d1117c5be8fc3ae940df6e25a3c21f383df 100644 (file)
@@ -270,7 +270,7 @@ fn propagate_node(&mut self, node: &hir_map::Node<'tcx>,
                     hir::ItemMod(..) | hir::ItemForeignMod(..) |
                     hir::ItemImpl(..) | hir::ItemTrait(..) |
                     hir::ItemStruct(..) | hir::ItemEnum(..) |
-                    hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
+                    hir::ItemUnion(..) | hir::ItemAutoImpl(..) |
                     hir::ItemGlobalAsm(..) => {}
                 }
             }
index e725592ff99e6877ee3ac2662c6aaf10e77bfb2c..89707839144ccdffb2a22be63a246f0f03012d8f 100644 (file)
@@ -158,8 +158,8 @@ pub struct BlockRemainder {
 
 newtype_index!(FirstStatementIndex
     {
-        DEBUG_FORMAT = "{}",
-        MAX = SCOPE_DATA_REMAINDER_MAX,
+        pub idx
+        MAX = SCOPE_DATA_REMAINDER_MAX
     });
 
 impl From<ScopeData> for Scope {
index ee0e580920e1f2ff958312be1cf651eae3aac125..4c7ce4c09e25b4372b935ad8e4d845f33635d108 100644 (file)
@@ -313,7 +313,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemExternCrate(_) |
             hir::ItemUse(..) |
             hir::ItemMod(..) |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemForeignMod(..) |
             hir::ItemGlobalAsm(..) => {
                 // These sorts of items have no lifetime parameters at all.
@@ -332,7 +332,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             hir::ItemEnum(_, ref generics) |
             hir::ItemStruct(_, ref generics) |
             hir::ItemUnion(_, ref generics) |
-            hir::ItemTrait(_, ref generics, ..) |
+            hir::ItemTrait(_, _, ref generics, ..) |
             hir::ItemImpl(_, _, _, ref generics, ..) => {
                 // These kinds of items have only early bound lifetime parameters.
                 let mut index = if let hir::ItemTrait(..) = item.node {
@@ -688,7 +688,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
             hir::ItemUnion(_, ref generics) |
             hir::ItemEnum(_, ref generics) |
             hir::ItemTy(_, ref generics) |
-            hir::ItemTrait(_, ref generics, ..) => {
+            hir::ItemTrait(_, _, ref generics, ..) => {
                 let result = object_lifetime_defaults_for_item(hir_map, generics);
 
                 // Debugging aid.
@@ -844,7 +844,7 @@ fn visit_early_late<F>(&mut self,
                 index += 1; // Self comes first.
             }
             match parent.node {
-                hir::ItemTrait(_, ref generics, ..) |
+                hir::ItemTrait(_, _, ref generics, ..) |
                 hir::ItemImpl(_, _, _, ref generics, ..) => {
                     index += (generics.lifetimes.len() + generics.ty_params.len()) as u32;
                 }
index c4a33bb07cdf21d4fd067dfbb17872d04d1f642a..2fc27de137faa13de7c59eb400e13ddc7e510711 100644 (file)
@@ -682,6 +682,11 @@ pub enum TerminatorKind<'tcx> {
 
     /// Indicates the end of the dropping of a generator
     GeneratorDrop,
+
+    FalseEdges {
+        real_target: BasicBlock,
+        imaginary_targets: Vec<BasicBlock>
+    },
 }
 
 impl<'tcx> Terminator<'tcx> {
@@ -731,6 +736,11 @@ pub fn successors(&self) -> Cow<[BasicBlock]> {
             }
             Assert { target, cleanup: Some(unwind), .. } => vec![target, unwind].into_cow(),
             Assert { ref target, .. } => slice::ref_slice(target).into_cow(),
+            FalseEdges { ref real_target, ref imaginary_targets } => {
+                let mut s = vec![*real_target];
+                s.extend_from_slice(imaginary_targets);
+                s.into_cow()
+            }
         }
     }
 
@@ -757,7 +767,12 @@ pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
                 vec![target]
             }
             Assert { ref mut target, cleanup: Some(ref mut unwind), .. } => vec![target, unwind],
-            Assert { ref mut target, .. } => vec![target]
+            Assert { ref mut target, .. } => vec![target],
+            FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
+                let mut s = vec![real_target];
+                s.extend(imaginary_targets.iter_mut());
+                s
+            }
         }
     }
 }
@@ -874,7 +889,8 @@ pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
                 }
 
                 write!(fmt, ")")
-            }
+            },
+            FalseEdges { .. } => write!(fmt, "falseEdges")
         }
     }
 
@@ -910,7 +926,12 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
             }
             Assert { cleanup: None, .. } => vec!["".into()],
             Assert { .. } =>
-                vec!["success".into_cow(), "unwind".into_cow()]
+                vec!["success".into_cow(), "unwind".into_cow()],
+            FalseEdges { ref imaginary_targets, .. } => {
+                let mut l = vec!["real".into()];
+                l.resize(imaginary_targets.len() + 1, "imaginary".into());
+                l
+            }
         }
     }
 }
@@ -1531,6 +1552,7 @@ pub struct Constant<'tcx> {
 
 newtype_index!(Promoted { DEBUG_FORMAT = "promoted[{}]" });
 
+
 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum Literal<'tcx> {
     Value {
@@ -1878,6 +1900,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             Resume => Resume,
             Return => Return,
             Unreachable => Unreachable,
+            FalseEdges { real_target, ref imaginary_targets } =>
+                FalseEdges { real_target, imaginary_targets: imaginary_targets.clone() }
         };
         Terminator {
             source_info: self.source_info,
@@ -1917,7 +1941,8 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             Resume |
             Return |
             GeneratorDrop |
-            Unreachable => false
+            Unreachable |
+            FalseEdges { .. } => false
         }
     }
 }
index 2d9d3643ff69d69aafdf498d33447cbc4606bb75..00863abc84deeb61b4e5652aadbdb399b34895fc 100644 (file)
@@ -488,8 +488,15 @@ fn super_terminator_kind(&mut self,
                         self.visit_operand(value, source_location);
                         self.visit_branch(block, resume);
                         drop.map(|t| self.visit_branch(block, t));
+
                     }
 
+                    TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
+                        self.visit_branch(block, real_target);
+                        for target in imaginary_targets {
+                            self.visit_branch(block, *target);
+                        }
+                    }
                 }
             }
 
index 0f8312abc3f9f10f7f75a0fe6d4df1dd16866ee3..c4fc30429e0aabe965516f3fcd8c68d186c57a5f 100644 (file)
@@ -155,7 +155,7 @@ pub fn extension(&self) -> &'static str {
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum ErrorOutputType {
     HumanReadable(ColorConfig),
-    Json,
+    Json(bool),
     Short(ColorConfig),
 }
 
@@ -410,7 +410,7 @@ pub struct OutputFilenames {
     outputs
 });
 
-pub const RUST_CGU_EXT: &str = "rust-cgu";
+pub const RUST_CGU_EXT: &str = "rcgu";
 
 impl OutputFilenames {
     pub fn path(&self, flavor: OutputType) -> PathBuf {
@@ -1433,7 +1433,8 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
     let error_format = if matches.opts_present(&["error-format".to_owned()]) {
         match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
             Some("human") => ErrorOutputType::HumanReadable(color),
-            Some("json")  => ErrorOutputType::Json,
+            Some("json")  => ErrorOutputType::Json(false),
+            Some("pretty-json") => ErrorOutputType::Json(true),
             Some("short") => ErrorOutputType::Short(color),
 
             None => ErrorOutputType::HumanReadable(color),
@@ -1474,6 +1475,11 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
 
     let debugging_opts = build_debugging_options(matches, error_format);
 
+    if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
+        early_error(ErrorOutputType::Json(false),
+                    "--error-format=pretty-json is unstable");
+    }
+
     let mut output_types = BTreeMap::new();
     if !debugging_opts.parse_only {
         for list in matches.opt_strs("emit") {
@@ -2254,46 +2260,46 @@ fn test_search_paths_tracking_hash_different_values() {
         let mut v5 = super::basic_options();
 
         // Reference
-        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Native changed
-        v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Crate changed
-        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Dependency changed
-        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // Framework changed
-        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
 
         // All changed
-        v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json);
+        v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json(false));
 
         assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
@@ -2316,29 +2322,29 @@ fn test_search_paths_tracking_hash_different_order() {
         let mut v4 = super::basic_options();
 
         // Reference
-        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
-        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
-        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
-        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
-        v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
+        v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+        v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+        v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+        v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+        v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
 
         assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
index be35cc8e4a1c0e834d63bfc67935f5dfd433c37c..39cf50787effedeb7353e5fbf462ac03551bf1b0 100644 (file)
@@ -24,7 +24,7 @@
 use util::common::{duration_to_secs_str, ErrorReported};
 
 use syntax::ast::NodeId;
-use errors::{self, DiagnosticBuilder};
+use errors::{self, DiagnosticBuilder, DiagnosticId};
 use errors::emitter::{Emitter, EmitterWriter};
 use syntax::json::JsonEmitter;
 use syntax::feature_gate;
@@ -187,7 +187,7 @@ pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
     pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                               sp: S,
                                                               msg: &str,
-                                                              code: &str)
+                                                              code: DiagnosticId)
                                                               -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_warn_with_code(sp, msg, code)
     }
@@ -203,7 +203,7 @@ pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
-                                                             code: &str)
+                                                             code: DiagnosticId)
                                                              -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
@@ -211,7 +211,11 @@ pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_err(msg)
     }
-    pub fn struct_err_with_code<'a>(&'a self, msg: &str, code: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_err_with_code<'a>(
+        &'a self,
+        msg: &str,
+        code: DiagnosticId,
+    ) -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_err_with_code(msg, code)
     }
     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
@@ -223,7 +227,7 @@ pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
     pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                                sp: S,
                                                                msg: &str,
-                                                               code: &str)
+                                                               code: DiagnosticId)
                                                                -> DiagnosticBuilder<'a> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
@@ -234,7 +238,12 @@ pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         panic!(self.diagnostic().span_fatal(sp, msg))
     }
-    pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) -> ! {
+    pub fn span_fatal_with_code<S: Into<MultiSpan>>(
+        &self,
+        sp: S,
+        msg: &str,
+        code: DiagnosticId,
+    ) -> ! {
         panic!(self.diagnostic().span_fatal_with_code(sp, msg, code))
     }
     pub fn fatal(&self, msg: &str) -> ! {
@@ -250,7 +259,7 @@ pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg:
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().span_err(sp, msg)
     }
-    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.diagnostic().span_err_with_code(sp, &msg, code)
     }
     pub fn err(&self, msg: &str) {
@@ -283,7 +292,7 @@ pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorReported>
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().span_warn(sp, msg)
     }
-    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.diagnostic().span_warn_with_code(sp, msg, code)
     }
     pub fn warn(&self, msg: &str) {
@@ -363,7 +372,7 @@ fn diag_once<'a, 'b>(&'a self,
         match self.opts.error_format {
             // when outputting JSON for tool consumption, the tool might want
             // the duplicates
-            config::ErrorOutputType::Json => {
+            config::ErrorOutputType::Json(_) => {
                 do_method()
             },
             _ => {
@@ -727,11 +736,11 @@ pub fn build_session_with_codemap(sopts: config::Options,
         (config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
             Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false))
         }
-        (config::ErrorOutputType::Json, None) => {
-            Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
+        (config::ErrorOutputType::Json(pretty), None) => {
+            Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(), pretty))
         }
-        (config::ErrorOutputType::Json, Some(dst)) => {
-            Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone()))
+        (config::ErrorOutputType::Json(pretty), Some(dst)) => {
+            Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(), pretty))
         }
         (config::ErrorOutputType::Short(color_config), None) => {
             Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true))
@@ -909,7 +918,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false))
         }
-        config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
+        config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
         config::ErrorOutputType::Short(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, true))
         }
@@ -924,7 +933,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, false))
         }
-        config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
+        config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
         config::ErrorOutputType::Short(color_config) => {
             Box::new(EmitterWriter::stderr(color_config, None, true))
         }
index 1fddb1864175f0752b2043d7101dbb9f3edcd8f7..c08fe187f99bfee2e56b95c5d5a7ea4d77b68468 100644 (file)
@@ -288,11 +288,11 @@ pub enum Vtable<'tcx, N> {
     /// Vtable identifying a particular impl.
     VtableImpl(VtableImplData<'tcx, N>),
 
-    /// Vtable for default trait implementations
+    /// Vtable for auto trait implementations
     /// This carries the information and nested obligations with regards
-    /// to a default implementation for a trait `Trait`. The nested obligations
+    /// to an auto implementation for a trait `Trait`. The nested obligations
     /// ensure the trait implementation holds for all the constituent types.
-    VtableDefaultImpl(VtableDefaultImplData<N>),
+    VtableAutoImpl(VtableAutoImplData<N>),
 
     /// Successful resolution to an obligation provided by the caller
     /// for some type parameter. The `Vec<N>` represents the
@@ -354,7 +354,7 @@ pub struct VtableClosureData<'tcx, N> {
 }
 
 #[derive(Clone)]
-pub struct VtableDefaultImplData<N> {
+pub struct VtableAutoImplData<N> {
     pub trait_def_id: DefId,
     pub nested: Vec<N>
 }
@@ -758,7 +758,7 @@ pub fn nested_obligations(self) -> Vec<N> {
             VtableImpl(i) => i.nested,
             VtableParam(n) => n,
             VtableBuiltin(i) => i.nested,
-            VtableDefaultImpl(d) => d.nested,
+            VtableAutoImpl(d) => d.nested,
             VtableClosure(c) => c.nested,
             VtableGenerator(c) => c.nested,
             VtableObject(d) => d.nested,
@@ -771,7 +771,7 @@ fn nested_obligations_mut(&mut self) -> &mut Vec<N> {
             &mut VtableImpl(ref mut i) => &mut i.nested,
             &mut VtableParam(ref mut n) => n,
             &mut VtableBuiltin(ref mut i) => &mut i.nested,
-            &mut VtableDefaultImpl(ref mut d) => &mut d.nested,
+            &mut VtableAutoImpl(ref mut d) => &mut d.nested,
             &mut VtableGenerator(ref mut c) => &mut c.nested,
             &mut VtableClosure(ref mut c) => &mut c.nested,
             &mut VtableObject(ref mut d) => &mut d.nested,
@@ -795,7 +795,7 @@ pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M {
                 vtable_base: o.vtable_base,
                 nested: o.nested.into_iter().map(f).collect(),
             }),
-            VtableDefaultImpl(d) => VtableDefaultImpl(VtableDefaultImplData {
+            VtableAutoImpl(d) => VtableAutoImpl(VtableAutoImplData {
                 trait_def_id: d.trait_def_id,
                 nested: d.nested.into_iter().map(f).collect(),
             }),
index 0fa1b32ceb7f66931276e1c3d62d162f6474feb5..9c56df058c3dd0fd2a1bb4dff47e8b45b9f52b96 100644 (file)
@@ -1116,7 +1116,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                 // projection. And the projection where clause is handled
                 // in `assemble_candidates_from_param_env`.
             }
-            super::VtableDefaultImpl(..) |
+            super::VtableAutoImpl(..) |
             super::VtableBuiltin(..) => {
                 // These traits have no associated types.
                 span_bug!(
@@ -1182,7 +1182,7 @@ fn confirm_select_candidate<'cx, 'gcx, 'tcx>(
             confirm_fn_pointer_candidate(selcx, obligation, data),
         super::VtableObject(_) =>
             confirm_object_candidate(selcx, obligation, obligation_trait_ref),
-        super::VtableDefaultImpl(..) |
+        super::VtableAutoImpl(..) |
         super::VtableParam(..) |
         super::VtableBuiltin(..) =>
             // we don't create Select candidates with this kind of resolution
index 6c573acf07d63270c72a761537391fedb4f4b227..7716770d318bae1b47bf6d4d763240b73c199607 100644 (file)
@@ -25,9 +25,9 @@
 use super::Selection;
 use super::SelectionResult;
 use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, VtableGenerator,
-            VtableFnPointer, VtableObject, VtableDefaultImpl};
+            VtableFnPointer, VtableObject, VtableAutoImpl};
 use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableGeneratorData,
-            VtableClosureData, VtableDefaultImplData, VtableFnPointerData};
+            VtableClosureData, VtableAutoImplData, VtableFnPointerData};
 use super::util;
 
 use dep_graph::{DepNodeIndex, DepKind};
@@ -225,7 +225,7 @@ enum SelectionCandidate<'tcx> {
     BuiltinCandidate { has_nested: bool },
     ParamCandidate(ty::PolyTraitRef<'tcx>),
     ImplCandidate(DefId),
-    DefaultImplCandidate(DefId),
+    AutoImplCandidate(DefId),
 
     /// This is a trait matching with a projected type as `Self`, and
     /// we found an applicable bound in the trait definition.
@@ -260,7 +260,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                 }
             }
             ImplCandidate(def_id) => ImplCandidate(def_id),
-            DefaultImplCandidate(def_id) => DefaultImplCandidate(def_id),
+            AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
             ProjectionCandidate => ProjectionCandidate,
             FnPointerCandidate => FnPointerCandidate,
             ObjectCandidate => ObjectCandidate,
@@ -910,7 +910,7 @@ pub fn coinductive_match<I>(&mut self, cycle: I) -> bool
     fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
         let result = match predicate {
             ty::Predicate::Trait(ref data) => {
-                self.tcx().trait_has_default_impl(data.def_id())
+                self.tcx().trait_is_auto(data.def_id())
             }
             _ => {
                 false
@@ -1368,10 +1368,10 @@ fn assemble_candidates<'o>(&mut self,
 
         self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
         self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
-        // Default implementations have lower priority, so we only
+        // Auto implementations have lower priority, so we only
         // consider triggering a default if there is no other impl that can apply.
         if candidates.vec.is_empty() {
-            self.assemble_candidates_from_default_impls(obligation, &mut candidates)?;
+            self.assemble_candidates_from_auto_impls(obligation, &mut candidates)?;
         }
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
@@ -1686,18 +1686,18 @@ fn assemble_candidates_from_impls(&mut self,
         Ok(())
     }
 
-    fn assemble_candidates_from_default_impls(&mut self,
+    fn assemble_candidates_from_auto_impls(&mut self,
                                               obligation: &TraitObligation<'tcx>,
                                               candidates: &mut SelectionCandidateSet<'tcx>)
                                               -> Result<(), SelectionError<'tcx>>
     {
         // OK to skip binder here because the tests we do below do not involve bound regions
         let self_ty = *obligation.self_ty().skip_binder();
-        debug!("assemble_candidates_from_default_impls(self_ty={:?})", self_ty);
+        debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty);
 
         let def_id = obligation.predicate.def_id();
 
-        if self.tcx().trait_has_default_impl(def_id) {
+        if self.tcx().trait_is_auto(def_id) {
             match self_ty.sty {
                 ty::TyDynamic(..) => {
                     // For object types, we don't know what the closed
@@ -1728,11 +1728,11 @@ fn assemble_candidates_from_default_impls(&mut self,
                     // this path.
                 }
                 ty::TyInfer(ty::TyVar(_)) => {
-                    // the defaulted impl might apply, we don't know
+                    // the auto impl might apply, we don't know
                     candidates.ambiguous = true;
                 }
                 _ => {
-                    candidates.vec.push(DefaultImplCandidate(def_id.clone()))
+                    candidates.vec.push(AutoImplCandidate(def_id.clone()))
                 }
             }
         }
@@ -1933,7 +1933,7 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
         match other.candidate {
             ObjectCandidate |
             ParamCandidate(_) | ProjectionCandidate => match victim.candidate {
-                DefaultImplCandidate(..) => {
+                AutoImplCandidate(..) => {
                     bug!(
                         "default implementations shouldn't be recorded \
                          when there are other valid candidates");
@@ -2282,9 +2282,9 @@ fn confirm_candidate(&mut self,
                 Ok(VtableParam(obligations))
             }
 
-            DefaultImplCandidate(trait_def_id) => {
-                let data = self.confirm_default_impl_candidate(obligation, trait_def_id);
-                Ok(VtableDefaultImpl(data))
+            AutoImplCandidate(trait_def_id) => {
+                let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
+                Ok(VtableAutoImpl(data))
             }
 
             ImplCandidate(impl_def_id) => {
@@ -2417,29 +2417,29 @@ fn confirm_builtin_candidate(&mut self,
     ///
     /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
     /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
-    fn confirm_default_impl_candidate(&mut self,
+    fn confirm_auto_impl_candidate(&mut self,
                                       obligation: &TraitObligation<'tcx>,
                                       trait_def_id: DefId)
-                                      -> VtableDefaultImplData<PredicateObligation<'tcx>>
+                                      -> VtableAutoImplData<PredicateObligation<'tcx>>
     {
-        debug!("confirm_default_impl_candidate({:?}, {:?})",
+        debug!("confirm_auto_impl_candidate({:?}, {:?})",
                obligation,
                trait_def_id);
 
         // binder is moved below
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
         let types = self.constituent_types_for_ty(self_ty);
-        self.vtable_default_impl(obligation, trait_def_id, ty::Binder(types))
+        self.vtable_auto_impl(obligation, trait_def_id, ty::Binder(types))
     }
 
-    /// See `confirm_default_impl_candidate`
-    fn vtable_default_impl(&mut self,
+    /// See `confirm_auto_impl_candidate`
+    fn vtable_auto_impl(&mut self,
                            obligation: &TraitObligation<'tcx>,
                            trait_def_id: DefId,
                            nested: ty::Binder<Vec<Ty<'tcx>>>)
-                           -> VtableDefaultImplData<PredicateObligation<'tcx>>
+                           -> VtableAutoImplData<PredicateObligation<'tcx>>
     {
-        debug!("vtable_default_impl: nested={:?}", nested);
+        debug!("vtable_auto_impl: nested={:?}", nested);
 
         let cause = obligation.derived_cause(BuiltinDerivedObligation);
         let mut obligations = self.collect_predicates_for_types(
@@ -2465,9 +2465,9 @@ fn vtable_default_impl(&mut self,
 
         obligations.extend(trait_obligations);
 
-        debug!("vtable_default_impl: obligations={:?}", obligations);
+        debug!("vtable_auto_impl: obligations={:?}", obligations);
 
-        VtableDefaultImplData {
+        VtableAutoImplData {
             trait_def_id,
             nested: obligations
         }
index 19ed03aa14917b8e67e5b77c0e49d7e89471e663..fd93aa162a612b291f04c338c4436916c1c1f95b 100644 (file)
@@ -47,7 +47,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             super::VtableImpl(ref v) =>
                 write!(f, "{:?}", v),
 
-            super::VtableDefaultImpl(ref t) =>
+            super::VtableAutoImpl(ref t) =>
                 write!(f, "{:?}", t),
 
             super::VtableClosure(ref d) =>
@@ -104,9 +104,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableDefaultImplData<N> {
+impl<'tcx, N: fmt::Debug> fmt::Debug for traits::VtableAutoImplData<N> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "VtableDefaultImplData(trait_def_id={:?}, nested={:?})",
+        write!(f, "VtableAutoImplData(trait_def_id={:?}, nested={:?})",
                self.trait_def_id,
                self.nested)
     }
@@ -292,7 +292,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                     })
                 })
             }
-            traits::VtableDefaultImpl(t) => Some(traits::VtableDefaultImpl(t)),
+            traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
             traits::VtableGenerator(traits::VtableGeneratorData {
                 closure_def_id,
                 substs,
@@ -407,9 +407,9 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableAutoImplData<N> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        traits::VtableDefaultImplData {
+        traits::VtableAutoImplData {
             trait_def_id: self.trait_def_id,
             nested: self.nested.fold_with(folder),
         }
@@ -463,7 +463,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         match *self {
             traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
-            traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
+            traits::VtableAutoImpl(ref t) => traits::VtableAutoImpl(t.fold_with(folder)),
             traits::VtableGenerator(ref d) => {
                 traits::VtableGenerator(d.fold_with(folder))
             }
@@ -482,7 +482,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         match *self {
             traits::VtableImpl(ref v) => v.visit_with(visitor),
-            traits::VtableDefaultImpl(ref t) => t.visit_with(visitor),
+            traits::VtableAutoImpl(ref t) => t.visit_with(visitor),
             traits::VtableGenerator(ref d) => d.visit_with(visitor),
             traits::VtableClosure(ref d) => d.visit_with(visitor),
             traits::VtableFnPointer(ref d) => d.visit_with(visitor),
index 761e7259204bff0b32ff75ff7fab3883431bfd4f..73fdbfe8831e3102156e9a8bc259713767581279 100644 (file)
@@ -99,6 +99,26 @@ pub fn trans_apply_param_substs<T>(self,
         let substituted = self.erase_regions(&substituted);
         AssociatedTypeNormalizer::new(self).fold(&substituted)
     }
+
+    pub fn trans_apply_param_substs_env<T>(
+        self,
+        param_substs: &Substs<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: &T,
+    ) -> T
+    where
+        T: TransNormalize<'tcx>,
+    {
+        debug!(
+            "apply_param_substs_env(param_substs={:?}, value={:?}, param_env={:?})",
+            param_substs,
+            value,
+            param_env,
+        );
+        let substituted = value.subst(self, param_substs);
+        let substituted = self.erase_regions(&substituted);
+        AssociatedTypeNormalizerEnv::new(self, param_env).fold(&substituted)
+    }
 }
 
 struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
@@ -134,6 +154,40 @@ fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
     }
 }
 
+struct AssociatedTypeNormalizerEnv<'a, 'gcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
+    param_env: ty::ParamEnv<'gcx>,
+}
+
+impl<'a, 'gcx> AssociatedTypeNormalizerEnv<'a, 'gcx> {
+    fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>, param_env: ty::ParamEnv<'gcx>) -> Self {
+        Self { tcx, param_env }
+    }
+
+    fn fold<T: TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
+        if !value.has_projections() {
+            value.clone()
+        } else {
+            value.fold_with(self)
+        }
+    }
+}
+
+impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizerEnv<'a, 'gcx> {
+    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
+        if !ty.has_projections() {
+            ty
+        } else {
+            debug!("AssociatedTypeNormalizerEnv: ty={:?}", ty);
+            self.tcx.normalize_associated_type_in_env(&ty, self.param_env)
+        }
+    }
+}
+
 // Implement DepTrackingMapConfig for `trait_cache`
 pub struct TraitSelectionCache<'tcx> {
     data: PhantomData<&'tcx ()>
index 442c79393fdc7f3000af293267d08d40cad267dc..6ea953c3f7375bf5f055c35563e5f4020837d666 100644 (file)
@@ -144,7 +144,7 @@ pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
         } else {
             let ty = tcx.type_of(def_id);
-            let item_type = tcx.trans_apply_param_substs(substs, &ty);
+            let item_type = tcx.trans_apply_param_substs_env(substs, param_env, &ty);
 
             let def = match item_type.sty {
                 ty::TyFnDef(..) if {
@@ -256,7 +256,7 @@ fn resolve_associated_item<'a, 'tcx>(
                 None
             }
         }
-        traits::VtableDefaultImpl(..) | traits::VtableParam(..) => None
+        traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
     }
 }
 
index 98c55331f8a1094576a8eeccd3a277608ab20518..24c19bfc3f3f00f7ab78ad843457db824fde07b9 100644 (file)
@@ -218,7 +218,7 @@ fn push_impl_path<T>(self,
 
         // Always use types for non-local impls, where types are always
         // available, and filename/line-number is mostly uninteresting.
-        let use_types = !self.is_default_impl(impl_def_id) && (!impl_def_id.is_local() || {
+        let use_types = !self.is_auto_impl(impl_def_id) && (!impl_def_id.is_local() || {
             // Otherwise, use filename/line-number if forced.
             let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
             !force_no_types
index c77175bbbdcc9663fcb51a71d0e044806d2ccc04..7d8586741fb156557ea7bdd3de6a7afdb26c0b52 100644 (file)
     /// True if this is a foreign item (i.e., linked via `extern { ... }`).
     [] fn is_foreign_item: IsForeignItem(DefId) -> bool,
 
-    /// True if this is a default impl (aka impl Foo for ..)
-    [] fn is_default_impl: IsDefaultImpl(DefId) -> bool,
+    /// True if this is an auto impl (aka impl Foo for ..)
+    [] fn is_auto_impl: IsAutoImpl(DefId) -> bool,
 
     /// Get a map with the variance of every item; use `item_variance`
     /// instead.
index 2f10b9e8b9a833729da1f712a0e7aa28d54ef79b..cc698cf03da98913131c6d88a51551d8510e8984 100644 (file)
@@ -731,7 +731,7 @@ macro_rules! force {
         DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
         DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
         DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
-        DepKind::IsDefaultImpl => { force!(is_default_impl, def_id!()); }
+        DepKind::IsAutoImpl => { force!(is_auto_impl, def_id!()); }
         DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
         DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
         DepKind::ClosureKind => { force!(closure_kind, def_id!()); }
index ee1668d6fa25f6616d9f7eb9fec21eac4dde0e6b..0deababd21829d5fd045e794351f67983a8ec679 100644 (file)
@@ -1326,6 +1326,12 @@ pub struct AdtFlags: u32 {
         const IS_FUNDAMENTAL      = 1 << 2;
         const IS_UNION            = 1 << 3;
         const IS_BOX              = 1 << 4;
+        /// Indicates whether this abstract data type will be expanded on in future (new
+        /// fields/variants) and as such, whether downstream crates must match exhaustively on the
+        /// fields/variants of this data type.
+        ///
+        /// See RFC 2008 (https://github.com/rust-lang/rfcs/pull/2008).
+        const IS_NON_EXHAUSTIVE   = 1 << 5;
     }
 }
 
@@ -1526,6 +1532,9 @@ fn new(tcx: TyCtxt,
         if Some(did) == tcx.lang_items().owned_box() {
             flags = flags | AdtFlags::IS_BOX;
         }
+        if tcx.has_attr(did, "non_exhaustive") {
+            flags = flags | AdtFlags::IS_NON_EXHAUSTIVE;
+        }
         match kind {
             AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
             AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
@@ -1554,6 +1563,11 @@ pub fn is_enum(&self) -> bool {
         self.flags.intersects(AdtFlags::IS_ENUM)
     }
 
+    #[inline]
+    pub fn is_non_exhaustive(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_NON_EXHAUSTIVE)
+    }
+
     /// Returns the kind of the ADT - Struct or Enum.
     #[inline]
     pub fn adt_kind(&self) -> AdtKind {
@@ -2308,8 +2322,11 @@ pub fn has_attr(self, did: DefId, attr: &str) -> bool {
         self.get_attrs(did).iter().any(|item| item.check_name(attr))
     }
 
-    pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool {
-        self.trait_def(trait_def_id).has_default_impl
+    /// Returns true if this is an `auto trait`.
+    ///
+    /// NB. For a limited time, also returns true if `impl Trait for .. { }` is in the code-base.
+    pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
+        self.trait_def(trait_def_id).has_auto_impl
     }
 
     pub fn generator_layout(self, def_id: DefId) -> &'tcx GeneratorLayout<'tcx> {
index e0b05c2ba39ac7ad3dab4283363db1061bbdcb18..0fbf9f1bd587bffc070f41544d43532dc455089c 100644 (file)
@@ -34,7 +34,7 @@ pub struct TraitDef {
     /// be usable with the sugar (or without it).
     pub paren_sugar: bool,
 
-    pub has_default_impl: bool,
+    pub has_auto_impl: bool,
 
     /// The ICH of this trait's DefPath, cached here so it doesn't have to be
     /// recomputed all the time.
@@ -51,14 +51,14 @@ impl<'a, 'gcx, 'tcx> TraitDef {
     pub fn new(def_id: DefId,
                unsafety: hir::Unsafety,
                paren_sugar: bool,
-               has_default_impl: bool,
+               has_auto_impl: bool,
                def_path_hash: DefPathHash)
                -> TraitDef {
         TraitDef {
             def_id,
             paren_sugar,
             unsafety,
-            has_default_impl,
+            has_auto_impl,
             def_path_hash,
         }
     }
index eafb4c5c80078c6cc8a91bf73786369f0e2384c2..352184c1efa76965fb5959224dcedff7b4b176f4 100644 (file)
@@ -177,9 +177,13 @@ fn attrs(&self) -> Vec<Attribute> {
 
         let no_mangle = Symbol::intern("no_mangle");
         let no_mangle = self.cx.meta_word(self.span, no_mangle);
+
+        let special = Symbol::intern("rustc_std_internal_symbol");
+        let special = self.cx.meta_word(self.span, special);
         vec![
             self.cx.attribute(self.span, linkage),
             self.cx.attribute(self.span, no_mangle),
+            self.cx.attribute(self.span, special),
         ]
     }
 
index add128cc2cf6a16633cbe13ef75c0412dc36cc3c..6be07878487b920fd89d28013399933551d072cf 100644 (file)
@@ -47,7 +47,7 @@
 use std::hash::{Hash, Hasher};
 use syntax::ast;
 use syntax_pos::{MultiSpan, Span};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor};
@@ -256,7 +256,7 @@ impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
     fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                          sp: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a>
     {
         self.tcx.sess.struct_span_err_with_code(sp, msg, code)
@@ -755,12 +755,17 @@ pub fn report_reassigned_immutable_variable(&self,
     pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self,
                                                          s: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a> {
         self.tcx.sess.struct_span_err_with_code(s, msg, code)
     }
 
-    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, s: S, msg: &str, code: &str) {
+    pub fn span_err_with_code<S: Into<MultiSpan>>(
+        &self,
+        s: S,
+        msg: &str,
+        code: DiagnosticId,
+    ) {
         self.tcx.sess.span_err_with_code(s, msg, code);
     }
 
index 08f3b0a4c5fd1cfd0e1104fa852a58d7f1c14723..6ebe3c679667f0a7afffa15811ae4cdbe3359af5 100644 (file)
@@ -208,6 +208,20 @@ fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         }
     }
 
+    fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::TyAdt(adt_def, ..) => adt_def.is_enum() && adt_def.is_non_exhaustive(),
+            _ => false,
+        }
+    }
+
+    fn is_local(&self, ty: Ty<'tcx>) -> bool {
+        match ty.sty {
+            ty::TyAdt(adt_def, ..) => adt_def.did.is_local(),
+            _ => false,
+        }
+    }
+
     fn is_variant_uninhabited(&self,
                               variant: &'tcx ty::VariantDef,
                               substs: &'tcx ty::subst::Substs<'tcx>)
@@ -628,9 +642,16 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 
         let is_privately_empty =
             all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
-        debug!("missing_ctors={:?} is_privately_empty={:?}", missing_ctors,
-               is_privately_empty);
-        if missing_ctors.is_empty() && !is_privately_empty {
+        let is_declared_nonexhaustive =
+            cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty);
+        debug!("missing_ctors={:?} is_privately_empty={:?} is_declared_nonexhaustive={:?}",
+               missing_ctors, is_privately_empty, is_declared_nonexhaustive);
+
+        // For privately empty and non-exhaustive enums, we work as if there were an "extra"
+        // `_` constructor for the type, so we can never match over all constructors.
+        let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive;
+
+        if missing_ctors.is_empty() && !is_non_exhaustive {
             all_ctors.into_iter().map(|c| {
                 is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
             }).find(|result| result.is_useful()).unwrap_or(NotUseful)
@@ -645,7 +666,51 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
             match is_useful(cx, &matrix, &v[1..], witness) {
                 UsefulWithWitness(pats) => {
                     let cx = &*cx;
-                    let new_witnesses = if used_ctors.is_empty() {
+                    // In this case, there's at least one "free"
+                    // constructor that is only matched against by
+                    // wildcard patterns.
+                    //
+                    // There are 2 ways we can report a witness here.
+                    // Commonly, we can report all the "free"
+                    // constructors as witnesses, e.g. if we have:
+                    //
+                    // ```
+                    //     enum Direction { N, S, E, W }
+                    //     let Direction::N = ...;
+                    // ```
+                    //
+                    // we can report 3 witnesses: `S`, `E`, and `W`.
+                    //
+                    // However, there are 2 cases where we don't want
+                    // to do this and instead report a single `_` witness:
+                    //
+                    // 1) If the user is matching against a non-exhaustive
+                    // enum, there is no point in enumerating all possible
+                    // variants, because the user can't actually match
+                    // against them himself, e.g. in an example like:
+                    // ```
+                    //     let err: io::ErrorKind = ...;
+                    //     match err {
+                    //         io::ErrorKind::NotFound => {},
+                    //     }
+                    // ```
+                    // we don't want to show every possible IO error,
+                    // but instead have `_` as the witness (this is
+                    // actually *required* if the user specified *all*
+                    // IO errors, but is probably what we want in every
+                    // case).
+                    //
+                    // 2) If the user didn't actually specify a constructor
+                    // in this arm, e.g. in
+                    // ```
+                    //     let x: (Direction, Direction, bool) = ...;
+                    //     let (_, _, false) = x;
+                    // ```
+                    // we don't want to show all 16 possible witnesses
+                    // `(<direction-1>, <direction-2>, true)` - we are
+                    // satisfied with `(_, _, true)`. In this case,
+                    // `used_ctors` is empty.
+                    let new_witnesses = if is_non_exhaustive || used_ctors.is_empty() {
                         // All constructors are unused. Add wild patterns
                         // rather than each individual constructor
                         pats.into_iter().map(|mut witness| {
index 0660cd96a4a34ee6be812e7e11637d23ca67f103..a733e9de5a1ab0df6fc58bbf055e4283ac4be063 100644 (file)
@@ -45,38 +45,62 @@ macro_rules! newtype_index {
     // Use default constants
     ($name:ident) => (
         newtype_index!(
-            @type[$name]
-            @max[::std::u32::MAX]
-            @debug_format["{}"]);
+            // Leave out derives marker so we can use its absence to ensure it comes first
+            @type         [$name]
+            @max          [::std::u32::MAX]
+            @debug_format ["{}"]);
     );
 
     // Define any constants
     ($name:ident { $($tokens:tt)+ }) => (
         newtype_index!(
-            @type[$name]
-            @max[::std::u32::MAX]
-            @debug_format["{}"]
-            $($tokens)+);
+            // Leave out derives marker so we can use its absence to ensure it comes first
+            @type         [$name]
+            @max          [::std::u32::MAX]
+            @debug_format ["{}"]
+                          $($tokens)+);
     );
 
     // ---- private rules ----
 
     // Base case, user-defined constants (if any) have already been defined
-    (@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]) => (
-        #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
-            RustcEncodable, RustcDecodable)]
-        pub struct $type(pub u32);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]) => (
+        #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
+        pub struct $type($($pub)* u32);
 
         impl Idx for $type {
             fn new(value: usize) -> Self {
                 assert!(value < ($max) as usize);
                 $type(value as u32)
             }
+
             fn index(self) -> usize {
                 self.0 as usize
             }
         }
 
+        newtype_index!(
+            @handle_debug
+            @derives      [$($derives,)*]
+            @type         [$type]
+            @debug_format [$debug_format]);
+    );
+
+    // base case for handle_debug where format is custom. No Debug implementation is emitted.
+    (@handle_debug
+     @derives      [$($_derives:ident,)*]
+     @type         [$type:ident]
+     @debug_format [custom]) => ();
+
+    // base case for handle_debug, no debug overrides found, so use default
+    (@handle_debug
+     @derives      []
+     @type         [$type:ident]
+     @debug_format [$debug_format:tt]) => (
         impl ::std::fmt::Debug for $type {
             fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                 write!(fmt, $debug_format, self.0)
@@ -84,38 +108,219 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         }
     );
 
+    // Debug is requested for derive, don't generate any Debug implementation.
+    (@handle_debug
+     @derives      [Debug, $($derives:ident,)*]
+     @type         [$type:ident]
+     @debug_format [$debug_format:tt]) => ();
+
+    // It's not Debug, so just pop it off the front of the derives stack and check the rest.
+    (@handle_debug
+     @derives      [$_derive:ident, $($derives:ident,)*]
+     @type         [$type:ident]
+     @debug_format [$debug_format:tt]) => (
+        newtype_index!(
+            @handle_debug
+            @derives      [$($derives,)*]
+            @type         [$type]
+            @debug_format [$debug_format]);
+    );
+
+    // Handle the case where someone wants to make the internal field public
+    (@type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   pub idx
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @pub          [pub]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // The default case is that the internal field is private
+    (@type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @pub          []
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // Append comma to end of derives list if it's missing
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   derive [$($derives:ident),*]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          derive [$($derives,)*]
+                          $($tokens)*);
+    );
+
+    // By not including the @derives marker in this list nor in the default args, we can force it
+    // to come first if it exists. When encodable is custom, just use the derives list as-is.
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   derive [$($derives:ident,)+]
+                   ENCODABLE = custom
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)+]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // By not including the @derives marker in this list nor in the default args, we can force it
+    // to come first if it exists. When encodable isn't custom, add serialization traits by default.
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   derive [$($derives:ident,)+]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)+ RustcDecodable, RustcEncodable,]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // The case where no derives are added, but encodable is overriden. Don't
+    // derive serialization traits
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   ENCODABLE = custom
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      []
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
+    // The case where no derives are added, add serialization derives by default
+    (@pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [RustcDecodable, RustcEncodable,]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
+    );
+
     // Rewrite final without comma to one that includes comma
-    (@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]
-            $name:ident = $constant:expr) => (
-        newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $name = $constant,);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $name:ident = $constant:expr) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $name = $constant,);
     );
 
     // Rewrite final const without comma to one that includes comma
-    (@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr]
-            const $name:ident = $constant:expr) => (
-        newtype_index!(@type[$type]
-                       @max[$max]
-                       @debug_format[$debug_format]
-                       const $name = $constant,);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$_max:expr]
+     @debug_format [$debug_format:tt]
+                   $(#[doc = $doc:expr])*
+                   const $name:ident = $constant:expr) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $(#[doc = $doc])* const $name = $constant,);
     );
 
     // Replace existing default for max
-    (@type[$type:ident] @max[$_max:expr] @debug_format[$debug_format:expr]
-            MAX = $max:expr, $($tokens:tt)*) => (
-        newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$_max:expr]
+     @debug_format [$debug_format:tt]
+                   MAX = $max:expr,
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
     );
 
     // Replace existing default for debug_format
-    (@type[$type:ident] @max[$max:expr] @debug_format[$_debug_format:expr]
-            DEBUG_FORMAT = $debug_format:expr, $($tokens:tt)*) => (
-        newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$_debug_format:tt]
+                   DEBUG_FORMAT = $debug_format:tt,
+                   $($tokens:tt)*) => (
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
     );
 
-    // Assign a user-defined constant (as final param)
-    (@type[$type:ident] @max[$max:expr] @debug_format[$debug_format:expr]
-            const $name:ident = $constant:expr, $($tokens:tt)*) => (
+    // Assign a user-defined constant
+    (@derives      [$($derives:ident,)*]
+     @pub          [$($pub:tt)*]
+     @type         [$type:ident]
+     @max          [$max:expr]
+     @debug_format [$debug_format:tt]
+                   $(#[doc = $doc:expr])*
+                   const $name:ident = $constant:expr,
+                   $($tokens:tt)*) => (
+        $(#[doc = $doc])*
         pub const $name: $type = $type($constant);
-        newtype_index!(@type[$type] @max[$max] @debug_format[$debug_format] $($tokens)*);
+        newtype_index!(
+            @derives      [$($derives,)*]
+            @pub          [$($pub)*]
+            @type         [$type]
+            @max          [$max]
+            @debug_format [$debug_format]
+                          $($tokens)*);
     );
 }
 
index d86d51f3747225da74988678638d1021e8317918..5ff75351b635beedd99bb5503e17953c46d02341 100644 (file)
@@ -253,7 +253,7 @@ fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option<as
                 hir::ItemUnion(..) |
                 hir::ItemTrait(..) |
                 hir::ItemImpl(..) |
-                hir::ItemDefaultImpl(..) => None,
+                hir::ItemAutoImpl(..) => None,
 
                 hir::ItemMod(ref m) => search_mod(this, m, idx, names),
             };
index 5e0e624082e6fafe787262552b3ee3cb30c27176..2d70de89355ee2a729d2e30885e45811c273fd1f 100644 (file)
 pub struct Diagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
-    pub code: Option<String>,
+    pub code: Option<DiagnosticId>,
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
     pub suggestions: Vec<CodeSuggestion>,
 }
 
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub enum DiagnosticId {
+    Error(String),
+    Lint(String),
+}
+
 /// For example a note attached to an error.
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct SubDiagnostic {
@@ -81,7 +87,7 @@ pub fn new(level: Level, message: &str) -> Self {
         Diagnostic::new_with_code(level, None, message)
     }
 
-    pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self {
+    pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) -> Self {
         Diagnostic {
             level,
             message: vec![(message.to_owned(), Style::NoStyle)],
@@ -267,7 +273,7 @@ pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
         self
     }
 
-    pub fn code(&mut self, s: String) -> &mut Self {
+    pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
         self.code = Some(s);
         self
     }
index 2cd433bfe3aeef5c2cbd45766d790718de4c56c3..40b5810454b9ac25550ab3e64a4a331bc7c29db6 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use Diagnostic;
+use DiagnosticId;
 use DiagnosticStyledString;
 
 use Level;
@@ -192,7 +193,7 @@ pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self
                                      suggestions: Vec<String>)
                                      -> &mut Self);
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
-    forward!(pub fn code(&mut self, s: String) -> &mut Self);
+    forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
 
     /// Convenience function for internal use, clients should use one of the
     /// struct_* methods on Handler.
@@ -204,7 +205,7 @@ pub fn new(handler: &'a Handler, level: Level, message: &str) -> DiagnosticBuild
     /// struct_* methods on Handler.
     pub fn new_with_code(handler: &'a Handler,
                          level: Level,
-                         code: Option<String>,
+                         code: Option<DiagnosticId>,
                          message: &str)
                          -> DiagnosticBuilder<'a> {
         let diagnostic = Diagnostic::new_with_code(level, code, message);
index 5db5a9a1133d8dcb2fe5307c8b72c92e656da606..6c43c60686ee424e2aa458ff70ac6ea212438c21 100644 (file)
@@ -10,9 +10,9 @@
 
 use self::Destination::*;
 
-use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan, CharPos};
+use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan};
 
-use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper};
+use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper, DiagnosticId};
 use RenderSpan::*;
 use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
 use styled_buffer::StyledBuffer;
@@ -201,8 +201,8 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                 // 6..7. This is degenerate input, but it's best to degrade
                 // gracefully -- and the parser likes to supply a span like
                 // that for EOF, in particular.
-                if lo.col == hi.col && lo.line == hi.line {
-                    hi.col = CharPos(lo.col.0 + 1);
+                if lo.col_display == hi.col_display && lo.line == hi.line {
+                    hi.col_display += 1;
                 }
 
                 let ann_type = if lo.line != hi.line {
@@ -210,8 +210,8 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                         depth: 1,
                         line_start: lo.line,
                         line_end: hi.line,
-                        start_col: lo.col.0,
-                        end_col: hi.col.0,
+                        start_col: lo.col_display,
+                        end_col: hi.col_display,
                         is_primary: span_label.is_primary,
                         label: span_label.label.clone(),
                     };
@@ -221,8 +221,8 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                     AnnotationType::Singleline
                 };
                 let ann = Annotation {
-                    start_col: lo.col.0,
-                    end_col: hi.col.0,
+                    start_col: lo.col_display,
+                    end_col: hi.col_display,
                     is_primary: span_label.is_primary,
                     label: span_label.label.clone(),
                     annotation_type: ann_type,
@@ -886,7 +886,7 @@ fn style_or_override(style: Style, override_style: Option<Style>) -> Style {
     fn emit_message_default(&mut self,
                             msp: &MultiSpan,
                             msg: &Vec<(String, Style)>,
-                            code: &Option<String>,
+                            code: &Option<DiagnosticId>,
                             level: &Level,
                             max_line_num_len: usize,
                             is_secondary: bool)
@@ -905,13 +905,11 @@ fn emit_message_default(&mut self,
             self.msg_to_buffer(&mut buffer, msg, max_line_num_len, "note", None);
         } else {
             buffer.append(0, &level.to_string(), Style::Level(level.clone()));
-            match code {
-                &Some(ref code) => {
-                    buffer.append(0, "[", Style::Level(level.clone()));
-                    buffer.append(0, &code, Style::Level(level.clone()));
-                    buffer.append(0, "]", Style::Level(level.clone()));
-                }
-                _ => {}
+            // only render error codes, not lint codes
+            if let Some(DiagnosticId::Error(ref code)) = *code {
+                buffer.append(0, "[", Style::Level(level.clone()));
+                buffer.append(0, &code, Style::Level(level.clone()));
+                buffer.append(0, "]", Style::Level(level.clone()));
             }
             buffer.append(0, ": ", Style::HeaderMsg);
             for &(ref text, _) in msg.iter() {
@@ -1174,7 +1172,7 @@ fn emit_suggestion_default(&mut self,
     fn emit_messages_default(&mut self,
                              level: &Level,
                              message: &Vec<(String, Style)>,
-                             code: &Option<String>,
+                             code: &Option<DiagnosticId>,
                              span: &MultiSpan,
                              children: &Vec<SubDiagnostic>) {
         let max_line_num = self.get_max_line_num(span, children);
index ba7268a4bc39398fa13930463481c0d8d7d26518..b30ee7016ab1cee7a7dbb1d237b0719ba58a5613 100644 (file)
@@ -262,7 +262,7 @@ fn description(&self) -> &str {
     }
 }
 
-pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString};
+pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, DiagnosticId};
 pub use diagnostic_builder::DiagnosticBuilder;
 
 /// A handler deals with errors; certain errors
@@ -337,11 +337,11 @@ pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
     pub fn struct_span_warn_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                               sp: S,
                                                               msg: &str,
-                                                              code: &str)
+                                                              code: DiagnosticId)
                                                               -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
         result.set_span(sp);
-        result.code(code.to_owned());
+        result.code(code);
         if !self.can_emit_warnings {
             result.cancel();
         }
@@ -365,20 +365,24 @@ pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
-                                                             code: &str)
+                                                             code: DiagnosticId)
                                                              -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
         result.set_span(sp);
-        result.code(code.to_owned());
+        result.code(code);
         result
     }
     // FIXME: This method should be removed (every error should have an associated error code).
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         DiagnosticBuilder::new(self, Level::Error, msg)
     }
-    pub fn struct_err_with_code<'a>(&'a self, msg: &str, code: &str) -> DiagnosticBuilder<'a> {
+    pub fn struct_err_with_code<'a>(
+        &'a self,
+        msg: &str,
+        code: DiagnosticId,
+    ) -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
-        result.code(code.to_owned());
+        result.code(code);
         result
     }
     pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
@@ -392,11 +396,11 @@ pub fn struct_span_fatal<'a, S: Into<MultiSpan>>(&'a self,
     pub fn struct_span_fatal_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                                sp: S,
                                                                msg: &str,
-                                                               code: &str)
+                                                               code: DiagnosticId)
                                                                -> DiagnosticBuilder<'a> {
         let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
         result.set_span(sp);
-        result.code(code.to_owned());
+        result.code(code);
         result
     }
     pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
@@ -420,7 +424,7 @@ pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError {
     pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
                                                     sp: S,
                                                     msg: &str,
-                                                    code: &str)
+                                                    code: DiagnosticId)
                                                     -> FatalError {
         self.emit_with_code(&sp.into(), msg, code, Fatal);
         FatalError
@@ -436,13 +440,13 @@ pub fn mut_span_err<'a, S: Into<MultiSpan>>(&'a self,
         result.set_span(sp);
         result
     }
-    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.emit_with_code(&sp.into(), msg, code, Error);
     }
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Warning);
     }
-    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
+    pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
         self.emit_with_code(&sp.into(), msg, code, Warning);
     }
     pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
@@ -546,11 +550,11 @@ pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
             self.abort_if_errors();
         }
     }
-    pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: &str, lvl: Level) {
+    pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: DiagnosticId, lvl: Level) {
         if lvl == Warning && !self.can_emit_warnings {
             return;
         }
-        let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code.to_owned()), msg);
+        let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code), msg);
         db.set_span(msp.clone());
         db.emit();
         if !self.continue_after_error.get() {
index 0cb920a111dd91ff4df0b25a247a75f6982b1dc0..e871c0dbdab138ad24ca5d169e1f7448c7cbaa55 100644 (file)
@@ -409,7 +409,7 @@ fn auto_labels(&mut self, item_id: ast::NodeId, attr: &Attribute) -> (&'static s
                     //HirItem::ItemTrait(..) => ("ItemTrait", LABELS_TRAIT),
 
                     // `impl Trait for .. {}`
-                    HirItem::ItemDefaultImpl(..) => ("ItemDefaultImpl", LABELS_IMPL),
+                    HirItem::ItemAutoImpl(..) => ("ItemAutoImpl", LABELS_IMPL),
 
                     // An implementation, eg `impl<A> Trait for Foo { .. }`
                     HirItem::ItemImpl(..) => ("ItemImpl", LABELS_IMPL),
index 027ed84faf0fdcc3553af352b383f6f3adb0d5a3..d14a6943fc11279f55bcc66ce67f58f5156a71d7 100644 (file)
@@ -23,7 +23,7 @@
 
 #[derive(PartialEq)]
 pub enum MethodLateContext {
-    TraitDefaultImpl,
+    TraitAutoImpl,
     TraitImpl,
     PlainImpl,
 }
@@ -32,7 +32,7 @@ pub fn method_context(cx: &LateContext, id: ast::NodeId) -> MethodLateContext {
     let def_id = cx.tcx.hir.local_def_id(id);
     let item = cx.tcx.associated_item(def_id);
     match item.container {
-        ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
+        ty::TraitContainer(..) => MethodLateContext::TraitAutoImpl,
         ty::ImplContainer(cid) => {
             match cx.tcx.impl_trait_ref(cid) {
                 Some(_) => MethodLateContext::TraitImpl,
@@ -245,7 +245,7 @@ fn check_fn(&mut self,
                     MethodLateContext::PlainImpl => {
                         self.check_snake_case(cx, "method", &name.as_str(), Some(span))
                     }
-                    MethodLateContext::TraitDefaultImpl => {
+                    MethodLateContext::TraitAutoImpl => {
                         self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
                     }
                     _ => (),
index 70cac419648d5e663427369a577cac2c27cd2a44..07874a8cc69dd0eaae4b3319d6d514f5425dec27 100644 (file)
 // hardwired lints from librustc
 pub use lint::builtin::*;
 
+declare_lint! {
+    pub AUTO_IMPL,
+    Deny,
+    "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`"
+}
+
+#[derive(Copy, Clone)]
+pub struct AutoImpl;
+
+impl LintPass for AutoImpl {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(AUTO_IMPL)
+    }
+}
+
+impl EarlyLintPass for AutoImpl {
+    fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) {
+        let msg = "The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`";
+        match item.node {
+            ast::ItemKind::AutoImpl(..) => cx.span_lint(AUTO_IMPL, item.span, msg),
+            _ => ()
+        }
+     }
+}
+
 declare_lint! {
     WHILE_TRUE,
     Warn,
@@ -228,7 +253,7 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
 
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
-            hir::ItemTrait(hir::Unsafety::Unsafe, ..) => {
+            hir::ItemTrait(_, hir::Unsafety::Unsafe, ..) => {
                 self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
             }
 
@@ -1301,3 +1326,60 @@ fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
         }
     }
 }
+
+/// Lint for items marked `pub` that aren't reachable from other crates
+pub struct UnreachablePub;
+
+declare_lint! {
+    UNREACHABLE_PUB,
+    Allow,
+    "`pub` items not reachable from crate root"
+}
+
+impl LintPass for UnreachablePub {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNREACHABLE_PUB)
+    }
+}
+
+impl UnreachablePub {
+    fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId,
+                    vis: &hir::Visibility, span: Span, exportable: bool) {
+        if !cx.access_levels.is_reachable(id) && *vis == hir::Visibility::Public {
+            let def_span = cx.tcx.sess.codemap().def_span(span);
+            let mut err = cx.struct_span_lint(UNREACHABLE_PUB, def_span,
+                                              &format!("unreachable `pub` {}", what));
+            // visibility is token at start of declaration (can be macro
+            // variable rather than literal `pub`)
+            let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' ');
+            let replacement = if cx.tcx.sess.features.borrow().crate_visibility_modifier {
+                "crate"
+            } else {
+                "pub(crate)"
+            }.to_owned();
+            err.span_suggestion(pub_span, "consider restricting its visibility", replacement);
+            if exportable {
+                err.help("or consider exporting it for use by other crates");
+            }
+            err.emit();
+        }
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
+    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
+        self.perform_lint(cx, "item", item.id, &item.vis, item.span, true);
+    }
+
+    fn check_foreign_item(&mut self, cx: &LateContext, foreign_item: &hir::ForeignItem) {
+        self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis, foreign_item.span, true);
+    }
+
+    fn check_struct_field(&mut self, cx: &LateContext, field: &hir::StructField) {
+        self.perform_lint(cx, "field", field.id, &field.vis, field.span, false);
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
+        self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false);
+    }
+}
index 42fcf377d65396a29034d8f557b4ff6f22d4fcdc..1a8ad9718cfabafcb85c5892535b8c3318b39e76 100644 (file)
@@ -109,6 +109,7 @@ macro_rules! add_lint_group {
                        AnonymousParameters,
                        IllegalFloatLiteralPattern,
                        UnusedDocComment,
+                       AutoImpl,
                        );
 
     add_early_builtin_with_new!(sess,
@@ -137,6 +138,7 @@ macro_rules! add_lint_group {
                  PluginAsLibrary,
                  MutableTransmutes,
                  UnionsWithDropFields,
+                 UnreachablePub,
                  );
 
     add_builtin_with_new!(sess,
@@ -181,6 +183,10 @@ macro_rules! add_lint_group {
     // - Eventually, remove lint
     store.register_future_incompatible(sess,
                                        vec![
+        FutureIncompatibleInfo {
+            id: LintId::of(AUTO_IMPL),
+            reference: "issue #13231 <https://github.com/rust-lang/rust/issues/13231>",
+        },
         FutureIncompatibleInfo {
             id: LintId::of(PRIVATE_IN_PUBLIC),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
index fbe63e0ab4a8af51f2d88a205f22cc88ac4c8eae..97c00aede90cfd229b3948d14d618fb37395df19 100644 (file)
@@ -144,7 +144,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_const_fn => { cdata.is_const_fn(def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
-    is_default_impl => { cdata.is_default_impl(def_id.index) }
+    is_auto_impl => { cdata.is_auto_impl(def_id.index) }
     describe_def => { cdata.get_def(def_id.index) }
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
     lookup_stability => {
index b45196191249d869c673270d2942100f015c05ec..603e79155fb726d859c4c0d9995cc83f73eaba02 100644 (file)
@@ -41,6 +41,7 @@
 use std::u32;
 
 use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
+use rustc_data_structures::indexed_vec::Idx;
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
@@ -459,7 +460,7 @@ fn to_def(&self, did: DefId) -> Option<Def> {
 
             EntryKind::ForeignMod |
             EntryKind::Impl(_) |
-            EntryKind::DefaultImpl(_) |
+            EntryKind::AutoImpl(_) |
             EntryKind::Field |
             EntryKind::Generator(_) |
             EntryKind::Closure(_) => return None,
@@ -529,7 +530,7 @@ pub fn get_trait_def(&self, item_id: DefIndex) -> ty::TraitDef {
         ty::TraitDef::new(self.local_def_id(item_id),
                           data.unsafety,
                           data.paren_sugar,
-                          data.has_default_impl,
+                          data.has_auto_impl,
                           self.def_path_table.def_path_hash(item_id))
     }
 
@@ -735,7 +736,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
                         continue;
                     }
                     EntryKind::Impl(_) |
-                    EntryKind::DefaultImpl(_) => continue,
+                    EntryKind::AutoImpl(_) => continue,
 
                     _ => {}
                 }
@@ -1082,9 +1083,9 @@ pub fn is_dllimport_foreign_item(&self, id: DefIndex) -> bool {
         self.dllimport_foreign_items.contains(&id)
     }
 
-    pub fn is_default_impl(&self, impl_id: DefIndex) -> bool {
+    pub fn is_auto_impl(&self, impl_id: DefIndex) -> bool {
         match self.entry(impl_id).kind {
-            EntryKind::DefaultImpl(_) => true,
+            EntryKind::AutoImpl(_) => true,
             _ => false,
         }
     }
@@ -1189,6 +1190,7 @@ pub fn imported_filemaps(&'a self,
                                       end_pos,
                                       lines,
                                       multibyte_chars,
+                                      non_narrow_chars,
                                       .. } = filemap_to_import;
 
             let source_length = (end_pos - start_pos).to_usize();
@@ -1206,6 +1208,10 @@ pub fn imported_filemaps(&'a self,
             for mbc in &mut multibyte_chars {
                 mbc.pos = mbc.pos - start_pos;
             }
+            let mut non_narrow_chars = non_narrow_chars.into_inner();
+            for swc in &mut non_narrow_chars {
+                *swc = *swc - start_pos;
+            }
 
             let local_version = local_codemap.new_imported_filemap(name,
                                                                    name_was_remapped,
@@ -1213,7 +1219,8 @@ pub fn imported_filemaps(&'a self,
                                                                    src_hash,
                                                                    source_length,
                                                                    lines,
-                                                                   multibyte_chars);
+                                                                   multibyte_chars,
+                                                                   non_narrow_chars);
             debug!("CrateMetaData::imported_filemaps alloc \
                     filemap {:?} original (start_pos {:?} end_pos {:?}) \
                     translated (start_pos {:?} end_pos {:?})",
index 725d6d8fad0e098bb422ffcac4c7841769554712..d5eee14bf506bd1889e039a45985b885c63971ab 100644 (file)
@@ -584,7 +584,8 @@ fn encode_field(&mut self,
     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
         debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
-        let variant = tcx.adt_def(adt_def_id).struct_variant();
+        let adt_def = tcx.adt_def(adt_def_id);
+        let variant = adt_def.struct_variant();
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -606,6 +607,12 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
             }
         }
 
+        // If the structure is marked as non_exhaustive then lower the visibility
+        // to within the crate.
+        if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public {
+            ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+        }
+
         let repr_options = get_repr_options(&tcx, adt_def_id);
 
         Entry {
@@ -919,7 +926,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                     ctor_sig: None,
                 }), repr_options)
             }
-            hir::ItemDefaultImpl(..) => {
+            hir::ItemAutoImpl(..) => {
                 let data = ImplData {
                     polarity: hir::ImplPolarity::Positive,
                     defaultness: hir::Defaultness::Final,
@@ -928,7 +935,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                     trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
                 };
 
-                EntryKind::DefaultImpl(self.lazy(&data))
+                EntryKind::AutoImpl(self.lazy(&data))
             }
             hir::ItemImpl(_, polarity, defaultness, ..) => {
                 let trait_ref = tcx.impl_trait_ref(def_id);
@@ -970,7 +977,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 let data = TraitData {
                     unsafety: trait_def.unsafety,
                     paren_sugar: trait_def.paren_sugar,
-                    has_default_impl: tcx.trait_has_default_impl(def_id),
+                    has_auto_impl: tcx.trait_is_auto(def_id),
                     super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
                 };
 
@@ -1517,7 +1524,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
             hir::ItemGlobalAsm(..) |
             hir::ItemExternCrate(..) |
             hir::ItemUse(..) |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemTy(..) => {
                 // no sub-item recording needed in these cases
             }
index d85fdeb377cd30d43127c5729bfd71ccb10cfe78..3efe74bfecc92f1ea883a01686517c05b994818e 100644 (file)
@@ -303,7 +303,7 @@ pub enum EntryKind<'tcx> {
     Generator(Lazy<GeneratorData<'tcx>>),
     Trait(Lazy<TraitData<'tcx>>),
     Impl(Lazy<ImplData<'tcx>>),
-    DefaultImpl(Lazy<ImplData<'tcx>>),
+    AutoImpl(Lazy<ImplData<'tcx>>),
     Method(Lazy<MethodData<'tcx>>),
     AssociatedType(AssociatedContainer),
     AssociatedConst(AssociatedContainer, u8),
@@ -359,7 +359,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             EntryKind::Trait(ref trait_data) => {
                 trait_data.hash_stable(hcx, hasher);
             }
-            EntryKind::DefaultImpl(ref impl_data) |
+            EntryKind::AutoImpl(ref impl_data) |
             EntryKind::Impl(ref impl_data) => {
                 impl_data.hash_stable(hcx, hasher);
             }
@@ -426,14 +426,14 @@ pub struct VariantData<'tcx> {
 pub struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
     pub paren_sugar: bool,
-    pub has_default_impl: bool,
+    pub has_auto_impl: bool,
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
 impl_stable_hash_for!(struct TraitData<'tcx> {
     unsafety,
     paren_sugar,
-    has_default_impl,
+    has_auto_impl,
     super_predicates
 });
 
index 819f67a39e931c88fa121d15d7ad2412bf451cc2..2cb1a23ef5a15cfb4f8cc289c997a87ec631563c 100644 (file)
@@ -364,7 +364,8 @@ fn visit_terminator_entry(&mut self,
             TerminatorKind::Resume |
             TerminatorKind::Return |
             TerminatorKind::GeneratorDrop |
-            TerminatorKind::Unreachable => {
+            TerminatorKind::Unreachable |
+            TerminatorKind::FalseEdges { .. } => {
                 // no data used, thus irrelevant to borrowck
             }
         }
index 56c926eaa615343ee7737abda5f9ac668871c62f..b65d859e7d7568ab596eda5dc5ee54d2dc079034 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::hir;
 use hair::*;
 use syntax::ast::{Name, NodeId};
-use syntax_pos::{DUMMY_SP, Span};
+use syntax_pos::Span;
 
 // helper functions, broken out by category:
 mod simplify;
@@ -54,11 +54,17 @@ pub fn match_expr(&mut self,
             (body, scope.unwrap_or(self.visibility_scope))
         }).collect();
 
+        // create binding start block for link them by false edges
+        let candidate_count = arms.iter().fold(0, |ac, c| ac + c.patterns.len());
+        let pre_binding_blocks: Vec<_> = (0..candidate_count + 1)
+            .map(|_| self.cfg.start_new_block()).collect();
+
         // assemble a list of candidates: there is one candidate per
         // pattern, which means there may be more than one candidate
         // *per arm*. These candidates are kept sorted such that the
         // highest priority candidate comes first in the list.
         // (i.e. same order as in source)
+
         let candidates: Vec<_> =
             arms.iter()
                 .enumerate()
@@ -66,17 +72,25 @@ pub fn match_expr(&mut self,
                     arm.patterns.iter()
                                 .map(move |pat| (arm_index, pat, arm.guard.clone()))
                 })
-                .map(|(arm_index, pattern, guard)| {
+                .zip(pre_binding_blocks.iter().zip(pre_binding_blocks.iter().skip(1)))
+                .map(|((arm_index, pattern, guard),
+                       (pre_binding_block, next_candidate_pre_binding_block))| {
                     Candidate {
                         span: pattern.span,
                         match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)],
                         bindings: vec![],
                         guard,
                         arm_index,
+                        pre_binding_block: *pre_binding_block,
+                        next_candidate_pre_binding_block: *next_candidate_pre_binding_block,
                     }
                 })
                 .collect();
 
+        let outer_source_info = self.source_info(span);
+        self.cfg.terminate(*pre_binding_blocks.last().unwrap(),
+                           outer_source_info, TerminatorKind::Unreachable);
+
         // this will generate code to test discriminant_lvalue and
         // branch to the appropriate arm block
         let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block);
@@ -148,7 +162,11 @@ pub fn lvalue_into_pattern(&mut self,
             match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
             bindings: vec![],
             guard: None,
-            arm_index: 0, // since we don't call `match_candidates`, this field is unused
+
+            // since we don't call `match_candidates`, next fields is unused
+            arm_index: 0,
+            pre_binding_block: block,
+            next_candidate_pre_binding_block: block
         };
 
         // Simplify the candidate. Since the pattern is irrefutable, this should
@@ -278,6 +296,10 @@ pub struct Candidate<'pat, 'tcx:'pat> {
 
     // ...and then we branch to arm with this index.
     arm_index: usize,
+
+    // ...and the blocks for add false edges between candidates
+    pre_binding_block: BasicBlock,
+    next_candidate_pre_binding_block: BasicBlock,
 }
 
 #[derive(Clone, Debug)]
@@ -398,17 +420,43 @@ fn match_candidates<'pat>(&mut self,
             candidates.iter().take_while(|c| c.match_pairs.is_empty()).count();
         debug!("match_candidates: {:?} candidates fully matched", fully_matched);
         let mut unmatched_candidates = candidates.split_off(fully_matched);
-        for (index, candidate) in candidates.into_iter().enumerate() {
+
+        let fully_matched_with_guard =
+            candidates.iter().take_while(|c| c.guard.is_some()).count();
+
+        let unreachable_candidates = if fully_matched_with_guard + 1 < candidates.len() {
+            candidates.split_off(fully_matched_with_guard + 1)
+        } else {
+            vec![]
+        };
+
+        for candidate in candidates {
             // If so, apply any bindings, test the guard (if any), and
             // branch to the arm.
-            let is_last = index == fully_matched - 1;
-            if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks,
-                                                                   candidate, is_last) {
+            if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) {
                 block = b;
             } else {
                 // if None is returned, then any remaining candidates
                 // are unreachable (at least not through this path).
-                return vec![];
+                // Link them with false edges.
+                debug!("match_candidates: add false edges for unreachable {:?} and unmatched {:?}",
+                       unreachable_candidates, unmatched_candidates);
+                for candidate in unreachable_candidates {
+                    let source_info = self.source_info(candidate.span);
+                    let target = self.cfg.start_new_block();
+                    if let Some(otherwise) = self.bind_and_guard_matched_candidate(target,
+                                                                                   arm_blocks,
+                                                                                   candidate) {
+                        self.cfg.terminate(otherwise, source_info, TerminatorKind::Unreachable);
+                    }
+                }
+
+                if unmatched_candidates.is_empty() {
+                    return vec![]
+                } else {
+                    let target = self.cfg.start_new_block();
+                    return self.match_candidates(span, arm_blocks, unmatched_candidates, target);
+                }
             }
         }
 
@@ -423,9 +471,7 @@ fn match_candidates<'pat>(&mut self,
             self.test_candidates(span, arm_blocks, &unmatched_candidates, block);
 
         // If the target candidates were exhaustive, then we are done.
-        if otherwise.is_empty() {
-            return vec![];
-        }
+        // But for borrowck continue build decision tree.
 
         // If all candidates were sorted into `target_candidates` somewhere, then
         // the initial set was inexhaustive.
@@ -666,17 +712,27 @@ fn test_candidates<'pat>(&mut self,
     fn bind_and_guard_matched_candidate<'pat>(&mut self,
                                               mut block: BasicBlock,
                                               arm_blocks: &mut ArmBlocks,
-                                              candidate: Candidate<'pat, 'tcx>,
-                                              is_last_arm: bool)
+                                              candidate: Candidate<'pat, 'tcx>)
                                               -> Option<BasicBlock> {
         debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
                block, candidate);
 
         debug_assert!(candidate.match_pairs.is_empty());
 
-        self.bind_matched_candidate(block, candidate.bindings);
-
         let arm_block = arm_blocks.blocks[candidate.arm_index];
+        let candidate_source_info = self.source_info(candidate.span);
+
+        self.cfg.terminate(block, candidate_source_info,
+                               TerminatorKind::Goto { target: candidate.pre_binding_block });
+
+        block = self.cfg.start_new_block();
+        self.cfg.terminate(candidate.pre_binding_block, candidate_source_info,
+                               TerminatorKind::FalseEdges {
+                                   real_target: block,
+                                   imaginary_targets:
+                                       vec![candidate.next_candidate_pre_binding_block]});
+
+        self.bind_matched_candidate(block, candidate.bindings);
 
         if let Some(guard) = candidate.guard {
             // the block to branch to if the guard fails; if there is no
@@ -684,30 +740,22 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self,
             let guard = self.hir.mirror(guard);
             let source_info = self.source_info(guard.span);
             let cond = unpack!(block = self.as_local_operand(block, guard));
-            let otherwise = self.cfg.start_new_block();
+
+            let false_edge_block = self.cfg.start_new_block();
             self.cfg.terminate(block, source_info,
-                               TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
-            Some(otherwise)
-        } else if !is_last_arm {
-            // Add always true guard in case of more than one arm
-            // it creates false edges and allow MIR borrowck detects errors
-            // FIXME(#45184) -- permit "false edges"
-            let source_info = self.source_info(candidate.span);
-            let true_expr = Expr {
-                temp_lifetime: None,
-                ty: self.hir.tcx().types.bool,
-                span: DUMMY_SP,
-                kind: ExprKind::Literal{literal: self.hir.true_literal()},
-            };
-            let cond = unpack!(block = self.as_local_operand(block, true_expr));
+                               TerminatorKind::if_(self.hir.tcx(), cond, arm_block,
+                                   false_edge_block));
+
             let otherwise = self.cfg.start_new_block();
-            self.cfg.terminate(block, source_info,
-                               TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
+            self.cfg.terminate(false_edge_block, source_info,
+                               TerminatorKind::FalseEdges {
+                                   real_target: otherwise,
+                                   imaginary_targets:
+                                       vec![candidate.next_candidate_pre_binding_block] });
             Some(otherwise)
         } else {
-            let source_info = self.source_info(candidate.span);
-            self.cfg.terminate(block, source_info,
-                               TerminatorKind::Goto { target: arm_block  });
+            self.cfg.terminate(block, candidate_source_info,
+                               TerminatorKind::Goto { target: arm_block });
             None
         }
     }
index 7b91c43aa37222dbeaf0a8f1c255d2fe0a6eb861..4792bf2b213e64e7567136e0509a3d964b892502 100644 (file)
@@ -598,6 +598,8 @@ fn candidate_without_match_pair<'pat>(&mut self,
             bindings: candidate.bindings.clone(),
             guard: candidate.guard.clone(),
             arm_index: candidate.arm_index,
+            pre_binding_block: candidate.pre_binding_block,
+            next_candidate_pre_binding_block: candidate.next_candidate_pre_binding_block,
         }
     }
 
@@ -659,6 +661,8 @@ fn candidate_after_variant_switch<'pat>(&mut self,
             bindings: candidate.bindings.clone(),
             guard: candidate.guard.clone(),
             arm_index: candidate.arm_index,
+            pre_binding_block: candidate.pre_binding_block,
+            next_candidate_pre_binding_block: candidate.next_candidate_pre_binding_block,
         }
     }
 
index d27a4e7e9d9c3fe98070d89f86977d19c2982680..f5517096e3abae49ed72a96614759e4983d474d1 100644 (file)
@@ -721,6 +721,12 @@ fn propagate_bits_into_graph_successors_of(
                     self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb);
                 }
             }
+            mir::TerminatorKind::FalseEdges { ref real_target, ref imaginary_targets } => {
+                self.propagate_bits_into_entry_set_for(in_out, changed, real_target);
+                for target in imaginary_targets {
+                    self.propagate_bits_into_entry_set_for(in_out, changed, target);
+                }
+            }
         }
     }
 
index 8f473d035ee1df128f32e39ca72246248d94adf4..79ea745125c5332569172eb9a8aa81573a3bdfa7 100644 (file)
@@ -305,6 +305,7 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
             TerminatorKind::Goto { target: _ } |
             TerminatorKind::Resume |
             TerminatorKind::GeneratorDrop |
+            TerminatorKind::FalseEdges { .. } |
             TerminatorKind::Unreachable => { }
 
             TerminatorKind::Return => {
index 49ce36223994b56f53c8825da2773078532edd79..80c8f22c1029e0c60ce2873ee54285cdd5aa4983 100644 (file)
@@ -73,7 +73,8 @@ fn visit_terminator(&mut self,
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Resume |
             TerminatorKind::Return |
-            TerminatorKind::Unreachable => {
+            TerminatorKind::Unreachable |
+            TerminatorKind::FalseEdges { .. } => {
                                 // safe (at least as emitted during MIR construction)
             }
 
index 9d32861aedade2e9609c67f08a7c0ec34023897e..f2453d3946172f40241d39d8bd46f74316c93546 100644 (file)
@@ -720,6 +720,12 @@ fn visit_terminator_kind(&mut self, block: BasicBlock,
                 }
             }
             TerminatorKind::Unreachable => { }
+            TerminatorKind::FalseEdges { ref mut real_target, ref mut imaginary_targets } => {
+                *real_target = self.update_target(*real_target);
+                for target in imaginary_targets {
+                    *target = self.update_target(*target);
+                }
+            }
         }
     }
 
index fa6bb644871dced4e11184f0bfa68d6f9eac738c..7de8de3c96bd7bca3bff2923442208d128232dc7 100644 (file)
@@ -45,7 +45,8 @@ fn visit_terminator(&mut self,
             TerminatorKind::Unreachable |
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Yield { .. } |
-            TerminatorKind::SwitchInt { .. } => {
+            TerminatorKind::SwitchInt { .. } |
+            TerminatorKind::FalseEdges { .. } => {
                 /* nothing to do */
             },
             TerminatorKind::Call { cleanup: ref mut unwind, .. } |
index 3f3b9d177d70c03a72c62e5cdfe5de68b423117b..583dfd9b616f1bea64b21d925751a135d84cdeae 100644 (file)
@@ -317,7 +317,8 @@ fn qualify_const(&mut self) -> (Qualif, Rc<IdxSetBuf<Local>>) {
                 TerminatorKind::Resume |
                 TerminatorKind::GeneratorDrop |
                 TerminatorKind::Yield { .. } |
-                TerminatorKind::Unreachable => None,
+                TerminatorKind::Unreachable |
+                TerminatorKind::FalseEdges { .. } => None,
 
                 TerminatorKind::Return => {
                     // Check for unused values. This usually means
index 0dff145ecbce94c547568b7651b91529fcf4079f..edbbe5305e959cb1dff9714bed2f645dfe2e854d 100644 (file)
@@ -61,6 +61,9 @@ fn run_pass<'a, 'tcx>(&self,
                 }), expected, .. } if cond == expected => {
                     TerminatorKind::Goto { target: target }
                 },
+                TerminatorKind::FalseEdges { real_target, .. } => {
+                    TerminatorKind::Goto { target: real_target }
+                },
                 _ => continue
             };
         }
index d238b145d424c32195f8542f74430d9f52c73348..b07e818ee87525045e6d237d575d74cb66117cef 100644 (file)
@@ -441,7 +441,8 @@ fn check_terminator(&mut self,
             TerminatorKind::Return |
             TerminatorKind::GeneratorDrop |
             TerminatorKind::Unreachable |
-            TerminatorKind::Drop { .. } => {
+            TerminatorKind::Drop { .. } |
+            TerminatorKind::FalseEdges { .. } => {
                 // no checks needed for these
             }
 
@@ -685,6 +686,12 @@ fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block: &BasicBlockData<'tcx>)
                     self.assert_iscleanup(mir, block, cleanup, true);
                 }
             }
+            TerminatorKind::FalseEdges { real_target, ref imaginary_targets } => {
+                self.assert_iscleanup(mir, block, real_target, is_cleanup);
+                for target in imaginary_targets {
+                    self.assert_iscleanup(mir, block, *target, is_cleanup);
+                }
+            }
         }
     }
 
index a4a7699abda59ace31aeaba96bb50adc9dbb3868..2f29b79eeb6cc49bd05d30e05a5d5c28fa0ed9ed 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc::ty::{self, TyCtxt};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use syntax_pos::{MultiSpan, Span};
 
 use std::fmt;
@@ -41,7 +41,7 @@ pub trait BorrowckErrors {
     fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                          sp: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a>;
 
     fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
@@ -445,7 +445,7 @@ impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
     fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                          sp: S,
                                                          msg: &str,
-                                                         code: &str)
+                                                         code: DiagnosticId)
                                                          -> DiagnosticBuilder<'a>
     {
         self.sess.struct_span_err_with_code(sp, msg, code)
index e44f3f3982491af01c9c983927c644b06a2cd163..6d9c294884128688364485bd5e63d7908e7ffe51 100644 (file)
@@ -42,6 +42,15 @@ fn check_label(&self, label: Ident, span: Span) {
         }
     }
 
+    fn invalid_non_exhaustive_attribute(&self, variant: &Variant) {
+        let has_non_exhaustive = variant.node.attrs.iter()
+            .any(|attr| attr.check_name("non_exhaustive"));
+        if has_non_exhaustive {
+            self.err_handler().span_err(variant.span,
+                                        "#[non_exhaustive] is not yet supported on variants");
+        }
+    }
+
     fn invalid_visibility(&self, vis: &Visibility, span: Span, note: Option<&str>) {
         if vis != &Visibility::Inherited {
             let mut err = struct_span_err!(self.session,
@@ -213,7 +222,7 @@ fn visit_item(&mut self, item: &'a Item) {
                                         item.span,
                                         Some("place qualifiers on individual impl items instead"));
             }
-            ItemKind::DefaultImpl(..) => {
+            ItemKind::AutoImpl(..) => {
                 self.invalid_visibility(&item.vis, item.span, None);
             }
             ItemKind::ForeignMod(..) => {
@@ -224,12 +233,28 @@ fn visit_item(&mut self, item: &'a Item) {
             }
             ItemKind::Enum(ref def, _) => {
                 for variant in &def.variants {
+                    self.invalid_non_exhaustive_attribute(variant);
                     for field in variant.node.data.fields() {
                         self.invalid_visibility(&field.vis, field.span, None);
                     }
                 }
             }
-            ItemKind::Trait(.., ref bounds, ref trait_items) => {
+            ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
+                if is_auto == IsAuto::Yes {
+                    // Auto traits cannot have generics, super traits nor contain items.
+                    if !generics.ty_params.is_empty() {
+                        self.err_handler().span_err(item.span,
+                                                    "auto traits cannot have generics");
+                    }
+                    if !bounds.is_empty() {
+                        self.err_handler().span_err(item.span,
+                                                    "auto traits cannot have super traits");
+                    }
+                    if !trait_items.is_empty() {
+                        self.err_handler().span_err(item.span,
+                                                    "auto traits cannot contain items");
+                    }
+                }
                 self.no_questions_in_bounds(bounds, "supertraits", true);
                 for trait_item in trait_items {
                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
index 3f75c6385223e0094019dee5c12e2e7842cba56b..ab41ad1e0995056c46635618869377fffad65af6 100644 (file)
@@ -121,6 +121,7 @@ fn visit_terminator_kind(&mut self,
             TerminatorKind::Assert { .. } => "TerminatorKind::Assert",
             TerminatorKind::GeneratorDrop => "TerminatorKind::GeneratorDrop",
             TerminatorKind::Yield { .. } => "TerminatorKind::Yield",
+            TerminatorKind::FalseEdges { .. } => "TerminatorKind::FalseEdges",
         }, kind);
         self.super_terminator_kind(block, kind, location);
     }
index 3beba03ee1401884cf2915b78c1b8a0d68fed7e4..630260feed789acc5a11f51f99165a140e0b71f8 100644 (file)
@@ -147,7 +147,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 let def_id = self.tcx.hir.local_def_id(item.id);
                 cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id))
             }
-            hir::ItemDefaultImpl(..) => {
+            hir::ItemAutoImpl(..) => {
                 let def_id = self.tcx.hir.local_def_id(item.id);
                 self.impl_trait_level(def_id)
             }
@@ -213,7 +213,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             }
             hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
             hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
-            hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemDefaultImpl(..) => {}
+            hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemAutoImpl(..) => {}
         }
 
         // Mark all items in interfaces of reachable items as reachable
@@ -225,7 +225,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
             // Reexports are handled in visit_mod
             hir::ItemUse(..) => {}
             // The interface is empty
-            hir::ItemDefaultImpl(..) => {}
+            hir::ItemAutoImpl(..) => {}
             // The interface is empty
             hir::ItemGlobalAsm(..) => {}
             // Visit everything
@@ -627,6 +627,16 @@ fn def_id_visibility(&self, did: DefId) -> ty::Visibility {
                                 ctor_vis = field_vis;
                             }
                         }
+
+                        // If the structure is marked as non_exhaustive then lower the
+                        // visibility to within the crate.
+                        let struct_def_id = self.tcx.hir.get_parent_did(node_id);
+                        let adt_def = self.tcx.adt_def(struct_def_id);
+                        if adt_def.is_non_exhaustive() && ctor_vis == ty::Visibility::Public {
+                            ctor_vis = ty::Visibility::Restricted(
+                                DefId::local(CRATE_DEF_INDEX));
+                        }
+
                         return ctor_vis;
                     }
                     node => bug!("unexpected node kind: {:?}", node)
@@ -1504,7 +1514,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 }
             }
             // The interface is empty
-            hir::ItemDefaultImpl(..) => {}
+            hir::ItemAutoImpl(..) => {}
             // An inherent impl is public when its type is public
             // Subitems of inherent impls have their own publicity
             hir::ItemImpl(.., None, _, ref impl_item_refs) => {
index 0968ea31b754f9e7b2d0e47f5ccd871156483204..ab2d152b724a7227be3528a9cf48a9bf4e054f25 100644 (file)
@@ -16,3 +16,4 @@ rustc = { path = "../librustc" }
 arena = { path = "../libarena" }
 rustc_errors = { path = "../librustc_errors" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc_data_structures = { path = "../librustc_data_structures" }
index 880b370c7f66b07c3ac9bc5f7d65ae6b7b2a14d6..a10bce293422645ea01729844bb0c4e9edb3f1bf 100644 (file)
@@ -338,11 +338,22 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
             // These items live in both the type and value namespaces.
             ItemKind::Struct(ref struct_def, _) => {
                 // Define a name in the type namespace.
-                let def = Def::Struct(self.definitions.local_def_id(item.id));
+                let def_id = self.definitions.local_def_id(item.id);
+                let def = Def::Struct(def_id);
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
 
-                // Record field names for error reporting.
                 let mut ctor_vis = vis;
+
+                let has_non_exhaustive = item.attrs.iter()
+                    .any(|item| item.check_name("non_exhaustive"));
+
+                // If the structure is marked as non_exhaustive then lower the visibility
+                // to within the crate.
+                if has_non_exhaustive && vis == ty::Visibility::Public {
+                    ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+                }
+
+                // Record field names for error reporting.
                 let field_names = struct_def.fields().iter().filter_map(|field| {
                     let field_vis = self.resolve_visibility(&field.vis);
                     if ctor_vis.is_at_least(field_vis, &*self) {
@@ -376,7 +387,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 self.insert_field_names(item_def_id, field_names);
             }
 
-            ItemKind::DefaultImpl(..) | ItemKind::Impl(..) => {}
+            ItemKind::AutoImpl(..) | ItemKind::Impl(..) => {}
 
             ItemKind::Trait(..) => {
                 let def_id = self.definitions.local_def_id(item.id);
@@ -414,6 +425,7 @@ fn build_reduced_graph_for_variant(&mut self,
         // value namespace, they are reserved for possible future use.
         let ctor_kind = CtorKind::from_ast(&variant.node.data);
         let ctor_def = Def::VariantCtor(def_id, ctor_kind);
+
         self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
     }
 
index 3b27890013a227f28a1c9dd7db6b5b62b6d6ac57..bed9f37c5157fab483b947fbf3b70a54e706f490 100644 (file)
@@ -24,6 +24,7 @@
 extern crate arena;
 #[macro_use]
 extern crate rustc;
+extern crate rustc_data_structures;
 
 use self::Namespace::*;
 use self::TypeParameters::*;
@@ -59,7 +60,7 @@
 use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue};
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 
 use std::cell::{Cell, RefCell};
 use std::cmp;
@@ -223,7 +224,11 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             let target_sp = binding_error.target.iter().map(|x| *x).collect::<Vec<_>>();
             let msp = MultiSpan::from_spans(target_sp.clone());
             let msg = format!("variable `{}` is not bound in all patterns", binding_error.name);
-            let mut err = resolver.session.struct_span_err_with_code(msp, &msg, "E0408");
+            let mut err = resolver.session.struct_span_err_with_code(
+                msp,
+                &msg,
+                DiagnosticId::Error("E0408".into()),
+            );
             for sp in target_sp {
                 err.span_label(sp, format!("pattern doesn't bind `{}`", binding_error.name));
             }
@@ -1841,7 +1846,7 @@ fn resolve_item(&mut self, item: &Item) {
                                              |this| visit::walk_item(this, item));
             }
 
-            ItemKind::DefaultImpl(_, ref trait_ref) => {
+            ItemKind::AutoImpl(_, ref trait_ref) => {
                 self.with_optional_trait_ref(Some(trait_ref), |this, _| {
                     // Resolve type arguments in trait path
                     visit::walk_trait_ref(this, trait_ref);
@@ -1854,7 +1859,7 @@ fn resolve_item(&mut self, item: &Item) {
                                             item.id,
                                             impl_items),
 
-            ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
+            ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
                     let local_def_id = this.definitions.local_def_id(item.id);
@@ -2490,18 +2495,19 @@ fn smart_resolve_path_fragment(&mut self,
                 (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
                  format!("not found in {}", mod_str), item_span)
             };
+            let code = DiagnosticId::Error(code.into());
             let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
 
             // Emit special messages for unresolved `Self` and `self`.
             if is_self_type(path, ns) {
                 __diagnostic_used!(E0411);
-                err.code("E0411".into());
+                err.code(DiagnosticId::Error("E0411".into()));
                 err.span_label(span, "`Self` is only available in traits and impls");
                 return (err, Vec::new());
             }
             if is_self_value(path, ns) {
                 __diagnostic_used!(E0424);
-                err.code("E0424".into());
+                err.code(DiagnosticId::Error("E0424".into()));
                 err.span_label(span, format!("`self` value is only available in \
                                                methods with `self` parameter"));
                 return (err, Vec::new());
index 064032b888499abb77d13451e8c2c4967dee59c8..a52e6fcad14812bf34841ffebe53c5bd1a01c27a 100644 (file)
@@ -13,6 +13,7 @@
 use Namespace::{self, MacroNS};
 use build_reduced_graph::BuildReducedGraphVisitor;
 use resolve_imports::ImportResolver;
+use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
 use rustc::hir::def::{Def, Export};
 use rustc::hir::map::{self, DefCollector};
index 2658ba22e7d1642d94be429778361a9c996b03a3..d190ae1431fd80db73e78f9d15c27645a924f7d2 100644 (file)
@@ -322,16 +322,15 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
             let mut collector = PathCollector::new();
             collector.visit_pat(&arg.pat);
             let span_utils = self.span.clone();
-            for &(id, ref p, ..) in &collector.collected_paths {
+
+            for (id, i, sp, ..) in collector.collected_idents {
                 let hir_id = self.tcx.hir.node_to_hir_id(id);
                 let typ = match self.save_ctxt.tables.node_id_to_type_opt(hir_id) {
                     Some(s) => s.to_string(),
                     None => continue,
                 };
-                // get the span only for the name of the variable (I hope the path is only ever a
-                // variable name, but who knows?)
-                let sub_span = span_utils.span_for_last_ident(p.span);
-                if !self.span.filter_generated(sub_span, p.span) {
+                let sub_span = span_utils.span_for_last_ident(sp);
+                if !self.span.filter_generated(sub_span, sp) {
                     let id = ::id_from_node_id(id, &self.save_ctxt);
                     let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
@@ -339,8 +338,8 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
                         kind: DefKind::Local,
                         id,
                         span,
-                        name: path_to_string(p),
-                        qualname: format!("{}::{}", qualname, path_to_string(p)),
+                        name: i.to_string(),
+                        qualname: format!("{}::{}", qualname, i.to_string()),
                         value: typ,
                         parent: None,
                         children: vec![],
@@ -395,14 +394,6 @@ fn process_method(&mut self,
         }
     }
 
-    fn process_trait_ref(&mut self, trait_ref: &'l ast::TraitRef) {
-        let trait_ref_data = self.save_ctxt.get_trait_ref_data(trait_ref);
-        if let Some(trait_ref_data) = trait_ref_data {
-            self.dumper.dump_ref(trait_ref_data);
-        }
-        self.process_path(trait_ref.ref_id, &trait_ref.path);
-    }
-
     fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
         let field_data = self.save_ctxt.get_field_data(field, parent_id);
         if let Some(field_data) = field_data {
@@ -530,36 +521,43 @@ fn process_struct(&mut self,
                       item: &'l ast::Item,
                       def: &'l ast::VariantData,
                       ty_params: &'l ast::Generics) {
+        debug!("process_struct {:?} {:?}", item, item.span);
         let name = item.ident.to_string();
         let qualname = format!("::{}", self.tcx.node_path_str(item.id));
 
-        let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
-        let (value, fields) =
-            if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node
-        {
-            let include_priv_fields = !self.save_ctxt.config.pub_only;
-            let fields_str = fields
-                .iter()
-                .enumerate()
-                .filter_map(|(i, f)| {
-                     if include_priv_fields || f.vis == ast::Visibility::Public {
-                         f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
-                     } else {
-                         None
-                     }
-                })
-                .collect::<Vec<_>>()
-                .join(", ");
-            let value = format!("{} {{ {} }}", name, fields_str);
-            (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
-        } else {
-            (String::new(), vec![])
+        let (kind, keyword) = match item.node {
+            ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct),
+            ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union),
+            _ => unreachable!(),
+        };
+
+        let sub_span = self.span.sub_span_after_keyword(item.span, keyword);
+        let (value, fields) = match item.node {
+            ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) |
+            ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => {
+                let include_priv_fields = !self.save_ctxt.config.pub_only;
+                let fields_str = fields
+                    .iter()
+                    .enumerate()
+                    .filter_map(|(i, f)| {
+                         if include_priv_fields || f.vis == ast::Visibility::Public {
+                             f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
+                         } else {
+                             None
+                         }
+                    })
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                let value = format!("{} {{ {} }}", name, fields_str);
+                (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
+            }
+            _ => (String::new(), vec![])
         };
 
         if !self.span.filter_generated(sub_span, item.span) {
             let span = self.span_from_span(sub_span.expect("No span found for struct"));
             self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
-                kind: DefKind::Struct,
+                kind,
                 id: ::id_from_node_id(item.id, &self.save_ctxt),
                 span,
                 name,
@@ -787,7 +785,8 @@ fn process_mod(&mut self, item: &ast::Item) {
         }
     }
 
-    fn process_path(&mut self, id: NodeId, path: &ast::Path) {
+    fn process_path(&mut self, id: NodeId, path: &'l ast::Path) {
+        debug!("process_path {:?}", path);
         let path_data = self.save_ctxt.get_path_data(id, path);
         if generated_code(path.span) && path_data.is_none() {
             return;
@@ -802,6 +801,27 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path) {
 
         self.dumper.dump_ref(path_data);
 
+        // Type parameters
+        for seg in &path.segments {
+            if let Some(ref params) = seg.parameters {
+                match **params {
+                    ast::PathParameters::AngleBracketed(ref data) => {
+                        for t in &data.types {
+                            self.visit_ty(t);
+                        }
+                    }
+                    ast::PathParameters::Parenthesized(ref data) => {
+                        for t in &data.inputs {
+                            self.visit_ty(t);
+                        }
+                        if let Some(ref t) = data.output {
+                            self.visit_ty(t);
+                        }
+                    }
+                }
+            }
+        }
+
         // Modules or types in the path prefix.
         match self.save_ctxt.get_path_def(id) {
             HirDef::Method(did) => {
@@ -854,7 +874,11 @@ fn process_struct_lit(&mut self,
         walk_list!(self, visit_expr, base);
     }
 
-    fn process_method_call(&mut self, ex: &'l ast::Expr, args: &'l [P<ast::Expr>]) {
+    fn process_method_call(&mut self,
+                           ex: &'l ast::Expr,
+                           seg: &'l ast::PathSegment,
+                           args: &'l [P<ast::Expr>]) {
+        debug!("process_method_call {:?} {:?}", ex, ex.span);
         if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
             down_cast_data!(mcd, RefData, ex.span);
             if !generated_code(ex.span) {
@@ -862,6 +886,15 @@ fn process_method_call(&mut self, ex: &'l ast::Expr, args: &'l [P<ast::Expr>]) {
             }
         }
 
+        // Explicit types in the turbo-fish.
+        if let Some(ref params) = seg.parameters {
+            if let ast::PathParameters::AngleBracketed(ref data) = **params {
+                for t in &data.types {
+                    self.visit_ty(t);
+                }
+            }
+        }
+
         // walk receiver and args
         walk_list!(self, visit_expr, args);
     }
@@ -908,7 +941,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
         collector.visit_pat(&p);
         self.visit_pat(&p);
 
-        for &(id, ref p, immut) in &collector.collected_paths {
+        for (id, i, sp, immut) in collector.collected_idents {
             let mut value = match immut {
                 ast::Mutability::Immutable => value.to_string(),
                 _ => String::new(),
@@ -928,10 +961,10 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
 
             // Get the span only for the name of the variable (I hope the path
             // is only ever a variable name, but who knows?).
-            let sub_span = self.span.span_for_last_ident(p.span);
+            let sub_span = self.span.span_for_last_ident(sp);
             // Rust uses the id of the pattern for var lookups, so we'll use it too.
-            if !self.span.filter_generated(sub_span, p.span) {
-                let qualname = format!("{}${}", path_to_string(p), id);
+            if !self.span.filter_generated(sub_span, sp) {
+                let qualname = format!("{}${}", i.to_string(), id);
                 let id = ::id_from_node_id(id, &self.save_ctxt);
                 let span = self.span_from_span(sub_span.expect("No span found for variable"));
 
@@ -939,7 +972,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
                     kind: DefKind::Local,
                     id,
                     span,
-                    name: path_to_string(p),
+                    name: i.to_string(),
                     qualname,
                     value: typ,
                     parent: None,
@@ -1216,7 +1249,9 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                 self.process_static_or_const_item(item, typ, expr),
             Const(ref typ, ref expr) =>
                 self.process_static_or_const_item(item, &typ, &expr),
-            Struct(ref def, ref ty_params) => self.process_struct(item, def, ty_params),
+            Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => {
+                self.process_struct(item, def, ty_params)
+            }
             Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
             Impl(..,
                  ref ty_params,
@@ -1225,7 +1260,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                  ref impl_items) => {
                 self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
             }
-            Trait(_, ref generics, ref trait_refs, ref methods) =>
+            Trait(_, _, ref generics, ref trait_refs, ref methods) =>
                 self.process_trait(item, generics, trait_refs, methods),
             Mod(ref m) => {
                 self.process_mod(item);
@@ -1267,7 +1302,7 @@ fn visit_generics(&mut self, generics: &'l ast::Generics) {
         for param in generics.ty_params.iter() {
             for bound in param.bounds.iter() {
                 if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
-                    self.process_trait_ref(&trait_ref.trait_ref);
+                    self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
                 }
             }
             if let Some(ref ty) = param.default {
@@ -1322,7 +1357,7 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                 let def = self.save_ctxt.get_path_def(hir_expr.id);
                 self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
             }
-            ast::ExprKind::MethodCall(.., ref args) => self.process_method_call(ex, args),
+            ast::ExprKind::MethodCall(ref seg, ref args) => self.process_method_call(ex, seg, args),
             ast::ExprKind::Field(ref sub_ex, _) => {
                 self.visit_expr(&sub_ex);
 
@@ -1394,15 +1429,15 @@ fn visit_expr(&mut self, ex: &'l ast::Expr) {
                 let value = self.span.snippet(subexpression.span);
                 self.process_var_decl(pattern, value);
                 debug!("for loop, walk sub-expr: {:?}", subexpression.node);
-                visit::walk_expr(self, subexpression);
+                self.visit_expr(subexpression);
                 visit::walk_block(self, block);
             }
             ast::ExprKind::IfLet(ref pattern, ref subexpression, ref block, ref opt_else) => {
                 let value = self.span.snippet(subexpression.span);
                 self.process_var_decl(pattern, value);
-                visit::walk_expr(self, subexpression);
+                self.visit_expr(subexpression);
                 visit::walk_block(self, block);
-                opt_else.as_ref().map(|el| visit::walk_expr(self, el));
+                opt_else.as_ref().map(|el| self.visit_expr(el));
             }
             ast::ExprKind::Repeat(ref element, ref count) => {
                 self.visit_expr(element);
@@ -1434,15 +1469,12 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
             self.visit_pat(&pattern);
         }
 
-        // This is to get around borrow checking, because we need mut self to call process_path.
-        let mut paths_to_process = vec![];
-
         // process collected paths
-        for &(id, ref p, immut) in &collector.collected_paths {
+        for (id, i, sp, immut) in collector.collected_idents {
             match self.save_ctxt.get_path_def(id) {
                 HirDef::Local(id) => {
                     let mut value = if immut == ast::Mutability::Immutable {
-                        self.span.snippet(p.span).to_string()
+                        self.span.snippet(sp).to_string()
                     } else {
                         "<mutable>".to_string()
                     };
@@ -1455,18 +1487,16 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                     value.push_str(": ");
                     value.push_str(&typ);
 
-                    assert!(p.segments.len() == 1,
-                            "qualified path for local variable def in arm");
-                    if !self.span.filter_generated(Some(p.span), p.span) {
-                        let qualname = format!("{}${}", path_to_string(p), id);
+                    if !self.span.filter_generated(Some(sp), sp) {
+                        let qualname = format!("{}${}", i.to_string(), id);
                         let id = ::id_from_node_id(id, &self.save_ctxt);
-                        let span = self.span_from_span(p.span);
+                        let span = self.span_from_span(sp);
 
                         self.dumper.dump_def(false, Def {
                             kind: DefKind::Local,
                             id,
                             span,
-                            name: path_to_string(p),
+                            name: i.to_string(),
                             qualname,
                             value: typ,
                             parent: None,
@@ -1478,19 +1508,12 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                         });
                     }
                 }
-                HirDef::StructCtor(..) | HirDef::VariantCtor(..) |
-                HirDef::Const(..) | HirDef::AssociatedConst(..) |
-                HirDef::Struct(..) | HirDef::Variant(..) |
-                HirDef::TyAlias(..) | HirDef::AssociatedTy(..) |
-                HirDef::SelfTy(..) => {
-                    paths_to_process.push((id, p.clone()))
-                }
-                def => error!("unexpected definition kind when processing collected paths: {:?}",
+                def => error!("unexpected definition kind when processing collected idents: {:?}",
                               def),
             }
         }
 
-        for &(id, ref path) in &paths_to_process {
+        for (id, ref path) in collector.collected_paths {
             self.process_path(id, path);
         }
         walk_list!(self, visit_expr, &arm.guard);
index f98a89781f74d68582b65139cb44121e309bf41a..edb51ae59e1b56c8b431893212f0e0fd87aa9693 100644 (file)
@@ -546,16 +546,16 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
                     }
                 }
             }
-            ast::ExprKind::MethodCall(..) => {
+            ast::ExprKind::MethodCall(ref seg, ..) => {
                 let expr_hir_id = self.tcx.hir.definitions().node_to_hir_id(expr.id);
                 let method_id = self.tables.type_dependent_defs()[expr_hir_id].def_id();
                 let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
                     ty::ImplContainer(_) => (Some(method_id), None),
                     ty::TraitContainer(_) => (None, Some(method_id)),
                 };
-                let sub_span = self.span_utils.sub_span_for_meth_name(expr.span);
-                filter!(self.span_utils, sub_span, expr.span, None);
-                let span = self.span_from_span(sub_span.unwrap());
+                let sub_span = seg.span;
+                filter!(self.span_utils, Some(sub_span), expr.span, None);
+                let span = self.span_from_span(sub_span);
                 Some(Data::RefData(Ref {
                     kind: RefKind::Function,
                     span,
@@ -579,8 +579,8 @@ pub fn get_path_def(&self, id: NodeId) -> HirDef {
             Node::NodeItem(&hir::Item { node: hir::ItemUse(ref path, _), .. }) |
             Node::NodeVisibility(&hir::Visibility::Restricted { ref path, .. }) => path.def,
 
-            Node::NodeExpr(&hir::Expr { node: hir::ExprPath(ref qpath), .. }) |
             Node::NodeExpr(&hir::Expr { node: hir::ExprStruct(ref qpath, ..), .. }) |
+            Node::NodeExpr(&hir::Expr { node: hir::ExprPath(ref qpath), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => {
@@ -614,13 +614,31 @@ pub fn get_path_def(&self, id: NodeId) -> HirDef {
     }
 
     pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
+        // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
+        fn fn_type(path: &ast::Path) -> bool {
+            if path.segments.len() != 1 {
+                return false;
+            }
+            if let Some(ref params) = path.segments[0].parameters {
+                if let ast::PathParameters::Parenthesized(_) = **params {
+                    return true;
+                }
+            }
+            false
+        }
+
+        if path.segments.is_empty() {
+            return None;
+        }
+
         let def = self.get_path_def(id);
-        let sub_span = self.span_utils.span_for_last_ident(path.span);
-        filter!(self.span_utils, sub_span, path.span, None);
+        let last_seg = &path.segments[path.segments.len() - 1];
+        let sub_span = last_seg.span;
+        filter!(self.span_utils, Some(sub_span), path.span, None);
         match def {
             HirDef::Upvar(id, ..) |
             HirDef::Local(id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
@@ -630,15 +648,24 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
             HirDef::Static(..) |
             HirDef::Const(..) |
             HirDef::AssociatedConst(..) |
-            HirDef::StructCtor(..) |
             HirDef::VariantCtor(..) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
                     ref_id: id_from_def_id(def.def_id()),
                 })
             }
+            HirDef::Trait(def_id) if fn_type(path) => {
+                // Function type bounds are desugared in the parser, so we have to
+                // special case them here.
+                let fn_span = self.span_utils.span_for_first_ident(path.span);
+                fn_span.map(|span| Ref {
+                    kind: RefKind::Type,
+                    span: self.span_from_span(span),
+                    ref_id: id_from_def_id(def_id),
+                })
+            }
             HirDef::Struct(def_id) |
             HirDef::Variant(def_id, ..) |
             HirDef::Union(def_id) |
@@ -648,16 +675,26 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
             HirDef::AssociatedTy(def_id) |
             HirDef::Trait(def_id) |
             HirDef::TyParam(def_id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Type,
                     span,
                     ref_id: id_from_def_id(def_id),
                 })
             }
+            HirDef::StructCtor(def_id, _) => {
+                // This is a reference to a tuple struct where the def_id points
+                // to an invisible constructor function. That is not a very useful
+                // def, so adjust to point to the tuple struct itself.
+                let span = self.span_from_span(sub_span);
+                let parent_def_id = self.tcx.parent_def_id(def_id).unwrap();
+                Some(Ref {
+                    kind: RefKind::Type,
+                    span,
+                    ref_id: id_from_def_id(parent_def_id),
+                })
+            }
             HirDef::Method(decl_id) => {
-                let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
-                filter!(self.span_utils, sub_span, path.span, None);
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
                     self.tcx.associated_items(ti.container.id())
@@ -666,7 +703,7 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
                 } else {
                     None
                 };
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Function,
                     span,
@@ -674,7 +711,7 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
                 })
             }
             HirDef::Fn(def_id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Function,
                     span,
@@ -682,7 +719,7 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Ref> {
                 })
             }
             HirDef::Mod(def_id) => {
-                let span = self.span_from_span(sub_span.unwrap());
+                let span = self.span_from_span(sub_span);
                 Some(Ref {
                     kind: RefKind::Mod,
                     span,
@@ -818,29 +855,31 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String {
     sig
 }
 
-// An AST visitor for collecting paths from patterns.
-struct PathCollector {
-    // The Row field identifies the kind of pattern.
-    collected_paths: Vec<(NodeId, ast::Path, ast::Mutability)>,
+// An AST visitor for collecting paths (e.g., the names of structs) and formal
+// variables (idents) from patterns.
+struct PathCollector<'l> {
+    collected_paths: Vec<(NodeId, &'l ast::Path)>,
+    collected_idents: Vec<(NodeId, ast::Ident, Span, ast::Mutability)>,
 }
 
-impl PathCollector {
-    fn new() -> PathCollector {
-        PathCollector { collected_paths: vec![] }
+impl<'l> PathCollector<'l> {
+    fn new() -> PathCollector<'l> {
+        PathCollector {
+            collected_paths: vec![],
+            collected_idents: vec![],
+        }
     }
 }
 
-impl<'a> Visitor<'a> for PathCollector {
-    fn visit_pat(&mut self, p: &ast::Pat) {
+impl<'l, 'a: 'l> Visitor<'a> for PathCollector<'l> {
+    fn visit_pat(&mut self, p: &'a ast::Pat) {
         match p.node {
             PatKind::Struct(ref path, ..) => {
-                self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable));
+                self.collected_paths.push((p.id, path));
             }
             PatKind::TupleStruct(ref path, ..) |
             PatKind::Path(_, ref path) => {
-                self.collected_paths.push((p.id, path.clone(),
-                                           ast::Mutability::Mutable));
+                self.collected_paths.push((p.id, path));
             }
             PatKind::Ident(bm, ref path1, _) => {
                 debug!("PathCollector, visit ident in pat {}: {:?} {:?}",
@@ -854,9 +893,7 @@ fn visit_pat(&mut self, p: &ast::Pat) {
                     ast::BindingMode::ByRef(_) => ast::Mutability::Immutable,
                     ast::BindingMode::ByValue(mt) => mt,
                 };
-                // collect path for either visit_local or visit_arm
-                let path = ast::Path::from_ident(path1.span, path1.node);
-                self.collected_paths.push((p.id, path, immut));
+                self.collected_idents.push((p.id, path1.node, path1.span, immut));
             }
             _ => {}
         }
index b0844d1b82404f0f53c493dfc803797de1c68818..80c1b0ebeb0b2d307518dd11bd0f27fbebe5477b 100644 (file)
@@ -477,8 +477,13 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                 sig.text.push_str(" {}");
                 Ok(sig)
             }
-            ast::ItemKind::Trait(unsafety, ref generics, ref bounds, _) => {
+            ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, _) => {
                 let mut text = String::new();
+
+                if is_auto == ast::IsAuto::Yes {
+                    text.push_str("auto ");
+                }
+
                 if unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
                 }
@@ -499,7 +504,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
 
                 Ok(sig)
             }
-            ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
+            ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
                 let mut text = String::new();
                 if unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
index b9d82b8e2512a1c21bb64a871c7b879c6274222f..5bfb4d1b3b20389546be7f1fba6538b64fe5165f 100644 (file)
@@ -103,47 +103,6 @@ pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
         }
     }
 
-    // Return the span for the last ident before a `(` or `<` or '::<' and outside any
-    // any brackets, or the last span.
-    pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
-        let mut toks = self.retokenise_span(span);
-        let mut prev = toks.real_token();
-        let mut result = None;
-        let mut bracket_count = 0;
-        let mut prev_span = None;
-        while prev.tok != token::Eof {
-            prev_span = None;
-            let mut next = toks.real_token();
-
-            if (next.tok == token::OpenDelim(token::Paren) || next.tok == token::Lt) &&
-               bracket_count == 0 && prev.tok.is_ident() {
-                result = Some(prev.sp);
-            }
-
-            if bracket_count == 0 && next.tok == token::ModSep {
-                let old = prev;
-                prev = next;
-                next = toks.real_token();
-                if next.tok == token::Lt && old.tok.is_ident() {
-                    result = Some(old.sp);
-                }
-            }
-
-            bracket_count += match prev.tok {
-                token::OpenDelim(token::Paren) | token::Lt => 1,
-                token::CloseDelim(token::Paren) | token::Gt => -1,
-                token::BinOp(token::Shr) => -2,
-                _ => 0,
-            };
-
-            if prev.tok.is_ident() && bracket_count == 0 {
-                prev_span = Some(prev.sp);
-            }
-            prev = next;
-        }
-        result.or(prev_span)
-    }
-
     // Return the span for the last ident before a `<` and outside any
     // angle brackets, or the last span.
     pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
@@ -330,7 +289,7 @@ pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
 }
 
 macro_rules! filter {
-    ($util: expr, $span: ident, $parent: expr, None) => {
+    ($util: expr, $span: expr, $parent: expr, None) => {
         if $util.filter_generated($span, $parent) {
             return None;
         }
index b203bd640cf1467fb79441dcdb83e146b7b06c1f..907693ea8a379ee179908b9132eefaf70cc02dcf 100644 (file)
@@ -1222,7 +1222,7 @@ fn add_static_crate(cmd: &mut Linker,
                 let canonical = f.replace("-", "_");
                 let canonical_name = name.replace("-", "_");
 
-                // Look for `.rust-cgu.o` at the end of the filename to conclude
+                // Look for `.rcgu.o` at the end of the filename to conclude
                 // that this is a Rust-related object file.
                 fn looks_like_rust(s: &str) -> bool {
                     let path = Path::new(s);
index eb1c5cb78815344b56e09e4ad014572c3a0f5cf7..b9519bba2dd89b1eb6ed337a3c5b071ef346076c 100644 (file)
@@ -21,6 +21,7 @@
 use rustc::ty::maps::Providers;
 use rustc::util::nodemap::FxHashMap;
 use rustc_allocator::ALLOCATOR_METHODS;
+use syntax::attr;
 
 pub type ExportedSymbols = FxHashMap<
     CrateNum,
@@ -180,7 +181,15 @@ pub fn provide_extern(providers: &mut Providers) {
 }
 
 fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
-    if tcx.contains_extern_indicator(sym_def_id) {
+    // We export anything that's not mangled at the "C" layer as it probably has
+    // to do with ABI concerns. We do not, however, apply such treatment to
+    // special symbols in the standard library for various plumbing between
+    // core/std/allocators/etc. For example symbols used to hook up allocation
+    // are not considered for export
+    let is_extern = tcx.contains_extern_indicator(sym_def_id);
+    let std_internal = attr::contains_name(&tcx.get_attrs(sym_def_id),
+                                           "rustc_std_internal_symbol");
+    if is_extern && !std_internal {
         SymbolExportLevel::C
     } else {
         SymbolExportLevel::Rust
index 5550ab9fa55e6752863dc192fd75f9d29ee8eec9..10475a2b1b1a06fa98ff3b2a99a73d84d969fdd3 100644 (file)
@@ -32,7 +32,7 @@
 use rustc::ty::TyCtxt;
 use rustc::util::common::{time, time_depth, set_time_depth, path2cstr, print_time_passes_entry};
 use rustc::util::fs::{link_or_copy, rename_or_copy_remove};
-use errors::{self, Handler, Level, DiagnosticBuilder, FatalError};
+use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
 use errors::emitter::{Emitter};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
@@ -1262,7 +1262,7 @@ enum Message {
 
 struct Diagnostic {
     msg: String,
-    code: Option<String>,
+    code: Option<DiagnosticId>,
     lvl: Level,
 }
 
@@ -2015,7 +2015,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
                         Some(ref code) => {
                             handler.emit_with_code(&MultiSpan::new(),
                                                    &diag.msg,
-                                                   &code,
+                                                   code.clone(),
                                                    diag.lvl);
                         }
                         None => {
index 00815be278ee0e845c14caacb1199e68078e101e..73f60ff29a85141c1987dcea6725c6c3c75cb3e2 100644 (file)
@@ -228,7 +228,8 @@ fn discover_masters<'tcx>(result: &mut IndexVec<mir::BasicBlock, CleanupKind>,
                 TerminatorKind::GeneratorDrop |
                 TerminatorKind::Unreachable |
                 TerminatorKind::SwitchInt { .. } |
-                TerminatorKind::Yield { .. }  => {
+                TerminatorKind::Yield { .. } |
+                TerminatorKind::FalseEdges { .. } => {
                     /* nothing to do */
                 }
                 TerminatorKind::Call { cleanup: unwind, .. } |
index 591aa974666cce89dbff36feafed0bebb0424d6f..11d992bd4cf0eb89fd891ada29090af21c0fc5d8 100644 (file)
@@ -583,7 +583,8 @@ fn trans_terminator(&mut self,
                         cleanup);
             }
             mir::TerminatorKind::GeneratorDrop |
-            mir::TerminatorKind::Yield { .. } => bug!("generator ops in trans"),
+            mir::TerminatorKind::Yield { .. } |
+            mir::TerminatorKind::FalseEdges { .. } => bug!("generator ops in trans"),
         }
     }
 
index cf9b80e5ed404a140b5397dc2714bacf0cb49ea2..fd003fc097933c1cfddd0274994d9a7efe3891a9 100644 (file)
@@ -623,7 +623,8 @@ fn visit_terminator_kind(&mut self,
             mir::TerminatorKind::Unreachable |
             mir::TerminatorKind::Assert { .. } => {}
             mir::TerminatorKind::GeneratorDrop |
-            mir::TerminatorKind::Yield { .. } => bug!(),
+            mir::TerminatorKind::Yield { .. } |
+            mir::TerminatorKind::FalseEdges { .. } => bug!(),
         }
 
         self.super_terminator_kind(block, kind, location);
@@ -883,7 +884,7 @@ fn visit_item(&mut self, item: &'v hir::Item) {
             hir::ItemUse(..)         |
             hir::ItemForeignMod(..)  |
             hir::ItemTy(..)          |
-            hir::ItemDefaultImpl(..) |
+            hir::ItemAutoImpl(..) |
             hir::ItemTrait(..)       |
             hir::ItemMod(..)         => {
                 // Nothing to do, just keep recursing...
index a38f04e304b6c38d5b1da48341d48ec7e0e59003..1abc914e7d66155b462bc1e6c5b2beaed60d4a1e 100644 (file)
@@ -12,7 +12,7 @@ The `rustc_typeck` crate contains the source for "type collection" and
 
 ## Type collection
 
-Type "collection" is the process of convering the types found in the
+Type "collection" is the process of converting the types found in the
 HIR (`hir::Ty`), which represent the syntactic things that the user
 wrote, into the **internal representation** used by the compiler
 (`Ty<'tcx>`) -- we also do similar conversions for where-clauses and
index c7f7e62fd61ef0f627eb6bd49b30c3c6dd9bd583..1471e235156eb8ade6a050fe0668ceb92e75565a 100644 (file)
@@ -1206,60 +1206,6 @@ pub fn ty_of_fn(&self,
         bare_fn_ty
     }
 
-    pub fn ty_of_closure(&self,
-        unsafety: hir::Unsafety,
-        decl: &hir::FnDecl,
-        abi: abi::Abi,
-        expected_sig: Option<ty::FnSig<'tcx>>)
-        -> ty::PolyFnSig<'tcx>
-    {
-        debug!("ty_of_closure(expected_sig={:?})",
-               expected_sig);
-
-        let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| {
-            let expected_arg_ty = expected_sig.as_ref().and_then(|e| {
-                // no guarantee that the correct number of expected args
-                // were supplied
-                if i < e.inputs().len() {
-                    Some(e.inputs()[i])
-                } else {
-                    None
-                }
-            });
-            self.ty_of_arg(a, expected_arg_ty)
-        });
-
-        let expected_ret_ty = expected_sig.as_ref().map(|e| e.output());
-
-        let output_ty = match decl.output {
-            hir::Return(ref output) => {
-                if let (&hir::TyInfer, Some(expected_ret_ty)) = (&output.node, expected_ret_ty) {
-                    self.record_ty(output.hir_id, expected_ret_ty, output.span);
-                    expected_ret_ty
-                } else {
-                    self.ast_ty_to_ty(&output)
-                }
-            }
-            hir::DefaultReturn(span) => {
-                if let Some(expected_ret_ty) = expected_ret_ty {
-                    expected_ret_ty
-                } else {
-                    self.ty_infer(span)
-                }
-            }
-        };
-
-        debug!("ty_of_closure: output_ty={:?}", output_ty);
-
-        ty::Binder(self.tcx().mk_fn_sig(
-            input_tys,
-            output_ty,
-            decl.variadic,
-            unsafety,
-            abi
-        ))
-    }
-
     /// Given the bounds on an object, determines what single region bound (if any) we can
     /// use to summarize this type. The basic idea is that we will use the bound the user
     /// provided, if they provided one, and otherwise search the supertypes of trait bounds
index ab8994bcae2537bed89e4f3bcee629111802b1ff..272f13b28030ebbd86e873283224c8138ea7ff27 100644 (file)
@@ -23,6 +23,7 @@
 use std::cmp;
 use syntax::ast;
 use syntax::codemap::Spanned;
+use syntax::feature_gate;
 use syntax::ptr::P;
 use syntax_pos::Span;
 
@@ -68,7 +69,7 @@ pub fn check_pat_walk(
             PatKind::Binding(..) |
             PatKind::Ref(..) => false,
         };
-        if is_non_ref_pat && tcx.sess.features.borrow().match_default_bindings {
+        if is_non_ref_pat {
             debug!("pattern is non reference pattern");
             let mut exp_ty = self.resolve_type_vars_with_obligations(&expected);
 
@@ -113,10 +114,24 @@ pub fn check_pat_walk(
                 }
             };
             if pat_adjustments.len() > 0 {
-                debug!("default binding mode is now {:?}", def_bm);
-                self.inh.tables.borrow_mut()
-                    .pat_adjustments_mut()
-                    .insert(pat.hir_id, pat_adjustments);
+                if tcx.sess.features.borrow().match_default_bindings {
+                    debug!("default binding mode is now {:?}", def_bm);
+                    self.inh.tables.borrow_mut()
+                        .pat_adjustments_mut()
+                        .insert(pat.hir_id, pat_adjustments);
+                } else {
+                    let mut err = feature_gate::feature_err(
+                        &tcx.sess.parse_sess,
+                        "match_default_bindings",
+                        pat.span,
+                        feature_gate::GateIssue::Language,
+                        "non-reference pattern used to match a reference",
+                    );
+                    if let Ok(snippet) = tcx.sess.codemap().span_to_snippet(pat.span) {
+                        err.span_suggestion(pat.span, "consider using", format!("&{}", &snippet));
+                    }
+                    err.emit();
+                }
             }
         }
 
@@ -325,8 +340,8 @@ pub fn check_pat_walk(
                             if let Some(mut err) = err {
                                 if is_arg {
                                     if let PatKind::Binding(..) = inner.node {
-                                        if let Ok(snippet) = self.sess().codemap()
-                                                                        .span_to_snippet(pat.span)
+                                        if let Ok(snippet) = tcx.sess.codemap()
+                                                                     .span_to_snippet(pat.span)
                                         {
                                             err.help(&format!("did you mean `{}: &{}`?",
                                                               &snippet[1..],
@@ -810,10 +825,11 @@ fn check_struct_pat_fields(&self,
                                def_bm: ty::BindingMode) {
         let tcx = self.tcx;
 
-        let (substs, kind_name) = match adt_ty.sty {
-            ty::TyAdt(adt, substs) => (substs, adt.variant_descr()),
+        let (substs, adt) = match adt_ty.sty {
+            ty::TyAdt(adt, substs) => (substs, adt),
             _ => span_bug!(span, "struct pattern is not an ADT")
         };
+        let kind_name = adt.variant_descr();
 
         // Index the struct fields' types.
         let field_map = variant.fields
@@ -867,6 +883,13 @@ fn check_struct_pat_fields(&self,
             self.check_pat_walk(&field.pat, field_ty, def_bm, true);
         }
 
+        // Require `..` if struct has non_exhaustive attribute.
+        if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc {
+            span_err!(tcx.sess, span, E0638,
+                      "`..` required with {} marked as non-exhaustive",
+                      kind_name);
+        }
+
         // Report an error if incorrect number of the fields were specified.
         if kind_name == "union" {
             if fields.len() != 1 {
index 07159770d5ba2a15766553e188692c9fed78f434..d475fb0cf1a142c5139f8a607f996d79743c1aaf 100644 (file)
 use super::{check_fn, Expectation, FnCtxt};
 
 use astconv::AstConv;
+use rustc::hir::def_id::DefId;
+use rustc::infer::{InferOk, InferResult};
+use rustc::infer::LateBoundRegionConversionTime;
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::ty::{self, ToPolyTraitRef, Ty};
 use rustc::ty::subst::Substs;
+use rustc::ty::TypeFoldable;
 use std::cmp;
 use std::iter;
 use syntax::abi::Abi;
 use rustc::hir;
 
+struct ClosureSignatures<'tcx> {
+    bound_sig: ty::PolyFnSig<'tcx>,
+    liberated_sig: ty::FnSig<'tcx>,
+}
+
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn check_expr_closure(&self,
-                              expr: &hir::Expr,
-                              _capture: hir::CaptureClause,
-                              decl: &'gcx hir::FnDecl,
-                              body_id: hir::BodyId,
-                              expected: Expectation<'tcx>)
-                              -> Ty<'tcx> {
-        debug!("check_expr_closure(expr={:?},expected={:?})",
-               expr,
-               expected);
+    pub fn check_expr_closure(
+        &self,
+        expr: &hir::Expr,
+        _capture: hir::CaptureClause,
+        decl: &'gcx hir::FnDecl,
+        body_id: hir::BodyId,
+        expected: Expectation<'tcx>,
+    ) -> Ty<'tcx> {
+        debug!(
+            "check_expr_closure(expr={:?},expected={:?})",
+            expr,
+            expected
+        );
 
         // It's always helpful for inference if we know the kind of
         // closure sooner rather than later, so first examine the expected
@@ -44,70 +56,84 @@ pub fn check_expr_closure(&self,
         self.check_closure(expr, expected_kind, decl, body, expected_sig)
     }
 
-    fn check_closure(&self,
-                     expr: &hir::Expr,
-                     opt_kind: Option<ty::ClosureKind>,
-                     decl: &'gcx hir::FnDecl,
-                     body: &'gcx hir::Body,
-                     expected_sig: Option<ty::FnSig<'tcx>>)
-                     -> Ty<'tcx> {
-        debug!("check_closure opt_kind={:?} expected_sig={:?}",
-               opt_kind,
-               expected_sig);
+    fn check_closure(
+        &self,
+        expr: &hir::Expr,
+        opt_kind: Option<ty::ClosureKind>,
+        decl: &'gcx hir::FnDecl,
+        body: &'gcx hir::Body,
+        expected_sig: Option<ty::FnSig<'tcx>>,
+    ) -> Ty<'tcx> {
+        debug!(
+            "check_closure(opt_kind={:?}, expected_sig={:?})",
+            opt_kind,
+            expected_sig
+        );
 
         let expr_def_id = self.tcx.hir.local_def_id(expr.id);
-        let sig = AstConv::ty_of_closure(self,
-                                         hir::Unsafety::Normal,
-                                         decl,
-                                         Abi::RustCall,
-                                         expected_sig);
-        // `deduce_expectations_from_expected_type` introduces late-bound
-        // lifetimes defined elsewhere, which we need to anonymize away.
-        let sig = self.tcx.anonymize_late_bound_regions(&sig);
+
+        let ClosureSignatures {
+            bound_sig,
+            liberated_sig,
+        } = self.sig_of_closure(expr_def_id, decl, body, expected_sig);
+
+        debug!("check_closure: ty_of_closure returns {:?}", liberated_sig);
+
+        let interior = check_fn(
+            self,
+            self.param_env,
+            liberated_sig,
+            decl,
+            expr.id,
+            body,
+            true,
+        ).1;
 
         // Create type variables (for now) to represent the transformed
         // types of upvars. These will be unified during the upvar
         // inference phase (`upvar.rs`).
-        let base_substs = Substs::identity_for_item(self.tcx,
-            self.tcx.closure_base_def_id(expr_def_id));
-        let substs = base_substs.extend_to(self.tcx, expr_def_id,
-                |_, _| span_bug!(expr.span, "closure has region param"),
-                |_, _| self.infcx.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
+        let base_substs =
+            Substs::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
+        let substs = base_substs.extend_to(
+            self.tcx,
+            expr_def_id,
+            |_, _| span_bug!(expr.span, "closure has region param"),
+            |_, _| {
+                self.infcx
+                    .next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
+            },
         );
-
-        let fn_sig = self.liberate_late_bound_regions(expr_def_id, &sig);
-        let fn_sig = self.inh.normalize_associated_types_in(body.value.span,
-                                                            body.value.id,
-                                                            self.param_env,
-                                                            &fn_sig);
-
-        let interior = check_fn(self, self.param_env, fn_sig, decl, expr.id, body, true).1;
+        let closure_type = self.tcx.mk_closure(expr_def_id, substs);
 
         if let Some(interior) = interior {
-            let closure_substs = ty::ClosureSubsts {
-                substs: substs,
-            };
+            let closure_substs = ty::ClosureSubsts { substs: substs };
             return self.tcx.mk_generator(expr_def_id, closure_substs, interior);
         }
 
-        let closure_type = self.tcx.mk_closure(expr_def_id, substs);
-
-        debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type);
+        debug!(
+            "check_closure: expr.id={:?} closure_type={:?}",
+            expr.id,
+            closure_type
+        );
 
         // Tuple up the arguments and insert the resulting function type into
         // the `closures` table.
-        let sig = sig.map_bound(|sig| self.tcx.mk_fn_sig(
-            iter::once(self.tcx.intern_tup(sig.inputs(), false)),
-            sig.output(),
-            sig.variadic,
-            sig.unsafety,
-            sig.abi
-        ));
-
-        debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
-               expr_def_id,
-               sig,
-               opt_kind);
+        let sig = bound_sig.map_bound(|sig| {
+            self.tcx.mk_fn_sig(
+                iter::once(self.tcx.intern_tup(sig.inputs(), false)),
+                sig.output(),
+                sig.variadic,
+                sig.unsafety,
+                sig.abi,
+            )
+        });
+
+        debug!(
+            "check_closure: expr_def_id={:?}, sig={:?}, opt_kind={:?}",
+            expr_def_id,
+            sig,
+            opt_kind
+        );
 
         {
             let mut tables = self.tables.borrow_mut();
@@ -123,22 +149,26 @@ fn check_closure(&self,
         closure_type
     }
 
-    fn deduce_expectations_from_expected_type
-        (&self,
-         expected_ty: Ty<'tcx>)
-         -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
-        debug!("deduce_expectations_from_expected_type(expected_ty={:?})",
-               expected_ty);
+    fn deduce_expectations_from_expected_type(
+        &self,
+        expected_ty: Ty<'tcx>,
+    ) -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
+        debug!(
+            "deduce_expectations_from_expected_type(expected_ty={:?})",
+            expected_ty
+        );
 
         match expected_ty.sty {
             ty::TyDynamic(ref object_type, ..) => {
-                let sig = object_type.projection_bounds()
+                let sig = object_type
+                    .projection_bounds()
                     .filter_map(|pb| {
                         let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
                         self.deduce_sig_from_projection(&pb)
                     })
                     .next();
-                let kind = object_type.principal()
+                let kind = object_type
+                    .principal()
                     .and_then(|p| self.tcx.lang_items().fn_trait_kind(p.def_id()));
                 (sig, kind)
             }
@@ -148,19 +178,22 @@ fn deduce_expectations_from_expected_type
         }
     }
 
-    fn deduce_expectations_from_obligations
-        (&self,
-         expected_vid: ty::TyVid)
-         -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
+    fn deduce_expectations_from_obligations(
+        &self,
+        expected_vid: ty::TyVid,
+    ) -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) {
         let fulfillment_cx = self.fulfillment_cx.borrow();
         // Here `expected_ty` is known to be a type inference variable.
 
-        let expected_sig = fulfillment_cx.pending_obligations()
+        let expected_sig = fulfillment_cx
+            .pending_obligations()
             .iter()
             .map(|obligation| &obligation.obligation)
             .filter_map(|obligation| {
-                debug!("deduce_expectations_from_obligations: obligation.predicate={:?}",
-                       obligation.predicate);
+                debug!(
+                    "deduce_expectations_from_obligations: obligation.predicate={:?}",
+                    obligation.predicate
+                );
 
                 match obligation.predicate {
                     // Given a Projection predicate, we can potentially infer
@@ -179,7 +212,8 @@ fn deduce_expectations_from_obligations
         // infer the kind. This can occur if there is a trait-reference
         // like `F : Fn<A>`. Note that due to subtyping we could encounter
         // many viable options, so pick the most restrictive.
-        let expected_kind = fulfillment_cx.pending_obligations()
+        let expected_kind = fulfillment_cx
+            .pending_obligations()
             .iter()
             .map(|obligation| &obligation.obligation)
             .filter_map(|obligation| {
@@ -204,20 +238,23 @@ fn deduce_expectations_from_obligations
                     // inference variable.
                     ty::Predicate::ClosureKind(..) => None,
                 };
-                opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
+                opt_trait_ref
+                    .and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
                     .and_then(|tr| self.tcx.lang_items().fn_trait_kind(tr.def_id()))
             })
-            .fold(None,
-                  |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
+            .fold(None, |best, cur| {
+                Some(best.map_or(cur, |best| cmp::min(best, cur)))
+            });
 
         (expected_sig, expected_kind)
     }
 
     /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
     /// everything we need to know about a closure.
-    fn deduce_sig_from_projection(&self,
-                                  projection: &ty::PolyProjectionPredicate<'tcx>)
-                                  -> Option<ty::FnSig<'tcx>> {
+    fn deduce_sig_from_projection(
+        &self,
+        projection: &ty::PolyProjectionPredicate<'tcx>,
+    ) -> Option<ty::FnSig<'tcx>> {
         let tcx = self.tcx;
 
         debug!("deduce_sig_from_projection({:?})", projection);
@@ -230,8 +267,10 @@ fn deduce_sig_from_projection(&self,
 
         let arg_param_ty = trait_ref.substs().type_at(1);
         let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
-        debug!("deduce_sig_from_projection: arg_param_ty {:?}",
-               arg_param_ty);
+        debug!(
+            "deduce_sig_from_projection: arg_param_ty {:?}",
+            arg_param_ty
+        );
 
         let input_tys = match arg_param_ty.sty {
             ty::TyTuple(tys, _) => tys.into_iter(),
@@ -242,31 +281,291 @@ fn deduce_sig_from_projection(&self,
 
         let ret_param_ty = projection.0.ty;
         let ret_param_ty = self.resolve_type_vars_if_possible(&ret_param_ty);
-        debug!("deduce_sig_from_projection: ret_param_ty {:?}", ret_param_ty);
+        debug!(
+            "deduce_sig_from_projection: ret_param_ty {:?}",
+            ret_param_ty
+        );
 
         let fn_sig = self.tcx.mk_fn_sig(
             input_tys.cloned(),
             ret_param_ty,
             false,
             hir::Unsafety::Normal,
-            Abi::Rust
+            Abi::Rust,
         );
         debug!("deduce_sig_from_projection: fn_sig {:?}", fn_sig);
 
         Some(fn_sig)
     }
 
-    fn self_type_matches_expected_vid(&self,
-                                      trait_ref: ty::PolyTraitRef<'tcx>,
-                                      expected_vid: ty::TyVid)
-                                      -> Option<ty::PolyTraitRef<'tcx>> {
+    fn self_type_matches_expected_vid(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        expected_vid: ty::TyVid,
+    ) -> Option<ty::PolyTraitRef<'tcx>> {
         let self_ty = self.shallow_resolve(trait_ref.self_ty());
-        debug!("self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
-               trait_ref,
-               self_ty);
+        debug!(
+            "self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?})",
+            trait_ref,
+            self_ty
+        );
         match self_ty.sty {
             ty::TyInfer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref),
             _ => None,
         }
     }
+
+    fn sig_of_closure(
+        &self,
+        expr_def_id: DefId,
+        decl: &hir::FnDecl,
+        body: &hir::Body,
+        expected_sig: Option<ty::FnSig<'tcx>>,
+    ) -> ClosureSignatures<'tcx> {
+        if let Some(e) = expected_sig {
+            self.sig_of_closure_with_expectation(expr_def_id, decl, body, e)
+        } else {
+            self.sig_of_closure_no_expectation(expr_def_id, decl, body)
+        }
+    }
+
+    /// If there is no expected signature, then we will convert the
+    /// types that the user gave into a signature.
+    fn sig_of_closure_no_expectation(
+        &self,
+        expr_def_id: DefId,
+        decl: &hir::FnDecl,
+        body: &hir::Body,
+    ) -> ClosureSignatures<'tcx> {
+        debug!("sig_of_closure_no_expectation()");
+
+        let bound_sig = self.supplied_sig_of_closure(decl);
+
+        self.closure_sigs(expr_def_id, body, bound_sig)
+    }
+
+    /// Invoked to compute the signature of a closure expression. This
+    /// combines any user-provided type annotations (e.g., `|x: u32|
+    /// -> u32 { .. }`) with the expected signature.
+    ///
+    /// The approach is as follows:
+    ///
+    /// - Let `S` be the (higher-ranked) signature that we derive from the user's annotations.
+    /// - Let `E` be the (higher-ranked) signature that we derive from the expectations, if any.
+    ///   - If we have no expectation `E`, then the signature of the closure is `S`.
+    ///   - Otherwise, the signature of the closure is E. Moreover:
+    ///     - Skolemize the late-bound regions in `E`, yielding `E'`.
+    ///     - Instantiate all the late-bound regions bound in the closure within `S`
+    ///       with fresh (existential) variables, yielding `S'`
+    ///     - Require that `E' = S'`
+    ///       - We could use some kind of subtyping relationship here,
+    ///         I imagine, but equality is easier and works fine for
+    ///         our purposes.
+    ///
+    /// The key intuition here is that the user's types must be valid
+    /// from "the inside" of the closure, but the expectation
+    /// ultimately drives the overall signature.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// fn with_closure<F>(_: F)
+    ///   where F: Fn(&u32) -> &u32 { .. }
+    ///
+    /// with_closure(|x: &u32| { ... })
+    /// ```
+    ///
+    /// Here:
+    /// - E would be `fn(&u32) -> &u32`.
+    /// - S would be `fn(&u32) ->
+    /// - E' is `&'!0 u32 -> &'!0 u32`
+    /// - S' is `&'?0 u32 -> ?T`
+    ///
+    /// S' can be unified with E' with `['?0 = '!0, ?T = &'!10 u32]`.
+    ///
+    /// # Arguments
+    ///
+    /// - `expr_def_id`: the def-id of the closure expression
+    /// - `decl`: the HIR declaration of the closure
+    /// - `body`: the body of the closure
+    /// - `expected_sig`: the expected signature (if any). Note that
+    ///   this is missing a binder: that is, there may be late-bound
+    ///   regions with depth 1, which are bound then by the closure.
+    fn sig_of_closure_with_expectation(
+        &self,
+        expr_def_id: DefId,
+        decl: &hir::FnDecl,
+        body: &hir::Body,
+        expected_sig: ty::FnSig<'tcx>,
+    ) -> ClosureSignatures<'tcx> {
+        debug!(
+            "sig_of_closure_with_expectation(expected_sig={:?})",
+            expected_sig
+        );
+
+        // Watch out for some surprises and just ignore the
+        // expectation if things don't see to match up with what we
+        // expect.
+        if expected_sig.variadic != decl.variadic {
+            return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
+        } else if expected_sig.inputs_and_output.len() != decl.inputs.len() + 1 {
+            // we could probably handle this case more gracefully
+            return self.sig_of_closure_no_expectation(expr_def_id, decl, body);
+        }
+
+        // Create a `PolyFnSig`. Note the oddity that late bound
+        // regions appearing free in `expected_sig` are now bound up
+        // in this binder we are creating.
+        assert!(!expected_sig.has_regions_escaping_depth(1));
+        let bound_sig = ty::Binder(self.tcx.mk_fn_sig(
+            expected_sig.inputs().iter().cloned(),
+            expected_sig.output(),
+            decl.variadic,
+            hir::Unsafety::Normal,
+            Abi::RustCall,
+        ));
+
+        // `deduce_expectations_from_expected_type` introduces
+        // late-bound lifetimes defined elsewhere, which we now
+        // anonymize away, so as not to confuse the user.
+        let bound_sig = self.tcx.anonymize_late_bound_regions(&bound_sig);
+
+        let closure_sigs = self.closure_sigs(expr_def_id, body, bound_sig);
+
+        // Up till this point, we have ignored the annotations that the user
+        // gave. This function will check that they unify successfully.
+        // Along the way, it also writes out entries for types that the user
+        // wrote into our tables, which are then later used by the privacy
+        // check.
+        match self.check_supplied_sig_against_expectation(decl, &closure_sigs) {
+            Ok(infer_ok) => self.register_infer_ok_obligations(infer_ok),
+            Err(_) => return self.sig_of_closure_no_expectation(expr_def_id, decl, body),
+        }
+
+        closure_sigs
+    }
+
+    /// Enforce the user's types against the expectation.  See
+    /// `sig_of_closure_with_expectation` for details on the overall
+    /// strategy.
+    fn check_supplied_sig_against_expectation(
+        &self,
+        decl: &hir::FnDecl,
+        expected_sigs: &ClosureSignatures<'tcx>,
+    ) -> InferResult<'tcx, ()> {
+        // Get the signature S that the user gave.
+        //
+        // (See comment on `sig_of_closure_with_expectation` for the
+        // meaning of these letters.)
+        let supplied_sig = self.supplied_sig_of_closure(decl);
+
+        debug!(
+            "check_supplied_sig_against_expectation: supplied_sig={:?}",
+            supplied_sig
+        );
+
+        // FIXME(#45727): As discussed in [this comment][c1], naively
+        // forcing equality here actually results in suboptimal error
+        // messages in some cases.  For now, if there would have been
+        // an obvious error, we fallback to declaring the type of the
+        // closure to be the one the user gave, which allows other
+        // error message code to trigger.
+        //
+        // However, I think [there is potential to do even better
+        // here][c2], since in *this* code we have the precise span of
+        // the type parameter in question in hand when we report the
+        // error.
+        //
+        // [c1]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341089706
+        // [c2]: https://github.com/rust-lang/rust/pull/45072#issuecomment-341096796
+        self.infcx.commit_if_ok(|_| {
+            let mut all_obligations = vec![];
+
+            // The liberated version of this signature should be be a subtype
+            // of the liberated form of the expectation.
+            for ((hir_ty, &supplied_ty), expected_ty) in decl.inputs.iter()
+                           .zip(*supplied_sig.inputs().skip_binder()) // binder moved to (*) below
+                           .zip(expected_sigs.liberated_sig.inputs())
+            // `liberated_sig` is E'.
+            {
+                // Instantiate (this part of..) S to S', i.e., with fresh variables.
+                let (supplied_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                    hir_ty.span,
+                    LateBoundRegionConversionTime::FnCall,
+                    &ty::Binder(supplied_ty),
+                ); // recreated from (*) above
+
+                // Check that E' = S'.
+                let cause = &self.misc(hir_ty.span);
+                let InferOk {
+                    value: (),
+                    obligations,
+                } = self.at(cause, self.param_env)
+                    .eq(*expected_ty, supplied_ty)?;
+                all_obligations.extend(obligations);
+            }
+
+            let (supplied_output_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                decl.output.span(),
+                LateBoundRegionConversionTime::FnCall,
+                &supplied_sig.output(),
+            );
+            let cause = &self.misc(decl.output.span());
+            let InferOk {
+                value: (),
+                obligations,
+            } = self.at(cause, self.param_env)
+                .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
+            all_obligations.extend(obligations);
+
+            Ok(InferOk {
+                value: (),
+                obligations: all_obligations,
+            })
+        })
+    }
+
+    /// If there is no expected signature, then we will convert the
+    /// types that the user gave into a signature.
+    fn supplied_sig_of_closure(&self, decl: &hir::FnDecl) -> ty::PolyFnSig<'tcx> {
+        let astconv: &AstConv = self;
+
+        // First, convert the types that the user supplied (if any).
+        let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a));
+        let supplied_return = match decl.output {
+            hir::Return(ref output) => astconv.ast_ty_to_ty(&output),
+            hir::DefaultReturn(_) => astconv.ty_infer(decl.output.span()),
+        };
+
+        let result = ty::Binder(self.tcx.mk_fn_sig(
+            supplied_arguments,
+            supplied_return,
+            decl.variadic,
+            hir::Unsafety::Normal,
+            Abi::RustCall,
+        ));
+
+        debug!("supplied_sig_of_closure: result={:?}", result);
+
+        result
+    }
+
+    fn closure_sigs(
+        &self,
+        expr_def_id: DefId,
+        body: &hir::Body,
+        bound_sig: ty::PolyFnSig<'tcx>,
+    ) -> ClosureSignatures<'tcx> {
+        let liberated_sig = self.liberate_late_bound_regions(expr_def_id, &bound_sig);
+        let liberated_sig = self.inh.normalize_associated_types_in(
+            body.value.span,
+            body.value.id,
+            self.param_env,
+            &liberated_sig,
+        );
+        ClosureSignatures {
+            bound_sig,
+            liberated_sig,
+        }
+    }
 }
index a24f420af80dcdfff8caefb0fd8821567b4f9639..81e5b2fe00a6ae895e73dfe1f0d5526b94c662a4 100644 (file)
@@ -431,6 +431,9 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
             ty::TySlice(_) => {
                 let lang_def_id = lang_items.slice_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
+
+                let lang_def_id = lang_items.slice_u8_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();
index 26f7a7a37847768f98bfcee1940dd788fb42cca8..82d59ecfc92cfabb75bee8413c423ce30fc70d56 100644 (file)
 use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder, DiagnosticId};
 use require_c_abi_if_variadic;
 use session::{CompileIncomplete, Session};
 use TypeAndSubsts;
@@ -2467,7 +2467,7 @@ fn parameter_count_error<'tcx>(sess: &Session,
                     if expected_count == 1 {""} else {"s"},
                     arg_count,
                     if arg_count == 1 {" was"} else {"s were"}),
-                error_code);
+                DiagnosticId::Error(error_code.to_owned()));
 
             if let Some(def_s) = def_span {
                 err.span_label(def_s, "defined here");
@@ -3448,6 +3448,15 @@ fn check_expr_struct(&self,
             hir::QPath::TypeRelative(ref qself, _) => qself.span
         };
 
+        // Prohibit struct expressions when non exhaustive flag is set.
+        if let ty::TyAdt(adt, _) = struct_ty.sty {
+            if !adt.did.is_local() && adt.is_non_exhaustive() {
+                span_err!(self.tcx.sess, expr.span, E0639,
+                          "cannot create non-exhaustive {} using struct expression",
+                          adt.variant_descr());
+            }
+        }
+
         self.check_expr_struct_fields(struct_ty, expected, expr.id, path_span, variant, fields,
                                       base_expr.is_none());
         if let &Some(ref base_expr) = base_expr {
index ddbdd204305890f9e3dfffe463aab47d92583577..483af08cabfce624deec7e8da665377672928f17 100644 (file)
@@ -114,7 +114,7 @@ fn check_item_well_formed(&mut self, item: &hir::Item) {
                 // FIXME(#27579) what amount of WF checking do we need for neg impls?
 
                 let trait_ref = tcx.impl_trait_ref(tcx.hir.local_def_id(item.id)).unwrap();
-                if !tcx.trait_has_default_impl(trait_ref.def_id) {
+                if !tcx.trait_is_auto(trait_ref.def_id) {
                     error_192(tcx, item.span);
                 }
             }
@@ -318,7 +318,7 @@ fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) {
     fn check_trait(&mut self, item: &hir::Item) {
         let trait_def_id = self.tcx.hir.local_def_id(item.id);
 
-        if self.tcx.trait_has_default_impl(trait_def_id) {
+        if self.tcx.trait_is_auto(trait_def_id) {
             self.check_auto_trait(trait_def_id, item.span);
         }
 
index c56a3b91ca37f7d720d9b37562ec20b1e748c09d..569b6a2febb4509a631b3aecc84bb7bb8c315d83 100644 (file)
@@ -137,6 +137,13 @@ fn visit_item(&mut self, item: &hir::Item) {
                                           "str",
                                           item.span);
             }
+            ty::TySlice(slice_item) if slice_item == self.tcx.types.u8 => {
+                self.check_primitive_impl(def_id,
+                                          lang_items.slice_u8_impl(),
+                                          "slice_u8",
+                                          "[u8]",
+                                          item.span);
+            }
             ty::TySlice(_) => {
                 self.check_primitive_impl(def_id,
                                           lang_items.slice_impl(),
index 6109fc57b0dfccfa5f6041e627d5e7d304ccc5f0..90a0952af042504b7d5f245335e50741f577f503 100644 (file)
@@ -132,7 +132,7 @@ pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     unsafety::check(tcx);
     orphan::check(tcx);
-    overlap::check_default_impls(tcx);
+    overlap::check_auto_impls(tcx);
 
     // these queries are executed for side-effects (error reporting):
     tcx.crate_inherent_impls(LOCAL_CRATE);
index a5edc95b79b08621aad106eedf732f1db9c98de3..9f183973621894e6ad465893540fd1d92fa3cfc7 100644 (file)
@@ -100,11 +100,11 @@ fn visit_item(&mut self, item: &hir::Item) {
                 // This final impl is legal according to the orpan
                 // rules, but it invalidates the reasoning from
                 // `two_foos` above.
-                debug!("trait_ref={:?} trait_def_id={:?} trait_has_default_impl={}",
+                debug!("trait_ref={:?} trait_def_id={:?} trait_is_auto={}",
                        trait_ref,
                        trait_def_id,
-                       self.tcx.trait_has_default_impl(trait_def_id));
-                if self.tcx.trait_has_default_impl(trait_def_id) &&
+                       self.tcx.trait_is_auto(trait_def_id));
+                if self.tcx.trait_is_auto(trait_def_id) &&
                    !trait_def_id.is_local() {
                     let self_ty = trait_ref.self_ty();
                     let opt_self_def_id = match self_ty.sty {
@@ -142,7 +142,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                     }
                 }
             }
-            hir::ItemDefaultImpl(_, ref item_trait_ref) => {
+            hir::ItemAutoImpl(_, ref item_trait_ref) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: default trait impl {}",
                        self.tcx.hir.node_to_string(item.id));
index 59ebae16d08ca9364406261cf17f55607e672309..5cc6eaa5602fbe7d57bafe0f67853c8655bc1eee 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 
-pub fn check_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+pub fn check_auto_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut overlap = OverlapChecker { tcx };
 
     // this secondary walk specifically checks for some other cases,
@@ -74,19 +74,19 @@ struct OverlapChecker<'cx, 'tcx: 'cx> {
 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            hir::ItemDefaultImpl(..) => {
-                // look for another default impl; note that due to the
+            hir::ItemAutoImpl(..) => {
+                // look for another auto impl; note that due to the
                 // general orphan/coherence rules, it must always be
                 // in this crate.
                 let impl_def_id = self.tcx.hir.local_def_id(item.id);
                 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
 
-                let prev_id = self.tcx.hir.trait_default_impl(trait_ref.def_id).unwrap();
+                let prev_id = self.tcx.hir.trait_auto_impl(trait_ref.def_id).unwrap();
                 if prev_id != item.id {
                     let mut err = struct_span_err!(self.tcx.sess,
                                                    self.tcx.span_of_impl(impl_def_id).unwrap(),
                                                    E0521,
-                                                   "redundant default implementations of trait \
+                                                   "redundant auto implementations of trait \
                                                     `{}`:",
                                                    trait_ref);
                     err.span_note(self.tcx
index 4672975d056b8679c897a079f4e0d8a7f283146f..280fb04e040011f8af896dd646387652f4a6ab2d 100644 (file)
@@ -84,7 +84,7 @@ fn check_unsafety_coherence(&mut self,
 impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for UnsafetyChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item) {
         match item.node {
-            hir::ItemDefaultImpl(unsafety, _) => {
+            hir::ItemAutoImpl(unsafety, _) => {
                 self.check_unsafety_coherence(item, None, unsafety, hir::ImplPolarity::Positive);
             }
             hir::ItemImpl(unsafety, polarity, _, ref generics, ..) => {
index 75e864d07a6c276bb35608f6ec5d5321ab789653..814470974285fdf717da82936eab2a6b71da8c2b 100644 (file)
@@ -73,7 +73,7 @@ pub fn provide(providers: &mut Providers) {
         impl_trait_ref,
         impl_polarity,
         is_foreign_item,
-        is_default_impl,
+        is_auto_impl,
         ..*providers
     };
 }
@@ -273,7 +273,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemEnum(_, ref generics) |
                 ItemStruct(_, ref generics) |
                 ItemUnion(_, ref generics) => generics,
-                ItemTrait(_, ref generics, ..) => {
+                ItemTrait(_, _, ref generics, ..) => {
                     // Implied `Self: Trait` and supertrait bounds.
                     if param_id == item_node_id {
                         result.predicates.push(ty::TraitRef {
@@ -425,7 +425,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             tcx.predicates_of(def_id);
             convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
         },
-        hir::ItemDefaultImpl(..) => {
+        hir::ItemAutoImpl(..) => {
             tcx.impl_trait_ref(def_id);
         }
         hir::ItemImpl(..) => {
@@ -670,7 +670,7 @@ fn super_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
 
     let (generics, bounds) = match item.node {
-        hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
+        hir::ItemTrait(.., ref generics, ref supertraits, _) => (generics, supertraits),
         _ => span_bug!(item.span,
                        "super_predicates invoked on non-trait"),
     };
@@ -713,7 +713,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let item = tcx.hir.expect_item(node_id);
 
     let unsafety = match item.node {
-        hir::ItemTrait(unsafety, ..) => unsafety,
+        hir::ItemTrait(_, unsafety, ..) => unsafety,
         _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
     };
 
@@ -730,11 +730,14 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     let def_path_hash = tcx.def_path_hash(def_id);
-    let has_default_impl = tcx.hir.trait_is_auto(def_id);
+    let is_auto = match item.node {
+        hir::ItemTrait(hir::IsAuto::Yes, ..) => true,
+        _ => tcx.hir.trait_is_auto(def_id),
+    };
     let def = ty::TraitDef::new(def_id,
                                 unsafety,
                                 paren_sugar,
-                                has_default_impl,
+                                is_auto,
                                 def_path_hash);
     tcx.alloc_trait_def(def)
 }
@@ -888,7 +891,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     generics
                 }
 
-                ItemTrait(_, ref generics, ..) => {
+                ItemTrait(_, _, ref generics, ..) => {
                     // Add in the self type parameter.
                     //
                     // Something of a hack: use the node id for the trait, also as
@@ -1074,7 +1077,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let substs = Substs::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
-                ItemDefaultImpl(..) |
+                ItemAutoImpl(..) |
                 ItemTrait(..) |
                 ItemMod(..) |
                 ItemForeignMod(..) |
@@ -1223,7 +1226,7 @@ fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     match tcx.hir.expect_item(node_id).node {
-        hir::ItemDefaultImpl(_, ref ast_trait_ref) => {
+        hir::ItemAutoImpl(_, ref ast_trait_ref) => {
             Some(AstConv::instantiate_mono_trait_ref(&icx,
                                                      ast_trait_ref,
                                                      tcx.mk_self_type()))
@@ -1350,7 +1353,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     generics
                 }
 
-                ItemTrait(_, ref generics, .., ref items) => {
+                ItemTrait(_, _, ref generics, .., ref items) => {
                     is_trait = Some((ty::TraitRef {
                         def_id,
                         substs: Substs::identity_for_item(tcx, def_id)
@@ -1665,13 +1668,13 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn is_default_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              def_id: DefId)
                              -> bool {
     match tcx.hir.get_if_local(def_id) {
-        Some(hir_map::NodeItem(&hir::Item { node: hir::ItemDefaultImpl(..), .. }))
+        Some(hir_map::NodeItem(&hir::Item { node: hir::ItemAutoImpl(..), .. }))
              => true,
         Some(_) => false,
-        _ => bug!("is_default_impl applied to non-local def-id {:?}", def_id)
+        _ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id)
     }
 }
index 594cd0878cbfbc62144d3aabfed38bf24350174c..075367cbbb7cdc2130a0eeec101516bb0484a2f6 100644 (file)
@@ -1854,7 +1854,7 @@ unsafe impl !Clone for Foo { }
 
 This will compile:
 
-```
+```ignore (ignore auto_trait future compatibility warning)
 #![feature(optin_builtin_traits)]
 
 struct Foo;
@@ -4606,6 +4606,65 @@ pub fn method(&self) {} // It's now public.
 ```
 "##,
 
+E0638: r##"
+This error indicates that the struct or enum must be matched non-exhaustively
+as it has been marked as `non_exhaustive`.
+
+When applied within a crate, downstream users of the crate will need to use the
+`_` pattern when matching enums and use the `..` pattern when matching structs.
+
+For example, in the below example, since the enum is marked as
+`non_exhaustive`, it is required that downstream crates match non-exhaustively
+on it.
+
+```rust,ignore (pseudo-Rust)
+use std::error::Error as StdError;
+
+#[non_exhaustive] pub enum Error {
+   Message(String),
+   Other,
+}
+
+impl StdError for Error {
+   fn description(&self) -> &str {
+        // This will not error, despite being marked as non_exhaustive, as this
+        // enum is defined within the current crate, it can be matched
+        // exhaustively.
+        match *self {
+           Message(ref s) => s,
+           Other => "other or unknown error",
+        }
+   }
+}
+```
+
+An example of matching non-exhaustively on the above enum is provided below:
+
+```rust,ignore (pseudo-Rust)
+use mycrate::Error;
+
+// This will not error as the non_exhaustive Error enum has been matched with a
+// wildcard.
+match error {
+   Message(ref s) => ...,
+   Other => ...,
+   _ => ...,
+}
+```
+
+Similarly, for structs, match with `..` to avoid this error.
+"##,
+
+E0639: r##"
+This error indicates that the struct or enum cannot be instantiated from
+outside of the defining crate as it has been marked as `non_exhaustive` and as
+such more fields/variants may be added in future that could cause adverse side
+effects for this code.
+
+It is recommended that you look for a `new` function or equivalent in the
+crate's documentation.
+"##,
+
 }
 
 register_diagnostics! {
@@ -4669,7 +4728,7 @@ pub fn method(&self) {} // It's now public.
 //  E0372, // coherence not object safe
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
-    E0521, // redundant default implementations of trait
+    E0521, // redundant auto implementations of trait
     E0533, // `{}` does not name a unit variant, unit struct or a constant
 //  E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
     E0564, // only named lifetimes are allowed in `impl Trait`,
index 49ba0499f7868bcf7268a57b343ee8f9b964de26..5227955d7b902441dce6e08c0dcc85faa0b0c947 100644 (file)
@@ -76,6 +76,7 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
+#![feature(match_default_bindings)]
 #![feature(never_type)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
index e3ce403f3c17baa60ded8e1321678f41de939a30..915383d8189e0db2a797150a318453e9723d7a22 100644 (file)
@@ -15,6 +15,7 @@
 use std::mem;
 use std::fmt::{self, Write};
 use std::ops;
+#[cfg(stage0)]
 use std::ascii::AsciiExt;
 
 use syntax::symbol::Symbol;
index 3a4dcc3217388706c32784990768c985521216e2..9fb9437e1bc9a717d8d796512932c269deecd272 100644 (file)
@@ -292,10 +292,10 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
         }
     }
 
-    // If this is a defaulted impl, then bail out early here
-    if tcx.is_default_impl(did) {
+    // If this is an auto impl, then bail out early here
+    if tcx.is_auto_impl(did) {
         return ret.push(clean::Item {
-            inner: clean::DefaultImplItem(clean::DefaultImpl {
+            inner: clean::AutoImplItem(clean::AutoImpl {
                 // FIXME: this should be decoded
                 unsafety: hir::Unsafety::Normal,
                 trait_: match associated_trait.as_ref().unwrap().clean(cx) {
index f8fea643d5e145316f4358369ad4cbe4efd71f2f..4b60536e1d17627513247312dbf4e8d299cad5e8 100644 (file)
@@ -425,7 +425,7 @@ pub enum ItemEnum {
     PrimitiveItem(PrimitiveType),
     AssociatedConstItem(Type, Option<String>),
     AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
-    DefaultImplItem(DefaultImpl),
+    AutoImplItem(AutoImpl),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemEnum>),
 }
@@ -2733,12 +2733,12 @@ fn build_deref_target_impls(cx: &DocContext,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct DefaultImpl {
+pub struct AutoImpl {
     pub unsafety: hir::Unsafety,
     pub trait_: Type,
 }
 
-impl Clean<Item> for doctree::DefaultImpl {
+impl Clean<Item> for doctree::AutoImpl {
     fn clean(&self, cx: &DocContext) -> Item {
         Item {
             name: None,
@@ -2748,7 +2748,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             visibility: Some(Public),
             stability: None,
             deprecation: None,
-            inner: DefaultImplItem(DefaultImpl {
+            inner: AutoImplItem(AutoImpl {
                 unsafety: self.unsafety,
                 trait_: self.trait_.clean(cx),
             }),
index 71594825cdb01215c8ab5fdcbd2a0a74a526c9fa..c21bfd8842f7240efdc7220be531038bbd55920c 100644 (file)
@@ -44,7 +44,7 @@ pub struct Module {
     pub stab: Option<attr::Stability>,
     pub depr: Option<attr::Deprecation>,
     pub impls: Vec<Impl>,
-    pub def_traits: Vec<DefaultImpl>,
+    pub def_traits: Vec<AutoImpl>,
     pub foreigns: Vec<hir::ForeignMod>,
     pub macros: Vec<Macro>,
     pub is_crate: bool,
@@ -227,7 +227,7 @@ pub struct Impl {
     pub id: ast::NodeId,
 }
 
-pub struct DefaultImpl {
+pub struct AutoImpl {
     pub unsafety: hir::Unsafety,
     pub trait_: hir::TraitRef,
     pub id: ast::NodeId,
index c9c5f01f0aea14fff6e697acc30dac3c6db48977..c214c15ed4b2be1a0c0b56b736decaf70095fbf4 100644 (file)
@@ -82,7 +82,7 @@ fn from(item: &'a clean::Item) -> ItemType {
             clean::PrimitiveItem(..)       => ItemType::Primitive,
             clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
             clean::AssociatedTypeItem(..)  => ItemType::AssociatedType,
-            clean::DefaultImplItem(..)     => ItemType::Impl,
+            clean::AutoImplItem(..)        => ItemType::Impl,
             clean::ForeignTypeItem         => ItemType::ForeignType,
             clean::StrippedItem(..)        => unreachable!(),
         }
index 001e773098eb36b91c4761ec60ec5a957d94583e..c132cf75e40a416499dac9a65e7625a089cab6cb 100644 (file)
@@ -30,7 +30,6 @@
 use libc;
 use std::slice;
 
-use std::ascii::AsciiExt;
 use std::cell::RefCell;
 use std::collections::{HashMap, VecDeque};
 use std::default::Default;
index edd01a66075b0b62d128c5ca05f9b638b27dc1e0..f3a897d2121cb4c2f3345341a2fed5536e6290ac 100644 (file)
@@ -34,6 +34,7 @@
 //! both occur before the crate is rendered.
 pub use self::ExternalLocation::*;
 
+#[cfg(stage0)]
 use std::ascii::AsciiExt;
 use std::cell::RefCell;
 use std::cmp::Ordering;
@@ -1929,7 +1930,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
     document(w, cx, item)?;
 
     let mut indices = (0..items.len()).filter(|i| {
-        if let clean::DefaultImplItem(..) = items[*i].inner {
+        if let clean::AutoImplItem(..) = items[*i].inner {
             return false;
         }
         !items[*i].is_stripped()
@@ -3744,7 +3745,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
                    ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
                    ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
         if items.iter().any(|it| {
-            if let clean::DefaultImplItem(..) = it.inner {
+            if let clean::AutoImplItem(..) = it.inner {
                 false
             } else {
                 !it.is_stripped() && it.type_() == myty
index 04bf466a7804dee5fb53479542a07a2e477afe58..b1120e0af38949e13daa2d1eb2125e2098291766 100644 (file)
             var valLower = query.query.toLowerCase(),
                 val = valLower,
                 typeFilter = itemTypeFromName(query.type),
-                results = [],
+                results = {},
                 split = valLower.split("::");
 
             // remove empty keywords
                 }
             }
 
+            function min(a, b) {
+                if (a < b) {
+                    return a;
+                }
+                return b;
+            }
+
+            function nbElements(obj) {
+                var size = 0, key;
+                for (key in obj) {
+                    if (obj.hasOwnProperty(key)) {
+                        size += 1;
+                    }
+                }
+                return size;
+            }
+
             function findArg(obj, val) {
+                var lev_distance = MAX_LEV_DISTANCE + 1;
                 if (obj && obj.type && obj.type.inputs.length > 0) {
                     for (var i = 0; i < obj.type.inputs.length; i++) {
                         if (obj.type.inputs[i].name === val) {
-                            return true;
+                            // No need to check anything else: we found it. Let's just move on.
+                            return 0;
+                        }
+                        lev_distance = min(levenshtein(obj.type.inputs[i].name, val), lev_distance);
+                        if (lev_distance === 0) {
+                            return 0;
                         }
                     }
                 }
-                return false;
+                return lev_distance;
+            }
+
+            function checkReturned(obj, val) {
+                var lev_distance = MAX_LEV_DISTANCE + 1;
+                if (obj && obj.type && obj.type.output) {
+                    if (obj.type.output.name.toLowerCase() === val) {
+                        return 0;
+                    }
+                    lev_distance = min(levenshtein(obj.type.output.name, val));
+                    if (lev_distance === 0) {
+                        return 0;
+                    }
+                }
+                return lev_distance;
             }
 
             function typePassesFilter(filter, type) {
             if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
                 val.charAt(val.length - 1) === val.charAt(0))
             {
-                val = val.substr(1, val.length - 2);
+                val = val.substr(1, val.length - 2).toLowerCase();
                 for (var i = 0; i < nSearchWords; ++i) {
+                    var ty = searchIndex[i];
                     if (searchWords[i] === val) {
                         // filter type: ... queries
                         if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
-                            results.push({id: i, index: -1});
+                            results[ty.path + ty.name] = {id: i, index: -1};
                         }
-                    } else if (findArg(searchIndex[i], val.toLowerCase()) ||
-                               (searchIndex[i].type &&
-                                searchIndex[i].type.output &&
-                                searchIndex[i].type.output.name === val.toLowerCase())) {
+                    } else if (findArg(searchIndex[i], val) ||
+                               (ty.type &&
+                                ty.type.output &&
+                                ty.type.output.name === val)) {
                         if (typePassesFilter(typeFilter, searchIndex[i].ty)) {
-                            results.push({id: i, index: -1, dontValidate: true});
+                            results[ty.path + ty.name] = {
+                                id: i,
+                                index: -1,
+                                dontValidate: true,
+                            };
                         }
                     }
-                    if (results.length === max) {
+                    if (nbElements(results) === max) {
                         break;
                     }
                 }
 
                 for (var i = 0; i < nSearchWords; ++i) {
                     var type = searchIndex[i].type;
+                    var ty = searchIndex[i];
                     if (!type) {
                         continue;
                     }
                     var typeOutput = type.output ? type.output.name : "";
                     if (output === "*" || output == typeOutput) {
                         if (input === "*") {
-                            results.push({id: i, index: -1, dontValidate: true});
+                            results[ty.path + ty.name] = {id: i, index: -1, dontValidate: true};
                         } else {
                             var allFound = true;
                             for (var it = 0; allFound === true && it < inputs.length; it++) {
                                 allFound = found;
                             }
                             if (allFound === true) {
-                                results.push({id: i, index: -1, dontValidate: true});
+                                results[ty.path + ty.name] = {
+                                    id: i,
+                                    index: -1,
+                                    dontValidate: true,
+                                };
                             }
                         }
                     }
                 for (var i = 0; i < split.length; ++i) {
                     for (var j = 0; j < nSearchWords; ++j) {
                         var lev_distance;
+                        var ty = searchIndex[j];
+                        if (!ty) {
+                            continue;
+                        }
                         if (searchWords[j].indexOf(split[i]) > -1 ||
                             searchWords[j].indexOf(val) > -1 ||
                             searchWords[j].replace(/_/g, "").indexOf(val) > -1)
                         {
                             // filter type: ... queries
                             if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                results.push({
+                                results[ty.path + ty.name] = {
                                     id: j,
                                     index: searchWords[j].replace(/_/g, "").indexOf(val),
                                     lev: 0,
-                                });
+                                };
                             }
                         } else if (
-                            (lev_distance = levenshtein(searchWords[j], val)) <=
-                                MAX_LEV_DISTANCE) {
+                            (lev_distance = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
                             if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                results.push({
-                                    id: j,
-                                    index: 0,
-                                    // we want lev results to go lower than others
-                                    lev: lev_distance,
-                                });
+                                if (results[ty.path + ty.name] === undefined ||
+                                    results[ty.path + ty.name].lev > lev_distance) {
+                                    results[ty.path + ty.name] = {
+                                        id: j,
+                                        index: 0,
+                                        // we want lev results to go lower than others
+                                        lev: lev_distance,
+                                    };
+                                }
                             }
-                        } else if (findArg(searchIndex[j], val)) {
+                        } else if (
+                            (lev_distance = findArg(searchIndex[j], val)) <= MAX_LEV_DISTANCE) {
                             if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
-                                results.push({
-                                    id: j,
-                                    index: 0,
-                                    // we want lev results to go lower than others
-                                    lev: lev_distance,
-                                });
+                                if (results[ty.path + ty.name] === undefined ||
+                                    results[ty.path + ty.name].lev > lev_distance) {
+                                    results[ty.path + ty.name] = {
+                                        id: j,
+                                        index: 0,
+                                        // we want lev results to go lower than others
+                                        lev: lev_distance,
+                                    };
+                                }
+                            }
+                        } else if (
+                            (lev_distance = checkReturned(searchIndex[j], val)) <=
+                            MAX_LEV_DISTANCE) {
+                            if (typePassesFilter(typeFilter, searchIndex[j].ty)) {
+                                if (results[ty.path + ty.name] === undefined ||
+                                    results[ty.path + ty.name].lev > lev_distance) {
+                                    results[ty.path + ty.name] = {
+                                        id: j,
+                                        index: 0,
+                                        // we want lev results to go lower than others
+                                        lev: lev_distance,
+                                    };
+                                }
                             }
                         }
-                        if (results.length === max) {
+                        if (nbElements(results) === max) {
                             break;
                         }
                     }
                 }
             }
 
+            var ar = [];
+            for (var entry in results) {
+                if (results.hasOwnProperty(entry)) {
+                    ar.push(results[entry]);
+                }
+            }
+            results = ar;
             var nresults = results.length;
             for (var i = 0; i < nresults; ++i) {
                 results[i].word = searchWords[results[i].id];
                 return 0;
             });
 
-            // remove duplicates, according to the data provided
-            for (var i = results.length - 1; i > 0; i -= 1) {
-                if (results[i].word === results[i - 1].word &&
-                    results[i].item.ty === results[i - 1].item.ty &&
-                    results[i].item.path === results[i - 1].item.path &&
-                    (results[i].item.parent || {}).name === (results[i - 1].item.parent || {}).name)
-                {
-                    results[i].id = -1;
-                }
-            }
             for (var i = 0; i < results.length; ++i) {
                 var result = results[i],
                     name = result.item.name.toLowerCase(),
             elems[0].onclick = function() { printTab(0); };
             elems[1].onclick = function() { printTab(1); };
             elems[2].onclick = function() { printTab(2); };
+            printTab(currentTab);
         }
 
         function search(e) {
                         }
                     }
                     if (results['others'].length < maxResults &&
-                        ((query.search && obj.name.indexOf(query.search)) || added === false)) {
+                        ((query.search && obj.name.indexOf(query.search) !== -1) ||
+                          added === false)) {
                         results['others'].push(obj);
                     }
                 }
index 20da99a6b137658acaec97ef85359666abe58db8..fcb25f7aef3d4b10e00dc02eeca5dc0c9528fe0f 100644 (file)
@@ -14,6 +14,7 @@
        html_playground_url = "https://play.rust-lang.org/")]
 #![deny(warnings)]
 
+#![feature(ascii_ctype)]
 #![feature(rustc_private)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
@@ -23,7 +24,6 @@
 #![feature(test)]
 #![feature(unicode)]
 #![feature(vec_remove_item)]
-#![feature(ascii_ctype)]
 
 extern crate arena;
 extern crate getopts;
index 959543404d8d239242c656ee844668e447abf459..77d97c84c99bf0e77c125d57ab9575816d60b713 100644 (file)
@@ -116,7 +116,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             // handled in the `strip-priv-imports` pass
             clean::ExternCrateItem(..) | clean::ImportItem(..) => {}
 
-            clean::DefaultImplItem(..) | clean::ImplItem(..) => {}
+            clean::AutoImplItem(..) | clean::ImplItem(..) => {}
 
             // tymethods/macros have no control over privacy
             clean::MacroItem(..) | clean::TyMethodItem(..) => {}
index 327a330c2a2e5dba7a181a28a556a459f94828aa..b55076a01afe02c3de5a24f7229791730dd81259 100644 (file)
@@ -481,7 +481,7 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 };
                 om.constants.push(s);
             },
-            hir::ItemTrait(unsafety, ref gen, ref b, ref item_ids) => {
+            hir::ItemTrait(_, unsafety, ref gen, ref b, ref item_ids) => {
                 let items = item_ids.iter()
                                     .map(|ti| self.cx.tcx.hir.trait_item(ti.id).clone())
                                     .collect();
@@ -532,10 +532,10 @@ pub fn visit_item(&mut self, item: &hir::Item,
                     om.impls.push(i);
                 }
             },
-            hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
+            hir::ItemAutoImpl(unsafety, ref trait_ref) => {
                 // See comment above about ItemImpl.
                 if !self.inlining {
-                    let i = DefaultImpl {
+                    let i = AutoImpl {
                         unsafety,
                         trait_: trait_ref.clone(),
                         id: item.id,
index 5dd5f8953a00e143b7f130e1773327aa6fbd23ed..d239b79d4ba7a2d13a8df296ea7936ee8a1c2427 100644 (file)
@@ -3,6 +3,9 @@ authors = ["The Rust Project Developers"]
 name = "std"
 version = "0.0.0"
 build = "build.rs"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rust-lang/rust.git"
+description = "The Rust Standard Library"
 
 [lib]
 name = "std"
index 327deb9b419bee6c93ead3b6bf3554c152dfaace..96d719c528c109bf5fad03ef6a48ad897ce36b4a 100644 (file)
@@ -38,8 +38,8 @@
 /// ```
 /// use std::ascii::AsciiExt;
 ///
-/// assert_eq!("café".to_ascii_uppercase(), "CAFÉ");
-/// assert_eq!("café".to_ascii_uppercase(), "CAFé");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFÉ");
+/// assert_eq!(AsciiExt::to_ascii_uppercase("café"), "CAFé");
 /// ```
 ///
 /// In the first example, the lowercased string is represented `"cafe\u{301}"`
@@ -60,19 +60,10 @@ pub trait AsciiExt {
 
     /// Checks if the value is within the ASCII range.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
-    ///
-    /// assert!(ascii.is_ascii());
-    /// assert!(!non_ascii.is_ascii());
-    /// assert!(int_ascii.is_ascii());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn is_ascii(&self) -> bool;
 
@@ -86,19 +77,10 @@ pub trait AsciiExt {
     /// To uppercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_uppercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'a';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 97;
+    /// # Note
     ///
-    /// assert_eq!('A', ascii.to_ascii_uppercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
-    /// assert_eq!(65, int_ascii.to_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
     /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase
@@ -115,19 +97,10 @@ pub trait AsciiExt {
     /// To lowercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_lowercase`].
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii = 'A';
-    /// let non_ascii = '❤';
-    /// let int_ascii = 65;
-    ///
-    /// assert_eq!('a', ascii.to_ascii_lowercase());
-    /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
-    /// assert_eq!(97, int_ascii.to_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
     /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase
@@ -139,20 +112,10 @@ pub trait AsciiExt {
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
     /// but without allocating and copying temporaries.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let ascii1 = 'A';
-    /// let ascii2 = 'a';
-    /// let ascii3 = 'A';
-    /// let ascii4 = 'z';
+    /// # Note
     ///
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii2));
-    /// assert!(ascii1.eq_ignore_ascii_case(&ascii3));
-    /// assert!(!ascii1.eq_ignore_ascii_case(&ascii4));
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
 
@@ -164,17 +127,10 @@ pub trait AsciiExt {
     /// To return a new uppercased value without modifying the existing one, use
     /// [`to_ascii_uppercase`].
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// use std::ascii::AsciiExt;
-    ///
-    /// let mut ascii = 'a';
-    ///
-    /// ascii.make_ascii_uppercase();
-    ///
-    /// assert_eq!('A', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_uppercase`]: #tymethod.to_ascii_uppercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -188,17 +144,10 @@ pub trait AsciiExt {
     /// To return a new lowercased value without modifying the existing one, use
     /// [`to_ascii_lowercase`].
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::ascii::AsciiExt;
+    /// # Note
     ///
-    /// let mut ascii = 'A';
-    ///
-    /// ascii.make_ascii_lowercase();
-    ///
-    /// assert_eq!('a', ascii);
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     ///
     /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
     #[stable(feature = "ascii", since = "1.9.0")]
@@ -209,32 +158,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphabetic.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(A.is_ascii_alphabetic());
-    /// assert!(G.is_ascii_alphabetic());
-    /// assert!(a.is_ascii_alphabetic());
-    /// assert!(g.is_ascii_alphabetic());
-    /// assert!(!zero.is_ascii_alphabetic());
-    /// assert!(!percent.is_ascii_alphabetic());
-    /// assert!(!space.is_ascii_alphabetic());
-    /// assert!(!lf.is_ascii_alphabetic());
-    /// assert!(!esc.is_ascii_alphabetic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
 
@@ -243,32 +170,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII uppercase.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_uppercase());
-    /// assert!(G.is_ascii_uppercase());
-    /// assert!(!a.is_ascii_uppercase());
-    /// assert!(!g.is_ascii_uppercase());
-    /// assert!(!zero.is_ascii_uppercase());
-    /// assert!(!percent.is_ascii_uppercase());
-    /// assert!(!space.is_ascii_uppercase());
-    /// assert!(!lf.is_ascii_uppercase());
-    /// assert!(!esc.is_ascii_uppercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
 
@@ -277,32 +182,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII lowercase.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_lowercase());
-    /// assert!(!G.is_ascii_lowercase());
-    /// assert!(a.is_ascii_lowercase());
-    /// assert!(g.is_ascii_lowercase());
-    /// assert!(!zero.is_ascii_lowercase());
-    /// assert!(!percent.is_ascii_lowercase());
-    /// assert!(!space.is_ascii_lowercase());
-    /// assert!(!lf.is_ascii_lowercase());
-    /// assert!(!esc.is_ascii_lowercase());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
 
@@ -312,32 +195,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII alphanumeric.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_alphanumeric());
-    /// assert!(G.is_ascii_alphanumeric());
-    /// assert!(a.is_ascii_alphanumeric());
-    /// assert!(g.is_ascii_alphanumeric());
-    /// assert!(zero.is_ascii_alphanumeric());
-    /// assert!(!percent.is_ascii_alphanumeric());
-    /// assert!(!space.is_ascii_alphanumeric());
-    /// assert!(!lf.is_ascii_alphanumeric());
-    /// assert!(!esc.is_ascii_alphanumeric());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
 
@@ -346,32 +207,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII digits.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_digit());
-    /// assert!(!G.is_ascii_digit());
-    /// assert!(!a.is_ascii_digit());
-    /// assert!(!g.is_ascii_digit());
-    /// assert!(zero.is_ascii_digit());
-    /// assert!(!percent.is_ascii_digit());
-    /// assert!(!space.is_ascii_digit());
-    /// assert!(!lf.is_ascii_digit());
-    /// assert!(!esc.is_ascii_digit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_digit(&self) -> bool { unimplemented!(); }
 
@@ -381,32 +220,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII hex digits.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_hexdigit());
-    /// assert!(!G.is_ascii_hexdigit());
-    /// assert!(a.is_ascii_hexdigit());
-    /// assert!(!g.is_ascii_hexdigit());
-    /// assert!(zero.is_ascii_hexdigit());
-    /// assert!(!percent.is_ascii_hexdigit());
-    /// assert!(!space.is_ascii_hexdigit());
-    /// assert!(!lf.is_ascii_hexdigit());
-    /// assert!(!esc.is_ascii_hexdigit());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
 
@@ -420,32 +237,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_punctuation());
-    /// assert!(!G.is_ascii_punctuation());
-    /// assert!(!a.is_ascii_punctuation());
-    /// assert!(!g.is_ascii_punctuation());
-    /// assert!(!zero.is_ascii_punctuation());
-    /// assert!(percent.is_ascii_punctuation());
-    /// assert!(!space.is_ascii_punctuation());
-    /// assert!(!lf.is_ascii_punctuation());
-    /// assert!(!esc.is_ascii_punctuation());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
 
@@ -454,32 +249,10 @@ pub trait AsciiExt {
     /// For strings, true if all characters in the string are
     /// ASCII punctuation.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(A.is_ascii_graphic());
-    /// assert!(G.is_ascii_graphic());
-    /// assert!(a.is_ascii_graphic());
-    /// assert!(g.is_ascii_graphic());
-    /// assert!(zero.is_ascii_graphic());
-    /// assert!(percent.is_ascii_graphic());
-    /// assert!(!space.is_ascii_graphic());
-    /// assert!(!lf.is_ascii_graphic());
-    /// assert!(!esc.is_ascii_graphic());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
 
@@ -505,32 +278,10 @@ pub trait AsciiExt {
     /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
     /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
     ///
-    /// # Examples
+    /// # Note
     ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
-    ///
-    /// assert!(!A.is_ascii_whitespace());
-    /// assert!(!G.is_ascii_whitespace());
-    /// assert!(!a.is_ascii_whitespace());
-    /// assert!(!g.is_ascii_whitespace());
-    /// assert!(!zero.is_ascii_whitespace());
-    /// assert!(!percent.is_ascii_whitespace());
-    /// assert!(space.is_ascii_whitespace());
-    /// assert!(lf.is_ascii_whitespace());
-    /// assert!(!esc.is_ascii_whitespace());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
 
@@ -539,36 +290,18 @@ pub trait AsciiExt {
     /// Note that most ASCII whitespace characters are control
     /// characters, but SPACE is not.
     ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ascii_ctype)]
-    /// # #![allow(non_snake_case)]
-    /// use std::ascii::AsciiExt;
-    /// let A = 'A';
-    /// let G = 'G';
-    /// let a = 'a';
-    /// let g = 'g';
-    /// let zero = '0';
-    /// let percent = '%';
-    /// let space = ' ';
-    /// let lf = '\n';
-    /// let esc = '\u{001b}';
+    /// # Note
     ///
-    /// assert!(!A.is_ascii_control());
-    /// assert!(!G.is_ascii_control());
-    /// assert!(!a.is_ascii_control());
-    /// assert!(!g.is_ascii_control());
-    /// assert!(!zero.is_ascii_control());
-    /// assert!(!percent.is_ascii_control());
-    /// assert!(!space.is_ascii_control());
-    /// assert!(lf.is_ascii_control());
-    /// assert!(esc.is_ascii_control());
-    /// ```
+    /// This method will be deprecated in favor of the identically-named
+    /// inherent methods on `u8`, `char`, `[u8]` and `str`.
     #[unstable(feature = "ascii_ctype", issue = "39658")]
     fn is_ascii_control(&self) -> bool { unimplemented!(); }
 }
 
+// FIXME(LukasKalbertodt): this impl block can be removed in the future. This is
+// possible once the stage0 compiler is new enough to contain the inherent
+// ascii methods for `[str]`. See FIXME comment further down.
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsciiExt for str {
     type Owned = String;
@@ -660,6 +393,10 @@ fn is_ascii_control(&self) -> bool {
     }
 }
 
+// FIXME(LukasKalbertodt): this impl block can be removed in the future. This is
+// possible once the stage0 compiler is new enough to contain the inherent
+// ascii methods for `[u8]`. See FIXME comment further down.
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsciiExt for [u8] {
     type Owned = Vec<u8>;
@@ -753,201 +490,77 @@ fn is_ascii_control(&self) -> bool {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for u8 {
-    type Owned = u8;
-    #[inline]
-    fn is_ascii(&self) -> bool { *self & 128 == 0 }
-    #[inline]
-    fn to_ascii_uppercase(&self) -> u8 { ASCII_UPPERCASE_MAP[*self as usize] }
-    #[inline]
-    fn to_ascii_lowercase(&self) -> u8 { ASCII_LOWERCASE_MAP[*self as usize] }
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+macro_rules! impl_by_delegating {
+    ($ty:ty, $owned:ty) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl AsciiExt for $ty {
+            type Owned = $owned;
 
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii(&self) -> bool { self.is_ascii() }
 
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn to_ascii_uppercase(&self) -> Self::Owned { self.to_ascii_uppercase() }
 
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            L|Lx => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn to_ascii_lowercase(&self) -> Self::Owned { self.to_ascii_lowercase() }
 
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|L|Lx|U|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn eq_ignore_ascii_case(&self, o: &Self) -> bool { self.eq_ignore_ascii_case(o) }
 
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn make_ascii_uppercase(&mut self) { self.make_ascii_uppercase(); }
 
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            D|Lx|Ux => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn make_ascii_lowercase(&mut self) { self.make_ascii_lowercase(); }
 
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        if *self >= 0x80 { return false }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            P => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
 
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Ux|U|Lx|L|D|P => true,
-            _ => false
-        }
-    }
+            #[inline]
+            fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
 
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            Cw|W => true,
-            _ => false
-        }
-    }
-
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        if *self >= 0x80 { return false; }
-        match ASCII_CHARACTER_CLASS[*self as usize] {
-            C|Cw => true,
-            _ => false
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsciiExt for char {
-    type Owned = char;
-    #[inline]
-    fn is_ascii(&self) -> bool {
-        *self as u32 <= 0x7F
-    }
+            #[inline]
+            fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
 
-    #[inline]
-    fn to_ascii_uppercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_uppercase() as char
-        } else {
-            *self
-        }
-    }
+            #[inline]
+            fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
 
-    #[inline]
-    fn to_ascii_lowercase(&self) -> char {
-        if self.is_ascii() {
-            (*self as u8).to_ascii_lowercase() as char
-        } else {
-            *self
-        }
-    }
+            #[inline]
+            fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
 
-    #[inline]
-    fn eq_ignore_ascii_case(&self, other: &char) -> bool {
-        self.to_ascii_lowercase() == other.to_ascii_lowercase()
-    }
+            #[inline]
+            fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
 
-    #[inline]
-    fn make_ascii_uppercase(&mut self) { *self = self.to_ascii_uppercase(); }
-    #[inline]
-    fn make_ascii_lowercase(&mut self) { *self = self.to_ascii_lowercase(); }
+            #[inline]
+            fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
 
-    #[inline]
-    fn is_ascii_alphabetic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphabetic()
-    }
+            #[inline]
+            fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
 
-    #[inline]
-    fn is_ascii_uppercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_uppercase()
-    }
+            #[inline]
+            fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
 
-    #[inline]
-    fn is_ascii_lowercase(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_lowercase()
-    }
-
-    #[inline]
-    fn is_ascii_alphanumeric(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_alphanumeric()
-    }
-
-    #[inline]
-    fn is_ascii_digit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_digit()
-    }
-
-    #[inline]
-    fn is_ascii_hexdigit(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_hexdigit()
-    }
-
-    #[inline]
-    fn is_ascii_punctuation(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_punctuation()
+            #[inline]
+            fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
+        }
     }
+}
 
-    #[inline]
-    fn is_ascii_graphic(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_graphic()
-    }
+impl_by_delegating!(u8, u8);
+impl_by_delegating!(char, char);
 
-    #[inline]
-    fn is_ascii_whitespace(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_whitespace()
-    }
+// FIXME(LukasKalbertodt): the macro invocation should replace the impl block
+// for `[u8]` above. But this is not possible until the stage0 compiler is new
+// enough to contain the inherent ascii methods for `[u8]`.
+#[cfg(not(stage0))]
+impl_by_delegating!([u8], Vec<u8>);
 
-    #[inline]
-    fn is_ascii_control(&self) -> bool {
-        (*self as u32 <= 0x7f) && (*self as u8).is_ascii_control()
-    }
-}
+// FIXME(LukasKalbertodt): the macro invocation should replace the impl block
+// for `str` above. But this is not possible until the stage0 compiler is new
+// enough to contain the inherent ascii methods for `str`.
+#[cfg(not(stage0))]
+impl_by_delegating!(str, String);
 
 /// An iterator over the escaped version of a byte.
 ///
@@ -1066,112 +679,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 
-static ASCII_LOWERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@',
-
-          b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z',
-
-                      b'[', b'\\', b']', b'^', b'_',
-    b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
-    b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o',
-    b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
-    b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-static ASCII_UPPERCASE_MAP: [u8; 256] = [
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
-    b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
-    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
-    b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
-    b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
-    b'`',
-
-          b'A', b'B', b'C', b'D', b'E', b'F', b'G',
-    b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
-    b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
-    b'X', b'Y', b'Z',
-
-                      b'{', b'|', b'}', b'~', 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-];
-
-enum AsciiCharacterClass {
-    C,  // control
-    Cw, // control whitespace
-    W,  // whitespace
-    D,  // digit
-    L,  // lowercase
-    Lx, // lowercase hex digit
-    U,  // uppercase
-    Ux, // uppercase hex digit
-    P,  // punctuation
-}
-use self::AsciiCharacterClass::*;
-
-static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [
-//  _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
-    C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
-    C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_
-    W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_
-    D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_
-    P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_
-    U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_
-    P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_
-    L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_
-];
-
 #[cfg(test)]
 mod tests {
-    use super::*;
+    //! Note that most of these tests are not testing `AsciiExt` methods, but
+    //! test inherent ascii methods of char, u8, str and [u8]. `AsciiExt` is
+    //! just using those methods, though.
     use char::from_u32;
 
     #[test]
index d76ab31862bfc37a94eaeb96b4f87ec889e0fa33..4d5e4df6f95b8f24983dca3512292ca15b74339d 100644 (file)
@@ -17,6 +17,7 @@
 
 #[cfg(not(test))]
 #[doc(hidden)]
+#[allow(unused_attributes)]
 pub mod __default_lib_allocator {
     use super::{System, Layout, Alloc, AllocErr};
     use ptr;
@@ -28,6 +29,7 @@ pub mod __default_lib_allocator {
     // ABI
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc(size: usize,
                                      align: usize,
                                      err: *mut u8) -> *mut u8 {
@@ -42,11 +44,13 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
         System.oom((*(err as *const AllocErr)).clone())
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
                                        size: usize,
                                        align: usize) {
@@ -54,6 +58,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_usable_size(layout: *const u8,
                                            min: *mut usize,
                                            max: *mut usize) {
@@ -63,6 +68,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
                                        old_size: usize,
                                        old_align: usize,
@@ -81,6 +87,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
                                             align: usize,
                                             err: *mut u8) -> *mut u8 {
@@ -95,6 +102,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_alloc_excess(size: usize,
                                             align: usize,
                                             excess: *mut usize,
@@ -113,6 +121,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
                                               old_size: usize,
                                               old_align: usize,
@@ -135,6 +144,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
                                              old_size: usize,
                                              old_align: usize,
@@ -149,6 +159,7 @@ pub mod __default_lib_allocator {
     }
 
     #[no_mangle]
+    #[rustc_std_internal_symbol]
     pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
                                                old_size: usize,
                                                old_align: usize,
index 4ebd3554fd1428fc60f2854d7e1bc709fac70382..6d3fbc9d268222d3407b3e4cc8c3bbf43478da01 100644 (file)
@@ -147,6 +147,31 @@ pub fn get_ref(&self) -> &R { &self.inner }
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
 
+    /// Returns `true` if there are no bytes in the internal buffer.
+    ///
+    /// # Examples
+    /// ```
+    /// # #![feature(bufreader_is_empty)]
+    /// use std::io::BufReader;
+    /// use std::io::BufRead;
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let f1 = File::open("log.txt")?;
+    /// let mut reader = BufReader::new(f1);
+    /// assert!(reader.is_empty());
+    ///
+    /// if reader.fill_buf()?.len() > 0 {
+    ///     assert!(!reader.is_empty());
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+    pub fn is_empty(&self) -> bool {
+        self.pos == self.cap
+    }
+
     /// Unwraps this `BufReader`, returning the underlying reader.
     ///
     /// Note that any leftover data in the internal buffer is lost.
index 5cf1d225b9028cf90d2249bc3c222e33bbe5c446..429153dc58b4cb8e5bdd53f038375e07204f3b8e 100644 (file)
 #![feature(allow_internal_unstable)]
 #![feature(align_offset)]
 #![feature(array_error_internals)]
+#![feature(ascii_ctype)]
 #![feature(asm)]
 #![feature(attr_literals)]
 #![feature(box_syntax)]
index 97b09b7e2ad996b28c244adabffe7ed0d80b2063..385076e50ddeafc0e2341508472fadf589d2c91d 100644 (file)
@@ -188,6 +188,8 @@ pub struct AssertUnwindSafe<T>(
 // * Types like Mutex/RwLock which are explicilty poisoned are unwind safe
 // * Our custom AssertUnwindSafe wrapper is indeed unwind safe
 #[stable(feature = "catch_unwind", since = "1.9.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl UnwindSafe for .. {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<'a, T: ?Sized> !UnwindSafe for &'a mut T {}
@@ -221,6 +223,8 @@ impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Arc<T> {}
 // only thing which doesn't implement it (which then transitively applies to
 // everything else).
 #[stable(feature = "catch_unwind", since = "1.9.0")]
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl RefUnwindSafe for .. {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> !RefUnwindSafe for UnsafeCell<T> {}
index 294743ed2cc5414ff4879c35f03af301b7d10a01..270878dc029c3d52fec5fb70a17b5e1e43fc4a15 100644 (file)
@@ -77,7 +77,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use ascii::*;
 use borrow::{Borrow, Cow};
 use cmp;
 use error::Error;
index 39e00270233b41aa14a25e646b67984f5997bd3e..6e0cccff0019317419d934cb9f450c6c796c8309 100644 (file)
@@ -1228,7 +1228,7 @@ pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN {
     }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", feature = "backtrace"))]
 mod gnu {
     use super::*;
 
@@ -1256,5 +1256,5 @@ pub fn QueryFullProcessImageNameW(_hProcess: HANDLE,
     }
 }
 
-#[cfg(target_env = "gnu")]
+#[cfg(all(target_env = "gnu", feature = "backtrace"))]
 pub use self::gnu::*;
index 2b47808451bc29ed7b629e76778d6f7c52cf9024..98d62a0c953a6e6426546b075d2657af89579972 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ascii::*;
-
 use path::Prefix;
 use ffi::OsStr;
 use mem;
index 0d1766d5aec6d91b967cd5ff20a45c30011fdb66..631d69b05e115871e02c51997a41f44af8d96b7a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ascii::*;
+use ascii::AsciiExt;
 use collections::HashMap;
 use collections;
 use env::split_paths;
index 5c0c7a4fbca35c52a842f2f414f460f4ec0303ce..c012bdcb6dbe3fe707a86c9330d3646d8957913f 100644 (file)
@@ -923,6 +923,529 @@ pub fn to_lowercase(self) -> ToLowercase {
     pub fn to_uppercase(self) -> ToUppercase {
         ToUppercase(CaseMappingIter::new(conversions::to_upper(self)))
     }
+
+    /// Checks if the value is within the ASCII range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 'a';
+    /// let non_ascii = '❤';
+    ///
+    /// assert!(ascii.is_ascii());
+    /// assert!(!non_ascii.is_ascii());
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        *self as u32 <= 0x7F
+    }
+
+    /// Makes a copy of the value in its ASCII upper case equivalent.
+    ///
+    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
+    ///
+    /// To uppercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_uppercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 'a';
+    /// let non_ascii = '❤';
+    ///
+    /// assert_eq!('A', ascii.to_ascii_uppercase());
+    /// assert_eq!('❤', non_ascii.to_ascii_uppercase());
+    /// ```
+    ///
+    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    /// [`to_uppercase`]: #method.to_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_uppercase(&self) -> char {
+        if self.is_ascii() {
+            (*self as u8).to_ascii_uppercase() as char
+        } else {
+            *self
+        }
+    }
+
+    /// Makes a copy of the value in its ASCII lower case equivalent.
+    ///
+    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
+    /// but non-ASCII letters are unchanged.
+    ///
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
+    ///
+    /// To lowercase ASCII characters in addition to non-ASCII characters, use
+    /// [`to_lowercase`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let ascii = 'A';
+    /// let non_ascii = '❤';
+    ///
+    /// assert_eq!('a', ascii.to_ascii_lowercase());
+    /// assert_eq!('❤', non_ascii.to_ascii_lowercase());
+    /// ```
+    ///
+    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    /// [`to_lowercase`]: #method.to_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn to_ascii_lowercase(&self) -> char {
+        if self.is_ascii() {
+            (*self as u8).to_ascii_lowercase() as char
+        } else {
+            *self
+        }
+    }
+
+    /// Checks that two values are an ASCII case-insensitive match.
+    ///
+    /// Equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let upper_a = 'A';
+    /// let lower_a = 'a';
+    /// let lower_z = 'z';
+    ///
+    /// assert!(upper_a.eq_ignore_ascii_case(&lower_a));
+    /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
+    /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
+    /// ```
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &char) -> bool {
+        self.to_ascii_lowercase() == other.to_ascii_lowercase()
+    }
+
+    /// Converts this type 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`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut ascii = 'a';
+    ///
+    /// ascii.make_ascii_uppercase();
+    ///
+    /// assert_eq!('A', ascii);
+    /// ```
+    ///
+    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        *self = self.to_ascii_uppercase();
+    }
+
+    /// Converts this type 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`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut ascii = 'A';
+    ///
+    /// ascii.make_ascii_lowercase();
+    ///
+    /// assert_eq!('a', ascii);
+    /// ```
+    ///
+    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    #[stable(feature = "ascii_methods_on_intrinsics", since = "1.21.0")]
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        *self = self.to_ascii_lowercase();
+    }
+
+    /// Checks if the value is an ASCII alphabetic character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_alphabetic());
+    /// assert!(uppercase_g.is_ascii_alphabetic());
+    /// assert!(a.is_ascii_alphabetic());
+    /// assert!(g.is_ascii_alphabetic());
+    /// assert!(!zero.is_ascii_alphabetic());
+    /// assert!(!percent.is_ascii_alphabetic());
+    /// assert!(!space.is_ascii_alphabetic());
+    /// assert!(!lf.is_ascii_alphabetic());
+    /// assert!(!esc.is_ascii_alphabetic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphabetic(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_alphabetic()
+    }
+
+    /// Checks if the value is an ASCII uppercase character:
+    /// U+0041 'A' ... U+005A 'Z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_uppercase());
+    /// assert!(uppercase_g.is_ascii_uppercase());
+    /// assert!(!a.is_ascii_uppercase());
+    /// assert!(!g.is_ascii_uppercase());
+    /// assert!(!zero.is_ascii_uppercase());
+    /// assert!(!percent.is_ascii_uppercase());
+    /// assert!(!space.is_ascii_uppercase());
+    /// assert!(!lf.is_ascii_uppercase());
+    /// assert!(!esc.is_ascii_uppercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_uppercase(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_uppercase()
+    }
+
+    /// Checks if the value is an ASCII lowercase character:
+    /// U+0061 'a' ... U+007A 'z'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_lowercase());
+    /// assert!(!uppercase_g.is_ascii_lowercase());
+    /// assert!(a.is_ascii_lowercase());
+    /// assert!(g.is_ascii_lowercase());
+    /// assert!(!zero.is_ascii_lowercase());
+    /// assert!(!percent.is_ascii_lowercase());
+    /// assert!(!space.is_ascii_lowercase());
+    /// assert!(!lf.is_ascii_lowercase());
+    /// assert!(!esc.is_ascii_lowercase());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_lowercase(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_lowercase()
+    }
+
+    /// Checks if the value is an ASCII alphanumeric character:
+    ///
+    /// - U+0041 'A' ... U+005A 'Z', or
+    /// - U+0061 'a' ... U+007A 'z', or
+    /// - U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_alphanumeric());
+    /// assert!(uppercase_g.is_ascii_alphanumeric());
+    /// assert!(a.is_ascii_alphanumeric());
+    /// assert!(g.is_ascii_alphanumeric());
+    /// assert!(zero.is_ascii_alphanumeric());
+    /// assert!(!percent.is_ascii_alphanumeric());
+    /// assert!(!space.is_ascii_alphanumeric());
+    /// assert!(!lf.is_ascii_alphanumeric());
+    /// assert!(!esc.is_ascii_alphanumeric());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_alphanumeric(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_alphanumeric()
+    }
+
+    /// Checks if the value is an ASCII decimal digit:
+    /// U+0030 '0' ... U+0039 '9'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_digit());
+    /// assert!(!uppercase_g.is_ascii_digit());
+    /// assert!(!a.is_ascii_digit());
+    /// assert!(!g.is_ascii_digit());
+    /// assert!(zero.is_ascii_digit());
+    /// assert!(!percent.is_ascii_digit());
+    /// assert!(!space.is_ascii_digit());
+    /// assert!(!lf.is_ascii_digit());
+    /// assert!(!esc.is_ascii_digit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_digit(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_digit()
+    }
+
+    /// Checks if the value is an ASCII hexadecimal digit:
+    ///
+    /// - U+0030 '0' ... U+0039 '9', or
+    /// - U+0041 'A' ... U+0046 'F', or
+    /// - U+0061 'a' ... U+0066 'f'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_hexdigit());
+    /// assert!(!uppercase_g.is_ascii_hexdigit());
+    /// assert!(a.is_ascii_hexdigit());
+    /// assert!(!g.is_ascii_hexdigit());
+    /// assert!(zero.is_ascii_hexdigit());
+    /// assert!(!percent.is_ascii_hexdigit());
+    /// assert!(!space.is_ascii_hexdigit());
+    /// assert!(!lf.is_ascii_hexdigit());
+    /// assert!(!esc.is_ascii_hexdigit());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_hexdigit(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_hexdigit()
+    }
+
+    /// Checks if the value is an ASCII punctuation character:
+    ///
+    /// - U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`, or
+    /// - U+003A ... U+0040 `: ; < = > ? @`, or
+    /// - U+005B ... U+0060 `[ \\ ] ^ _ \``, or
+    /// - U+007B ... U+007E `{ | } ~`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_punctuation());
+    /// assert!(!uppercase_g.is_ascii_punctuation());
+    /// assert!(!a.is_ascii_punctuation());
+    /// assert!(!g.is_ascii_punctuation());
+    /// assert!(!zero.is_ascii_punctuation());
+    /// assert!(percent.is_ascii_punctuation());
+    /// assert!(!space.is_ascii_punctuation());
+    /// assert!(!lf.is_ascii_punctuation());
+    /// assert!(!esc.is_ascii_punctuation());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_punctuation(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_punctuation()
+    }
+
+    /// Checks if the value is an ASCII graphic character:
+    /// U+0021 '@' ... U+007E '~'.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(uppercase_a.is_ascii_graphic());
+    /// assert!(uppercase_g.is_ascii_graphic());
+    /// assert!(a.is_ascii_graphic());
+    /// assert!(g.is_ascii_graphic());
+    /// assert!(zero.is_ascii_graphic());
+    /// assert!(percent.is_ascii_graphic());
+    /// assert!(!space.is_ascii_graphic());
+    /// assert!(!lf.is_ascii_graphic());
+    /// assert!(!esc.is_ascii_graphic());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_graphic(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_graphic()
+    }
+
+    /// Checks if the value is an ASCII whitespace character:
+    /// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
+    /// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
+    ///
+    /// Rust uses the WhatWG Infra Standard's [definition of ASCII
+    /// whitespace][infra-aw]. There are several other definitions in
+    /// wide use. For instance, [the POSIX locale][pct] includes
+    /// U+000B VERTICAL TAB as well as all the above characters,
+    /// but—from the very same specification—[the default rule for
+    /// "field splitting" in the Bourne shell][bfs] considers *only*
+    /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
+    ///
+    /// If you are writing a program that will process an existing
+    /// file format, check what that format's definition of whitespace is
+    /// before using this function.
+    ///
+    /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
+    /// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
+    /// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_whitespace());
+    /// assert!(!uppercase_g.is_ascii_whitespace());
+    /// assert!(!a.is_ascii_whitespace());
+    /// assert!(!g.is_ascii_whitespace());
+    /// assert!(!zero.is_ascii_whitespace());
+    /// assert!(!percent.is_ascii_whitespace());
+    /// assert!(space.is_ascii_whitespace());
+    /// assert!(lf.is_ascii_whitespace());
+    /// assert!(!esc.is_ascii_whitespace());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_whitespace(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_whitespace()
+    }
+
+    /// Checks if the value is an ASCII control character:
+    /// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
+    /// Note that most ASCII whitespace characters are control
+    /// characters, but SPACE is not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ascii_ctype)]
+    ///
+    /// let uppercase_a = 'A';
+    /// let uppercase_g = 'G';
+    /// let a = 'a';
+    /// let g = 'g';
+    /// let zero = '0';
+    /// let percent = '%';
+    /// let space = ' ';
+    /// let lf = '\n';
+    /// let esc: char = 0x1b_u8.into();
+    ///
+    /// assert!(!uppercase_a.is_ascii_control());
+    /// assert!(!uppercase_g.is_ascii_control());
+    /// assert!(!a.is_ascii_control());
+    /// assert!(!g.is_ascii_control());
+    /// assert!(!zero.is_ascii_control());
+    /// assert!(!percent.is_ascii_control());
+    /// assert!(!space.is_ascii_control());
+    /// assert!(lf.is_ascii_control());
+    /// assert!(esc.is_ascii_control());
+    /// ```
+    #[unstable(feature = "ascii_ctype", issue = "39658")]
+    #[inline]
+    pub fn is_ascii_control(&self) -> bool {
+        self.is_ascii() && (*self as u8).is_ascii_control()
+    }
 }
 
 /// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
index e5a114caed0f4e90378751d7e736f1667cd62fb9..65058b6554aa6d6a809c22f93764c2cd781dedbf 100644 (file)
@@ -30,6 +30,7 @@
 #![deny(warnings)]
 #![no_std]
 
+#![feature(ascii_ctype)]
 #![feature(core_char_ext)]
 #![feature(str_internals)]
 #![feature(decode_utf8)]
index be0af8052eb13d5776d6b402cf7657e5a9f7c2d6..99dff4edaade751cfcf5492bcd0969ee1f2e2428 100644 (file)
@@ -1581,6 +1581,13 @@ pub fn has_self(&self) -> bool {
     }
 }
 
+/// Is the trait definition an auto trait?
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum IsAuto {
+    Yes,
+    No
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Unsafety {
     Unsafe,
@@ -1942,12 +1949,12 @@ pub enum ItemKind {
     Union(VariantData, Generics),
     /// A Trait declaration (`trait` or `pub trait`).
     ///
-    /// E.g. `trait Foo { .. }` or `trait Foo<T> { .. }`
-    Trait(Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
+    /// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`
+    Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
     /// Auto trait implementation.
     ///
     /// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
-    DefaultImpl(Unsafety, TraitRef),
+    AutoImpl(Unsafety, TraitRef),
     /// An implementation.
     ///
     /// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
@@ -1986,7 +1993,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemKind::Mac(..) |
             ItemKind::MacroDef(..) |
             ItemKind::Impl(..) |
-            ItemKind::DefaultImpl(..) => "item"
+            ItemKind::AutoImpl(..) => "item"
         }
     }
 }
index ad78c550cf60e1b1be5f32c2a4559a4b67567b85..3464db2a811119ebd63767af1a7ca2c49f7e6e79 100644 (file)
@@ -242,7 +242,8 @@ pub fn new_imported_filemap(&self,
                                 src_hash: u128,
                                 source_len: usize,
                                 mut file_local_lines: Vec<BytePos>,
-                                mut file_local_multibyte_chars: Vec<MultiByteChar>)
+                                mut file_local_multibyte_chars: Vec<MultiByteChar>,
+                                mut file_local_non_narrow_chars: Vec<NonNarrowChar>)
                                 -> Rc<FileMap> {
         let start_pos = self.next_start_pos();
         let mut files = self.files.borrow_mut();
@@ -258,6 +259,10 @@ pub fn new_imported_filemap(&self,
             mbc.pos = mbc.pos + start_pos;
         }
 
+        for swc in &mut file_local_non_narrow_chars {
+            *swc = *swc + start_pos;
+        }
+
         let filemap = Rc::new(FileMap {
             name: filename,
             name_was_remapped,
@@ -270,6 +275,7 @@ pub fn new_imported_filemap(&self,
             end_pos,
             lines: RefCell::new(file_local_lines),
             multibyte_chars: RefCell::new(file_local_multibyte_chars),
+            non_narrow_chars: RefCell::new(file_local_non_narrow_chars),
         });
 
         files.push(filemap.clone());
@@ -297,6 +303,24 @@ pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
                 let line = a + 1; // Line numbers start at 1
                 let linebpos = (*f.lines.borrow())[a];
                 let linechpos = self.bytepos_to_file_charpos(linebpos);
+                let col = chpos - linechpos;
+
+                let col_display = {
+                    let non_narrow_chars = f.non_narrow_chars.borrow();
+                    let start_width_idx = non_narrow_chars
+                        .binary_search_by_key(&linebpos, |x| x.pos())
+                        .unwrap_or_else(|x| x);
+                    let end_width_idx = non_narrow_chars
+                        .binary_search_by_key(&pos, |x| x.pos())
+                        .unwrap_or_else(|x| x);
+                    let special_chars = end_width_idx - start_width_idx;
+                    let non_narrow: usize =
+                        non_narrow_chars[start_width_idx..end_width_idx]
+                        .into_iter()
+                        .map(|x| x.width())
+                        .sum();
+                    col.0 - special_chars + non_narrow
+                };
                 debug!("byte pos {:?} is on the line at byte pos {:?}",
                        pos, linebpos);
                 debug!("char pos {:?} is on the line at char pos {:?}",
@@ -306,14 +330,28 @@ pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
                 Loc {
                     file: f,
                     line,
-                    col: chpos - linechpos,
+                    col,
+                    col_display,
                 }
             }
             Err(f) => {
+                let col_display = {
+                    let non_narrow_chars = f.non_narrow_chars.borrow();
+                    let end_width_idx = non_narrow_chars
+                        .binary_search_by_key(&pos, |x| x.pos())
+                        .unwrap_or_else(|x| x);
+                    let non_narrow: usize =
+                        non_narrow_chars[0..end_width_idx]
+                        .into_iter()
+                        .map(|x| x.width())
+                        .sum();
+                    chpos.0 - end_width_idx + non_narrow
+                };
                 Loc {
                     file: f,
                     line: 0,
                     col: chpos,
+                    col_display,
                 }
             }
         }
index e8ecf58072a6988007148e277ddf40ca7b5a0a97..c01836b6194113b3097a4429df1e547f840410a8 100644 (file)
@@ -18,7 +18,11 @@ macro_rules! register_diagnostic {
 macro_rules! span_fatal {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.span_fatal_with_code($span, &format!($($message)*), stringify!($code))
+        $session.span_fatal_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -26,7 +30,11 @@ macro_rules! span_fatal {
 macro_rules! span_err {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.span_err_with_code($span, &format!($($message)*), stringify!($code))
+        $session.span_err_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -34,7 +42,11 @@ macro_rules! span_err {
 macro_rules! span_warn {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.span_warn_with_code($span, &format!($($message)*), stringify!($code))
+        $session.span_warn_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -42,7 +54,10 @@ macro_rules! span_warn {
 macro_rules! struct_err {
     ($session:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_err_with_code(&format!($($message)*), stringify!($code))
+        $session.struct_err_with_code(
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -51,9 +66,17 @@ macro_rules! span_err_or_warn {
     ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
         if $is_warning {
-            $session.span_warn_with_code($span, &format!($($message)*), stringify!($code))
+            $session.span_warn_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         } else {
-            $session.span_err_with_code($span, &format!($($message)*), stringify!($code))
+            $session.span_err_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         }
     })
 }
@@ -62,7 +85,11 @@ macro_rules! span_err_or_warn {
 macro_rules! struct_span_fatal {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_span_fatal_with_code($span, &format!($($message)*), stringify!($code))
+        $session.struct_span_fatal_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -70,7 +97,11 @@ macro_rules! struct_span_fatal {
 macro_rules! struct_span_err {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_span_err_with_code($span, &format!($($message)*), stringify!($code))
+        $session.struct_span_err_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -89,7 +120,11 @@ macro_rules! type_error_struct {
 macro_rules! struct_span_warn {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        $session.struct_span_warn_with_code($span, &format!($($message)*), stringify!($code))
+        $session.struct_span_warn_with_code(
+            $span,
+            &format!($($message)*),
+            $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+        )
     })
 }
 
@@ -98,9 +133,17 @@ macro_rules! struct_span_err_or_warn {
     ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
         if $is_warning {
-            $session.struct_span_warn_with_code($span, &format!($($message)*), stringify!($code))
+            $session.struct_span_warn_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         } else {
-            $session.struct_span_err_with_code($span, &format!($($message)*), stringify!($code))
+            $session.struct_span_err_with_code(
+                $span,
+                &format!($($message)*),
+                $crate::errors::DiagnosticId::Error(stringify!($code).to_owned()),
+            )
         }
     })
 }
index 30451ec757a9f5c0f17109795110e9fb50de53f4..a69bf53ee14a3e1306553758b8694948a0e02936 100644 (file)
@@ -35,7 +35,6 @@
 use parse::ParseSess;
 use symbol::Symbol;
 
-use std::ascii::AsciiExt;
 use std::env;
 
 macro_rules! set {
@@ -386,6 +385,9 @@ pub fn new() -> Features {
     // allow '|' at beginning of match arms (RFC 1925)
     (active, match_beginning_vert, "1.21.0", Some(44101)),
 
+    // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008)
+    (active, non_exhaustive, "1.22.0", Some(44109)),
+
     // Copy/Clone closures (RFC 2132)
     (active, clone_closures, "1.22.0", Some(44490)),
     (active, copy_closures, "1.22.0", Some(44490)),
@@ -614,6 +616,12 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                              not yet settled",
                                             cfg_fn!(structural_match))),
 
+    // RFC #2008
+    ("non_exhaustive", Whitelisted, Gated(Stability::Unstable,
+                                          "non_exhaustive",
+                                          "non exhaustive is an experimental feature",
+                                          cfg_fn!(non_exhaustive))),
+
     ("plugin", CrateLevel, Gated(Stability::Unstable,
                                  "plugin",
                                  "compiler plugins are experimental \
@@ -908,6 +916,12 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                  "allow_fail attribute is currently unstable",
                                  cfg_fn!(allow_fail))),
 
+    ("rustc_std_internal_symbol", Whitelisted, Gated(Stability::Unstable,
+                                     "rustc_attrs",
+                                     "this is an internal attribute that will \
+                                      never be stable",
+                                     cfg_fn!(rustc_attrs))),
+
     // Crate level attributes
     ("crate_name", CrateLevel, Ungated),
     ("crate_type", CrateLevel, Ungated),
@@ -1357,10 +1371,10 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
-            ast::ItemKind::DefaultImpl(..) => {
+            ast::ItemKind::AutoImpl(..) => {
                 gate_feature_post!(&self, optin_builtin_traits,
                                    i.span,
-                                   "default trait implementations are experimental \
+                                   "auto trait implementations are experimental \
                                     and possibly buggy");
             }
 
@@ -1389,6 +1403,12 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
+            ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
+                gate_feature_post!(&self, optin_builtin_traits,
+                                   i.span,
+                                   "auto traits are experimental and possibly buggy");
+            }
+
             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
                 let msg = "`macro` is experimental";
                 gate_feature_post!(&self, decl_macro, i.span, msg);
index fea49424dc8d2261c6dbba20f44bb4f78bcf6846..cc63bffec48a1652eca563e33bc0b58096eb8768 100644 (file)
@@ -908,8 +908,8 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
             let generics = folder.fold_generics(generics);
             ItemKind::Union(folder.fold_variant_data(struct_def), generics)
         }
-        ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
-            ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
+        ItemKind::AutoImpl(unsafety, ref trait_ref) => {
+            ItemKind::AutoImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
         }
         ItemKind::Impl(unsafety,
                        polarity,
@@ -926,7 +926,8 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
             folder.fold_ty(ty),
             impl_items.move_flat_map(|item| folder.fold_impl_item(item)),
         ),
-        ItemKind::Trait(unsafety, generics, bounds, items) => ItemKind::Trait(
+        ItemKind::Trait(is_auto, unsafety, generics, bounds, items) => ItemKind::Trait(
+            is_auto,
             unsafety,
             folder.fold_generics(generics),
             folder.fold_bounds(bounds),
index b8151819bffed683f4589ea1798e9170b20b2790..74a762f2f622cdf702840e9377fc3d46a39fb312 100644 (file)
 use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
 use errors::registry::Registry;
 use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
+use errors::DiagnosticId;
 use errors::emitter::Emitter;
 
 use std::rc::Rc;
 use std::io::{self, Write};
 use std::vec;
 
-use rustc_serialize::json::as_json;
+use rustc_serialize::json::{as_json, as_pretty_json};
 
 pub struct JsonEmitter {
     dst: Box<Write + Send>,
     registry: Option<Registry>,
     cm: Rc<CodeMapper + 'static>,
+    pretty: bool,
 }
 
 impl JsonEmitter {
     pub fn stderr(registry: Option<Registry>,
-                  code_map: Rc<CodeMap>) -> JsonEmitter {
+                  code_map: Rc<CodeMap>,
+                  pretty: bool) -> JsonEmitter {
         JsonEmitter {
             dst: Box::new(io::stderr()),
             registry,
             cm: code_map,
+            pretty,
         }
     }
 
-    pub fn basic() -> JsonEmitter {
+    pub fn basic(pretty: bool) -> JsonEmitter {
         let file_path_mapping = FilePathMapping::empty();
-        JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)))
+        JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)), pretty)
     }
 
     pub fn new(dst: Box<Write + Send>,
                registry: Option<Registry>,
-               code_map: Rc<CodeMap>) -> JsonEmitter {
+               code_map: Rc<CodeMap>,
+               pretty: bool) -> JsonEmitter {
         JsonEmitter {
             dst,
             registry,
             cm: code_map,
+            pretty,
         }
     }
 }
@@ -66,7 +72,12 @@ pub fn new(dst: Box<Write + Send>,
 impl Emitter for JsonEmitter {
     fn emit(&mut self, db: &DiagnosticBuilder) {
         let data = Diagnostic::from_diagnostic_builder(db, self);
-        if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
+        let result = if self.pretty {
+            writeln!(&mut self.dst, "{}", as_pretty_json(&data))
+        } else {
+            writeln!(&mut self.dst, "{}", as_json(&data))
+        };
+        if let Err(e) = result {
             panic!("failed to print diagnostics: {:?}", e);
         }
     }
@@ -84,9 +95,7 @@ struct Diagnostic {
     spans: Vec<DiagnosticSpan>,
     /// Associated diagnostic messages.
     children: Vec<Diagnostic>,
-    /// The message as rustc would render it. Currently this is only
-    /// `Some` for "suggestions", but eventually it will include all
-    /// snippets.
+    /// The message as rustc would render it. Currently this is always `None`
     rendered: Option<String>,
 }
 
@@ -109,9 +118,7 @@ struct DiagnosticSpan {
     /// Label that should be placed at this location (if any)
     label: Option<String>,
     /// If we are suggesting a replacement, this will contain text
-    /// that should be sliced in atop this span. You may prefer to
-    /// load the fully rendered version from the parent `Diagnostic`,
-    /// however.
+    /// that should be sliced in atop this span.
     suggested_replacement: Option<String>,
     /// Macro invocations that created the code at this span, if any.
     expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
@@ -340,9 +347,12 @@ fn from_span(span: Span, je: &JsonEmitter) -> Vec<DiagnosticSpanLine> {
 }
 
 impl DiagnosticCode {
-    fn map_opt_string(s: Option<String>, je: &JsonEmitter) -> Option<DiagnosticCode> {
+    fn map_opt_string(s: Option<DiagnosticId>, je: &JsonEmitter) -> Option<DiagnosticCode> {
         s.map(|s| {
-
+            let s = match s {
+                DiagnosticId::Error(s) => s,
+                DiagnosticId::Lint(s) => s,
+            };
             let explanation = je.registry
                                 .as_ref()
                                 .and_then(|registry| registry.find_description(&s));
index d9c3dbb630d0cb9890b41920f3884c542062bcfb..951163d35fa0fbc7fe321e18a31e783bdbcc4ee0 100644 (file)
@@ -433,6 +433,7 @@ pub fn bump(&mut self) {
                     self.filemap.record_multibyte_char(self.pos, new_ch_len);
                 }
             }
+            self.filemap.record_width(self.pos, new_ch);
         } else {
             self.ch = None;
             self.pos = new_pos;
index a3a265450ab0e9c1949f253c3bcd055618311e23..424f46840ad14ec5717cea439e0932bc998ced42 100644 (file)
@@ -21,7 +21,7 @@
 use ast::{Expr, ExprKind, RangeLimits};
 use ast::{Field, FnDecl};
 use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
-use ast::{Ident, ImplItem, Item, ItemKind};
+use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
 use ast::{Lifetime, LifetimeDef, Lit, LitKind, UintTy};
 use ast::Local;
 use ast::MacStmtStyle;
@@ -3154,7 +3154,13 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
 
         let pat = self.parse_pat()?;
-        self.expect_keyword(keywords::In)?;
+        if !self.eat_keyword(keywords::In) {
+            let in_span = self.prev_span.between(self.span);
+            let mut err = self.sess.span_diagnostic
+                .struct_span_err(in_span, "missing `in` in `for` loop");
+            err.span_suggestion_short(in_span, "try adding `in` here", " in ".into());
+            err.emit();
+        }
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
         let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
@@ -3873,6 +3879,16 @@ fn is_union_item(&self) -> bool {
         self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
     }
 
+    fn eat_auto_trait(&mut self) -> bool {
+        if self.token.is_keyword(keywords::Auto)
+            && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
+        {
+            self.eat_keyword(keywords::Auto) && self.eat_keyword(keywords::Trait)
+        } else {
+            false
+        }
+    }
+
     fn is_defaultness(&self) -> bool {
         // `pub` is included for better error messages
         self.token.is_keyword(keywords::Default) &&
@@ -5051,7 +5067,7 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
     }
 
     /// Parse trait Foo { ... }
-    fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
         let ident = self.parse_ident()?;
         let mut tps = self.parse_generics()?;
 
@@ -5078,7 +5094,7 @@ fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
                 }
             }
         }
-        Ok((ident, ItemKind::Trait(unsafety, tps, bounds, trait_items), None))
+        Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None))
     }
 
     /// Parses items implementations variants
@@ -5133,19 +5149,19 @@ fn parse_item_impl(&mut self,
 
         if opt_trait.is_some() && self.eat(&token::DotDot) {
             if generics.is_parameterized() {
-                self.span_err(impl_span, "default trait implementations are not \
+                self.span_err(impl_span, "auto trait implementations are not \
                                           allowed to have generics");
             }
 
             if let ast::Defaultness::Default = defaultness {
                 self.span_err(impl_span, "`default impl` is not allowed for \
-                                         default trait implementations");
+                                         auto trait implementations");
             }
 
             self.expect(&token::OpenDelim(token::Brace))?;
             self.expect(&token::CloseDelim(token::Brace))?;
             Ok((keywords::Invalid.ident(),
-             ItemKind::DefaultImpl(unsafety, opt_trait.unwrap()), None))
+             ItemKind::AutoImpl(unsafety, opt_trait.unwrap()), None))
         } else {
             if opt_trait.is_some() {
                 ty = self.parse_ty()?;
@@ -5988,13 +6004,19 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
             return Ok(Some(item));
         }
         if self.check_keyword(keywords::Unsafe) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
+            (self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) ||
+            self.look_ahead(1, |t| t.is_keyword(keywords::Auto)))
         {
             // UNSAFE TRAIT ITEM
             self.expect_keyword(keywords::Unsafe)?;
-            self.expect_keyword(keywords::Trait)?;
+            let is_auto = if self.eat_keyword(keywords::Trait) {
+                IsAuto::No
+            } else {
+                self.eat_auto_trait();
+                IsAuto::Yes
+            };
             let (ident, item_, extra_attrs) =
-                self.parse_item_trait(ast::Unsafety::Unsafe)?;
+                self.parse_item_trait(is_auto, ast::Unsafety::Unsafe)?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
@@ -6097,10 +6119,19 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.eat_keyword(keywords::Trait) {
+        if self.check_keyword(keywords::Trait)
+            || (self.check_keyword(keywords::Auto)
+                && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
+        {
+            let is_auto = if self.eat_keyword(keywords::Trait) {
+                IsAuto::No
+            } else {
+                self.eat_auto_trait();
+                IsAuto::Yes
+            };
             // TRAIT ITEM
             let (ident, item_, extra_attrs) =
-                self.parse_item_trait(ast::Unsafety::Normal)?;
+                self.parse_item_trait(is_auto, ast::Unsafety::Normal)?;
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
index 8a970fd409895af864a30681ba79f9be2e021230..227db93cf656e0196ee7af197b31b34df95c91e5 100644 (file)
@@ -1287,7 +1287,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.head(&visibility_qualified(&item.vis, "union"))?;
                 self.print_struct(struct_def, generics, item.ident, item.span, true)?;
             }
-            ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
+            ast::ItemKind::AutoImpl(unsafety, ref trait_ref) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
                 self.print_unsafety(unsafety)?;
@@ -1338,10 +1338,11 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 }
                 self.bclose(item.span)?;
             }
-            ast::ItemKind::Trait(unsafety, ref generics, ref bounds, ref trait_items) => {
+            ast::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
                 self.head("")?;
                 self.print_visibility(&item.vis)?;
                 self.print_unsafety(unsafety)?;
+                self.print_is_auto(is_auto)?;
                 self.word_nbsp("trait")?;
                 self.print_ident(item.ident)?;
                 self.print_generics(generics)?;
@@ -3123,6 +3124,13 @@ pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> {
             ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
         }
     }
+
+    pub fn print_is_auto(&mut self, s: ast::IsAuto) -> io::Result<()> {
+        match s {
+            ast::IsAuto::Yes => self.word_nbsp("auto"),
+            ast::IsAuto::No => Ok(()),
+        }
+    }
 }
 
 fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
index 96e47a6cc0ff64e0b0e5210c204c03b1e0ea7c6d..c2e90f0bb13a32f30d19bf688c7a13e89ecc35a2 100644 (file)
@@ -281,7 +281,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(type_parameters);
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
-        ItemKind::DefaultImpl(_, ref trait_ref) => {
+        ItemKind::AutoImpl(_, ref trait_ref) => {
             visitor.visit_trait_ref(trait_ref)
         }
         ItemKind::Impl(_, _, _,
@@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_variant_data(struct_definition, item.ident,
                                      generics, item.id, item.span);
         }
-        ItemKind::Trait(_, ref generics, ref bounds, ref methods) => {
+        ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_ty_param_bound, bounds);
             walk_list!(visitor, visit_trait_item, methods);
index dd8129bab510fc28d7381b4c20a3fe614efb4c5b..aad2155157d841cf62a7595d26da62131e2dfef2 100644 (file)
@@ -11,3 +11,4 @@ crate-type = ["dylib"]
 [dependencies]
 serialize = { path = "../libserialize" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+unicode-width = "0.1.4"
index 44e73d876e85a9f1ee3a84d7c4ebac2b7df138c2..47755dc1d54680a3a0c899ec0ff94a459897d79b 100644 (file)
@@ -44,6 +44,8 @@
 extern crate serialize;
 extern crate serialize as rustc_serialize; // used by deriving
 
+extern crate unicode_width;
+
 pub mod hygiene;
 pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind};
 
@@ -494,6 +496,63 @@ pub struct MultiByteChar {
     pub bytes: usize,
 }
 
+/// Identifies an offset of a non-narrow character in a FileMap
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq)]
+pub enum NonNarrowChar {
+    /// Represents a zero-width character
+    ZeroWidth(BytePos),
+    /// Represents a wide (fullwidth) character
+    Wide(BytePos),
+}
+
+impl NonNarrowChar {
+    fn new(pos: BytePos, width: usize) -> Self {
+        match width {
+            0 => NonNarrowChar::ZeroWidth(pos),
+            2 => NonNarrowChar::Wide(pos),
+            _ => panic!("width {} given for non-narrow character", width),
+        }
+    }
+
+    /// Returns the absolute offset of the character in the CodeMap
+    pub fn pos(&self) -> BytePos {
+        match *self {
+            NonNarrowChar::ZeroWidth(p) |
+            NonNarrowChar::Wide(p) => p,
+        }
+    }
+
+    /// Returns the width of the character, 0 (zero-width) or 2 (wide)
+    pub fn width(&self) -> usize {
+        match *self {
+            NonNarrowChar::ZeroWidth(_) => 0,
+            NonNarrowChar::Wide(_) => 2,
+        }
+    }
+}
+
+impl Add<BytePos> for NonNarrowChar {
+    type Output = Self;
+
+    fn add(self, rhs: BytePos) -> Self {
+        match self {
+            NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs),
+            NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs),
+        }
+    }
+}
+
+impl Sub<BytePos> for NonNarrowChar {
+    type Output = Self;
+
+    fn sub(self, rhs: BytePos) -> Self {
+        match self {
+            NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs),
+            NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs),
+        }
+    }
+}
+
 /// The state of the lazy external source loading mechanism of a FileMap.
 #[derive(PartialEq, Eq, Clone)]
 pub enum ExternalSource {
@@ -552,11 +611,13 @@ pub struct FileMap {
     pub lines: RefCell<Vec<BytePos>>,
     /// Locations of multi-byte characters in the source code
     pub multibyte_chars: RefCell<Vec<MultiByteChar>>,
+    /// Width of characters that are not narrow in the source code
+    pub non_narrow_chars: RefCell<Vec<NonNarrowChar>>,
 }
 
 impl Encodable for FileMap {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_struct("FileMap", 7, |s| {
+        s.emit_struct("FileMap", 8, |s| {
             s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
             s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?;
             s.emit_struct_field("src_hash", 6, |s| self.src_hash.encode(s))?;
@@ -610,6 +671,9 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
             })?;
             s.emit_struct_field("multibyte_chars", 5, |s| {
                 (*self.multibyte_chars.borrow()).encode(s)
+            })?;
+            s.emit_struct_field("non_narrow_chars", 7, |s| {
+                (*self.non_narrow_chars.borrow()).encode(s)
             })
         })
     }
@@ -618,7 +682,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 impl Decodable for FileMap {
     fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
 
-        d.read_struct("FileMap", 6, |d| {
+        d.read_struct("FileMap", 8, |d| {
             let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
             let name_was_remapped: bool =
                 d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?;
@@ -657,6 +721,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
             })?;
             let multibyte_chars: Vec<MultiByteChar> =
                 d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?;
+            let non_narrow_chars: Vec<NonNarrowChar> =
+                d.read_struct_field("non_narrow_chars", 7, |d| Decodable::decode(d))?;
             Ok(FileMap {
                 name,
                 name_was_remapped,
@@ -671,7 +737,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
                 src_hash,
                 external_src: RefCell::new(ExternalSource::AbsentOk),
                 lines: RefCell::new(lines),
-                multibyte_chars: RefCell::new(multibyte_chars)
+                multibyte_chars: RefCell::new(multibyte_chars),
+                non_narrow_chars: RefCell::new(non_narrow_chars)
             })
         })
     }
@@ -709,6 +776,7 @@ pub fn new(name: FileName,
             end_pos: Pos::from_usize(end_pos),
             lines: RefCell::new(Vec::new()),
             multibyte_chars: RefCell::new(Vec::new()),
+            non_narrow_chars: RefCell::new(Vec::new()),
         }
     }
 
@@ -798,6 +866,23 @@ pub fn record_multibyte_char(&self, pos: BytePos, bytes: usize) {
         self.multibyte_chars.borrow_mut().push(mbc);
     }
 
+    pub fn record_width(&self, pos: BytePos, ch: char) {
+        let width = match ch {
+            '\t' | '\n' =>
+                // Tabs will consume one column.
+                // Make newlines take one column so that displayed spans can point them.
+                1,
+            ch =>
+                // Assume control characters are zero width.
+                // FIXME: How can we decide between `width` and `width_cjk`?
+                unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0),
+        };
+        // Only record non-narrow characters.
+        if width != 1 {
+            self.non_narrow_chars.borrow_mut().push(NonNarrowChar::new(pos, width));
+        }
+    }
+
     pub fn is_real_file(&self) -> bool {
         !(self.name.starts_with("<") &&
           self.name.ends_with(">"))
@@ -944,7 +1029,9 @@ pub struct Loc {
     /// The (1-based) line number
     pub line: usize,
     /// The (0-based) column offset
-    pub col: CharPos
+    pub col: CharPos,
+    /// The (0-based) column offset when displayed
+    pub col_display: usize,
 }
 
 /// A source code location used as the result of lookup_char_pos_adj
index c2b32171a9a98313c52f6c6bbbe793b59ffd0959..b23e40ce7a932787be02a642d5ac70e0d2989b3c 100644 (file)
@@ -59,9 +59,11 @@ pub fn data(self) -> SpanData {
 const CTXT_INDEX: usize = 2;
 
 // Tag = 0, inline format.
-// -----------------------------------
-// | base 31:8  | len 7:1  | tag 0:0 |
-// -----------------------------------
+// -------------------------------------------------------------
+// | base 31:8  | len 7:1  | ctxt (currently 0 bits) | tag 0:0 |
+// -------------------------------------------------------------
+// Since there are zero bits for ctxt, only SpanData with a 0 SyntaxContext
+// can be inline.
 const INLINE_SIZES: [u32; 3] = [24, 7, 0];
 const INLINE_OFFSETS: [u32; 3] = [8, 1, 1];
 
index 872fc031cfb1a8a0fe980b86a5f6e34857884de9..26e6f27e20f40d5f7774d52c12bc8f19450bcc7e 100644 (file)
@@ -309,11 +309,12 @@ fn fresh() -> Self {
     (54, Yield,          "yield")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (55, Catch,          "catch")
-    (56, Default,        "default")
-    (57, Dyn,            "dyn")
-    (58, StaticLifetime, "'static")
-    (59, Union,          "union")
+    (55, Auto,           "auto")
+    (56, Catch,          "catch")
+    (57, Default,        "default")
+    (58, Dyn,            "dyn")
+    (59, StaticLifetime, "'static")
+    (60, Union,          "union")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
index 8733c7436d5bd9658280ab37bfa313d479759a5d..d33b52486296f8b3c7fe27e68ec99b9baeb97ab9 100644 (file)
@@ -14,7 +14,7 @@
 // When an executable or dylib image is linked, all user code and libraries are
 // "sandwiched" between these two object files, so code or data from rsbegin.o
 // become first in the respective sections of the image, whereas code and data
-// from rsend.o become the last ones.  This effect can be used to place symbols
+// from rsend.o become the last ones. This effect can be used to place symbols
 // at the beginning or at the end of a section, as well as to insert any required
 // headers or footers.
 //
 trait Sized {}
 #[lang = "sync"]
 trait Sync {}
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl Sync for .. {}
 #[lang = "copy"]
 trait Copy {}
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl Freeze for .. {}
 
 #[lang = "drop_in_place"]
index a6aed3540ddbb8b9d092f137a23322d7a9b49201..410366d0d7ff50f87039c0df29593afe67bff5da 100644 (file)
@@ -23,6 +23,8 @@ impl<T> Sync for T {}
 trait Copy {}
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(unknown_lints)]
+#[allow(auto_impl)]
 impl Freeze for .. {}
 
 #[lang = "drop_in_place"]
index ec84e2a3f8a3650c8e910752e5fdeba1fb71a4fc..e43290bb1541654bf293cc0fcb8a91f2ef451d12 100644 (file)
@@ -17,6 +17,7 @@ fn main() {
         //~| NOTE ranges require char or numeric types
         //~| NOTE start type: &'static str
         //~| NOTE end type: &'static str
+        //~| ERROR non-reference pattern used to match a reference
         _ => {}
     }
 }
diff --git a/src/test/compile-fail/auto-impl-future-compat.rs b/src/test/compile-fail/auto-impl-future-compat.rs
new file mode 100644 (file)
index 0000000..5c32a75
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+trait Foo {}
+impl Foo for .. {}
+//~^ ERROR The form `impl Foo for .. {}` will be removed, please use `auto trait Foo {}`
+//~^^ WARN this was previously accepted by the compiler
diff --git a/src/test/compile-fail/auto-trait-validation.rs b/src/test/compile-fail/auto-trait-validation.rs
new file mode 100644 (file)
index 0000000..b28b776
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+auto trait Generic<T> {}
+//~^ ERROR auto traits cannot have generics
+//~^^ traits with auto impls (`e.g. impl Trait for ..`) can not have type parameters
+auto trait Bound : Copy {}
+//~^ ERROR auto traits cannot have super traits
+//~^^ traits with auto impls (`e.g. impl Trait for ..`) cannot have predicates
+auto trait MyTrait { fn foo() {} }
+//~^ ERROR auto traits cannot contain items
+//~^^ traits with default impls (`e.g. impl Trait for ..`) must have no methods or associated items
+fn main() {}
index 2e425ac96c55f9de510c0358e93105c48424d3ba..1e1c55de87e17aa1ecb57b6fb16c6a796633e8b0 100644 (file)
@@ -12,6 +12,7 @@
 #![crate_type = "rlib"]
 
 pub trait DefaultedTrait { }
+#[allow(auto_impl)]
 impl DefaultedTrait for .. { }
 
 pub struct Something<T> { t: T }
diff --git a/src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs b/src/test/compile-fail/borrowck/borrowck-drop-from-guard.rs
new file mode 100644 (file)
index 0000000..8bab6e8
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+
+//compile-flags: -Z emit-end-regions -Z borrowck-mir
+
+fn foo(_:String) {}
+
+fn main()
+{
+    let my_str = "hello".to_owned();
+    match Some(42) {
+        Some(_) if { drop(my_str); false } => {}
+        Some(_) => {}
+        None => { foo(my_str); } //~ ERROR (Mir) [E0381]
+    }
+}
index 1d21f40fccaef50b36a99d8b3c1a0eaceee06c52..5f236014457a7222e33b22b63fecbd092098b27c 100644 (file)
 // revisions: ast mir
 //[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
 
+enum Foo {
+    A(i32),
+    B
+}
+
+fn match_enum() {
+    let mut foo = Foo::B;
+    let p = &mut foo;
+    let _ = match foo {
+        Foo::B => 1, //[mir]~ ERROR (Mir) [E0503]
+        _ => 2,
+        Foo::A(x) => x //[ast]~ ERROR [E0503]
+                       //[mir]~^ ERROR (Ast) [E0503]
+                       //[mir]~| ERROR (Mir) [E0503]
+    };
+}
+
+
 fn main() {
     let mut x = 1;
     let _x = &mut x;
diff --git a/src/test/compile-fail/closure-expected-type/README.md b/src/test/compile-fail/closure-expected-type/README.md
new file mode 100644 (file)
index 0000000..9995b00
--- /dev/null
@@ -0,0 +1 @@
+See `src/test/run-pass/closure-expected-type`.
diff --git a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn-multiple.rs
new file mode 100644 (file)
index 0000000..f1b198a
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2016 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.
+
+// must-compile-successfully
+
+#![feature(underscore_lifetimes)]
+#![allow(warnings)]
+
+type Different<'a, 'b> = &'a mut (&'a (), &'b ());
+type Same<'a> = Different<'a, 'a>;
+
+fn with_closure_expecting_different<F>(_: F)
+    where F: for<'a, 'b> FnOnce(Different<'a, 'b>)
+{
+}
+
+fn with_closure_expecting_different_anon<F>(_: F)
+    where F: FnOnce(Different<'_, '_>)
+{
+}
+
+fn supplying_nothing_expecting_anon() {
+    with_closure_expecting_different_anon(|x: Different| {
+    })
+}
+
+fn supplying_nothing_expecting_named() {
+    with_closure_expecting_different(|x: Different| {
+    })
+}
+
+fn supplying_underscore_expecting_anon() {
+    with_closure_expecting_different_anon(|x: Different<'_, '_>| {
+    })
+}
+
+fn supplying_underscore_expecting_named() {
+    with_closure_expecting_different(|x: Different<'_, '_>| {
+    })
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs b/src/test/compile-fail/closure-expected-type/expect-fn-supply-fn.rs
new file mode 100644 (file)
index 0000000..645fd1f
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright 2016 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(underscore_lifetimes)]
+
+fn with_closure_expecting_fn_with_free_region<F>(_: F)
+    where F: for<'a> FnOnce(fn(&'a u32), &i32)
+{
+}
+
+fn with_closure_expecting_fn_with_bound_region<F>(_: F)
+    where F: FnOnce(fn(&u32), &i32)
+{
+}
+
+fn expect_free_supply_free_from_fn<'x>(x: &'x u32) {
+    // Here, the type given for `'x` "obscures" a region from the
+    // expected signature that is bound at closure level.
+    with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {});
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+}
+
+fn expect_free_supply_free_from_closure() {
+    // A variant on the previous test. Here, the region `'a` will be
+    // bound at the closure level, just as is expected, so no error
+    // results.
+    type Foo<'a> = fn(&'a u32);
+    with_closure_expecting_fn_with_free_region(|_x: Foo<'_>, y| {});
+}
+
+fn expect_free_supply_bound() {
+    // Here, we are given a function whose region is bound at closure level,
+    // but we expect one bound in the argument. Error results.
+    with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
+    //~^ ERROR type mismatch in closure arguments
+}
+
+fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) {
+    // Here, we are given a `fn(&u32)` but we expect a `fn(&'x
+    // u32)`. In principle, this could be ok, but we demand equality.
+    with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
+    //~^ ERROR type mismatch in closure arguments
+}
+
+fn expect_bound_supply_free_from_closure() {
+    // A variant on the previous test. Here, the region `'a` will be
+    // bound at the closure level, but we expect something bound at
+    // the argument level.
+    type Foo<'a> = fn(&'a u32);
+    with_closure_expecting_fn_with_bound_region(|_x: Foo<'_>, y| {});
+    //~^ ERROR type mismatch in closure arguments
+}
+
+fn expect_bound_supply_bound<'x>(x: &'x u32) {
+    // No error in this case. The supplied type supplies the bound
+    // regions, and hence we are able to figure out the type of `y`
+    // from the expected type
+    with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {
+    });
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-infer-var-appearing-twice.rs b/src/test/compile-fail/closure-expected-type/expect-infer-var-appearing-twice.rs
new file mode 100644 (file)
index 0000000..bef69a4
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, A)
+{
+}
+
+fn a() {
+    with_closure(|x: u32, y| {
+        // We deduce type of `y` from `x`.
+    });
+}
+
+fn b() {
+    // Here we take the supplied types, resulting in an error later on.
+    with_closure(|x: u32, y: i32| {
+        //~^ ERROR type mismatch in closure arguments
+    });
+}
+
+fn c() {
+    with_closure(|x, y: i32| {
+        // We deduce type of `x` from `y`.
+    });
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs b/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs
new file mode 100644 (file)
index 0000000..f8cb643
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+// must-compile-successfully
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, &u32)
+{
+}
+
+fn foo() {
+    // This version works; we infer `A` to be `u32`, and take the type
+    // of `y` to be `&u32`.
+    with_closure(|x: u32, y| {});
+}
+
+fn bar() {
+    // This version also works.
+    with_closure(|x: &u32, y| {});
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs b/src/test/compile-fail/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs
new file mode 100644 (file)
index 0000000..d3c111c
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+// must-compile-successfully
+
+fn with_closure<F, A>(_: F)
+    where F: FnOnce(A, &u32)
+{
+}
+
+fn foo() {
+    // This version works; we infer `A` to be `u32`, and take the type
+    // of `y` to be `&u32`.
+    with_closure(|x: u32, y| {});
+}
+
+fn bar<'x>(x: &'x u32) {
+    // Same.
+    with_closure(|x: &'x u32, y| {});
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs b/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs
new file mode 100644 (file)
index 0000000..9da12dc
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2016 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.
+
+#![allow(warnings)]
+
+fn closure_expecting_bound<F>(_: F)
+    where F: FnOnce(&u32)
+{
+}
+
+fn closure_expecting_free<'a, F>(_: F)
+    where F: FnOnce(&'a u32)
+{
+}
+
+fn expect_bound_supply_nothing() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x| {
+        f = Some(x); //~ ERROR E0495
+    });
+}
+
+fn expect_bound_supply_bound() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`, even with an explicit type annotation on
+    // closure:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x: &u32| {
+        f = Some(x); //~ ERROR E0495
+    });
+}
+
+fn expect_bound_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here we give a type annotation that `x` should be free. We get
+    // an error because of that.
+    closure_expecting_bound(|x: &'x u32| {
+        //~^ ERROR mismatched types
+        //~| ERROR mismatched types
+
+        // And we still cannot let `x` escape into `f`.
+        f = Some(x);
+        //~^ ERROR cannot infer
+    });
+}
+
+fn expect_free_supply_nothing() {
+    let mut f: Option<&u32> = None;
+    closure_expecting_free(|x| f = Some(x)); // OK
+}
+
+fn expect_free_supply_bound() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &u32| f = Some(x)); // OK
+}
+
+fn expect_free_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &'x u32| f = Some(x)); // OK
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs b/src/test/compile-fail/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs
new file mode 100644 (file)
index 0000000..377eaad
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+fn with_closure<F, A, B>(_: F)
+    where F: FnOnce(A, B)
+{
+}
+
+fn a() {
+    // Type of `y` is unconstrained.
+    with_closure(|x: u32, y| {}); //~ ERROR E0282
+}
+
+fn b() {
+    with_closure(|x: u32, y: u32| {}); // OK
+}
+
+fn c() {
+    with_closure(|x: u32, y: u32| {}); // OK
+}
+
+fn main() { }
index e6bf068156c2b037fcf4d99a987cfc8a2e6c9c74..9c26b8b05f259ce1e8c3aa03b62bce48a1a06ff5 100644 (file)
 
 trait MyTrait { fn foo() {} }
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
-//~^ ERROR redundant default implementations of trait `MyTrait`
+//~^ ERROR redundant auto implementations of trait `MyTrait`
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 
 trait MySafeTrait {}
 
+#[allow(auto_impl)]
 unsafe impl MySafeTrait for .. {}
 //~^ ERROR implementing the trait `MySafeTrait` is not unsafe
 
 unsafe trait MyUnsafeTrait {}
 
+#[allow(auto_impl)]
 impl MyUnsafeTrait for .. {}
 //~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
 
index 2b3bf94eadce5ed020fb8a36033b778a883df466..4ee2c1e2936a85a2f168e053486dad28964a6481 100644 (file)
@@ -10,7 +10,8 @@
 
 pub fn main() {
     match &Some(3) {
-        Some(n) => {}, //~ ERROR mismatched types [E0308]
+        Some(n) => {},
+        //~^ ERROR non-reference pattern used to match a reference
         _ => panic!(),
     }
 }
diff --git a/src/test/compile-fail/feature-gate-non_exhaustive.rs b/src/test/compile-fail/feature-gate-non_exhaustive.rs
new file mode 100644 (file)
index 0000000..d271108
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//#![feature(non_exhaustive)]
+
+#[non_exhaustive] //~ERROR non exhaustive is an experimental feature (see issue #44109)
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+fn main() { }
index 59d7473a741d6297f1d20c2d4633636a4a4cf1d6..4c5502cec18a851ff4c7d25cb6e07c17dab1f9ea 100644 (file)
@@ -17,8 +17,12 @@ trait DummyTrait {
     fn dummy(&self) {}
 }
 
+auto trait AutoDummyTrait {}
+//~^ ERROR auto traits are experimental and possibly buggy
+
+#[allow(auto_impl)]
 impl DummyTrait for .. {}
-//~^ ERROR default trait implementations are experimental and possibly buggy
+//~^ ERROR auto trait implementations are experimental and possibly buggy
 
 impl !DummyTrait for DummyStruct {}
 //~^ ERROR negative trait bounds are not yet fully implemented; use marker types for now
index a4517e60d66e195bb61dd57492d5437da9b32227..6fdf8802e385e5a1079cae3602d508c86a35109e 100644 (file)
@@ -16,7 +16,6 @@ struct Slice<T> {
 fn main() {
     let Slice { data: data, len: len } = "foo";
     //~^ ERROR mismatched types
-    //~| expected type `&str`
     //~| found type `Slice<_>`
-    //~| expected &str, found struct `Slice`
+    //~| ERROR non-reference pattern used to match a reference
 }
index 7b5e61380f2ba263ddb60186e200074957bf814c..092aaa769550538ad296bc2e50b2012754d3bad8 100644 (file)
@@ -10,7 +10,8 @@
 
 fn main() {
     // NB: this (almost) typechecks when default binding modes are enabled.
-    for (ref i,) in [].iter() { //~ ERROR mismatched types [E0308]
+    for (ref i,) in [].iter() {
+        //~^ ERROR non-reference pattern used to match a reference
         i.clone();
     }
 }
index 9d20c17674bc374100192f24f3bc31b9750254c2..bf44cd53f67dc45bda84c3d1bbd7c25692315da3 100644 (file)
@@ -17,6 +17,7 @@ unsafe trait Trait {
     type Output;
 }
 
+#[allow(auto_impl)]
 unsafe impl Trait for .. {}
 
 fn call_method<T: Trait>(x: T) {}
index 2e8cba87be5151cc251e32cdf07a2cd2d76aea57..1fb63391d5608df43db2846b69917f97cbccff97 100644 (file)
@@ -19,6 +19,7 @@ fn method(&self) {
     }
 }
 
+#[allow(auto_impl)]
 unsafe impl Trait for .. {}
 
 fn call_method<T: Trait>(x: T) {
index e8af94f16b1b906d85c7b380a0c52d81b1f34557..f246d6e75df8d85f69accebef365aac6c91d4f73 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let false = "foo"; //~ error: mismatched types
+    let false = 22; //~ error: mismatched types
 }
index f01aab92356dd624ff1e70234f207f5b6a5d84d6..b50fc68bed6be587c24f1d525165931dfd543fb6 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let Self = "foo"; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
+    let Self = 22; //~ ERROR cannot find unit struct/variant or constant `Self` in this scope
 }
index 62649ba8a0fe1e364cdca2e26c02939d9ea5d687..54dac771f01ed8818fbfa72ad10777734a7c815d 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let super = "foo"; //~ ERROR failed to resolve. There are too many initial `super`s
+    let super = 22; //~ ERROR failed to resolve. There are too many initial `super`s
 }
index 90414fa912dba7b396bf6b11beb3a92fdafbb688..b09d09db560f511c50287114900105c63e52795d 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let true = "foo"; //~ error: mismatched types
+    let true = 22; //~ error: mismatched types
 }
index f89b3e39390d31de8b22d29cbea8c112ede25b71..355ff6404cea79cf798ca80aea8d9866add32032 100644 (file)
@@ -15,6 +15,7 @@ fn main() {
     //~^^ ERROR only char and numeric types are allowed in range
     //~| start type: &'static str
     //~| end type: &'static str
+    //~| ERROR non-reference pattern used to match a reference
 
     match "wow" {
         10 ... "what" => ()
@@ -22,6 +23,7 @@ fn main() {
     //~^^ ERROR only char and numeric types are allowed in range
     //~| start type: {integer}
     //~| end type: &'static str
+    //~| ERROR non-reference pattern used to match a reference
 
     match 5 {
         'c' ... 100 => { }
index d72ec8ba40868c59c30f816ac26475bd86d60ddc..fed68da0068898cef0eb6e55816396a6ed54262a 100644 (file)
@@ -19,7 +19,7 @@ fn main() {
 
     // Note that this one works with default binding modes.
     match &[0, 1, 2] {
-        [..] => {} //~ ERROR expected an array or slice, found `&[{integer}; 3]` [E0529]
+        [..] => {} //~ ERROR non-reference pattern used to match a reference
     };
 
     match &[0, 1, 2] {
index 54028ffa63ffc0f87bb2f27cd8bc1b887e713d93..d49ce56ccf6e7da054241efd45d181d93f3082ee 100644 (file)
@@ -17,8 +17,9 @@ fn slice_pat(x: &[u8]) {
     // OLD!
     match x {
         [a, b..] => {},
-        //~^ ERROR expected an array or slice, found `&[u8]`
-        //~| HELP the semantics of slice patterns changed recently; see issue #23121
+        //~^ ERROR non-reference pattern used to match a reference
+        //~| HELP add #![feature(match_default_bindings)] to the crate attributes to enable
+        //~| HELP consider using
         _ => panic!(),
     }
 }
index c84927ea266394e41e25e4a14415857a10dff276..1c1cb396a54f200e8a50eaa296dd3c30efd6c4c9 100644 (file)
@@ -18,6 +18,7 @@
 
 unsafe trait Zen {}
 
+#[allow(auto_impl)]
 unsafe impl Zen for .. {}
 
 unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
index 933ec3837dfc712a2ab2b0dd3abce3aa95438e8e..34082adb8f9a563a82c674d5fbb723f0e849a676 100644 (file)
@@ -21,6 +21,7 @@ pub struct S {
 }
 struct Ts(pub u8);
 
+#[allow(auto_impl)]
 pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
 pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
     pub fn f() {} //~ ERROR unnecessary visibility qualifier
@@ -49,6 +50,7 @@ pub struct S {
     }
     struct Ts(pub u8);
 
+    #[allow(auto_impl)]
     pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
@@ -80,6 +82,7 @@ pub struct S {
     }
     struct Ts(pub u8);
 
+    #[allow(auto_impl)]
     pub impl MarkerTr for .. {} //~ ERROR unnecessary visibility qualifier
     pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
         pub fn f() {} //~ ERROR unnecessary visibility qualifier
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/enums.rs
new file mode 100644 (file)
index 0000000..12d1bf9
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/structs.rs
new file mode 100644 (file)
index 0000000..4d083cc
--- /dev/null
@@ -0,0 +1,37 @@
+// 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.
+
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct(pub u16, pub u16);
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub struct FunctionalRecord {
+    pub first_field: u16,
+    pub second_field: u16,
+    pub third_field: bool
+}
+
+impl Default for FunctionalRecord {
+    fn default() -> FunctionalRecord {
+        FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
+    }
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/variants.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/auxiliary/variants.rs
new file mode 100644 (file)
index 0000000..d04c107
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/enum.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/enum.rs
new file mode 100644 (file)
index 0000000..0c19210
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+// aux-build:enums.rs
+extern crate enums;
+
+use enums::NonExhaustiveEnum;
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        //~^ ERROR non-exhaustive patterns: `_` not covered [E0004]
+        NonExhaustiveEnum::Unit => "first",
+        NonExhaustiveEnum::Tuple(_) => "second",
+        NonExhaustiveEnum::Struct { .. } => "third"
+    };
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/structs.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/structs.rs
new file mode 100644 (file)
index 0000000..74c9c7c
--- /dev/null
@@ -0,0 +1,47 @@
+// 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.
+
+// aux-build:structs.rs
+extern crate structs;
+
+use structs::{NormalStruct, UnitStruct, TupleStruct, FunctionalRecord};
+
+fn main() {
+    let fr = FunctionalRecord {
+    //~^ ERROR cannot create non-exhaustive struct
+        first_field: 1920,
+        second_field: 1080,
+        ..FunctionalRecord::default()
+    };
+
+    let ns = NormalStruct { first_field: 640, second_field: 480 };
+    //~^ ERROR cannot create non-exhaustive struct
+
+    let NormalStruct { first_field, second_field } = ns;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+
+    let ts = TupleStruct(640, 480);
+    //~^ ERROR expected function, found struct `TupleStruct` [E0423]
+
+    let ts_explicit = structs::TupleStruct(640, 480);
+    //~^ ERROR tuple struct `TupleStruct` is private [E0603]
+
+    let TupleStruct { 0: first_field, 1: second_field } = ts;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+
+    let us = UnitStruct;
+    //~^ ERROR expected value, found struct `UnitStruct` [E0423]
+
+    let us_explicit = structs::UnitStruct;
+    //~^ ERROR unit struct `UnitStruct` is private [E0603]
+
+    let UnitStruct { } = us;
+    //~^ ERROR `..` required with struct marked as non-exhaustive
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/variants.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/variants.rs
new file mode 100644 (file)
index 0000000..d1b65ac
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.
+
+// aux-build:variants.rs
+extern crate variants;
+
+use variants::NonExhaustiveVariants;
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+// ignore-test
+
+fn main() {
+    let variant_struct = NonExhaustiveVariants::Struct { field: 640 };
+    //~^ ERROR cannot create non-exhaustive variant
+
+    let variant_tuple = NonExhaustiveVariants::Tuple { 0: 640 };
+    //~^ ERROR cannot create non-exhaustive variant
+
+    match variant_struct {
+        NonExhaustiveVariants::Unit => "",
+        NonExhaustiveVariants::Tuple(fe_tpl) => "",
+        //~^ ERROR `..` required with variant marked as non-exhaustive
+        NonExhaustiveVariants::Struct { field } => ""
+        //~^ ERROR `..` required with variant marked as non-exhaustive
+    };
+}
diff --git a/src/test/compile-fail/rfc-2008-non-exhaustive/variants_create.rs b/src/test/compile-fail/rfc-2008-non-exhaustive/variants_create.rs
new file mode 100644 (file)
index 0000000..f4e4b1b
--- /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.
+
+#![feature(non_exhaustive)]
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    //~^ ERROR #[non_exhaustive] is not yet supported on variants
+    #[non_exhaustive] Tuple(u32),
+    //~^ ERROR #[non_exhaustive] is not yet supported on variants
+    #[non_exhaustive] Struct { field: u32 }
+    //~^ ERROR #[non_exhaustive] is not yet supported on variants
+}
+
+fn main() { }
index c1746d765dd9f5f86239c882e7a1bf6fde8b7f7b..cad43ffeacec9afd002cf17275513a612faa147b 100644 (file)
@@ -13,7 +13,8 @@
 
 trait Foo {}
 
+#[allow(auto_impl)]
 default impl Foo for .. {}
-//~^ ERROR `default impl` is not allowed for default trait implementations
+//~^ ERROR `default impl` is not allowed for auto trait implementations
 
 fn main() {}
index 27a3e31491b823307c28469f58929e2a9cbf9987..c97cb3f6bb70b6c47a6d019ae2e21255a7f8137f 100644 (file)
@@ -15,6 +15,7 @@
 
 trait Foo {}
 
+#[allow(auto_impl)]
 impl Foo for .. {}
 
 impl<T> Foo for T {}
@@ -22,6 +23,7 @@ impl !Foo for u8 {} //~ ERROR E0119
 
 trait Bar {}
 
+#[allow(auto_impl)]
 impl Bar for .. {}
 
 impl<T> !Bar for T {}
index 7d6a1c9c1544c296daafa72c8817564ab609226e..45303cbf70025c2e283dbd422631888da47479ff 100644 (file)
 
 #![feature(optin_builtin_traits)]
 
-trait MyDefaultImpl {}
+trait MyAutoImpl {}
 
-impl<T> MyDefaultImpl for .. {}
-//~^ ERROR default trait implementations are not allowed to have generics
+#[allow(auto_impl)]
+impl<T> MyAutoImpl for .. {}
+//~^ ERROR auto trait implementations are not allowed to have generics
 
 fn main() {}
index fe0e583b20a3896684bd3010b89e545303d954ca..6c7928f13f8941f3052c74189e808490d1ca110b 100644 (file)
@@ -15,6 +15,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic: Copy {} //~ ERROR E0568
+#[allow(auto_impl)]
 impl Magic for .. {}
 
 fn copy<T: Magic>(x: T) -> (T, T) { (x, x) }
index f6678ac7c2d8ced8825ee3ee74fb4673c667bc11..173582ed22fdc2523f74fbef0296694abf7c5c2b 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568
+#[allow(auto_impl)]
 impl Magic for .. {}
 impl<T:Magic> Magic for T {}
 
index 9497dfb39d7d0b9e792da770afed4de733ef4711..6802f72504b7d65adc1457fc8112254c89948f37 100644 (file)
@@ -35,6 +35,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic: Copy {} //~ ERROR E0568
+#[allow(auto_impl)]
 impl Magic for .. {}
 impl<T:Magic> Magic for T {}
 
index 5a852c54869a56145ea3bd7d642674c7a0046289..3c409d1b371eb3ee90eb916adcb660fb1854698b 100644 (file)
@@ -11,4 +11,5 @@
 #![feature(optin_builtin_traits)]
 
 trait Magic<T> {} //~ ERROR E0567
+#[allow(auto_impl)]
 impl Magic<isize> for .. {}
index 8a46d6c76c30fad5dd6a9a20c8c87c4b893ff544..a837d8c9ca74eccf2d989c134f7a5d7ce8a155dd 100644 (file)
@@ -12,6 +12,7 @@
 
 trait MyTrait {}
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 
 struct MyS;
index 3d7746b369cc0a65315df93151bf3a63da5f2956..bed184eb4ccca9e70f57e35bae9ccd28692ada6a 100644 (file)
@@ -12,6 +12,7 @@
 
 trait MyTrait {}
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 impl<T> !MyTrait for *mut T {}
 
index 8c2658b89a506f0cb3f49269544ff27c067c1349..f3a6d8a342e221c7153bc70f7255270f406de7a1 100644 (file)
 
 trait MyTrait {}
 
+#[allow(auto_impl)]
 impl MyTrait for .. {}
 
 unsafe trait MyUnsafeTrait {}
 
+#[allow(auto_impl)]
 unsafe impl MyUnsafeTrait for .. {}
 
 struct ThisImplsTrait;
index 4d71517e06058fde9f39628a694afe1cd5dc99d7..da3e926d6fc1fdd2375c1795c3cc178047d255df 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
+#[allow(auto_impl)]
 impl Copy for .. {} //~ ERROR E0318
      //~^ NOTE `Copy` trait not defined in this crate
 fn main() {}
index 66c7a1c75ffe47a71ea93ddbd6b75247f46d941e..bdd6487b86d74ea65de8026a350697aac56717b3 100644 (file)
@@ -16,6 +16,7 @@
 #![feature(optin_builtin_traits)]
 
 trait Defaulted { }
+#[allow(auto_impl)]
 impl Defaulted for .. { }
 impl<'a,T:Signed> Defaulted for &'a T { }
 impl<'a,T:Signed> Defaulted for &'a mut T { }
index 44950ee8a601f90865698e22d955bc9a07344bf5..108363a464519d56bb41a9de9876e5adace1ce6c 100644 (file)
@@ -249,7 +249,7 @@ trait TraitChangeMethodParametersOrder {
 
 // Add default implementation to method -------------------------------------------
 #[cfg(cfail1)]
-trait TraitAddMethodDefaultImplementation {
+trait TraitAddMethodAutoImplementation {
     fn method();
 }
 
@@ -258,7 +258,7 @@ trait TraitAddMethodDefaultImplementation {
 #[rustc_clean(label="Hir", cfg="cfail3")]
 #[rustc_metadata_clean(cfg="cfail2")]
 #[rustc_metadata_clean(cfg="cfail3")]
-trait TraitAddMethodDefaultImplementation {
+trait TraitAddMethodAutoImplementation {
     #[rustc_dirty(label="Hir", cfg="cfail2")]
     #[rustc_clean(label="Hir", cfg="cfail3")]
     #[rustc_metadata_dirty(cfg="cfail2")]
diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs
new file mode 100644 (file)
index 0000000..78214da
--- /dev/null
@@ -0,0 +1,236 @@
+// Copyright 2012-2016 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: -Z emit-end-regions -Z borrowck-mir
+
+fn guard() -> bool {
+    false
+}
+
+fn guard2(_:i32) -> bool {
+    true
+}
+
+fn full_tested_match() {
+    let _ = match Some(42) {
+        Some(x) if guard() => (1, x),
+        Some(y) => (2, y),
+        None => (3, 3),
+    };
+}
+
+fn full_tested_match2() {
+    let _ = match Some(42) {
+        Some(x) if guard() => (1, x),
+        None => (3, 3),
+        Some(y) => (2, y),
+    };
+}
+
+fn main() {
+    let _ = match Some(1) {
+        Some(_w) if guard() => 1,
+        _x => 2,
+        Some(y) if guard2(y) => 3,
+        _z => 4,
+    };
+}
+
+// END RUST SOURCE
+//
+// START rustc.node17.SimplifyBranches-initial.before.mir
+//  bb0: {
+//      ...
+//      _2 = std::option::Option<i32>::Some(const 42i32,);
+//      _5 = discriminant(_2);
+//      switchInt(_5) -> [0isize: bb5, otherwise: bb3];
+//  }
+//  bb1: { // arm1
+//      StorageLive(_7);
+//      _7 = _3;
+//      _1 = (const 1i32, _7);
+//      StorageDead(_7);
+//      goto -> bb11;
+//  }
+//  bb2: { // binding3(empty) and arm3
+//      _1 = (const 3i32, const 3i32);
+//      goto -> bb11;
+//  }
+//  bb3: {
+//      falseEdges -> [real: bb7, imaginary: bb4]; //pre_binding1
+//  }
+//  bb4: {
+//      falseEdges -> [real: bb10, imaginary: bb5]; //pre_binding2
+//  }
+//  bb5: {
+//      falseEdges -> [real: bb2, imaginary: bb6]; //pre_binding3
+//  }
+//  bb6: {
+//      unreachable;
+//  }
+//  bb7: { // binding1 and guard
+//      StorageLive(_3);
+//      _3 = ((_2 as Some).0: i32);
+//      StorageLive(_6);
+//      _6 = const guard() -> bb8;
+//  }
+//  bb8: { // end of guard
+//      switchInt(_6) -> [0u8: bb9, otherwise: bb1];
+//  }
+//  bb9: { // to pre_binding2
+//      falseEdges -> [real: bb4, imaginary: bb4];
+//  }
+//  bb10: { // bindingNoLandingPads.before.mir2 and arm2
+//      StorageLive(_4);
+//      _4 = ((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = _4;
+//      _1 = (const 2i32, _8);
+//      StorageDead(_8);
+//      goto -> bb11;
+//  }
+//  bb11: {
+//      ...
+//      return;
+//  }
+// END rustc.node17.SimplifyBranches-initial.before.mir
+//
+// START rustc.node42.SimplifyBranches-initial.before.mir
+//  bb0: {
+//      ...
+//      _2 = std::option::Option<i32>::Some(const 42i32,);
+//      _5 = discriminant(_2);
+//      switchInt(_5) -> [0isize: bb4, otherwise: bb3];
+//  }
+//  bb1: { // arm1
+//      StorageLive(_7);
+//      _7 = _3;
+//      _1 = (const 1i32, _7);
+//      StorageDead(_7);
+//      goto -> bb11;
+//  }
+//  bb2: { // binding3(empty) and arm3
+//      _1 = (const 3i32, const 3i32);
+//      goto -> bb11;
+//  }
+//  bb3: {
+//      falseEdges -> [real: bb7, imaginary: bb4]; //pre_binding1
+//  }
+//  bb4: {
+//      falseEdges -> [real: bb2, imaginary: bb5]; //pre_binding2
+//  }
+//  bb5: {
+//      falseEdges -> [real: bb10, imaginary: bb6]; //pre_binding3
+//  }
+//  bb6: {
+//      unreachable;
+//  }
+//  bb7: { // binding1 and guard
+//      StorageLive(_3);
+//      _3 = ((_2 as Some).0: i32);
+//      StorageLive(_6);
+//      _6 = const guard() -> bb8;
+//  }
+//  bb8: { // end of guard
+//      switchInt(_6) -> [0u8: bb9, otherwise: bb1];
+//  }
+//  bb9: { // to pre_binding2
+//      falseEdges -> [real: bb5, imaginary: bb4];
+//  }
+//  bb10: { // binding2 and arm2
+//      StorageLive(_4);
+//      _4 = ((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = _4;
+//      _1 = (const 2i32, _8);
+//      StorageDead(_8);
+//      goto -> bb11;
+//  }
+//  bb11: {
+//      ...
+//      return;
+//  }
+// END rustc.node42.SimplifyBranches-initial.before.mir
+//
+// START rustc.node67.SimplifyBranches-initial.before.mir
+// bb0: {
+//     ...
+//     _2 = std::option::Option<i32>::Some(const 1i32,);
+//     _7 = discriminant(_2);
+//     switchInt(_7) -> [1isize: bb3, otherwise: bb4];
+// }
+// bb1: { // arm1
+//      _1 = const 1i32;
+//      goto -> bb16;
+// }
+// bb2: { // arm3
+//     _1 = const 3i32;
+//      goto -> bb16;
+// }
+//
+//  bb3: {
+//      falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
+//  }
+//  bb4: {
+//      falseEdges -> [real: bb11, imaginary: bb5]; //pre_binding2
+//  }
+//  bb5: {
+//      falseEdges -> [real: bb12, imaginary: bb6]; //pre_binding3
+//  }
+//  bb6: {
+//      falseEdges -> [real: bb15, imaginary: bb7]; //pre_binding4
+//  }
+//  bb7: {
+//      unreachable;
+//  }
+//  bb8: { // binding1: Some(w) if guard()
+//      StorageLive(_3);
+//      _3 = ((_2 as Some).0: i32);
+//      StorageLive(_8);
+//      _8 = const guard() -> bb9;
+//  }
+//  bb9: { //end of guard
+//      switchInt(_8) -> [0u8: bb10, otherwise: bb1];
+//  }
+//  bb10: { // to pre_binding2
+//      falseEdges -> [real: bb4, imaginary: bb4];
+//  }
+//  bb11: { // binding2 & arm2
+//      StorageLive(_4);
+//      _4 = _2;
+//      _1 = const 2i32;
+//      goto -> bb16;
+//  }
+//  bb12: { // binding3: Some(y) if guard2(y)
+//      StorageLive(_5);
+//      _5 = ((_2 as Some).0: i32);
+//      StorageLive(_10);
+//      StorageLive(_11);
+//      _11 = _5;
+//      _10 = const guard2(_11) -> bb13;
+//  }
+//  bb13: { // end of guard2
+//      StorageDead(_11);
+//      switchInt(_10) -> [0u8: bb14, otherwise: bb2];
+//  }
+//  bb14: { // to pre_binding4
+//      falseEdges -> [real: bb6, imaginary: bb6];
+//  }
+//  bb15: { // binding4 & arm4
+//      StorageLive(_6);
+//      _6 = _2;
+//      _1 = const 4i32;
+//      goto -> bb16;
+//  }
+// bb16: {
+//     ...
+//     return;
+// }
+// END rustc.node67.SimplifyBranches-initial.before.mir
index 53454c0cc9ae6adc4ba58bf08636fed0d51a5431..a97ce4e8cbe5549326e128000b5e2e292c725047 100644 (file)
@@ -62,7 +62,7 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:11) => validate_1[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
 //         StorageLive(_3);
 //         Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 }))), [(*_2): i32]);
 //         _3 = &ReErased (*_2);
index 042edca82a650a103a0b0d5603fff516cb321b61..3585ac0b8be76529025ed7ab98a849a94b731cf4 100644 (file)
@@ -78,8 +78,8 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
-//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
+//         Validate(Release, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:10) => validate_4[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
 //         StorageLive(_3);
 //         ...
 //         _0 = const write_42(_3) -> bb1;
index fc849c5aee33b3a0c4ccf28016145588f42223d7..ae09d72942e55808e3ce1b9c60f9868014f6be49 100644 (file)
@@ -49,7 +49,7 @@ fn main() {
 // fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool {
 //     ...
 //     bb0: {
-//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrAnon(1)) mut i32]);
+//         Validate(Acquire, [_1: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId { krate: CrateNum(0), index: DefIndex(1:9) => validate_5[317d]::main[0]::{{closure}}[0] }, BrAnon(0)) mut i32]);
 //         StorageLive(_3);
 //         StorageLive(_4);
 //         Validate(Suspend(ReScope(Node(ItemLocalId(9)))), [(*_2): i32]);
diff --git a/src/test/pretty/auto-trait.rs b/src/test/pretty/auto-trait.rs
new file mode 100644 (file)
index 0000000..842af49
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2014 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(optin_builtin_traits)]
+
+// pp-exact
+
+auto trait MyTrait { }
+
+unsafe auto trait UnsafeMyTrait { }
+
+pub fn main() { }
diff --git a/src/test/pretty/default-trait-impl.rs b/src/test/pretty/default-trait-impl.rs
deleted file mode 100644 (file)
index a5246b9..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 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(optin_builtin_traits)]
-
-// pp-exact
-
-trait MyTrait { }
-
-impl MyTrait for .. { }
-
-pub fn main() { }
diff --git a/src/test/run-make/cdylib-fewer-symbols/Makefile b/src/test/run-make/cdylib-fewer-symbols/Makefile
new file mode 100644 (file)
index 0000000..954ee79
--- /dev/null
@@ -0,0 +1,17 @@
+# Test that allocator-related symbols don't show up as exported from a cdylib as
+# they're internal to Rust and not part of the public ABI.
+
+-include ../tools.mk
+
+ifdef IS_MSVC
+all:
+       true
+else
+all:
+       $(RUSTC) foo.rs
+       nm -g "$(call DYLIB,foo)"
+       nm -g "$(call DYLIB,foo)" | grep -vq __rdl_
+       nm -g "$(call DYLIB,foo)" | grep -vq __rde_
+       nm -g "$(call DYLIB,foo)" | grep -vq __rg_
+       nm -g "$(call DYLIB,foo)" | grep -vq __rust_
+endif
diff --git a/src/test/run-make/cdylib-fewer-symbols/foo.rs b/src/test/run-make/cdylib-fewer-symbols/foo.rs
new file mode 100644 (file)
index 0000000..4ec8d4e
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+#![crate_type = "cdylib"]
+
+#[no_mangle]
+pub extern fn foo() -> u32 {
+    3
+}
index 13ca397eaf23e6bdd7da538494416c5141e9a734..6de4f97df0c16bf6df2b83c8fec542a2e8198910 100644 (file)
@@ -2,5 +2,5 @@
 
 all:
        $(RUSTC) -C extra-filename=bar foo.rs -C save-temps
-       rm $(TMPDIR)/foobar.foo0.rust-cgu.o
+       rm $(TMPDIR)/foobar.foo0.rcgu.o
        rm $(TMPDIR)/$(call BIN,foobar)
index 5cb363ac34435719f0c493518753cbbad34195e3..834a7554a555d4a48a37327f686bc6f3f76e2672 100644 (file)
@@ -441,6 +441,11 @@ fn test_format_args() {
     print!("x is {}, y is {1}, name is {n}", x, y, n = name);
 }
 
+
+union TestUnion {
+    f1: u32
+}
+
 struct FrameBuffer;
 
 struct SilenceGenerator;
index 8ab8f4715755ddbef149777ab726c29d023afe0f..185476fb704f7fe4176766abe11d54c7c3e2025d 100644 (file)
@@ -81,4 +81,5 @@ pub mod marker {
 
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(auto_impl)]
 impl Freeze for .. {}
index af24c3b460b2e844d43123eb9aaf9f6725967996..a0feb72702834e74eed0166eaeab601f322cbfd3 100644 (file)
@@ -19,6 +19,7 @@ trait Sized { }
 
 #[lang = "freeze"]
 trait Freeze {}
+#[allow(auto_impl)]
 impl Freeze for .. {}
 
 #[lang="start"]
diff --git a/src/test/run-pass/auto-is-contextual.rs b/src/test/run-pass/auto-is-contextual.rs
new file mode 100644 (file)
index 0000000..ad433cc
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+macro_rules! auto {
+    () => (struct S;)
+}
+
+auto!();
+
+fn auto() {}
+
+fn main() {
+    auto();
+    let auto = 10;
+    auto;
+    auto as u8;
+}
diff --git a/src/test/run-pass/auto-traits.rs b/src/test/run-pass/auto-traits.rs
new file mode 100644 (file)
index 0000000..752f5a1
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+auto trait Auto {}
+// Redundant but accepted until we remove it.
+#[allow(auto_impl)]
+impl Auto for .. {}
+
+unsafe auto trait AutoUnsafe {}
+
+impl !Auto for bool {}
+impl !AutoUnsafe for bool {}
+
+struct AutoBool(bool);
+
+impl Auto for AutoBool {}
+unsafe impl AutoUnsafe for AutoBool {}
+
+fn take_auto<T: Auto>(_: T) {}
+fn take_auto_unsafe<T: AutoUnsafe>(_: T) {}
+
+fn main() {
+    take_auto(0);
+    take_auto(AutoBool(true));
+    take_auto_unsafe(0);
+    take_auto_unsafe(AutoBool(true));
+}
diff --git a/src/test/run-pass/closure-expected-type/README.md b/src/test/run-pass/closure-expected-type/README.md
new file mode 100644 (file)
index 0000000..fd493e1
--- /dev/null
@@ -0,0 +1,8 @@
+Some tests targeted at how we deduce the types of closure arguments.
+This process is a result of some heuristics aimed at combining the
+*expected type* we have with the *actual types* that we get from
+inputs. This investigation was kicked off by #38714, which revealed
+some pretty deep flaws in the ad-hoc way that we were doing things
+before.
+
+See also `src/test/compile-fail/closure-expected-type`.
diff --git a/src/test/run-pass/closure-expected-type/expect-infer-supply-two-infers.rs b/src/test/run-pass/closure-expected-type/expect-infer-supply-two-infers.rs
new file mode 100644 (file)
index 0000000..8a90a49
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+fn with_closure<A, F>(_: F)
+    where F: FnOnce(Vec<A>, A)
+{
+}
+
+fn expect_free_supply_free<'x>(x: &'x u32) {
+    with_closure(|mut x: Vec<_>, y| {
+        // Shows that the call to `x.push()` is influencing type of `y`...
+        x.push(22_u32);
+
+        // ...since we now know the type of `y` and can resolve the method call.
+        y.wrapping_add(1);
+    });
+}
+
+fn main() { }
diff --git a/src/test/run-pass/closure-expected-type/issue-38714.rs b/src/test/run-pass/closure-expected-type/issue-38714.rs
new file mode 100644 (file)
index 0000000..a1d5121
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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 UsizeRef<'a> {
+    a: &'a usize
+}
+
+type RefTo = Box<for<'r> Fn(&'r Vec<usize>) -> UsizeRef<'r>>;
+
+fn ref_to<'a>(vec: &'a Vec<usize>) -> UsizeRef<'a> {
+    UsizeRef{ a: &vec[0]}
+}
+
+fn main() {
+    // Regression test: this was causing ICEs; it should compile.
+    let a: RefTo = Box::new(|vec: &Vec<usize>| {
+        UsizeRef{ a: &vec[0] }
+    });
+}
diff --git a/src/test/run-pass/closure-expected-type/supply-just-return-type.rs b/src/test/run-pass/closure-expected-type/supply-just-return-type.rs
new file mode 100644 (file)
index 0000000..0b930b3
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2016 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.
+
+fn with_closure<F, R>(f: F) -> Result<char, R>
+    where F: FnOnce(&char) -> Result<char, R>,
+{
+    f(&'a')
+}
+
+fn main() {
+    // Test that supplying the `-> Result<char, ()>` manually here
+    // (which is needed to constrain `R`) still allows us to figure
+    // out that the type of `x` is `&'a char` where `'a` is bound in
+    // the closure (if we didn't, we'd get a type-error because
+    // `with_closure` requires a bound region).
+    //
+    // This pattern was found in the wild.
+    let z = with_closure(|x| -> Result<char, ()> { Ok(*x) });
+    assert_eq!(z.unwrap(), 'a');
+
+    // It also works with `_`:
+    let z = with_closure(|x: _| -> Result<char, ()> { Ok(*x) });
+    assert_eq!(z.unwrap(), 'a');
+
+    // It also works with `&_`:
+    let z = with_closure(|x: &_| -> Result<char, ()> { Ok(*x) });
+    assert_eq!(z.unwrap(), 'a');
+}
diff --git a/src/test/run-pass/closure-expected-type/supply-nothing.rs b/src/test/run-pass/closure-expected-type/supply-nothing.rs
new file mode 100644 (file)
index 0000000..15d8b39
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 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.
+
+fn with_closure<F>(f: F) -> u32
+    where F: FnOnce(&u32, &u32) -> u32
+{
+    f(&22, &44)
+}
+
+fn main() {
+    let z = with_closure(|x, y| x + y).wrapping_add(1);
+    assert_eq!(z, 22 + 44 + 1);
+}
index b586abc29e243a2f3a8fa5382aba03b13c1af75c..5fa0a002a10db9071c31f3f4418bda4ffccbc959 100644 (file)
@@ -11,6 +11,7 @@
 #![feature(optin_builtin_traits)]
 
 trait NotSame {}
+#[allow(auto_impl)]
 impl NotSame for .. {}
 impl<A> !NotSame for (A, A) {}
 
diff --git a/src/test/run-pass/mir-inlining/ice-issue-45493.rs b/src/test/run-pass/mir-inlining/ice-issue-45493.rs
new file mode 100644 (file)
index 0000000..bd178f0
--- /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:-Zmir-opt-level=2
+
+trait Array {
+    type Item;
+}
+
+fn foo<A: Array>() {
+    let _: *mut A::Item = std::ptr::null_mut();
+}
+
+struct Foo;
+impl Array for Foo { type Item = i32; }
+
+fn main() {
+    foo::<Foo>();
+}
diff --git a/src/test/run-pass/next-power-of-two-overflow-debug.rs b/src/test/run-pass/next-power-of-two-overflow-debug.rs
new file mode 100644 (file)
index 0000000..a3e7ffd
--- /dev/null
@@ -0,0 +1,36 @@
+// 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: -C debug_assertions=yes
+
+#![feature(i128_type)]
+
+use std::panic;
+
+fn main() {
+    macro_rules! overflow_test {
+        ($t:ident) => (
+            let r = panic::catch_unwind(|| {
+                ($t::max_value()).next_power_of_two()
+            });
+            assert!(r.is_err());
+
+            let r = panic::catch_unwind(|| {
+                (($t::max_value() >> 1) + 2).next_power_of_two()
+            });
+            assert!(r.is_err());
+        )
+    }
+    overflow_test!(u8);
+    overflow_test!(u16);
+    overflow_test!(u32);
+    overflow_test!(u64);
+    overflow_test!(u128);
+}
diff --git a/src/test/run-pass/next-power-of-two-overflow-ndebug.rs b/src/test/run-pass/next-power-of-two-overflow-ndebug.rs
new file mode 100644 (file)
index 0000000..f8bcb96
--- /dev/null
@@ -0,0 +1,24 @@
+// 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: -C debug_assertions=no
+
+#![feature(i128_type)]
+
+fn main() {
+    for i in 129..256 {
+        assert_eq!((i as u8).next_power_of_two(), 0);
+    }
+
+    assert_eq!(((1u16 << 15) + 1).next_power_of_two(), 0);
+    assert_eq!(((1u32 << 31) + 1).next_power_of_two(), 0);
+    assert_eq!(((1u64 << 63) + 1).next_power_of_two(), 0);
+    assert_eq!(((1u128 << 127) + 1).next_power_of_two(), 0);
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/enums.rs
new file mode 100644 (file)
index 0000000..12d1bf9
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/structs.rs
new file mode 100644 (file)
index 0000000..a2c6f8c
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct (pub u16, pub u16);
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs b/src/test/run-pass/rfc-2008-non-exhaustive/auxiliary/variants.rs
new file mode 100644 (file)
index 0000000..d04c107
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+#![crate_type = "rlib"]
+#![feature(non_exhaustive)]
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/enums.rs b/src/test/run-pass/rfc-2008-non-exhaustive/enums.rs
new file mode 100644 (file)
index 0000000..9d41eca
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+// aux-build:enums.rs
+extern crate enums;
+
+// ignore-pretty issue #37199
+
+use enums::NonExhaustiveEnum;
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        NonExhaustiveEnum::Unit => 1,
+        NonExhaustiveEnum::Tuple(_) => 2,
+        // This particular arm tests that a enum marked as non-exhaustive
+        // will not error if its variants are matched exhaustively.
+        NonExhaustiveEnum::Struct { field } => field,
+        _ => 0 // no error with wildcard
+    };
+
+    match enum_unit {
+        _ => "no error with only wildcard"
+    };
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/enums_same_crate.rs b/src/test/run-pass/rfc-2008-non-exhaustive/enums_same_crate.rs
new file mode 100644 (file)
index 0000000..8f1ba36
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+fn main() {
+    let enum_unit = NonExhaustiveEnum::Unit;
+
+    match enum_unit {
+        NonExhaustiveEnum::Unit => "first",
+        NonExhaustiveEnum::Tuple(_) => "second",
+        NonExhaustiveEnum::Struct { .. } => "third",
+    };
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/structs.rs b/src/test/run-pass/rfc-2008-non-exhaustive/structs.rs
new file mode 100644 (file)
index 0000000..bb65e10
--- /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.
+
+// aux-build:structs.rs
+extern crate structs;
+
+use structs::{NormalStruct, UnitStruct, TupleStruct};
+
+// We only test matching here as we cannot create non-exhaustive
+// structs from another crate. ie. they'll never pass in run-pass tests.
+
+fn match_structs(ns: NormalStruct, ts: TupleStruct, us: UnitStruct) {
+    let NormalStruct { first_field, second_field, .. } = ns;
+
+    let TupleStruct { 0: first, 1: second, .. } = ts;
+
+    let UnitStruct { .. } = us;
+}
+
+fn main() { }
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/structs_same_crate.rs b/src/test/run-pass/rfc-2008-non-exhaustive/structs_same_crate.rs
new file mode 100644 (file)
index 0000000..175782f
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+pub struct TupleStruct (pub u16, pub u16);
+
+fn main() {
+    let ns = NormalStruct { first_field: 640, second_field: 480 };
+
+    let NormalStruct { first_field, second_field } = ns;
+
+    let ts = TupleStruct { 0: 340, 1: 480 };
+    let ts_constructor = TupleStruct(340, 480);
+
+    let TupleStruct { 0: first, 1: second } = ts;
+    let TupleStruct(first, second) = ts_constructor;
+
+    let us = UnitStruct {};
+    let us_constructor = UnitStruct;
+
+    let UnitStruct { } = us;
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/variants.rs b/src/test/run-pass/rfc-2008-non-exhaustive/variants.rs
new file mode 100644 (file)
index 0000000..2658c59
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+// aux-build:variants.rs
+extern crate variants;
+
+use variants::NonExhaustiveVariants;
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+// ignore-test
+
+fn main() {
+    let variant_tuple = NonExhaustiveVariants::Tuple { 0: 340 };
+    let variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+
+    match variant_struct {
+        NonExhaustiveVariants::Unit => "",
+        NonExhaustiveVariants::Struct { field, .. } => "",
+        NonExhaustiveVariants::Tuple(fe_tpl, ..) => ""
+    };
+}
diff --git a/src/test/run-pass/rfc-2008-non-exhaustive/variants_same_crate.rs b/src/test/run-pass/rfc-2008-non-exhaustive/variants_same_crate.rs
new file mode 100644 (file)
index 0000000..a1c376c
--- /dev/null
@@ -0,0 +1,34 @@
+// 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.
+
+#![feature(non_exhaustive)]
+
+/*
+ * The initial implementation of #[non_exhaustive] (RFC 2008) does not include support for
+ * variants. See issue #44109 and PR 45394.
+ */
+// ignore-test
+
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
+
+fn main() {
+    let variant_tuple = NonExhaustiveVariants::Tuple(340);
+    let variant_struct = NonExhaustiveVariants::Struct { field: 340 };
+
+    match variant_tuple {
+        NonExhaustiveVariants::Unit => "",
+        NonExhaustiveVariants::Tuple(fe_tpl) => "",
+        NonExhaustiveVariants::Struct { field } => ""
+    };
+}
index 52bd386ba595bb9ae064a21e61805613e8675bf6..4fd55bd482cd998029fb89eb2dcd477d999414c3 100644 (file)
@@ -16,6 +16,7 @@ pub mod bar {
 
     pub trait Bar {}
 
+    #[allow(auto_impl)]
     impl Bar for .. {}
 
     pub trait Foo {
index 6e8f80c8f5f9f1a2af5211223891e191dce930c4..d886778278dfd3dd86a35bc16c5096961eaca876 100644 (file)
@@ -12,4 +12,5 @@
 
 pub trait AnOibit {}
 
+#[allow(auto_impl)]
 impl AnOibit for .. {}
index 48ef4b6be66dea34e4d204f8ce7eba6bce392b74..f74f66ce7290551849082781c0f7184313d6e956 100644 (file)
@@ -12,6 +12,7 @@
 
 pub trait AnOibit {}
 
+#[allow(auto_impl)]
 impl AnOibit for .. {}
 
 pub struct Foo<T> { field: T }
diff --git a/src/test/rustdoc/method-list.rs b/src/test/rustdoc/method-list.rs
new file mode 100644 (file)
index 0000000..b711288
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+// ignore-tidy-linelength
+
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="sidebar-links"]/a' 'super_long_name'
+// @has - '//*[@class="sidebar-links"]/a' 'Disp'
+pub struct Foo(usize);
+
+impl Foo {
+    pub fn super_long_name() {}
+}
+
+pub trait Disp {
+    fn disp_trait_method();
+}
+
+impl Disp for Foo {
+    fn disp_trait_method() {}
+}
index 0828fd28b5878642ec5c640d90fcb0aad1ed8ba3..02a9d7ee0ef4f6dd12708fb21c95fbfdb2bd2c7e 100644 (file)
@@ -2,7 +2,7 @@ error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thisc
   --> $DIR/unicode.rs:11:8
    |
 11 | extern "路濫狼á́́" fn foo() {}
-   |        ^^^^^^^^
+   |        ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/unicode_2.rs b/src/test/ui/codemap_tests/unicode_2.rs
new file mode 100644 (file)
index 0000000..cc3eae9
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2016 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(non_ascii_idents)]
+
+fn main() {
+    let _ = ("a̐éö̲", 0u7);
+    let _ = ("아あ", 1i42);
+    let _ = a̐é;
+}
diff --git a/src/test/ui/codemap_tests/unicode_2.stderr b/src/test/ui/codemap_tests/unicode_2.stderr
new file mode 100644 (file)
index 0000000..6cfa667
--- /dev/null
@@ -0,0 +1,24 @@
+error: invalid width `7` for integer literal
+  --> $DIR/unicode_2.rs:14:25
+   |
+14 |     let _ = ("a̐éö̲", 0u7);
+   |                     ^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error: invalid width `42` for integer literal
+  --> $DIR/unicode_2.rs:15:20
+   |
+15 |     let _ = ("아あ", 1i42);
+   |                      ^^^^
+   |
+   = help: valid widths are 8, 16, 32, 64 and 128
+
+error[E0425]: cannot find value `a̐é` in this scope
+  --> $DIR/unicode_2.rs:16:13
+   |
+16 |     let _ = a̐é;
+   |             ^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/codemap_tests/unicode_3.rs b/src/test/ui/codemap_tests/unicode_3.rs
new file mode 100644 (file)
index 0000000..5294eed
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2016 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.
+
+fn main() {
+    let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
+    println!("{}", s);
+}
diff --git a/src/test/ui/codemap_tests/unicode_3.stderr b/src/test/ui/codemap_tests/unicode_3.stderr
new file mode 100644 (file)
index 0000000..a7514a6
--- /dev/null
@@ -0,0 +1,10 @@
+warning: denote infinite loops with `loop { ... }`
+  --> $DIR/unicode_3.rs:12:45
+   |
+12 |     let s = "ZͨA͑ͦ͒͋ͤ͑̚L̄͑͋Ĝͨͥ̿͒̽̈́Oͥ͛ͭ!̏"; while true { break; }
+   |                       ----------^^^^^^^^^^^
+   |                       |
+   |                       help: use `loop`
+   |
+   = note: #[warn(while_true)] on by default
+
index 5ad9c19fa8cc2b2e366ad8f7fa1b747f4714a366..3ed3297e05ed95a5976c1795ce3deccb9fe9e987 100644 (file)
@@ -10,8 +10,8 @@ error[E0308]: mismatched types
            - .escape_debug()
            - .escape_default()
            - .escape_unicode()
-           - .to_lowercase()
-           - .to_uppercase()
+           - .to_ascii_lowercase()
+           - .to_ascii_uppercase()
 
 error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:23:10
diff --git a/src/test/ui/issue-35241.rs b/src/test/ui/issue-35241.rs
new file mode 100644 (file)
index 0000000..7ec3974
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+struct Foo(u32);
+
+fn test() -> Foo { Foo }
+
+fn main() {}
diff --git a/src/test/ui/issue-35241.stderr b/src/test/ui/issue-35241.stderr
new file mode 100644 (file)
index 0000000..bb1bba1
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-35241.rs:13:20
+   |
+13 | fn test() -> Foo { Foo }
+   |              ---   ^^^
+   |              |     |
+   |              |     expected struct `Foo`, found fn item
+   |              |     did you mean `Foo(/* fields */)`?
+   |              expected `Foo` because of return type
+   |
+   = note: expected type `Foo`
+              found type `fn(u32) -> Foo {Foo::{{constructor}}}`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-40782.rs b/src/test/ui/issue-40782.rs
new file mode 100644 (file)
index 0000000..56ee225
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+fn main() {
+    for i 0..2 {
+    }
+}
+
diff --git a/src/test/ui/issue-40782.stderr b/src/test/ui/issue-40782.stderr
new file mode 100644 (file)
index 0000000..0d49eeb
--- /dev/null
@@ -0,0 +1,8 @@
+error: missing `in` in `for` loop
+  --> $DIR/issue-40782.rs:12:10
+   |
+12 |     for i 0..2 {
+   |          ^ help: try adding `in` here
+
+error: aborting due to previous error
+
index 389f3b2479aa45c3f6669934be61380275c0013d..2ed4578d5389ec7e143eade954ce687caa3758f4 100644 (file)
@@ -2,7 +2,7 @@ error: unterminated double quote string
   --> $DIR/issue-44078.rs:12:8
    |
 12 |       "😊"";
-   |  ________^
+   |  _________^
 13 | | }
    | |__^
 
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.rs b/src/test/ui/lint/unreachable_pub-pub_crate.rs
new file mode 100644 (file)
index 0000000..b794f6c
--- /dev/null
@@ -0,0 +1,74 @@
+// 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.
+
+// This is just like unreachable_pub.rs, but without the
+// `crate_visibility_modifier` feature (so that we can test the suggestions to
+// use `pub(crate)` that are given when that feature is off, as opposed to the
+// suggestions to use `crate` given when it is on). When that feature becomes
+// stable, this test can be deleted.
+
+#![feature(macro_vis_matcher)]
+
+#![allow(unused)]
+#![warn(unreachable_pub)]
+
+mod private_mod {
+    // non-leaked `pub` items in private module should be linted
+    pub use std::fmt;
+
+    pub struct Hydrogen {
+        // `pub` struct fields, too
+        pub neutrons: usize,
+        // (... but not more-restricted fields)
+        pub(crate) electrons: usize
+    }
+    impl Hydrogen {
+        // impls, too
+        pub fn count_neutrons(&self) -> usize { self.neutrons }
+        pub(crate) fn count_electrons(&self) -> usize { self.electrons }
+    }
+
+    pub enum Helium {}
+    pub union Lithium { c1: usize, c2: u8 }
+    pub fn beryllium() {}
+    pub trait Boron {}
+    pub const CARBON: usize = 1;
+    pub static NITROGEN: usize = 2;
+    pub type Oxygen = bool;
+
+    macro_rules! define_empty_struct_with_visibility {
+        ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+    }
+    define_empty_struct_with_visibility!(pub, Fluorine);
+
+    extern {
+        pub fn catalyze() -> bool;
+    }
+
+    // items leaked through signatures (see `get_neon` below) are OK
+    pub struct Neon {}
+
+    // crate-visible items are OK
+    pub(crate) struct Sodium {}
+}
+
+pub mod public_mod {
+    // module is public: these are OK, too
+    pub struct Magnesium {}
+    pub(crate) struct Aluminum {}
+}
+
+pub fn get_neon() -> private_mod::Neon {
+    private_mod::Neon {}
+}
+
+fn main() {
+    let _ = get_neon();
+}
diff --git a/src/test/ui/lint/unreachable_pub-pub_crate.stderr b/src/test/ui/lint/unreachable_pub-pub_crate.stderr
new file mode 100644 (file)
index 0000000..84cbf87
--- /dev/null
@@ -0,0 +1,134 @@
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:24:5
+   |
+24 |     pub use std::fmt;
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+note: lint level defined here
+  --> $DIR/unreachable_pub-pub_crate.rs:20:9
+   |
+20 | #![warn(unreachable_pub)]
+   |         ^^^^^^^^^^^^^^^
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:26:5
+   |
+26 |     pub struct Hydrogen {
+   |     ---^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` field
+  --> $DIR/unreachable_pub-pub_crate.rs:28:9
+   |
+28 |         pub neutrons: usize,
+   |         ---^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:34:9
+   |
+34 |         pub fn count_neutrons(&self) -> usize { self.neutrons }
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:38:5
+   |
+38 |     pub enum Helium {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:39:5
+   |
+39 |     pub union Lithium { c1: usize, c2: u8 }
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:40:5
+   |
+40 |     pub fn beryllium() {}
+   |     ---^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:41:5
+   |
+41 |     pub trait Boron {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:42:5
+   |
+42 |     pub const CARBON: usize = 1;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:43:5
+   |
+43 |     pub static NITROGEN: usize = 2;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:44:5
+   |
+44 |     pub type Oxygen = bool;
+   |     ---^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:47:47
+   |
+47 |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+   |                                               -----------^^^^^^^^^^^^^
+   |                                               |
+   |                                               help: consider restricting its visibility: `pub(crate)`
+48 |     }
+49 |     define_empty_struct_with_visibility!(pub, Fluorine);
+   |     ---------------------------------------------------- in this macro invocation
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:52:9
+   |
+52 |         pub fn catalyze() -> bool;
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
diff --git a/src/test/ui/lint/unreachable_pub.rs b/src/test/ui/lint/unreachable_pub.rs
new file mode 100644 (file)
index 0000000..5812061
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(crate_visibility_modifier)]
+#![feature(macro_vis_matcher)]
+
+#![allow(unused)]
+#![warn(unreachable_pub)]
+
+mod private_mod {
+    // non-leaked `pub` items in private module should be linted
+    pub use std::fmt;
+
+    pub struct Hydrogen {
+        // `pub` struct fields, too
+        pub neutrons: usize,
+        // (... but not more-restricted fields)
+        crate electrons: usize
+    }
+    impl Hydrogen {
+        // impls, too
+        pub fn count_neutrons(&self) -> usize { self.neutrons }
+        crate fn count_electrons(&self) -> usize { self.electrons }
+    }
+
+    pub enum Helium {}
+    pub union Lithium { c1: usize, c2: u8 }
+    pub fn beryllium() {}
+    pub trait Boron {}
+    pub const CARBON: usize = 1;
+    pub static NITROGEN: usize = 2;
+    pub type Oxygen = bool;
+
+    macro_rules! define_empty_struct_with_visibility {
+        ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+    }
+    define_empty_struct_with_visibility!(pub, Fluorine);
+
+    extern {
+        pub fn catalyze() -> bool;
+    }
+
+    // items leaked through signatures (see `get_neon` below) are OK
+    pub struct Neon {}
+
+    // crate-visible items are OK
+    crate struct Sodium {}
+}
+
+pub mod public_mod {
+    // module is public: these are OK, too
+    pub struct Magnesium {}
+    crate struct Aluminum {}
+}
+
+pub fn get_neon() -> private_mod::Neon {
+    private_mod::Neon {}
+}
+
+fn main() {
+    let _ = get_neon();
+}
diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr
new file mode 100644 (file)
index 0000000..bdd016f
--- /dev/null
@@ -0,0 +1,134 @@
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:19:5
+   |
+19 |     pub use std::fmt;
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+note: lint level defined here
+  --> $DIR/unreachable_pub.rs:15:9
+   |
+15 | #![warn(unreachable_pub)]
+   |         ^^^^^^^^^^^^^^^
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:21:5
+   |
+21 |     pub struct Hydrogen {
+   |     ---^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` field
+  --> $DIR/unreachable_pub.rs:23:9
+   |
+23 |         pub neutrons: usize,
+   |         ---^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:29:9
+   |
+29 |         pub fn count_neutrons(&self) -> usize { self.neutrons }
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:33:5
+   |
+33 |     pub enum Helium {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:34:5
+   |
+34 |     pub union Lithium { c1: usize, c2: u8 }
+   |     ---^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:35:5
+   |
+35 |     pub fn beryllium() {}
+   |     ---^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:36:5
+   |
+36 |     pub trait Boron {}
+   |     ---^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:37:5
+   |
+37 |     pub const CARBON: usize = 1;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:38:5
+   |
+38 |     pub static NITROGEN: usize = 2;
+   |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:39:5
+   |
+39 |     pub type Oxygen = bool;
+   |     ---^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:42:47
+   |
+42 |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
+   |                                               -----------^^^^^^^^^^^^^
+   |                                               |
+   |                                               help: consider restricting its visibility: `crate`
+43 |     }
+44 |     define_empty_struct_with_visibility!(pub, Fluorine);
+   |     ---------------------------------------------------- in this macro invocation
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:47:9
+   |
+47 |         pub fn catalyze() -> bool;
+   |         ---^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
index 15251795d5e082a5078b1dfee673aa62e85d1ee2..ad501e668095ae86cade1f29b49da5929e08a7ca 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: --error-format json
+// compile-flags: --error-format pretty-json -Zunstable-options
 
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
index ae5b53da1750387f461b47cb47c33438d53eff58..e166f7011b58ac42a2b63205b136046e30dee436 100644 (file)
@@ -1 +1,91 @@
-{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"lint level defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":847,"byte_end":860,"line_start":19,"line_end":19,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![warn(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":null}],"rendered":null}
+{
+  "message": "unnecessary parentheses around assigned value",
+  "code": {
+    "code": "unused_parens",
+    "explanation": null
+  },
+  "level": "warning",
+  "spans": [
+    {
+      "file_name": "$DIR/unused_parens_json_suggestion.rs",
+      "byte_start": 1027,
+      "byte_end": 1040,
+      "line_start": 24,
+      "line_end": 24,
+      "column_start": 14,
+      "column_end": 27,
+      "is_primary": true,
+      "text": [
+        {
+          "text": "    let _a = (1 / (2 + 3));",
+          "highlight_start": 14,
+          "highlight_end": 27
+        }
+      ],
+      "label": null,
+      "suggested_replacement": null,
+      "expansion": null
+    }
+  ],
+  "children": [
+    {
+      "message": "lint level defined here",
+      "code": null,
+      "level": "note",
+      "spans": [
+        {
+          "file_name": "$DIR/unused_parens_json_suggestion.rs",
+          "byte_start": 873,
+          "byte_end": 886,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 9,
+          "column_end": 22,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "#![warn(unused_parens)]",
+              "highlight_start": 9,
+              "highlight_end": 22
+            }
+          ],
+          "label": null,
+          "suggested_replacement": null,
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    },
+    {
+      "message": "remove these parentheses",
+      "code": null,
+      "level": "help",
+      "spans": [
+        {
+          "file_name": "$DIR/unused_parens_json_suggestion.rs",
+          "byte_start": 1027,
+          "byte_end": 1040,
+          "line_start": 24,
+          "line_end": 24,
+          "column_start": 14,
+          "column_end": 27,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "    let _a = (1 / (2 + 3));",
+              "highlight_start": 14,
+              "highlight_end": 27
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "1 / (2 + 3)",
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    }
+  ],
+  "rendered": null
+}
index 20c24d6405042e15cb128b08d3ef2efd2c080af0..27232c4fec4ad89590c882df463e1bef7faaae28 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: --error-format json
+// compile-flags: --error-format pretty-json -Zunstable-options
 
 // The output for humans should just highlight the whole span without showing
 // the suggested replacement, but we also want to test that suggested
index 2ebe212b93ddb7f0a9db59e5c5103587af86d9a2..fd3b5fe1adadf0be0a26e802ecbf8400a02aac2a 100644 (file)
@@ -1,2 +1,290 @@
-{"message":"cannot find type `Iter` in this scope","code":{"code":"E0412","explanation":"/nThe type name used is not in scope./n/nErroneous code examples:/n/n```compile_fail,E0412/nimpl Something {} // error: type name `Something` is not in scope/n/n// or:/n/ntrait Foo {/n    fn bar(N); // error: type name `N` is not in scope/n}/n/n// or:/n/nfn foo(x: T) {} // type name `T` is not in scope/n```/n/nTo fix this error, please verify you didn't misspell the type name, you did/ndeclare it or imported it into the scope. Examples:/n/n```/nstruct Something;/n/nimpl Something {} // ok!/n/n// or:/n/ntrait Foo {/n    type N;/n/n    fn bar(_: Self::N); // ok!/n}/n/n// or:/n/nfn foo<T>(x: T) {} // ok!/n```/n/nAnother case that causes this error is when a type is imported into a parent/nmodule. To fix this, you can follow the suggestion and use File directly or/n`use super::File;` which will import the types from the parent namespace. An/nexample that causes this error is below:/n/n```compile_fail,E0412/nuse std::fs::File;/n/nmod foo {/n    fn some_function(f: File) {}/n}/n```/n/n```/nuse std::fs::File;/n/nmod foo {/n    // either/n    use super::File;/n    // or/n    // use std::fs::File;/n    fn foo(f: File) {}/n}/n# fn main() {} // don't insert it for us; that'll break imports/n```/n"},"level":"error","spans":[{"file_name":"$DIR/use_suggestion_json.rs","byte_start":862,"byte_end":866,"line_start":20,"line_end":20,"column_start":12,"column_end":16,"is_primary":true,"text":[{"text":"    let x: Iter;","highlight_start":12,"highlight_end":16}],"label":"not found in this scope","suggested_replacement":null,"expansion":null}],"children":[{"message":"possible candidates are found in other modules, you can import them into scope","code":null,"level":"help","spans":[{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::binary_heap::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::btree_map::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::btree_set::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::hash_map::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::hash_set::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::linked_list::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::vec_deque::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::option::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::path::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::result::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::slice::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::sync::mpsc::Iter;/n/n","expansion":null}],"children":[],"rendered":null}],"rendered":null}
-{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":null}
+{
+  "message": "cannot find type `Iter` in this scope",
+  "code": {
+    "code": "E0412",
+    "explanation": "/nThe type name used is not in scope./n/nErroneous code examples:/n/n```compile_fail,E0412/nimpl Something {} // error: type name `Something` is not in scope/n/n// or:/n/ntrait Foo {/n    fn bar(N); // error: type name `N` is not in scope/n}/n/n// or:/n/nfn foo(x: T) {} // type name `T` is not in scope/n```/n/nTo fix this error, please verify you didn't misspell the type name, you did/ndeclare it or imported it into the scope. Examples:/n/n```/nstruct Something;/n/nimpl Something {} // ok!/n/n// or:/n/ntrait Foo {/n    type N;/n/n    fn bar(_: Self::N); // ok!/n}/n/n// or:/n/nfn foo<T>(x: T) {} // ok!/n```/n/nAnother case that causes this error is when a type is imported into a parent/nmodule. To fix this, you can follow the suggestion and use File directly or/n`use super::File;` which will import the types from the parent namespace. An/nexample that causes this error is below:/n/n```compile_fail,E0412/nuse std::fs::File;/n/nmod foo {/n    fn some_function(f: File) {}/n}/n```/n/n```/nuse std::fs::File;/n/nmod foo {/n    // either/n    use super::File;/n    // or/n    // use std::fs::File;/n    fn foo(f: File) {}/n}/n# fn main() {} // don't insert it for us; that'll break imports/n```/n"
+  },
+  "level": "error",
+  "spans": [
+    {
+      "file_name": "$DIR/use_suggestion_json.rs",
+      "byte_start": 888,
+      "byte_end": 892,
+      "line_start": 20,
+      "line_end": 20,
+      "column_start": 12,
+      "column_end": 16,
+      "is_primary": true,
+      "text": [
+        {
+          "text": "    let x: Iter;",
+          "highlight_start": 12,
+          "highlight_end": 16
+        }
+      ],
+      "label": "not found in this scope",
+      "suggested_replacement": null,
+      "expansion": null
+    }
+  ],
+  "children": [
+    {
+      "message": "possible candidates are found in other modules, you can import them into scope",
+      "code": null,
+      "level": "help",
+      "spans": [
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::binary_heap::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::btree_map::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::btree_set::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::hash_map::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::hash_set::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::linked_list::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::collections::vec_deque::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::option::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::path::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::result::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::slice::Iter;/n/n",
+          "expansion": null
+        },
+        {
+          "file_name": "$DIR/use_suggestion_json.rs",
+          "byte_start": 865,
+          "byte_end": 865,
+          "line_start": 19,
+          "line_end": 19,
+          "column_start": 1,
+          "column_end": 1,
+          "is_primary": true,
+          "text": [
+            {
+              "text": "fn main() {",
+              "highlight_start": 1,
+              "highlight_end": 1
+            }
+          ],
+          "label": null,
+          "suggested_replacement": "use std::sync::mpsc::Iter;/n/n",
+          "expansion": null
+        }
+      ],
+      "children": [],
+      "rendered": null
+    }
+  ],
+  "rendered": null
+}
+{
+  "message": "aborting due to previous error",
+  "code": null,
+  "level": "error",
+  "spans": [],
+  "children": [],
+  "rendered": null
+}
index 9d4ac6305465a54ba1efeeb491e2d926ca41a10d..9de5e8fea0194e15b836a09593635e3eefdb2066 100644 (file)
@@ -14,15 +14,6 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
    |               |
    |               expected closure that takes 2 arguments
 
-error[E0308]: mismatched types
-  --> $DIR/closure-arg-count.rs:17:24
-   |
-17 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
-   |                        ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
-   |
-   = note: expected type `&{integer}`
-              found type `(_, _)`
-
 error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
   --> $DIR/closure-arg-count.rs:17:15
    |
@@ -65,5 +56,5 @@ error[E0593]: closure is expected to take a single 2-tuple as argument, but it t
    |                                                     |
    |                                                     expected closure that takes a single 2-tuple as argument
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/suggestion.rs b/src/test/ui/rfc-2005-default-binding-mode/suggestion.rs
new file mode 100644 (file)
index 0000000..52ff817
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+fn main() {
+    if let Some(y) = &Some(22) {
+      println!("{}", y);
+    }
+}
diff --git a/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr b/src/test/ui/rfc-2005-default-binding-mode/suggestion.stderr
new file mode 100644 (file)
index 0000000..0594f86
--- /dev/null
@@ -0,0 +1,10 @@
+error: non-reference pattern used to match a reference (see issue #42640)
+  --> $DIR/suggestion.rs:12:12
+   |
+12 |     if let Some(y) = &Some(22) {
+   |            ^^^^^^^ help: consider using: `&Some(y)`
+   |
+   = help: add #![feature(match_default_bindings)] to the crate attributes to enable
+
+error: aborting due to previous error
+
index 859c2305b5d7ff820d7f7af158bbca999cbd8bf3..b83550edc300e3d80dd16d0440123ffc1ad77bb9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 859c2305b5d7ff820d7f7af158bbca999cbd8bf3
+Subproject commit b83550edc300e3d80dd16d0440123ffc1ad77bb9
index 4f4960efc9b2c176f9d4c3b5182bb538df9fa559..a6c56a13076297824a26afe127dd1cbffafbbc74 100644 (file)
@@ -165,6 +165,8 @@ fn run_cargo_test(cargo_path: &Path, crate_path: &Path, packages: &[&str]) -> bo
     let status = command
         // Disable rust-lang/cargo's cross-compile tests
         .env("CFG_DISABLE_CROSS_TESTS", "1")
+        // Relax #![deny(warnings)] in some crates
+        .env("RUSTFLAGS", "--cap-lints warn")
         .current_dir(crate_path)
         .status()
         .expect("");
index aa98f818f40405a241e03ce3db37c7eb574546c3..660462ad419f70c70a047590c735a102dcc7f0ee 100644 (file)
@@ -34,6 +34,20 @@ pub enum Mode {
     MirOpt,
 }
 
+impl Mode {
+    pub fn disambiguator(self) -> &'static str {
+        // Run-pass and pretty run-pass tests could run concurrently, and if they do,
+        // they need to keep their output segregated. Same is true for debuginfo tests that
+        // can be run both on gdb and lldb.
+        match self {
+            Pretty => ".pretty",
+            DebugInfoGdb => ".gdb",
+            DebugInfoLldb => ".lldb",
+            _ => "",
+        }
+    }
+}
+
 impl FromStr for Mode {
     type Err = ();
     fn from_str(s: &str) -> Result<Mode, ()> {
index f8628158aff46c093353abb417f0373331721988..16c48ccfdd1cd440b36cc1ea639bf41fe10447e1 100644 (file)
@@ -1565,7 +1565,7 @@ 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!(".{}.libaux", self.config.mode));
+        fname.push(&format!("{}.aux", self.config.mode.disambiguator()));
         f.with_file_name(&fname)
     }
 
@@ -2286,6 +2286,10 @@ fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedL
         output_file.push(test_name);
         debug!("comparing the contests of: {:?}", output_file);
         debug!("with: {:?}", expected_content);
+        if !output_file.exists() {
+            panic!("Output file `{}` from test does not exist",
+                   output_file.into_os_string().to_string_lossy());
+        }
         self.check_mir_test_timestamp(test_name, &output_file);
 
         let mut dumped_file = fs::File::open(output_file.clone()).unwrap();
@@ -2334,13 +2338,22 @@ fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedL
 
         // We expect each non-empty line to appear consecutively, non-consecutive lines
         // must be separated by at least one Elision
+        let mut start_block_line = None;
         while let Some(dumped_line) = dumped_lines.next() {
             match expected_lines.next() {
-                Some(&ExpectedLine::Text(expected_line)) =>
+                Some(&ExpectedLine::Text(expected_line)) => {
+                    let normalized_expected_line = normalize_mir_line(expected_line);
+                    if normalized_expected_line.contains(":{") {
+                        start_block_line = Some(expected_line);
+                    }
+
                     if !compare(expected_line, dumped_line) {
+                        error!("{:?}", start_block_line);
                         error(expected_line,
-                              format!("Mismatch in lines\nExpected Line: {:?}", dumped_line));
-                    },
+                              format!("Mismatch in lines\nCurrnt block: {}\nExpected Line: {:?}",
+                                      start_block_line.unwrap_or("None"), dumped_line));
+                    }
+                },
                 Some(&ExpectedLine::Elision) => {
                     // skip any number of elisions in a row.
                     while let Some(&&ExpectedLine::Elision) = expected_lines.peek() {
@@ -2378,7 +2391,8 @@ fn get_mir_dump_dir(&self) -> PathBuf {
     fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
         let parent_dir = self.testpaths.file.parent().unwrap();
         let cflags = self.props.compile_flags.join(" ");
-        let parent_dir_str = if cflags.contains("--error-format json") {
+        let parent_dir_str = if cflags.contains("--error-format json")
+                             || cflags.contains("--error-format pretty-json") {
             parent_dir.display().to_string().replace("\\", "\\\\")
         } else {
             parent_dir.display().to_string()
index 48fd42fe92175ce93a5b67f78c195254ee94493d..9ad92e134ff56df52481cf19dc3da14b9e735061 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 48fd42fe92175ce93a5b67f78c195254ee94493d
+Subproject commit 9ad92e134ff56df52481cf19dc3da14b9e735061
index cf0d494dda7447bacaab743a70c47e28bea55c6f..51b03c3aaf5e69afbb7508e566c5da2bf0bc3662 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cf0d494dda7447bacaab743a70c47e28bea55c6f
+Subproject commit 51b03c3aaf5e69afbb7508e566c5da2bf0bc3662