]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #59432 - phansch:compiletest_docs, r=alexcrichton
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Tue, 26 Mar 2019 21:26:46 +0000 (22:26 +0100)
committerGitHub <noreply@github.com>
Tue, 26 Mar 2019 21:26:46 +0000 (22:26 +0100)
Improve some compiletest documentation

This adds some missing documentation for rustfix related things and adds
a test for the `is_test` function.

276 files changed:
Cargo.lock
README.md
src/bootstrap/doc.rs
src/doc/redirect.inc [new file with mode: 0644]
src/doc/robots.txt [new file with mode: 0644]
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/libcore/cmp.rs
src/libcore/convert.rs
src/libcore/hint.rs
src/libcore/num/flt2dec/mod.rs
src/libcore/option.rs
src/libcore/ptr.rs
src/libcore/result.rs
src/libcore/slice/mod.rs
src/libcore/tests/slice.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/def.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/pat_util.rs
src/librustc/hir/print.rs
src/librustc/infer/nll_relate/mod.rs
src/librustc/lint/context.rs
src/librustc/lint/levels.rs
src/librustc/lint/mod.rs
src/librustc/middle/dead.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/lib_features.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/reachable.rs
src/librustc/middle/stability.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc/query/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/traits/util.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/instance.rs
src/librustc/ty/mod.rs
src/librustc/ty/print/pretty.rs
src/librustc/ty/query/config.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/util.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/llvm/diagnostic.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_ssa/mir/place.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustc_driver/pretty.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_lint/builtin.rs
src/librustc_lint/unused.rs
src/librustc_macros/Cargo.toml
src/librustc_macros/src/query.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/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/path_utils.rs
src/librustc_mir/borrow_check/place_ext.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/borrow_check/prefixes.rs
src/librustc_mir/build/expr/as_place.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/dataflow/graphviz.rs
src/librustc_mir/dataflow/impls/borrowed_locals.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/dataflow/move_paths/mod.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/add_retag.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/transform/rustc_peek.rs
src/librustc_mir/util/graphviz.rs
src/librustc_mir/util/mod.rs
src/librustc_mir/util/pretty.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/layout_test.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_plugin/load.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/error_reporting.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_traits/chalk_context/program_clauses.rs [deleted file]
src/librustc_traits/chalk_context/program_clauses/builtin.rs [new file with mode: 0644]
src/librustc_traits/chalk_context/program_clauses/mod.rs [new file with mode: 0644]
src/librustc_traits/chalk_context/program_clauses/primitive.rs [new file with mode: 0644]
src/librustc_traits/chalk_context/resolvent_ops.rs
src/librustc_traits/lowering/environment.rs
src/librustc_traits/lowering/mod.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/mod.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/doctree.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/visit_ast.rs
src/libstd/Cargo.toml
src/libstd/env.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/fs.rs
src/libstd/net/addr.rs
src/libstd/net/tcp.rs
src/libstd/net/test.rs
src/libstd/net/udp.rs
src/libstd/path.rs
src/libstd/process.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sys/cloudabi/time.rs
src/libstd/sys/redox/time.rs
src/libstd/sys/sgx/abi/mod.rs
src/libstd/sys/sgx/abi/panic.rs
src/libstd/sys/sgx/abi/tls.rs
src/libstd/sys/sgx/abi/usercalls/alloc.rs
src/libstd/sys/sgx/alloc.rs
src/libstd/sys/sgx/args.rs
src/libstd/sys/sgx/condvar.rs
src/libstd/sys/sgx/net.rs
src/libstd/sys/sgx/os.rs
src/libstd/sys/sgx/rwlock.rs
src/libstd/sys/sgx/stack_overflow.rs
src/libstd/sys/sgx/thread.rs
src/libstd/sys/sgx/time.rs
src/libstd/sys/sgx/waitqueue.rs
src/libstd/sys/unix/time.rs
src/libstd/sys/wasm/time.rs
src/libstd/sys/windows/time.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libstd/time.rs
src/libsyntax/ast.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/attr/mod.rs
src/libsyntax/config.rs
src/libsyntax/ext/build.rs
src/libsyntax/feature_gate.rs
src/libsyntax/mut_visit.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_pos/lib.rs
src/libsyntax_pos/symbol.rs
src/stage0.txt
src/test/codegen/enum-debug-clike.rs
src/test/codegen/enum-debug-niche-2.rs
src/test/codegen/enum-debug-niche.rs
src/test/codegen/enum-debug-tagged.rs
src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs [new file with mode: 0644]
src/test/debuginfo/borrowed-enum.rs
src/test/debuginfo/generic-enum-with-different-disr-sizes.rs
src/test/debuginfo/generic-struct-style-enum.rs
src/test/debuginfo/generic-tuple-style-enum.rs
src/test/debuginfo/recursive-struct.rs
src/test/debuginfo/struct-style-enum.rs
src/test/debuginfo/tuple-style-enum.rs
src/test/debuginfo/unique-enum.rs
src/test/incremental/hashes/call_expressions.rs
src/test/incremental/hashes/closure_expressions.rs
src/test/incremental/hashes/enum_constructors.rs
src/test/incremental/hashes/exported_vs_not.rs
src/test/incremental/hashes/for_loops.rs
src/test/incremental/hashes/function_interfaces.rs
src/test/incremental/hashes/if_expressions.rs
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/inline_asm.rs
src/test/incremental/hashes/let_expressions.rs
src/test/incremental/hashes/loop_expressions.rs
src/test/incremental/hashes/match_expressions.rs
src/test/incremental/hashes/panic_exprs.rs
src/test/incremental/hashes/struct_constructors.rs
src/test/incremental/hashes/unary_and_binary_exprs.rs
src/test/incremental/hashes/while_let_loops.rs
src/test/incremental/hashes/while_loops.rs
src/test/incremental/spans_significant_w_panic.rs
src/test/incremental/string_constant.rs
src/test/mir-opt/graphviz.rs [new file with mode: 0644]
src/test/mir-opt/unusual-item-types.rs
src/test/ui/chalkify/lower_env2.stderr
src/test/ui/chalkify/lower_env3.stderr
src/test/ui/chalkify/lower_struct.stderr
src/test/ui/chalkify/lower_trait.stderr
src/test/ui/const-generics/struct-with-invalid-const-param.rs [new file with mode: 0644]
src/test/ui/const-generics/struct-with-invalid-const-param.stderr [new file with mode: 0644]
src/test/ui/deprecation/atomic_initializers.stderr
src/test/ui/deprecation/suggestion.fixed [new file with mode: 0644]
src/test/ui/deprecation/suggestion.rs [new file with mode: 0644]
src/test/ui/deprecation/suggestion.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0423.stderr
src/test/ui/imports/auxiliary/gensymed.rs [new file with mode: 0644]
src/test/ui/imports/gensymed.rs [new file with mode: 0644]
src/test/ui/issues/issue-17800.stderr
src/test/ui/issues/issue-22644.stderr
src/test/ui/issues/issue-23458.rs [new file with mode: 0644]
src/test/ui/issues/issue-23458.stderr [new file with mode: 0644]
src/test/ui/issues/issue-34255-1.rs [new file with mode: 0644]
src/test/ui/issues/issue-34255-1.stderr [new file with mode: 0644]
src/test/ui/issues/issue-51102.stderr
src/test/ui/issues/issue-52717.stderr
src/test/ui/lifetime_starts_expressions.stderr
src/test/ui/numeric/numeric-fields.stderr
src/test/ui/parser/struct-literal-in-for.stderr
src/test/ui/parser/struct-literal-in-if.stderr
src/test/ui/parser/struct-literal-in-while.stderr
src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr
src/test/ui/proc-macro/resolve-error.stderr
src/test/ui/resolve/issue-22692.stderr
src/test/ui/structs/struct-field-cfg.stderr
src/test/ui/suggestions/assoc-const-as-field.rs [new file with mode: 0644]
src/test/ui/suggestions/assoc-const-as-field.stderr [new file with mode: 0644]
src/test/ui/suggestions/auxiliary/foo.rs [new file with mode: 0644]
src/test/ui/suggestions/borrow-for-loop-head.nll.stderr [new file with mode: 0644]
src/test/ui/suggestions/borrow-for-loop-head.rs [new file with mode: 0644]
src/test/ui/suggestions/borrow-for-loop-head.stderr [new file with mode: 0644]
src/test/ui/suggestions/no-extern-crate-in-type.rs [new file with mode: 0644]
src/test/ui/suggestions/no-extern-crate-in-type.stderr [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-let.rs [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-let.stderr [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-method.rs [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-method.stderr [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-path.rs [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-path.stderr [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-variant.rs [new file with mode: 0644]
src/test/ui/suggestions/type-ascription-instead-of-variant.stderr [new file with mode: 0644]
src/test/ui/type/type-ascription-instead-of-statement-end.stderr
src/tools/tidy/src/deps.rs
src/tools/tidy/src/pal.rs

index ec1cda96b99a6de88c0e21f1682d97b100cec7c9..7fd39bd1f6eb637c072f8542075a7667e2f7b8d2 100644 (file)
@@ -2811,6 +2811,7 @@ dependencies = [
 name = "rustc_macros"
 version = "0.1.0"
 dependencies = [
+ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
index 514e420ca457cab879d3daae5746caf370dcdd4f..55e6e8d7f188925804bc82aa14e68a7b63e65a15 100644 (file)
--- a/README.md
+++ b/README.md
@@ -45,6 +45,22 @@ of the rustc-guide instead._
     $ ./x.py build && sudo ./x.py install
     ```
 
+    If after running `sudo ./x.py install` you see an error message like
+
+    ```
+    error: failed to load source for a dependency on 'cc'
+    ```
+
+    then run these two commands and then try `sudo ./x.py install` again:
+
+    ```
+    $ cargo install cargo-vendor
+    ```
+
+    ```
+    $ cargo vendor
+    ```
+
     > ***Note:*** Install locations can be adjusted by copying the config file
     > from `./config.toml.example` to `./config.toml`, and
     > adjusting the `prefix` option under `[install]`. Various other options, such
index ae329286486d6d46992f3f54485e1bb88b5b7acb..2ea6be552106b3671c2abedd8ee645ac95bae7b9 100644 (file)
@@ -331,7 +331,7 @@ fn invoke_rustdoc(
 
     let path = builder.src.join("src/doc").join(markdown);
 
-    let favicon = builder.src.join("src/doc/favicon.inc");
+    let header = builder.src.join("src/doc/redirect.inc");
     let footer = builder.src.join("src/doc/footer.inc");
     let version_info = out.join("version_info.html");
 
@@ -341,7 +341,7 @@ fn invoke_rustdoc(
 
     cmd.arg("--html-after-content").arg(&footer)
         .arg("--html-before-content").arg(&version_info)
-        .arg("--html-in-header").arg(&favicon)
+        .arg("--html-in-header").arg(&header)
         .arg("--markdown-no-toc")
         .arg("--markdown-playground-url")
         .arg("https://play.rust-lang.org/")
diff --git a/src/doc/redirect.inc b/src/doc/redirect.inc
new file mode 100644 (file)
index 0000000..33e3860
--- /dev/null
@@ -0,0 +1,2 @@
+<meta name="robots" content="noindex,follow">
+<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">
diff --git a/src/doc/robots.txt b/src/doc/robots.txt
new file mode 100644 (file)
index 0000000..a54ec50
--- /dev/null
@@ -0,0 +1,19 @@
+# NB: This file is not automatically deployed. After changes, it needs to be uploaded manually to doc.rust-lang.org
+User-agent: *
+Disallow: /0.3/
+Disallow: /0.4/
+Disallow: /0.5/
+Disallow: /0.6/
+Disallow: /0.7/
+Disallow: /0.8/
+Disallow: /0.9/
+Disallow: /0.10/
+Disallow: /0.11.0/
+Disallow: /0.12.0/
+Disallow: /1.0.0-alpha/
+Disallow: /1.0.0-alpha.2/
+Disallow: /1.0.0-beta/
+Disallow: /1.0.0-beta.2/
+Disallow: /1.0.0-beta.3/
+Disallow: /1.0.0-beta.4/
+Disallow: /1.0.0-beta.5/
index 9bce142b483f22f06c996aa8269a20eb19c7d59b..b2315c6a7390795bd3a71bc957e8f9014b637dde 100644 (file)
@@ -677,6 +677,9 @@ impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
     fn next_back(&mut self) -> Option<I::Item> {
         (**self).next_back()
     }
+    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
+        (**self).nth_back(n)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {
index 440ce8ac5e842d47ad5ee631f4ecdfa56bbb6c40..90ff56814fbb153b97dd4452dd53aee29bccfc27 100644 (file)
 #![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)]
 #![feature(alloc_layout_extra)]
 #![feature(try_trait)]
+#![feature(iter_nth_back)]
 
 // Allow testing this library
 
index ea52b0ea7212054dea929b0a3eb85d7e0fe7c981..807b35e1af10b1e35350751408a83516dee349f1 100644 (file)
@@ -568,8 +568,14 @@ fn min(self, other: Self) -> Self
         if self <= other { self } else { other }
     }
 
-    /// Returns max if self is greater than max, and min if self is less than min.
-    /// Otherwise this will return self.  Panics if min > max.
+    /// Restrict a value to a certain interval.
+    ///
+    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+    /// less than `min`. Otherwise this returns `self`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `min > max`.
     ///
     /// # Examples
     ///
@@ -586,8 +592,7 @@ fn clamp(self, min: Self, max: Self) -> Self
         assert!(min <= max);
         if self < min {
             min
-        }
-        else if self > max {
+        } else if self > max {
             max
         } else {
             self
index 774d648558b48ebd80f30dc519b4f253c7e619c1..cee4fc6f49a713cdfb8ae38350154d5628e226eb 100644 (file)
@@ -1,26 +1,25 @@
 //! Traits for conversions between types.
 //!
-//! The traits in this module provide a general way to talk about conversions
-//! from one type to another. They follow the standard Rust conventions of
-//! `as`/`into`/`from`.
+//! The traits in this module provide a way to convert from one type to another type.
+//! Each trait serves a different purpose:
 //!
-//! Like many traits, these are often used as bounds for generic functions, to
-//! support arguments of multiple types.
+//! - Implement the [`AsRef`] trait for cheap reference-to-reference conversions
+//! - Implement the [`AsMut`] trait for cheap mutable-to-mutable conversions
+//! - Implement the [`From`] trait for consuming value-to-value conversions
+//! - Implement the [`Into`] trait for consuming value-to-value conversions to types
+//!   outside the current crate
+//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
+//!   but should be implemented when the conversion can fail.
 //!
-//! - Implement the `As*` traits for reference-to-reference conversions
-//! - Implement the [`Into`] trait when you want to consume the value in the conversion
-//! - The [`From`] trait is the most flexible, useful for value _and_ reference conversions
-//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`], but allow for the
-//!   conversion to fail
+//! The traits in this module are often used as trait bounds for generic functions such that to
+//! arguments of multiple types are supported. See the documentation of each trait for examples.
 //!
-//! As a library author, you should prefer implementing [`From<T>`][`From`] or
+//! As a library author, you should always prefer implementing [`From<T>`][`From`] or
 //! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
 //! as [`From`] and [`TryFrom`] provide greater flexibility and offer
 //! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a
-//! blanket implementation in the standard library.  However, there are some cases
-//! where this is not possible, such as creating conversions into a type defined
-//! outside your library, so implementing [`Into`] instead of [`From`] is
-//! sometimes necessary.
+//! blanket implementation in the standard library. Only implement [`Into`] or [`TryInto`]
+//! when a conversion to a type outside the current crate is required.
 //!
 //! # Generic Implementations
 //!
 #[inline]
 pub const fn identity<T>(x: T) -> T { x }
 
-/// A cheap reference-to-reference conversion. Used to convert a value to a
-/// reference value within generic code.
+/// Used to do a cheap reference-to-reference conversion.
 ///
-/// `AsRef` is very similar to, but serves a slightly different purpose than,
-/// [`Borrow`].
+/// This trait is similar to [`AsMut`] which is used for converting between mutable references.
+/// If you need to do a costly conversion it is better to implement [`From`] with type
+/// `&T` or write a custom function.
 ///
-/// `AsRef` is to be used when wishing to convert to a reference of another
-/// type.
-/// `Borrow` is more related to the notion of taking the reference. It is
-/// useful when wishing to abstract over the type of reference
-/// (`&T`, `&mut T`) or allow both the referenced and owned type to be treated
-/// in the same manner.
 ///
-/// The key difference between the two traits is the intention:
+/// `AsRef` is very similar to, but serves a slightly different purpose than [`Borrow`]:
 ///
 /// - Use `AsRef` when the goal is to simply convert into a reference
 /// - Use `Borrow` when the goal is related to writing code that is agnostic to
@@ -120,7 +113,7 @@ pub const fn identity<T>(x: T) -> T { x }
 ///
 /// [`Borrow`]: ../../std/borrow/trait.Borrow.html
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use a
+/// **Note: This trait must not fail**. If the conversion can fail, use a
 /// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
 ///
 /// [`Option<T>`]: ../../std/option/enum.Option.html
@@ -134,7 +127,12 @@ pub const fn identity<T>(x: T) -> T { x }
 ///
 /// # Examples
 ///
-/// Both [`String`] and `&str` implement `AsRef<str>`:
+/// By using trait bounds we can accept arguments of different types as long as they can be
+/// converted a the specified type `T`.
+///
+/// For example: By creating a generic function that takes an `AsRef<str>` we express that we
+/// want to accept all references that can be converted to &str as an argument.
+/// Since both [`String`] and `&str` implement `AsRef<str>` we can accept both as input argument.
 ///
 /// [`String`]: ../../std/string/struct.String.html
 ///
@@ -157,12 +155,13 @@ pub trait AsRef<T: ?Sized> {
     fn as_ref(&self) -> &T;
 }
 
-/// A cheap, mutable reference-to-mutable reference conversion.
+/// Used to do a cheap mutable-to-mutable reference conversion.
 ///
-/// This trait is similar to `AsRef` but used for converting between mutable
-/// references.
+/// This trait is similar to [`AsRef`] but used for converting between mutable
+/// references. If you need to do a costly conversion it is better to
+/// implement [`From`] with type `&mut T` or write a custom function.
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use a
+/// **Note: This trait must not fail**. If the conversion can fail, use a
 /// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
 ///
 /// [`Option<T>`]: ../../std/option/enum.Option.html
@@ -176,10 +175,11 @@ pub trait AsRef<T: ?Sized> {
 ///
 /// # Examples
 ///
-/// [`Box<T>`] implements `AsMut<T>`:
-///
-/// [`Box<T>`]: ../../std/boxed/struct.Box.html
-///
+/// Using `AsMut` as trait bound for a generic function we can accept all mutable references
+/// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
+/// write a function `add_one`that takes all arguments that can be converted to `&mut u64`.
+/// Because [`Box<T>`] implements `AsMut<T>` `add_one` accepts arguments of type
+/// `&mut Box<u64>` as well:
 /// ```
 /// fn add_one<T: AsMut<u64>>(num: &mut T) {
 ///     *num.as_mut() += 1;
@@ -189,7 +189,7 @@ pub trait AsRef<T: ?Sized> {
 /// add_one(&mut boxed_num);
 /// assert_eq!(*boxed_num, 1);
 /// ```
-///
+/// [`Box<T>`]: ../../std/boxed/struct.Box.html
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsMut<T: ?Sized> {
@@ -198,29 +198,27 @@ pub trait AsMut<T: ?Sized> {
     fn as_mut(&mut self) -> &mut T;
 }
 
-/// A conversion that consumes `self`, which may or may not be expensive. The
-/// reciprocal of [`From`][From].
+/// A value-to-value conversion that consumes the input value. The
+/// opposite of [`From`].
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use
-/// [`TryInto`] or a dedicated method which returns an [`Option<T>`] or a
-/// [`Result<T, E>`].
+/// One should only implement [`Into`] if a conversion to a type outside the current crate is
+/// required. Otherwise one should always prefer implementing [`From`] over [`Into`] because
+/// implementing [`From`] automatically provides one with a implementation of [`Into`] thanks to
+/// the blanket implementation in the standard library. [`From`] cannot do these type of
+/// conversions because of Rust's orphaning rules.
 ///
-/// Library authors should not directly implement this trait, but should prefer
-/// implementing the [`From`][From] trait, which offers greater flexibility and
-/// provides an equivalent `Into` implementation for free, thanks to a blanket
-/// implementation in the standard library.
+/// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`].
 ///
 /// # Generic Implementations
 ///
-/// - [`From<T>`][From]` for U` implies `Into<U> for T`
-/// - [`into`] is reflexive, which means that `Into<T> for T` is implemented
+/// - [`From<T>`]` for U` implies `Into<U> for T`
+/// - [`Into`]` is reflexive, which means that `Into<T> for T` is implemented
 ///
-/// # Implementing `Into`
+/// # Implementing `Into` for conversions to external types
 ///
-/// There is one exception to implementing `Into`, and it's kind of esoteric.
-/// If the destination type is not part of the current crate, and it uses a
-/// generic variable, then you can't implement `From` directly. For example,
-/// take this crate:
+/// If the destination type is not part of the current crate
+/// then you can't implement [`From`] directly.
+/// For example, take this code:
 ///
 /// ```compile_fail
 /// struct Wrapper<T>(Vec<T>);
@@ -230,8 +228,9 @@ pub trait AsMut<T: ?Sized> {
 ///     }
 /// }
 /// ```
-///
-/// To fix this, you can implement `Into` directly:
+/// This will fail to compile because we cannot implement a trait for a type
+/// if both the trait and the type are not defined by the current crate.
+/// This is due to Rust's orphaning rules. To bypass this, you can implement `Into` directly:
 ///
 /// ```
 /// struct Wrapper<T>(Vec<T>);
@@ -242,17 +241,22 @@ pub trait AsMut<T: ?Sized> {
 /// }
 /// ```
 ///
-/// This won't always allow the conversion: for example, `try!` and `?`
-/// always use `From`. However, in most cases, people use `Into` to do the
-/// conversions, and this will allow that.
+/// It is important to understand that `Into` does not provide a [`From`] implementation
+/// (as [`From`] does with `Into`). Therefore, you should always try to implement [`From`]
+/// and then fall back to `Into` if [`From`] can't be implemented.
 ///
-/// In almost all cases, you should try to implement `From`, then fall back
-/// to `Into` if `From` can't be implemented.
+/// Prefer using `Into` over [`From`] when specifying trait bounds on a generic function
+/// to ensure that types that only implement `Into` can be used as well.
 ///
 /// # Examples
 ///
 /// [`String`] implements `Into<Vec<u8>>`:
 ///
+/// In order to express that we want a generic function to take all arguments that can be
+/// converted to a specified type `T`, we can use a trait bound of `Into<T>`.
+/// For example: The function `is_hello` takes all arguments that can be converted into a
+/// `Vec<u8>`.
+///
 /// ```
 /// fn is_hello<T: Into<Vec<u8>>>(s: T) {
 ///    let bytes = b"hello".to_vec();
@@ -276,36 +280,38 @@ pub trait Into<T>: Sized {
     fn into(self) -> T;
 }
 
-/// Simple and safe type conversions in to `Self`. It is the reciprocal of
-/// `Into`.
+/// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of
+/// [`Into`].
 ///
-/// This trait is useful when performing error handling as described by
-/// [the book][book] and is closely related to the `?` operator.
+/// One should always prefer implementing [`From`] over [`Into`]
+/// because implementing [`From`] automatically provides one with a implementation of [`Into`]
+/// thanks to the blanket implementation in the standard library.
 ///
-/// When constructing a function that is capable of failing the return type
-/// will generally be of the form `Result<T, E>`.
+/// Only implement [`Into`] if a conversion to a type outside the current crate is required.
+/// [`From`] cannot do these type of conversions because of Rust's orphaning rules.
+/// See [`Into`] for more details.
 ///
-/// The `From` trait allows for simplification of error handling by providing a
-/// means of returning a single error type that encapsulates numerous possible
-/// erroneous situations.
+/// Prefer using [`Into`] over using [`From`] when specifying trait bounds on a generic function.
+/// This way, types that directly implement [`Into`] can be used as arguments as well.
 ///
-/// This trait is not limited to error handling, rather the general case for
-/// this trait would be in any type conversions to have an explicit definition
-/// of how they are performed.
+/// The [`From`] is also very useful when performing error handling. When constructing a function
+/// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
+/// The `From` trait simplifies error handling by allowing a function to return a single error type
+/// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
+/// details.
 ///
-/// **Note: this trait must not fail**. If the conversion can fail, use
-/// [`TryFrom`] or a dedicated method which returns an [`Option<T>`] or a
-/// [`Result<T, E>`].
+/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`].
 ///
 /// # Generic Implementations
 ///
-/// - `From<T> for U` implies [`Into<U>`]` for T`
-/// - [`from`] is reflexive, which means that `From<T> for T` is implemented
+/// - [`From<T>`]` for U` implies [`Into<U>`]` for T`
+/// - [`From`] is reflexive, which means that `From<T> for T` is implemented
 ///
 /// # Examples
 ///
 /// [`String`] implements `From<&str>`:
 ///
+/// An explicit conversion from a &str to a String is done as follows:
 /// ```
 /// let string = "hello".to_string();
 /// let other_string = String::from("hello");
@@ -313,7 +319,12 @@ pub trait Into<T>: Sized {
 /// assert_eq!(string, other_string);
 /// ```
 ///
-/// An example usage for error handling:
+/// While performing error handling it is often useful to implement `From` for your own error type.
+/// By converting underlying error types to our own custom error type that encapsulates the
+/// underlying error type, we can return a single error type without losing information on the
+/// underlying cause. The '?' operator automatically converts the underlying error type to our
+/// custom error type by calling `Into<CliError>::into` which is automatically provided when
+/// implementing `From`. The compiler then infers which implementation of `Into` should be used.
 ///
 /// ```
 /// use std::fs;
index 89de5c1bc8af80d5c2652849fe760ca5247e19d0..b2f82ef0d175ccf3124b89728a1e292aeb0895b4 100644 (file)
@@ -62,13 +62,32 @@ pub unsafe fn unreachable_unchecked() -> ! {
 #[inline]
 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
 pub fn spin_loop() {
-    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-    unsafe {
-        asm!("pause" ::: "memory" : "volatile");
+    #[cfg(
+        all(
+            any(target_arch = "x86", target_arch = "x86_64"),
+            target_feature = "sse2"
+        )
+    )] {
+        #[cfg(target_arch = "x86")] {
+            unsafe { crate::arch::x86::_mm_pause() };
+        }
+
+        #[cfg(target_arch = "x86_64")] {
+            unsafe { crate::arch::x86_64::_mm_pause() };
+        }
     }
 
-    #[cfg(target_arch = "aarch64")]
-    unsafe {
-        asm!("yield" ::: "memory" : "volatile");
+    #[cfg(
+        any(
+            target_arch = "aarch64",
+            all(target_arch = "arm", target_feature = "v6")
+        )
+    )] {
+        #[cfg(target_arch = "aarch64")] {
+            unsafe { crate::arch::aarch64::__yield() };
+        }
+        #[cfg(target_arch = "arm")] {
+            unsafe { crate::arch::arm::__yield() };
+        }
     }
 }
index defd4247f4ea49b747d7fbc297ebf78bfa0176f1..c9a9375ec590e7032dd42b80f1d5db602e3152f8 100644 (file)
@@ -239,10 +239,8 @@ pub fn write(&self, out: &mut [u8]) -> Option<usize> {
 
         let mut written = self.sign.len();
         for part in self.parts {
-            match part.write(&mut out[written..]) {
-                Some(len) => { written += len; }
-                None => { return None; }
-            }
+            let len = part.write(&mut out[written..])?;
+            written += len;
         }
         Some(written)
     }
index dfc388409a84b53744287394c1428ab37639fe47..3da92c0a05ac4ece408b25b610df2a07fbe18ff4 100644 (file)
@@ -1315,6 +1315,26 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
     /// Since the last element is zero, it would underflow. Thus, the resulting
     /// value is `None`.
     ///
+    /// Here is a variation on the previous example, showing that no
+    /// further elements are taken from `iter` after the first `None`.
+    ///
+    /// ```
+    /// let items = vec![3_u16, 2, 1, 10];
+    ///
+    /// let mut shared = 0;
+    ///
+    /// let res: Option<Vec<u16>> = items
+    ///     .iter()
+    ///     .map(|x| { shared += x; x.checked_sub(2) })
+    ///     .collect();
+    ///
+    /// assert_eq!(res, None);
+    /// assert_eq!(shared, 6);
+    /// ```
+    ///
+    /// Since the third element caused an underflow, no further elements were taken,
+    /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
+    ///
     /// [`Iterator`]: ../iter/trait.Iterator.html
     #[inline]
     fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
index a9a029d606d6f84315931b1b69381dfe663c1de4..1897caa5aa53f520318b8ec9b468105ed2afb5e8 100644 (file)
@@ -2869,10 +2869,10 @@ fn from(p: NonNull<T>) -> Self {
 /// However the pointer may still dangle if it isn't dereferenced.
 ///
 /// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
-/// for your use case, you should include some PhantomData in your type to
+/// for your use case, you should include some [`PhantomData`] in your type to
 /// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
 /// Usually this won't be necessary; covariance is correct for most safe abstractions,
-/// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they
+/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they
 /// provide a public API that follows the normal shared XOR mutable rules of Rust.
 ///
 /// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
@@ -2883,6 +2883,7 @@ fn from(p: NonNull<T>) -> Self {
 /// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
 /// is never used for mutation.
 ///
+/// [`PhantomData`]: ../marker/struct.PhantomData.html
 /// [`UnsafeCell<T>`]: ../cell/struct.UnsafeCell.html
 #[stable(feature = "nonnull", since = "1.25.0")]
 #[repr(transparent)]
@@ -2913,7 +2914,7 @@ impl<T: Sized> NonNull<T> {
     /// some other means.
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
-    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
+    #[rustc_const_unstable(feature = "const_ptr_nonnull")]
     pub const fn dangling() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
@@ -2977,7 +2978,7 @@ pub unsafe fn as_mut(&mut self) -> &mut T {
     /// Cast to a pointer of another type
     #[stable(feature = "nonnull_cast", since = "1.27.0")]
     #[inline]
-    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
+    #[rustc_const_unstable(feature = "const_ptr_nonnull")]
     pub const fn cast<U>(self) -> NonNull<U> {
         unsafe {
             NonNull::new_unchecked(self.as_ptr() as *mut U)
index 967f7e3e2fe72fc9cbbc2a80b3e44f13c412af74..9b7b83689861bca2bdea241c7ceb392c7a5c4ef8 100644 (file)
@@ -1202,6 +1202,34 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
     /// ).collect();
     /// assert_eq!(res, Ok(vec![2, 3]));
     /// ```
+    ///
+    /// Here is another example that tries to subtract one from another list
+    /// of integers, this time checking for underflow:
+    ///
+    /// ```
+    /// let v = vec![1, 2, 0];
+    /// let res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|
+    ///     x.checked_sub(1).ok_or("Underflow!")
+    /// ).collect();
+    /// assert_eq!(res, Err("Underflow!"));
+    /// ```
+    ///
+    /// Here is a variation on the previous example, showing that no
+    /// further elements are taken from `iter` after the first `Err`.
+    ///
+    /// ```
+    /// let v = vec![3, 2, 1, 10];
+    /// let mut shared = 0;
+    /// let res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32| {
+    ///     shared += x;
+    ///     x.checked_sub(2).ok_or("Underflow!")
+    /// }).collect();
+    /// assert_eq!(res, Err("Underflow!"));
+    /// assert_eq!(shared, 6);
+    /// ```
+    ///
+    /// Since the third element caused an underflow, no further elements were taken,
+    /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
     #[inline]
     fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
         // FIXME(#11084): This could be replaced with Iterator::scan when this
index b3594f8a3858aec27cc66408fa1bb8ae41fe523f..4eb5bddb5d2f469d7bb74ae410facfe7907dca8c 100644 (file)
@@ -3867,6 +3867,19 @@ fn next_back(&mut self) -> Option<&'a [T]> {
             ret
         }
     }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
+        let (end, overflow) = self.v.len().overflowing_sub(n);
+        if end < self.size || overflow {
+            self.v = &[];
+            None
+        } else {
+            let ret = &self.v[end-self.size..end];
+            self.v = &self.v[..end-1];
+            Some(ret)
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index ac9c17a0f7c356ec4962927297b2490ad09044d5..4946fd52a7e12d7c914e842d1f6cd45347753355 100644 (file)
@@ -578,6 +578,19 @@ fn test_windows_nth() {
     assert_eq!(c2.next(), None);
 }
 
+#[test]
+fn test_windows_nth_back() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let mut c = v.windows(2);
+    assert_eq!(c.nth_back(2).unwrap()[0], 2);
+    assert_eq!(c.next_back().unwrap()[1], 2);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let mut c2 = v2.windows(4);
+    assert_eq!(c2.nth_back(1).unwrap()[1], 1);
+    assert_eq!(c2.next_back(), None);
+}
+
 #[test]
 fn test_windows_last() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
index 43e865ad08941c6e877e8c99c7760603ba8a6ce6..4babadb67bce6e428131310885be27f5e86f0e0a 100644 (file)
@@ -461,11 +461,6 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
 
     // Represents the MIR for a fn; also used as the task node for
     // things read/modify that MIR.
-    [] MirConstQualif(DefId),
-    [] MirBuilt(DefId),
-    [] MirConst(DefId),
-    [] MirValidated(DefId),
-    [] MirOptimized(DefId),
     [] MirShim { instance_def: InstanceDef<'tcx> },
 
     [] BorrowCheckKrate,
@@ -485,7 +480,6 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
     [] CollectModItemTypes(DefId),
 
     [] Reachability,
-    [] MirKeys,
     [eval_always] CrateVariances,
 
     // Nodes representing bits of computed IR in the tcx. Each shared
@@ -544,7 +538,6 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
     [anon] TraitSelect,
 
     [] ParamEnv(DefId),
-    [] Environment(DefId),
     [] DescribeDef(DefId),
 
     // FIXME(mw): DefSpans are not really inputs since they are derived from
@@ -571,7 +564,6 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
     [] HasGlobalAllocator(CrateNum),
     [] HasPanicHandler(CrateNum),
     [input] ExternCrate(DefId),
-    [eval_always] LintLevels,
     [] Specializes { impl1: DefId, impl2: DefId },
     [input] InScopeTraits(DefIndex),
     [input] ModuleExports(DefId),
@@ -621,14 +613,6 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
     [input] UsedCrateSource(CrateNum),
     [input] PostorderCnums,
 
-    // These queries are not expected to have inputs -- as a result, they
-    // are not good candidates for "replay" because they are essentially
-    // pure functions of their input (and hence the expectation is that
-    // no caller would be green **apart** from just these
-    // queries). Making them anonymous avoids hashing the result, which
-    // may save a bit of time.
-    [anon] EraseRegionsTy { ty: Ty<'tcx> },
-
     [input] Freevars(DefId),
     [input] MaybeUnusedTraitImport(DefId),
     [input] MaybeUnusedExternCrates,
@@ -667,9 +651,6 @@ pub fn to_dep_node(self, tcx: TyCtxt<'_, '_, '_>, kind: DepKind) -> DepNode {
 
     [input] Features,
 
-    [] ProgramClausesFor(DefId),
-    [] ProgramClausesForEnv(traits::Environment<'tcx>),
-    [] WasmImportModuleMap(CrateNum),
     [] ForeignModules(CrateNum),
 
     [] UpstreamMonomorphizations(CrateNum),
index 8602d159ba9603fd5ee7f5a9ca2d69d5d0daaecf..4c527f80d0f5d7593401c2891cfdeda08b08b8fa 100644 (file)
@@ -177,16 +177,8 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
         let mut is_transparent = false;
 
         for hint in &hints {
-            let name = if let Some(name) = hint.ident_str() {
-                name
-            } else {
-                // Invalid repr hint like repr(42). We don't check for unrecognized hints here
-                // (libsyntax does that), so just ignore it.
-                continue;
-            };
-
-            let (article, allowed_targets) = match name {
-                "C" | "align" => {
+            let (article, allowed_targets) = match hint.name_or_empty().get() {
+                name @ "C" | name @ "align" => {
                     is_c |= name == "C";
                     if target != Target::Struct &&
                             target != Target::Union &&
index b45fc3ffd82fe0118ba89baaa58db033ba234392..3cc23ccdb642c586afb9e8cb200495128996526a 100644 (file)
@@ -9,6 +9,15 @@
 
 use self::Namespace::*;
 
+/// Encodes if a `Def::Ctor` is the constructor of an enum variant or a struct.
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
+pub enum CtorOf {
+    /// This `Def::Ctor` is a synthesized constructor of a tuple or unit struct.
+    Struct,
+    /// This `Def::Ctor` is a synthesized constructor of a tuple or unit variant.
+    Variant,
+}
+
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
 pub enum CtorKind {
     /// Constructor function automatically created by a tuple struct/variant.
@@ -37,9 +46,11 @@ pub enum NonMacroAttrKind {
 pub enum Def {
     // Type namespace
     Mod(DefId),
-    Struct(DefId), // `DefId` refers to `NodeId` of the struct itself
+    /// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists.
+    Struct(DefId),
     Union(DefId),
     Enum(DefId),
+    /// `DefId` refers to the variant itself, `Def::Ctor` refers to its constructor if it exists.
     Variant(DefId),
     Trait(DefId),
     /// `existential type Foo: Bar;`
@@ -61,8 +72,8 @@ pub enum Def {
     Const(DefId),
     ConstParam(DefId),
     Static(DefId, bool /* is_mutbl */),
-    StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor
-    VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant
+    /// `DefId` refers to the struct or enum variant's constructor.
+    Ctor(DefId, CtorOf, CtorKind),
     SelfCtor(DefId /* impl */),  // `DefId` refers to the impl
     Method(DefId),
     AssociatedConst(DefId),
@@ -265,10 +276,9 @@ pub fn def_id(&self) -> DefId {
     pub fn opt_def_id(&self) -> Option<DefId> {
         match *self {
             Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
-            Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
+            Def::Variant(id) | Def::Ctor(id, ..) | Def::Enum(id) |
             Def::TyAlias(id) | Def::TraitAlias(id) |
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::ConstParam(id) | Def::Struct(id) |
-            Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
             Def::AssociatedConst(id) | Def::Macro(id, ..) |
             Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
@@ -303,20 +313,21 @@ pub fn kind_name(&self) -> &'static str {
             Def::Fn(..) => "function",
             Def::Mod(..) => "module",
             Def::Static(..) => "static",
-            Def::Variant(..) => "variant",
-            Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
-            Def::VariantCtor(.., CtorKind::Const) => "unit variant",
-            Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
             Def::Enum(..) => "enum",
+            Def::Variant(..) => "variant",
+            Def::Ctor(_, CtorOf::Variant, CtorKind::Fn) => "tuple variant",
+            Def::Ctor(_, CtorOf::Variant, CtorKind::Const) => "unit variant",
+            Def::Ctor(_, CtorOf::Variant, CtorKind::Fictive) => "struct variant",
+            Def::Struct(..) => "struct",
+            Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) => "tuple struct",
+            Def::Ctor(_, CtorOf::Struct, CtorKind::Const) => "unit struct",
+            Def::Ctor(_, CtorOf::Struct, CtorKind::Fictive) =>
+                bug!("impossible struct constructor"),
             Def::Existential(..) => "existential type",
             Def::TyAlias(..) => "type alias",
             Def::TraitAlias(..) => "trait alias",
             Def::AssociatedTy(..) => "associated type",
             Def::AssociatedExistential(..) => "associated existential type",
-            Def::Struct(..) => "struct",
-            Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
-            Def::StructCtor(.., CtorKind::Const) => "unit struct",
-            Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
             Def::SelfCtor(..) => "self constructor",
             Def::Union(..) => "union",
             Def::Trait(..) => "trait",
index 977830315e23e893c74ea3dc240800bfcad33817..bce528189ad1e0dd011b4630bff2875c23e17f55 100644 (file)
@@ -559,6 +559,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                         generics: &'v Generics,
                                         parent_item_id: HirId) {
     visitor.visit_ident(variant.node.ident);
+    visitor.visit_id(variant.node.id);
     visitor.visit_variant_data(&variant.node.data,
                                variant.node.ident.name,
                                generics,
@@ -923,7 +924,9 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'
 
 
 pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
-    visitor.visit_id(struct_definition.hir_id());
+    if let Some(ctor_hir_id) = struct_definition.ctor_hir_id() {
+        visitor.visit_id(ctor_hir_id);
+    }
     walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
index 2251e67233c5fc65820a998b8f42e7957eafb516..891210511ca7972a44c02e815baff70c025263ba 100644 (file)
@@ -1615,9 +1615,11 @@ fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
     }
 
     fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
+        let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(v.node.id);
         Spanned {
             node: hir::VariantKind {
                 ident: v.node.ident,
+                id: hir_id,
                 attrs: self.lower_attrs(&v.node.attrs),
                 data: self.lower_variant_data(&v.node.data),
                 disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
@@ -2669,19 +2671,10 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
 
     fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
         match *vdata {
-            VariantData::Struct(ref fields, id, recovered) => {
-                let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
-
-                hir::VariantData::Struct(
-                    fields
-                        .iter()
-                        .enumerate()
-                        .map(|f| self.lower_struct_field(f))
-                        .collect(),
-                    hir_id,
-                    recovered,
-                )
-            },
+            VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
+                fields.iter().enumerate().map(|f| self.lower_struct_field(f)).collect(),
+                recovered,
+            ),
             VariantData::Tuple(ref fields, id) => {
                 let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
 
@@ -2696,7 +2689,6 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
             },
             VariantData::Unit(id) => {
                 let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
-
                 hir::VariantData::Unit(hir_id)
             },
         }
@@ -4334,13 +4326,14 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 //   }
 
                 // expand <head>
-                let head = self.lower_expr(head);
+                let mut head = self.lower_expr(head);
                 let head_sp = head.span;
                 let desugared_span = self.mark_span_with_reason(
                     CompilerDesugaringKind::ForLoop,
                     head_sp,
                     None,
                 );
+                head.span = desugared_span;
 
                 let iter = self.str_to_ident("iter");
 
index e88f9e60702f7865db9d762904bb34f2d213e6e1..75d7d843dea7e89fe3e4f98a919d55e0c98bdf45 100644 (file)
@@ -360,9 +360,9 @@ fn visit_item(&mut self, i: &'hir Item) {
             this.insert(i.span, i.hir_id, Node::Item(i));
             this.with_parent(i.hir_id, |this| {
                 if let ItemKind::Struct(ref struct_def, _) = i.node {
-                    // If this is a tuple-like struct, register the constructor.
-                    if !struct_def.is_struct() {
-                        this.insert(i.span, struct_def.hir_id(), Node::StructCtor(struct_def));
+                    // If this is a tuple or unit-like struct, register the constructor.
+                    if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+                        this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
                     }
                 }
                 intravisit::walk_item(this, i);
@@ -515,8 +515,12 @@ fn visit_macro_def(&mut self, macro_def: &'hir MacroDef) {
     }
 
     fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
-        self.insert(v.span, v.node.data.hir_id(), Node::Variant(v));
-        self.with_parent(v.node.data.hir_id(), |this| {
+        self.insert(v.span, v.node.id, Node::Variant(v));
+        self.with_parent(v.node.id, |this| {
+            // Register the constructor of this variant.
+            if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() {
+                this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data));
+            }
             intravisit::walk_variant(this, v, g, item_id);
         });
     }
index 12760f8b9828b2372c40c6335d1a422bfa64775f..1a3bbc5ecc49ed3bce7c9f370efa8a65059f5860 100644 (file)
@@ -158,12 +158,9 @@ fn visit_item(&mut self, i: &'a Item) {
         self.with_parent(def, |this| {
             match i.node {
                 ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
-                    // If this is a tuple-like struct, register the constructor.
-                    if !struct_def.is_struct() {
-                        this.create_def(struct_def.id(),
-                                        DefPathData::StructCtor,
-                                        REGULAR_SPACE,
-                                        i.span);
+                    // If this is a unit or tuple-like struct, register the constructor.
+                    if let Some(ctor_hir_id) = struct_def.ctor_id() {
+                        this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, i.span);
                     }
                 }
                 _ => {}
@@ -193,11 +190,16 @@ fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
     }
 
     fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
-        let def = self.create_def(v.node.data.id(),
+        let def = self.create_def(v.node.id,
                                   DefPathData::EnumVariant(v.node.ident.as_interned_str()),
                                   REGULAR_SPACE,
                                   v.span);
-        self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id));
+        self.with_parent(def, |this| {
+            if let Some(ctor_hir_id) = v.node.data.ctor_id() {
+                this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, v.span);
+            }
+            visit::walk_variant(this, v, g, item_id)
+        });
     }
 
     fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,
index dca4ce4aef81773e9ac5879a6fd0e750560f53f9..1006d813e65ed6cd29183fa0fff77da36c9f00b6 100644 (file)
@@ -366,8 +366,8 @@ pub enum DefPathData {
     EnumVariant(InternedString),
     /// A struct field
     Field(InternedString),
-    /// Implicit ctor for a tuple-like struct
-    StructCtor,
+    /// Implicit ctor for a unit or tuple-like struct or enum variant.
+    Ctor,
     /// A constant expression (see {ast,hir}::AnonConst).
     AnonConst,
     /// An `impl Trait` type node
@@ -652,7 +652,7 @@ pub fn get_opt_name(&self) -> Option<InternedString> {
             CrateRoot |
             Misc |
             ClosureExpr |
-            StructCtor |
+            Ctor |
             AnonConst |
             ImplTrait => None
         }
@@ -683,7 +683,7 @@ pub fn as_interned_str(&self) -> InternedString {
             Impl => "{{impl}}",
             Misc => "{{misc}}",
             ClosureExpr => "{{closure}}",
-            StructCtor => "{{constructor}}",
+            Ctor => "{{constructor}}",
             AnonConst => "{{constant}}",
             ImplTrait => "{{opaque}}",
         };
index 3e8da882eed15b21d68a764cfbd38c8708da3356..d810a9310c55fae4638161c91d60ce29b8749ddd 100644 (file)
@@ -366,12 +366,18 @@ pub fn describe_def(&self, node_id: NodeId) -> Option<Def> {
                 }
             }
             Node::Variant(variant) => {
-                let def_id = self.local_def_id_from_hir_id(variant.node.data.hir_id());
+                let def_id = self.local_def_id_from_hir_id(variant.node.id);
                 Some(Def::Variant(def_id))
             }
-            Node::StructCtor(variant) => {
-                let def_id = self.local_def_id_from_hir_id(variant.hir_id());
-                Some(Def::StructCtor(def_id, def::CtorKind::from_hir(variant)))
+            Node::Ctor(variant_data) => {
+                let ctor_of = match self.find(self.get_parent_node(node_id)) {
+                    Some(Node::Item(..)) => def::CtorOf::Struct,
+                    Some(Node::Variant(..)) => def::CtorOf::Variant,
+                    _ => unreachable!(),
+                };
+                variant_data.ctor_hir_id()
+                    .map(|hir_id| self.local_def_id_from_hir_id(hir_id))
+                    .map(|def_id| Def::Ctor(def_id, ctor_of, def::CtorKind::from_hir(variant_data)))
             }
             Node::AnonConst(_) |
             Node::Field(_) |
@@ -516,8 +522,7 @@ pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
             Node::AnonConst(_) => {
                 BodyOwnerKind::Const
             }
-            Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) |
-            Node::StructCtor(..) |
+            Node::Ctor(..) |
             Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
             Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) |
             Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => {
@@ -948,8 +953,8 @@ pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData {
                     _ => bug!("struct ID bound to non-struct {}", self.hir_to_string(id))
                 }
             }
-            Some(Node::StructCtor(data)) => data,
             Some(Node::Variant(variant)) => &variant.node.data,
+            Some(Node::Ctor(data)) => data,
             _ => bug!("expected struct or variant, found {}", self.hir_to_string(id))
         }
     }
@@ -993,7 +998,7 @@ pub fn name(&self, id: NodeId) -> Name {
             Node::Lifetime(lt) => lt.name.ident().name,
             Node::GenericParam(param) => param.name.ident().name,
             Node::Binding(&Pat { node: PatKind::Binding(_, _, l, _), .. }) => l.name,
-            Node::StructCtor(_) => self.name(self.get_parent(id)),
+            Node::Ctor(..) => self.name(self.get_parent(id)),
             _ => bug!("no name for {}", self.node_to_string(id))
         }
     }
@@ -1019,9 +1024,9 @@ pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] {
             Some(Node::Expr(ref e)) => Some(&*e.attrs),
             Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
             Some(Node::GenericParam(param)) => Some(&param.attrs[..]),
-            // unit/tuple structs take the attributes straight from
-            // the struct definition.
-            Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)),
+            // Unit/tuple structs/variants take the attributes straight from
+            // the struct/variant definition.
+            Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)),
             _ => None
         };
         attrs.unwrap_or(&[])
@@ -1068,7 +1073,11 @@ pub fn span(&self, id: NodeId) -> Span {
             Some(Node::Binding(pat)) => pat.span,
             Some(Node::Pat(pat)) => pat.span,
             Some(Node::Block(block)) => block.span,
-            Some(Node::StructCtor(_)) => self.expect_item(self.get_parent(id)).span,
+            Some(Node::Ctor(..)) => match self.find(self.get_parent_node(id)) {
+                Some(Node::Item(item)) => item.span,
+                Some(Node::Variant(variant)) => variant.span,
+                _ => unreachable!(),
+            }
             Some(Node::Lifetime(lifetime)) => lifetime.span,
             Some(Node::GenericParam(param)) => param.span,
             Some(Node::Visibility(&Spanned {
@@ -1324,7 +1333,7 @@ pub fn print_node(&mut self, node: Node<'_>) -> io::Result<()> {
             // these cases do not carry enough information in the
             // hir_map to reconstruct their full structure for pretty
             // printing.
-            Node::StructCtor(_)   => bug!("cannot print isolated StructCtor"),
+            Node::Ctor(..)        => bug!("cannot print isolated Ctor"),
             Node::Local(a)        => self.print_local_decl(&a),
             Node::MacroDef(_)     => bug!("cannot print MacroDef"),
             Node::Crate           => bug!("cannot print Crate"),
@@ -1443,8 +1452,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String {
         Some(Node::Local(_)) => {
             format!("local {}{}", map.node_to_pretty_string(id), id_str)
         }
-        Some(Node::StructCtor(_)) => {
-            format!("struct_ctor {}{}", path_str(), id_str)
+        Some(Node::Ctor(..)) => {
+            format!("ctor {}{}", path_str(), id_str)
         }
         Some(Node::Lifetime(_)) => {
             format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
index 823de08874e60fd0c91128457e2d3bbf972dc34a..1bf7eed71bf0ff67dcfd7d504b9929ef2c7fe959 100644 (file)
@@ -2049,9 +2049,14 @@ pub struct EnumDef {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub struct VariantKind {
+    /// Name of the variant.
     #[stable_hasher(project(name))]
     pub ident: Ident,
+    /// Attributes of the variant.
     pub attrs: HirVec<Attribute>,
+    /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`).
+    pub id: HirId,
+    /// Fields and constructor id of the variant.
     pub data: VariantData,
     /// Explicit discriminant (e.g., `Foo = 1`).
     pub disr_expr: Option<AnonConst>,
@@ -2063,7 +2068,7 @@ pub struct VariantKind {
 pub enum UseKind {
     /// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
     /// Also produced for each element of a list `use`, e.g.
-    // `use foo::{a, b}` lowers to `use foo::a; use foo::b;`.
+    /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`.
     Single,
 
     /// Glob import, e.g., `use foo::*`.
@@ -2170,57 +2175,37 @@ pub fn is_positional(&self) -> bool {
     }
 }
 
-/// Fields and Ids of enum variants and structs
-///
-/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all
-/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants).
-/// One shared Id can be successfully used for these two purposes.
-/// Id of the whole enum lives in `Item`.
-///
-/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually
-/// used for `Struct`-structs (but still present). Structures don't have an analogue of "Id of
-/// the variant itself" from enum variants.
-/// Id of the whole struct lives in `Item`.
+/// Fields and constructor ids of enum variants and structs
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
 pub enum VariantData {
-    Struct(HirVec<StructField>, HirId, /* recovered */ bool),
+    /// Struct variant.
+    ///
+    /// e.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
+    Struct(HirVec<StructField>, /* recovered */ bool),
+    /// Tuple variant.
+    ///
+    /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
     Tuple(HirVec<StructField>, HirId),
+    /// Unit variant.
+    ///
+    /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
     Unit(HirId),
 }
 
 impl VariantData {
+    /// Return the fields of this variant.
     pub fn fields(&self) -> &[StructField] {
         match *self {
             VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => fields,
             _ => &[],
         }
     }
-    pub fn hir_id(&self) -> HirId {
+
+    /// Return the `HirId` of this variant's constructor, if it has one.
+    pub fn ctor_hir_id(&self) -> Option<HirId> {
         match *self {
-            VariantData::Struct(_, hir_id, _)
-            | VariantData::Tuple(_, hir_id)
-            | VariantData::Unit(hir_id) => hir_id,
-        }
-    }
-    pub fn is_struct(&self) -> bool {
-        if let VariantData::Struct(..) = *self {
-            true
-        } else {
-            false
-        }
-    }
-    pub fn is_tuple(&self) -> bool {
-        if let VariantData::Tuple(..) = *self {
-            true
-        } else {
-            false
-        }
-    }
-    pub fn is_unit(&self) -> bool {
-        if let VariantData::Unit(..) = *self {
-            true
-        } else {
-            false
+            VariantData::Struct(_, _) => None,
+            VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id),
         }
     }
 }
@@ -2594,8 +2579,9 @@ pub enum Node<'hir> {
     Local(&'hir Local),
     MacroDef(&'hir MacroDef),
 
-    /// StructCtor represents a tuple struct.
-    StructCtor(&'hir VariantData),
+    /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
+    /// with synthesized constructors.
+    Ctor(&'hir VariantData),
 
     Lifetime(&'hir Lifetime),
     GenericParam(&'hir GenericParam),
index 18a3d6708db64c815a1465b630b44a606c3bb58d..e7eda5aab133fb2778a4e51df14484e4be92f906 100644 (file)
@@ -1,4 +1,4 @@
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
 use crate::hir::def_id::DefId;
 use crate::hir::{self, HirId, PatKind};
 use syntax::ast;
@@ -55,7 +55,7 @@ pub fn is_refutable(&self) -> bool {
             PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
             PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
                 match path.def {
-                    Def::Variant(..) | Def::VariantCtor(..) => true,
+                    Def::Variant(..) => true,
                     _ => false
                 }
             }
@@ -125,8 +125,8 @@ pub fn necessary_variants(&self) -> Vec<DefId> {
                 PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
                 PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
                     match path.def {
-                        Def::Variant(id) |
-                        Def::VariantCtor(id, ..) => variants.push(id),
+                        Def::Variant(id) => variants.push(id),
+                        Def::Ctor(id, CtorOf::Variant, ..) => variants.push(id),
                         _ => ()
                     }
                 }
index bff4190ae7925cb6aa6002f62cf1f5f82ed99727..cdd4043f4bc2189624ac137b55d0aa23ea853af3 100644 (file)
@@ -860,41 +860,44 @@ pub fn print_struct(&mut self,
                         -> io::Result<()> {
         self.print_name(name)?;
         self.print_generic_params(&generics.params)?;
-        if !struct_def.is_struct() {
-            if struct_def.is_tuple() {
-                self.popen()?;
-                self.commasep(Inconsistent, struct_def.fields(), |s, field| {
-                    s.maybe_print_comment(field.span.lo())?;
-                    s.print_outer_attributes(&field.attrs)?;
-                    s.print_visibility(&field.vis)?;
-                    s.print_type(&field.ty)
-                })?;
-                self.pclose()?;
-            }
-            self.print_where_clause(&generics.where_clause)?;
-            if print_finalizer {
-                self.s.word(";")?;
+        match struct_def {
+            hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
+                if let hir::VariantData::Tuple(..) = struct_def {
+                    self.popen()?;
+                    self.commasep(Inconsistent, struct_def.fields(), |s, field| {
+                        s.maybe_print_comment(field.span.lo())?;
+                        s.print_outer_attributes(&field.attrs)?;
+                        s.print_visibility(&field.vis)?;
+                        s.print_type(&field.ty)
+                    })?;
+                    self.pclose()?;
+                }
+                self.print_where_clause(&generics.where_clause)?;
+                if print_finalizer {
+                    self.s.word(";")?;
+                }
+                self.end()?;
+                self.end() // close the outer-box
             }
-            self.end()?;
-            self.end() // close the outer-box
-        } else {
-            self.print_where_clause(&generics.where_clause)?;
-            self.nbsp()?;
-            self.bopen()?;
-            self.hardbreak_if_not_bol()?;
-
-            for field in struct_def.fields() {
+            hir::VariantData::Struct(..) => {
+                self.print_where_clause(&generics.where_clause)?;
+                self.nbsp()?;
+                self.bopen()?;
                 self.hardbreak_if_not_bol()?;
-                self.maybe_print_comment(field.span.lo())?;
-                self.print_outer_attributes(&field.attrs)?;
-                self.print_visibility(&field.vis)?;
-                self.print_ident(field.ident)?;
-                self.word_nbsp(":")?;
-                self.print_type(&field.ty)?;
-                self.s.word(",")?;
-            }
 
-            self.bclose(span)
+                for field in struct_def.fields() {
+                    self.hardbreak_if_not_bol()?;
+                    self.maybe_print_comment(field.span.lo())?;
+                    self.print_outer_attributes(&field.attrs)?;
+                    self.print_visibility(&field.vis)?;
+                    self.print_ident(field.ident)?;
+                    self.word_nbsp(":")?;
+                    self.print_type(&field.ty)?;
+                    self.s.word(",")?;
+                }
+
+                self.bclose(span)
+            }
         }
     }
 
index 7140af36acbdc4191a0133b85f35f323b250b863..d8e7328c274b75fc69c8bc3e5ef5c95bfb9b47bf 100644 (file)
 //!   constituents)
 
 use crate::infer::InferCtxt;
+use crate::traits::DomainGoal;
+use crate::ty::error::TypeError;
 use crate::ty::fold::{TypeFoldable, TypeVisitor};
 use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use crate::ty::subst::Kind;
 use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::error::TypeError;
-use crate::traits::DomainGoal;
 use rustc_data_structures::fx::FxHashMap;
+use std::fmt::Debug;
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum NormalizationStrategy {
@@ -239,6 +240,7 @@ fn replace_bound_region(
         first_free_index: ty::DebruijnIndex,
         scopes: &[BoundRegionScope<'tcx>],
     ) -> ty::Region<'tcx> {
+        debug!("replace_bound_regions(scopes={:?})", scopes);
         if let ty::ReLateBound(debruijn, br) = r {
             Self::lookup_bound_region(*debruijn, br, first_free_index, scopes)
         } else {
@@ -265,7 +267,7 @@ fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
     fn relate_projection_ty(
         &mut self,
         projection_ty: ty::ProjectionTy<'tcx>,
-        value_ty: ty::Ty<'tcx>
+        value_ty: ty::Ty<'tcx>,
     ) -> Ty<'tcx> {
         use crate::infer::type_variable::TypeVariableOrigin;
         use crate::traits::WhereClause;
@@ -273,7 +275,9 @@ fn relate_projection_ty(
 
         match value_ty.sty {
             ty::Projection(other_projection_ty) => {
-                let var = self.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
+                let var = self
+                    .infcx
+                    .next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
                 self.relate_projection_ty(projection_ty, var);
                 self.relate_projection_ty(other_projection_ty, var);
                 var
@@ -284,32 +288,55 @@ fn relate_projection_ty(
                     projection_ty,
                     ty: value_ty,
                 };
-                self.delegate.push_domain_goal(
-                    DomainGoal::Holds(WhereClause::ProjectionEq(projection))
-                );
+                self.delegate
+                    .push_domain_goal(DomainGoal::Holds(WhereClause::ProjectionEq(projection)));
                 value_ty
             }
         }
     }
 
-    /// Relate a type inference variable with a value type.
-    fn relate_ty_var(
+    /// Relate a type inference variable with a value type. This works
+    /// by creating a "generalization" G of the value where all the
+    /// lifetimes are replaced with fresh inference values. This
+    /// genearlization G becomes the value of the inference variable,
+    /// and is then related in turn to the value. So e.g. if you had
+    /// `vid = ?0` and `value = &'a u32`, we might first instantiate
+    /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
+    /// and then relate `&'0 u32` with `&'a u32` (resulting in
+    /// relations between `'0` and `'a`).
+    ///
+    /// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
+    /// -- in other words, it is always a (unresolved) inference
+    /// variable `vid` and a type `ty` that are being related, but the
+    /// vid may appear either as the "a" type or the "b" type,
+    /// depending on where it appears in the tuple. The trait
+    /// `VidValuePair` lets us work with the vid/type while preserving
+    /// the "sidedness" when necessary -- the sidedness is relevant in
+    /// particular for the variance and set of in-scope things.
+    fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
         &mut self,
-        vid: ty::TyVid,
-        value_ty: Ty<'tcx>
+        pair: PAIR,
     ) -> RelateResult<'tcx, Ty<'tcx>> {
-        debug!("relate_ty_var(vid={:?}, value_ty={:?})", vid, value_ty);
+        debug!("relate_ty_var({:?})", pair);
 
+        let vid = pair.vid();
+        let value_ty = pair.value_ty();
+
+        // FIXME -- this logic assumes invariance, but that is wrong.
+        // This only presently applies to chalk integration, as NLL
+        // doesn't permit type variables to appear on both sides (and
+        // doesn't use lazy norm).
         match value_ty.sty {
             ty::Infer(ty::TyVar(value_vid)) => {
                 // Two type variables: just equate them.
-                self.infcx.type_variables.borrow_mut().equate(vid, value_vid);
+                self.infcx
+                    .type_variables
+                    .borrow_mut()
+                    .equate(vid, value_vid);
                 return Ok(value_ty);
             }
 
-            ty::Projection(projection_ty)
-                if D::normalization() == NormalizationStrategy::Lazy =>
-            {
+            ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
                 return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
             }
 
@@ -326,19 +353,22 @@ fn relate_ty_var(
             assert!(!generalized_ty.has_infer_types());
         }
 
-        self.infcx.type_variables.borrow_mut().instantiate(vid, generalized_ty);
+        self.infcx
+            .type_variables
+            .borrow_mut()
+            .instantiate(vid, generalized_ty);
 
         // The generalized values we extract from `canonical_var_values` have
         // been fully instantiated and hence the set of scopes we have
         // doesn't matter -- just to be sure, put an empty vector
         // in there.
-        let old_a_scopes = ::std::mem::replace(&mut self.a_scopes, vec![]);
+        let old_a_scopes = ::std::mem::replace(pair.vid_scopes(self), vec![]);
 
         // Relate the generalized kind to the original one.
-        let result = self.relate(&generalized_ty, &value_ty);
+        let result = pair.relate_generalized_ty(self, generalized_ty);
 
         // Restore the old scopes now.
-        self.a_scopes = old_a_scopes;
+        *pair.vid_scopes(self) = old_a_scopes;
 
         debug!("relate_ty_var: complete, result = {:?}", result);
         result
@@ -347,7 +377,7 @@ fn relate_ty_var(
     fn generalize_value<T: Relate<'tcx>>(
         &mut self,
         value: T,
-        for_vid: ty::TyVid
+        for_vid: ty::TyVid,
     ) -> RelateResult<'tcx, T> {
         let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
 
@@ -364,6 +394,104 @@ fn generalize_value<T: Relate<'tcx>>(
     }
 }
 
+/// When we instantiate a inference variable with a value in
+/// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
+/// but the ordering may vary (depending on whether the inference
+/// variable was found on the `a` or `b` sides). Therefore, this trait
+/// allows us to factor out common code, while preserving the order
+/// when needed.
+trait VidValuePair<'tcx>: Debug {
+    /// Extract the inference variable (which could be either the
+    /// first or second part of the tuple).
+    fn vid(&self) -> ty::TyVid;
+
+    /// Extract the value it is being related to (which will be the
+    /// opposite part of the tuple from the vid).
+    fn value_ty(&self) -> Ty<'tcx>;
+
+    /// Extract the scopes that apply to whichever side of the tuple
+    /// the vid was found on.  See the comment where this is called
+    /// for more details on why we want them.
+    fn vid_scopes<D: TypeRelatingDelegate<'tcx>>(
+        &self,
+        relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
+    ) -> &'r mut Vec<BoundRegionScope<'tcx>>;
+
+    /// Given a generalized type G that should replace the vid, relate
+    /// G to the value, putting G on whichever side the vid would have
+    /// appeared.
+    fn relate_generalized_ty<D>(
+        &self,
+        relate: &mut TypeRelating<'_, '_, 'tcx, D>,
+        generalized_ty: Ty<'tcx>,
+    ) -> RelateResult<'tcx, Ty<'tcx>>
+    where
+        D: TypeRelatingDelegate<'tcx>;
+}
+
+impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
+    fn vid(&self) -> ty::TyVid {
+        self.0
+    }
+
+    fn value_ty(&self) -> Ty<'tcx> {
+        self.1
+    }
+
+    fn vid_scopes<D>(
+        &self,
+        relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
+    ) -> &'r mut Vec<BoundRegionScope<'tcx>>
+    where
+        D: TypeRelatingDelegate<'tcx>,
+    {
+        &mut relate.a_scopes
+    }
+
+    fn relate_generalized_ty<D>(
+        &self,
+        relate: &mut TypeRelating<'_, '_, 'tcx, D>,
+        generalized_ty: Ty<'tcx>,
+    ) -> RelateResult<'tcx, Ty<'tcx>>
+    where
+        D: TypeRelatingDelegate<'tcx>,
+    {
+        relate.relate(&generalized_ty, &self.value_ty())
+    }
+}
+
+// In this case, the "vid" is the "b" type.
+impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
+    fn vid(&self) -> ty::TyVid {
+        self.1
+    }
+
+    fn value_ty(&self) -> Ty<'tcx> {
+        self.0
+    }
+
+    fn vid_scopes<D>(
+        &self,
+        relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
+    ) -> &'r mut Vec<BoundRegionScope<'tcx>>
+    where
+        D: TypeRelatingDelegate<'tcx>,
+    {
+        &mut relate.b_scopes
+    }
+
+    fn relate_generalized_ty<D>(
+        &self,
+        relate: &mut TypeRelating<'_, '_, 'tcx, D>,
+        generalized_ty: Ty<'tcx>,
+    ) -> RelateResult<'tcx, Ty<'tcx>>
+    where
+        D: TypeRelatingDelegate<'tcx>,
+    {
+        relate.relate(&self.value_ty(), &generalized_ty)
+    }
+}
+
 impl<D> TypeRelation<'me, 'gcx, 'tcx> for TypeRelating<'me, 'gcx, 'tcx, D>
 where
     D: TypeRelatingDelegate<'tcx>,
@@ -421,11 +549,11 @@ fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>
                     // Forbid inference variables in the RHS.
                     bug!("unexpected inference var {:?}", b)
                 } else {
-                    self.relate_ty_var(vid, a)
+                    self.relate_ty_var((a, vid))
                 }
             }
 
-            (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var(vid, b),
+            (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
 
             (&ty::Projection(projection_ty), _)
                 if D::normalization() == NormalizationStrategy::Lazy =>
@@ -752,7 +880,9 @@ fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                             drop(variables);
                             self.relate(&u, &u)
                         }
-                        TypeVariableValue::Unknown { universe: _universe } => {
+                        TypeVariableValue::Unknown {
+                            universe: _universe,
+                        } => {
                             if self.ambient_variance == ty::Bivariant {
                                 // FIXME: we may need a WF predicate (related to #54105).
                             }
@@ -767,8 +897,7 @@ fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                             let u = self.tcx().mk_ty_var(new_var_id);
                             debug!(
                                 "generalize: replacing original vid={:?} with new={:?}",
-                                vid,
-                                u
+                                vid, u
                             );
                             return Ok(u);
                         }
@@ -776,8 +905,7 @@ fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 }
             }
 
-            ty::Infer(ty::IntVar(_)) |
-            ty::Infer(ty::FloatVar(_)) => {
+            ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) => {
                 // No matter what mode we are in,
                 // integer/floating-point types must be equal to be
                 // relatable.
@@ -788,9 +916,8 @@ fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 if self.universe.cannot_name(placeholder.universe) {
                     debug!(
                         "TypeGeneralizer::tys: root universe {:?} cannot name\
-                        placeholder in universe {:?}",
-                        self.universe,
-                        placeholder.universe
+                         placeholder in universe {:?}",
+                        self.universe, placeholder.universe
                     );
                     Err(TypeError::Mismatch)
                 } else {
@@ -798,9 +925,7 @@ fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                 }
             }
 
-            _ => {
-                relate::super_relate_tys(self, a, a)
-            }
+            _ => relate::super_relate_tys(self, a, a),
         }
     }
 
index 9761ee313533fe446b3b2410996e798f676e4e88..94f1d9c2710071ba795c108054427d90118c0cc2 100644 (file)
@@ -917,7 +917,7 @@ fn visit_variant(&mut self,
                      v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
-        self.with_lint_attrs(v.node.data.hir_id(), &v.node.attrs, |cx| {
+        self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| {
             run_lints!(cx, check_variant, v, g);
             hir_visit::walk_variant(cx, v, g, item_id);
             run_lints!(cx, check_variant_post, v, g);
@@ -1073,7 +1073,9 @@ fn visit_variant_data(&mut self,
                         item_id: ast::NodeId,
                         _: Span) {
         run_early_pass!(self, check_struct_def, s, ident, g, item_id);
-        self.check_id(s.id());
+        if let Some(ctor_hir_id) = s.ctor_id() {
+            self.check_id(ctor_hir_id);
+        }
         ast_visit::walk_struct_def(self, s);
         run_early_pass!(self, check_struct_def_post, s, ident, g, item_id);
     }
index 19e899ceb421f72497f406b1532d95c7a52810a3..2e5bd8add0cdcb017c247f6b43f15640ab032be4 100644 (file)
@@ -194,7 +194,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
             struct_span_err!(sess, span, E0452, "malformed lint attribute")
         };
         for attr in attrs {
-            let level = match attr.ident_str().and_then(|name| Level::from_str(name)) {
+            let level = match Level::from_str(&attr.name_or_empty()) {
                 None => continue,
                 Some(lvl) => lvl,
             };
index 03ed62f2a0d664ef10f56629da1d17ef8d580726..ae44210bcfffcff8e4d7310f9b450dc0b1876b31 100644 (file)
@@ -723,12 +723,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
 
 pub fn maybe_lint_level_root(tcx: TyCtxt<'_, '_, '_>, id: hir::HirId) -> bool {
     let attrs = tcx.hir().attrs_by_hir_id(id);
-    for attr in attrs {
-        if attr.ident_str().and_then(Level::from_str).is_some() {
-            return true;
-        }
-    }
-    false
+    attrs.iter().any(|attr| Level::from_str(&attr.name_or_empty()).is_some())
 }
 
 fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
@@ -803,7 +798,7 @@ fn visit_variant(&mut self,
                      v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
-        self.with_lint_attrs(v.node.data.hir_id(), &v.node.attrs, |builder| {
+        self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| {
             intravisit::walk_variant(builder, v, g, item_id);
         })
     }
index ccec4bd1432695c81bc47569036d1e3536fbbfbb..f12367a89bbf3dae3c94414aa4a09812e8f812d6 100644 (file)
@@ -7,7 +7,7 @@
 use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use crate::hir::itemlikevisit::ItemLikeVisitor;
 
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
 use crate::hir::CodegenFnAttrFlags;
 use crate::hir::def_id::{DefId, LOCAL_CRATE};
 use crate::lint;
@@ -54,8 +54,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     fn check_def_id(&mut self, def_id: DefId) {
         if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
-            if should_explore(self.tcx, hir_id) ||
-               self.struct_constructors.contains_key(&hir_id) {
+            if should_explore(self.tcx, hir_id) || self.struct_constructors.contains_key(&hir_id) {
                 self.worklist.push(hir_id);
             }
             self.live_symbols.insert(hir_id);
@@ -77,10 +76,17 @@ fn handle_definition(&mut self, def: Def) {
             _ if self.in_pat => (),
             Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) |
             Def::Local(..) | Def::Upvar(..) => {}
-            Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
-                if let Some(enum_id) = self.tcx.parent(variant_id) {
-                    self.check_def_id(enum_id);
+            Def::Ctor(ctor_def_id, CtorOf::Variant, ..) => {
+                let variant_id = self.tcx.parent(ctor_def_id).unwrap();
+                let enum_id = self.tcx.parent(variant_id).unwrap();
+                self.check_def_id(enum_id);
+                if !self.ignore_variant_stack.contains(&ctor_def_id) {
+                    self.check_def_id(variant_id);
                 }
+            }
+            Def::Variant(variant_id) => {
+                let enum_id = self.tcx.parent(variant_id).unwrap();
+                self.check_def_id(enum_id);
                 if !self.ignore_variant_stack.contains(&variant_id) {
                     self.check_def_id(variant_id);
                 }
@@ -360,9 +366,16 @@ fn visit_item(&mut self, item: &hir::Item) {
             self.worklist.push(item.hir_id);
         }
         match item.node {
-            hir::ItemKind::Enum(ref enum_def, _) if allow_dead_code => {
-                self.worklist.extend(enum_def.variants.iter()
-                                                      .map(|variant| variant.node.data.hir_id()));
+            hir::ItemKind::Enum(ref enum_def, _) => {
+                if allow_dead_code {
+                    self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
+                }
+
+                for variant in &enum_def.variants {
+                    if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+                        self.struct_constructors.insert(ctor_hir_id, variant.node.id);
+                    }
+                }
             }
             hir::ItemKind::Trait(.., ref trait_item_refs) => {
                 for trait_item_ref in trait_item_refs {
@@ -392,7 +405,9 @@ fn visit_item(&mut self, item: &hir::Item) {
                 }
             }
             hir::ItemKind::Struct(ref variant_data, _) => {
-                self.struct_constructors.insert(variant_data.hir_id(), item.hir_id);
+                if let Some(ctor_hir_id) = variant_data.ctor_hir_id() {
+                    self.struct_constructors.insert(ctor_hir_id, item.hir_id);
+                }
             }
             _ => ()
         }
@@ -484,9 +499,9 @@ fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
     }
 
     fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool {
-        !self.symbol_is_live(variant.data.hir_id())
+        !self.symbol_is_live(variant.id)
             && !has_allow_dead_code_or_lang_attr(self.tcx,
-                                                 variant.data.hir_id(),
+                                                 variant.id,
                                                  &variant.attrs)
     }
 
@@ -583,7 +598,7 @@ fn visit_variant(&mut self,
                      g: &'tcx hir::Generics,
                      id: hir::HirId) {
         if self.should_warn_about_variant(&variant.node) {
-            self.warn_dead_code(variant.node.data.hir_id(), variant.span, variant.node.ident.name,
+            self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name,
                                 "variant", "constructed");
         } else {
             intravisit::walk_variant(self, variant, g, id);
index 8ada67efaafdd3048c871095a1ccd73d2e15afbc..6c8d9fe29d7a0e8832a0a4da4a18cb4794a7c250 100644 (file)
@@ -9,12 +9,12 @@
 use self::TrackMatchMode::*;
 use self::OverloadedCallType::*;
 
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
 use crate::hir::def_id::DefId;
 use crate::infer::InferCtxt;
 use crate::middle::mem_categorization as mc;
 use crate::middle::region;
-use crate::ty::{self, TyCtxt, adjustment};
+use crate::ty::{self, DefIdTree, TyCtxt, adjustment};
 
 use crate::hir::{self, PatKind};
 use rustc_data_structures::sync::Lrc;
@@ -902,14 +902,20 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
             };
             let def = mc.tables.qpath_def(qpath, pat.hir_id);
             match def {
-                Def::Variant(variant_did) |
-                Def::VariantCtor(variant_did, ..) => {
+                Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => {
+                    let variant_did = mc.tcx.parent(variant_ctor_did).unwrap();
+                    let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
+
+                    debug!("variantctor downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
+                    delegate.matched_pat(pat, &downcast_cmt, match_mode);
+                }
+                Def::Variant(variant_did) => {
                     let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
 
                     debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
                     delegate.matched_pat(pat, &downcast_cmt, match_mode);
                 }
-                Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
+                Def::Struct(..) | Def::Ctor(..) | Def::Union(..) |
                 Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
                     debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
                     delegate.matched_pat(pat, &cmt_pat, match_mode);
index 237b00db575a968efc32df021ee078c244ef4cfc..ee8dd9e58b5ff9b2babee032a9575bfad06aeac1 100644 (file)
@@ -65,9 +65,9 @@ fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
                 for meta in metas {
                     if let Some(mi) = meta.meta_item() {
                         // Find the `feature = ".."` meta-item.
-                        match (mi.ident_str(), mi.value_str()) {
-                            (Some("feature"), val) => feature = val,
-                            (Some("since"), val) => since = val,
+                        match (mi.name_or_empty().get(), mi.value_str()) {
+                            ("feature", val) => feature = val,
+                            ("since", val) => since = val,
                             _ => {}
                         }
                     }
index b36d2a57cb3b1d3f4043e86599eaaa4c1c60242f..4b169dea06c7c7970bf17e7375f2ae1316cbd930 100644 (file)
@@ -62,7 +62,7 @@
 use crate::hir::def_id::{DefId, LocalDefId};
 use crate::hir::Node;
 use crate::infer::InferCtxt;
-use crate::hir::def::{Def, CtorKind};
+use crate::hir::def::{CtorOf, Def, CtorKind};
 use crate::ty::adjustment;
 use crate::ty::{self, DefIdTree, Ty, TyCtxt};
 use crate::ty::fold::TypeFoldable;
@@ -704,7 +704,7 @@ pub fn cat_def(&self,
                hir_id, expr_ty, def);
 
         match def {
-            Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::ConstParam(..) |
+            Def::Ctor(..) | Def::Const(..) | Def::ConstParam(..) |
             Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
                 Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
             }
@@ -1274,12 +1274,14 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
                         debug!("access to unresolvable pattern {:?}", pat);
                         return Err(())
                     }
-                    Def::VariantCtor(def_id, CtorKind::Fn) => {
-                        let enum_def = self.tcx.parent(def_id).unwrap();
-                        (self.cat_downcast_if_needed(pat, cmt, def_id),
-                        self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
+                    Def::Ctor(variant_ctor_did, CtorOf::Variant, CtorKind::Fn) => {
+                        let variant_did = self.tcx.parent(variant_ctor_did).unwrap();
+                        let enum_did = self.tcx.parent(variant_did).unwrap();
+                        (self.cat_downcast_if_needed(pat, cmt, variant_did),
+                         self.tcx.adt_def(enum_did)
+                             .variant_with_ctor_id(variant_ctor_did).fields.len())
                     }
-                    Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
+                    Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) | Def::SelfCtor(..) => {
                         let ty = self.pat_ty_unadjusted(&pat)?;
                         match ty.sty {
                             ty::Adt(adt_def, _) => {
@@ -1314,8 +1316,11 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
                         debug!("access to unresolvable pattern {:?}", pat);
                         return Err(())
                     }
-                    Def::Variant(variant_did) |
-                    Def::VariantCtor(variant_did, ..) => {
+                    Def::Ctor(variant_ctor_did, CtorOf::Variant, _) => {
+                        let variant_did = self.tcx.parent(variant_ctor_did).unwrap();
+                        self.cat_downcast_if_needed(pat, cmt, variant_did)
+                    }
+                    Def::Variant(variant_did) => {
                         self.cat_downcast_if_needed(pat, cmt, variant_did)
                     }
                     _ => cmt,
index a7294dbf07c000a1c92ddeb51dce5e31f2a57bac..b57f96f2d469de6a82950cdff300c7ae5f304370 100644 (file)
@@ -311,7 +311,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>,
             // Nothing to recurse on for these
             Node::ForeignItem(_) |
             Node::Variant(_) |
-            Node::StructCtor(_) |
+            Node::Ctor(..) |
             Node::Field(_) |
             Node::Ty(_) |
             Node::MacroDef(_) => {}
index 72c90b258608df8c997a49ed70afdb1b544fa1eb..ef1270d304523949f46b9e7a7544284cf2847162 100644 (file)
@@ -194,12 +194,11 @@ fn annotate<F>(&mut self, hir_id: HirId, attrs: &[Attribute],
         } else {
             // Emit errors for non-staged-api crates.
             for attr in attrs {
-                if let Some(tag) = attr.ident_str() {
-                    if tag == "unstable" || tag == "stable" || tag == "rustc_deprecated" {
-                        attr::mark_used(attr);
-                        self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
-                                                           outside of the standard library");
-                    }
+                let name = attr.name_or_empty();
+                if ["unstable", "stable", "rustc_deprecated"].contains(&name.get()) {
+                    attr::mark_used(attr);
+                    self.tcx.sess.span_err(attr.span, "stability attributes may not be used \
+                                                        outside of the standard library");
                 }
             }
 
@@ -258,8 +257,8 @@ fn visit_item(&mut self, i: &'tcx Item) {
                 self.in_trait_impl = true;
             }
             hir::ItemKind::Struct(ref sd, _) => {
-                if !sd.is_struct() {
-                    self.annotate(sd.hir_id(), &i.attrs, i.span, AnnotationKind::Required, |_| {})
+                if let Some(ctor_hir_id) = sd.ctor_hir_id() {
+                    self.annotate(ctor_hir_id, &i.attrs, i.span, AnnotationKind::Required, |_| {})
                 }
             }
             _ => {}
@@ -289,8 +288,15 @@ fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
     }
 
     fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
-        self.annotate(var.node.data.hir_id(), &var.node.attrs, var.span, AnnotationKind::Required,
-            |v| { intravisit::walk_variant(v, var, g, item_id) })
+        self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required,
+            |v| {
+                if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() {
+                    v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required,
+                               |_| {});
+                }
+
+                intravisit::walk_variant(v, var, g, item_id)
+            })
     }
 
     fn visit_struct_field(&mut self, s: &'tcx StructField) {
@@ -364,7 +370,7 @@ fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
     }
 
     fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) {
-        self.check_missing_stability(var.node.data.hir_id(), var.span, "variant");
+        self.check_missing_stability(var.node.id, var.span, "variant");
         intravisit::walk_variant(self, var, g, item_id);
     }
 
@@ -576,7 +582,7 @@ pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> Eva
                 if let hir::Node::Expr(_) = self.hir().get_by_hir_id(id) {
                     diag.span_suggestion(
                         span,
-                        &msg,
+                        "replace the use of the deprecated item",
                         suggestion.to_string(),
                         Applicability::MachineApplicable,
                     );
index 9f2027e7d0563efd0b1fc710f81dadaa35c7938e..d35ee1e57d5ce35d72f23ea3af7830cf37a62525 100644 (file)
@@ -1913,22 +1913,24 @@ pub enum PlaceBase<'tcx> {
 
     /// static or static mut variable
     Static(Box<Static<'tcx>>),
-
-    /// Constant code promoted to an injected static
-    Promoted(Box<(Promoted, Ty<'tcx>)>),
 }
 
-/// The `DefId` of a static, along with its normalized type (which is
-/// stored to avoid requiring normalization when reading MIR).
+/// We store the normalized type to avoid requiring normalization when reading MIR
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub struct Static<'tcx> {
-    pub def_id: DefId,
     pub ty: Ty<'tcx>,
+    pub kind: StaticKind,
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable)]
+pub enum StaticKind {
+    Promoted(Promoted),
+    Static(DefId),
 }
 
 impl_stable_hash_for!(struct Static<'tcx> {
-    def_id,
-    ty
+    ty,
+    kind
 });
 
 /// The `Projection` data structure defines things of the form `B.x`
@@ -2048,7 +2050,7 @@ pub fn base_local(&self) -> Option<Local> {
         match self {
             Place::Base(PlaceBase::Local(local)) => Some(*local),
             Place::Projection(box Projection { base, elem: _ }) => base.base_local(),
-            Place::Base(PlaceBase::Promoted(..)) | Place::Base(PlaceBase::Static(..)) => None,
+            Place::Base(PlaceBase::Static(..)) => None,
         }
     }
 }
@@ -2059,18 +2061,24 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
         match *self {
             Base(PlaceBase::Local(id)) => write!(fmt, "{:?}", id),
-            Base(PlaceBase::Static(box self::Static { def_id, ty })) => write!(
-                fmt,
-                "({}: {:?})",
-                ty::tls::with(|tcx| tcx.def_path_str(def_id)),
-                ty
-            ),
-            Base(PlaceBase::Promoted(ref promoted)) => write!(
-                fmt,
-                "({:?}: {:?})",
-                promoted.0,
-                promoted.1
-            ),
+            Base(PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) })) => {
+                write!(
+                    fmt,
+                    "({}: {:?})",
+                    ty::tls::with(|tcx| tcx.def_path_str(def_id)),
+                    ty
+                )
+            },
+            Base(PlaceBase::Static(
+                box self::Static { ty, kind: StaticKind::Promoted(promoted) })
+            ) => {
+                write!(
+                    fmt,
+                    "({:?}: {:?})",
+                    promoted,
+                    ty
+                )
+            },
             Projection(ref data) => match data.elem {
                 ProjectionElem::Downcast(ref adt_def, index) => {
                     write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
@@ -2410,7 +2418,7 @@ fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
                         ty::tls::with(|tcx| {
                             let substs = tcx.lift(&substs).expect("could not lift for printing");
                             FmtPrinter::new(tcx, f, Namespace::ValueNS)
-                                .print_def_path(variant_def.did, substs)?;
+                                .print_def_path(variant_def.def_id, substs)?;
                             Ok(())
                         })?;
 
index a6f153eaf6461e5c0772c8f18b7188f2bbfb82e8..ac42eacacd7bfff0adbdd96c5f1f4f5446727de8 100644 (file)
@@ -160,7 +160,6 @@ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> P
         match *self {
             Place::Base(PlaceBase::Local(index)) =>
                 PlaceTy::Ty { ty: local_decls.local_decls()[index].ty },
-            Place::Base(PlaceBase::Promoted(ref data)) => PlaceTy::Ty { ty: data.1 },
             Place::Base(PlaceBase::Static(ref data)) =>
                 PlaceTy::Ty { ty: data.ty },
             Place::Projection(ref proj) =>
index 8bc0075c477195b2a1cfa900a8828d9d46226be8..54e5bfc4397e8be33144ebceb7d3235c55b30ae1 100644 (file)
@@ -156,13 +156,6 @@ fn visit_place(&mut self,
                 self.super_place(place, context, location);
             }
 
-            fn visit_static(&mut self,
-                            static_: & $($mutability)? Static<'tcx>,
-                            context: PlaceContext<'tcx>,
-                            location: Location) {
-                self.super_static(static_, context, location);
-            }
-
             fn visit_projection(&mut self,
                                 place: & $($mutability)? PlaceProjection<'tcx>,
                                 context: PlaceContext<'tcx>,
@@ -736,27 +729,18 @@ fn super_place(&mut self,
                     Place::Base(PlaceBase::Local(local)) => {
                         self.visit_local(local, context, location);
                     }
-                    Place::Base(PlaceBase::Static(static_)) => {
-                        self.visit_static(static_, context, location);
+                    Place::Base(PlaceBase::Static(box Static { kind, ty })) => {
+                        if let StaticKind::Static(def_id) = kind {
+                            self.visit_def_id(& $($mutability)? *def_id, location)
+                        }
+                        self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
                     }
-                    Place::Base(PlaceBase::Promoted(promoted)) => {
-                        self.visit_ty(& $($mutability)? promoted.1, TyContext::Location(location));
-                    },
                     Place::Projection(proj) => {
                         self.visit_projection(proj, context, location);
                     }
                 }
             }
 
-            fn super_static(&mut self,
-                            static_: & $($mutability)? Static<'tcx>,
-                            _context: PlaceContext<'tcx>,
-                            location: Location) {
-                let Static { def_id, ty } = static_;
-                self.visit_def_id(def_id, location);
-                self.visit_ty(ty, TyContext::Location(location));
-            }
-
             fn super_projection(&mut self,
                                 proj: & $($mutability)? PlaceProjection<'tcx>,
                                 context: PlaceContext<'tcx>,
index ecc00898600020b3a2fcab807b6c865bea7cd231..8d64818f49b18a752086794ad1448a0f107d5f88 100644 (file)
@@ -1,9 +1,9 @@
 use crate::ty::query::QueryDescription;
 use crate::ty::query::queries;
-use crate::ty::TyCtxt;
-use crate::ty;
-use crate::hir::def_id::CrateNum;
+use crate::ty::{self, Ty, TyCtxt};
+use crate::hir::def_id::{DefId, CrateNum};
 use crate::dep_graph::SerializedDepNodeIndex;
+use crate::traits;
 use std::borrow::Cow;
 
 // Each of these queries corresponds to a function pointer field in the
         query native_libraries(_: CrateNum) -> Lrc<Vec<NativeLibrary>> {
             desc { "looking up the native libraries of a linked crate" }
         }
+
+        query lint_levels(_: CrateNum) -> Lrc<lint::LintLevelMap> {
+            eval_always
+            desc { "computing the lint levels for items in this crate" }
+        }
     }
 
     Codegen {
             desc { "checking if the crate is_panic_runtime" }
         }
     }
+
+    Codegen {
+        /// Set of all the `DefId`s in this crate that have MIR associated with
+        /// them. This includes all the body owners, but also things like struct
+        /// constructors.
+        query mir_keys(_: CrateNum) -> Lrc<DefIdSet> {
+            desc { "getting a list of all mir_keys" }
+        }
+
+        /// Maps DefId's that have an associated Mir to the result
+        /// of the MIR qualify_consts pass. The actual meaning of
+        /// the value isn't known except to the pass itself.
+        query mir_const_qualif(key: DefId) -> (u8, Lrc<BitSet<mir::Local>>) {
+            cache { key.is_local() }
+        }
+
+        /// Fetch the MIR for a given `DefId` right after it's built - this includes
+        /// unreachable code.
+        query mir_built(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {}
+
+        /// Fetch the MIR for a given `DefId` up till the point where it is
+        /// ready for const evaluation.
+        ///
+        /// See the README for the `mir` module for details.
+        query mir_const(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+            no_hash
+        }
+
+        query mir_validated(_: DefId) -> &'tcx Steal<mir::Mir<'tcx>> {
+            no_hash
+        }
+
+        /// MIR after our optimization passes have run. This is MIR that is ready
+        /// for codegen. This is also the only query that can fetch non-local MIR, at present.
+        query optimized_mir(key: DefId) -> &'tcx mir::Mir<'tcx> {
+            cache { key.is_local() }
+            load_cached(tcx, id) {
+                let mir: Option<crate::mir::Mir<'tcx>> = tcx.queries.on_disk_cache
+                                                            .try_load_query_result(tcx, id);
+                mir.map(|x| tcx.alloc_mir(x))
+            }
+        }
+    }
+
+    TypeChecking {
+        // Erases regions from `ty` to yield a new type.
+        // Normally you would just use `tcx.erase_regions(&value)`,
+        // however, which uses this query as a kind of cache.
+        query erase_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> {
+            // This query is not expected to have input -- as a result, it
+            // is not a good candidates for "replay" because it is essentially a
+            // pure function of its input (and hence the expectation is that
+            // no caller would be green **apart** from just these
+            // queries). Making it anonymous avoids hashing the result, which
+            // may save a bit of time.
+            anon
+            no_force
+            desc { "erasing regions from `{:?}`", ty }
+        }
+
+        query program_clauses_for(_: DefId) -> Clauses<'tcx> {
+            desc { "generating chalk-style clauses" }
+        }
+
+        query program_clauses_for_env(_: traits::Environment<'tcx>) -> Clauses<'tcx> {
+            no_force
+            desc { "generating chalk-style clauses for environment" }
+        }
+
+        // Get the chalk-style environment of the given item.
+        query environment(_: DefId) -> traits::Environment<'tcx> {
+            desc { "return a chalk-style environment" }
+        }
+    }
+
+    Linking {
+        query wasm_import_module_map(_: CrateNum) -> Lrc<FxHashMap<DefId, String>> {
+            desc { "wasm import module map" }
+        }
+    }
 }
index f5f2ec38bdf2741247c1ac9ba480ba4422f06ecb..5b5a7cc9ed85b1d3a237ceb2b062c3d19fe6de49 100644 (file)
@@ -1077,23 +1077,13 @@ pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
                     _ => ArgKind::empty()
                 }).collect::<Vec<ArgKind>>())
             }
-            Node::Variant(&hir::Variant {
-                span,
-                node: hir::VariantKind {
-                    data: hir::VariantData::Tuple(ref fields, ..),
-                    ..
-                },
-                ..
-            }) => {
-                (self.tcx.sess.source_map().def_span(span),
-                 fields.iter().map(|field|
-                     ArgKind::Arg(field.ident.to_string(), "_".to_string())
-                 ).collect::<Vec<_>>())
-            }
-            Node::StructCtor(ref variant_data) => {
-                (self.tcx.sess.source_map().def_span(
-                    self.tcx.hir().span_by_hir_id(variant_data.hir_id())),
-                 vec![ArgKind::empty(); variant_data.fields().len()])
+            Node::Ctor(ref variant_data) => {
+                let span = variant_data.ctor_hir_id()
+                    .map(|hir_id| self.tcx.hir().span_by_hir_id(hir_id))
+                    .unwrap_or(DUMMY_SP);
+                let span = self.tcx.sess.source_map().def_span(span);
+
+                (span, vec![ArgKind::empty(); variant_data.fields().len()])
             }
             _ => panic!("non-FnLike node found: {:?}", node),
         }
index d0acaf674ae74f12b0b8b2afd32db4a53575b3b8..2b286ee1b97fb222948e28187d1ba277f0a4d0f2 100644 (file)
@@ -177,9 +177,9 @@ pub fn evaluate(&self,
         for command in self.subcommands.iter().chain(Some(self)).rev() {
             if let Some(ref condition) = command.condition {
                 if !attr::eval_condition(condition, &tcx.sess.parse_sess, &mut |c| {
-                    c.ident_str().map_or(false, |name| {
+                    c.ident().map_or(false, |ident| {
                         options.contains(&(
-                            name.to_string(),
+                            ident.to_string(),
                             c.value_str().map(|s| s.as_str().to_string())
                         ))
                     })
index c3223f0cd6331d9c8c1088b9b51d58384294a033..90f62a4d132c7c1731a9c93d751090cda5ff70f7 100644 (file)
@@ -292,11 +292,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for SupertraitDefIds<'cx, 'gcx, 'tcx> {
     type Item = DefId;
 
     fn next(&mut self) -> Option<DefId> {
-        let def_id = match self.stack.pop() {
-            Some(def_id) => def_id,
-            None => { return None; }
-        };
-
+        let def_id = self.stack.pop()?;
         let predicates = self.tcx.super_predicates_of(def_id);
         let visited = &mut self.visited;
         self.stack.extend(
index d732f3ff04086eb6c8692a24a4bd773ad188200a..963b4b439f84da38c29f6641142de6c6e617b786 100644 (file)
@@ -104,33 +104,6 @@ pub fn is_ty_uninhabited_from_all_modules(self, ty: Ty<'tcx>) -> bool {
     fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest {
         ty.uninhabited_from(self)
     }
-
-    pub fn is_enum_variant_uninhabited_from(self,
-                                            module: DefId,
-                                            variant: &'tcx VariantDef,
-                                            substs: SubstsRef<'tcx>)
-                                            -> bool
-    {
-        self.variant_inhabitedness_forest(variant, substs).contains(self, module)
-    }
-
-    pub fn is_variant_uninhabited_from_all_modules(self,
-                                                   variant: &'tcx VariantDef,
-                                                   substs: SubstsRef<'tcx>)
-                                                   -> bool
-    {
-        !self.variant_inhabitedness_forest(variant, substs).is_empty()
-    }
-
-    fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: SubstsRef<'tcx>)
-                                    -> DefIdForest {
-        // Determine the ADT kind:
-        let adt_def_id = self.adt_def_id_of_variant(variant);
-        let adt_kind = self.adt_def(adt_def_id).adt_kind();
-
-        // Compute inhabitedness forest:
-        variant.uninhabited_from(self, substs, adt_kind)
-    }
 }
 
 impl<'a, 'gcx, 'tcx> AdtDef {
@@ -148,7 +121,7 @@ fn uninhabited_from(
 
 impl<'a, 'gcx, 'tcx> VariantDef {
     /// Calculate the forest of DefIds from which this variant is visibly uninhabited.
-    fn uninhabited_from(
+    pub fn uninhabited_from(
         &self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
         substs: SubstsRef<'tcx>,
index 995e85fc5f4db557cf54dd8d0729986985a12bc5..f54e69f352a4ed481a0436086f5de8a448e7f4d4 100644 (file)
@@ -150,9 +150,7 @@ pub fn is_inline<'a>(
             _ => return true
         };
         match tcx.def_key(def_id).disambiguated_data.data {
-            DefPathData::StructCtor |
-            DefPathData::EnumVariant(..) |
-            DefPathData::ClosureExpr => true,
+            DefPathData::Ctor | DefPathData::ClosureExpr => true,
             _ => false
         }
     }
index 91b84b68802b1366556b50b81af1ea5e3ada7fb8..f0045136f41bfc7f0b6016e3f896646a54d03052 100644 (file)
@@ -6,9 +6,8 @@
 
 use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap};
 use crate::hir::{HirId, Node};
-use crate::hir::def::{Def, CtorKind, ExportMap};
+use crate::hir::def::{Def, CtorOf, CtorKind, ExportMap};
 use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use crate::hir::map::DefPathData;
 use rustc_data_structures::svh::Svh;
 use rustc_macros::HashStable;
 use crate::ich::Fingerprint;
@@ -1775,12 +1774,19 @@ pub struct Destructor {
     #[derive(HashStable)]
     pub struct AdtFlags: u32 {
         const NO_ADT_FLAGS        = 0;
+        /// Indicates whether the ADT is an enum.
         const IS_ENUM             = 1 << 0;
+        /// Indicates whether the ADT is a union.
         const IS_UNION            = 1 << 1;
+        /// Indicates whether the ADT is a struct.
         const IS_STRUCT           = 1 << 2;
+        /// Indicates whether the ADT is a struct and has a constructor.
         const HAS_CTOR            = 1 << 3;
+        /// Indicates whether the type is a `PhantomData`.
         const IS_PHANTOM_DATA     = 1 << 4;
+        /// Indicates whether the type has a `#[fundamental]` attribute.
         const IS_FUNDAMENTAL      = 1 << 5;
+        /// Indicates whether the type is a `Box`.
         const IS_BOX              = 1 << 6;
         /// Indicates whether the type is an `Arc`.
         const IS_ARC              = 1 << 7;
@@ -1801,55 +1807,73 @@ pub struct VariantFlags: u32 {
     }
 }
 
+/// Definition of a variant -- a struct's fields or a enum variant.
 #[derive(Debug)]
 pub struct VariantDef {
-    /// The variant's `DefId`. If this is a tuple-like struct,
-    /// this is the `DefId` of the struct's ctor.
-    pub did: DefId,
-    pub ident: Ident, // struct's name if this is a struct
+    /// `DefId` that identifies the variant itself.
+    /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
+    pub def_id: DefId,
+    /// `DefId` that identifies the variant's constructor.
+    /// If this variant is a struct variant, then this is `None`.
+    pub ctor_def_id: Option<DefId>,
+    /// Variant or struct name.
+    pub ident: Ident,
+    /// Discriminant of this variant.
     pub discr: VariantDiscr,
+    /// Fields of this variant.
     pub fields: Vec<FieldDef>,
+    /// Type of constructor of variant.
     pub ctor_kind: CtorKind,
+    /// Flags of the variant (e.g. is field list non-exhaustive)?
     flags: VariantFlags,
+    /// Recovered?
     pub recovered: bool,
 }
 
 impl<'a, 'gcx, 'tcx> VariantDef {
     /// Creates a new `VariantDef`.
     ///
-    /// - `did` is the `DefId` used for the variant.
-    /// This is the constructor `DefId` for tuple stucts, and the variant `DefId` for everything
-    /// else.
-    /// - `attribute_def_id` is the DefId that has the variant's attributes.
-    /// This is the struct `DefId` for structs, and the variant `DefId` for variants.
+    /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
+    /// represents an enum variant).
+    ///
+    /// `ctor_did` is the `DefId` that identifies the constructor of unit or
+    /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`.
     ///
-    /// Note that we *could* use the constructor `DefId`, because the constructor attributes
-    /// redirect to the base attributes, but compiling a small crate requires
-    /// loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
+    /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that
+    /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having
+    /// to go through the redirect of checking the ctor's attributes - but compiling a small crate
+    /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
     /// built-in trait), and we do not want to load attributes twice.
     ///
     /// If someone speeds up attribute loading to not be a performance concern, they can
     /// remove this hack and use the constructor `DefId` everywhere.
     pub fn new(
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        did: DefId,
         ident: Ident,
+        variant_did: Option<DefId>,
+        ctor_def_id: Option<DefId>,
         discr: VariantDiscr,
         fields: Vec<FieldDef>,
-        adt_kind: AdtKind,
         ctor_kind: CtorKind,
-        attribute_def_id: DefId,
+        adt_kind: AdtKind,
+        parent_did: DefId,
         recovered: bool,
     ) -> Self {
-        debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr,
-               fields, adt_kind, ctor_kind, attribute_def_id);
+        debug!(
+            "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?},
+             fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})",
+             ident, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did,
+        );
+
         let mut flags = VariantFlags::NO_VARIANT_FLAGS;
-        if adt_kind == AdtKind::Struct && tcx.has_attr(attribute_def_id, "non_exhaustive") {
-            debug!("found non-exhaustive field list for {:?}", did);
+        if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, "non_exhaustive") {
+            debug!("found non-exhaustive field list for {:?}", parent_did);
             flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
         }
+
         VariantDef {
-            did,
+            def_id: variant_did.unwrap_or(parent_did),
+            ctor_def_id,
             ident,
             discr,
             fields,
@@ -1859,6 +1883,7 @@ pub fn new(
         }
     }
 
+    /// Is this field list non-exhaustive?
     #[inline]
     pub fn is_field_list_non_exhaustive(&self) -> bool {
         self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
@@ -1866,7 +1891,8 @@ pub fn is_field_list_non_exhaustive(&self) -> bool {
 }
 
 impl_stable_hash_for!(struct VariantDef {
-    did,
+    def_id,
+    ctor_def_id,
     ident -> (ident.name),
     discr,
     fields,
@@ -1898,12 +1924,15 @@ pub struct FieldDef {
 
 /// The definition of an abstract data type -- a struct or enum.
 ///
-/// These are all interned (by `intern_adt_def`) into the `adt_defs`
-/// table.
+/// These are all interned (by `intern_adt_def`) into the `adt_defs` table.
 pub struct AdtDef {
+    /// `DefId` of the struct, enum or union item.
     pub did: DefId,
+    /// Variants of the ADT. If this is a struct or enum, then there will be a single variant.
     pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
+    /// Flags of the ADT (e.g. is this a struct? is this non-exhaustive?)
     flags: AdtFlags,
+    /// Repr options provided by the user.
     pub repr: ReprOptions,
 }
 
@@ -2102,11 +2131,14 @@ pub fn inhibit_union_abi_opt(&self) -> bool {
 }
 
 impl<'a, 'gcx, 'tcx> AdtDef {
-    fn new(tcx: TyCtxt<'_, '_, '_>,
-           did: DefId,
-           kind: AdtKind,
-           variants: IndexVec<VariantIdx, VariantDef>,
-           repr: ReprOptions) -> Self {
+    /// Creates a new `AdtDef`.
+    fn new(
+        tcx: TyCtxt<'_, '_, '_>,
+        did: DefId,
+        kind: AdtKind,
+        variants: IndexVec<VariantIdx, VariantDef>,
+        repr: ReprOptions
+    ) -> Self {
         debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
 
@@ -2120,13 +2152,8 @@ fn new(tcx: TyCtxt<'_, '_, '_>,
             AdtKind::Struct => AdtFlags::IS_STRUCT,
         };
 
-        if let AdtKind::Struct = kind {
-            let variant_def = &variants[VariantIdx::new(0)];
-            let def_key = tcx.def_key(variant_def.did);
-            match def_key.disambiguated_data.data {
-                DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR,
-                _ => (),
-            }
+        if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_def_id.is_some() {
+            flags |= AdtFlags::HAS_CTOR;
         }
 
         let attrs = tcx.get_attrs(did);
@@ -2154,21 +2181,25 @@ fn new(tcx: TyCtxt<'_, '_, '_>,
         }
     }
 
+    /// Returns `true` if this is a struct.
     #[inline]
     pub fn is_struct(&self) -> bool {
         self.flags.contains(AdtFlags::IS_STRUCT)
     }
 
+    /// Returns `true` if this is a union.
     #[inline]
     pub fn is_union(&self) -> bool {
         self.flags.contains(AdtFlags::IS_UNION)
     }
 
+    /// Returns `true` if this is a enum.
     #[inline]
     pub fn is_enum(&self) -> bool {
         self.flags.contains(AdtFlags::IS_ENUM)
     }
 
+    /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`.
     #[inline]
     pub fn is_variant_list_non_exhaustive(&self) -> bool {
         self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
@@ -2186,6 +2217,7 @@ pub fn adt_kind(&self) -> AdtKind {
         }
     }
 
+    /// Returns a description of this abstract data type.
     pub fn descr(&self) -> &'static str {
         match self.adt_kind() {
             AdtKind::Struct => "struct",
@@ -2194,6 +2226,7 @@ pub fn descr(&self) -> &'static str {
         }
     }
 
+    /// Returns a description of a variant of this abstract data type.
     #[inline]
     pub fn variant_descr(&self) -> &'static str {
         match self.adt_kind() {
@@ -2267,24 +2300,30 @@ pub fn is_payloadfree(&self) -> bool {
     }
 
     pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
-        self.variants
-            .iter()
-            .find(|v| v.did == vid)
+        self.variants.iter().find(|v| v.def_id == vid)
             .expect("variant_with_id: unknown variant")
     }
 
+    pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef {
+        self.variants.iter().find(|v| v.ctor_def_id == Some(cid))
+            .expect("variant_with_ctor_id: unknown variant")
+    }
+
     pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
-        self.variants
-            .iter_enumerated()
-            .find(|(_, v)| v.did == vid)
-            .expect("variant_index_with_id: unknown variant")
-            .0
+        self.variants.iter_enumerated().find(|(_, v)| v.def_id == vid)
+            .expect("variant_index_with_id: unknown variant").0
+    }
+
+    pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx {
+        self.variants.iter_enumerated().find(|(_, v)| v.ctor_def_id == Some(cid))
+            .expect("variant_index_with_ctor_id: unknown variant").0
     }
 
     pub fn variant_of_def(&self, def: Def) -> &VariantDef {
         match def {
-            Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
-            Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
+            Def::Variant(vid) => self.variant_with_id(vid),
+            Def::Ctor(cid, ..) => self.variant_with_ctor_id(cid),
+            Def::Struct(..) | Def::Union(..) |
             Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
             Def::SelfCtor(..) => self.non_enum_variant(),
             _ => bug!("unexpected def {:?} in variant_of_def", def)
@@ -2820,7 +2859,7 @@ pub fn field_index(self, hir_id: hir::HirId, tables: &TypeckTables<'_>) -> usize
 
     pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
         variant.fields.iter().position(|field| {
-            self.adjust_ident(ident, variant.did, hir::DUMMY_HIR_ID).0 == field.ident.modern()
+            self.adjust_ident(ident, variant.def_id, hir::DUMMY_HIR_ID).0 == field.ident.modern()
         })
     }
 
@@ -2895,50 +2934,41 @@ pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
     // or variant or their constructors, panics otherwise.
     pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
         match def {
-            Def::Variant(did) | Def::VariantCtor(did, ..) => {
+            Def::Variant(did) => {
                 let enum_did = self.parent(did).unwrap();
                 self.adt_def(enum_did).variant_with_id(did)
             }
             Def::Struct(did) | Def::Union(did) => {
                 self.adt_def(did).non_enum_variant()
             }
-            Def::StructCtor(ctor_did, ..) => {
-                let did = self.parent(ctor_did).expect("struct ctor has no parent");
-                self.adt_def(did).non_enum_variant()
+            Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => {
+                let variant_did = self.parent(variant_ctor_did).unwrap();
+                let enum_did = self.parent(variant_did).unwrap();
+                self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did)
+            }
+            Def::Ctor(ctor_did, CtorOf::Struct, ..) => {
+                let struct_did = self.parent(ctor_did).expect("struct ctor has no parent");
+                self.adt_def(struct_did).non_enum_variant()
             }
             _ => bug!("expect_variant_def used with unexpected def {:?}", def)
         }
     }
 
-    /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part.
-    pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId {
-        let def_key = self.def_key(variant_def.did);
-        match def_key.disambiguated_data.data {
-            // for enum variants and tuple structs, the def-id of the ADT itself
-            // is the *parent* of the variant
-            DefPathData::EnumVariant(..) | DefPathData::StructCtor =>
-                DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() },
-
-            // otherwise, for structs and unions, they share a def-id
-            _ => variant_def.did,
-        }
-    }
-
     pub fn item_name(self, id: DefId) -> InternedString {
         if id.index == CRATE_DEF_INDEX {
             self.original_crate_name(id.krate).as_interned_str()
         } else {
             let def_key = self.def_key(id);
-            // The name of a StructCtor is that of its struct parent.
-            if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data {
-                self.item_name(DefId {
-                    krate: id.krate,
-                    index: def_key.parent.unwrap()
-                })
-            } else {
-                def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| {
+            match def_key.disambiguated_data.data {
+                // The name of a constructor is that of its parent.
+                hir_map::DefPathData::Ctor =>
+                    self.item_name(DefId {
+                        krate: id.krate,
+                        index: def_key.parent.unwrap()
+                    }),
+                _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| {
                     bug!("item_name: no name for {:?}", self.def_path(id));
-                })
+                }),
             }
         }
     }
index 7701a10d8eeeeef66562e920f0bfe7b7ea4d301c..c9a4961a8e044cabfabbe53fb0ff850a0a6eb31e 100644 (file)
@@ -285,14 +285,18 @@ fn try_print_visible_def_path(
         let mut cur_def_key = self.tcx().def_key(def_id);
         debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
 
-        // For a UnitStruct or TupleStruct we want the name of its parent rather than <unnamed>.
-        if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data {
-            let parent = DefId {
-                krate: def_id.krate,
-                index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"),
-            };
+        // For a constructor we want the name of its parent rather than <unnamed>.
+        match cur_def_key.disambiguated_data.data {
+            DefPathData::Ctor => {
+                let parent = DefId {
+                    krate: def_id.krate,
+                    index: cur_def_key.parent
+                        .expect("DefPathData::Ctor/VariantData missing a parent"),
+                };
 
-            cur_def_key = self.tcx().def_key(parent);
+                cur_def_key = self.tcx().def_key(parent);
+            },
+            _ => {},
         }
 
         let visible_parent = match visible_parent_map.get(&def_id).cloned() {
@@ -860,7 +864,7 @@ fn guess_def_namespace(self, def_id: DefId) -> Namespace {
             DefPathData::AnonConst |
             DefPathData::ConstParam(..) |
             DefPathData::ClosureExpr |
-            DefPathData::StructCtor => Namespace::ValueNS,
+            DefPathData::Ctor => Namespace::ValueNS,
 
             DefPathData::MacroDef(..) => Namespace::MacroNS,
 
@@ -1024,7 +1028,7 @@ fn path_append(
 
         // Skip `::{{constructor}}` on tuple/unit structs.
         match disambiguated_data.data {
-            DefPathData::StructCtor => return Ok(self),
+            DefPathData::Ctor => return Ok(self),
             _ => {}
         }
 
index d8159f11acec0e84969e91dd9b2850df5df155bb..5cb5a0030f4eb916f63d3c3a10e73036540e41e6 100644 (file)
@@ -305,12 +305,6 @@ fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>) -> Cow<'static, str> {
-        format!("erasing regions from `{:?}`", ty).into()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> Cow<'static, str> {
         let id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -431,12 +425,6 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "getting a list of all mir_keys".into()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>, instance: ty::Instance<'tcx>) -> Cow<'static, str> {
         format!("computing the symbol for `{}`", instance).into()
@@ -617,12 +605,6 @@ fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::lint_levels<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "computing the lint levels for items in this crate".into()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::specializes<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (DefId, DefId)) -> Cow<'static, str> {
         "computing whether impls specialize one another".into()
@@ -898,21 +880,6 @@ fn try_load_from_disk(tcx: TyCtxt<'_, 'tcx, 'tcx>,
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::optimized_mir<'tcx> {
-    #[inline]
-    fn cache_on_disk(_: TyCtxt<'_, 'tcx, 'tcx>, def_id: Self::Key) -> bool {
-        def_id.is_local()
-    }
-
-    fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              id: SerializedDepNodeIndex)
-                              -> Option<Self::Value> {
-        let mir: Option<crate::mir::Mir<'tcx>> = tcx.queries.on_disk_cache
-                                               .try_load_query_result(tcx, id);
-        mir.map(|x| tcx.alloc_mir(x))
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, SubstsRef<'tcx>)) -> Cow<'static, str> {
         format!("testing substituted normalized predicates:`{}`", tcx.def_path_str(key.0)).into()
@@ -937,33 +904,9 @@ fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static,
     }
 }
 
-impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        "generating chalk-style clauses".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: traits::Environment<'tcx>) -> Cow<'static, str> {
-        "generating chalk-style clauses for environment".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::environment<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
-        "return a chalk-style environment".into()
-    }
-}
-
-impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "wasm import module map".into()
-    }
-}
-
 impl<'tcx> QueryDescription<'tcx> for queries::dllimport_foreign_items<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
-        "wasm import module map".into()
+        "dllimport_foreign_items".into()
     }
 }
 
@@ -997,7 +940,6 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 impl_disk_cacheable_query!(unsafety_check_result, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(borrowck, |_, def_id| def_id.is_local());
-impl_disk_cacheable_query!(mir_const_qualif, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(check_match, |_, def_id| def_id.is_local());
 impl_disk_cacheable_query!(def_symbol_name, |_, _| true);
 impl_disk_cacheable_query!(predicates_of, |_, def_id| def_id.is_local());
index a2d7815920e0b2418d63b3da4965578a9bd62949..85c2afd1159a1ec421a6586e078fcc4125deddff 100644 (file)
         [] fn inherent_impls: InherentImpls(DefId) -> Lrc<Vec<DefId>>,
     },
 
-    Codegen {
-        /// Set of all the `DefId`s in this crate that have MIR associated with
-        /// them. This includes all the body owners, but also things like struct
-        /// constructors.
-        [] fn mir_keys: mir_keys(CrateNum) -> Lrc<DefIdSet>,
-
-        /// Maps DefId's that have an associated Mir to the result
-        /// of the MIR qualify_consts pass. The actual meaning of
-        /// the value isn't known except to the pass itself.
-        [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Lrc<BitSet<mir::Local>>),
-
-        /// Fetch the MIR for a given `DefId` right after it's built - this includes
-        /// unreachable code.
-        [] fn mir_built: MirBuilt(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
-
-        /// Fetch the MIR for a given `DefId` up till the point where it is
-        /// ready for const evaluation.
-        ///
-        /// See the README for the `mir` module for details.
-        [no_hash] fn mir_const: MirConst(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
-
-        [no_hash] fn mir_validated: MirValidated(DefId) -> &'tcx Steal<mir::Mir<'tcx>>,
-
-        /// MIR after our optimization passes have run. This is MIR that is ready
-        /// for codegen. This is also the only query that can fetch non-local MIR, at present.
-        [] fn optimized_mir: MirOptimized(DefId) -> &'tcx mir::Mir<'tcx>,
-    },
-
     TypeChecking {
         /// The result of unsafety-checking this `DefId`.
         [] fn unsafety_check_result: UnsafetyCheckResult(DefId) -> mir::UnsafetyCheckResult,
 
     Other {
         [] fn module_exports: ModuleExports(DefId) -> Option<Lrc<Vec<Export>>>,
-        [] fn lint_levels: lint_levels_node(CrateNum) -> Lrc<lint::LintLevelMap>,
     },
 
     TypeChecking {
     },
 
     TypeChecking {
-        // Erases regions from `ty` to yield a new type.
-        // Normally you would just use `tcx.erase_regions(&value)`,
-        // however, which uses this query as a kind of cache.
-        [] fn erase_regions_ty: erase_regions_ty(Ty<'tcx>) -> Ty<'tcx>,
-
         /// Do not call this query directly: invoke `normalize` instead.
         [] fn normalize_projection_ty: NormalizeProjectionTy(
             CanonicalProjectionGoal<'tcx>
 
         [] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
     },
-
-    TypeChecking {
-        [] fn program_clauses_for: ProgramClausesFor(DefId) -> Clauses<'tcx>,
-
-        [] fn program_clauses_for_env: ProgramClausesForEnv(
-            traits::Environment<'tcx>
-        ) -> Clauses<'tcx>,
-
-        // Get the chalk-style environment of the given item.
-        [] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
-    },
-
-    Linking {
-        [] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
-            -> Lrc<FxHashMap<DefId, String>>,
-    },
 ]}
 
 //////////////////////////////////////////////////////////////////////
@@ -741,10 +691,6 @@ fn codegen_fn_attrs<'tcx>(id: DefId) -> DepConstructor<'tcx> {
     DepConstructor::CodegenFnAttrs { 0: id }
 }
 
-fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
-    DepConstructor::EraseRegionsTy { ty }
-}
-
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
     DepConstructor::TypeParamPredicates {
         item_id,
@@ -795,10 +741,6 @@ fn const_eval_raw_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>
     DepConstructor::ConstEvalRaw { param_env }
 }
 
-fn mir_keys<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::MirKeys
-}
-
 fn crate_variances<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::CrateVariances
 }
@@ -823,10 +765,6 @@ fn layout_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConst
     DepConstructor::Layout { param_env }
 }
 
-fn lint_levels_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
-    DepConstructor::LintLevels
-}
-
 fn specializes_node<'tcx>((a, b): (DefId, DefId)) -> DepConstructor<'tcx> {
     DepConstructor::Specializes { impl1: a, impl2: b }
 }
index e82e09c29976564d9ff17e35f1d31d6738275cac..adac19d3410b22e71e925d29aeadeb3df48269ad 100644 (file)
@@ -1223,7 +1223,6 @@ macro_rules! force {
         DepKind::CompileCodegenUnit |
         DepKind::FulfillObligation |
         DepKind::VtableMethods |
-        DepKind::EraseRegionsTy |
         DepKind::NormalizeProjectionTy |
         DepKind::NormalizeTyAfterErasingRegions |
         DepKind::ImpliedOutlivesBounds |
@@ -1240,11 +1239,7 @@ macro_rules! force {
         DepKind::TypeOpNormalizeFnSig |
         DepKind::SubstituteNormalizeAndTestPredicates |
         DepKind::MethodAutoderefSteps |
-        DepKind::InstanceDefSizeEstimate |
-        DepKind::ProgramClausesForEnv |
-
-        // This one should never occur in this context
-        DepKind::Null => {
+        DepKind::InstanceDefSizeEstimate => {
             bug!("force_from_dep_node() - Encountered {:?}", dep_node)
         }
 
@@ -1262,11 +1257,6 @@ macro_rules! force {
         },
         DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
         DepKind::CheckPrivateInPublic => { force!(check_private_in_public, LOCAL_CRATE); }
-        DepKind::MirBuilt => { force!(mir_built, def_id!()); }
-        DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
-        DepKind::MirConst => { force!(mir_const, def_id!()); }
-        DepKind::MirValidated => { force!(mir_validated, def_id!()); }
-        DepKind::MirOptimized => { force!(optimized_mir, def_id!()); }
 
         DepKind::BorrowCheck => { force!(borrowck, def_id!()); }
         DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
@@ -1282,7 +1272,6 @@ macro_rules! force {
         DepKind::CheckModImplWf => { force!(check_mod_impl_wf, def_id!()); }
         DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
         DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
-        DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
         DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
         DepKind::AssociatedItems => { force!(associated_item, def_id!()); }
         DepKind::PredicatesDefinedOnItem => { force!(predicates_defined_on, def_id!()); }
@@ -1317,7 +1306,6 @@ macro_rules! force {
         DepKind::CheckMatch => { force!(check_match, def_id!()); }
 
         DepKind::ParamEnv => { force!(param_env, def_id!()); }
-        DepKind::Environment => { force!(environment, def_id!()); }
         DepKind::DescribeDef => { force!(describe_def, def_id!()); }
         DepKind::DefSpan => { force!(def_span, def_id!()); }
         DepKind::LookupStability => { force!(lookup_stability, def_id!()); }
@@ -1344,7 +1332,6 @@ macro_rules! force {
         DepKind::HasGlobalAllocator => { force!(has_global_allocator, krate!()); }
         DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); }
         DepKind::ExternCrate => { force!(extern_crate, def_id!()); }
-        DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); }
         DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); }
         DepKind::ModuleExports => { force!(module_exports, def_id!()); }
         DepKind::IsSanitizerRuntime => { force!(is_sanitizer_runtime, krate!()); }
@@ -1425,8 +1412,6 @@ macro_rules! force {
 
         DepKind::Features => { force!(features_query, LOCAL_CRATE); }
 
-        DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
-        DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
         DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
 
         DepKind::UpstreamMonomorphizations => {
@@ -1491,11 +1476,11 @@ pub fn load_from_on_disk_cache(&self, tcx: TyCtxt<'_, '_, '_>) {
 
 impl_load_from_cache!(
     TypeckTables => typeck_tables_of,
-    MirOptimized => optimized_mir,
+    optimized_mir => optimized_mir,
     UnsafetyCheckResult => unsafety_check_result,
     BorrowCheck => borrowck,
     MirBorrowCheck => mir_borrowck,
-    MirConstQualif => mir_const_qualif,
+    mir_const_qualif => mir_const_qualif,
     SymbolName => def_symbol_name,
     ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
     CheckMatch => check_match,
index 4fb2bfb075c8f0819fd8a6923902231f90e026bf..ccead14e76b23ea68da5e34d49f32d69ce5cdca8 100644 (file)
@@ -549,8 +549,8 @@ pub fn is_trait_alias(self, def_id: DefId) -> bool {
 
     /// Returns `true` if this `DefId` refers to the implicit constructor for
     /// a tuple struct like `struct Foo(u32)`, and `false` otherwise.
-    pub fn is_struct_constructor(self, def_id: DefId) -> bool {
-        self.def_key(def_id).disambiguated_data.data == DefPathData::StructCtor
+    pub fn is_constructor(self, def_id: DefId) -> bool {
+        self.def_key(def_id).disambiguated_data.data == DefPathData::Ctor
     }
 
     /// Given the `DefId` of a fn or closure, returns the `DefId` of
index 4e1d360562d9d22fbb3a067fe6f44a8985519d42..fe39e3ae0c6cde9ba7118618d8a27d654a6daf63 100644 (file)
@@ -34,6 +34,7 @@
 use std::rc::Rc;
 use rustc_data_structures::sync::Lrc;
 use std::hash::{Hash, Hasher};
+use syntax::source_map::CompilerDesugaringKind;
 use syntax_pos::{MultiSpan, Span};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
@@ -85,8 +86,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
     let owner_id = tcx.hir().as_local_hir_id(owner_def_id).unwrap();
 
     match tcx.hir().get_by_hir_id(owner_id) {
-        Node::StructCtor(_) |
-        Node::Variant(_) => {
+        Node::Ctor(..) => {
             // We get invoked with anything that has MIR, but some of
             // those things (notably the synthesized constructors from
             // tuple structs/variants) do not have an associated body
@@ -744,6 +744,19 @@ pub fn report_use_of_moved_value(&self,
                 },
                 moved_lp.ty));
         }
+        if let (Some(CompilerDesugaringKind::ForLoop), Ok(snippet)) = (
+            move_span.compiler_desugaring_kind(),
+            self.tcx.sess.source_map().span_to_snippet(move_span),
+         ) {
+            if !snippet.starts_with("&") {
+                err.span_suggestion(
+                    move_span,
+                    "consider borrowing this to avoid moving it into the for loop",
+                    format!("&{}", snippet),
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        }
 
         // Note: we used to suggest adding a `ref binding` or calling
         // `clone` but those suggestions have been removed because
index ddcbf29da832b95dd9bab76446e1eb00b91498d1..8efa025e3dd9d4bfb07637bd3d26bb627fa30b50 100644 (file)
@@ -1156,12 +1156,14 @@ fn prepare_union_metadata(
 // Enums
 //=-----------------------------------------------------------------------------
 
-// DWARF variant support is only available starting in LLVM 7.
+// DWARF variant support is only available starting in LLVM 8.
 // Although the earlier enum debug info output did not work properly
 // in all situations, it is better for the time being to continue to
 // sometimes emit the old style rather than emit something completely
-// useless when rust is compiled against LLVM 6 or older.  This
-// function decides which representation will be emitted.
+// useless when rust is compiled against LLVM 6 or older. LLVM 7
+// contains an early version of the DWARF variant support, and will
+// crash when handling the new debug info format. This function
+// decides which representation will be emitted.
 fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
     // On MSVC we have to use the fallback mode, because LLVM doesn't
     // lower variant parts to PDB.
index a8d272f157ce3367f843e646fcfb60c7d7699a8c..04e65ac4233002b3796957ebdd3443a54928cbb8 100644 (file)
@@ -88,7 +88,7 @@ unsafe fn unpack(
 pub struct InlineAsmDiagnostic<'ll> {
     pub cookie: c_uint,
     pub message: &'ll Twine,
-    pub instruction: &'ll Value,
+    pub instruction: Option<&'ll Value>,
 }
 
 impl InlineAsmDiagnostic<'ll> {
@@ -107,7 +107,7 @@ unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
         InlineAsmDiagnostic {
             cookie,
             message: message.unwrap(),
-            instruction: instruction.unwrap(),
+            instruction,
         }
     }
 }
index 35fd30f34ad24e2a248224ff8fc6e73ce99cb3f7..4774f8fe5a380b97bc4aad9a406e50bd8d27d8bf 100644 (file)
@@ -1,7 +1,7 @@
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
-use rustc::mir;
+use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
 use rustc::mir::interpret::EvalErrorKind;
 use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
 use rustc_target::spec::abi::Abi;
@@ -621,15 +621,23 @@ fn codegen_call_terminator<'b>(
                         // but specified directly in the code. This means it gets promoted
                         // and we can then extract the value by evaluating the promoted.
                         mir::Operand::Copy(
-                            mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+                            Place::Base(
+                                PlaceBase::Static(
+                                    box Static { kind: StaticKind::Promoted(promoted), ty }
+                                )
+                            )
                         ) |
                         mir::Operand::Move(
-                            mir::Place::Base(mir::PlaceBase::Promoted(box(index, ty)))
+                            Place::Base(
+                                PlaceBase::Static(
+                                    box Static { kind: StaticKind::Promoted(promoted), ty }
+                                )
+                            )
                         ) => {
                             let param_env = ty::ParamEnv::reveal_all();
                             let cid = mir::interpret::GlobalId {
                                 instance: self.instance,
-                                promoted: Some(index),
+                                promoted: Some(promoted),
                             };
                             let c = bx.tcx().const_eval(param_env.and(cid));
                             let (llval, ty) = self.simd_shuffle_indices(
index 0408ccf039f340093dde20b6a4979e4cdebde86d..7cafa0088a01270961b763c7827f0822fb7f8f5f 100644 (file)
@@ -408,11 +408,15 @@ pub fn codegen_place(
 
         let result = match *place {
             mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
-            mir::Place::Base(mir::PlaceBase::Promoted(box (index, ty))) => {
+            mir::Place::Base(
+                mir::PlaceBase::Static(
+                    box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) }
+                )
+            ) => {
                 let param_env = ty::ParamEnv::reveal_all();
                 let cid = mir::interpret::GlobalId {
                     instance: self.instance,
-                    promoted: Some(index),
+                    promoted: Some(promoted),
                 };
                 let layout = cx.layout_of(self.monomorphize(&ty));
                 match bx.tcx().const_eval(param_env.and(cid)) {
@@ -435,7 +439,11 @@ pub fn codegen_place(
                     }
                 }
             }
-            mir::Place::Base(mir::PlaceBase::Static(box mir::Static { def_id, ty })) => {
+            mir::Place::Base(
+                mir::PlaceBase::Static(
+                    box mir::Static { ty, kind: mir::StaticKind::Static(def_id) }
+                )
+            ) => {
                 // NB: The layout of a static may be unsized as is the case when working
                 // with a static that is an extern_type.
                 let layout = cx.layout_of(self.monomorphize(&ty));
index 0fa935199f97b412e2d9125121b73e6c1d39495f..ebd48f0ae1e2b751a3fa63f9eb9a37fbaca47efb 100644 (file)
@@ -522,7 +522,7 @@ fn path_append(
 
         // Skip `::{{constructor}}` on tuple/unit structs.
         match disambiguated_data.data {
-            DefPathData::StructCtor => return Ok(self),
+            DefPathData::Ctor => return Ok(self),
             _ => {}
         }
 
index dde88a212408deee9f443ca006401849f905f1d0..ace5198deaf2edb7794520853125c882f227dd50 100644 (file)
@@ -633,10 +633,20 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
     let body = tcx.hir().body(body_id);
     let cfg = cfg::CFG::new(tcx, &body);
     let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
+    let hir_id = code.id();
+    // We have to disassemble the hir_id because name must be ASCII
+    // alphanumeric. This does not appear in the rendered graph, so it does not
+    // have to be user friendly.
+    let name = format!(
+        "hir_id_{}_{}_{}",
+        hir_id.owner.address_space().index(),
+        hir_id.owner.as_array_index(),
+        hir_id.local_id.index(),
+    );
     let lcfg = LabelledCFG {
         tcx,
         cfg: &cfg,
-        name: format!("node_{}", code.id()),
+        name,
         labelled_edges,
     };
 
index 6b5e19ca49b76eccb1facbec1ec124eaf42ea69f..46e2582ac3ba00f4de09a1ccac7f11167db62e04 100644 (file)
     label_strs::ImplTraitRef,
 ];
 
-/// DepNodes for MirBuilt/Optimized, which is relevant in "executable"
+/// DepNodes for mir_built/Optimized, which is relevant in "executable"
 /// code, i.e., functions+methods
 const BASE_MIR: &[&str] = &[
-    label_strs::MirOptimized,
-    label_strs::MirBuilt,
+    label_strs::optimized_mir,
+    label_strs::mir_built,
 ];
 
 /// Struct, Enum and Union DepNodes
@@ -576,8 +576,8 @@ fn expect_associated_value(tcx: TyCtxt<'_, '_, '_>, item: &NestedMetaItem) -> as
     if let Some(value) = item.value_str() {
         value
     } else {
-        let msg = if let Some(name) = item.ident_str() {
-            format!("associated value expected for `{}`", name)
+        let msg = if let Some(ident) = item.ident() {
+            format!("associated value expected for `{}`", ident)
         } else {
             "expected an associated value".to_string()
         };
index 8153653e48b255809dda9f383709c7e20b699680..304e6eb712e3c92bb48c40691f5f98bbec37d272 100644 (file)
@@ -528,7 +528,7 @@ fn check_struct_field(&mut self, cx: &LateContext<'_, '_>, sf: &hir::StructField
 
     fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) {
         self.check_missing_docs_attrs(cx,
-                                      Some(v.node.data.hir_id()),
+                                      Some(v.node.id),
                                       &v.node.attrs,
                                       v.span,
                                       "a variant");
@@ -756,8 +756,9 @@ fn get_lints(&self) -> LintArray {
 
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
+        let name = attr.name_or_empty();
         for &&(n, _, _, ref g) in &self.depr_attrs {
-            if attr.ident_str() == Some(n) {
+            if name == n {
                 if let &AttributeGate::Gated(Stability::Deprecated(link, suggestion),
                                              ref name,
                                              ref reason,
index 648cae30da6c8f14bbf93f01f612011ec75e0b9f..ebbd27798419bdd46d295a9476607e8ff54667ff 100644 (file)
@@ -267,21 +267,21 @@ fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) {
             }
         }
 
-        let name = attr.ident_str();
+        let name = attr.name_or_empty();
         if !attr::is_used(attr) {
             debug!("Emitting warning for: {:?}", attr);
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
             // Is it a builtin attribute that must be used at the crate level?
             let known_crate = BUILTIN_ATTRIBUTES.iter()
                 .find(|&&(builtin, ty, ..)| {
-                    name == Some(builtin) && ty == AttributeType::CrateLevel
+                    name == builtin && ty == AttributeType::CrateLevel
                 })
                 .is_some();
 
             // Has a plugin registered this attribute as one that must be used at
             // the crate level?
             let plugin_crate = plugin_attributes.iter()
-                .find(|&&(ref x, t)| name == Some(x) && AttributeType::CrateLevel == t)
+                .find(|&&(ref x, t)| name == x.as_str() && AttributeType::CrateLevel == t)
                 .is_some();
             if known_crate || plugin_crate {
                 let msg = match attr.style {
index 2fe51a22fb4845463e49754264e764309949e278..6e32a53c364a6502eb20fda0763111a78f7d63ef 100644 (file)
@@ -12,3 +12,4 @@ synstructure = "0.10.1"
 syn = { version = "0.15.22", features = ["full"] }
 proc-macro2 = "0.4.24"
 quote = "0.6.10"
+itertools = "0.8"
index 3849e47d40365befd090493944a98d328cc2f899..bd5be831ff68d537dc72ba82a487fc08cef9f6c3 100644 (file)
@@ -8,6 +8,7 @@
 use syn::punctuated::Punctuated;
 use syn;
 use quote::quote;
+use itertools::Itertools;
 
 #[allow(non_camel_case_types)]
 mod kw {
@@ -41,6 +42,18 @@ enum QueryModifier {
 
     /// A cycle error for this query aborting the compilation with a fatal error.
     FatalCycle,
+
+    /// Don't hash the result, instead just mark a query red if it runs
+    NoHash,
+
+    /// Don't force the query
+    NoForce,
+
+    /// Generate a dep node based on the dependencies of the query
+    Anon,
+
+    // Always evaluate the query, ignoring its depdendencies
+    EvalAlways,
 }
 
 impl Parse for QueryModifier {
@@ -88,6 +101,14 @@ fn parse(input: ParseStream<'_>) -> Result<Self> {
             Ok(QueryModifier::LoadCached(tcx, id, block))
         } else if modifier == "fatal_cycle" {
             Ok(QueryModifier::FatalCycle)
+        } else if modifier == "no_hash" {
+            Ok(QueryModifier::NoHash)
+        } else if modifier == "no_force" {
+            Ok(QueryModifier::NoForce)
+        } else if modifier == "anon" {
+            Ok(QueryModifier::Anon)
+        } else if modifier == "eval_always" {
+            Ok(QueryModifier::EvalAlways)
         } else {
             Err(Error::new(modifier.span(), "unknown query modifier"))
         }
@@ -185,6 +206,18 @@ struct QueryModifiers {
 
     /// A cycle error for this query aborting the compilation with a fatal error.
     fatal_cycle: bool,
+
+    /// Don't hash the result, instead just mark a query red if it runs
+    no_hash: bool,
+
+    /// Don't force the query
+    no_force: bool,
+
+    /// Generate a dep node based on the dependencies of the query
+    anon: bool,
+
+    // Always evaluate the query, ignoring its depdendencies
+    eval_always: bool,
 }
 
 /// Process query modifiers into a struct, erroring on duplicates
@@ -193,6 +226,10 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
     let mut cache = None;
     let mut desc = None;
     let mut fatal_cycle = false;
+    let mut no_hash = false;
+    let mut no_force = false;
+    let mut anon = false;
+    let mut eval_always = false;
     for modifier in query.modifiers.0.drain(..) {
         match modifier {
             QueryModifier::LoadCached(tcx, id, block) => {
@@ -219,6 +256,30 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
                 }
                 fatal_cycle = true;
             }
+            QueryModifier::NoHash => {
+                if no_hash {
+                    panic!("duplicate modifier `no_hash` for query `{}`", query.name);
+                }
+                no_hash = true;
+            }
+            QueryModifier::NoForce => {
+                if no_force {
+                    panic!("duplicate modifier `no_force` for query `{}`", query.name);
+                }
+                no_force = true;
+            }
+            QueryModifier::Anon => {
+                if anon {
+                    panic!("duplicate modifier `anon` for query `{}`", query.name);
+                }
+                anon = true;
+            }
+            QueryModifier::EvalAlways => {
+                if eval_always {
+                    panic!("duplicate modifier `eval_always` for query `{}`", query.name);
+                }
+                eval_always = true;
+            }
         }
     }
     QueryModifiers {
@@ -226,6 +287,10 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
         cache,
         desc,
         fatal_cycle,
+        no_hash,
+        no_force,
+        anon,
+        eval_always,
     }
 }
 
@@ -312,6 +377,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
     let mut query_description_stream = quote! {};
     let mut dep_node_def_stream = quote! {};
     let mut dep_node_force_stream = quote! {};
+    let mut no_force_queries = Vec::new();
 
     for group in groups.0 {
         let mut group_stream = quote! {};
@@ -325,41 +391,83 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
                 _ => quote! { #result_full },
             };
 
+            let mut attributes = Vec::new();
+
             // Pass on the fatal_cycle modifier
-            let fatal_cycle = if modifiers.fatal_cycle {
-                quote! { fatal_cycle }
-            } else {
-                quote! {}
+            if modifiers.fatal_cycle {
+                attributes.push(quote! { fatal_cycle });
             };
+            // Pass on the no_hash modifier
+            if modifiers.no_hash {
+                attributes.push(quote! { no_hash });
+            };
+
+            let mut attribute_stream = quote! {};
+
+            for e in attributes.into_iter().intersperse(quote! {,}) {
+                attribute_stream.extend(e);
+            }
 
             // Add the query to the group
             group_stream.extend(quote! {
-                [#fatal_cycle] fn #name: #name(#arg) #result,
+                [#attribute_stream] fn #name: #name(#arg) #result,
             });
 
-            add_query_description_impl(&query, modifiers, &mut query_description_stream);
+            let mut attributes = Vec::new();
+
+            // Pass on the anon modifier
+            if modifiers.anon {
+                attributes.push(quote! { anon });
+            };
+            // Pass on the eval_always modifier
+            if modifiers.eval_always {
+                attributes.push(quote! { eval_always });
+            };
 
+            let mut attribute_stream = quote! {};
+            for e in attributes.into_iter().intersperse(quote! {,}) {
+                attribute_stream.extend(e);
+            }
             // Create a dep node for the query
             dep_node_def_stream.extend(quote! {
-                [] #name(#arg),
+                [#attribute_stream] #name(#arg),
             });
 
-            // Add a match arm to force the query given the dep node
-            dep_node_force_stream.extend(quote! {
-                DepKind::#name => {
-                    if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
-                        force_ex!($tcx, #name, key);
-                    } else {
-                        return false;
+            if modifiers.no_force {
+                no_force_queries.push(name.clone());
+            } else {
+                // Add a match arm to force the query given the dep node
+                dep_node_force_stream.extend(quote! {
+                    DepKind::#name => {
+                        if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
+                            force_ex!($tcx, #name, key);
+                        } else {
+                            return false;
+                        }
                     }
-                }
-            });
+                });
+            }
+
+            add_query_description_impl(&query, modifiers, &mut query_description_stream);
         }
         let name = &group.name;
         query_stream.extend(quote! {
             #name { #group_stream },
         });
     }
+
+    // Add an arm for the no force queries to panic when trying to force them
+    for query in no_force_queries {
+        dep_node_force_stream.extend(quote! {
+            DepKind::#query |
+        });
+    }
+    dep_node_force_stream.extend(quote! {
+        DepKind::Null => {
+            bug!("Cannot force dep node: {:?}", $dep_node)
+        }
+    });
+
     TokenStream::from(quote! {
         macro_rules! rustc_query_append {
             ([$($macro:tt)*][$($other:tt)*]) => {
index 67a249e605ecc8e4ddb002df2ed1edbd8cfd7930..995532a00cd6e98c91e8a06b8602658bbe27607b 100644 (file)
@@ -407,6 +407,14 @@ pub fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
         self.get_crate_data(def.krate).get_struct_field_names(def.index)
     }
 
+    pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind {
+        self.get_crate_data(def.krate).get_ctor_kind(def.index)
+    }
+
+    pub fn item_attrs_untracked(&self, def: DefId, sess: &Session) -> Lrc<[ast::Attribute]> {
+        self.get_crate_data(def.krate).get_item_attrs(def.index, sess)
+    }
+
     pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export> {
         let mut result = vec![];
         self.get_crate_data(def_id.krate)
index c608c03095aa35f5c00d0c1fdf5c0361a2b8bd8c..fb519407398fe9a1074a216b0cf0ddb5e25d1e86 100644 (file)
@@ -8,7 +8,7 @@
 use rustc::hir;
 use rustc::middle::cstore::LinkagePreference;
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
-use rustc::hir::def::{self, Def, CtorKind};
+use rustc::hir::def::{self, Def, CtorOf, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace,
                          CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId};
 use rustc::hir::map::definitions::DefPathTable;
@@ -544,13 +544,14 @@ pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
         }
     }
 
-    fn get_variant(&self,
-                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                   item: &Entry<'_>,
-                   index: DefIndex,
-                   adt_kind: ty::AdtKind)
-                   -> ty::VariantDef
-    {
+    fn get_variant(
+        &self,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        item: &Entry<'_>,
+        index: DefIndex,
+        parent_did: DefId,
+        adt_kind: ty::AdtKind
+    ) -> ty::VariantDef {
         let data = match item.kind {
             EntryKind::Variant(data) |
             EntryKind::Struct(data, _) |
@@ -558,13 +559,18 @@ fn get_variant(&self,
             _ => bug!(),
         };
 
-        let def_id = self.local_def_id(data.struct_ctor.unwrap_or(index));
-        let attribute_def_id = self.local_def_id(index);
+        let variant_did = if adt_kind == ty::AdtKind::Enum {
+            Some(self.local_def_id(index))
+        } else {
+            None
+        };
+        let ctor_did = data.ctor.map(|index| self.local_def_id(index));
 
         ty::VariantDef::new(
             tcx,
-            def_id,
             Ident::from_interned_str(self.item_name(index)),
+            variant_did,
+            ctor_did,
             data.discr,
             item.children.decode(self).map(|index| {
                 let f = self.entry(index);
@@ -574,9 +580,9 @@ fn get_variant(&self,
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
-            adt_kind,
             data.ctor_kind,
-            attribute_def_id,
+            adt_kind,
+            parent_did,
             false,
         )
     }
@@ -599,11 +605,11 @@ pub fn get_adt_def(&self,
             item.children
                 .decode(self)
                 .map(|index| {
-                    self.get_variant(tcx, &self.entry(index), index, kind)
+                    self.get_variant(tcx, &self.entry(index), index, did, kind)
                 })
                 .collect()
         } else {
-            std::iter::once(self.get_variant(tcx, &item, item_id, kind)).collect()
+            std::iter::once(self.get_variant(tcx, &item, item_id, did, kind)).collect()
         };
 
         tcx.alloc_adt_def(did, kind, variants, repr)
@@ -808,22 +814,22 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
                     // Re-export lists automatically contain constructors when necessary.
                     match def {
                         Def::Struct(..) => {
-                            if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
+                            if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) {
                                 let ctor_kind = self.get_ctor_kind(child_index);
-                                let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
-                                callback(def::Export {
-                                    def: ctor_def,
-                                    vis: self.get_visibility(ctor_def_id.index),
-                                    ident, span,
-                                });
+                                let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Struct, ctor_kind);
+                                let vis = self.get_visibility(ctor_def_id.index);
+                                callback(def::Export { def: ctor_def, vis, ident, span });
                             }
                         }
                         Def::Variant(def_id) => {
                             // Braced variants, unlike structs, generate unusable names in
                             // value namespace, they are reserved for possible future use.
+                            // It's ok to use the variant's id as a ctor id since an
+                            // error will be reported on any use of such resolution anyway.
+                            let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
                             let ctor_kind = self.get_ctor_kind(child_index);
-                            let ctor_def = Def::VariantCtor(def_id, ctor_kind);
-                            let vis = self.get_visibility(child_index);
+                            let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
+                            let vis = self.get_visibility(ctor_def_id.index);
                             callback(def::Export { def: ctor_def, ident, vis, span });
                         }
                         _ => {}
@@ -925,10 +931,13 @@ pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
         }
     }
 
-    pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
+    pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
         match self.entry(node_id).kind {
             EntryKind::Struct(data, _) => {
-                data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
+                data.decode(self).ctor.map(|index| self.local_def_id(index))
+            }
+            EntryKind::Variant(data) => {
+                data.decode(self).ctor.map(|index| self.local_def_id(index))
             }
             _ => None,
         }
@@ -939,11 +948,11 @@ pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Att
             return Lrc::new([]);
         }
 
-        // The attributes for a tuple struct are attached to the definition, not the ctor;
+        // The attributes for a tuple struct/variant are attached to the definition, not the ctor;
         // we assume that someone passing in a tuple struct ctor is actually wanting to
         // look at the definition
         let def_key = self.def_key(node_id);
-        let item_id = if def_key.disambiguated_data.data == DefPathData::StructCtor {
+        let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor {
             def_key.parent.unwrap()
         } else {
             node_id
index ce0618d4599e714153e12ac551aee4331095632b..78a186fbb714ae37c9cff0e3ae18601a7df314cb 100644 (file)
@@ -572,24 +572,21 @@ fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
     /// will have to lookup the adt-def by its id, and that gives us
     /// the right to access any information in the adt-def (including,
     /// e.g., the length of the various vectors).
-    fn encode_enum_variant_info(&mut self,
-                                (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>))
-                                -> Entry<'tcx> {
+    fn encode_enum_variant_info(
+        &mut self,
+        (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+    ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let def = tcx.adt_def(enum_did);
         let variant = &def.variants[index];
-        let def_id = variant.did;
+        let def_id = variant.def_id;
         debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
-            struct_ctor: None,
-            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
-                Some(self.lazy(&tcx.fn_sig(def_id)))
-            } else {
-                None
-            }
+            ctor: variant.ctor_def_id.map(|did| did.index),
+            ctor_sig: None,
         };
 
         let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
@@ -622,6 +619,57 @@ fn encode_enum_variant_info(&mut self,
         }
     }
 
+    /// Encode the constructor for the given variant of the given ADT. See
+    /// `encode_enum_variant_info` for an explanation about why the index is untracked.
+    fn encode_enum_variant_ctor(
+        &mut self,
+        (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+    ) -> Entry<'tcx> {
+        let tcx = self.tcx;
+        let def = tcx.adt_def(enum_did);
+        let variant = &def.variants[index];
+        let def_id = variant.ctor_def_id.unwrap();
+        debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id);
+
+        let data = VariantData {
+            ctor_kind: variant.ctor_kind,
+            discr: variant.discr,
+            ctor: Some(def_id.index),
+            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+                Some(self.lazy(&tcx.fn_sig(def_id)))
+            } else {
+                None
+            }
+        };
+
+        // Variant constructors have the same visibility as the parent enums.
+        let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
+        let enum_vis = &tcx.hir().expect_item_by_hir_id(enum_id).vis;
+
+        Entry {
+            kind: EntryKind::Variant(self.lazy(&data)),
+            visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)),
+            span: self.lazy(&tcx.def_span(def_id)),
+            attributes: LazySeq::empty(),
+            children: LazySeq::empty(),
+            stability: self.encode_stability(def_id),
+            deprecation: self.encode_deprecation(def_id),
+
+            ty: Some(self.encode_item_type(def_id)),
+            inherent_impls: LazySeq::empty(),
+            variances: if variant.ctor_kind == CtorKind::Fn {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
+            generics: Some(self.encode_generics(def_id)),
+            predicates: Some(self.encode_predicates(def_id)),
+            predicates_defined_on: None,
+
+            mir: self.encode_optimized_mir(def_id),
+        }
+    }
+
     fn encode_info_for_mod(&mut self,
                            FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
                                                                  &[ast::Attribute],
@@ -678,7 +726,7 @@ fn encode_field(&mut self,
         let def_id = field.did;
         debug!("IsolatedEncoder::encode_field({:?})", def_id);
 
-        let variant_id = tcx.hir().as_local_hir_id(variant.did).unwrap();
+        let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
         let variant_data = tcx.hir().expect_variant_data(variant_id);
 
         Entry {
@@ -710,7 +758,7 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
-            struct_ctor: Some(def_id.index),
+            ctor: Some(def_id.index),
             ctor_sig: if variant.ctor_kind == CtorKind::Fn {
                 Some(self.lazy(&tcx.fn_sig(def_id)))
             } else {
@@ -1072,18 +1120,15 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 // Encode def_ids for each field and method
                 // for methods, write all the stuff get_trait_method
                 // needs to know
-                let struct_ctor = if !struct_def.is_struct() {
-                    Some(tcx.hir().local_def_id_from_hir_id(struct_def.hir_id()).index)
-                } else {
-                    None
-                };
+                let ctor = struct_def.ctor_hir_id()
+                    .map(|ctor_hir_id| tcx.hir().local_def_id_from_hir_id(ctor_hir_id).index);
 
                 let repr_options = get_repr_options(&tcx, def_id);
 
                 EntryKind::Struct(self.lazy(&VariantData {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
-                    struct_ctor,
+                    ctor,
                     ctor_sig: None,
                 }), repr_options)
             }
@@ -1094,7 +1139,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 EntryKind::Union(self.lazy(&VariantData {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
-                    struct_ctor: None,
+                    ctor: None,
                     ctor_sig: None,
                 }), repr_options)
             }
@@ -1171,8 +1216,8 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemKind::Enum(..) => {
                     let def = self.tcx.adt_def(def_id);
                     self.lazy_seq(def.variants.iter().map(|v| {
-                        assert!(v.did.is_local());
-                        v.did.index
+                        assert!(v.def_id.is_local());
+                        v.def_id.index
                     }))
                 }
                 hir::ItemKind::Struct(..) |
@@ -1765,17 +1810,23 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
 
                 let def = self.tcx.adt_def(def_id);
                 for (i, variant) in def.variants.iter_enumerated() {
-                    self.record(variant.did,
+                    self.record(variant.def_id,
                                 IsolatedEncoder::encode_enum_variant_info,
                                 (def_id, Untracked(i)));
+
+                    if let Some(ctor_def_id) = variant.ctor_def_id {
+                        self.record(ctor_def_id,
+                                    IsolatedEncoder::encode_enum_variant_ctor,
+                                    (def_id, Untracked(i)));
+                    }
                 }
             }
             hir::ItemKind::Struct(ref struct_def, _) => {
                 self.encode_fields(def_id);
 
                 // If the struct has a constructor, encode it.
-                if !struct_def.is_struct() {
-                    let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(struct_def.hir_id());
+                if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+                    let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id);
                     self.record(ctor_def_id,
                                 IsolatedEncoder::encode_struct_ctor,
                                 (def_id, ctor_def_id));
index afeea9947b5e3ecb149f9f42ecc1c0f7cdd13410..5b6166ebeaf59cc693321247827e826ece79715e 100644 (file)
@@ -445,11 +445,8 @@ pub struct FnData<'tcx> {
 pub struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
     pub discr: ty::VariantDiscr,
-
-    /// If this is a struct's only variant, this
-    /// is the index of the "struct ctor" item.
-    pub struct_ctor: Option<DefIndex>,
-
+    /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
+    pub ctor: Option<DefIndex>,
     /// If this is a tuple struct or variant
     /// ctor, this is its "function" signature.
     pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
@@ -458,7 +455,7 @@ pub struct VariantData<'tcx> {
 impl_stable_hash_for!(struct VariantData<'tcx> {
     ctor_kind,
     discr,
-    struct_ctor,
+    ctor,
     ctor_sig
 });
 
index 14289381aef456c4ff62d2625bbce3bdf0c64e0b..fac75989aa59034d7f0e15fc4eea912a2f15222a 100644 (file)
@@ -10,7 +10,7 @@
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant,
     ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand,
     Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind,
-    TerminatorKind, VarBindingForm,
+    Static, StaticKind, TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, DefIdTree};
 use rustc::ty::print::Print;
@@ -1598,14 +1598,14 @@ fn append_place_to_string(
         including_downcast: &IncludingDowncast,
     ) -> Result<(), ()> {
         match *place {
-            Place::Base(PlaceBase::Promoted(_)) => {
-                buf.push_str("promoted");
-            }
             Place::Base(PlaceBase::Local(local)) => {
                 self.append_local_to_string(local, buf)?;
             }
-            Place::Base(PlaceBase::Static(ref static_)) => {
-                buf.push_str(&self.infcx.tcx.item_name(static_.def_id).to_string());
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
+                buf.push_str("promoted");
+            }
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
+                buf.push_str(&self.infcx.tcx.item_name(def_id).to_string());
             }
             Place::Projection(ref proj) => {
                 match proj.elem {
@@ -1744,8 +1744,6 @@ fn describe_field(&self, base: &Place<'_>, field: Field) -> String {
                 let local = &self.mir.local_decls[local];
                 self.describe_field_from_ty(&local.ty, field)
             }
-            Place::Base(PlaceBase::Promoted(ref prom)) =>
-                self.describe_field_from_ty(&prom.1, field),
             Place::Base(PlaceBase::Static(ref static_)) =>
                 self.describe_field_from_ty(&static_.ty, field),
             Place::Projection(ref proj) => match proj.elem {
@@ -1809,8 +1807,10 @@ fn describe_field_from_ty(&self, ty: &ty::Ty<'_>, field: Field) -> String {
 
     /// Checks if a place is a thread-local static.
     pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
-        if let Place::Base(PlaceBase::Static(statik)) = place {
-            let attrs = self.infcx.tcx.get_attrs(statik.def_id);
+        if let Place::Base(
+            PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })
+        ) = place {
+            let attrs = self.infcx.tcx.get_attrs(*def_id);
             let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local"));
 
             debug!(
@@ -1828,8 +1828,7 @@ fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'t
         let tcx = self.infcx.tcx;
         match place {
             Place::Base(PlaceBase::Local(_)) |
-            Place::Base(PlaceBase::Static(_)) |
-            Place::Base(PlaceBase::Promoted(_)) => {
+            Place::Base(PlaceBase::Static(_)) => {
                 StorageDeadOrDrop::LocalStorageDead
             }
             Place::Projection(box PlaceProjection { base, elem }) => {
index c4e371d5afedb58e45d0b5864c71f5b656cb4447..5c159cda141a517923cde5bf5af04d82ed740021 100644 (file)
@@ -8,7 +8,9 @@
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::middle::borrowck::SignalledError;
 use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
-use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase};
+use rustc::mir::{
+    ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place, PlaceBase, Static, StaticKind
+};
 use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
@@ -75,8 +77,8 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowC
     // Return early if we are not supposed to use MIR borrow checker for this function.
     return_early = !tcx.has_attr(def_id, "rustc_mir") && !tcx.use_mir_borrowck();
 
-    if tcx.is_struct_constructor(def_id) {
-        // We are not borrow checking the automatically generated struct constructors
+    if tcx.is_constructor(def_id) {
+        // We are not borrow checking the automatically generated struct/variant constructors
         // because we want to accept structs such as this (taken from the `linked-hash-map`
         // crate):
         // ```rust
@@ -156,7 +158,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let mut flow_inits = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
-        id,
+        def_id,
         &attributes,
         &dead_unwinds,
         MaybeInitializedPlaces::new(tcx, mir, &mdpe),
@@ -191,7 +193,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let flow_borrows = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
-        id,
+        def_id,
         &attributes,
         &dead_unwinds,
         Borrows::new(tcx, mir, regioncx.clone(), &borrow_set),
@@ -200,7 +202,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let flow_uninits = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
-        id,
+        def_id,
         &attributes,
         &dead_unwinds,
         MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
@@ -209,7 +211,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let flow_ever_inits = FlowAtLocation::new(do_dataflow(
         tcx,
         mir,
-        id,
+        def_id,
         &attributes,
         &dead_unwinds,
         EverInitializedPlaces::new(tcx, mir, &mdpe),
@@ -1226,8 +1228,6 @@ fn consume_rvalue(
                                 }
                                 Operand::Move(Place::Base(PlaceBase::Static(..)))
                                 | Operand::Copy(Place::Base(PlaceBase::Static(..)))
-                                | Operand::Move(Place::Base(PlaceBase::Promoted(..)))
-                                | Operand::Copy(Place::Base(PlaceBase::Promoted(..)))
                                 | Operand::Constant(..) => {}
                             }
                         }
@@ -1310,12 +1310,13 @@ fn check_for_invalidation_at_exit(
         //
         // FIXME: allow thread-locals to borrow other thread locals?
         let (might_be_alive, will_be_dropped) = match root_place {
-            Place::Base(PlaceBase::Promoted(_)) => (true, false),
-            Place::Base(PlaceBase::Static(_)) => {
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
+                (true, false)
+            }
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(_), .. })) => {
                 // Thread-locals might be dropped after the function exits, but
                 // "true" statics will never be.
-                let is_thread_local = self.is_place_thread_local(&root_place);
-                (true, is_thread_local)
+                (true, self.is_place_thread_local(&root_place))
             }
             Place::Base(PlaceBase::Local(_)) => {
                 // Locals are always dropped at function exit, and if they
@@ -1578,7 +1579,6 @@ fn move_path_closest_to<'a>(
         match *last_prefix {
             Place::Base(PlaceBase::Local(_)) => panic!("should have move path for every Local"),
             Place::Projection(_) => panic!("PrefixSet::All meant don't stop for Projection"),
-            Place::Base(PlaceBase::Promoted(_)) |
             Place::Base(PlaceBase::Static(_)) => Err(NoMovePathFound::ReachedStatic),
         }
     }
@@ -1605,7 +1605,6 @@ fn check_if_assigned_path_is_moved(
         let mut place = place;
         loop {
             match *place {
-                Place::Base(PlaceBase::Promoted(_)) |
                 Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
                     // assigning to `x` does not require `x` be initialized.
                     break;
@@ -1953,10 +1952,6 @@ fn add_used_mut<'d>(
                     self.used_mut_upvars.push(field);
                 }
             }
-            RootPlace {
-                place: Place::Base(PlaceBase::Promoted(..)),
-                is_local_mutation_allowed: _,
-            } => {}
             RootPlace {
                 place: Place::Base(PlaceBase::Static(..)),
                 is_local_mutation_allowed: _,
@@ -1994,12 +1989,13 @@ fn is_mutable<'d>(
             }
             // The rules for promotion are made by `qualify_consts`, there wouldn't even be a
             // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this
-            Place::Base(PlaceBase::Promoted(_)) => Ok(RootPlace {
-                place,
-                is_local_mutation_allowed,
-            }),
-            Place::Base(PlaceBase::Static(ref static_)) => {
-                if self.infcx.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) {
+            Place::Base(PlaceBase::Static(box Static{kind: StaticKind::Promoted(_), ..})) =>
+                Ok(RootPlace {
+                    place,
+                    is_local_mutation_allowed,
+                }),
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
+                if self.infcx.tcx.is_static(def_id) != Some(hir::Mutability::MutMutable) {
                     Err(place)
                 } else {
                     Ok(RootPlace {
index b8dae98ec64f2affafd6914d17ce040f4077887f..f351212e9d5876f990c4d2d1896c05faa3450534 100644 (file)
@@ -1,7 +1,9 @@
 use rustc::hir;
 use rustc::hir::Node;
 use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Mir};
-use rustc::mir::{Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static};
+use rustc::mir::{
+    Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
+};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
@@ -129,9 +131,10 @@ pub(super) fn report_mutability_error(
                 }
             }
 
-            Place::Base(PlaceBase::Promoted(_)) => unreachable!(),
+            Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) =>
+                unreachable!(),
 
-            Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
+            Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })) => {
                 if let Place::Base(PlaceBase::Static(_)) = access_place {
                     item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
                     reason = String::new();
index 25a3160a498d3d335c98fe3495697bd83b1c6ba6..a3561515aaa31f3e7ebaae3092b748f7bb5c0528 100644 (file)
@@ -449,53 +449,49 @@ fn sanitize_place(
         context: PlaceContext<'_>,
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
-        let place_ty = match *place {
+        let place_ty = match place {
             Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
-                ty: self.mir.local_decls[index].ty,
+                ty: self.mir.local_decls[*index].ty,
             },
-            Place::Base(PlaceBase::Promoted(box (index, sty))) => {
+            Place::Base(PlaceBase::Static(box Static { kind, ty: sty })) => {
                 let sty = self.sanitize_type(place, sty);
-
-                if !self.errors_reported {
-                    let promoted_mir = &self.mir.promoted[index];
-                    self.sanitize_promoted(promoted_mir, location);
-
-                    let promoted_ty = promoted_mir.return_ty();
-
-                    if let Err(terr) = self.cx.eq_types(
-                        sty,
-                        promoted_ty,
-                        location.to_locations(),
-                        ConstraintCategory::Boring,
-                    ) {
-                        span_mirbug!(
-                            self,
+                let check_err =
+                    |verifier: &mut TypeVerifier<'a, 'b, 'gcx, 'tcx>,
+                     place: &Place<'tcx>,
+                     ty,
+                     sty| {
+                        if let Err(terr) = verifier.cx.eq_types(
+                            sty,
+                            ty,
+                            location.to_locations(),
+                            ConstraintCategory::Boring,
+                        ) {
+                            span_mirbug!(
+                            verifier,
                             place,
                             "bad promoted type ({:?}: {:?}): {:?}",
-                            promoted_ty,
+                            ty,
                             sty,
                             terr
                         );
+                        };
                     };
-                }
-                PlaceTy::Ty { ty: sty }
-            }
-            Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
-                let sty = self.sanitize_type(place, sty);
-                let ty = self.tcx().type_of(def_id);
-                let ty = self.cx.normalize(ty, location);
-                if let Err(terr) =
-                    self.cx
-                        .eq_types(ty, sty, location.to_locations(), ConstraintCategory::Boring)
-                {
-                    span_mirbug!(
-                        self,
-                        place,
-                        "bad static type ({:?}: {:?}): {:?}",
-                        ty,
-                        sty,
-                        terr
-                    );
+                match kind {
+                    StaticKind::Promoted(promoted) => {
+                        if !self.errors_reported {
+                            let promoted_mir = &self.mir.promoted[*promoted];
+                            self.sanitize_promoted(promoted_mir, location);
+
+                            let promoted_ty = promoted_mir.return_ty();
+                            check_err(self, place, promoted_ty, sty);
+                        }
+                    }
+                    StaticKind::Static(def_id) => {
+                        let ty = self.tcx().type_of(*def_id);
+                        let ty = self.cx.normalize(ty, location);
+
+                        check_err(self, place, ty, sty);
+                    }
                 }
                 PlaceTy::Ty { ty: sty }
             }
@@ -2685,8 +2681,8 @@ fn run_pass<'a, 'tcx>(
             return;
         }
 
-        if tcx.is_struct_constructor(def_id) {
-            // We just assume that the automatically generated struct constructors are
+        if tcx.is_constructor(def_id) {
+            // We just assume that the automatically generated struct/variant constructors are
             // correct. See the comment in the `mir_borrowck` implementation for an
             // explanation why we need this.
             return;
index 9e0bb93c33a5d5fd0362875adc49b7e8b8c035c5..42eb502b9076d6636d42d3c7d61904e6e13f1e92 100644 (file)
@@ -138,7 +138,6 @@ pub(super) fn is_active<'tcx>(
 /// This is called for all Yield statements on movable generators
 pub(super) fn borrow_of_local_data<'tcx>(place: &Place<'tcx>) -> bool {
     match place {
-        Place::Base(PlaceBase::Promoted(_)) |
         Place::Base(PlaceBase::Static(..)) => false,
         Place::Base(PlaceBase::Local(..)) => true,
         Place::Projection(box proj) => {
index c05ee3cf65b36447f48fb53fd11322dbfdd9c8f7..6bc56ab721f985711792ff270cd5bb920c5a8657 100644 (file)
@@ -1,6 +1,6 @@
 use rustc::hir;
 use rustc::mir::ProjectionElem;
-use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability};
+use rustc::mir::{Local, Mir, Place, PlaceBase, Mutability, Static, StaticKind};
 use rustc::ty::{self, TyCtxt};
 use crate::borrow_check::borrow_set::LocalsStateAtExit;
 
@@ -30,8 +30,6 @@ fn ignore_borrow(
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
         match self {
-            Place::Base(PlaceBase::Promoted(_)) => false,
-
             // If a local variable is immutable, then we only need to track borrows to guard
             // against two kinds of errors:
             // * The variable being dropped while still borrowed (e.g., because the fn returns
@@ -51,8 +49,10 @@ fn ignore_borrow(
                     }
                 }
             }
-            Place::Base(PlaceBase::Static(static_)) => {
-                tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable)
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
+                false,
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
+                tcx.is_static(*def_id) == Some(hir::Mutability::MutMutable)
             }
             Place::Projection(proj) => match proj.elem {
                 ProjectionElem::Field(..)
@@ -88,7 +88,6 @@ fn root_local(&self) -> Option<Local> {
         loop {
             match p {
                 Place::Projection(pi) => p = &pi.base,
-                Place::Base(PlaceBase::Promoted(_)) |
                 Place::Base(PlaceBase::Static(_)) => return None,
                 Place::Base(PlaceBase::Local(l)) => return Some(*l),
             }
index 1d18ada1fb69c97dad8b7ace197d65bf6d729d5b..52119d6b19bc06d5d4dc48cd8f1cf814de9b2548 100644 (file)
@@ -2,7 +2,7 @@
 use crate::borrow_check::Overlap;
 use crate::borrow_check::{Deep, Shallow, AccessDepth};
 use rustc::hir;
-use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem};
+use rustc::mir::{BorrowKind, Mir, Place, PlaceBase, Projection, ProjectionElem, StaticKind};
 use rustc::ty::{self, TyCtxt};
 use std::cmp::max;
 
@@ -338,7 +338,6 @@ fn unroll_place<'tcx, R>(
             op,
         ),
 
-        Place::Base(PlaceBase::Promoted(_)) |
         Place::Base(PlaceBase::Local(_)) | Place::Base(PlaceBase::Static(_)) => {
             let list = PlaceComponents {
                 component: place,
@@ -371,41 +370,45 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 Overlap::Disjoint
             }
         }
-        (Place::Base(PlaceBase::Static(static1)), Place::Base(PlaceBase::Static(static2))) => {
-            if static1.def_id != static2.def_id {
-                debug!("place_element_conflict: DISJOINT-STATIC");
-                Overlap::Disjoint
-            } else if tcx.is_static(static1.def_id) == Some(hir::Mutability::MutMutable) {
-                // We ignore mutable statics - they can only be unsafe code.
-                debug!("place_element_conflict: IGNORE-STATIC-MUT");
-                Overlap::Disjoint
-            } else {
-                debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
-                Overlap::EqualOrDisjoint
-            }
-        }
-        (Place::Base(PlaceBase::Promoted(p1)), Place::Base(PlaceBase::Promoted(p2))) => {
-            if p1.0 == p2.0 {
-                if let ty::Array(_, size) = p1.1.sty {
-                    if size.unwrap_usize(tcx) == 0 {
-                        // Ignore conflicts with promoted [T; 0].
-                        debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
-                        return Overlap::Disjoint;
+        (Place::Base(PlaceBase::Static(s1)), Place::Base(PlaceBase::Static(s2))) => {
+            match (&s1.kind, &s2.kind) {
+                (StaticKind::Static(def_id_1), StaticKind::Static(def_id_2)) => {
+                    if def_id_1 != def_id_2 {
+                        debug!("place_element_conflict: DISJOINT-STATIC");
+                        Overlap::Disjoint
+                    } else if tcx.is_static(*def_id_1) == Some(hir::Mutability::MutMutable) {
+                        // We ignore mutable statics - they can only be unsafe code.
+                        debug!("place_element_conflict: IGNORE-STATIC-MUT");
+                        Overlap::Disjoint
+                    } else {
+                        debug!("place_element_conflict: DISJOINT-OR-EQ-STATIC");
+                        Overlap::EqualOrDisjoint
                     }
+                },
+                (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => {
+                    if promoted_1 == promoted_2 {
+                        if let ty::Array(_, size) = s1.ty.sty {
+                            if size.unwrap_usize(tcx) == 0 {
+                                // Ignore conflicts with promoted [T; 0].
+                                debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
+                                return Overlap::Disjoint;
+                            }
+                        }
+                        // the same promoted - base case, equal
+                        debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
+                        Overlap::EqualOrDisjoint
+                    } else {
+                        // different promoteds - base case, disjoint
+                        debug!("place_element_conflict: DISJOINT-PROMOTED");
+                        Overlap::Disjoint
+                    }
+                },
+                (_, _) => {
+                    debug!("place_element_conflict: DISJOINT-STATIC-PROMOTED");
+                    Overlap::Disjoint
                 }
-                // the same promoted - base case, equal
-                debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
-                Overlap::EqualOrDisjoint
-            } else {
-                // different promoteds - base case, disjoint
-                debug!("place_element_conflict: DISJOINT-PROMOTED");
-                Overlap::Disjoint
             }
         }
-        (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Promoted(_))) |
-        (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Local(_))) |
-        (Place::Base(PlaceBase::Promoted(_)), Place::Base(PlaceBase::Static(_))) |
-        (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Promoted(_))) |
         (Place::Base(PlaceBase::Local(_)), Place::Base(PlaceBase::Static(_))) |
         (Place::Base(PlaceBase::Static(_)), Place::Base(PlaceBase::Local(_))) => {
             debug!("place_element_conflict: DISJOINT-STATIC-LOCAL-PROMOTED");
index 384fd5c9987b8a325103bec4fa2c79fd473c37bd..e70c9e81ebd16b8beff33970851e172eb2d2eaef 100644 (file)
@@ -26,7 +26,6 @@ fn is_prefix_of(&self, other: &Place<'tcx>) -> bool {
             }
 
             match *cursor {
-                Place::Base(PlaceBase::Promoted(_)) |
                 Place::Base(PlaceBase::Local(_)) |
                 Place::Base(PlaceBase::Static(_)) => return false,
                 Place::Projection(ref proj) => {
@@ -87,7 +86,6 @@ fn next(&mut self) -> Option<Self::Item> {
 
         'cursor: loop {
             let proj = match *cursor {
-                Place::Base(PlaceBase::Promoted(_)) |
                 Place::Base(PlaceBase::Local(_)) | // search yielded this leaf
                 Place::Base(PlaceBase::Static(_)) => {
                     self.next = None;
index 20b95c363f5f7f9b875dff9127386cbf74079958..199d03ac445ba51441bcd877e9d5b392a81a5ac0 100644 (file)
@@ -126,8 +126,8 @@ fn expr_as_place(
                 block.and(place)
             }
             ExprKind::StaticRef { id } => block.and(Place::Base(PlaceBase::Static(Box::new(Static {
-                def_id: id,
                 ty: expr.ty,
+                kind: StaticKind::Static(id),
             })))),
 
             ExprKind::PlaceTypeAscription { source, user_ty } => {
index 77978d7d38ff79b14fc22ffe355e99653638a43f..2e4f53023f409e918cd5447f6fc1ef39e1dccb65 100644 (file)
@@ -163,7 +163,7 @@ fn simplify_match_pair<'pat>(&mut self,
                     i == variant_index || {
                         self.hir.tcx().features().never_type &&
                         self.hir.tcx().features().exhaustive_patterns &&
-                        self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
+                        !v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
                     }
                 });
                 if irrefutable {
index 1138edcb3757e0f0ae49d44504438673d7dfd8be..7fe86d11c9ee4df56e961f8ab70ed920e36128d8 100644 (file)
@@ -31,10 +31,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
 
     // Figure out what primary body this item has.
     let (body_id, return_ty_span) = match tcx.hir().get_by_hir_id(id) {
-        Node::Variant(variant) =>
-            return create_constructor_shim(tcx, id, &variant.node.data),
-        Node::StructCtor(ctor) =>
-            return create_constructor_shim(tcx, id, ctor),
+        Node::Ctor(ctor) => return create_constructor_shim(tcx, id, ctor),
 
         Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, decl, body_id, _, _), .. })
         | Node::Item(hir::Item { node: hir::ItemKind::Fn(decl, _, _, body_id), .. })
index da9cc118f55215aedc3cbb48105b78f539a96b62..d68377681f1ca935ad6a2cc4468a320059c4b483 100644 (file)
@@ -1,6 +1,6 @@
 //! Hook into libgraphviz for rendering dataflow graphs for MIR.
 
-use rustc::hir::HirId;
+use rustc::hir::def_id::DefId;
 use rustc::mir::{BasicBlock, Mir};
 
 use std::fs;
@@ -8,13 +8,15 @@
 use std::marker::PhantomData;
 use std::path::Path;
 
+use crate::util::graphviz_safe_def_name;
+
 use super::{BitDenotation, DataflowState};
 use super::DataflowBuilder;
 use super::DebugFormatted;
 
 pub trait MirWithFlowState<'tcx> {
     type BD: BitDenotation<'tcx>;
-    fn hir_id(&self) -> HirId;
+    fn def_id(&self) -> DefId;
     fn mir(&self) -> &Mir<'tcx>;
     fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>;
 }
@@ -23,7 +25,7 @@ impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
     where BD: BitDenotation<'tcx>
 {
     type BD = BD;
-    fn hir_id(&self) -> HirId { self.hir_id }
+    fn def_id(&self) -> DefId { self.def_id }
     fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
     fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state }
 }
@@ -47,8 +49,8 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
     let g = Graph { mbcx, phantom: PhantomData, render_idx };
     let mut v = Vec::new();
     dot::render(&g, &mut v)?;
-    debug!("print_borrowck_graph_to path: {} hir_id: {}",
-           path.display(), mbcx.hir_id);
+    debug!("print_borrowck_graph_to path: {} def_id: {:?}",
+           path.display(), mbcx.def_id);
     fs::write(path, v)
 }
 
@@ -69,9 +71,8 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
     type Node = Node;
     type Edge = Edge;
     fn graph_id(&self) -> dot::Id<'_> {
-        dot::Id::new(format!("graph_for_node_{}",
-                             self.mbcx.hir_id()))
-            .unwrap()
+        let name = graphviz_safe_def_name(self.mbcx.def_id());
+        dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap()
     }
 
     fn node_id(&self, n: &Node) -> dot::Id<'_> {
index b9c8879b3c36429c5317bbba2607b3b536acecf1..9d4600d13ac138a169daf3cb6476abdb2a797f50 100644 (file)
@@ -93,7 +93,6 @@ struct BorrowedLocalsVisitor<'b, 'c: 'b> {
 fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
     match *place {
         Place::Base(PlaceBase::Local(l)) => Some(l),
-        Place::Base(PlaceBase::Promoted(_)) |
         Place::Base(PlaceBase::Static(..)) => None,
         Place::Projection(ref proj) => {
             match proj.elem {
index af2cd8f979a11fa781ac566b8b2b04b417c11faf..af0e3f5a2709130764cb7e211568a8f7f1bca623 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::work_queue::WorkQueue;
 
-use rustc::hir::HirId;
+use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator};
 use rustc::mir::traversal;
@@ -39,7 +39,7 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD>
 where
     BD: BitDenotation<'tcx>
 {
-    hir_id: HirId,
+    def_id: DefId,
     flow_state: DataflowAnalysis<'a, 'tcx, BD>,
     print_preflow_to: Option<String>,
     print_postflow_to: Option<String>,
@@ -117,7 +117,7 @@ pub struct MoveDataParamEnv<'gcx, 'tcx> {
 
 pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                                  mir: &'a Mir<'tcx>,
-                                                 hir_id: HirId,
+                                                 def_id: DefId,
                                                  attributes: &[ast::Attribute],
                                                  dead_unwinds: &BitSet<BasicBlock>,
                                                  bd: BD,
@@ -127,14 +127,14 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
           P: Fn(&BD, BD::Idx) -> DebugFormatted
 {
     let flow_state = DataflowAnalysis::new(mir, dead_unwinds, bd);
-    flow_state.run(tcx, hir_id, attributes, p)
+    flow_state.run(tcx, def_id, attributes, p)
 }
 
 impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation<'tcx>
 {
     pub(crate) fn run<P>(self,
                          tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                         hir_id: HirId,
+                         def_id: DefId,
                          attributes: &[ast::Attribute],
                          p: P) -> DataflowResults<'tcx, BD>
         where P: Fn(&BD, BD::Idx) -> DebugFormatted
@@ -159,7 +159,7 @@ pub(crate) fn run<P>(self,
             name_found(tcx.sess, attributes, "borrowck_graphviz_postflow");
 
         let mut mbcx = DataflowBuilder {
-            hir_id,
+            def_id,
             print_preflow_to, print_postflow_to, flow_state: self,
         };
 
index 7a9140bce6288f3faef7fe6f1bcd2b5a3463da1f..71805fd02b85714e650ced49e7e590a363c91996 100644 (file)
@@ -97,7 +97,6 @@ fn move_path_for(&mut self, place: &Place<'tcx>)
         debug!("lookup({:?})", place);
         match *place {
             Place::Base(PlaceBase::Local(local)) => Ok(self.builder.data.rev_lookup.locals[local]),
-            Place::Base(PlaceBase::Promoted(..)) |
             Place::Base(PlaceBase::Static(..)) => {
                 Err(MoveError::cannot_move_out_of(self.loc, Static))
             }
index 97f84675f94bf19d540efc7cbed7cbc84fc6bb4e..7eef68e5f807350dcd59491eaf314a03e7a822be 100644 (file)
@@ -286,7 +286,6 @@ impl<'tcx> MovePathLookup<'tcx> {
     pub fn find(&self, place: &Place<'tcx>) -> LookupResult {
         match *place {
             Place::Base(PlaceBase::Local(local)) => LookupResult::Exact(self.locals[local]),
-            Place::Base(PlaceBase::Promoted(_)) |
             Place::Base(PlaceBase::Static(..)) => LookupResult::Parent(None),
             Place::Projection(ref proj) => {
                 match self.find(&proj.base) {
index b83f048114b0661093347d998b97dce96f11204b..2ca44ecaba220d586a9826ff69bba44ecc4d28b4 100644 (file)
@@ -4,7 +4,7 @@
 use crate::hair::cx::to_ref::ToRef;
 use crate::hair::util::UserAnnotatedTyHelpers;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{CtorOf, Def, CtorKind};
 use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
 use rustc::ty::{self, AdtKind, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
@@ -261,10 +261,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
                     expr_ty.ty_adt_def().and_then(|adt_def| {
                         match path.def {
-                            Def::VariantCtor(variant_id, CtorKind::Fn) => {
-                                Some((adt_def, adt_def.variant_index_with_id(variant_id)))
-                            }
-                            Def::StructCtor(_, CtorKind::Fn) |
+                            Def::Ctor(ctor_id, _, CtorKind::Fn) =>
+                                Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))),
                             Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
                             _ => None,
                         }
@@ -677,8 +675,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         .ty_adt_def()
                         .and_then(|adt_def| {
                         match def {
-                            Def::VariantCtor(variant_id, CtorKind::Const) => {
-                                let idx = adt_def.variant_index_with_id(variant_id);
+                            Def::Ctor(variant_ctor_id, CtorOf::Variant, CtorKind::Const) => {
+                                let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
                                 let (d, o) = adt_def.discriminant_def_for_variant(idx);
                                 use rustc::ty::util::IntTypeExt;
                                 let ty = adt_def.repr.discr_type();
@@ -804,8 +802,7 @@ fn user_substs_applied_to_def(
         // `Fn` but with the user-given substitutions.
         Def::Fn(_) |
         Def::Method(_) |
-        Def::StructCtor(_, CtorKind::Fn) |
-        Def::VariantCtor(_, CtorKind::Fn) |
+        Def::Ctor(_, _, CtorKind::Fn) |
         Def::Const(_) |
         Def::AssociatedConst(_) => cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty),
 
@@ -813,8 +810,7 @@ fn user_substs_applied_to_def(
         // `None`). This has the type of the enum/struct that defines
         // this variant -- but with the substitutions given by the
         // user.
-        Def::StructCtor(_def_id, CtorKind::Const) |
-        Def::VariantCtor(_def_id, CtorKind::Const) =>
+        Def::Ctor(_, _, CtorKind::Const) =>
             cx.user_substs_applied_to_ty_of_hir_id(hir_id),
 
         // `Self` is used in expression as a tuple struct constructor or an unit struct constructor
@@ -911,8 +907,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         // A regular function, constructor function or a constant.
         Def::Fn(_) |
         Def::Method(_) |
-        Def::StructCtor(_, CtorKind::Fn) |
-        Def::VariantCtor(_, CtorKind::Fn) |
+        Def::Ctor(_, _, CtorKind::Fn) |
         Def::SelfCtor(..) => {
             let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
             debug!("convert_path_expr: user_ty={:?}", user_ty);
@@ -956,8 +951,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         },
 
-        Def::StructCtor(def_id, CtorKind::Const) |
-        Def::VariantCtor(def_id, CtorKind::Const) => {
+        Def::Ctor(def_id, _, CtorKind::Const) => {
             let user_provided_types = cx.tables.user_provided_types();
             let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty);
             debug!("convert_path_expr: user_provided_type={:?}", user_provided_type);
@@ -968,7 +962,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 ty::Adt(adt_def, substs) => {
                     ExprKind::Adt {
                         adt_def,
-                        variant_index: adt_def.variant_index_with_id(def_id),
+                        variant_index: adt_def.variant_index_with_ctor_id(def_id),
                         substs,
                         user_ty: user_provided_type,
                         fields: vec![],
index 88d1eb2ee0be019dc4736b703cf57a6714e25f62..303ffcb3bfb3ab653a5d17137982f0c59bb8add8 100644 (file)
 
 use rustc::hir::def_id::DefId;
 use rustc::hir::RangeEnd;
-use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt, TypeFoldable, Const};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
 use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
 
 use rustc::mir::Field;
@@ -399,22 +399,10 @@ fn is_local(&self, ty: Ty<'tcx>) -> bool {
             _ => false,
         }
     }
-
-    fn is_variant_uninhabited(&self,
-                              variant: &'tcx ty::VariantDef,
-                              substs: SubstsRef<'tcx>)
-                              -> bool
-    {
-        if self.tcx.features().exhaustive_patterns {
-            self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
-        } else {
-            false
-        }
-    }
 }
 
 #[derive(Clone, Debug, PartialEq)]
-pub enum Constructor<'tcx> {
+enum Constructor<'tcx> {
     /// The constructor of all patterns that don't vary by constructor,
     /// e.g., struct patterns and fixed-length arrays.
     Single,
@@ -435,7 +423,7 @@ fn variant_index_for_adt<'a>(
         adt: &'tcx ty::AdtDef,
     ) -> VariantIdx {
         match self {
-            &Variant(vid) => adt.variant_index_with_id(vid),
+            &Variant(id) => adt.variant_index_with_id(id),
             &Single => {
                 assert!(!adt.is_enum());
                 VariantIdx::new(0)
@@ -658,8 +646,11 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         }
         ty::Adt(def, substs) if def.is_enum() => {
             def.variants.iter()
-                .filter(|v| !cx.is_variant_uninhabited(v, substs))
-                .map(|v| Variant(v.did))
+                .filter(|v| {
+                    !cx.tcx.features().exhaustive_patterns ||
+                    !v.uninhabited_from(cx.tcx, substs, def.adt_kind()).contains(cx.tcx, cx.module)
+                })
+                .map(|v| Variant(v.def_id))
                 .collect()
         }
         ty::Char => {
@@ -1307,7 +1298,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
         PatternKind::Binding { .. } | PatternKind::Wild => None,
         PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]),
         PatternKind::Variant { adt_def, variant_index, .. } => {
-            Some(vec![Variant(adt_def.variants[variant_index].did)])
+            Some(vec![Variant(adt_def.variants[variant_index].def_id)])
         }
         PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
         PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
@@ -1742,11 +1733,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
 
         PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
             let ref variant = adt_def.variants[variant_index];
-            if *constructor == Variant(variant.did) {
-                Some(patterns_for_variant(subpatterns, wild_patterns))
-            } else {
-                None
-            }
+            Some(Variant(variant.def_id))
+                .filter(|variant_constructor| variant_constructor == constructor)
+                .map(|_| patterns_for_variant(subpatterns, wild_patterns))
         }
 
         PatternKind::Leaf { ref subpatterns } => {
index 8614be8d407b15be592abb0d19852fc290ba279b..6c532fce57f0eab1bb69443397b64ffa2082819c 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::ty::subst::{SubstsRef, Kind};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir::{self, PatKind, RangeEnd};
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::{CtorOf, Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 
 use rustc_data_structures::indexed_vec::Idx;
@@ -733,8 +733,16 @@ fn lower_variant_or_leaf(
         ty: Ty<'tcx>,
         subpatterns: Vec<FieldPattern<'tcx>>,
     ) -> PatternKind<'tcx> {
+        let def = match def {
+            Def::Ctor(variant_ctor_id, CtorOf::Variant, ..) => {
+                let variant_id = self.tcx.parent(variant_ctor_id).unwrap();
+                Def::Variant(variant_id)
+            },
+            def => def,
+        };
+
         let mut kind = match def {
-            Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
+            Def::Variant(variant_id) => {
                 let enum_id = self.tcx.parent(variant_id).unwrap();
                 let adt_def = self.tcx.adt_def(enum_id);
                 if adt_def.is_enum() {
@@ -757,7 +765,7 @@ fn lower_variant_or_leaf(
                 }
             }
 
-            Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
+            Def::Struct(..) | Def::Ctor(_, CtorOf::Struct, ..) | Def::Union(..) |
             Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => {
                 PatternKind::Leaf { subpatterns }
             }
index 755bbd96b02f9131b1d75b2e8020bb643c1f265d..d2c279e48fe280669638c817e7fab7c76216157d 100644 (file)
@@ -582,19 +582,20 @@ pub(super) fn eval_place_to_mplace(
     ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         use rustc::mir::Place::*;
         use rustc::mir::PlaceBase;
+        use rustc::mir::{Static, StaticKind};
         Ok(match *mir_place {
-            Base(PlaceBase::Promoted(ref promoted)) => {
+            Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })) => {
                 let instance = self.frame().instance;
                 self.const_eval_raw(GlobalId {
                     instance,
-                    promoted: Some(promoted.0),
+                    promoted: Some(promoted),
                 })?
             }
 
-            Base(PlaceBase::Static(ref static_)) => {
-                assert!(!static_.ty.needs_subst());
-                let layout = self.layout_of(static_.ty)?;
-                let instance = ty::Instance::mono(*self.tcx, static_.def_id);
+            Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), ty })) => {
+                assert!(!ty.needs_subst());
+                let layout = self.layout_of(ty)?;
+                let instance = ty::Instance::mono(*self.tcx, def_id);
                 let cid = GlobalId {
                     instance,
                     promoted: None
index 4fe47a9666a68e23a5fde40c12bbe51a445cea88..0ad6962cc4ac57b6fdd495650bcab44785395dac 100644 (file)
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::session::config::EntryFnType;
-use rustc::mir::{self, Location, Promoted};
+use rustc::mir::{self, Location, Place, PlaceBase, Promoted, Static, StaticKind};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::MonoItem;
 use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled};
@@ -650,19 +650,26 @@ fn visit_terminator_kind(&mut self,
         self.super_terminator_kind(block, kind, location);
     }
 
-    fn visit_static(&mut self,
-                    static_: &mir::Static<'tcx>,
+    fn visit_place(&mut self,
+                    place: &mir::Place<'tcx>,
                     context: mir::visit::PlaceContext<'tcx>,
                     location: Location) {
-        debug!("visiting static {:?} @ {:?}", static_.def_id, location);
+        match place {
+            Place::Base(
+                PlaceBase::Static(box Static{ kind:StaticKind::Static(def_id), .. })
+            ) => {
+                debug!("visiting static {:?} @ {:?}", def_id, location);
 
-        let tcx = self.tcx;
-        let instance = Instance::mono(tcx, static_.def_id);
-        if should_monomorphize_locally(tcx, &instance) {
-            self.output.push(MonoItem::Static(static_.def_id));
+                let tcx = self.tcx;
+                let instance = Instance::mono(tcx, *def_id);
+                if should_monomorphize_locally(tcx, &instance) {
+                    self.output.push(MonoItem::Static(*def_id));
+                }
+            }
+            _ => {}
         }
 
-        self.super_static(static_, context, location);
+        self.super_place(place, context, location);
     }
 }
 
index f1fbc80edfb4b231d1f85933e2c62387c29fc70a..cb25db73cd2becaca867c00c2f150c48078ad548 100644 (file)
@@ -880,7 +880,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
     };
 
     let variant_no = if adt_def.is_enum() {
-        adt_def.variant_index_with_id(def_id)
+        adt_def.variant_index_with_ctor_id(def_id)
     } else {
         VariantIdx::new(0)
     };
index 20b75c5586794e94f67afeee8af46f0c247cb252..b13a5fd2fd1c0994fc1c603539504472b04b73f1 100644 (file)
@@ -22,7 +22,6 @@ fn is_stable<'tcx>(
     match *place {
         // Locals and statics have stable addresses, for sure
         Base(PlaceBase::Local { .. }) |
-        Base(PlaceBase::Promoted { .. }) |
         Base(PlaceBase::Static { .. }) =>
             true,
         // Recurse for projections
index b494592c89f439929591ebcc95c4aa95e70feaaa..0e31515e4af9038fc7a6dbc75e28fccc3a112d2a 100644 (file)
@@ -300,10 +300,12 @@ fn visit_place(&mut self,
             &Place::Base(PlaceBase::Local(..)) => {
                 // locals are safe
             }
-            &Place::Base(PlaceBase::Promoted(_)) => {
+            &Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => {
                 bug!("unsafety checking should happen before promotion")
             }
-            &Place::Base(PlaceBase::Static(box Static { def_id, ty: _ })) => {
+            &Place::Base(
+                PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })
+            ) => {
                 if self.tcx.is_static(def_id) == Some(hir::Mutability::MutMutable) {
                     self.require_unsafe("use of mutable static",
                         "mutable statics can be mutated by multiple threads: aliasing violations \
index 33672a2b7745c8c276263604795aecaeabd447e2..102d03d7baac4bce4cefb00c44b7b13dd804b7fb 100644 (file)
@@ -4,7 +4,7 @@
 
 use rustc::hir::def::Def;
 use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, Rvalue, Local};
-use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind};
+use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind, Static, StaticKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::interpret::{EvalErrorKind, Scalar, GlobalId, EvalResult};
@@ -283,7 +283,9 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
                 // an `Index` projection would throw us off-track.
                 _ => None,
             },
-            Place::Base(PlaceBase::Promoted(ref promoted)) => {
+            Place::Base(
+                PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..})
+            ) => {
                 let generics = self.tcx.generics_of(self.source.def_id());
                 if generics.requires_monomorphization(self.tcx) {
                     // FIXME: can't handle code with generics
@@ -293,7 +295,7 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
                 let instance = Instance::new(self.source.def_id(), substs);
                 let cid = GlobalId {
                     instance,
-                    promoted: Some(promoted.0),
+                    promoted: Some(promoted),
                 };
                 // cannot use `const_eval` here, because that would require having the MIR
                 // for the current function available, but we're producing said MIR right now
index d5098bc1db2b1ee6270ae771311a41c001c82fd7..023a61588c42e9c964b754319659c4a2f136b725 100644 (file)
@@ -28,7 +28,7 @@ fn run_pass<'a, 'tcx>(&self,
     {
         debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
 
-        let id = tcx.hir().as_local_hir_id(src.def_id()).unwrap();
+        let def_id = src.def_id();
         let param_env = tcx.param_env(src.def_id()).with_reveal_all();
         let move_data = match MoveData::gather_moves(mir, tcx) {
             Ok(move_data) => move_data,
@@ -50,13 +50,13 @@ fn run_pass<'a, 'tcx>(&self,
                 move_data,
                 param_env,
             };
-            let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
+            let dead_unwinds = find_dead_unwinds(tcx, mir, def_id, &env);
             let flow_inits =
-                do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
                             MaybeInitializedPlaces::new(tcx, mir, &env),
                             |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
             let flow_uninits =
-                do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
                             MaybeUninitializedPlaces::new(tcx, mir, &env),
                             |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
 
@@ -80,7 +80,7 @@ fn run_pass<'a, 'tcx>(&self,
 fn find_dead_unwinds<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
-    id: hir::HirId,
+    def_id: hir::def_id::DefId,
     env: &MoveDataParamEnv<'tcx, 'tcx>)
     -> BitSet<BasicBlock>
 {
@@ -89,7 +89,7 @@ fn find_dead_unwinds<'a, 'tcx>(
     // reach cleanup blocks, which can't have unwind edges themselves.
     let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
     let flow_inits =
-        do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+        do_dataflow(tcx, mir, def_id, &[], &dead_unwinds,
                     MaybeInitializedPlaces::new(tcx, mir, &env),
                     |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
     for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
index b22258a49b24b6f7216bb8b4740b0ff3ca5f8572..c4e303eb9aa1f044b4980d9144eab05e61482fa4 100644 (file)
@@ -390,13 +390,13 @@ fn locals_live_across_suspend_points(
     FxHashMap<BasicBlock, liveness::LiveVarSet>,
 ) {
     let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
-    let hir_id = tcx.hir().as_local_hir_id(source.def_id()).unwrap();
+    let def_id = source.def_id();
 
     // Calculate when MIR locals have live storage. This gives us an upper bound of their
     // lifetimes.
     let storage_live_analysis = MaybeStorageLive::new(mir);
     let storage_live =
-        do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, storage_live_analysis,
+        do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, storage_live_analysis,
                     |bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
 
     // Find the MIR locals which do not use StorageLive/StorageDead statements.
@@ -410,7 +410,7 @@ fn locals_live_across_suspend_points(
     let borrowed_locals = if !movable {
         let analysis = HaveBeenBorrowedLocals::new(mir);
         let result =
-            do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, analysis,
+            do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, analysis,
                         |bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
         Some((analysis, result))
     } else {
index 234483df13ada3eae12c2da93bcc16951893a155..1063381d6aa57899fac01a7c113399fa3953c9a7 100644 (file)
@@ -692,12 +692,14 @@ fn visit_place(&mut self,
                 // Return pointer; update the place itself
                 *place = self.destination.clone();
             },
-            Place::Base(PlaceBase::Promoted(ref mut promoted)) => {
-                if let Some(p) = self.promoted_map.get(promoted.0).cloned() {
-                    promoted.0 = p;
+            Place::Base(
+                PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted), .. })
+            ) => {
+                if let Some(p) = self.promoted_map.get(*promoted).cloned() {
+                    *promoted = p;
                 }
             },
-            _ => self.super_place(place, _ctxt, _location),
+            _ => self.super_place(place, _ctxt, _location)
         }
     }
 
index 831d8b46a65c3a8ad2681abb9be92fc4cab5cda2..73b88e9904bf23cbd1a202343eb0d0acf5406faa 100644 (file)
@@ -292,9 +292,10 @@ fn promote_candidate(mut self, candidate: Candidate) {
             let promoted_id = Promoted::new(self.source.promoted.len());
             let mut promoted_place = |ty, span| {
                 promoted.span = span;
-                promoted.local_decls[RETURN_PLACE] =
-                    LocalDecl::new_return_place(ty, span);
-                Place::Base(PlaceBase::Promoted(box (promoted_id, ty)))
+                promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span);
+                Place::Base(
+                    PlaceBase::Static(box Static{ kind: StaticKind::Promoted(promoted_id), ty })
+                )
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
             match candidate {
index e96689809add71133ec5bedf75c0c18b64b8c7d7..0b9ad85e6b1c7c3585744e6e29ea0e84535926a0 100644 (file)
@@ -188,8 +188,11 @@ fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool {
     fn in_place(cx: &ConstCx<'_, 'tcx>, place: &Place<'tcx>) -> bool {
         match *place {
             Place::Base(PlaceBase::Local(local)) => Self::in_local(cx, local),
-            Place::Base(PlaceBase::Promoted(_)) => bug!("qualifying already promoted MIR"),
-            Place::Base(PlaceBase::Static(ref static_)) => Self::in_static(cx, static_),
+            Place::Base(PlaceBase::Static(box Static {kind: StaticKind::Promoted(_), .. })) =>
+                bug!("qualifying already promoted MIR"),
+            Place::Base(PlaceBase::Static(ref static_)) => {
+                Self::in_static(cx, static_)
+            },
             Place::Projection(ref proj) => Self::in_projection(cx, proj),
         }
     }
@@ -370,11 +373,18 @@ impl Qualif for IsNotConst {
     const IDX: usize = 2;
 
     fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool {
-        // Only allow statics (not consts) to refer to other statics.
-        let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut;
+        match static_.kind {
+            StaticKind::Promoted(_) => unreachable!(),
+            StaticKind::Static(def_id) => {
+                // Only allow statics (not consts) to refer to other statics.
+                let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut;
 
-        !allowed ||
-            cx.tcx.get_attrs(static_.def_id).iter().any(|attr| attr.check_name("thread_local"))
+                !allowed ||
+                    cx.tcx.get_attrs(def_id).iter().any(
+                        |attr| attr.check_name("thread_local"
+                    ))
+            }
+        }
     }
 
     fn in_projection(cx: &ConstCx<'_, 'tcx>, proj: &PlaceProjection<'tcx>) -> bool {
@@ -768,9 +778,9 @@ fn assign(&mut self, dest: &Place<'tcx>, source: ValueSource<'_, 'tcx>, location
                     );
                     dest = &proj.base;
                 },
-                Place::Base(PlaceBase::Promoted(..)) =>
+                Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) =>
                     bug!("promoteds don't exist yet during promotion"),
-                Place::Base(PlaceBase::Static(..)) => {
+                Place::Base(PlaceBase::Static(box Static{ kind: _, .. })) => {
                     // Catch more errors in the destination. `visit_place` also checks that we
                     // do not try to access statics from constants or try to mutate statics
                     self.visit_place(
@@ -919,11 +929,13 @@ fn visit_place(&mut self,
         debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
         self.super_place(place, context, location);
         match *place {
-            Place::Base(PlaceBase::Local(_)) |
-            Place::Base(PlaceBase::Promoted(_)) => {}
-            Place::Base(PlaceBase::Static(ref global)) => {
+            Place::Base(PlaceBase::Local(_)) => {}
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
+                unreachable!()
+            }
+            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
                 if self.tcx
-                       .get_attrs(global.def_id)
+                       .get_attrs(def_id)
                        .iter()
                        .any(|attr| attr.check_name("thread_local")) {
                     if self.mode != Mode::Fn {
index f82e536ab254957b42968a7496c84f61f330605e..8742c5d759c8f33feace505aee318a8d5c336a78 100644 (file)
@@ -257,8 +257,8 @@ fn check_place(
     match place {
         Place::Base(PlaceBase::Local(_)) => Ok(()),
         // promoteds are always fine, they are essentially constants
-        Place::Base(PlaceBase::Promoted(_)) => Ok(()),
-        Place::Base(PlaceBase::Static(_)) =>
+        Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. })) => Ok(()),
+        Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. })) =>
             Err((span, "cannot access `static` items in const fn".into())),
         Place::Projection(proj) => {
             match proj.elem {
index f9f8abbe6c06519874cea41b4ae164dda1431480..246f876235d71c384a782fbf24ec7523d0d14581 100644 (file)
@@ -3,7 +3,7 @@
 use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
-use rustc::hir;
+use rustc::hir::def_id::DefId;
 use rustc::mir::{self, Mir, Location};
 use rustc_data_structures::bit_set::BitSet;
 use crate::transform::{MirPass, MirSource};
@@ -27,7 +27,6 @@ impl MirPass for SanityCheck {
     fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           src: MirSource<'tcx>, mir: &mut Mir<'tcx>) {
         let def_id = src.def_id();
-        let id = tcx.hir().as_local_hir_id(def_id).unwrap();
         if !tcx.has_attr(def_id, "rustc_mir") {
             debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
             return;
@@ -41,26 +40,26 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
         let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
         let flow_inits =
-            do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+            do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
                         MaybeInitializedPlaces::new(tcx, mir, &mdpe),
                         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
         let flow_uninits =
-            do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+            do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
                         MaybeUninitializedPlaces::new(tcx, mir, &mdpe),
                         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
         let flow_def_inits =
-            do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+            do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds,
                         DefinitelyInitializedPlaces::new(tcx, mir, &mdpe),
                         |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
 
         if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() {
-            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits);
+            sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_inits);
         }
         if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() {
-            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits);
+            sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_uninits);
         }
         if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() {
-            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits);
+            sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_def_inits);
         }
         if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() {
             tcx.sess.fatal("stop_after_dataflow ended compilation");
@@ -86,12 +85,12 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// errors are not intended to be used for unit tests.)
 pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 mir: &Mir<'tcx>,
-                                                id: hir::HirId,
+                                                def_id: DefId,
                                                 _attributes: &[ast::Attribute],
                                                 results: &DataflowResults<'tcx, O>)
     where O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx>
 {
-    debug!("sanity_check_via_rustc_peek id: {:?}", id);
+    debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id);
     // FIXME: this is not DRY. Figure out way to abstract this and
     // `dataflow::build_sets`. (But note it is doing non-standard
     // stuff, so such generalization may not be realistic.)
index 69a2adcfce026e2587e2392af894103ed707acae..f87714b58c4423940affa94017ee041d2a5c25ae 100644 (file)
@@ -1,6 +1,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::mir::*;
 use rustc::ty::TyCtxt;
+use rustc_data_structures::indexed_vec::Idx;
 use std::fmt::Debug;
 use std::io::{self, Write};
 
@@ -20,6 +21,17 @@ pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
     Ok(())
 }
 
+// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so
+// it does not have to be user friendly.
+pub fn graphviz_safe_def_name(def_id: DefId) -> String {
+    format!(
+        "{}_{}_{}",
+        def_id.krate.index(),
+        def_id.index.address_space().index(),
+        def_id.index.as_array_index(),
+    )
+}
+
 /// Write a graphviz DOT graph of the MIR.
 pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
                                       def_id: DefId,
@@ -27,7 +39,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
                                       w: &mut W) -> io::Result<()>
     where W: Write
 {
-    writeln!(w, "digraph Mir_{} {{", tcx.hir().as_local_hir_id(def_id).unwrap())?;
+    writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?;
 
     // Global graph properties
     writeln!(w, r#"    graph [fontname="monospace"];"#)?;
index 29614a33f8e2789b64205c570d8b0deaee93ab0c..1a5a2a92247dd3f120bd354f0ca370ca5369af71 100644 (file)
@@ -15,7 +15,7 @@
 
 pub use self::alignment::is_disaligned;
 pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere};
-pub use self::graphviz::{write_mir_graphviz};
+pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz};
 pub use self::graphviz::write_node_label as write_graphviz_node_label;
 
 /// If possible, suggest replacing `ref` with `ref mut`.
index 13bcdc26a5efb43f512ee031362e2f065d46c38c..5e5e451b75bf2d2b853aedf5c0c316302142bb94 100644 (file)
@@ -1,5 +1,4 @@
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::hir::def::CtorKind;
 use rustc::mir::*;
 use rustc::mir::visit::Visitor;
 use rustc::ty::{self, TyCtxt};
@@ -587,15 +586,12 @@ fn write_mir_sig(
     trace!("write_mir_sig: {:?}", src.instance);
     let descr = tcx.describe_def(src.def_id());
     let is_function = match descr {
-        Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Variant(..)) |
-        Some(Def::StructCtor(_, CtorKind::Fn)) => true,
+        Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Ctor(..)) => true,
         _ => tcx.is_closure(src.def_id()),
     };
     match (descr, src.promoted) {
         (_, Some(i)) => write!(w, "{:?} in ", i)?,
-        (Some(Def::StructCtor(..)), _) => write!(w, "struct ")?,
-        (Some(Def::Const(_)), _)
-        | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?,
+        (Some(Def::Const(_)), _) | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?,
         (Some(Def::Static(_, /*is_mutbl*/false)), _) => write!(w, "static ")?,
         (Some(Def::Static(_, /*is_mutbl*/true)), _) => write!(w, "static mut ")?,
         (_, _) if is_function => write!(w, "fn ")?,
index b85429cd3cfdc7963fcb17119ff9ff53dfe35229..4e2aefe623167ffdb16e967db09ada688b74ca7e 100644 (file)
@@ -661,7 +661,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 }
             }
             ItemKind::Union(ref vdata, _) => {
-                if !vdata.is_struct() {
+                if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
                     self.err_handler().span_err(item.span,
                                                 "tuple and unit unions are not permitted");
                 }
index 373bcf7f0e2f3a4ab86479035bae7634c5d71d84..6940f8f442ee94a5789dc4f5a54c830244037be6 100644 (file)
@@ -53,8 +53,7 @@ fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item, attr: &Attribute)
                 // The `..` are the names of fields to dump.
                 let meta_items = attr.meta_item_list().unwrap_or_default();
                 for meta_item in meta_items {
-                    let name = meta_item.ident_str().unwrap_or("");
-                    match name {
+                    match meta_item.name_or_empty().get() {
                         "abi" => {
                             self.tcx
                                 .sess
@@ -84,7 +83,7 @@ fn dump_layout_of(&self, item_def_id: DefId, item: &hir::Item, attr: &Attribute)
                             );
                         }
 
-                        _ => {
+                        name => {
                             self.tcx.sess.span_err(
                                 meta_item.span(),
                                 &format!("unrecognized field name `{}`", name),
index 6de98675a3dc8cfa3815b47340a312c13b0999a1..71eb6ed7e0517be357bfb9038198eb437f60f0f0 100644 (file)
@@ -322,8 +322,8 @@ fn check_expr_kind<'a, 'tcx>(
         hir::ExprKind::Path(ref qpath) => {
             let def = v.tables.qpath_def(qpath, e.hir_id);
             match def {
-                Def::VariantCtor(..) | Def::StructCtor(..) |
-                Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => Promotable,
+                Def::Ctor(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) =>
+                    Promotable,
 
                 // References to a static that are themselves within a static
                 // are inherently promotable with the exception
@@ -387,8 +387,7 @@ fn check_expr_kind<'a, 'tcx>(
                 Def::Err
             };
             let def_result = match def {
-                Def::StructCtor(_, CtorKind::Fn) |
-                Def::VariantCtor(_, CtorKind::Fn) |
+                Def::Ctor(_, _, CtorKind::Fn) |
                 Def::SelfCtor(..) => Promotable,
                 Def::Fn(did) => v.handle_const_fn_call(did),
                 Def::Method(did) => {
index bd11e0ce8023aa6dbb10c620943626f1f24c0981..8b86bddb29f4e25264bbcae11e096e34f2fab62e 100644 (file)
@@ -56,12 +56,12 @@ pub fn load_plugins(sess: &Session,
 
             for plugin in plugins {
                 // plugins must have a name and can't be key = value
-                match plugin.ident_str() {
-                    Some(name) if !plugin.is_value_str() => {
-                        let args = plugin.meta_item_list().map(ToOwned::to_owned);
-                        loader.load_plugin(plugin.span(), name, args.unwrap_or_default());
-                    },
-                    _ => call_malformed_plugin_attribute(sess, attr.span),
+                let name = plugin.name_or_empty();
+                if !name.is_empty() && !plugin.is_value_str() {
+                    let args = plugin.meta_item_list().map(ToOwned::to_owned);
+                    loader.load_plugin(plugin.span(), &name, args.unwrap_or_default());
+                } else {
+                    call_malformed_plugin_attribute(sess, attr.span);
                 }
             }
         }
index 19b5fa1bfbe57c33569417f519ba7cf0da264a3f..bbd03e82a3730b8e262103c833394f74e87c89a5 100644 (file)
@@ -239,36 +239,48 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                         node => bug!("unexpected node kind: {:?}", node),
                     }
                 }
-                Node::StructCtor(vdata) => {
-                    let struct_hir_id = tcx.hir().get_parent_item(hir_id);
-                    let item = match tcx.hir().get_by_hir_id(struct_hir_id) {
-                        Node::Item(item) => item,
-                        node => bug!("unexpected node kind: {:?}", node),
-                    };
-                    let (mut ctor_vis, mut span, mut descr) =
-                        (ty::Visibility::from_hir(&item.vis, struct_hir_id, tcx),
-                         item.vis.span, item.vis.node.descr());
-                    for field in vdata.fields() {
-                        let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
-                        if ctor_vis.is_at_least(field_vis, tcx) {
-                            ctor_vis = field_vis;
-                            span = field.vis.span;
-                            descr = field.vis.node.descr();
+                Node::Ctor(vdata) => {
+                    let parent_hir_id = tcx.hir().get_parent_node_by_hir_id(hir_id);
+                    match tcx.hir().get_by_hir_id(parent_hir_id) {
+                        Node::Variant(..) => {
+                            let parent_did = tcx.hir().local_def_id_from_hir_id(parent_hir_id);
+                            return def_id_visibility(tcx, parent_did);
                         }
-                    }
+                        Node::Item(..) => {
+                            let item = match tcx.hir().get_by_hir_id(parent_hir_id) {
+                                Node::Item(item) => item,
+                                node => bug!("unexpected node kind: {:?}", node),
+                            };
+                            let (mut ctor_vis, mut span, mut descr) =
+                                (ty::Visibility::from_hir(&item.vis, parent_hir_id, tcx),
+                                item.vis.span, item.vis.node.descr());
+                            for field in vdata.fields() {
+                                let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
+                                if ctor_vis.is_at_least(field_vis, tcx) {
+                                    ctor_vis = field_vis;
+                                    span = field.vis.span;
+                                    descr = field.vis.node.descr();
+                                }
+                            }
 
-                    // If the structure is marked as non_exhaustive then lower the
-                    // visibility to within the crate.
-                    if ctor_vis == ty::Visibility::Public {
-                        let adt_def = tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id));
-                        if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
-                            ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
-                            span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span;
-                            descr = "crate-visible";
+                            // If the structure is marked as non_exhaustive then lower the
+                            // visibility to within the crate.
+                            if ctor_vis == ty::Visibility::Public {
+                                let adt_def =
+                                    tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id));
+                                if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
+                                    ctor_vis =
+                                        ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
+                                    span = attr::find_by_name(&item.attrs, "non_exhaustive")
+                                                .unwrap().span;
+                                    descr = "crate-visible";
+                                }
+                            }
+
+                            return (ctor_vis, span, descr);
                         }
+                        node => bug!("unexpected node kind: {:?}", node),
                     }
-
-                    return (ctor_vis, span, descr);
                 }
                 Node::Expr(expr) => {
                     return (ty::Visibility::Restricted(
@@ -504,7 +516,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
             hir::ItemKind::Enum(ref def, _) => {
                 for variant in &def.variants {
-                    let variant_level = self.update(variant.node.data.hir_id(), item_level);
+                    let variant_level = self.update(variant.node.id, item_level);
+                    if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+                        self.update(ctor_hir_id, item_level);
+                    }
                     for field in variant.node.data.fields() {
                         self.update(field.hir_id, variant_level);
                     }
@@ -523,8 +538,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                 }
             }
             hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
-                if !def.is_struct() {
-                    self.update(def.hir_id(), item_level);
+                if let Some(ctor_hir_id) = def.ctor_hir_id() {
+                    self.update(ctor_hir_id, item_level);
                 }
                 for field in def.fields() {
                     if field.vis.node.is_pub() {
@@ -624,7 +639,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     self.reach(item.hir_id, item_level).generics().predicates();
                 }
                 for variant in &def.variants {
-                    let variant_level = self.get(variant.node.data.hir_id());
+                    let variant_level = self.get(variant.node.id);
                     if variant_level.is_some() {
                         for field in variant.node.data.fields() {
                             self.reach(field.hir_id, variant_level).ty();
@@ -1468,7 +1483,7 @@ fn visit_variant(&mut self,
                      v: &'tcx hir::Variant,
                      g: &'tcx hir::Generics,
                      item_id: hir::HirId) {
-        if self.access_levels.is_reachable(v.node.data.hir_id()) {
+        if self.access_levels.is_reachable(v.node.id) {
             self.in_variant = true;
             intravisit::walk_variant(self, v, g, item_id);
             self.in_variant = false;
index 6fad4b2db9713c7a72382cb443b8872099836b70..f55425c3168ec0140163866ebc6872573a0744aa 100644 (file)
@@ -303,7 +303,7 @@ fn build_reduced_graph_for_use_tree(
                 }
 
                 // Empty groups `a::b::{}` are turned into synthetic `self` imports
-                // `a::b::c::{self as _}`, so that their prefixes are correctly
+                // `a::b::c::{self as __dummy}`, so that their prefixes are correctly
                 // resolved and checked for privacy/stability/etc.
                 if items.is_empty() && !empty_for_self(&prefix) {
                     let new_span = prefix[prefix.len() - 1].ident.span;
@@ -312,7 +312,7 @@ fn build_reduced_graph_for_use_tree(
                             Ident::new(keywords::SelfLower.name(), new_span)
                         ),
                         kind: ast::UseTreeKind::Simple(
-                            Some(Ident::new(keywords::Underscore.name().gensymed(), new_span)),
+                            Some(Ident::new(Name::gensym("__dummy"), new_span)),
                             ast::DUMMY_NODE_ID,
                             ast::DUMMY_NODE_ID,
                         ),
@@ -532,9 +532,10 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScop
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
-                if !struct_def.is_struct() {
-                    let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
-                                                   CtorKind::from_ast(struct_def));
+                if let Some(ctor_node_id) = struct_def.ctor_id() {
+                    let ctor_def = Def::Ctor(self.definitions.local_def_id(ctor_node_id),
+                                             CtorOf::Struct,
+                                             CtorKind::from_ast(struct_def));
                     self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
                     self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
                 }
@@ -581,18 +582,21 @@ fn build_reduced_graph_for_variant(&mut self,
                                        vis: ty::Visibility,
                                        expansion: Mark) {
         let ident = variant.node.ident;
-        let def_id = self.definitions.local_def_id(variant.node.data.id());
 
         // Define a name in the type namespace.
+        let def_id = self.definitions.local_def_id(variant.node.id);
         let def = Def::Variant(def_id);
         self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion));
 
         // Define a constructor name in the value namespace.
         // Braced variants, unlike structs, generate unusable names in
         // value namespace, they are reserved for possible future use.
+        // It's ok to use the variant's id as a ctor id since an
+        // error will be reported on any use of such resolution anyway.
+        let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.id);
+        let ctor_def_id = self.definitions.local_def_id(ctor_node_id);
         let ctor_kind = CtorKind::from_ast(&variant.node.data);
-        let ctor_def = Def::VariantCtor(def_id, ctor_kind);
-
+        let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
         self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
     }
 
@@ -649,10 +653,11 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
             Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
             }
-            Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
+            Def::Fn(..) | Def::Static(..) | Def::Const(..) |
+            Def::Ctor(_, CtorOf::Variant, ..) => {
                 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
             }
-            Def::StructCtor(def_id, ..) => {
+            Def::Ctor(def_id, CtorOf::Struct, ..) => {
                 self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
 
                 if let Some(struct_def_id) =
index 828ffc6d320e75a4c1488f5fca664bbf67ba2fa8..461d02e515d38dcfdacd6a66c9a218f3e8a885e2 100644 (file)
@@ -2,11 +2,10 @@
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use log::debug;
-use rustc::hir::def::*;
-use rustc::hir::def::Namespace::*;
+use rustc::hir::def::{Def, CtorKind, Namespace::*};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::session::config::nightly_options;
-use syntax::ast::{ExprKind};
+use syntax::ast::{Expr, ExprKind};
 use syntax::symbol::keywords;
 use syntax_pos::Span;
 
@@ -251,6 +250,29 @@ fn smart_resolve_context_dependent_help(
         let ns = source.namespace();
         let is_expected = &|def| source.is_expected(def);
 
+        let path_sep = |err: &mut DiagnosticBuilder<'_>, expr: &Expr| match expr.node {
+            ExprKind::Field(_, ident) => {
+                err.span_suggestion(
+                    expr.span,
+                    "use the path separator to refer to an item",
+                    format!("{}::{}", path_str, ident),
+                    Applicability::MaybeIncorrect,
+                );
+                true
+            }
+            ExprKind::MethodCall(ref segment, ..) => {
+                let span = expr.span.with_hi(segment.ident.span.hi());
+                err.span_suggestion(
+                    span,
+                    "use the path separator to refer to an item",
+                    format!("{}::{}", path_str, segment.ident),
+                    Applicability::MaybeIncorrect,
+                );
+                true
+            }
+            _ => false,
+        };
+
         match (def, source) {
             (Def::Macro(..), _) => {
                 err.span_suggestion(
@@ -260,8 +282,7 @@ fn smart_resolve_context_dependent_help(
                     Applicability::MaybeIncorrect,
                 );
                 if path_str == "try" && span.rust_2015() {
-                    err.note("if you want the `try` keyword, \
-                        you need to be in the 2018 edition");
+                    err.note("if you want the `try` keyword, you need to be in the 2018 edition");
                 }
             }
             (Def::TyAlias(..), PathSource::Trait(_)) => {
@@ -270,25 +291,8 @@ fn smart_resolve_context_dependent_help(
                     err.note("did you mean to use a trait alias?");
                 }
             }
-            (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
-                ExprKind::Field(_, ident) => {
-                    err.span_suggestion(
-                        parent.span,
-                        "use the path separator to refer to an item",
-                        format!("{}::{}", path_str, ident),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                ExprKind::MethodCall(ref segment, ..) => {
-                    let span = parent.span.with_hi(segment.ident.span.hi());
-                    err.span_suggestion(
-                        span,
-                        "use the path separator to refer to an item",
-                        format!("{}::{}", path_str, segment.ident),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                _ => return false,
+            (Def::Mod(..), PathSource::Expr(Some(parent))) => if !path_sep(err, &parent) {
+                return false;
             },
             (Def::Enum(..), PathSource::TupleStruct)
                 | (Def::Enum(..), PathSource::Expr(..))  => {
@@ -316,8 +320,10 @@ fn smart_resolve_context_dependent_help(
                         = self.struct_constructors.get(&def_id).cloned() {
                     let accessible_ctor = self.is_accessible(ctor_vis);
                     if is_expected(ctor_def) && !accessible_ctor {
-                        err.span_label(span, format!("constructor is not visible \
-                                                      here due to private fields"));
+                        err.span_label(
+                            span,
+                            format!("constructor is not visible here due to private fields"),
+                        );
                     }
                 } else {
                     // HACK(estebank): find a better way to figure out that this was a
@@ -367,28 +373,12 @@ fn smart_resolve_context_dependent_help(
                         }
                     }
                     match source {
-                        PathSource::Expr(Some(parent)) => {
-                            match parent.node {
-                                ExprKind::MethodCall(ref path_assignment, _)  => {
-                                    err.span_suggestion(
-                                        sm.start_point(parent.span)
-                                            .to(path_assignment.ident.span),
-                                        "use `::` to access an associated function",
-                                        format!("{}::{}",
-                                                path_str,
-                                                path_assignment.ident),
-                                        Applicability::MaybeIncorrect
-                                    );
-                                },
-                                _ => {
-                                    err.span_label(
-                                        span,
-                                        format!("did you mean `{} {{ /* fields */ }}`?",
-                                                path_str),
-                                    );
-                                },
-                            }
-                        },
+                        PathSource::Expr(Some(parent)) => if !path_sep(err, &parent) {
+                            err.span_label(
+                                span,
+                                format!("did you mean `{} {{ /* fields */ }}`?", path_str),
+                            );
+                        }
                         PathSource::Expr(None) if followed_by_brace == true => {
                             if let Some((sp, snippet)) = closing_brace {
                                 err.span_suggestion(
@@ -400,16 +390,14 @@ fn smart_resolve_context_dependent_help(
                             } else {
                                 err.span_label(
                                     span,
-                                    format!("did you mean `({} {{ /* fields */ }})`?",
-                                            path_str),
+                                    format!("did you mean `({} {{ /* fields */ }})`?", path_str),
                                 );
                             }
                         },
                         _ => {
                             err.span_label(
                                 span,
-                                format!("did you mean `{} {{ /* fields */ }}`?",
-                                        path_str),
+                                format!("did you mean `{} {{ /* fields */ }}`?", path_str),
                             );
                         },
                     }
@@ -417,14 +405,12 @@ fn smart_resolve_context_dependent_help(
             }
             (Def::Union(..), _) |
             (Def::Variant(..), _) |
-            (Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => {
-                err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
-                                             path_str));
+            (Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => {
+                err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str));
             }
             (Def::SelfTy(..), _) if ns == ValueNS => {
                 err.span_label(span, fallback_label);
-                err.note("can't use `Self` as a constructor, you must use the \
-                          implemented struct");
+                err.note("can't use `Self` as a constructor, you must use the implemented struct");
             }
             (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
                 err.note("can't use a type alias as a constructor");
index 38ca5f0b6640a85e992383d78d1806cb3463c8ef..f48cfa0b1479f2f66dc42dfb2c4edc8f1e64c06d 100644 (file)
@@ -571,24 +571,20 @@ fn is_expected(self, def: Def) -> bool {
                 _ => false,
             },
             PathSource::Expr(..) => match def {
-                Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) |
-                Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) |
+                Def::Ctor(_, _, CtorKind::Const) | Def::Ctor(_, _, CtorKind::Fn) |
                 Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) |
                 Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) |
                 Def::SelfCtor(..) | Def::ConstParam(..) => true,
                 _ => false,
             },
             PathSource::Pat => match def {
-                Def::StructCtor(_, CtorKind::Const) |
-                Def::VariantCtor(_, CtorKind::Const) |
+                Def::Ctor(_, _, CtorKind::Const) |
                 Def::Const(..) | Def::AssociatedConst(..) |
                 Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::TupleStruct => match def {
-                Def::StructCtor(_, CtorKind::Fn) |
-                Def::VariantCtor(_, CtorKind::Fn) |
-                Def::SelfCtor(..) => true,
+                Def::Ctor(_, _, CtorKind::Fn) | Def::SelfCtor(..) => true,
                 _ => false,
             },
             PathSource::Struct => match def {
@@ -814,7 +810,7 @@ fn visit_fn(&mut self,
         debug!("(resolving function) entering function");
         let (rib_kind, asyncness) = match function_kind {
             FnKind::ItemFn(_, ref header, ..) =>
-                (ItemRibKind, header.asyncness.node),
+                (FnItemRibKind, header.asyncness.node),
             FnKind::Method(_, ref sig, _, _) =>
                 (TraitOrImplItemRibKind, sig.header.asyncness.node),
             FnKind::Closure(_) =>
@@ -950,6 +946,10 @@ enum RibKind<'a> {
     /// upvars).
     TraitOrImplItemRibKind,
 
+    /// We passed through a function definition. Disallow upvars.
+    /// Permit only those const parameters that are specified in the function's generics.
+    FnItemRibKind,
+
     /// We passed through an item scope. Disallow upvars.
     ItemRibKind,
 
@@ -1364,7 +1364,7 @@ fn pseudo_vis(&self) -> ty::Visibility {
     fn is_variant(&self) -> bool {
         match self.kind {
             NameBindingKind::Def(Def::Variant(..), _) |
-            NameBindingKind::Def(Def::VariantCtor(..), _) => true,
+            NameBindingKind::Def(Def::Ctor(_, CtorOf::Variant, ..), _) => true,
             _ => false,
         }
     }
@@ -3089,16 +3089,14 @@ fn resolve_pattern(&mut self,
                         let is_syntactic_ambiguity = opt_pat.is_none() &&
                             bmode == BindingMode::ByValue(Mutability::Immutable);
                         match def {
-                            Def::StructCtor(_, CtorKind::Const) |
-                            Def::VariantCtor(_, CtorKind::Const) |
+                            Def::Ctor(_, _, CtorKind::Const) |
                             Def::Const(..) if is_syntactic_ambiguity => {
                                 // Disambiguate in favor of a unit struct/variant
                                 // or constant pattern.
                                 self.record_use(ident, ValueNS, binding.unwrap(), false);
                                 Some(PathResolution::new(def))
                             }
-                            Def::StructCtor(..) | Def::VariantCtor(..) |
-                            Def::Const(..) | Def::Static(..) => {
+                            Def::Ctor(..) | Def::Const(..) | Def::Static(..) => {
                                 // This is unambiguously a fresh binding, either syntactically
                                 // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
                                 // to something unusable as a pattern (e.g., constructor function),
@@ -3264,11 +3262,21 @@ fn smart_resolve_path_fragment(&mut self,
         resolution
     }
 
-    fn type_ascription_suggestion(&self,
-                                  err: &mut DiagnosticBuilder<'_>,
-                                  base_span: Span) {
+    /// Only used in a specific case of type ascription suggestions
+    #[doc(hidden)]
+    fn get_colon_suggestion_span(&self, start: Span) -> Span {
+        let cm = self.session.source_map();
+        start.to(cm.next_point(start))
+    }
+
+    fn type_ascription_suggestion(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        base_span: Span,
+    ) {
         debug!("type_ascription_suggetion {:?}", base_span);
         let cm = self.session.source_map();
+        let base_snippet = cm.span_to_snippet(base_span);
         debug!("self.current_type_ascription {:?}", self.current_type_ascription);
         if let Some(sp) = self.current_type_ascription.last() {
             let mut sp = *sp;
@@ -3276,13 +3284,10 @@ fn type_ascription_suggestion(&self,
                 // Try to find the `:`; bail on first non-':' / non-whitespace.
                 sp = cm.next_point(sp);
                 if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) {
-                    debug!("snippet {:?}", snippet);
                     let line_sp = cm.lookup_char_pos(sp.hi()).line;
                     let line_base_sp = cm.lookup_char_pos(base_span.lo()).line;
-                    debug!("{:?} {:?}", line_sp, line_base_sp);
                     if snippet == ":" {
-                        err.span_label(base_span,
-                                       "expecting a type here because of type ascription");
+                        let mut show_label = true;
                         if line_sp != line_base_sp {
                             err.span_suggestion_short(
                                 sp,
@@ -3290,6 +3295,49 @@ fn type_ascription_suggestion(&self,
                                 ";".to_string(),
                                 Applicability::MaybeIncorrect,
                             );
+                        } else {
+                            let colon_sp = self.get_colon_suggestion_span(sp);
+                            let after_colon_sp = self.get_colon_suggestion_span(
+                                colon_sp.shrink_to_hi(),
+                            );
+                            if !cm.span_to_snippet(after_colon_sp).map(|s| s == " ")
+                                .unwrap_or(false)
+                            {
+                                err.span_suggestion(
+                                    colon_sp,
+                                    "maybe you meant to write a path separator here",
+                                    "::".to_string(),
+                                    Applicability::MaybeIncorrect,
+                                );
+                                show_label = false;
+                            }
+                            if let Ok(base_snippet) = base_snippet {
+                                let mut sp = after_colon_sp;
+                                for _ in 0..100 {
+                                    // Try to find an assignment
+                                    sp = cm.next_point(sp);
+                                    let snippet = cm.span_to_snippet(sp.to(cm.next_point(sp)));
+                                    match snippet {
+                                        Ok(ref x) if x.as_str() == "=" => {
+                                            err.span_suggestion(
+                                                base_span,
+                                                "maybe you meant to write an assignment here",
+                                                format!("let {}", base_snippet),
+                                                Applicability::MaybeIncorrect,
+                                            );
+                                            show_label = false;
+                                            break;
+                                        }
+                                        Ok(ref x) if x.as_str() == "\n" => break,
+                                        Err(_) => break,
+                                        Ok(_) => {}
+                                    }
+                                }
+                            }
+                        }
+                        if show_label {
+                            err.span_label(base_span,
+                                           "expecting a type here because of type ascription");
                         }
                         break;
                     } else if !snippet.trim().is_empty() {
@@ -3863,7 +3911,7 @@ fn adjust_local_def(&mut self,
                                 seen.insert(node_id, depth);
                             }
                         }
-                        ItemRibKind | TraitOrImplItemRibKind => {
+                        ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => {
                             // This was an attempt to access an upvar inside a
                             // named function item. This is not allowed, so we
                             // report an error.
@@ -3897,7 +3945,7 @@ fn adjust_local_def(&mut self,
                         ConstantItemRibKind => {
                             // Nothing to do. Continue.
                         }
-                        ItemRibKind => {
+                        ItemRibKind | FnItemRibKind => {
                             // This was an attempt to use a type parameter outside its scope.
                             if record_used {
                                 resolve_error(
@@ -3912,12 +3960,15 @@ fn adjust_local_def(&mut self,
                 }
             }
             Def::ConstParam(..) => {
-                // A const param is always declared in a signature, which is always followed by
-                // some kind of function rib kind (specifically, ItemRibKind in the case of a
-                // normal function), so we can skip the first rib as it will be guaranteed to
-                // (spuriously) conflict with the const param.
-                for rib in &ribs[1..] {
-                    if let ItemRibKind = rib.kind {
+                let mut ribs = ribs.iter().peekable();
+                if let Some(Rib { kind: FnItemRibKind, .. }) = ribs.peek() {
+                    // When declaring const parameters inside function signatures, the first rib
+                    // is always a `FnItemRibKind`. In this case, we can skip it, to avoid it
+                    // (spuriously) conflicting with the const param.
+                    ribs.next();
+                }
+                for rib in ribs {
+                    if let ItemRibKind | FnItemRibKind = rib.kind {
                         // This was an attempt to use a const parameter outside its scope.
                         if record_used {
                             resolve_error(
@@ -4046,13 +4097,27 @@ fn lookup_typo_candidate<FilterFn>(
                     } else {
                         // Items from the prelude
                         if !module.no_implicit_prelude {
-                            names.extend(self.extern_prelude.iter().map(|(ident, _)| {
-                                TypoSuggestion {
-                                    candidate: ident.name,
-                                    article: "a",
-                                    kind: "crate",
-                                }
+                            names.extend(self.extern_prelude.clone().iter().flat_map(|(ident, _)| {
+                                self.crate_loader
+                                    .maybe_process_path_extern(ident.name, ident.span)
+                                    .and_then(|crate_id| {
+                                        let crate_mod = Def::Mod(DefId {
+                                            krate: crate_id,
+                                            index: CRATE_DEF_INDEX,
+                                        });
+
+                                        if filter_fn(crate_mod) {
+                                            Some(TypoSuggestion {
+                                                candidate: ident.name,
+                                                article: "a",
+                                                kind: "crate",
+                                            })
+                                        } else {
+                                            None
+                                        }
+                                    })
                             }));
+
                             if let Some(prelude) = self.prelude {
                                 add_module_candidates(prelude, &mut names);
                             }
@@ -4458,8 +4523,7 @@ fn lookup_import_candidates_from_module<FilterFn>(&mut self,
                         // outside crate private modules => no need to check this)
                         if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
                             let did = match def {
-                                Def::StructCtor(did, _) | Def::VariantCtor(did, _) =>
-                                    self.parent(did),
+                                Def::Ctor(did, ..) => self.parent(did),
                                 _ => def.opt_def_id(),
                             };
                             candidates.push(ImportSuggestion { did, path });
index 9daffd522bf2c3ee47ea89426b70eaf2e1c85161..c2d2bd753c82e0a532f0ace851d3536d38cb9643 100644 (file)
@@ -880,10 +880,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
                 Ok(binding) => {
                     let imported_binding = this.import(binding, directive);
                     target_bindings[ns].set(Some(imported_binding));
-                    let conflict = this.try_define(parent, target, ns, imported_binding);
-                    if let Err(old_binding) = conflict {
-                        this.report_conflict(parent, target, ns, imported_binding, old_binding);
-                    }
+                    this.define(parent, target, ns, imported_binding);
                 }
             }
         });
@@ -1295,9 +1292,11 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                 None => continue,
             };
 
-            // Filter away "empty import canaries" and ambiguous imports.
+            // Filter away ambiguous and gensymed imports. Gensymed imports
+            // (e.g. implicitly injected `std`) cannot be properly encoded in metadata,
+            // so they can cause name conflict errors downstream.
             let is_good_import = binding.is_import() && !binding.is_ambiguity() &&
-                                 binding.vis != ty::Visibility::Invisible;
+                                 !(ident.name.is_gensymed() && ident.name != "_");
             if is_good_import || binding.is_macro_def() {
                 let def = binding.def();
                 if def != Def::Err {
index 76fd8b22f745262621eaaa11389ead0cf18c0bbb..263f5acb662fc6ba1e3505d81e7f2abf8b13407e 100644 (file)
@@ -488,8 +488,8 @@ fn process_struct(
         };
 
         let (value, fields) = match item.node {
-            ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), _) |
-            ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), _) => {
+            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()
@@ -581,7 +581,7 @@ fn process_enum(
                     let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
-                        let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt);
+                        let id = id_from_node_id(variant.node.id, &self.save_ctxt);
                         let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
 
                         self.dumper.dump_def(
@@ -619,7 +619,7 @@ fn process_enum(
                     }
                     if !self.span.filter_generated(name_span) {
                         let span = self.span_from_span(name_span);
-                        let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt);
+                        let id = id_from_node_id(variant.node.id, &self.save_ctxt);
                         let parent = Some(id_from_node_id(item.id, &self.save_ctxt));
 
                         self.dumper.dump_def(
@@ -648,7 +648,7 @@ fn process_enum(
 
 
             for field in variant.node.data.fields() {
-                self.process_struct_field_def(field, variant.node.data.id());
+                self.process_struct_field_def(field, variant.node.id);
                 self.visit_ty(&field.ty);
             }
         }
@@ -957,8 +957,7 @@ fn process_var_decl_multi(&mut self, pats: &'l [P<ast::Pat>]) {
                         );
                     }
                 }
-                HirDef::StructCtor(..) |
-                HirDef::VariantCtor(..) |
+                HirDef::Ctor(_, _, _) |
                 HirDef::Const(..) |
                 HirDef::AssociatedConst(..) |
                 HirDef::Struct(..) |
index 7ad5b7ce8c73ebdf3a25dcb824c5bdb6a0b2af08..828ef802dd714a437edd7c6a9046b41b682fe095 100644 (file)
@@ -14,7 +14,7 @@
 mod sig;
 
 use rustc::hir;
-use rustc::hir::def::Def as HirDef;
+use rustc::hir::def::{CtorOf, Def as HirDef};
 use rustc::hir::Node;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::privacy::AccessLevels;
@@ -298,7 +298,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     parent: None,
                     children: def.variants
                         .iter()
-                        .map(|v| id_from_node_id(v.node.data.id(), self))
+                        .map(|v| id_from_node_id(v.node.id, self))
                         .collect(),
                     decl_id: None,
                     docs: self.docs_for_attrs(&item.attrs),
@@ -725,16 +725,6 @@ fn fn_type(seg: &ast::PathSegment) -> bool {
                     ref_id: id_from_node_id(id, self),
                 })
             }
-            HirDef::Static(..) |
-            HirDef::Const(..) |
-            HirDef::AssociatedConst(..) |
-            HirDef::VariantCtor(..) => {
-                Some(Ref {
-                    kind: RefKind::Variable,
-                    span,
-                    ref_id: id_from_def_id(def.def_id()),
-                })
-            }
             HirDef::Trait(def_id) if fn_type(path_seg) => {
                 Some(Ref {
                     kind: RefKind::Type,
@@ -767,7 +757,7 @@ fn fn_type(seg: &ast::PathSegment) -> bool {
                     ref_id: id_from_def_id(def_id),
                 })
             }
-            HirDef::StructCtor(def_id, _) => {
+            HirDef::Ctor(def_id, CtorOf::Struct, ..) => {
                 // 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.
@@ -778,6 +768,16 @@ fn fn_type(seg: &ast::PathSegment) -> bool {
                     ref_id: id_from_def_id(parent_def_id),
                 })
             }
+            HirDef::Static(..) |
+            HirDef::Const(..) |
+            HirDef::AssociatedConst(..) |
+            HirDef::Ctor(..) => {
+                Some(Ref {
+                    kind: RefKind::Variable,
+                    span,
+                    ref_id: id_from_def_id(def.def_id()),
+                })
+            }
             HirDef::Method(decl_id) => {
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
index 6e47ae6b159845259441cb626c0499683f46d9ea..76034f32c741c9d396ab550a6733eb22040f986e 100644 (file)
@@ -586,7 +586,7 @@ fn make(&self, offset: usize, id: Option<NodeId>, scx: &SaveContext<'_, '_>) ->
                     refs: vec![],
                 })
             }
-            Def::AssociatedConst(..) | Def::Variant(..) | Def::VariantCtor(..) => {
+            Def::AssociatedConst(..) | Def::Variant(..) | Def::Ctor(..) => {
                 let len = self.segments.len();
                 if len < 2 {
                     return Err("Bad path");
@@ -700,10 +700,11 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
 
 
 impl Sig for ast::Variant_ {
-    fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
+    fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
         let mut text = self.ident.to_string();
         match self.data {
-            ast::VariantData::Struct(ref fields, id, r) => {
+            ast::VariantData::Struct(ref fields, r) => {
+                let id = parent_id.unwrap();
                 let name_def = SigElement {
                     id: id_from_node_id(id, scx),
                     start: offset,
diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs
deleted file mode 100644 (file)
index 8d5d2b8..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-use rustc::traits::{
-    WellFormed,
-    FromEnv,
-    DomainGoal,
-    GoalKind,
-    Clause,
-    Clauses,
-    ProgramClause,
-    ProgramClauseCategory,
-    Environment,
-};
-use rustc::ty;
-use rustc::ty::subst::{InternalSubsts, Subst};
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc_target::spec::abi;
-use super::ChalkInferenceContext;
-use crate::lowering::Lower;
-use crate::generic_types;
-use std::iter;
-
-fn assemble_clauses_from_impls<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    trait_def_id: DefId,
-    clauses: &mut Vec<Clause<'tcx>>
-) {
-    tcx.for_each_impl(trait_def_id, |impl_def_id| {
-        clauses.extend(
-            tcx.program_clauses_for(impl_def_id)
-                .into_iter()
-                .cloned()
-        );
-    });
-}
-
-fn assemble_clauses_from_assoc_ty_values<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    trait_def_id: DefId,
-    clauses: &mut Vec<Clause<'tcx>>
-) {
-    tcx.for_each_impl(trait_def_id, |impl_def_id| {
-        for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
-            clauses.extend(
-                tcx.program_clauses_for(*def_id)
-                    .into_iter()
-                    .cloned()
-            );
-        }
-    });
-}
-
-fn assemble_builtin_sized_impls<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    sized_def_id: DefId,
-    ty: ty::Ty<'tcx>,
-    clauses: &mut Vec<Clause<'tcx>>
-) {
-    let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
-        let clause = ProgramClause {
-            goal: ty::TraitPredicate {
-                trait_ref: ty::TraitRef {
-                    def_id: sized_def_id,
-                    substs: tcx.mk_substs_trait(ty, &[]),
-                },
-            }.lower(),
-            hypotheses: tcx.mk_goals(
-                nested.iter()
-                    .cloned()
-                    .map(|nested_ty| ty::TraitRef {
-                        def_id: sized_def_id,
-                        substs: tcx.mk_substs_trait(nested_ty, &[]),
-                    })
-                    .map(|trait_ref| ty::TraitPredicate { trait_ref })
-                    .map(|pred| GoalKind::DomainGoal(pred.lower()))
-                    .map(|goal_kind| tcx.mk_goal(goal_kind))
-            ),
-            category: ProgramClauseCategory::Other,
-        };
-        // Bind innermost bound vars that may exist in `ty` and `nested`.
-        clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
-    };
-
-    match &ty.sty {
-        // Non parametric primitive types.
-        ty::Bool |
-        ty::Char |
-        ty::Int(..) |
-        ty::Uint(..) |
-        ty::Float(..) |
-        ty::Error |
-        ty::Never => push_builtin_impl(ty, &[]),
-
-        // These ones are always `Sized`.
-        &ty::Array(_, length) => {
-            push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
-        }
-        ty::RawPtr(ptr) => {
-            push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
-        }
-        &ty::Ref(_, _, mutbl) => {
-            push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
-        }
-        ty::FnPtr(fn_ptr) => {
-            let fn_ptr = fn_ptr.skip_binder();
-            let fn_ptr = generic_types::fn_ptr(
-                tcx,
-                fn_ptr.inputs_and_output.len(),
-                fn_ptr.c_variadic,
-                fn_ptr.unsafety,
-                fn_ptr.abi
-            );
-            push_builtin_impl(fn_ptr, &[]);
-        }
-        &ty::FnDef(def_id, ..) => {
-            push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
-        }
-        &ty::Closure(def_id, ..) => {
-            push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
-        }
-        &ty::Generator(def_id, ..) => {
-            push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
-        }
-
-        // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
-        &ty::Tuple(type_list) => {
-            let type_list = generic_types::type_list(tcx, type_list.len());
-            push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
-        }
-
-        // Struct def
-        ty::Adt(adt_def, _) => {
-            let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
-            let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
-            let sized_constraint = adt_def.sized_constraint(tcx)
-                .iter()
-                .map(|ty| ty.subst(tcx, substs))
-                .collect::<Vec<_>>();
-            push_builtin_impl(adt, &sized_constraint);
-        }
-
-        // Artificially trigger an ambiguity.
-        ty::Infer(..) => {
-            // Everybody can find at least two types to unify against:
-            // general ty vars, int vars and float vars.
-            push_builtin_impl(tcx.types.i32, &[]);
-            push_builtin_impl(tcx.types.u32, &[]);
-            push_builtin_impl(tcx.types.f32, &[]);
-            push_builtin_impl(tcx.types.f64, &[]);
-        }
-
-        ty::Projection(_projection_ty) => {
-            // FIXME: add builtin impls from the associated type values found in
-            // trait impls of `projection_ty.trait_ref(tcx)`.
-        }
-
-        // The `Sized` bound can only come from the environment.
-        ty::Param(..) |
-        ty::Placeholder(..) |
-        ty::UnnormalizedProjection(..) => (),
-
-        // Definitely not `Sized`.
-        ty::Foreign(..) |
-        ty::Str |
-        ty::Slice(..) |
-        ty::Dynamic(..) |
-        ty::Opaque(..) => (),
-
-        ty::Bound(..) |
-        ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
-    }
-}
-
-fn wf_clause_for_raw_ptr<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    mutbl: hir::Mutability
-) -> Clauses<'tcx> {
-    let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
-        hypotheses: ty::List::empty(),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::Implies(wf_clause);
-
-    // `forall<T> { WellFormed(*const T). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_fn_ptr<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    arity_and_output: usize,
-    c_variadic: bool,
-    unsafety: hir::Unsafety,
-    abi: abi::Abi
-) -> Clauses<'tcx> {
-    let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, c_variadic, unsafety, abi);
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
-        hypotheses: ty::List::empty(),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
-    // where `n + 1` == `arity_and_output`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
-    let ty = generic_types::bound(tcx, 0);
-    let slice_ty = tcx.mk_slice(ty);
-
-    let sized_trait = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => return ty::List::empty(),
-    };
-    let sized_implemented = ty::TraitRef {
-        def_id: sized_trait,
-        substs: tcx.mk_substs_trait(ty, ty::List::empty()),
-    };
-    let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
-        trait_ref: sized_implemented
-    }.lower();
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
-        hypotheses: tcx.mk_goals(
-            iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
-        ),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_array<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    length: &'tcx ty::Const<'tcx>
-) -> Clauses<'tcx> {
-    let ty = generic_types::bound(tcx, 0);
-    let array_ty = tcx.mk_ty(ty::Array(ty, length));
-
-    let sized_trait = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => return ty::List::empty(),
-    };
-    let sized_implemented = ty::TraitRef {
-        def_id: sized_trait,
-        substs: tcx.mk_substs_trait(ty, ty::List::empty()),
-    };
-    let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
-        trait_ref: sized_implemented
-    }.lower();
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
-        hypotheses: tcx.mk_goals(
-            iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
-        ),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_tuple<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    arity: usize
-) -> Clauses<'tcx> {
-    let type_list = generic_types::type_list(tcx, arity);
-    let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
-
-    let sized_trait = match tcx.lang_items().sized_trait() {
-        Some(def_id) => def_id,
-        None => return ty::List::empty(),
-    };
-
-    // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
-    // hypotheses is actually empty.
-    let sized_implemented = type_list[0 .. std::cmp::max(arity, 1) - 1].iter()
-        .map(|ty| ty::TraitRef {
-            def_id: sized_trait,
-            substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
-        })
-        .map(|trait_ref| ty::TraitPredicate { trait_ref })
-        .map(|predicate| predicate.lower());
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
-        hypotheses: tcx.mk_goals(
-            sized_implemented.map(|domain_goal| {
-                tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
-            })
-        ),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // ```
-    // forall<T1, ..., Tn-1, Tn> {
-    //     WellFormed((T1, ..., Tn)) :-
-    //         Implemented(T1: Sized),
-    //         ...
-    //         Implemented(Tn-1: Sized).
-    // }
-    // ```
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_ref<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    mutbl: hir::Mutability
-) -> Clauses<'tcx> {
-    let region = tcx.mk_region(
-        ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
-    );
-    let ty = generic_types::bound(tcx, 1);
-    let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
-        ty,
-        mutbl,
-    });
-
-    let _outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower();
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
-        hypotheses: ty::List::empty(),
-
-        // FIXME: restore this later once we get better at handling regions
-        // hypotheses: tcx.mk_goals(
-        //     iter::once(tcx.mk_goal(outlives.into_goal()))
-        // ),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-fn wf_clause_for_fn_def<'tcx>(
-    tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    def_id: DefId
-) -> Clauses<'tcx> {
-    let fn_def = generic_types::fn_def(tcx, def_id);
-
-    let wf_clause = ProgramClause {
-        goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
-        hypotheses: ty::List::empty(),
-        category: ProgramClauseCategory::WellFormed,
-    };
-    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
-
-    // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
-    // where `def_id` maps to the `some_fn` function definition
-    tcx.mk_clauses(iter::once(wf_clause))
-}
-
-impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
-    pub(super) fn program_clauses_impl(
-        &self,
-        environment: &Environment<'tcx>,
-        goal: &DomainGoal<'tcx>,
-    ) -> Vec<Clause<'tcx>> {
-        use rustc::traits::WhereClause::*;
-        use rustc::infer::canonical::OriginalQueryValues;
-
-        let goal = self.infcx.resolve_type_vars_if_possible(goal);
-
-        debug!("program_clauses(goal = {:?})", goal);
-
-        let mut clauses = match goal {
-            DomainGoal::Holds(Implemented(trait_predicate)) => {
-                // These come from:
-                // * implementations of the trait itself (rule `Implemented-From-Impl`)
-                // * the trait decl (rule `Implemented-From-Env`)
-
-                let mut clauses = vec![];
-
-                assemble_clauses_from_impls(
-                    self.infcx.tcx,
-                    trait_predicate.def_id(),
-                    &mut clauses
-                );
-
-                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
-                    assemble_builtin_sized_impls(
-                        self.infcx.tcx,
-                        trait_predicate.def_id(),
-                        trait_predicate.self_ty(),
-                        &mut clauses
-                    );
-                }
-
-                // FIXME: we need to add special rules for builtin impls:
-                // * `Copy` / `Clone`
-                // * `Sized`
-                // * `Unsize`
-                // * `Generator`
-                // * `FnOnce` / `FnMut` / `Fn`
-                // * trait objects
-                // * auto traits
-
-                // Rule `Implemented-From-Env` will be computed from the environment.
-                clauses
-            }
-
-            DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
-                // These come from:
-                // * the assoc type definition (rule `ProjectionEq-Placeholder`)
-                // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
-                let clauses = self.infcx.tcx.program_clauses_for(
-                    projection_predicate.projection_ty.item_def_id
-                ).into_iter()
-
-                    // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
-                    .filter(|clause| clause.category() == ProgramClauseCategory::Other)
-
-                    .cloned()
-                    .collect::<Vec<_>>();
-
-                // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
-                // from the environment.
-                clauses
-            }
-
-            DomainGoal::Holds(RegionOutlives(..)) => {
-                // These come from:
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
-                // All of these rules are computed in the environment.
-                vec![]
-            }
-
-            DomainGoal::Holds(TypeOutlives(..)) => {
-                // These come from:
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-
-                // All of these rules are computed in the environment.
-                vec![]
-            }
-
-            DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
-                // These come from -- the trait decl (rule `WellFormed-TraitRef`).
-                self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
-                    .into_iter()
-
-                    // only select `WellFormed-TraitRef`
-                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-
-                    .cloned()
-                    .collect()
-            }
-
-            DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
-                // These come from:
-                // * the associated type definition if `ty` refers to an unnormalized
-                //   associated type (rule `WellFormed-AssocTy`)
-                // * custom rules for built-in types
-                // * the type definition otherwise (rule `WellFormed-Type`)
-                let clauses = match ty.sty {
-                    ty::Projection(data) => {
-                        self.infcx.tcx.program_clauses_for(data.item_def_id)
-                    }
-
-                    // These types are always WF.
-                    ty::Bool |
-                    ty::Char |
-                    ty::Int(..) |
-                    ty::Uint(..) |
-                    ty::Float(..) |
-                    ty::Str |
-                    ty::Param(..) |
-                    ty::Placeholder(..) |
-                    ty::Error |
-                    ty::Never => {
-                        let wf_clause = ProgramClause {
-                            goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
-                            hypotheses: ty::List::empty(),
-                            category: ProgramClauseCategory::WellFormed,
-                        };
-                        let wf_clause = Clause::Implies(wf_clause);
-
-                        self.infcx.tcx.mk_clauses(iter::once(wf_clause))
-                    }
-
-                    // Always WF (recall that we do not check for parameters to be WF).
-                    ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
-
-                    // Always WF (recall that we do not check for parameters to be WF).
-                    ty::FnPtr(fn_ptr) => {
-                        let fn_ptr = fn_ptr.skip_binder();
-                        wf_clause_for_fn_ptr(
-                            self.infcx.tcx,
-                            fn_ptr.inputs_and_output.len(),
-                            fn_ptr.c_variadic,
-                            fn_ptr.unsafety,
-                            fn_ptr.abi
-                        )
-                    }
-
-                    // WF if inner type is `Sized`.
-                    ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
-
-                    // WF if inner type is `Sized`.
-                    ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
-
-                    // WF if all types but the last one are `Sized`.
-                    ty::Tuple(types) => wf_clause_for_tuple(
-                        self.infcx.tcx,
-                        types.len()
-                    ),
-
-                    // WF if `sub_ty` outlives `region`.
-                    ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
-
-                    ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
-
-                    ty::Dynamic(..) => {
-                        // FIXME: no rules yet for trait objects
-                        ty::List::empty()
-                    }
-
-                    ty::Adt(def, ..) => {
-                        self.infcx.tcx.program_clauses_for(def.did)
-                    }
-
-                    // FIXME: these are probably wrong
-                    ty::Foreign(def_id) |
-                    ty::Closure(def_id, ..) |
-                    ty::Generator(def_id, ..) |
-                    ty::Opaque(def_id, ..) => {
-                        self.infcx.tcx.program_clauses_for(def_id)
-                    }
-
-                    // Artificially trigger an ambiguity.
-                    ty::Infer(..) => {
-                        let tcx = self.infcx.tcx;
-                        let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
-                        let clauses = types.iter()
-                            .cloned()
-                            .map(|ty| ProgramClause {
-                                goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
-                                hypotheses: ty::List::empty(),
-                                category: ProgramClauseCategory::WellFormed,
-                            })
-                            .map(|clause| Clause::Implies(clause));
-                        tcx.mk_clauses(clauses)
-                    }
-
-                    ty::GeneratorWitness(..) |
-                    ty::UnnormalizedProjection(..) |
-                    ty::Bound(..) => {
-                        bug!("unexpected type {:?}", ty)
-                    }
-                };
-
-                clauses.into_iter()
-                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
-                    .cloned()
-                    .collect()
-            }
-
-            DomainGoal::FromEnv(FromEnv::Trait(..)) => {
-                // These come from:
-                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
-                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
-                // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
-                //   `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
-
-                // All of these rules are computed in the environment.
-                vec![]
-            }
-
-            DomainGoal::FromEnv(FromEnv::Ty(..)) => {
-                // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
-                // comes from the environment).
-                vec![]
-            }
-
-            DomainGoal::Normalize(projection_predicate) => {
-                // These come from -- assoc ty values (rule `Normalize-From-Impl`).
-                let mut clauses = vec![];
-
-                assemble_clauses_from_assoc_ty_values(
-                    self.infcx.tcx,
-                    projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
-                    &mut clauses
-                );
-
-                clauses
-            }
-        };
-
-        debug!("program_clauses: clauses = {:?}", clauses);
-        debug!("program_clauses: adding clauses from environment = {:?}", environment);
-
-        let mut _orig_query_values = OriginalQueryValues::default();
-        let canonical_environment = self.infcx.canonicalize_query(
-            environment,
-            &mut _orig_query_values
-        ).value;
-        let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
-
-        debug!("program_clauses: env_clauses = {:?}", env_clauses);
-
-        clauses.extend(env_clauses.into_iter().cloned());
-        clauses.extend(environment.clauses.iter().cloned());
-        clauses
-    }
-}
diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs
new file mode 100644 (file)
index 0000000..ae9f1a2
--- /dev/null
@@ -0,0 +1,208 @@
+use rustc::traits::{
+    GoalKind,
+    Clause,
+    ProgramClause,
+    ProgramClauseCategory,
+};
+use rustc::ty;
+use rustc::ty::subst::{InternalSubsts, Subst};
+use rustc::hir::def_id::DefId;
+use crate::lowering::Lower;
+use crate::generic_types;
+
+crate fn assemble_builtin_unsize_impls<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    unsize_def_id: DefId,
+    source: ty::Ty<'tcx>,
+    target: ty::Ty<'tcx>,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    match (&source.sty, &target.sty) {
+        (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => {
+            if data_a.principal_def_id() != data_b.principal_def_id()
+                || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b))
+            {
+                return;
+            }
+
+            // FIXME: rules for trait upcast
+        }
+
+        (_, &ty::Dynamic(..)) => {
+            // FIXME: basically, we should have something like:
+            // ```
+            // forall<T> {
+            //     Implemented(T: Unsize< for<...> dyn Trait<...> >) :-
+            //         for<...> Implemented(T: Trait<...>).
+            // }
+            // ```
+            // The question is: how to correctly handle the higher-ranked
+            // `for<...>` binder in order to have a generic rule?
+            // (Having generic rules is useful for caching, as we may be able
+            // to turn this function and others into tcx queries later on).
+        }
+
+        (ty::Array(_, length), ty::Slice(_)) => {
+            let ty_param = generic_types::bound(tcx, 0);
+            let array_ty = tcx.mk_ty(ty::Array(ty_param, length));
+            let slice_ty = tcx.mk_ty(ty::Slice(ty_param));
+
+            // `forall<T> { Implemented([T; N]: Unsize<[T]>). }`
+            let clause = ProgramClause {
+                goal: ty::TraitPredicate {
+                    trait_ref: ty::TraitRef {
+                        def_id: unsize_def_id,
+                        substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()])
+                    },
+                }.lower(),
+                hypotheses: ty::List::empty(),
+                category: ProgramClauseCategory::Other,
+            };
+
+            clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
+        }
+
+        (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => {
+            // FIXME: ambiguous
+        }
+
+        (ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => {
+            if def_id_a != def_id_b {
+                return;
+            }
+
+            // FIXME: rules for struct unsizing
+        }
+
+        (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
+            if tys_a.len() != tys_b.len() {
+                return;
+            }
+
+            // FIXME: rules for tuple unsizing
+        }
+
+        _ => (),
+    }
+}
+
+crate fn assemble_builtin_sized_impls<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    sized_def_id: DefId,
+    ty: ty::Ty<'tcx>,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    let mut push_builtin_impl = |ty: ty::Ty<'tcx>, nested: &[ty::Ty<'tcx>]| {
+        let clause = ProgramClause {
+            goal: ty::TraitPredicate {
+                trait_ref: ty::TraitRef {
+                    def_id: sized_def_id,
+                    substs: tcx.mk_substs_trait(ty, &[]),
+                },
+            }.lower(),
+            hypotheses: tcx.mk_goals(
+                nested.iter()
+                    .cloned()
+                    .map(|nested_ty| ty::TraitRef {
+                        def_id: sized_def_id,
+                        substs: tcx.mk_substs_trait(nested_ty, &[]),
+                    })
+                    .map(|trait_ref| ty::TraitPredicate { trait_ref })
+                    .map(|pred| GoalKind::DomainGoal(pred.lower()))
+                    .map(|goal_kind| tcx.mk_goal(goal_kind))
+            ),
+            category: ProgramClauseCategory::Other,
+        };
+        // Bind innermost bound vars that may exist in `ty` and `nested`.
+        clauses.push(Clause::ForAll(ty::Binder::bind(clause)));
+    };
+
+    match &ty.sty {
+        // Non parametric primitive types.
+        ty::Bool |
+        ty::Char |
+        ty::Int(..) |
+        ty::Uint(..) |
+        ty::Float(..) |
+        ty::Error |
+        ty::Never => push_builtin_impl(ty, &[]),
+
+        // These ones are always `Sized`.
+        &ty::Array(_, length) => {
+            push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]);
+        }
+        ty::RawPtr(ptr) => {
+            push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]);
+        }
+        &ty::Ref(_, _, mutbl) => {
+            push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]);
+        }
+        ty::FnPtr(fn_ptr) => {
+            let fn_ptr = fn_ptr.skip_binder();
+            let fn_ptr = generic_types::fn_ptr(
+                tcx,
+                fn_ptr.inputs_and_output.len(),
+                fn_ptr.c_variadic,
+                fn_ptr.unsafety,
+                fn_ptr.abi
+            );
+            push_builtin_impl(fn_ptr, &[]);
+        }
+        &ty::FnDef(def_id, ..) => {
+            push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]);
+        }
+        &ty::Closure(def_id, ..) => {
+            push_builtin_impl(generic_types::closure(tcx, def_id), &[]);
+        }
+        &ty::Generator(def_id, ..) => {
+            push_builtin_impl(generic_types::generator(tcx, def_id), &[]);
+        }
+
+        // `Sized` if the last type is `Sized` (because else we will get a WF error anyway).
+        &ty::Tuple(type_list) => {
+            let type_list = generic_types::type_list(tcx, type_list.len());
+            push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list);
+        }
+
+        // Struct def
+        ty::Adt(adt_def, _) => {
+            let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did);
+            let adt = tcx.mk_ty(ty::Adt(adt_def, substs));
+            let sized_constraint = adt_def.sized_constraint(tcx)
+                .iter()
+                .map(|ty| ty.subst(tcx, substs))
+                .collect::<Vec<_>>();
+            push_builtin_impl(adt, &sized_constraint);
+        }
+
+        // Artificially trigger an ambiguity.
+        ty::Infer(..) => {
+            // Everybody can find at least two types to unify against:
+            // general ty vars, int vars and float vars.
+            push_builtin_impl(tcx.types.i32, &[]);
+            push_builtin_impl(tcx.types.u32, &[]);
+            push_builtin_impl(tcx.types.f32, &[]);
+            push_builtin_impl(tcx.types.f64, &[]);
+        }
+
+        ty::Projection(_projection_ty) => {
+            // FIXME: add builtin impls from the associated type values found in
+            // trait impls of `projection_ty.trait_ref(tcx)`.
+        }
+
+        // The `Sized` bound can only come from the environment.
+        ty::Param(..) |
+        ty::Placeholder(..) |
+        ty::UnnormalizedProjection(..) => (),
+
+        // Definitely not `Sized`.
+        ty::Foreign(..) |
+        ty::Str |
+        ty::Slice(..) |
+        ty::Dynamic(..) |
+        ty::Opaque(..) => (),
+
+        ty::Bound(..) |
+        ty::GeneratorWitness(..) => bug!("unexpected type {:?}", ty),
+    }
+}
diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs
new file mode 100644 (file)
index 0000000..80fbd97
--- /dev/null
@@ -0,0 +1,310 @@
+mod builtin;
+mod primitive;
+
+use rustc::traits::{
+    WellFormed,
+    FromEnv,
+    DomainGoal,
+    Clause,
+    ProgramClause,
+    ProgramClauseCategory,
+    Environment,
+};
+use rustc::ty;
+use rustc::hir::def_id::DefId;
+use super::ChalkInferenceContext;
+use std::iter;
+
+use self::primitive::*;
+use self::builtin::*;
+
+fn assemble_clauses_from_impls<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    trait_def_id: DefId,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    tcx.for_each_impl(trait_def_id, |impl_def_id| {
+        clauses.extend(
+            tcx.program_clauses_for(impl_def_id)
+                .into_iter()
+                .cloned()
+        );
+    });
+}
+
+fn assemble_clauses_from_assoc_ty_values<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    trait_def_id: DefId,
+    clauses: &mut Vec<Clause<'tcx>>
+) {
+    tcx.for_each_impl(trait_def_id, |impl_def_id| {
+        for def_id in tcx.associated_item_def_ids(impl_def_id).iter() {
+            clauses.extend(
+                tcx.program_clauses_for(*def_id)
+                    .into_iter()
+                    .cloned()
+            );
+        }
+    });
+}
+
+impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
+    pub(super) fn program_clauses_impl(
+        &self,
+        environment: &Environment<'tcx>,
+        goal: &DomainGoal<'tcx>,
+    ) -> Vec<Clause<'tcx>> {
+        use rustc::traits::WhereClause::*;
+        use rustc::infer::canonical::OriginalQueryValues;
+
+        let goal = self.infcx.resolve_type_vars_if_possible(goal);
+
+        debug!("program_clauses(goal = {:?})", goal);
+
+        let mut clauses = match goal {
+            DomainGoal::Holds(Implemented(trait_predicate)) => {
+                // These come from:
+                // * implementations of the trait itself (rule `Implemented-From-Impl`)
+                // * the trait decl (rule `Implemented-From-Env`)
+
+                let mut clauses = vec![];
+
+                assemble_clauses_from_impls(
+                    self.infcx.tcx,
+                    trait_predicate.def_id(),
+                    &mut clauses
+                );
+
+                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() {
+                    assemble_builtin_sized_impls(
+                        self.infcx.tcx,
+                        trait_predicate.def_id(),
+                        trait_predicate.self_ty(),
+                        &mut clauses
+                    );
+                }
+
+                if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() {
+                    let source = trait_predicate.self_ty();
+                    let target = trait_predicate.trait_ref.substs.type_at(1);
+                    assemble_builtin_unsize_impls(
+                        self.infcx.tcx,
+                        trait_predicate.def_id(),
+                        source,
+                        target,
+                        &mut clauses
+                    );
+                }
+
+                // FIXME: we need to add special rules for other builtin impls:
+                // * `Copy` / `Clone`
+                // * `Generator`
+                // * `FnOnce` / `FnMut` / `Fn`
+                // * trait objects
+                // * auto traits
+
+                // Rule `Implemented-From-Env` will be computed from the environment.
+                clauses
+            }
+
+            DomainGoal::Holds(ProjectionEq(projection_predicate)) => {
+                // These come from:
+                // * the assoc type definition (rule `ProjectionEq-Placeholder`)
+                // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`)
+                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+
+                let clauses = self.infcx.tcx.program_clauses_for(
+                    projection_predicate.projection_ty.item_def_id
+                ).into_iter()
+
+                    // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize`
+                    .filter(|clause| clause.category() == ProgramClauseCategory::Other)
+
+                    .cloned()
+                    .collect::<Vec<_>>();
+
+                // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed
+                // from the environment.
+                clauses
+            }
+
+            // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause`
+            // will register them as actual region constraints later.
+            DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => {
+                vec![Clause::Implies(ProgramClause {
+                    goal,
+                    hypotheses: ty::List::empty(),
+                    category: ProgramClauseCategory::Other,
+                })]
+            }
+
+            DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => {
+                // These come from -- the trait decl (rule `WellFormed-TraitRef`).
+                self.infcx.tcx.program_clauses_for(trait_predicate.def_id())
+                    .into_iter()
+
+                    // only select `WellFormed-TraitRef`
+                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+
+                    .cloned()
+                    .collect()
+            }
+
+            DomainGoal::WellFormed(WellFormed::Ty(ty)) => {
+                // These come from:
+                // * the associated type definition if `ty` refers to an unnormalized
+                //   associated type (rule `WellFormed-AssocTy`)
+                // * custom rules for built-in types
+                // * the type definition otherwise (rule `WellFormed-Type`)
+                let clauses = match ty.sty {
+                    ty::Projection(data) => {
+                        self.infcx.tcx.program_clauses_for(data.item_def_id)
+                    }
+
+                    // These types are always WF.
+                    ty::Bool |
+                    ty::Char |
+                    ty::Int(..) |
+                    ty::Uint(..) |
+                    ty::Float(..) |
+                    ty::Str |
+                    ty::Param(..) |
+                    ty::Placeholder(..) |
+                    ty::Error |
+                    ty::Never => {
+                        let wf_clause = ProgramClause {
+                            goal,
+                            hypotheses: ty::List::empty(),
+                            category: ProgramClauseCategory::WellFormed,
+                        };
+                        let wf_clause = Clause::Implies(wf_clause);
+
+                        self.infcx.tcx.mk_clauses(iter::once(wf_clause))
+                    }
+
+                    // Always WF (recall that we do not check for parameters to be WF).
+                    ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl),
+
+                    // Always WF (recall that we do not check for parameters to be WF).
+                    ty::FnPtr(fn_ptr) => {
+                        let fn_ptr = fn_ptr.skip_binder();
+                        wf_clause_for_fn_ptr(
+                            self.infcx.tcx,
+                            fn_ptr.inputs_and_output.len(),
+                            fn_ptr.c_variadic,
+                            fn_ptr.unsafety,
+                            fn_ptr.abi
+                        )
+                    }
+
+                    // WF if inner type is `Sized`.
+                    ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx),
+
+                    // WF if inner type is `Sized`.
+                    ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length),
+
+                    // WF if all types but the last one are `Sized`.
+                    ty::Tuple(types) => wf_clause_for_tuple(
+                        self.infcx.tcx,
+                        types.len()
+                    ),
+
+                    // WF if `sub_ty` outlives `region`.
+                    ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl),
+
+                    ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id),
+
+                    ty::Dynamic(..) => {
+                        // FIXME: no rules yet for trait objects
+                        ty::List::empty()
+                    }
+
+                    ty::Adt(def, ..) => {
+                        self.infcx.tcx.program_clauses_for(def.did)
+                    }
+
+                    // FIXME: these are probably wrong
+                    ty::Foreign(def_id) |
+                    ty::Closure(def_id, ..) |
+                    ty::Generator(def_id, ..) |
+                    ty::Opaque(def_id, ..) => {
+                        self.infcx.tcx.program_clauses_for(def_id)
+                    }
+
+                    // Artificially trigger an ambiguity.
+                    ty::Infer(..) => {
+                        let tcx = self.infcx.tcx;
+                        let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64];
+                        let clauses = types.iter()
+                            .cloned()
+                            .map(|ty| ProgramClause {
+                                goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
+                                hypotheses: ty::List::empty(),
+                                category: ProgramClauseCategory::WellFormed,
+                            })
+                            .map(|clause| Clause::Implies(clause));
+                        tcx.mk_clauses(clauses)
+                    }
+
+                    ty::GeneratorWitness(..) |
+                    ty::UnnormalizedProjection(..) |
+                    ty::Bound(..) => {
+                        bug!("unexpected type {:?}", ty)
+                    }
+                };
+
+                clauses.into_iter()
+                    .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed)
+                    .cloned()
+                    .collect()
+            }
+
+            DomainGoal::FromEnv(FromEnv::Trait(..)) => {
+                // These come from:
+                // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`)
+                // * implied bounds from type definitions (rule `Implied-Bound-From-Type`)
+                // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`,
+                //   `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`)
+
+                // All of these rules are computed in the environment.
+                vec![]
+            }
+
+            DomainGoal::FromEnv(FromEnv::Ty(..)) => {
+                // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only
+                // comes from the environment).
+                vec![]
+            }
+
+            DomainGoal::Normalize(projection_predicate) => {
+                // These come from -- assoc ty values (rule `Normalize-From-Impl`).
+                let mut clauses = vec![];
+
+                assemble_clauses_from_assoc_ty_values(
+                    self.infcx.tcx,
+                    projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id,
+                    &mut clauses
+                );
+
+                clauses
+            }
+        };
+
+        debug!("program_clauses: clauses = {:?}", clauses);
+        debug!("program_clauses: adding clauses from environment = {:?}", environment);
+
+        let mut _orig_query_values = OriginalQueryValues::default();
+        let canonical_environment = self.infcx.canonicalize_query(
+            environment,
+            &mut _orig_query_values
+        ).value;
+        let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment);
+
+        debug!("program_clauses: env_clauses = {:?}", env_clauses);
+
+        clauses.extend(env_clauses.into_iter().cloned());
+        clauses.extend(environment.clauses.iter().cloned());
+        clauses
+    }
+}
diff --git a/src/librustc_traits/chalk_context/program_clauses/primitive.rs b/src/librustc_traits/chalk_context/program_clauses/primitive.rs
new file mode 100644 (file)
index 0000000..fc6d409
--- /dev/null
@@ -0,0 +1,204 @@
+use rustc::traits::{
+    WellFormed,
+    DomainGoal,
+    GoalKind,
+    Clause,
+    Clauses,
+    ProgramClause,
+    ProgramClauseCategory,
+};
+use rustc::ty;
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc_target::spec::abi;
+use crate::lowering::Lower;
+use crate::generic_types;
+use std::iter;
+
+crate fn wf_clause_for_raw_ptr<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    mutbl: hir::Mutability
+) -> Clauses<'tcx> {
+    let ptr_ty = generic_types::raw_ptr(tcx, mutbl);
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)),
+        hypotheses: ty::List::empty(),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::Implies(wf_clause);
+
+    // `forall<T> { WellFormed(*const T). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_fn_ptr<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    arity_and_output: usize,
+    variadic: bool,
+    unsafety: hir::Unsafety,
+    abi: abi::Abi
+) -> Clauses<'tcx> {
+    let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi);
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)),
+        hypotheses: ty::List::empty(),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }`
+    // where `n + 1` == `arity_and_output`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
+    let ty = generic_types::bound(tcx, 0);
+    let slice_ty = tcx.mk_slice(ty);
+
+    let sized_trait = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => return ty::List::empty(),
+    };
+    let sized_implemented = ty::TraitRef {
+        def_id: sized_trait,
+        substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+    };
+    let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
+        trait_ref: sized_implemented
+    }.lower();
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)),
+        hypotheses: tcx.mk_goals(
+            iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+        ),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_array<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    length: &'tcx ty::Const<'tcx>
+) -> Clauses<'tcx> {
+    let ty = generic_types::bound(tcx, 0);
+    let array_ty = tcx.mk_ty(ty::Array(ty, length));
+
+    let sized_trait = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => return ty::List::empty(),
+    };
+    let sized_implemented = ty::TraitRef {
+        def_id: sized_trait,
+        substs: tcx.mk_substs_trait(ty, ty::List::empty()),
+    };
+    let sized_implemented: DomainGoal<'_> = ty::TraitPredicate {
+        trait_ref: sized_implemented
+    }.lower();
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)),
+        hypotheses: tcx.mk_goals(
+            iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))
+        ),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_tuple<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    arity: usize
+) -> Clauses<'tcx> {
+    let type_list = generic_types::type_list(tcx, arity);
+    let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
+
+    let sized_trait = match tcx.lang_items().sized_trait() {
+        Some(def_id) => def_id,
+        None => return ty::List::empty(),
+    };
+
+    // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of
+    // hypotheses is actually empty.
+    let sized_implemented = type_list[0 .. std::cmp::max(arity, 1) - 1].iter()
+        .map(|ty| ty::TraitRef {
+            def_id: sized_trait,
+            substs: tcx.mk_substs_trait(*ty, ty::List::empty()),
+        })
+        .map(|trait_ref| ty::TraitPredicate { trait_ref })
+        .map(|predicate| predicate.lower());
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)),
+        hypotheses: tcx.mk_goals(
+            sized_implemented.map(|domain_goal| {
+                tcx.mk_goal(GoalKind::DomainGoal(domain_goal))
+            })
+        ),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // ```
+    // forall<T1, ..., Tn-1, Tn> {
+    //     WellFormed((T1, ..., Tn)) :-
+    //         Implemented(T1: Sized),
+    //         ...
+    //         Implemented(Tn-1: Sized).
+    // }
+    // ```
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_ref<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    mutbl: hir::Mutability
+) -> Clauses<'tcx> {
+    let region = tcx.mk_region(
+        ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
+    );
+    let ty = generic_types::bound(tcx, 1);
+    let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
+        ty,
+        mutbl,
+    });
+
+    let outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower();
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)),
+        hypotheses: tcx.mk_goals(
+            iter::once(tcx.mk_goal(outlives.into_goal()))
+        ),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }`
+    tcx.mk_clauses(iter::once(wf_clause))
+}
+
+crate fn wf_clause_for_fn_def<'tcx>(
+    tcx: ty::TyCtxt<'_, '_, 'tcx>,
+    def_id: DefId
+) -> Clauses<'tcx> {
+    let fn_def = generic_types::fn_def(tcx, def_id);
+
+    let wf_clause = ProgramClause {
+        goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)),
+        hypotheses: ty::List::empty(),
+        category: ProgramClauseCategory::WellFormed,
+    };
+    let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause));
+
+    // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }`
+    // where `def_id` maps to the `some_fn` function definition
+    tcx.mk_clauses(iter::once(wf_clause))
+}
index 932501cc04fe0dd8c4fa471042023fcb2d0af705..41f983e6acac81c3129da0199b230129dcb3e7b1 100644 (file)
@@ -8,6 +8,7 @@
 use rustc::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc::traits::{
     DomainGoal,
+    WhereClause,
     Goal,
     GoalKind,
     Clause,
@@ -75,6 +76,23 @@ fn resolvent_clause(
                 })
             );
 
+            // If we have a goal of the form `T: 'a` or `'a: 'b`, then just
+            // assume it is true (no subgoals) and register it as a constraint
+            // instead.
+            match goal {
+                DomainGoal::Holds(WhereClause::RegionOutlives(pred)) => {
+                    assert_eq!(ex_clause.subgoals.len(), 0);
+                    ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1));
+                }
+
+                DomainGoal::Holds(WhereClause::TypeOutlives(pred)) => {
+                    assert_eq!(ex_clause.subgoals.len(), 0);
+                    ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1));
+                }
+
+                _ => (),
+            };
+
             let canonical_ex_clause = self.canonicalize_ex_clause(&ex_clause);
             Ok(canonical_ex_clause)
         });
@@ -112,10 +130,8 @@ fn apply_answer_subst(
         substitutor.relate(&answer_table_goal.value, &selected_goal)
             .map_err(|_| NoSolution)?;
 
-        let ex_clause = substitutor.ex_clause;
-
-        // FIXME: restore this later once we get better at handling regions
-        // ex_clause.constraints.extend(answer_subst.constraints);
+        let mut ex_clause = substitutor.ex_clause;
+        ex_clause.constraints.extend(answer_subst.constraints);
 
         debug!("apply_answer_subst: ex_clause = {:?}", ex_clause);
         Ok(ex_clause)
index c908c6993e19e883e8230a903382a6feda561858..3570cb102460002a3596fa49179a14266fd4082b 100644 (file)
@@ -10,9 +10,6 @@
 use rustc::ty::{self, TyCtxt, Ty};
 use rustc::hir::def_id::DefId;
 use rustc_data_structures::fx::FxHashSet;
-use super::Lower;
-use crate::generic_types;
-use std::iter;
 
 struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -38,30 +35,6 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
                 );
             }
 
-            // forall<'a, T> { `Outlives(T: 'a) :- FromEnv(&'a T)` }
-            ty::Ref(_, _, mutbl) => {
-                let region = self.tcx.mk_region(
-                    ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
-                );
-                let ty = generic_types::bound(self.tcx, 1);
-                let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
-                    ty,
-                    mutbl,
-                });
-
-                let from_env = DomainGoal::FromEnv(FromEnv::Ty(ref_ty));
-
-                let clause = ProgramClause {
-                    goal: ty::OutlivesPredicate(ty, region).lower(),
-                    hypotheses: self.tcx.mk_goals(
-                        iter::once(self.tcx.mk_goal(from_env.into_goal()))
-                    ),
-                    category: ProgramClauseCategory::ImpliedBound,
-                };
-                let clause = Clause::ForAll(ty::Binder::bind(clause));
-                self.round.insert(clause);
-            }
-
             ty::Dynamic(..) => {
                 // FIXME: trait object rules are not yet implemented
             }
@@ -99,6 +72,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) {
             ty::RawPtr(..) |
             ty::FnPtr(..) |
             ty::Tuple(..) |
+            ty::Ref(..) |
             ty::Never |
             ty::Infer(..) |
             ty::Placeholder(..) |
index 44883d438a1e52eddbe93a724df59185e8e1d3dd..c3cbdb0376251474514337777400fa7a158fa769 100644 (file)
@@ -209,6 +209,10 @@ fn program_clauses_for_trait<'a, 'tcx>(
     let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env));
 
     let predicates = &tcx.predicates_defined_on(def_id).predicates;
+
+    // Warning: these where clauses are not substituted for bound vars yet,
+    // so that we don't need to adjust binders in the `FromEnv` rules below
+    // (see the FIXME).
     let where_clauses = &predicates
         .iter()
         .map(|(wc, _)| wc.lower())
@@ -258,6 +262,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
     // `WellFormed(WC)`
     let wf_conditions = where_clauses
         .into_iter()
+        .map(|wc| wc.subst(tcx, bound_vars))
         .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal()));
 
     // `WellFormed(Self: Trait<P1..Pn>) :- Implemented(Self: Trait<P1..Pn>) && WellFormed(WC)`
@@ -332,7 +337,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
     //
     // ```
     // forall<P1..Pn> {
-    //   WellFormed(Ty<...>) :- WC1, ..., WCm`
+    //   WellFormed(Ty<...>) :- WellFormed(WC1), ..., WellFormed(WCm)`
     // }
     // ```
 
@@ -341,19 +346,22 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
     // `Ty<...>`
     let ty = tcx.type_of(def_id).subst(tcx, bound_vars);
 
-    // `WC`
+    // Warning: these where clauses are not substituted for bound vars yet,
+    // so that we don't need to adjust binders in the `FromEnv` rules below
+    // (see the FIXME).
     let where_clauses = tcx.predicates_of(def_id).predicates
         .iter()
         .map(|(wc, _)| wc.lower())
         .collect::<Vec<_>>();
 
-    // `WellFormed(Ty<...>) :- WC1, ..., WCm`
+    // `WellFormed(Ty<...>) :- WellFormed(WC1), ..., WellFormed(WCm)`
     let well_formed_clause = ProgramClause {
         goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
         hypotheses: tcx.mk_goals(
             where_clauses
                 .iter()
                 .map(|wc| wc.subst(tcx, bound_vars))
+                .map(|wc| wc.map_bound(|bound| bound.into_well_formed_goal()))
                 .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
         ),
         category: ProgramClauseCategory::WellFormed,
@@ -450,13 +458,13 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
     // ```
     // forall<Self, P1..Pn, Pn+1..Pm> {
     //     WellFormed((Trait::AssocType)<Self, P1..Pn, Pn+1..Pm>)
-    //         :- Implemented(Self: Trait<P1..Pn>)
+    //         :- WellFormed(Self: Trait<P1..Pn>)
     // }
     // ```
 
     let trait_predicate = ty::TraitPredicate { trait_ref };
     let hypothesis = tcx.mk_goal(
-        DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal()
+        DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)).into_goal()
     );
 
     let wf_clause = ProgramClause {
index e470748e3443493dcdcf8e3852bc0360b695db24..3e61b175b76e048b34e8bdf8fafdade676a44c39 100644 (file)
@@ -4,7 +4,7 @@
 
 use errors::{Applicability, DiagnosticId};
 use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
-use crate::hir::def::Def;
+use crate::hir::def::{CtorOf, Def};
 use crate::hir::def_id::DefId;
 use crate::hir::HirVec;
 use crate::lint;
@@ -1318,10 +1318,10 @@ pub fn associated_path_to_ty(
                     tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did)
                 });
                 if let Some(variant_def) = variant_def {
-                    let def = Def::Variant(variant_def.did);
+                    let def = Def::Variant(variant_def.def_id);
                     if permit_variants {
                         check_type_alias_enum_variants_enabled(tcx, span);
-                        tcx.check_stability(variant_def.did, Some(hir_ref_id), span);
+                        tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span);
                         return (qself_ty, def);
                     } else {
                         variant_resolution = Some(def);
@@ -1596,7 +1596,7 @@ pub fn def_ids_for_path_segments(&self,
 
         match def {
             // Case 1. Reference to a struct constructor.
-            Def::StructCtor(def_id, ..) |
+            Def::Ctor(def_id, CtorOf::Struct, ..) |
             Def::SelfCtor(.., def_id) => {
                 // Everything but the final segment should have no
                 // parameters at all.
@@ -1608,8 +1608,7 @@ pub fn def_ids_for_path_segments(&self,
             }
 
             // Case 2. Reference to a variant constructor.
-            Def::Variant(def_id) |
-            Def::VariantCtor(def_id, ..) => {
+            Def::Ctor(def_id, CtorOf::Variant, ..) | Def::Variant(def_id, ..) => {
                 let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
                 let (generics_def_id, index) = if let Some(adt_def) = adt_def {
                     debug_assert!(adt_def.is_enum());
@@ -1617,6 +1616,14 @@ pub fn def_ids_for_path_segments(&self,
                 } else if last >= 1 && segments[last - 1].args.is_some() {
                     // Everything but the penultimate segment should have no
                     // parameters at all.
+                    let mut def_id = def_id;
+
+                    // `Def::Ctor` -> `Def::Variant`
+                    if let Def::Ctor(..) = def {
+                        def_id = tcx.parent(def_id).unwrap()
+                    }
+
+                    // `Def::Variant` -> `Def::Item` (enum)
                     let enum_def_id = tcx.parent(def_id).unwrap();
                     (enum_def_id, last - 1)
                 } else {
index c30b9d65fec831bef6c99f856554a8cf8189fd1e..affd3a2d16af75e9f6b0bf63c60ebdb26009036d 100644 (file)
@@ -807,14 +807,12 @@ fn check_pat_path(
                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
                 return tcx.types.err;
             }
-            Def::VariantCtor(_, CtorKind::Fictive) |
-            Def::VariantCtor(_, CtorKind::Fn) => {
+            Def::Ctor(_, _, CtorKind::Fictive) |
+            Def::Ctor(_, _, CtorKind::Fn) => {
                 report_unexpected_variant_def(tcx, &def, pat.span, qpath);
                 return tcx.types.err;
             }
-            Def::VariantCtor(_, CtorKind::Const) |
-            Def::StructCtor(_, CtorKind::Const) |
-            Def::SelfCtor(..) |
+            Def::Ctor(_, _, CtorKind::Const) | Def::SelfCtor(..) |
             Def::Const(..) | Def::AssociatedConst(..) => {} // OK
             _ => bug!("unexpected pattern definition: {:?}", def)
         }
@@ -876,8 +874,7 @@ fn check_pat_tuple_struct(
                 report_unexpected_def(def);
                 return tcx.types.err;
             }
-            Def::VariantCtor(_, CtorKind::Fn) |
-            Def::StructCtor(_, CtorKind::Fn) => {
+            Def::Ctor(_, _, CtorKind::Fn) => {
                 tcx.expect_variant_def(def)
             }
             _ => bug!("unexpected pattern definition: {:?}", def)
@@ -950,7 +947,7 @@ fn check_struct_pat_fields(
         let mut inexistent_fields = vec![];
         // Typecheck each field.
         for &Spanned { node: ref field, span } in fields {
-            let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
+            let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
             let field_ty = match used_fields.entry(ident) {
                 Occupied(occupied) => {
                     struct_span_err!(tcx.sess, span, E0025,
@@ -973,7 +970,7 @@ fn check_struct_pat_fields(
                             self.field_ty(span, f, substs)
                         })
                         .unwrap_or_else(|| {
-                            inexistent_fields.push((span, field.ident));
+                            inexistent_fields.push(field.ident);
                             no_field_errors = false;
                             tcx.types.err
                         })
@@ -989,27 +986,27 @@ fn check_struct_pat_fields(
                 .collect::<Vec<_>>();
         if inexistent_fields.len() > 0 && !variant.recovered {
             let (field_names, t, plural) = if inexistent_fields.len() == 1 {
-                (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
+                (format!("a field named `{}`", inexistent_fields[0]), "this", "")
             } else {
                 (format!("fields named {}",
                          inexistent_fields.iter()
-                            .map(|(_, name)| format!("`{}`", name))
+                            .map(|ident| format!("`{}`", ident))
                             .collect::<Vec<String>>()
                             .join(", ")), "these", "s")
             };
-            let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
+            let spans = inexistent_fields.iter().map(|ident| ident.span).collect::<Vec<_>>();
             let mut err = struct_span_err!(tcx.sess,
                                            spans,
                                            E0026,
                                            "{} `{}` does not have {}",
                                            kind_name,
-                                           tcx.def_path_str(variant.did),
+                                           tcx.def_path_str(variant.def_id),
                                            field_names);
-            if let Some((span, ident)) = inexistent_fields.last() {
-                err.span_label(*span,
+            if let Some(ident) = inexistent_fields.last() {
+                err.span_label(ident.span,
                                format!("{} `{}` does not have {} field{}",
                                        kind_name,
-                                       tcx.def_path_str(variant.did),
+                                       tcx.def_path_str(variant.def_id),
                                        t,
                                        plural));
                 if plural == "" {
@@ -1018,8 +1015,8 @@ fn check_struct_pat_fields(
                         find_best_match_for_name(input, &ident.as_str(), None);
                     if let Some(suggested_name) = suggested_name {
                         err.span_suggestion(
-                            *span,
-                            "did you mean",
+                            ident.span,
+                            "a field with a similar name exists",
                             suggested_name.to_string(),
                             Applicability::MaybeIncorrect,
                         );
index 3a7308d09172e6581402db7d77fd0eecba619a29..b1a249d821bec77b279f3d3629d90e2fbadc237d 100644 (file)
@@ -130,7 +130,7 @@ pub fn demand_coerce_diag(&self,
                         let sole_field = &variant.fields[0];
                         let sole_field_ty = sole_field.ty(self.tcx, substs);
                         if self.can_coerce(expr_ty, sole_field_ty) {
-                            let variant_path = self.tcx.def_path_str(variant.did);
+                            let variant_path = self.tcx.def_path_str(variant.def_id);
                             // FIXME #56861: DRYer prelude filtering
                             Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
                         } else {
index 5e3ebcb3446c6620dc49e070181efb6d58ba6c0b..34a24308e491aa7950e1f5dfec2939db9971cb62 100644 (file)
@@ -15,7 +15,7 @@
 use errors::{Applicability, DiagnosticBuilder};
 use rustc_data_structures::sync::Lrc;
 use rustc::hir;
-use rustc::hir::def::Def;
+use rustc::hir::def::{CtorOf, Def};
 use rustc::hir::def_id::DefId;
 use rustc::traits;
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
@@ -417,7 +417,12 @@ pub fn resolve_ufcs(
                 if let Some(variant_def) = variant_def {
                     check_type_alias_enum_variants_enabled(tcx, span);
 
-                    let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
+                    // Braced variants generate unusable names in value namespace (reserved for
+                    // possible future use), so variants resolved as associated items may refer to
+                    // them as well. It's ok to use the variant's id as a ctor id since an
+                    // error will be reported on any use of such resolution anyway.
+                    let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id);
+                    let def = Def::Ctor(ctor_def_id, CtorOf::Variant, variant_def.ctor_kind);
                     tcx.check_stability(def.def_id(), Some(expr_id), span);
                     return Ok(def);
                 }
index 1054619f0f808c042ba62ca9af551d78618556bd..b11bd9c2408bf75506a5e25e4105ce25cbf42b24 100644 (file)
@@ -86,7 +86,7 @@
 use crate::astconv::{AstConv, PathSeg};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath};
-use rustc::hir::def::{CtorKind, Def};
+use rustc::hir::def::{CtorOf, CtorKind, Def};
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -1863,7 +1863,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     for ((_, discr), v) in def.discriminants(tcx).zip(vs) {
         // Check for duplicate discriminant values
         if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
-            let variant_did = def.variants[VariantIdx::new(i)].did;
+            let variant_did = def.variants[VariantIdx::new(i)].def_id;
             let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did).unwrap();
             let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
             let i_span = match variant_i.node.disr_expr {
@@ -3693,7 +3693,8 @@ fn suggest_field_name(variant: &'tcx ty::VariantDef,
         let names = variant.fields.iter().filter_map(|field| {
             // ignore already set fields and private fields from non-local crates
             if skip.iter().any(|x| *x == field.ident.as_str()) ||
-               (variant.did.krate != LOCAL_CRATE && field.vis != Visibility::Public) {
+               (!variant.def_id.is_local() && field.vis != Visibility::Public)
+            {
                 None
             } else {
                 Some(&field.ident.name)
@@ -3705,7 +3706,7 @@ fn suggest_field_name(variant: &'tcx ty::VariantDef,
 
     fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> {
         variant.fields.iter().filter(|field| {
-            let def_scope = self.tcx.adjust_ident(field.ident, variant.did, self.body_id).1;
+            let def_scope = self.tcx.adjust_ident(field.ident, variant.def_id, self.body_id).1;
             field.vis.is_accessible_from(def_scope, self.tcx)
         })
         .map(|field| field.ident.name)
@@ -3823,7 +3824,7 @@ fn check_expr_struct_fields(&self,
 
         // Type-check each field.
         for field in ast_fields {
-            let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
+            let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
             let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
                 seen_fields.insert(ident, field.span);
                 self.write_field_index(field.hir_id, i);
@@ -4237,7 +4238,7 @@ fn check_expr_kind(
                         self.set_tainted_by_errors();
                         tcx.types.err
                     }
-                    Def::VariantCtor(_, CtorKind::Fictive) => {
+                    Def::Ctor(_, _, CtorKind::Fictive) => {
                         report_unexpected_variant_def(tcx, &def, expr.span, qpath);
                         tcx.types.err
                     }
@@ -5317,10 +5318,7 @@ fn could_remove_semicolon(
     ) -> Option<Span> {
         // Be helpful when the user wrote `{... expr;}` and
         // taking the `;` off is enough to fix the error.
-        let last_stmt = match blk.stmts.last() {
-            Some(s) => s,
-            None => return None,
-        };
+        let last_stmt = blk.stmts.last()?;
         let last_expr = match last_stmt.node {
             hir::StmtKind::Semi(ref e) => e,
             _ => return None,
@@ -5333,7 +5331,7 @@ fn could_remove_semicolon(
         Some(original_span.with_lo(original_span.hi() - BytePos(1)))
     }
 
-    // Rewrite `SelfCtor` to `StructCtor`
+    // Rewrite `SelfCtor` to `Ctor`
     pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>) {
         let tcx = self.tcx;
         if let Def::SelfCtor(impl_def_id) = def {
@@ -5343,8 +5341,9 @@ pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>)
             match adt_def {
                 Some(adt_def) if adt_def.has_ctor() => {
                     let variant = adt_def.non_enum_variant();
-                    let def = Def::StructCtor(variant.did, variant.ctor_kind);
-                    (def, variant.did, tcx.type_of(variant.did))
+                    let ctor_def_id = variant.ctor_def_id.unwrap();
+                    let def = Def::Ctor(ctor_def_id, CtorOf::Struct, variant.ctor_kind);
+                    (def, ctor_def_id, tcx.type_of(ctor_def_id))
                 }
                 _ => {
                     let mut err = tcx.sess.struct_span_err(span,
@@ -5416,7 +5415,7 @@ pub fn instantiate_value_path(&self,
         let mut user_self_ty = None;
         let mut is_alias_variant_ctor = false;
         match def {
-            Def::VariantCtor(_, _) => {
+            Def::Ctor(_, CtorOf::Variant, _) => {
                 if let Some(self_ty) = self_ty {
                     let adt_def = self_ty.ty_adt_def().unwrap();
                     user_self_ty = Some(UserSelfTy {
index c0739db3df6a2ad51f4bd441c0fd04e46313ddfd..8960c9acafa6e87852041dd26ed4500aad0deefb 100644 (file)
@@ -446,8 +446,8 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: hir::HirId) {
                 tcx.predicates_of(def_id);
             }
 
-            if !struct_def.is_struct() {
-                convert_variant_ctor(tcx, struct_def.hir_id());
+            if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
+                convert_variant_ctor(tcx, ctor_hir_id);
             }
         }
 
@@ -556,21 +556,24 @@ fn convert_enum_variant_types<'a, 'tcx>(
 
         // Convert the ctor, if any. This also registers the variant as
         // an item.
-        convert_variant_ctor(tcx, variant.node.data.hir_id());
+        if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() {
+            convert_variant_ctor(tcx, ctor_hir_id);
+        }
     }
 }
 
 fn convert_variant<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    did: DefId,
+    variant_did: Option<DefId>,
+    ctor_did: Option<DefId>,
     ident: Ident,
     discr: ty::VariantDiscr,
     def: &hir::VariantData,
     adt_kind: ty::AdtKind,
-    attribute_def_id: DefId
+    parent_did: DefId
 ) -> ty::VariantDef {
     let mut seen_fields: FxHashMap<ast::Ident, Span> = Default::default();
-    let hir_id = tcx.hir().as_local_hir_id(did).unwrap();
+    let hir_id = tcx.hir().as_local_hir_id(variant_did.unwrap_or(parent_did)).unwrap();
     let fields = def
         .fields()
         .iter()
@@ -599,17 +602,19 @@ fn convert_variant<'a, 'tcx>(
         })
         .collect();
     let recovered = match def {
-        hir::VariantData::Struct(_, _, r) => *r,
+        hir::VariantData::Struct(_, r) => *r,
         _ => false,
     };
-    ty::VariantDef::new(tcx,
-        did,
+    ty::VariantDef::new(
+        tcx,
         ident,
+        variant_did,
+        ctor_did,
         discr,
         fields,
-        adt_kind,
         CtorKind::from_hir(def),
-        attribute_def_id,
+        adt_kind,
+        parent_did,
         recovered,
     )
 }
@@ -627,58 +632,52 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
     let (kind, variants) = match item.node {
         ItemKind::Enum(ref def, _) => {
             let mut distance_from_explicit = 0;
-            (
-                AdtKind::Enum,
-                def.variants
-                    .iter()
-                    .map(|v| {
-                        let did = tcx.hir().local_def_id_from_hir_id(v.node.data.hir_id());
-                        let discr = if let Some(ref e) = v.node.disr_expr {
-                            distance_from_explicit = 0;
-                            ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
-                        } else {
-                            ty::VariantDiscr::Relative(distance_from_explicit)
-                        };
-                        distance_from_explicit += 1;
+            let variants = def.variants
+                .iter()
+                .map(|v| {
+                    let variant_did = Some(tcx.hir().local_def_id_from_hir_id(v.node.id));
+                    let ctor_did = v.node.data.ctor_hir_id()
+                        .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+
+                    let discr = if let Some(ref e) = v.node.disr_expr {
+                        distance_from_explicit = 0;
+                        ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
+                    } else {
+                        ty::VariantDiscr::Relative(distance_from_explicit)
+                    };
+                    distance_from_explicit += 1;
 
-                        convert_variant(tcx, did, v.node.ident, discr, &v.node.data, AdtKind::Enum,
-                                        did)
-                    })
-                    .collect(),
-            )
+                    convert_variant(tcx, variant_did, ctor_did, v.node.ident, discr,
+                                    &v.node.data, AdtKind::Enum, def_id)
+                })
+                .collect();
+
+            (AdtKind::Enum, variants)
         }
         ItemKind::Struct(ref def, _) => {
-            // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
-            let ctor_id = if !def.is_struct() {
-                Some(tcx.hir().local_def_id_from_hir_id(def.hir_id()))
-            } else {
-                None
-            };
-            (
-                AdtKind::Struct,
-                std::iter::once(convert_variant(
-                    tcx,
-                    ctor_id.unwrap_or(def_id),
-                    item.ident,
-                    ty::VariantDiscr::Relative(0),
-                    def,
-                    AdtKind::Struct,
-                    def_id
-                )).collect(),
-            )
-        }
-        ItemKind::Union(ref def, _) => (
-            AdtKind::Union,
-            std::iter::once(convert_variant(
-                tcx,
-                def_id,
-                item.ident,
-                ty::VariantDiscr::Relative(0),
-                def,
-                AdtKind::Union,
-                def_id
-            )).collect(),
-        ),
+            let variant_did = None;
+            let ctor_did = def.ctor_hir_id()
+                .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+
+            let variants = std::iter::once(convert_variant(
+                tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def,
+                AdtKind::Struct, def_id,
+            )).collect();
+
+            (AdtKind::Struct, variants)
+        }
+        ItemKind::Union(ref def, _) => {
+            let variant_did = None;
+            let ctor_did = def.ctor_hir_id()
+                .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id));
+
+            let variants = std::iter::once(convert_variant(
+                tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def,
+                AdtKind::Union, def_id,
+            )).collect();
+
+            (AdtKind::Union, variants)
+        },
         _ => bug!(),
     };
     tcx.alloc_adt_def(def_id, kind, variants, repr)
@@ -889,8 +888,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
 
     let node = tcx.hir().get_by_hir_id(hir_id);
     let parent_def_id = match node {
-        Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_)
-        | Node::StructCtor(_) | Node::Field(_) => {
+        Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) |
+        Node::Ctor(..) | Node::Field(_) => {
             let parent_id = tcx.hir().get_parent_item(hir_id);
             Some(tcx.hir().local_def_id_from_hir_id(parent_id))
         }
@@ -1135,13 +1134,33 @@ fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span:
 }
 
 fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
+    checked_type_of(tcx, def_id, true).unwrap()
+}
+
+/// Same as [`type_of`] but returns [`Option`] instead of failing.
+///
+/// If you want to fail anyway, you can set the `fail` parameter to true, but in this case,
+/// you'd better just call [`type_of`] directly.
+pub fn checked_type_of<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+    fail: bool,
+) -> Option<Ty<'tcx>> {
     use rustc::hir::*;
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
+    let hir_id = match tcx.hir().as_local_hir_id(def_id) {
+        Some(hir_id) => hir_id,
+        None => {
+            if !fail {
+                return None;
+            }
+            bug!("invalid node");
+        }
+    };
 
     let icx = ItemCtxt::new(tcx, def_id);
 
-    match tcx.hir().get_by_hir_id(hir_id) {
+    Some(match tcx.hir().get_by_hir_id(hir_id) {
         Node::TraitItem(item) => match item.node {
             TraitItemKind::Method(..) => {
                 let substs = InternalSubsts::identity_for_item(tcx, def_id);
@@ -1149,6 +1168,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             }
             TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
             TraitItemKind::Type(_, None) => {
+                if !fail {
+                    return None;
+                }
                 span_bug!(item.span, "associated type missing default");
             }
         },
@@ -1230,6 +1252,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
                 | ItemKind::GlobalAsm(..)
                 | ItemKind::ExternCrate(..)
                 | ItemKind::Use(..) => {
+                    if !fail {
+                        return None;
+                    }
                     span_bug!(
                         item.span,
                         "compute_type_of_item: unexpected item type: {:?}",
@@ -1248,8 +1273,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             ForeignItemKind::Type => tcx.mk_foreign(def_id),
         },
 
-        Node::StructCtor(&ref def)
-        | Node::Variant(&Spanned {
+        Node::Ctor(&ref def) | Node::Variant(&Spanned {
             node: hir::VariantKind { data: ref def, .. },
             ..
         }) => match *def {
@@ -1269,7 +1293,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             ..
         }) => {
             if gen.is_some() {
-                return tcx.typeck_tables_of(def_id).node_type(hir_id);
+                return Some(tcx.typeck_tables_of(def_id).node_type(hir_id));
             }
 
             let substs = ty::ClosureSubsts {
@@ -1347,6 +1371,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
                             }
                             // Sanity check to make sure everything is as expected.
                             if !found_const {
+                                if !fail {
+                                    return None;
+                                }
                                 bug!("no arg matching AnonConst in path")
                             }
                             match path.def {
@@ -1362,24 +1389,37 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
                                     for param in &generics.params {
                                         if let ty::GenericParamDefKind::Const = param.kind {
                                             if param_index == arg_index {
-                                                return tcx.type_of(param.def_id);
+                                                return Some(tcx.type_of(param.def_id));
                                             }
                                             param_index += 1;
                                         }
                                     }
                                     // This is no generic parameter associated with the arg. This is
                                     // probably from an extra arg where one is not needed.
-                                    return tcx.types.err;
+                                    return Some(tcx.types.err);
                                 }
                                 Def::Err => tcx.types.err,
-                                x => bug!("unexpected const parent path def {:?}", x),
+                                x => {
+                                    if !fail {
+                                        return None;
+                                    }
+                                    bug!("unexpected const parent path def {:?}", x);
+                                }
+                            }
+                        }
+                        x => {
+                            if !fail {
+                                return None;
                             }
+                            bug!("unexpected const parent path {:?}", x);
                         }
-                        x => bug!("unexpected const parent path {:?}", x),
                     }
                 }
 
                 x => {
+                    if !fail {
+                        return None;
+                    }
                     bug!("unexpected const parent in type_of_def_id(): {:?}", x);
                 }
             }
@@ -1390,13 +1430,21 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
             hir::GenericParamKind::Const { ref ty, .. } => {
                 icx.to_ty(ty)
             }
-            x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
+            x => {
+                if !fail {
+                    return None;
+                }
+                bug!("unexpected non-type Node::GenericParam: {:?}", x)
+            },
         },
 
         x => {
+            if !fail {
+                return None;
+            }
             bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
         }
-    }
+    })
 }
 
 fn find_existential_constraints<'a, 'tcx>(
@@ -1627,17 +1675,12 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig
             compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
         }
 
-        StructCtor(&VariantData::Tuple(ref fields, ..))
-        | Variant(&Spanned {
-            node:
-                hir::VariantKind {
-                    data: VariantData::Tuple(ref fields, ..),
-                    ..
-                },
+        Ctor(data) | Variant(Spanned {
+            node: hir::VariantKind { data, ..  },
             ..
-        }) => {
+        }) if data.ctor_hir_id().is_some() => {
             let ty = tcx.type_of(tcx.hir().get_parent_did_by_hir_id(hir_id));
-            let inputs = fields
+            let inputs = data.fields()
                 .iter()
                 .map(|f| tcx.type_of(tcx.hir().local_def_id_from_hir_id(f.hir_id)));
             ty::Binder::bind(tcx.mk_fn_sig(
index b2c2b233c81ab3402d7dfc5e2844198de63668b6..3ddc18284b302a9bc7ef36eda6ddc14096f2d1e6 100644 (file)
 
 use std::iter;
 
+pub use collect::checked_type_of;
+
 pub struct TypeAndSubsts<'tcx> {
     substs: SubstsRef<'tcx>,
     ty: Ty<'tcx>,
index 20eae5d88351b457d4785be89e753dff09ca905d..f2406bd8540b5b804bde26bbdd1687a0bef150bf 100644 (file)
@@ -75,7 +75,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                 self.visit_node_helper(item.hir_id);
 
                 if let hir::VariantData::Tuple(..) = *struct_def {
-                    self.visit_node_helper(struct_def.hir_id());
+                    self.visit_node_helper(struct_def.ctor_hir_id().unwrap());
                 }
             }
 
@@ -84,7 +84,7 @@ fn visit_item(&mut self, item: &hir::Item) {
 
                 for variant in &enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.node.data {
-                        self.visit_node_helper(variant.node.data.hir_id());
+                        self.visit_node_helper(variant.node.data.ctor_hir_id().unwrap());
                     }
                 }
             }
index c2f79207a562469ef6e1b86e6ce22408037f0eb2..9b9a6bace96b10fbf35454ab9201b4ceee089fe2 100644 (file)
@@ -79,7 +79,7 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
             _ => unsupported()
         },
 
-        Node::Variant(_) | Node::StructCtor(_) => {}
+        Node::Variant(_) | Node::Ctor(..) => {}
 
         _ => unsupported()
     }
index 50c8d5adfa3702d255dcddf5bd5a8a0ca0ed5986..ac686e40076eb54a8de4e6923c7a7a5728fc1c9f 100644 (file)
@@ -136,7 +136,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                 self.add_inferreds_for_item(item.hir_id);
 
                 if let hir::VariantData::Tuple(..) = *struct_def {
-                    self.add_inferreds_for_item(struct_def.hir_id());
+                    self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap());
                 }
             }
 
@@ -145,7 +145,7 @@ fn visit_item(&mut self, item: &hir::Item) {
 
                 for variant in &enum_def.variants {
                     if let hir::VariantData::Tuple(..) = variant.node.data {
-                        self.add_inferreds_for_item(variant.node.data.hir_id());
+                        self.add_inferreds_for_item(variant.node.data.ctor_hir_id().unwrap());
                     }
                 }
             }
index 880f67281b9679bfe85e50d6f2e75706b2d26038..d9a63969fec972c9eb212979570649c4f852b9c3 100644 (file)
@@ -88,9 +88,7 @@ pub fn try_inline(
         Def::Variant(..) => return None,
         // Assume that enum variants and struct types are re-exported next to
         // their constructors.
-        Def::VariantCtor(..) |
-        Def::StructCtor(..) |
-        Def::SelfCtor(..) => return Some(Vec::new()),
+        Def::Ctor(..) | Def::SelfCtor(..) => return Some(Vec::new()),
         Def::Mod(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Module);
             clean::ModuleItem(build_module(cx, did, visited))
@@ -212,15 +210,20 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
     };
 
     let predicates = cx.tcx.predicates_of(did);
+    let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
+    let decl = (did, sig).clean(cx);
+    let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx);
     clean::Function {
-        decl: (did, sig).clean(cx),
-        generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
+        decl,
+        generics,
         header: hir::FnHeader {
             unsafety: sig.unsafety(),
             abi: sig.abi(),
             constness,
             asyncness: hir::IsAsync::NotAsync,
-        }
+        },
+        all_types,
+        ret_types,
     }
 }
 
index ba4481733d592cab99a8381dd8f5d4569e37d008..31f757c87b23e6586c3b9480bea361744eb63670 100644 (file)
@@ -1084,9 +1084,10 @@ fn get_poly_trait(&self) -> Option<PolyTrait> {
 
     fn get_trait_type(&self) -> Option<Type> {
         if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
-            return Some(trait_.clone());
+            Some(trait_.clone())
+        } else {
+            None
         }
-        None
     }
 }
 
@@ -1325,6 +1326,16 @@ pub enum WherePredicate {
     EqPredicate { lhs: Type, rhs: Type },
 }
 
+impl WherePredicate {
+    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
+        match *self {
+            WherePredicate::BoundPredicate { ref bounds, .. } => Some(bounds),
+            WherePredicate::RegionPredicate { ref bounds, .. } => Some(bounds),
+            _ => None,
+        }
+    }
+}
+
 impl Clean<WherePredicate> for hir::WherePredicate {
     fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
         match *self {
@@ -1461,6 +1472,25 @@ pub enum GenericParamDefKind {
     },
 }
 
+impl GenericParamDefKind {
+    pub fn is_type(&self) -> bool {
+        match *self {
+            GenericParamDefKind::Type { .. } => true,
+            _ => false,
+        }
+    }
+
+    pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
+        match *self {
+            GenericParamDefKind::Type { did, .. } => {
+                rustc_typeck::checked_type_of(cx.tcx, did, false).map(|t| t.clean(cx))
+            }
+            GenericParamDefKind::Const { ref ty, .. } => Some(ty.clone()),
+            GenericParamDefKind::Lifetime => None,
+        }
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
 pub struct GenericParamDef {
     pub name: String,
@@ -1472,12 +1502,25 @@ impl GenericParamDef {
     pub fn is_synthetic_type_param(&self) -> bool {
         match self.kind {
             GenericParamDefKind::Lifetime |
-            GenericParamDefKind::Const { .. } => {
-                false
-            }
+            GenericParamDefKind::Const { .. } => false,
             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
         }
     }
+
+    pub fn is_type(&self) -> bool {
+        self.kind.is_type()
+    }
+
+    pub fn get_type(&self, cx: &DocContext<'_>) -> Option<Type> {
+        self.kind.get_type(cx)
+    }
+
+    pub fn get_bounds(&self) -> Option<&[GenericBound]> {
+        match self.kind {
+            GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
+            _ => None,
+        }
+    }
 }
 
 impl Clean<GenericParamDef> for ty::GenericParamDef {
@@ -1714,12 +1757,122 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics {
     }
 }
 
+/// The point of this function is to replace bounds with types.
+///
+/// i.e. `[T, U]` when you have the following bounds: `T: Display, U: Option<T>` will return
+/// `[Display, Option]` (we just returns the list of the types, we don't care about the
+/// wrapped types in here).
+fn get_real_types(
+    generics: &Generics,
+    arg: &Type,
+    cx: &DocContext<'_>,
+) -> FxHashSet<Type> {
+    let arg_s = arg.to_string();
+    let mut res = FxHashSet::default();
+    if arg.is_full_generic() {
+        if let Some(where_pred) = generics.where_predicates.iter().find(|g| {
+            match g {
+                &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
+                _ => false,
+            }
+        }) {
+            let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
+            for bound in bounds.iter() {
+                match *bound {
+                    GenericBound::TraitBound(ref poly_trait, _) => {
+                        for x in poly_trait.generic_params.iter() {
+                            if !x.is_type() {
+                                continue
+                            }
+                            if let Some(ty) = x.get_type(cx) {
+                                let adds = get_real_types(generics, &ty, cx);
+                                if !adds.is_empty() {
+                                    res.extend(adds);
+                                } else if !ty.is_full_generic() {
+                                    res.insert(ty);
+                                }
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            }
+        }
+        if let Some(bound) = generics.params.iter().find(|g| {
+            g.is_type() && g.name == arg_s
+        }) {
+            for bound in bound.get_bounds().unwrap_or_else(|| &[]) {
+                if let Some(ty) = bound.get_trait_type() {
+                    let adds = get_real_types(generics, &ty, cx);
+                    if !adds.is_empty() {
+                        res.extend(adds);
+                    } else if !ty.is_full_generic() {
+                        res.insert(ty.clone());
+                    }
+                }
+            }
+        }
+    } else {
+        res.insert(arg.clone());
+        if let Some(gens) = arg.generics() {
+            for gen in gens.iter() {
+                if gen.is_full_generic() {
+                    let adds = get_real_types(generics, gen, cx);
+                    if !adds.is_empty() {
+                        res.extend(adds);
+                    }
+                } else {
+                    res.insert(gen.clone());
+                }
+            }
+        }
+    }
+    res
+}
+
+/// Return the full list of types when bounds have been resolved.
+///
+/// i.e. `fn foo<A: Display, B: Option<A>>(x: u32, y: B)` will return
+/// `[u32, Display, Option]`.
+pub fn get_all_types(
+    generics: &Generics,
+    decl: &FnDecl,
+    cx: &DocContext<'_>,
+) -> (Vec<Type>, Vec<Type>) {
+    let mut all_types = FxHashSet::default();
+    for arg in decl.inputs.values.iter() {
+        if arg.type_.is_self_type() {
+            continue;
+        }
+        let args = get_real_types(generics, &arg.type_, cx);
+        if !args.is_empty() {
+            all_types.extend(args);
+        } else {
+            all_types.insert(arg.type_.clone());
+        }
+    }
+
+    let ret_types = match decl.output {
+        FunctionRetTy::Return(ref return_type) => {
+            let mut ret = get_real_types(generics, &return_type, cx);
+            if ret.is_empty() {
+                ret.insert(return_type.clone());
+            }
+            ret.into_iter().collect()
+        }
+        _ => Vec::new(),
+    };
+    (all_types.into_iter().collect(), ret_types)
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Method {
     pub generics: Generics,
     pub decl: FnDecl,
     pub header: hir::FnHeader,
     pub defaultness: Option<hir::Defaultness>,
+    pub all_types: Vec<Type>,
+    pub ret_types: Vec<Type>,
 }
 
 impl<'a> Clean<Method> for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId,
@@ -1728,11 +1881,14 @@ fn clean(&self, cx: &DocContext<'_>) -> Method {
         let (generics, decl) = enter_impl_trait(cx, || {
             (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx))
         });
+        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
         Method {
             decl,
             generics,
             header: self.0.header,
             defaultness: self.3,
+            all_types,
+            ret_types,
         }
     }
 }
@@ -1742,6 +1898,8 @@ pub struct TyMethod {
     pub header: hir::FnHeader,
     pub decl: FnDecl,
     pub generics: Generics,
+    pub all_types: Vec<Type>,
+    pub ret_types: Vec<Type>,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -1749,6 +1907,8 @@ pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
     pub header: hir::FnHeader,
+    pub all_types: Vec<Type>,
+    pub ret_types: Vec<Type>,
 }
 
 impl Clean<Item> for doctree::Function {
@@ -1763,6 +1923,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
         } else {
             hir::Constness::NotConst
         };
+        let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -1775,6 +1936,8 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                 decl,
                 generics,
                 header: hir::FnHeader { constness, ..self.header },
+                all_types,
+                ret_types,
             }),
         }
     }
@@ -1862,7 +2025,7 @@ fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
         FnDecl {
             inputs: (&self.0.inputs[..], self.1).clean(cx),
             output: self.0.output.clean(cx),
-            attrs: Attributes::default()
+            attrs: Attributes::default(),
         }
     }
 }
@@ -2044,10 +2207,13 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                 let (generics, decl) = enter_impl_trait(cx, || {
                     (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
                 });
+                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
                 TyMethodItem(TyMethod {
                     header: sig.header,
                     decl,
                     generics,
+                    all_types,
+                    ret_types,
                 })
             }
             hir::TraitItemKind::Type(ref bounds, ref default) => {
@@ -2145,6 +2311,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                     ty::ImplContainer(_) => true,
                     ty::TraitContainer(_) => self.defaultness.has_value()
                 };
+                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
                 if provided {
                     let constness = if cx.tcx.is_min_const_fn(self.def_id) {
                         hir::Constness::Const
@@ -2161,6 +2328,8 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                             asyncness: hir::IsAsync::NotAsync,
                         },
                         defaultness: Some(self.defaultness),
+                        all_types,
+                        ret_types,
                     })
                 } else {
                     TyMethodItem(TyMethod {
@@ -2171,7 +2340,9 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                             abi: sig.abi(),
                             constness: hir::Constness::NotConst,
                             asyncness: hir::IsAsync::NotAsync,
-                        }
+                        },
+                        all_types,
+                        ret_types,
                     })
                 }
             }
@@ -2420,6 +2591,13 @@ pub fn bindings(&self) -> Option<&[TypeBinding]> {
             _ => None
         }
     }
+
+    pub fn is_full_generic(&self) -> bool {
+        match *self {
+            Type::Generic(_) => true,
+            _ => false,
+        }
+    }
 }
 
 impl GetDefId for Type {
@@ -3133,7 +3311,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
             visibility: None,
             stability: self.stab.clean(cx),
             deprecation: self.depr.clean(cx),
-            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.def.hir_id()),
+            def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
             inner: VariantItem(Variant {
                 kind: self.def.clean(cx),
             }),
@@ -3171,13 +3349,13 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
         };
         Item {
             name: Some(self.ident.clean(cx)),
-            attrs: inline::load_attrs(cx, self.did),
-            source: cx.tcx.def_span(self.did).clean(cx),
+            attrs: inline::load_attrs(cx, self.def_id),
+            source: cx.tcx.def_span(self.def_id).clean(cx),
             visibility: Some(Inherited),
-            def_id: self.did,
+            def_id: self.def_id,
             inner: VariantItem(Variant { kind }),
-            stability: get_stability(cx, self.did),
-            deprecation: get_deprecation(cx, self.did),
+            stability: get_stability(cx, self.def_id),
+            deprecation: get_deprecation(cx, self.def_id),
         }
     }
 }
@@ -3191,12 +3369,11 @@ pub enum VariantKind {
 
 impl Clean<VariantKind> for hir::VariantData {
     fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
-        if self.is_struct() {
-            VariantKind::Struct(self.clean(cx))
-        } else if self.is_unit() {
-            VariantKind::CLike
-        } else {
-            VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
+        match self {
+            hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
+            hir::VariantData::Tuple(..) =>
+                VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()),
+            hir::VariantData::Unit(..) => VariantKind::CLike,
         }
     }
 }
@@ -3850,6 +4027,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                 let (generics, decl) = enter_impl_trait(cx, || {
                     (generics.clean(cx), (&**decl, &names[..]).clean(cx))
                 });
+                let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
                 ForeignFunctionItem(Function {
                     decl,
                     generics,
@@ -3859,6 +4037,8 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                         constness: hir::Constness::NotConst,
                         asyncness: hir::IsAsync::NotAsync,
                     },
+                    all_types,
+                    ret_types,
                 })
             }
             hir::ForeignItemKind::Static(ref ty, mutbl) => {
index 46e76d60d7d726e44066cd8116452a3ad37cf8fb..3cf6b32b07c4c0868d6a22e3e053cdd6607f2f8b 100644 (file)
@@ -529,21 +529,21 @@ fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
             for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
                 let diag = ctxt.sess().diagnostic();
 
-                let name = attr.ident_str();
+                let name = attr.name_or_empty();
                 if attr.is_word() {
-                    if name == Some("no_default_passes") {
+                    if name == "no_default_passes" {
                         report_deprecated_attr("no_default_passes", diag);
                         if default_passes == passes::DefaultPassOption::Default {
                             default_passes = passes::DefaultPassOption::None;
                         }
                     }
                 } else if let Some(value) = attr.value_str() {
-                    let sink = match name {
-                        Some("passes") => {
+                    let sink = match name.get() {
+                        "passes" => {
                             report_deprecated_attr("passes = \"...\"", diag);
                             &mut manual_passes
                         },
-                        Some("plugins") => {
+                        "plugins" => {
                             report_deprecated_attr("plugins = \"...\"", diag);
                             eprintln!("WARNING: #![doc(plugins = \"...\")] no longer functions; \
                                       see CVE-2018-1000622");
@@ -556,7 +556,7 @@ fn report_deprecated_attr(name: &str, diag: &errors::Handler) {
                     }
                 }
 
-                if attr.is_word() && name == Some("document_private_items") {
+                if attr.is_word() && name == "document_private_items" {
                     if default_passes == passes::DefaultPassOption::Default {
                         default_passes = passes::DefaultPassOption::Private;
                     }
index 9c54b40b422aedd3fbe713f0599b5b8a8838fa0a..7a528e50e9c3f8aaccc00936d51d84ed3a3d2920 100644 (file)
@@ -125,6 +125,7 @@ pub struct Enum {
 
 pub struct Variant {
     pub name: Name,
+    pub id: hir::HirId,
     pub attrs: hir::HirVec<ast::Attribute>,
     pub def: hir::VariantData,
     pub stab: Option<attr::Stability>,
index 445ce0637662d4918faf168e0ac9ca9d9ac869a1..866d8fe682a7b4a71b04cf4a59d42b2fce80600b 100644 (file)
@@ -446,7 +446,7 @@ fn to_json(&self) -> Json {
                 }
                 Json::Array(data)
             }
-            None => Json::Null
+            None => Json::Null,
         }
     }
 }
@@ -455,19 +455,27 @@ fn to_json(&self) -> Json {
 #[derive(Debug)]
 struct IndexItemFunctionType {
     inputs: Vec<Type>,
-    output: Option<Type>,
+    output: Option<Vec<Type>>,
 }
 
 impl ToJson for IndexItemFunctionType {
     fn to_json(&self) -> Json {
         // If we couldn't figure out a type, just write `null`.
-        if self.inputs.iter().chain(self.output.iter()).any(|ref i| i.name.is_none()) {
+        let mut iter = self.inputs.iter();
+        if match self.output {
+            Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
+            None => iter.any(|ref i| i.name.is_none()),
+        } {
             Json::Null
         } else {
             let mut data = Vec::with_capacity(2);
             data.push(self.inputs.to_json());
             if let Some(ref output) = self.output {
-                data.push(output.to_json());
+                if output.len() > 1 {
+                    data.push(output.to_json());
+                } else {
+                    data.push(output[0].to_json());
+                }
             }
             Json::Array(data)
         }
@@ -562,23 +570,23 @@ pub fn run(mut krate: clean::Crate,
     // going to emit HTML
     if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
         for attr in attrs.lists("doc") {
-            match (attr.ident_str(), attr.value_str()) {
-                (Some("html_favicon_url"), Some(s)) => {
+            match (attr.name_or_empty().get(), attr.value_str()) {
+                ("html_favicon_url", Some(s)) => {
                     scx.layout.favicon = s.to_string();
                 }
-                (Some("html_logo_url"), Some(s)) => {
+                ("html_logo_url", Some(s)) => {
                     scx.layout.logo = s.to_string();
                 }
-                (Some("html_playground_url"), Some(s)) => {
+                ("html_playground_url", Some(s)) => {
                     markdown::PLAYGROUND.with(|slot| {
                         let name = krate.name.clone();
                         *slot.borrow_mut() = Some((Some(name), s.to_string()));
                     });
                 }
-                (Some("issue_tracker_base_url"), Some(s)) => {
+                ("issue_tracker_base_url", Some(s)) => {
                     scx.issue_tracker_base_url = Some(s.to_string());
                 }
-                (Some("html_no_source"), None) if attr.is_word() => {
+                ("html_no_source", None) if attr.is_word() => {
                     scx.include_sources = false;
                 }
                 _ => {}
@@ -3751,7 +3759,7 @@ fn render_attributes(w: &mut fmt::Formatter<'_>, it: &clean::Item) -> fmt::Resul
     let mut attrs = String::new();
 
     for attr in &it.attrs.other_attrs {
-        if !attr.ident_str().map_or(false, |name| ATTRIBUTE_WHITELIST.contains(&name)) {
+        if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty().get()) {
             continue;
         }
         if let Some(s) = render_attribute(&attr.meta().unwrap()) {
@@ -5025,20 +5033,26 @@ fn make_item_keywords(it: &clean::Item) -> String {
 }
 
 fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
-    let decl = match item.inner {
-        clean::FunctionItem(ref f) => &f.decl,
-        clean::MethodItem(ref m) => &m.decl,
-        clean::TyMethodItem(ref m) => &m.decl,
-        _ => return None
+    let (all_types, ret_types) = match item.inner {
+        clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types),
+        clean::MethodItem(ref m) => (&m.all_types, &m.ret_types),
+        clean::TyMethodItem(ref m) => (&m.all_types, &m.ret_types),
+        _ => return None,
     };
 
-    let inputs = decl.inputs.values.iter().map(|arg| get_index_type(&arg.type_)).collect();
-    let output = match decl.output {
-        clean::FunctionRetTy::Return(ref return_type) => Some(get_index_type(return_type)),
-        _ => None
+    let inputs = all_types.iter().map(|arg| {
+        get_index_type(&arg)
+    }).filter(|a| a.name.is_some()).collect();
+    let output = ret_types.iter().map(|arg| {
+        get_index_type(&arg)
+    }).filter(|a| a.name.is_some()).collect::<Vec<_>>();
+    let output = if output.is_empty() {
+        None
+    } else {
+        Some(output)
     };
 
-    Some(IndexItemFunctionType { inputs: inputs, output: output })
+    Some(IndexItemFunctionType { inputs, output })
 }
 
 fn get_index_type(clean_type: &clean::Type) -> Type {
index fef6910f40a574c5f62d6f259b25f1b6d25c88ee..aad7eb627bfe2603a463789a504ef879f579b541 100644 (file)
@@ -714,7 +714,10 @@ if (!DOMTokenList.prototype.remove) {
                 }
                 lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
                 if (lev_distance <= MAX_LEV_DISTANCE) {
-                    lev_distance = Math.min(checkGenerics(obj, val), lev_distance);
+                    // The generics didn't match but the name kinda did so we give it
+                    // a levenshtein distance value that isn't *this* good so it goes
+                    // into the search results but not too high.
+                    lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
                 } else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
                     // We can check if the type we're looking for is inside the generics!
                     var olength = obj[GENERICS_DATA].length;
@@ -752,13 +755,26 @@ if (!DOMTokenList.prototype.remove) {
                 var lev_distance = MAX_LEV_DISTANCE + 1;
 
                 if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
-                    var tmp = checkType(obj.type[OUTPUT_DATA], val, literalSearch);
-                    if (literalSearch === true && tmp === true) {
-                        return true;
+                    var ret = obj.type[OUTPUT_DATA];
+                    if (!obj.type[OUTPUT_DATA].length) {
+                        ret = [ret];
                     }
-                    lev_distance = Math.min(tmp, lev_distance);
-                    if (lev_distance === 0) {
-                        return 0;
+                    for (var x = 0; x < ret.length; ++x) {
+                        var r = ret[x];
+                        if (typeof r === "string") {
+                            r = [r];
+                        }
+                        var tmp = checkType(r, val, literalSearch);
+                        if (literalSearch === true) {
+                            if (tmp === true) {
+                                return true;
+                            }
+                            continue;
+                        }
+                        lev_distance = Math.min(tmp, lev_distance);
+                        if (lev_distance === 0) {
+                            return 0;
+                        }
                     }
                 }
                 return literalSearch === true ? false : lev_distance;
index 787f3c7f48004f342502e9a19b7279a89d357868..5314255ac322b9d58b221c898e792dc68a48d270 100644 (file)
@@ -1195,7 +1195,7 @@ pre.rust {
        border-top: 2px solid;
 }
 
-#titles > div:not(:last-child):not(.selected) {
+#titles > div:not(:last-child) {
        margin-right: 1px;
        width: calc(33.3% - 1px);
 }
index e756ab60ccc6d28e3def52300cf4caffdfaf4a28..e3bb41ae672f450f2dcd50b1e5edc6d65a3bcc66 100644 (file)
@@ -189,6 +189,10 @@ a.test-arrow {
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; }
 .stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; }
 
+.stab > code {
+       color: #ddd;
+}
+
 #help > div {
        background: #4d4d4d;
        border-color: #bfbfbf;
index a294f6f2ff12326aba5961de5041297e7d551461..dd4d028c6c9bee60d6d0a3a09cc158c3161709a8 100644 (file)
@@ -190,6 +190,10 @@ a.test-arrow {
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
 .stab.portability { background: #C4ECFF; border-color: #7BA5DB; }
 
+.stab > code {
+       color: #000;
+}
+
 #help > div {
        background: #e9e9e9;
        border-color: #bfbfbf;
index 7c1a61449a26fc2e8220fc00ee47e2ed5599f1e6..ee182237b49ec540d8f5546a8e7adf3decf04d91 100644 (file)
@@ -344,9 +344,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                                 .and_then(|(def, fragment)| {
                                     // Constructors are picked up in the type namespace.
                                     match def {
-                                        Def::StructCtor(..)
-                                        | Def::VariantCtor(..)
-                                        | Def::SelfCtor(..) => None,
+                                        Def::Ctor(..) | Def::SelfCtor(..) => None,
                                         _ => Some((def, fragment))
                                     }
                                 }),
index b4db121fb530ac3bddb5604bf72d32082098cc2a..a7e2b2155e9f34dacd0d2598655482edab98522c 100644 (file)
@@ -141,9 +141,10 @@ pub fn visit_enum_def(&mut self, it: &hir::Item,
             name,
             variants: def.variants.iter().map(|v| Variant {
                 name: v.node.ident.name,
+                id: v.node.id,
                 attrs: v.node.attrs.clone(),
-                stab: self.stability(v.node.data.hir_id()),
-                depr: self.deprecation(v.node.data.hir_id()),
+                stab: self.stability(v.node.id),
+                depr: self.deprecation(v.node.id),
                 def: v.node.data.clone(),
                 whence: v.span,
             }).collect(),
@@ -420,8 +421,8 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 // Struct and variant constructors and proc macro stubs always show up alongside
                 // their definitions, we've already processed them so just discard these.
                 match path.def {
-                    Def::StructCtor(..) | Def::VariantCtor(..) | Def::SelfCtor(..) |
-                    Def::Macro(_, MacroKind::ProcMacroStub) => return,
+                    Def::Ctor(..) | Def::SelfCtor(..) | Def::Macro(_, MacroKind::ProcMacroStub) =>
+                        return,
                     _ => {}
                 }
 
index 1a6b58f35b398c30047935133a59816534760925..b2eaf956d0e2d5b66dfc2ee8ab77ed3a38a656a8 100644 (file)
@@ -72,3 +72,7 @@ wasm-bindgen-threads = []
 # https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/std_detect/Cargo.toml
 std_detect_file_io = []
 std_detect_dlsym_getauxval = []
+
+[package.metadata.fortanix-sgx]
+# Maximum possible number of threads when testing
+threads = 125
index 97c67f562a7dfac171052b854ec03ce49b91219f..f723a2b0bb281eeab9677338cc2cefb40df7ac44 100644 (file)
@@ -975,7 +975,7 @@ mod tests {
     use crate::path::Path;
 
     #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
     fn test_self_exe_path() {
         let path = current_exe();
         assert!(path.is_ok());
@@ -989,6 +989,7 @@ fn test_self_exe_path() {
     fn test() {
         assert!((!Path::new("test-path").is_absolute()));
 
+        #[cfg(not(target_env = "sgx"))]
         current_dir().unwrap();
     }
 
index 688d9c1aabbee60b8dcce1e14e17a99146305ef3..796908b0df943cd6526668bca1eae3e29557e26f 100644 (file)
@@ -960,17 +960,27 @@ pub fn acosh(self) -> f32 {
     pub fn atanh(self) -> f32 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
-    /// Returns max if self is greater than max, and min if self is less than min.
-    /// Otherwise this returns self.  Panics if min > max, min equals NaN, or max equals NaN.
+
+    /// Restrict a value to a certain interval unless it is NaN.
+    ///
+    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+    /// less than `min`. Otherwise this returns `self`.
+    ///
+    /// Not that this function returns NaN if the initial value was NaN as
+    /// well.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(clamp)]
-    /// assert!((-3.0f32).clamp(-2.0f32, 1.0f32) == -2.0f32);
-    /// assert!((0.0f32).clamp(-2.0f32, 1.0f32) == 0.0f32);
-    /// assert!((2.0f32).clamp(-2.0f32, 1.0f32) == 1.0f32);
-    /// assert!((std::f32::NAN).clamp(-2.0f32, 1.0f32).is_nan());
+    /// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0);
+    /// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
+    /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
+    /// assert!((std::f32::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[unstable(feature = "clamp", issue = "44095")]
     #[inline]
index b171e1c7ac93feb600cfcebff8cf45fbe88c4945..e679a7d2e8c0455591527b5f5fcb478bd1dd74eb 100644 (file)
@@ -882,17 +882,26 @@ pub fn atanh(self) -> f64 {
         0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
     }
 
-    /// Returns max if self is greater than max, and min if self is less than min.
-    /// Otherwise this returns self.  Panics if min > max, min equals NaN, or max equals NaN.
+    /// Restrict a value to a certain interval unless it is NaN.
+    ///
+    /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+    /// less than `min`. Otherwise this returns `self`.
+    ///
+    /// Not that this function returns NaN if the initial value was NaN as
+    /// well.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(clamp)]
-    /// assert!((-3.0f64).clamp(-2.0f64, 1.0f64) == -2.0f64);
-    /// assert!((0.0f64).clamp(-2.0f64, 1.0f64) == 0.0f64);
-    /// assert!((2.0f64).clamp(-2.0f64, 1.0f64) == 1.0f64);
-    /// assert!((std::f64::NAN).clamp(-2.0f64, 1.0f64).is_nan());
+    /// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
+    /// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
+    /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
+    /// assert!((std::f64::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[unstable(feature = "clamp", issue = "44095")]
     #[inline]
index 8c3d0da0a7e405836a723ff096c7b5aa2b9560c3..dfff44b88ea784e3598285ca9555f18db0d5255c 100644 (file)
@@ -2095,7 +2095,7 @@ fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::prelude::*;
 
index f5a87cc3ea67a057759d62e562b8e9b3927fca08..eaa6a070154f7ed684401b0424c13d92159ffcf3 100644 (file)
@@ -941,7 +941,10 @@ fn to_socket_addr_str_u16() {
         assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53)));
 
         let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+        #[cfg(not(target_env = "sgx"))]
         assert!(tsa(("localhost", 23924)).unwrap().contains(&a));
+        #[cfg(target_env = "sgx")]
+        let _ = a;
     }
 
     #[test]
@@ -953,7 +956,10 @@ fn to_socket_addr_str() {
         assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53"));
 
         let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924);
+        #[cfg(not(target_env = "sgx"))]
         assert!(tsa("localhost:23924").unwrap().contains(&a));
+        #[cfg(target_env = "sgx")]
+        let _ = a;
     }
 
     #[test]
index ce0c5c0bb0dc7d25dad48eaf0c3e83e763dc49fc..7e14de7cc4f4a8b0b49eb8c2b77a7ba5a43d50db 100644 (file)
@@ -929,12 +929,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
+    use crate::fmt;
     use crate::io::{ErrorKind, IoVec, IoVecMut};
     use crate::io::prelude::*;
     use crate::net::*;
     use crate::net::test::{next_test_ip4, next_test_ip6};
     use crate::sync::mpsc::channel;
-    use crate::sys_common::AsInner;
     use crate::time::{Instant, Duration};
     use crate::thread;
 
@@ -1129,7 +1129,7 @@ fn connect(i: usize, addr: SocketAddr) {
                 connect(i + 1, addr);
                 t!(stream.write(&[i as u8]));
             });
-            t.join().ok().unwrap();
+            t.join().ok().expect("thread panicked");
         }
     }
 
@@ -1162,7 +1162,7 @@ fn connect(i: usize, addr: SocketAddr) {
                 connect(i + 1, addr);
                 t!(stream.write(&[99]));
             });
-            t.join().ok().unwrap();
+            t.join().ok().expect("thread panicked");
         }
     }
 
@@ -1377,6 +1377,8 @@ fn tcp_clone_two_write() {
     }
 
     #[test]
+    // FIXME: https://github.com/fortanix/rust-sgx/issues/110
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn shutdown_smoke() {
         each_ip(&mut |addr| {
             let a = t!(TcpListener::bind(&addr));
@@ -1397,6 +1399,8 @@ fn shutdown_smoke() {
     }
 
     #[test]
+    // FIXME: https://github.com/fortanix/rust-sgx/issues/110
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn close_readwrite_smoke() {
         each_ip(&mut |addr| {
             let a = t!(TcpListener::bind(&addr));
@@ -1550,30 +1554,51 @@ fn clone_accept_concurrent() {
 
     #[test]
     fn debug() {
-        let name = if cfg!(windows) {"socket"} else {"fd"};
+        #[cfg(not(target_env = "sgx"))]
+        fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+            addr
+        }
+        #[cfg(target_env = "sgx")]
+        fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
+            addr.to_string()
+        }
+
+        #[cfg(unix)]
+        use crate::os::unix::io::AsRawFd;
+        #[cfg(target_env = "sgx")]
+        use crate::os::fortanix_sgx::io::AsRawFd;
+        #[cfg(not(windows))]
+        fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
+            addr.as_raw_fd()
+        }
+        #[cfg(windows)]
+        fn render_inner(addr: &dyn crate::os::windows::io::AsRawSocket) -> impl fmt::Debug {
+            addr.as_raw_socket()
+        }
+
+        let inner_name = if cfg!(windows) {"socket"} else {"fd"};
         let socket_addr = next_test_ip4();
 
         let listener = t!(TcpListener::bind(&socket_addr));
-        let listener_inner = listener.0.socket().as_inner();
         let compare = format!("TcpListener {{ addr: {:?}, {}: {:?} }}",
-                              socket_addr, name, listener_inner);
+                              render_socket_addr(&socket_addr),
+                              inner_name,
+                              render_inner(&listener));
         assert_eq!(format!("{:?}", listener), compare);
 
-        let stream = t!(TcpStream::connect(&("localhost",
-                                                 socket_addr.port())));
-        let stream_inner = stream.0.socket().as_inner();
-        let compare = format!("TcpStream {{ addr: {:?}, \
-                              peer: {:?}, {}: {:?} }}",
-                              stream.local_addr().unwrap(),
-                              stream.peer_addr().unwrap(),
-                              name,
-                              stream_inner);
+        let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
+        let compare = format!("TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
+                              render_socket_addr(&stream.local_addr().unwrap()),
+                              render_socket_addr(&stream.peer_addr().unwrap()),
+                              inner_name,
+                              render_inner(&stream));
         assert_eq!(format!("{:?}", stream), compare);
     }
 
     // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code
     //        no longer has rounding errors.
     #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     #[test]
     fn timeouts() {
         let addr = next_test_ip4();
@@ -1601,6 +1626,7 @@ fn timeouts() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_read_timeout() {
         let addr = next_test_ip4();
         let listener = t!(TcpListener::bind(&addr));
@@ -1618,6 +1644,7 @@ fn test_read_timeout() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_read_with_timeout() {
         let addr = next_test_ip4();
         let listener = t!(TcpListener::bind(&addr));
@@ -1661,6 +1688,7 @@ fn test_timeout_zero_duration() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn nodelay() {
         let addr = next_test_ip4();
         let _listener = t!(TcpListener::bind(&addr));
@@ -1675,6 +1703,7 @@ fn nodelay() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn ttl() {
         let ttl = 100;
 
@@ -1691,6 +1720,7 @@ fn ttl() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)]
     fn set_nonblocking() {
         let addr = next_test_ip4();
         let listener = t!(TcpListener::bind(&addr));
@@ -1712,6 +1742,7 @@ fn set_nonblocking() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn peek() {
         each_ip(&mut |addr| {
             let (txdone, rxdone) = channel();
@@ -1743,6 +1774,7 @@ fn peek() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn connect_timeout_valid() {
         let listener = TcpListener::bind("127.0.0.1:0").unwrap();
         let addr = listener.local_addr().unwrap();
index 89fefd9d1d5e069f8bd3a58398b6b4782b1cf5f5..e2991cbdd88226c3abf6ba2cbf7b08ca82f71678 100644 (file)
@@ -36,12 +36,16 @@ pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
 // all want to use ports. This function figures out which workspace
 // it is running in and assigns a port range based on it.
 fn base_port() -> u16 {
-    let cwd = env::current_dir().unwrap();
+    let cwd = if cfg!(target_env = "sgx") {
+        String::from("sgx")
+    } else {
+        env::current_dir().unwrap().into_os_string().into_string().unwrap()
+    };
     let dirs = ["32-opt", "32-nopt",
                 "musl-64-opt", "cross-opt",
                 "64-opt", "64-nopt", "64-opt-vg", "64-debug-opt",
-                "all-opt", "snap3", "dist"];
+                "all-opt", "snap3", "dist", "sgx"];
     dirs.iter().enumerate().find(|&(_, dir)| {
-        cwd.to_str().unwrap().contains(dir)
+        cwd.contains(dir)
     }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600
 }
index b42a8123042694b52b89e48ba8f1adf8e9c6b627..836d1f8be632bfbf1ea9debae5de6072590439af 100644 (file)
@@ -837,7 +837,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::ErrorKind;
     use crate::net::*;
index ea3fcd8ce28597df108ef63dd077a81c4245240f..4048bc4da2557f0434c33bd9ef8aca9c90a972b1 100644 (file)
@@ -3801,7 +3801,7 @@ macro_rules! tp(
             });
         );
 
-        if cfg!(unix) {
+        if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
             tp!("", "foo", "foo");
             tp!("foo", "bar", "foo/bar");
             tp!("foo/", "bar", "foo/bar");
@@ -3960,7 +3960,7 @@ macro_rules! tfn(
         tfn!("foo", "bar", "bar");
         tfn!("foo", "", "");
         tfn!("", "foo", "foo");
-        if cfg!(unix) {
+        if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
             tfn!(".", "foo", "./foo");
             tfn!("foo/", "bar", "bar");
             tfn!("foo/.", "bar", "bar");
index ad86acbb47de420c6ed67365fd2cf118c81a18f1..054b398b01f26a414bef98dae648e2458c3d883b 100644 (file)
@@ -1621,7 +1621,7 @@ fn report(self) -> i32 {
     }
 }
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests {
     use crate::io::prelude::*;
 
index c383f21dcd752ae327a13ad9289977d2387467a2..2e8182671dd6f4d84299e39c8559b4073a06f5a8 100644 (file)
@@ -705,6 +705,7 @@ fn wait_until() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
@@ -724,6 +725,7 @@ fn wait_timeout_wait() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_until_wait() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
@@ -748,6 +750,7 @@ fn wait_timeout_until_instant_satisfy() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_until_wake() {
         let pair = Arc::new((Mutex::new(false), Condvar::new()));
         let pair_copy = pair.clone();
@@ -771,6 +774,7 @@ fn wait_timeout_until_wake() {
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn wait_timeout_wake() {
         let m = Arc::new(Mutex::new(()));
         let c = Arc::new(Condvar::new());
index 90c5c50c23b9cc3304d78e434be7aba27f9191db..4ed2bfb175a464da1bcb1ba0a3d46810dd3ac3a2 100644 (file)
@@ -1951,7 +1951,7 @@ fn stress() {
         for _ in 0..10000 {
             assert_eq!(rx.recv().unwrap(), 1);
         }
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1977,7 +1977,7 @@ fn stress_shared() {
             });
         }
         drop(tx);
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1996,8 +1996,8 @@ fn send_from_outside_runtime() {
                 tx2.send(1).unwrap();
             }
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        t1.join().ok().expect("thread panicked");
+        t2.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2011,7 +2011,7 @@ fn recv_from_outside_runtime() {
         for _ in 0..40 {
             tx.send(1).unwrap();
         }
-        t.join().ok().unwrap();
+        t.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2026,8 +2026,8 @@ fn no_runtime() {
             tx1.send(1).unwrap();
             assert_eq!(rx2.recv().unwrap(), 2);
         });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
+        t1.join().ok().expect("thread panicked");
+        t2.join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -2225,6 +2225,7 @@ fn recv(rx: Receiver<Box<i32>>, i: i32) {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn oneshot_single_thread_recv_timeout() {
         let (tx, rx) = channel();
         tx.send(()).unwrap();
@@ -2235,6 +2236,7 @@ fn oneshot_single_thread_recv_timeout() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_two_threads() {
         let (tx, rx) = channel();
         let stress = stress_factor() + 100;
@@ -2265,6 +2267,7 @@ fn stress_recv_timeout_two_threads() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn recv_timeout_upgrade() {
         let (tx, rx) = channel::<()>();
         let timeout = Duration::from_millis(1);
@@ -2276,6 +2279,7 @@ fn recv_timeout_upgrade() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_shared() {
         let (tx, rx) = channel();
         let stress = stress_factor() + 100;
@@ -2306,6 +2310,7 @@ fn stress_recv_timeout_shared() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn very_long_recv_timeout_wont_panic() {
         let (tx, rx) = channel::<()>();
         let join_handle = thread::spawn(move || {
@@ -2325,6 +2330,7 @@ fn recv_a_lot() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn shared_recv_timeout() {
         let (tx, rx) = channel();
         let total = 5;
@@ -2550,6 +2556,7 @@ fn smoke_shared() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn recv_timeout() {
         let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout));
@@ -2639,6 +2646,7 @@ fn stress() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_two_threads() {
         let (tx, rx) = sync_channel::<i32>(0);
 
@@ -2662,6 +2670,7 @@ fn stress_recv_timeout_two_threads() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn stress_recv_timeout_shared() {
         const AMT: u32 = 1000;
         const NTHREADS: u32 = 8;
index d7502c61eff2c044359123990b4ca321134344b6..49a234e1158044b4de1f4f76ea4e67ab30f86ca4 100644 (file)
@@ -33,11 +33,9 @@ pub const fn zero() -> Instant {
         Instant { t: 0 }
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        let diff = self.t
-            .checked_sub(other.t)
-            .expect("second instant is later than self");
-        Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        let diff = self.t.checked_sub(other.t)?;
+        Some(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
index 9db3e85ca9c8b3505bb779010f2503348e1f6067..881ad5c0aeb14b849b1347e62b1005440567becb 100644 (file)
@@ -137,10 +137,8 @@ pub fn actually_monotonic() -> bool {
         false
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-            panic!("specified instant was later than self")
-        })
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        self.t.sub_timespec(&other.t).ok()
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
index 7426f7be9e9615063e4fc419883c78e046451e5f..85ec8be4aae69bf157b89a7e6c86209279a20dc6 100644 (file)
@@ -1,3 +1,5 @@
+#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
+
 use core::sync::atomic::{AtomicUsize, Ordering};
 use crate::io::Write;
 
 #[macro_use]
 pub mod usercalls;
 
+#[cfg(not(test))]
 global_asm!(include_str!("entry.S"));
 
+#[cfg(not(test))]
 #[no_mangle]
 unsafe extern "C" fn tcs_init(secondary: bool) {
     // Be very careful when changing this code: it runs before the binary has been
@@ -48,6 +52,7 @@
 // FIXME: this item should only exist if this is linked into an executable
 // (main function exists). If this is a library, the crate author should be
 // able to specify this
+#[cfg(not(test))]
 #[no_mangle]
 extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) {
     // FIXME: how to support TLS in library mode?
index 83411cb5b4c26fd9e58672510b2093c9f7f88be0..de86394b4b88cdfd8013b57b089988f60567df04 100644 (file)
@@ -49,7 +49,7 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-#[no_mangle]
+#[cfg_attr(not(test), no_mangle)]
 pub extern "C" fn panic_msg(msg: &str) -> ! {
     let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
     usercalls::exit(true)
index b2a812c7231da4159a88462b82e18e63151f532c..6b9ab7e383c01565f27fc18664ae768f1af6d5c8 100644 (file)
 const TLS_KEYS: usize = 128; // Same as POSIX minimum
 const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS;
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"]
 static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT;
 macro_rules! dup {
     ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* ));
     (() $($val:tt)*) => ([$($val),*])
 }
-static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = [
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-    AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
-];
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"]
+static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0)));
 
 extern "C" {
     fn get_tls_ptr() -> *const u8;
index b787bd1a5abac44b088bc00fe8b8dea2d3f006ab..449a5fe5ae3082a837e1f5d7c744e1bb7228c8a3 100644 (file)
@@ -188,8 +188,13 @@ impl<T: ?Sized> User<T> where T: UserSafe {
     // from outside as obtained by `super::alloc`.
     fn new_uninit_bytes(size: usize) -> Self {
         unsafe {
-            let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed");
-            User(NonNull::new_userref(T::from_raw_sized(ptr as _, size)))
+            // Mustn't call alloc with size 0.
+            let ptr = if size > 0 {
+                super::alloc(size, T::align_of()).expect("User memory allocation failed") as _
+            } else {
+                T::align_of() as _ // dangling pointer ok for size 0
+            };
+            User(NonNull::new_userref(T::from_raw_sized(ptr, size)))
         }
     }
 
index 94dc8ec25b5872e5f9339c0c6260388740944b02..98eb8397436bfeb98b06852cea90c6e541c5e5ed 100644 (file)
@@ -4,6 +4,8 @@
 
 // Using a SpinMutex because we never want to exit the enclave waiting for the
 // allocator.
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE"]
 static DLMALLOC: SpinMutex<dlmalloc::Dlmalloc> = SpinMutex::new(dlmalloc::DLMALLOC_INIT);
 
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
index b73bf9213b7727ec677bebff4af9618db050a990..a84ab4138761ef6fd672e59c3c9e5aabe045eeea 100644 (file)
@@ -5,9 +5,12 @@
 use crate::sys_common::FromInner;
 use crate::slice;
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
 static ARGS: AtomicUsize = AtomicUsize::new(0);
 type ArgsStore = Vec<OsString>;
 
+#[cfg_attr(test, allow(dead_code))]
 pub unsafe fn init(argc: isize, argv: *const *const u8) {
     if argc != 0 {
         let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _);
index e9a7684f74d00f3b6b26568799bf8695c3ffa3a3..f9a76f0baf51a383ef5c18ce02b3c01befd17b55 100644 (file)
@@ -32,7 +32,8 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
         mutex.lock()
     }
 
-    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, _dur: Duration) -> bool {
+        mutex.unlock(); // don't hold the lock while panicking
         panic!("timeout not supported in SGX");
     }
 
index 81f33c16294c3679d666929b7ba1d35e3a076af0..0e7602a906efa36e795c7d62b0fbf7a12a8328c5 100644 (file)
@@ -41,12 +41,29 @@ fn from_inner(inner: FileDesc) -> Socket {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct TcpStream {
     inner: Socket,
     peer_addr: Option<String>,
 }
 
+impl fmt::Debug for TcpStream {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut res = f.debug_struct("TcpStream");
+
+        if let Some(ref addr) = self.inner.local_addr {
+            res.field("addr", addr);
+        }
+
+        if let Some(ref peer) = self.peer_addr {
+            res.field("peer", peer);
+        }
+
+        res.field("fd", &self.inner.inner.as_inner())
+            .finish()
+    }
+}
+
 fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result<String> {
     match result {
         Ok(saddr) => Ok(saddr.to_string()),
@@ -75,16 +92,32 @@ pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
         Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) })
     }
 
-    pub fn connect_timeout(addr: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
+    pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result<TcpStream> {
+        if dur == Duration::default() {
+            return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                      "cannot set a 0 duration timeout"));
+        }
         Self::connect(Ok(addr)) // FIXME: ignoring timeout
     }
 
-    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        sgx_ineffective(())
+    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        match dur {
+            Some(dur) if dur == Duration::default() => {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
+            _ => sgx_ineffective(())
+        }
     }
 
-    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        sgx_ineffective(())
+    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
+        match dur {
+            Some(dur) if dur == Duration::default() => {
+                return Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                          "cannot set a 0 duration timeout"));
+            }
+            _ => sgx_ineffective(())
+        }
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
@@ -174,11 +207,24 @@ fn from_inner((inner, peer_addr): (Socket, Option<String>)) -> TcpStream {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct TcpListener {
     inner: Socket,
 }
 
+impl fmt::Debug for TcpListener {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut res = f.debug_struct("TcpListener");
+
+        if let Some(ref addr) = self.inner.local_addr {
+            res.field("addr", addr);
+        }
+
+        res.field("fd", &self.inner.inner.as_inner())
+            .finish()
+    }
+}
+
 impl TcpListener {
     pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
         let addr = io_err_to_addr(addr)?;
index 2725e66ce5de4001d43489e1e517b8264e0118fd..0bb7b897058db08878ca2e28df709d6384deb398 100644 (file)
@@ -73,7 +73,11 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
 }
 
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE"]
 static ENV: AtomicUsize = AtomicUsize::new(0);
+#[cfg_attr(test, linkage = "available_externally")]
+#[export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE"]
 static ENV_INIT: Once = Once::new();
 type EnvStore = Mutex<HashMap<OsString, OsString>>;
 
index 372760bbf26b4221959e1f7a243932d630785c5e..7b113267865b6cde073e02309fdeb9a99459a19b 100644 (file)
@@ -1,6 +1,9 @@
+#[cfg(not(test))]
 use crate::alloc::{self, Layout};
 use crate::num::NonZeroUsize;
+#[cfg(not(test))]
 use crate::slice;
+#[cfg(not(test))]
 use crate::str;
 
 use super::waitqueue::{
@@ -147,6 +150,7 @@ pub unsafe fn write_unlock(&self) {
 
     // only used by __rust_rwlock_unlock below
     #[inline]
+    #[cfg_attr(test, allow(dead_code))]
     unsafe fn unlock(&self) {
         let rguard = self.readers.lock();
         let wguard = self.writer.lock();
@@ -161,9 +165,11 @@ unsafe fn unlock(&self) {
     pub unsafe fn destroy(&self) {}
 }
 
+#[cfg(not(test))]
 const EINVAL: i32 = 22;
 
 // used by libunwind port
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -173,6 +179,7 @@ pub unsafe fn destroy(&self) {}
     return 0;
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -181,6 +188,7 @@ pub unsafe fn destroy(&self) {}
     (*p).write();
     return 0;
 }
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
     if p.is_null() {
@@ -192,6 +200,7 @@ pub unsafe fn destroy(&self) {}
 
 // the following functions are also used by the libunwind port. They're
 // included here to make sure parallel codegen and LTO don't mess things up.
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
     if s < 0 {
@@ -203,17 +212,20 @@ pub unsafe fn destroy(&self) {}
     }
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 // NB. used by both libunwind and libpanic_abort
 pub unsafe extern "C" fn __rust_abort() {
     crate::sys::abort_internal();
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 {
     alloc::alloc(Layout::from_size_align_unchecked(size, align))
 }
 
+#[cfg(not(test))]
 #[no_mangle]
 pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) {
     alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align))
@@ -221,15 +233,13 @@ pub unsafe fn destroy(&self) {}
 
 #[cfg(test)]
 mod tests {
-
     use super::*;
     use core::array::FixedSizeArray;
-    use crate::mem::MaybeUninit;
-    use crate::{mem, ptr};
+    use crate::mem::{self, MaybeUninit};
 
-    // The below test verifies that the bytes of initialized RWLock are the ones
-    // we use in libunwind.
-    // If they change we need to update src/UnwindRustSgx.h in libunwind.
+    // Verify that the bytes of initialized RWLock are the same as in
+    // libunwind. If they change, `src/UnwindRustSgx.h` in libunwind needs to
+    // be changed too.
     #[test]
     fn test_c_rwlock_initializer() {
         const RWLOCK_INIT: &[u8] = &[
@@ -251,11 +261,28 @@ fn test_c_rwlock_initializer() {
             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
         ];
 
-        let mut init = MaybeUninit::<RWLock>::zeroed();
-        init.set(RWLock::new());
-        assert_eq!(
-            mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(),
-            RWLOCK_INIT
-        );
+        #[inline(never)]
+        fn zero_stack() {
+            test::black_box(MaybeUninit::<[RWLock; 16]>::zeroed());
+        }
+
+        #[inline(never)]
+        unsafe fn rwlock_new(init: &mut MaybeUninit<RWLock>) {
+            init.set(RWLock::new());
+        }
+
+        unsafe {
+            // try hard to make sure that the padding/unused bytes in RWLock
+            // get initialized as 0. If the assertion below fails, that might
+            // just be an issue with the test code and not with the value of
+            // RWLOCK_INIT.
+            zero_stack();
+            let mut init = MaybeUninit::<RWLock>::zeroed();
+            rwlock_new(&mut init);
+            assert_eq!(
+                mem::transmute::<_, [u8; 128]>(init.into_initialized()).as_slice(),
+                RWLOCK_INIT
+            )
+        };
     }
 }
index c0e7c824615c88a824c84005fbfcf42b6ced8fe4..e63fa2bed65d56700f5a67447f5bc134602bf205 100644 (file)
@@ -6,6 +6,7 @@ pub unsafe fn new() -> Handler {
     }
 }
 
+#[cfg_attr(test, allow(dead_code))]
 pub unsafe fn init() {
 }
 
index 13569062ac184cfd99675c800c0c0bb9d33de149..a3637723ba1bd05611daf419248562941587fce7 100644 (file)
@@ -1,3 +1,4 @@
+#![cfg_attr(test, allow(dead_code))] // why is this necessary?
 use crate::boxed::FnBox;
 use crate::ffi::CStr;
 use crate::io;
@@ -33,7 +34,11 @@ pub(super) fn run(self) {
         }
     }
 
+    #[cfg_attr(test, linkage = "available_externally")]
+    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"]
     static TASK_QUEUE_INIT: Once = Once::new();
+    #[cfg_attr(test, linkage = "available_externally")]
+    #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"]
     static mut TASK_QUEUE: Option<Mutex<Vec<Task>>> = None;
 
     pub(super) fn lock() -> MutexGuard<'static, Vec<Task>> {
index e4f789c3e36565db4086523f55706df3820db074..4659f7ba71fe07a50ba895aa8bffc9236c258f56 100644 (file)
@@ -14,8 +14,8 @@ pub fn now() -> Instant {
         Instant(usercalls::insecure_time())
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        self.0 - other.0
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        self.0.checked_sub(other.0)
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
index 1dbf2afbf4987e7b47368d7ecca303b69200922f..3f5e03ddad69eee59068aa76735f8a98ba1cc1a0 100644 (file)
@@ -498,6 +498,7 @@ mod tests {
         use super::*;
         use crate::sync::Arc;
         use crate::thread;
+        use crate::time::{SystemTime, Duration};
 
         #[test]
         fn sleep() {
@@ -507,7 +508,13 @@ fn sleep() {
             let t1 = thread::spawn(move || {
                 *mutex2.lock() = 1;
             });
-            thread::sleep_ms(50);
+
+            // "sleep" for 50ms
+            // FIXME: https://github.com/fortanix/rust-sgx/issues/31
+            let start = SystemTime::now();
+            let max = Duration::from_millis(50);
+            while start.elapsed().unwrap() < max {}
+
             assert_eq!(*guard, 0);
             drop(guard);
             t1.join().unwrap();
@@ -530,7 +537,8 @@ fn queue() {
         let locked = wq.lock();
 
         let t1 = thread::spawn(move || {
-            assert!(WaitQueue::notify_one(wq2.lock()).is_none())
+            // if we obtain the lock, the main thread should be waiting
+            assert!(WaitQueue::notify_one(wq2.lock()).is_ok());
         });
 
         WaitQueue::wait(locked);
index cbb0615911adf8298f58760cde61bdecdb45a4a6..6b5a89aee7d690e3229f79b165cd4e6c5f3344b6 100644 (file)
@@ -149,12 +149,11 @@ pub fn actually_monotonic() -> bool {
             true
         }
 
-        pub fn sub_instant(&self, other: &Instant) -> Duration {
+        pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+            let diff = self.t.checked_sub(other.t)?;
             let info = info();
-            let diff = self.t.checked_sub(other.t)
-                           .expect("second instant is later than self");
             let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
-            Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
+            Some(Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32))
         }
 
         pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
@@ -285,10 +284,8 @@ pub fn actually_monotonic() -> bool {
             false // last clause, used so `||` is always trailing above
         }
 
-        pub fn sub_instant(&self, other: &Instant) -> Duration {
-            self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-                panic!("specified instant was later than self")
-            })
+        pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+            self.t.sub_timespec(&other.t).ok()
         }
 
         pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
index c1228a1b75e39e35741e271eee31891b5b2cf401..3f71461eea4872f2a422b2dc86085b30eb135bb9 100644 (file)
@@ -22,8 +22,8 @@ pub fn actually_monotonic() -> bool {
         false
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
-        self.0 - other.0
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
+        self.0.checked_sub(other.0)
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
index 2c99bca70095cb5fb26427592ef2b7b24eca42b1..aa53f1194fdb43b8f8ff20a38aefe708252971d4 100644 (file)
@@ -49,17 +49,17 @@ pub const fn zero() -> Instant {
         Instant { t: Duration::from_secs(0) }
     }
 
-    pub fn sub_instant(&self, other: &Instant) -> Duration {
+    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
         // On windows there's a threshold below which we consider two timestamps
         // equivalent due to measurement error. For more details + doc link,
         // check the docs on epsilon.
         let epsilon =
             perf_counter::PerformanceCounterInstant::epsilon();
         if other.t > self.t && other.t - self.t <= epsilon {
-            return Duration::new(0, 0)
+            Some(Duration::new(0, 0))
+        } else {
+            self.t.checked_sub(other.t)
         }
-        self.t.checked_sub(other.t)
-              .expect("specified instant was later than self")
     }
 
     pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
index 7ad6b124e3a384c1f57543d2230e4b0f513421de..b73c5856b8805bdd91cee0c7a9363734694ac081 100644 (file)
@@ -530,7 +530,7 @@ fn drop(&mut self) {
 
         thread::spawn(|| {
             assert!(FOO.try_with(|_| ()).is_ok());
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -584,7 +584,7 @@ fn drop(&mut self) {
 
         thread::spawn(move|| {
             drop(S1);
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -600,7 +600,7 @@ fn drop(&mut self) {
 
         thread::spawn(move|| unsafe {
             K1.with(|s| *s.get() = Some(S1));
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     // Note that this test will deadlock if TLS destructors aren't run (this
index d856f9b465e04057c50456274ec00b42b1cbe529..6d305aed748d0dab2561fdaa3875340ab1f66c2e 100644 (file)
@@ -1499,7 +1499,7 @@ mod tests {
     fn test_unnamed_thread() {
         thread::spawn(move|| {
             assert!(thread::current().name().is_none());
-        }).join().ok().unwrap();
+        }).join().ok().expect("thread panicked");
     }
 
     #[test]
@@ -1693,6 +1693,7 @@ fn test_park_timeout_unpark_before() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_park_timeout_unpark_not_called() {
         for _ in 0..10 {
             thread::park_timeout(Duration::from_millis(10));
@@ -1700,6 +1701,7 @@ fn test_park_timeout_unpark_not_called() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn test_park_timeout_unpark_called_other_thread() {
         for _ in 0..10 {
             let th = thread::current();
@@ -1714,6 +1716,7 @@ fn test_park_timeout_unpark_called_other_thread() {
     }
 
     #[test]
+    #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn sleep_ms_smoke() {
         thread::sleep(Duration::from_millis(2));
     }
index 4c86f70ad871d6df5617bc4828ab5f7513081a56..ab1a43d6672e405296298262b05aa6fc6e169d1e 100644 (file)
@@ -212,7 +212,7 @@ pub fn now() -> Instant {
     /// ```
     #[stable(feature = "time2", since = "1.8.0")]
     pub fn duration_since(&self, earlier: Instant) -> Duration {
-        self.0.sub_instant(&earlier.0)
+        self.0.checked_sub_instant(&earlier.0).expect("supplied instant is later than self")
     }
 
     /// Returns the amount of time elapsed from another instant to this one,
@@ -233,11 +233,7 @@ pub fn duration_since(&self, earlier: Instant) -> Duration {
     /// ```
     #[unstable(feature = "checked_duration_since", issue = "58402")]
     pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
-        if self >= &earlier {
-            Some(self.0.sub_instant(&earlier.0))
-        } else {
-            None
-        }
+        self.0.checked_sub_instant(&earlier.0)
     }
 
     /// Returns the amount of time elapsed from another instant to this one,
@@ -664,20 +660,23 @@ fn instant_math_is_associative() {
 
     #[test]
     #[should_panic]
-    fn instant_duration_panic() {
+    fn instant_duration_since_panic() {
         let a = Instant::now();
         (a - Duration::new(1, 0)).duration_since(a);
     }
 
     #[test]
-    fn checked_instant_duration_nopanic() {
-        let a = Instant::now();
-        let ret = (a - Duration::new(1, 0)).checked_duration_since(a);
-        assert_eq!(ret, None);
+    fn instant_checked_duration_since_nopanic() {
+        let now = Instant::now();
+        let earlier = now - Duration::new(1, 0);
+        let later = now + Duration::new(1, 0);
+        assert_eq!(earlier.checked_duration_since(now), None);
+        assert_eq!(later.checked_duration_since(now), Some(Duration::new(1, 0)));
+        assert_eq!(now.checked_duration_since(now), Some(Duration::new(0, 0)));
     }
 
     #[test]
-    fn saturating_instant_duration_nopanic() {
+    fn instant_saturating_duration_since_nopanic() {
         let a = Instant::now();
         let ret = (a - Duration::new(1, 0)).saturating_duration_since(a);
         assert_eq!(ret, Duration::new(0,0));
index 2cbd2dfeb25d6372d9fb58b283f3055126736e45..bcc8fdf8cd4e7fc68e3955b3214d8b69e9aff66f 100644 (file)
@@ -1956,8 +1956,13 @@ pub struct EnumDef {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Variant_ {
+    /// Name of the variant.
     pub ident: Ident,
+    /// Attributes of the variant.
     pub attrs: Vec<Attribute>,
+    /// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
+    pub id: NodeId,
+    /// Fields and constructor id of the variant.
     pub data: VariantData,
     /// Explicit discriminant, e.g., `Foo = 1`.
     pub disr_expr: Option<AnonConst>,
@@ -2117,23 +2122,13 @@ pub struct StructField {
     pub attrs: Vec<Attribute>,
 }
 
-/// Fields and Ids of enum variants and structs
-///
-/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all
-/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants).
-/// One shared Id can be successfully used for these two purposes.
-/// Id of the whole enum lives in `Item`.
-///
-/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually
-/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of
-/// the variant itself" from enum variants.
-/// Id of the whole struct lives in `Item`.
+/// Fields and constructor ids of enum variants and structs.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum VariantData {
     /// Struct variant.
     ///
     /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
-    Struct(Vec<StructField>, NodeId, bool),
+    Struct(Vec<StructField>, bool),
     /// Tuple variant.
     ///
     /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
@@ -2145,36 +2140,19 @@ pub enum VariantData {
 }
 
 impl VariantData {
+    /// Return the fields of this variant.
     pub fn fields(&self) -> &[StructField] {
         match *self {
             VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields,
             _ => &[],
         }
     }
-    pub fn id(&self) -> NodeId {
+
+    /// Return the `NodeId` of this variant's constructor, if it has one.
+    pub fn ctor_id(&self) -> Option<NodeId> {
         match *self {
-            VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id,
-        }
-    }
-    pub fn is_struct(&self) -> bool {
-        if let VariantData::Struct(..) = *self {
-            true
-        } else {
-            false
-        }
-    }
-    pub fn is_tuple(&self) -> bool {
-        if let VariantData::Tuple(..) = *self {
-            true
-        } else {
-            false
-        }
-    }
-    pub fn is_unit(&self) -> bool {
-        if let VariantData::Unit(..) = *self {
-            true
-        } else {
-            false
+            VariantData::Struct(..) => None,
+            VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
         }
     }
 }
index cdfb83c6e56c8ca6f44caab293dd2af51ce5ca36..74c952b076cd72483da3bcc67a4dbc068fd63f2a 100644 (file)
@@ -222,9 +222,9 @@ macro_rules! get_meta {
                     )+
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match mi.ident_str() {
+                            match mi.name_or_empty().get() {
                                 $(
-                                    Some(stringify!($name))
+                                    stringify!($name)
                                         => if !get(mi, &mut $name) { continue 'outer },
                                 )+
                                 _ => {
@@ -252,7 +252,7 @@ macro_rules! get_meta {
                 }
             }
 
-            match meta.ident_str().expect("not a stability level") {
+            match meta.name_or_empty().get() {
                 "rustc_deprecated" => {
                     if rustc_depr.is_some() {
                         span_err!(diagnostic, item_sp, E0540,
@@ -306,10 +306,10 @@ macro_rules! get_meta {
                     let mut issue = None;
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match mi.ident_str() {
-                                Some("feature") => if !get(mi, &mut feature) { continue 'outer },
-                                Some("reason") => if !get(mi, &mut reason) { continue 'outer },
-                                Some("issue") => if !get(mi, &mut issue) { continue 'outer },
+                            match mi.name_or_empty().get() {
+                                "feature" => if !get(mi, &mut feature) { continue 'outer },
+                                "reason" => if !get(mi, &mut reason) { continue 'outer },
+                                "issue" => if !get(mi, &mut issue) { continue 'outer },
                                 _ => {
                                     handle_errors(
                                         sess,
@@ -377,10 +377,10 @@ macro_rules! get_meta {
                     for meta in metas {
                         match meta {
                             NestedMetaItem::MetaItem(mi) => {
-                                match mi.ident_str() {
-                                    Some("feature") =>
+                                match mi.name_or_empty().get() {
+                                    "feature" =>
                                         if !get(mi, &mut feature) { continue 'outer },
-                                    Some("since") =>
+                                    "since" =>
                                         if !get(mi, &mut since) { continue 'outer },
                                     _ => {
                                         handle_errors(
@@ -532,14 +532,14 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
 
             // The unwraps below may look dangerous, but we've already asserted
             // that they won't fail with the loop above.
-            match cfg.ident_str() {
-                Some("any") => mis.iter().any(|mi| {
+            match cfg.name_or_empty().get() {
+                "any" => mis.iter().any(|mi| {
                     eval_condition(mi.meta_item().unwrap(), sess, eval)
                 }),
-                Some("all") => mis.iter().all(|mi| {
+                "all" => mis.iter().all(|mi| {
                     eval_condition(mi.meta_item().unwrap(), sess, eval)
                 }),
-                Some("not") => {
+                "not" => {
                     if mis.len() != 1 {
                         span_err!(sess.span_diagnostic, cfg.span, E0536, "expected 1 cfg-pattern");
                         return false;
@@ -635,9 +635,9 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess,
                 for meta in list {
                     match meta {
                         NestedMetaItem::MetaItem(mi) => {
-                            match mi.ident_str() {
-                                Some("since") => if !get(mi, &mut since) { continue 'outer },
-                                Some("note") => if !get(mi, &mut note) { continue 'outer },
+                            match mi.name_or_empty().get() {
+                                "since" => if !get(mi, &mut since) { continue 'outer },
+                                "note" => if !get(mi, &mut note) { continue 'outer },
                                 _ => {
                                     handle_errors(
                                         sess,
@@ -729,12 +729,12 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> {
 
                 let mut recognised = false;
                 if item.is_word() {
-                    let hint = match item.ident_str() {
-                        Some("C") => Some(ReprC),
-                        Some("packed") => Some(ReprPacked(1)),
-                        Some("simd") => Some(ReprSimd),
-                        Some("transparent") => Some(ReprTransparent),
-                        name => name.and_then(|name| int_type_of_word(name)).map(ReprInt),
+                    let hint = match item.name_or_empty().get() {
+                        "C" => Some(ReprC),
+                        "packed" => Some(ReprPacked(1)),
+                        "simd" => Some(ReprSimd),
+                        "transparent" => Some(ReprTransparent),
+                        name => int_type_of_word(name).map(ReprInt),
                     };
 
                     if let Some(h) = hint {
index 1a8faa43fff7c1fc065312eb6935c09c1a652a4d..c0bd5c79b1dd107d1ef76d96b79734d43cb2cfa1 100644 (file)
@@ -22,7 +22,7 @@
 use crate::parse::{self, ParseSess, PResult};
 use crate::parse::token::{self, Token};
 use crate::ptr::P;
-use crate::symbol::Symbol;
+use crate::symbol::{keywords, LocalInternedString, Symbol};
 use crate::ThinVec;
 use crate::tokenstream::{TokenStream, TokenTree, DelimSpan};
 use crate::GLOBALS;
@@ -89,8 +89,8 @@ pub fn check_name(&self, name: &str) -> bool {
     pub fn ident(&self) -> Option<Ident> {
         self.meta_item().and_then(|meta_item| meta_item.ident())
     }
-    pub fn ident_str(&self) -> Option<&str> {
-        self.ident().map(|name| name.as_str().get())
+    pub fn name_or_empty(&self) -> LocalInternedString {
+        self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
     }
 
     /// Gets the string value if self is a MetaItem and the MetaItem is a
@@ -167,8 +167,8 @@ pub fn ident(&self) -> Option<Ident> {
             None
         }
     }
-    pub fn ident_str(&self) -> Option<&str> {
-        self.ident().map(|name| name.as_str().get())
+    pub fn name_or_empty(&self) -> LocalInternedString {
+        self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
     }
 
     pub fn value_str(&self) -> Option<Symbol> {
@@ -205,8 +205,8 @@ pub fn ident(&self) -> Option<Ident> {
             None
         }
     }
-    pub fn ident_str(&self) -> Option<&str> {
-        self.ident().map(|name| name.as_str().get())
+    pub fn name_or_empty(&self) -> LocalInternedString {
+        self.ident().unwrap_or(keywords::Invalid.ident()).name.as_str()
     }
 
     // #[attribute(name = "value")]
index 7159c949513ac280e01aa16574464a6f564780f9..18173628a2602f922cf89d8b0cb89ed675ffc295 100644 (file)
@@ -225,10 +225,9 @@ pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
 
     fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
         match vdata {
-            ast::VariantData::Struct(fields, _id, _) |
-            ast::VariantData::Tuple(fields, _id) =>
+            ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) =>
                 fields.flat_map_in_place(|field| self.configure(field)),
-            ast::VariantData::Unit(_id) => {}
+            ast::VariantData::Unit(_) => {}
         }
     }
 
index e95f05894491b670f6c5e8d9df58bd22951226f1..614967bdeb447002eef0cd67bd5604608ae19872 100644 (file)
@@ -1062,6 +1062,7 @@ fn variant(&self, span: Span, ident: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Varia
         respan(span,
                ast::Variant_ {
                    ident,
+                   id: ast::DUMMY_NODE_ID,
                    attrs: Vec::new(),
                    data: vdata,
                    disr_expr: None,
index 9beaabb0cd58ba857fc6b3175427568826aa10f9..96c89d3176ab60ad035ccf39410a064a5b502cb2 100644 (file)
@@ -1341,9 +1341,9 @@ macro_rules! gate_feature {
 impl<'a> Context<'a> {
     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
-        let name = attr.ident_str();
+        let name = attr.name_or_empty();
         for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES {
-            if name == Some(n) {
+            if name == n {
                 if let Gated(_, name, desc, ref has_feature) = *gateage {
                     if !attr.span.allows_unstable(name) {
                         gate_feature_fn!(
@@ -1373,7 +1373,7 @@ fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
             }
         }
         if !attr::is_known(attr) {
-            if name.map_or(false, |name| name.starts_with("rustc_")) {
+            if name.starts_with("rustc_") {
                 let msg = "unless otherwise specified, attributes with the prefix `rustc_` \
                            are reserved for internal compiler diagnostics";
                 gate_feature!(self, rustc_attrs, attr.span, msg);
@@ -1836,8 +1836,12 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
                 gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
             }
             ast::ExprKind::Type(..) => {
-                gate_feature_post!(&self, type_ascription, e.span,
-                                  "type ascription is experimental");
+                // To avoid noise about type ascription in common syntax errors, only emit if it
+                // is the *only* error.
+                if self.context.parse_sess.span_diagnostic.err_count() == 0 {
+                    gate_feature_post!(&self, type_ascription, e.span,
+                                       "type ascription is experimental");
+                }
             }
             ast::ExprKind::ObsoleteInPlace(..) => {
                 // these get a hard error in ast-validation
@@ -2054,12 +2058,12 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
         };
 
         for mi in list {
-            let name = match mi.ident_str() {
-                Some(name) if mi.is_word() => name,
-                _ => continue,
-            };
+            if !mi.is_word() {
+                continue;
+            }
 
-            if incomplete_features.iter().any(|f| *f == name) {
+            let name = mi.name_or_empty();
+            if incomplete_features.iter().any(|f| name == *f) {
                 span_handler.struct_span_warn(
                     mi.span(),
                     &format!(
index 5bb1d8a4b94768814c7f53004625db8dabf4b746..784d0049ac51f7069a1aecf83e0b1861a6f0b807 100644 (file)
@@ -450,9 +450,10 @@ pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis:
 }
 
 pub fn noop_visit_variant<T: MutVisitor>(variant: &mut Variant, vis: &mut T) {
-    let Spanned { node: Variant_ { ident, attrs, data, disr_expr }, span } = variant;
+    let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant;
     vis.visit_ident(ident);
     visit_attrs(attrs, vis);
+    vis.visit_id(id);
     vis.visit_variant_data(data);
     visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr));
     vis.visit_span(span);
@@ -765,11 +766,11 @@ pub fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis:
 
 pub fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut T) {
     match vdata {
-        VariantData::Struct(fields, id, _) |
+        VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)),
         VariantData::Tuple(fields, id) => {
             visit_vec(fields, |field| vis.visit_struct_field(field));
             vis.visit_id(id);
-        }
+        },
         VariantData::Unit(id) => vis.visit_id(id),
     }
 }
index 99260314054168a668e2cae42039b24c5d0df539..a0c3fe356083f76bb6031d85f11d26b933b98d76 100644 (file)
@@ -3538,22 +3538,19 @@ fn parse_assoc_expr_with(&mut self,
                 lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?;
                 continue
             } else if op == AssocOp::Colon {
+                let maybe_path = self.could_ascription_be_path(&lhs.node);
+                let next_sp = self.span;
+
                 lhs = match self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type) {
                     Ok(lhs) => lhs,
                     Err(mut err) => {
-                        err.span_label(self.span,
-                                       "expecting a type here because of type ascription");
-                        let cm = self.sess.source_map();
-                        let cur_pos = cm.lookup_char_pos(self.span.lo());
-                        let op_pos = cm.lookup_char_pos(cur_op_span.hi());
-                        if cur_pos.line != op_pos.line {
-                            err.span_suggestion(
-                                cur_op_span,
-                                "try using a semicolon",
-                                ";".to_string(),
-                                Applicability::MaybeIncorrect // speculative
-                            );
-                        }
+                        self.bad_type_ascription(
+                            &mut err,
+                            lhs_span,
+                            cur_op_span,
+                            next_sp,
+                            maybe_path,
+                        );
                         return Err(err);
                     }
                 };
@@ -3658,6 +3655,58 @@ fn parse_assoc_expr_with(&mut self,
         Ok(lhs)
     }
 
+    fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
+        self.token.is_ident() &&
+            if let ast::ExprKind::Path(..) = node { true } else { false } &&
+            !self.token.is_reserved_ident() &&           // v `foo:bar(baz)`
+            self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) ||
+            self.look_ahead(1, |t| t == &token::Lt) &&     // `foo:bar<baz`
+            self.look_ahead(2, |t| t.is_ident()) ||
+            self.look_ahead(1, |t| t == &token::Colon) &&  // `foo:bar:baz`
+            self.look_ahead(2, |t| t.is_ident()) ||
+            self.look_ahead(1, |t| t == &token::ModSep) &&  // `foo:bar::baz`
+            self.look_ahead(2, |t| t.is_ident())
+    }
+
+    fn bad_type_ascription(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        lhs_span: Span,
+        cur_op_span: Span,
+        next_sp: Span,
+        maybe_path: bool,
+    ) {
+        err.span_label(self.span, "expecting a type here because of type ascription");
+        let cm = self.sess.source_map();
+        let next_pos = cm.lookup_char_pos(next_sp.lo());
+        let op_pos = cm.lookup_char_pos(cur_op_span.hi());
+        if op_pos.line != next_pos.line {
+            err.span_suggestion(
+                cur_op_span,
+                "try using a semicolon",
+                ";".to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            if maybe_path {
+                err.span_suggestion(
+                    cur_op_span,
+                    "maybe you meant to write a path separator here",
+                    "::".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                err.note("type ascription is a nightly-only feature that lets \
+                          you annotate an expression with a type: `<expr>: <type>`");
+                err.span_note(
+                    lhs_span,
+                    "this expression expects an ascribed type after the colon",
+                );
+                err.help("this might be indicative of a syntax error elsewhere");
+            }
+        }
+    }
+
     fn parse_assoc_op_cast(&mut self, lhs: P<Expr>, lhs_span: Span,
                            expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind)
                            -> PResult<'a, P<Expr>> {
@@ -6844,7 +6893,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
             } else {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
                 let (fields, recovered) = self.parse_record_struct_body()?;
-                VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+                VariantData::Struct(fields, recovered)
             }
         // No `where` so: `struct Foo<T>;`
         } else if self.eat(&token::Semi) {
@@ -6852,7 +6901,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
         // Record-style struct definition
         } else if self.token == token::OpenDelim(token::Brace) {
             let (fields, recovered) = self.parse_record_struct_body()?;
-            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+            VariantData::Struct(fields, recovered)
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(token::Paren) {
             let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
@@ -6881,10 +6930,10 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
         let vdata = if self.token.is_keyword(keywords::Where) {
             generics.where_clause = self.parse_where_clause()?;
             let (fields, recovered) = self.parse_record_struct_body()?;
-            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+            VariantData::Struct(fields, recovered)
         } else if self.token == token::OpenDelim(token::Brace) {
             let (fields, recovered) = self.parse_record_struct_body()?;
-            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
+            VariantData::Struct(fields, recovered)
         } else {
             let token_str = self.this_token_descr();
             let mut err = self.fatal(&format!(
@@ -7708,7 +7757,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef>
                 // Parse a struct variant.
                 all_nullary = false;
                 let (fields, recovered) = self.parse_record_struct_body()?;
-                struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered);
+                struct_def = VariantData::Struct(fields, recovered);
             } else if self.check(&token::OpenDelim(token::Paren)) {
                 all_nullary = false;
                 struct_def = VariantData::Tuple(
@@ -7730,6 +7779,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef>
 
             let vr = ast::Variant_ {
                 ident,
+                id: ast::DUMMY_NODE_ID,
                 attrs: variant_attrs,
                 data: struct_def,
                 disr_expr,
index 07df14ddc722cc50b85b9582307794aa0d8e0fb4..f5a9aded8455e5a40a5bd8ec9ac60fa88e521324 100644 (file)
@@ -1550,44 +1550,47 @@ pub fn print_struct(&mut self,
                         print_finalizer: bool) -> io::Result<()> {
         self.print_ident(ident)?;
         self.print_generic_params(&generics.params)?;
-        if !struct_def.is_struct() {
-            if struct_def.is_tuple() {
-                self.popen()?;
-                self.commasep(
-                    Inconsistent, struct_def.fields(),
-                    |s, field| {
-                        s.maybe_print_comment(field.span.lo())?;
-                        s.print_outer_attributes(&field.attrs)?;
-                        s.print_visibility(&field.vis)?;
-                        s.print_type(&field.ty)
-                    }
-                )?;
-                self.pclose()?;
-            }
-            self.print_where_clause(&generics.where_clause)?;
-            if print_finalizer {
-                self.s.word(";")?;
+        match struct_def {
+            ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
+                if let ast::VariantData::Tuple(..) = struct_def {
+                    self.popen()?;
+                    self.commasep(
+                        Inconsistent, struct_def.fields(),
+                        |s, field| {
+                            s.maybe_print_comment(field.span.lo())?;
+                            s.print_outer_attributes(&field.attrs)?;
+                            s.print_visibility(&field.vis)?;
+                            s.print_type(&field.ty)
+                        }
+                    )?;
+                    self.pclose()?;
+                }
+                self.print_where_clause(&generics.where_clause)?;
+                if print_finalizer {
+                    self.s.word(";")?;
+                }
+                self.end()?;
+                self.end() // close the outer-box
             }
-            self.end()?;
-            self.end() // close the outer-box
-        } else {
-            self.print_where_clause(&generics.where_clause)?;
-            self.nbsp()?;
-            self.bopen()?;
-            self.hardbreak_if_not_bol()?;
-
-            for field in struct_def.fields() {
+            ast::VariantData::Struct(..) => {
+                self.print_where_clause(&generics.where_clause)?;
+                self.nbsp()?;
+                self.bopen()?;
                 self.hardbreak_if_not_bol()?;
-                self.maybe_print_comment(field.span.lo())?;
-                self.print_outer_attributes(&field.attrs)?;
-                self.print_visibility(&field.vis)?;
-                self.print_ident(field.ident.unwrap())?;
-                self.word_nbsp(":")?;
-                self.print_type(&field.ty)?;
-                self.s.word(",")?;
-            }
 
-            self.bclose(span)
+                for field in struct_def.fields() {
+                    self.hardbreak_if_not_bol()?;
+                    self.maybe_print_comment(field.span.lo())?;
+                    self.print_outer_attributes(&field.attrs)?;
+                    self.print_visibility(&field.vis)?;
+                    self.print_ident(field.ident.unwrap())?;
+                    self.word_nbsp(":")?;
+                    self.print_type(&field.ty)?;
+                    self.s.word(",")?;
+                }
+
+                self.bclose(span)
+            }
         }
     }
 
@@ -3266,6 +3269,7 @@ fn test_variant_to_string() {
             let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
                 ident,
                 attrs: Vec::new(),
+                id: ast::DUMMY_NODE_ID,
                 // making this up as I go.... ?
                 data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
                 disr_expr: None,
index 7dc2d007d73d6b86835075ae38af8c96336cf294..7c47c6ff79ac1f25d45f077c2887f3e67029e43d 100644 (file)
@@ -51,9 +51,9 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
     // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
     // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
     // based on the "shape".
-    let (ident, is_struct) = match *substr.fields {
-        Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
-        EnumMatching(_, _, v, _) => (v.node.ident, v.node.data.is_struct()),
+    let (ident, vdata, fields) = match substr.fields {
+        Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
+        EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields),
         EnumNonMatchingCollapsed(..) |
         StaticStruct(..) |
         StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
@@ -67,55 +67,51 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
 
     let fmt = substr.nonself_args[0].clone();
 
-    let mut stmts = match *substr.fields {
-        Struct(_, ref fields) |
-        EnumMatching(.., ref fields) => {
-            let mut stmts = vec![];
-            if !is_struct {
-                // tuple struct/"normal" variant
-                let expr =
-                    cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
-                stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
-
-                for field in fields {
-                    // Use double indirection to make sure this works for unsized types
-                    let field = cx.expr_addr_of(field.span, field.self_.clone());
-                    let field = cx.expr_addr_of(field.span, field);
-
-                    let expr = cx.expr_method_call(span,
-                                                   builder_expr.clone(),
-                                                   Ident::from_str("field"),
-                                                   vec![field]);
-
-                    // Use `let _ = expr;` to avoid triggering the
-                    // unused_results lint.
-                    stmts.push(stmt_let_undescore(cx, span, expr));
-                }
-            } else {
-                // normal struct/struct variant
-                let expr =
-                    cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
-                stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
-
-                for field in fields {
-                    let name = cx.expr_lit(field.span,
-                                           ast::LitKind::Str(field.name.unwrap().name,
-                                                             ast::StrStyle::Cooked));
-
-                    // Use double indirection to make sure this works for unsized types
-                    let field = cx.expr_addr_of(field.span, field.self_.clone());
-                    let field = cx.expr_addr_of(field.span, field);
-                    let expr = cx.expr_method_call(span,
-                                                   builder_expr.clone(),
-                                                   Ident::from_str("field"),
-                                                   vec![name, field]);
-                    stmts.push(stmt_let_undescore(cx, span, expr));
-                }
+    let mut stmts = vec![];
+    match vdata {
+        ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
+            // tuple struct/"normal" variant
+            let expr =
+                cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
+            stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
+
+            for field in fields {
+                // Use double indirection to make sure this works for unsized types
+                let field = cx.expr_addr_of(field.span, field.self_.clone());
+                let field = cx.expr_addr_of(field.span, field);
+
+                let expr = cx.expr_method_call(span,
+                                                builder_expr.clone(),
+                                                Ident::from_str("field"),
+                                                vec![field]);
+
+                // Use `let _ = expr;` to avoid triggering the
+                // unused_results lint.
+                stmts.push(stmt_let_undescore(cx, span, expr));
             }
-            stmts
         }
-        _ => unreachable!(),
-    };
+        ast::VariantData::Struct(..) => {
+            // normal struct/struct variant
+            let expr =
+                cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
+            stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
+
+            for field in fields {
+                let name = cx.expr_lit(field.span,
+                                        ast::LitKind::Str(field.name.unwrap().name,
+                                                            ast::StrStyle::Cooked));
+
+                // Use double indirection to make sure this works for unsized types
+                let field = cx.expr_addr_of(field.span, field.self_.clone());
+                let field = cx.expr_addr_of(field.span, field);
+                let expr = cx.expr_method_call(span,
+                                                builder_expr.clone(),
+                                                Ident::from_str("field"),
+                                                vec![name, field]);
+                stmts.push(stmt_let_undescore(cx, span, expr));
+            }
+        }
+    }
 
     let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]);
 
index 2bb98c1bf625cfb9363b7d86dab8513b98e5da6a..e5939e396e5c1372141a718c41e5387996f46247 100644 (file)
@@ -463,9 +463,10 @@ pub fn expand_ext(self,
                 let mut attrs = newitem.attrs.clone();
                 attrs.extend(item.attrs
                     .iter()
-                    .filter(|a| a.ident_str().map_or(false, |name| {
-                        ["allow", "warn", "deny", "forbid", "stable", "unstable"].contains(&name)
-                    }))
+                    .filter(|a| {
+                        ["allow", "warn", "deny", "forbid", "stable", "unstable"]
+                            .contains(&a.name_or_empty().get())
+                    })
                     .cloned());
                 push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
             }
@@ -1539,6 +1540,7 @@ fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> St
             }
         }
 
+        let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false };
         match (just_spans.is_empty(), named_idents.is_empty()) {
             (false, false) => {
                 cx.span_bug(self.span,
@@ -1547,9 +1549,10 @@ fn summarise_struct(&self, cx: &mut ExtCtxt<'_>, struct_def: &VariantData) -> St
             }
             // named fields
             (_, false) => Named(named_idents),
-            // empty structs
-            _ if struct_def.is_struct() => Named(named_idents),
-            _ => Unnamed(just_spans, struct_def.is_tuple()),
+            // unnamed fields
+            (false, _) => Unnamed(just_spans, is_tuple),
+            // empty
+            _ => Named(Vec::new()),
         }
     }
 
index f4771a52034d8de5700b1fad1ce9a32f80b4d0db..48d087ee43cd58b73bbb6b85064cad7b0703ae04 100644 (file)
@@ -17,7 +17,6 @@
 #![feature(rustc_attrs)]
 #![feature(specialization)]
 #![feature(step_trait)]
-#![cfg_attr(not(stage0), feature(stdsimd))]
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
index e8d215a562e2c36a05b0a2d903bffbdf3d324822..f61aa4284d29b65030568fd0c0c8e241b78484b4 100644 (file)
@@ -179,6 +179,10 @@ pub fn gensymed(self) -> Self {
         with_interner(|interner| interner.gensymed(self))
     }
 
+    pub fn is_gensymed(self) -> bool {
+        with_interner(|interner| interner.is_gensymed(self))
+    }
+
     pub fn as_str(self) -> LocalInternedString {
         with_interner(|interner| unsafe {
             LocalInternedString {
index 274c0f90442f6bac0872b6be4a3a7cbfb1d776fd..43610f9068f574243b977472a3dc1eb78b92c0f3 100644 (file)
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2019-02-27
+date: 2019-03-20
 rustc: beta
 cargo: beta
 
index 62cfef5a845e9d5f64449f737a367375e6a5387d..f268c8bcbccdb2291783f5f4b69a19aa29f546af 100644 (file)
@@ -4,7 +4,7 @@
 
 // ignore-tidy-linelength
 // ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index 369fa1fcfda7b9a0ce488d1678c16434068d301d..aa6cbf66b4aa3bc24ad4334acecce3e4a64760e5 100644 (file)
@@ -4,7 +4,7 @@
 
 // ignore-tidy-linelength
 // ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index 1273a785ba42f01980430d34faa33f55524e78b0..93eebde7b8f42bdc22c56d54b6847761d8c364bf 100644 (file)
@@ -4,7 +4,7 @@
 
 // ignore-tidy-linelength
 // ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
index 5c37e40c2703272573afeb4f04687b15b5168f3c..84976ce97af4b1bad724c45ac0e40588ffaa5bfa 100644 (file)
@@ -4,7 +4,7 @@
 
 // ignore-tidy-linelength
 // ignore-windows
-// min-system-llvm-version 7.0
+// min-system-llvm-version 8.0
 
 // compile-flags: -g -C no-prepopulate-passes
 
diff --git a/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs b/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs
new file mode 100644 (file)
index 0000000..861f86e
--- /dev/null
@@ -0,0 +1,28 @@
+// compile-flags: -Z chalk
+
+#![feature(trivial_bounds)]
+
+trait Bar {
+    fn foo();
+}
+trait Foo: Bar { }
+
+struct S where S: Foo;
+
+impl Foo for S {
+}
+
+fn bar<T: Bar>() {
+    T::foo();
+}
+
+fn foo<T: Foo>() {
+    bar::<T>()
+}
+
+fn main() {
+    // For some reason, the error is duplicated...
+
+    foo::<S>() //~ ERROR the type `S` is not well-formed (chalk)
+    //~^ ERROR the type `S` is not well-formed (chalk)
+}
index e27a31dd0e58558e751c74997310ffa8529b0c47..63c11f59c157d598422cae0cf43a3aaa2743f345 100644 (file)
@@ -1,7 +1,7 @@
 // ignore-tidy-linelength
 
 // Require LLVM with DW_TAG_variant_part and a gdb or lldb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
index 9392aa70971473814ff9c4f5511949ade85346dd..e26294cb730a06a0baae024d0e6f46a8770ad042 100644 (file)
@@ -3,7 +3,7 @@
 // min-lldb-version: 310
 
 // Require LLVM with DW_TAG_variant_part and a gdb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g
index 3e593470303ea3342cbaf03affcef268c54577c0..3dc5cb807b452349c7c424c8819a363d0318cb04 100644 (file)
@@ -2,7 +2,7 @@
 // min-lldb-version: 310
 
 // Require LLVM with DW_TAG_variant_part and a gdb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g
index 3c136add07915e16c2d1f4010ded189ac65192ca..b16634ee6d7f99a8203a7195131da086e6995c6c 100644 (file)
@@ -2,7 +2,7 @@
 
 // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
 // read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
index c3d2bea9139c0a751aa696e2ac864bc467d19cf4..8fb83b7956be3309b818fae9d100b8b38302daad 100644 (file)
@@ -2,7 +2,7 @@
 // ignore-lldb
 
 // Require LLVM with DW_TAG_variant_part and a gdb that can read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 
 // compile-flags:-g
index 1654c9320912f405373f1477c37a5e1206dbb608..5843b076b1f465d9a11f45cc35bb74f5d79f1922 100644 (file)
@@ -2,7 +2,7 @@
 
 // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
 // read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
index fd76bcb0afc32c6902a1eec299cc46a983aaa80e..4d9727a388b8ed87e4b35df1d95edbcc7bbd22b7 100644 (file)
@@ -2,7 +2,7 @@
 
 // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
 // read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
index da0d06213e0ab2d56c775d3c98d970bb7c0e906f..32bd93f1ed2cee2671feda502eec1fd4a0936d2f 100644 (file)
@@ -2,7 +2,7 @@
 
 // Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
 // read it.
-// min-system-llvm-version: 7.0
+// min-system-llvm-version: 8.0
 // min-gdb-version: 8.2
 // rust-lldb
 
index f0f1f09a8388b9d677e5e7b07bfa70a71973057f..05cc945bbaf0098175fe0d03b29be69126b46acc 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_callee_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_function() {
     callee2(1, 2)
@@ -40,7 +40,7 @@ pub fn change_argument_function() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_function() {
     callee1(1, 3)
@@ -81,7 +81,7 @@ pub fn change_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_callee_method() {
     let s = Struct;
@@ -98,7 +98,7 @@ pub fn change_argument_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method() {
     let s = Struct;
@@ -115,7 +115,7 @@ pub fn change_ufcs_callee_method() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
@@ -132,7 +132,7 @@ pub fn change_argument_method_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
@@ -149,7 +149,7 @@ pub fn change_to_ufcs() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 // One might think this would be expanded in the HirBody/Mir, but it actually
 // results in slightly different Hir/Mir.
@@ -171,7 +171,7 @@ pub mod change_ufcs_callee_indirectly {
     #[cfg(not(cfail1))]
     use super::Struct2 as Struct;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
     #[rustc_clean(cfg="cfail3")]
 
 
index 4e82729aa3be14643538a8de73990828e6b35483..b8e84173ec06ce03da0ea4b7831c3d77990bb74d 100644 (file)
@@ -37,7 +37,7 @@ pub fn add_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_parameter() {
     let x = 0u32;
@@ -53,7 +53,7 @@ pub fn change_parameter_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_pattern() {
     let _ = |&x: &u32| x;
@@ -84,7 +84,7 @@ pub fn add_type_ascription_to_parameter() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_type_ascription_to_parameter() {
     let closure = |x: u32| x + 1u32;
@@ -101,7 +101,7 @@ pub fn change_parameter_type() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_parameter_type() {
     let closure = |x: u16| (x as u64) + 1;
index a74c3ab04e2af44e94575f024f108adb4c08296b..d3f96c9947b89379aa58625e614c3daf8212a820 100644 (file)
@@ -34,7 +34,7 @@ pub fn change_field_value_struct_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
@@ -96,7 +96,7 @@ pub fn change_constructor_path_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
@@ -119,7 +119,7 @@ pub fn change_constructor_variant_struct_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
@@ -139,7 +139,7 @@ pub mod change_constructor_path_indirectly_struct_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,\
+        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
                 TypeckTables"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -161,7 +161,7 @@ pub mod change_constructor_variant_indirectly_struct_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Struct2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant {
@@ -180,7 +180,7 @@ pub fn change_field_value_tuple_like() -> Enum {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
@@ -197,7 +197,7 @@ pub fn change_constructor_path_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="HirBody,MirOptimized,MirBuilt,TypeckTables"
+    except="HirBody,optimized_mir,mir_built,TypeckTables"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_like() {
@@ -215,7 +215,7 @@ pub fn change_constructor_variant_tuple_like() {
 #[cfg(not(cfail1))]
 #[rustc_clean(
     cfg="cfail2",
-    except="HirBody,MirOptimized,MirBuilt,TypeckTables"
+    except="HirBody,optimized_mir,mir_built,TypeckTables"
 )]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_tuple_like() {
@@ -232,7 +232,7 @@ pub mod change_constructor_path_indirectly_tuple_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,\
+        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
                 TypeckTables"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -251,7 +251,7 @@ pub mod change_constructor_variant_indirectly_tuple_like {
     #[cfg(not(cfail1))]
     use super::Enum2::Tuple2 as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Enum2 {
         Variant(0, 1, 2)
@@ -278,7 +278,7 @@ pub fn change_constructor_path_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_c_like() {
     let _ = Clike2::B;
@@ -293,7 +293,7 @@ pub fn change_constructor_variant_c_like() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_variant_c_like() {
     let _ = Clike::C;
@@ -309,7 +309,7 @@ pub mod change_constructor_path_indirectly_c_like {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,\
+        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,\
                 TypeckTables"
     )]
     #[rustc_clean(cfg="cfail3")]
@@ -328,7 +328,7 @@ pub mod change_constructor_variant_indirectly_c_like {
     #[cfg(not(cfail1))]
     use super::Clike::B as Variant;
 
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Clike {
         Variant
index c9f844f96ebd7737897f09d4f40cb14d801312a4..dc919abc02d44311bf190811f1fd5242f18b1dc4 100644 (file)
@@ -16,7 +16,7 @@ pub fn body_not_exported_to_metadata() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn body_not_exported_to_metadata() -> u32 {
     2
@@ -35,7 +35,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
@@ -55,7 +55,7 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
index da093ded63566996d75f5ce102d11cfe1c0fd9fe..91abca3312bc27ad6381c66d8a022415840d0f47 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_iteration_variable_name() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
@@ -71,7 +71,7 @@ pub fn change_iteration_variable_pattern() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
@@ -94,7 +94,7 @@ pub fn change_iterable() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_iterable() {
     let mut _x = 0;
@@ -116,7 +116,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -187,7 +187,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -237,7 +237,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -262,7 +262,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index fccec704d6356caf4ea08e28a61ce261a1cf908c..db8fa9ced113ce05c0bd669275d30a126b1f3309 100644 (file)
@@ -24,7 +24,7 @@ pub fn add_parameter() {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn add_parameter(p: i32) {}
 
@@ -47,7 +47,7 @@ pub fn type_of_parameter(p: i32) {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter(p: i64) {}
 
@@ -59,7 +59,7 @@ pub fn type_of_parameter_ref(p: &i32) {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn type_of_parameter_ref(p: &mut i32) {}
 
@@ -71,7 +71,7 @@ pub fn order_of_parameters(p1: i32, p2: i64) {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn order_of_parameters(p2: i64, p1: i32) {}
 
@@ -83,7 +83,7 @@ pub fn make_unsafe() {}
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg = "cfail2",
-              except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+              except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
 #[rustc_clean(cfg = "cfail3")]
 pub unsafe fn make_unsafe() {}
 
@@ -94,7 +94,7 @@ pub unsafe fn make_unsafe() {}
 pub fn make_extern() {}
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, MirBuilt, TypeckTables, FnSignature")]
+#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, mir_built, TypeckTables, FnSignature")]
 #[rustc_clean(cfg = "cfail3")]
 pub extern "C" fn make_extern() {}
 
@@ -292,7 +292,7 @@ pub mod change_return_type_indirectly {
     use super::ReferencedType2 as ReturnType;
 
     #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+                  except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_return_type() -> ReturnType {
         ReturnType {}
@@ -309,7 +309,7 @@ pub mod change_parameter_type_indirectly {
     use super::ReferencedType2 as ParameterType;
 
     #[rustc_clean(cfg = "cfail2",
-                  except = "Hir, HirBody, MirBuilt, MirOptimized, TypeckTables, FnSignature")]
+                  except = "Hir, HirBody, mir_built, optimized_mir, TypeckTables, FnSignature")]
     #[rustc_clean(cfg = "cfail3")]
     pub fn indirect_parameter_type(p: ParameterType) {}
 }
index a01247ff4243c02979ce29ee491341cbf95ccdbb..32a0c8b6b7e797d2a3ae1050e864cc52ba250457 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_condition(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition(x: bool) -> u32 {
     if !x {
@@ -46,7 +46,7 @@ pub fn change_then_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
@@ -69,7 +69,7 @@ pub fn change_else_branch(x: bool) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
@@ -120,7 +120,7 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     if let Some(_) = x {
@@ -143,7 +143,7 @@ pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
@@ -166,7 +166,7 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
index ebafd07dbef573bd4517005b724f85c8dcdf479f..1b6b41ce05b789baeac7750a7e0083b8dab71445 100644 (file)
@@ -42,7 +42,7 @@ pub fn method_body() { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_body() {
         println!("Hello, world!");
@@ -63,7 +63,7 @@ pub fn method_body_inlined() { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
     #[rustc_clean(cfg="cfail3")]
     #[inline]
     pub fn method_body_inlined() {
@@ -114,7 +114,7 @@ pub fn method_selfmutness(&self) { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirBuilt"
+        except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_selfmutness(&mut self) { }
@@ -154,7 +154,7 @@ pub fn add_method_parameter(&self) { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirBuilt"
+        except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_method_parameter(&self, _: i32) { }
@@ -172,7 +172,7 @@ pub fn change_method_parameter_name(&self, a: i64) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
@@ -191,7 +191,7 @@ pub fn change_method_return_type(&self) -> u16 { 0 }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,MirOptimized,MirBuilt,TypeckTables")]
+        except="Hir,HirBody,FnSignature,optimized_mir,mir_built,TypeckTables")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_return_type(&self) -> u8 { 0 }
 }
@@ -226,7 +226,7 @@ pub fn change_method_parameter_order(&self, a: i64, b: i64) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+    #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
@@ -245,7 +245,7 @@ pub fn make_method_unsafe(&self) { }
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
-        except="Hir,HirBody,FnSignature,TypeckTables,MirOptimized,MirBuilt"
+        except="Hir,HirBody,FnSignature,TypeckTables,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub unsafe fn make_method_unsafe(&self) { }
@@ -263,7 +263,7 @@ pub fn make_method_extern(&self) { }
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,MirBuilt,FnSignature,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="Hir,HirBody,mir_built,FnSignature,TypeckTables")]
     #[rustc_clean(cfg="cfail3")]
     pub extern fn make_method_extern(&self) { }
 }
@@ -447,7 +447,7 @@ pub fn add_type_parameter_to_impl(&self) { }
 impl<T> Bar<T> {
     #[rustc_clean(
         cfg="cfail2",
-        except="generics_of,FnSignature,TypeckTables,type_of,MirOptimized,MirBuilt"
+        except="generics_of,FnSignature,TypeckTables,type_of,optimized_mir,mir_built"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn add_type_parameter_to_impl(&self) { }
@@ -465,7 +465,7 @@ pub fn change_impl_self_type(&self) { }
 #[rustc_clean(cfg="cfail2", except="Hir,HirBody")]
 #[rustc_clean(cfg="cfail3")]
 impl Bar<u64> {
-    #[rustc_clean(cfg="cfail2", except="FnSignature,MirOptimized,MirBuilt,TypeckTables")]
+    #[rustc_clean(cfg="cfail2", except="FnSignature,optimized_mir,mir_built,TypeckTables")]
     #[rustc_clean(cfg="cfail3")]
     pub fn change_impl_self_type(&self) { }
 }
index c5e7f525fd0fb5fd1e7ef582878d1c6537531d00..53e77a370a334ab99c5d78122c3cf1dd01037e16 100644 (file)
@@ -33,7 +33,7 @@ pub fn change_template(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
@@ -69,7 +69,7 @@ pub fn change_output(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
@@ -105,7 +105,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
@@ -140,7 +140,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
@@ -175,7 +175,7 @@ pub fn change_clobber(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
@@ -210,7 +210,7 @@ pub fn change_options(_a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
index a2b33fecea8657a0d8431bc97c84f24a2d2e1306..76be2ccbf608c8db23f49f175f47a41abf5e0d99 100644 (file)
@@ -22,7 +22,7 @@ pub fn change_name() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized")]
+    except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name() {
     let _y = 2u64;
@@ -38,7 +38,7 @@ pub fn add_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_type() {
     let _x: u32 = 2u32;
@@ -54,7 +54,7 @@ pub fn change_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_type() {
     let _x: u8 = 2;
@@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_reference_type() {
     let _x: &mut u64;
@@ -86,7 +86,7 @@ pub fn change_mutability_of_slot() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_slot() {
     let _x: u64 = 0;
@@ -102,7 +102,7 @@ pub fn change_simple_binding_to_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_binding_to_pattern() {
     let (_a, _b) = (0u8, 'x');
@@ -118,7 +118,7 @@ pub fn change_name_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized")]
+    except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern() {
     let (_a, _c) = (1u8, 'y');
@@ -134,7 +134,7 @@ pub fn add_ref_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_in_pattern() {
     let (ref _a, _b) = (1u8, 'y');
@@ -150,7 +150,7 @@ pub fn add_amp_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_in_pattern() {
     let (&_a, _b) = (&1u8, 'y');
@@ -166,7 +166,7 @@ pub fn change_mutability_of_binding_in_pattern() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern() {
     let (mut _a, _b) = (99u8, 'q');
@@ -182,7 +182,7 @@ pub fn add_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,TypeckTables,MirBuilt,MirOptimized")]
+    except="HirBody,TypeckTables,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
@@ -198,7 +198,7 @@ pub fn change_initializer() {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized")]
+    except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_initializer() {
     let _x = 5u16;
index a48d150b8b0f244d82877e9e9b294441a40a6044..63cf1e9d5e826819e30416c9cf31e4485e5bc571 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -47,7 +47,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -118,7 +118,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -168,7 +168,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -193,7 +193,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index 11fe84d88e9b37b274b7d161459a8827ecf098c6..37f6aa9ee9bdc86d328e2acc020ef9b5fdd1496e 100644 (file)
@@ -26,7 +26,7 @@ pub fn add_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_arm(x: u32) -> u32 {
     match x {
@@ -51,7 +51,7 @@ pub fn change_order_of_arms(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized")]
+    except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
@@ -75,7 +75,7 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -99,7 +99,7 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
@@ -123,7 +123,7 @@ pub fn add_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
@@ -147,7 +147,7 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized")]
+    except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
@@ -170,7 +170,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -193,7 +193,7 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized")]
+    except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -216,7 +216,7 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -238,7 +238,7 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
@@ -260,7 +260,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
@@ -283,7 +283,7 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized")]
+    except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
@@ -307,7 +307,7 @@ pub fn add_alternative_to_arm(x: u32) -> u32 {
 
 #[cfg(not(cfail1))]
 #[rustc_clean(cfg="cfail2",
-    except="HirBody,MirBuilt,MirOptimized,TypeckTables")]
+    except="HirBody,mir_built,optimized_mir,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
index 9a3c93147a098143ef80adaf8286e0471b4cb210..0803f4e01d63b1775f5e37f01dfb0462876b5d5c 100644 (file)
@@ -18,7 +18,7 @@
 
 
 // Indexing expression ---------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn indexing(slice: &[u8]) -> u8 {
     #[cfg(cfail1)]
@@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 {
 
 
 // Arithmetic overflow plus ----------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_plus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 {
 
 
 // Arithmetic overflow minus ----------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_minus(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 {
 
 
 // Arithmetic overflow mult ----------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_mult(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 {
 
 
 // Arithmetic overflow negation ------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn arithmetic_overflow_negation(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 {
 
 
 // Division by zero ------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn division_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 {
 }
 
 // Division by zero ------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn mod_by_zero(val: i32) -> i32 {
     #[cfg(cfail1)]
@@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 {
 
 
 // shift left ------------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_left(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
@@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 {
 
 
 // shift right ------------------------------------------------------------------
-#[rustc_clean(cfg="cfail2", except="HirBody,MirBuilt,MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn shift_right(val: i32, shift: usize) -> i32 {
     #[cfg(cfail1)]
index a42fda31885209ae3ab49580a42f953949842472..3190f65a8173130a50506164231aa1136327d646 100644 (file)
@@ -31,7 +31,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
@@ -82,7 +82,7 @@ pub fn add_field_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -117,7 +117,7 @@ pub fn change_field_label_regular_struct() -> RegularStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
@@ -152,7 +152,7 @@ pub fn change_constructor_path_regular_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
@@ -173,7 +173,7 @@ pub mod change_constructor_path_indirectly_regular_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,TypeckTables"
+        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,TypeckTables"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
@@ -196,7 +196,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
@@ -213,7 +213,7 @@ pub fn change_constructor_path_tuple_struct() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody,MirOptimized,MirBuilt,TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
@@ -230,7 +230,7 @@ pub mod change_constructor_path_indirectly_tuple_struct {
 
     #[rustc_clean(
         cfg="cfail2",
-        except="FnSignature,Hir,HirBody,MirOptimized,MirBuilt,TypeckTables"
+        except="FnSignature,Hir,HirBody,optimized_mir,mir_built,TypeckTables"
     )]
     #[rustc_clean(cfg="cfail3")]
     pub fn function() -> Struct {
index ef8035a300a4313e963d3b7dfe8dcfe5040c4ece..f3331ec61cb6a4cc6379b4e33614a755bae201a1 100644 (file)
@@ -21,7 +21,7 @@ pub fn const_negation() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_negation() -> i32 {
     -1
@@ -36,7 +36,7 @@ pub fn const_bitwise_not() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn const_bitwise_not() -> i32 {
     !99
@@ -51,7 +51,7 @@ pub fn var_negation(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -y
@@ -66,7 +66,7 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !y
@@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt,TypeckTables", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built,TypeckTables", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *y
@@ -96,7 +96,7 @@ pub fn first_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_const_add() -> i32 {
     2 + 3
@@ -111,7 +111,7 @@ pub fn second_const_add() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_const_add() -> i32 {
     1 + 3
@@ -126,7 +126,7 @@ pub fn first_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     b + 2
@@ -141,7 +141,7 @@ pub fn second_var_add(a: i32, b: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + b
@@ -156,7 +156,7 @@ pub fn plus_to_minus(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 - a
@@ -171,7 +171,7 @@ pub fn plus_to_mult(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 * a
@@ -186,7 +186,7 @@ pub fn plus_to_div(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_div(a: i32) -> i32 {
     1 / a
@@ -201,7 +201,7 @@ pub fn plus_to_mod(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 % a
@@ -216,7 +216,7 @@ pub fn and_to_or(a: bool, b: bool) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a || b
@@ -231,7 +231,7 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 | a
@@ -246,7 +246,7 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 ^ a
@@ -261,7 +261,7 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
     a << 1
@@ -276,7 +276,7 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
     a >> 1
@@ -291,7 +291,7 @@ pub fn eq_to_uneq(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_uneq(a: i32) -> bool {
     a != 1
@@ -306,7 +306,7 @@ pub fn eq_to_lt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_lt(a: i32) -> bool {
     a < 1
@@ -321,7 +321,7 @@ pub fn eq_to_gt(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_gt(a: i32) -> bool {
     a > 1
@@ -336,7 +336,7 @@ pub fn eq_to_le(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_le(a: i32) -> bool {
     a <= 1
@@ -351,7 +351,7 @@ pub fn eq_to_ge(a: i32) -> bool {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn eq_to_ge(a: i32) -> bool {
     a >= 1
@@ -368,7 +368,7 @@ pub fn type_cast(a: u8) -> u64 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt,TypeckTables", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built,TypeckTables", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as u32;
@@ -385,7 +385,7 @@ pub fn value_cast(a: u32) -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn value_cast(a: u32) -> i32 {
     2 as i32
@@ -403,7 +403,7 @@ pub fn place() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn place() -> i32 {
     let mut x = 10;
@@ -423,7 +423,7 @@ pub fn rvalue() -> i32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn rvalue() -> i32 {
     let mut x = 10;
@@ -440,7 +440,7 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(except="HirBody,MirOptimized,MirBuilt", cfg="cfail2")]
+#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[j]
index c708d5b969df586c4d3512a5b5621af0c03957f3..7e866ae925ed90cb67adda376472450a7ab11581 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index c7b84a120c8dfa3dde6d19dab987c15f80699759..cbd1341fdd4fb1fc68d9dc9d228da2df600138d0 100644 (file)
@@ -25,7 +25,7 @@ pub fn change_loop_body() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_body() {
     let mut _x = 0;
@@ -48,7 +48,7 @@ pub fn change_loop_condition() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_loop_condition() {
     let mut _x = 0;
@@ -70,7 +70,7 @@ pub fn add_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized, TypeckTables")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, TypeckTables")]
 #[rustc_clean(cfg="cfail3")]
 pub fn add_break() {
     let mut _x = 0;
@@ -141,7 +141,7 @@ pub fn change_break_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_break_label() {
     let mut _x = 0;
@@ -191,7 +191,7 @@ pub fn change_continue_label() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_label() {
     let mut _x = 0;
@@ -216,7 +216,7 @@ pub fn change_continue_to_break() {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, MirBuilt, MirOptimized")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
index ecda56f7e942e596469b931d42ecc5847676f87b..2574ef5199c867785e6cb6b5dbcacbf01d27f9b7 100644 (file)
@@ -13,7 +13,7 @@ pub fn main() {
 }
 
 #[cfg(rpass2)]
-#[rustc_dirty(label="MirOptimized", cfg="rpass2")]
+#[rustc_dirty(label="optimized_mir", cfg="rpass2")]
 pub fn main() {
     let _ = 0u8 + 1;
 }
index 41c72335d63051ac24161bb46a421e166843ae67..db2660bb66129ce8540e9b783ee1ae789842f175 100644 (file)
@@ -19,7 +19,7 @@ pub fn x() {
 
     #[cfg(cfail2)]
     #[rustc_dirty(label="HirBody", cfg="cfail2")]
-    #[rustc_dirty(label="MirOptimized", cfg="cfail2")]
+    #[rustc_dirty(label="optimized_mir", cfg="cfail2")]
     pub fn x() {
         println!("{}", "2");
     }
@@ -29,7 +29,7 @@ pub mod y {
     use x;
 
     #[rustc_clean(label="TypeckTables", cfg="cfail2")]
-    #[rustc_clean(label="MirOptimized", cfg="cfail2")]
+    #[rustc_clean(label="optimized_mir", cfg="cfail2")]
     pub fn y() {
         x::x();
     }
@@ -39,7 +39,7 @@ pub mod z {
     use y;
 
     #[rustc_clean(label="TypeckTables", cfg="cfail2")]
-    #[rustc_clean(label="MirOptimized", cfg="cfail2")]
+    #[rustc_clean(label="optimized_mir", cfg="cfail2")]
     pub fn z() {
         y::y();
     }
diff --git a/src/test/mir-opt/graphviz.rs b/src/test/mir-opt/graphviz.rs
new file mode 100644 (file)
index 0000000..6605769
--- /dev/null
@@ -0,0 +1,23 @@
+// Test graphviz output
+// compile-flags: -Z dump-mir-graphviz
+
+// ignore-tidy-linelength
+
+fn main() {}
+
+// END RUST SOURCE
+// START rustc.main.mir_map.0.dot
+// digraph Mir_0_0_3 { // The name here MUST be an ASCII identifier.
+//     graph [fontname="monospace"];
+//     node [fontname="monospace"];
+//     edge [fontname="monospace"];
+//     label=<fn main() -&gt; ()<br align="left"/>>;
+//     bb0 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = ()<br/></td></tr><tr><td align="left">goto</td></tr></table>
+// >];
+//     bb1 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left">resume</td></tr></table>
+// >];
+//     bb2 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">2</td></tr><tr><td align="left">return</td></tr></table>
+// >];
+//     bb0 -> bb2 [label=""];
+// }
+// END rustc.main.mir_map.0.dot
index ef41373d774e319e52a8e6fa770b56c7be054781..606503151c985911077be563dde3d98a1da4174e 100644 (file)
@@ -72,7 +72,7 @@ fn main() {
 // }
 // END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
 
-// START rustc.Test-X.mir_map.0.mir
+// START rustc.Test-X-{{constructor}}.mir_map.0.mir
 // fn Test::X(_1: usize) -> Test {
 //     let mut _0: Test;
 //
@@ -81,4 +81,4 @@ fn main() {
 //         return;
 //     }
 // }
-// END rustc.Test-X.mir_map.0.mir
+// END rustc.Test-X-{{constructor}}.mir_map.0.mir
index 2a71fa9df5e8e330703f96b32e5631ee8f1d5191..613a568a8549c95a7711747f48791d80750bb2db 100644 (file)
@@ -6,7 +6,7 @@ LL | #[rustc_dump_program_clauses]
    |
    = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
    = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). }
-   = note: forall<'a, T> { WellFormed(S<'a, T>) :- Implemented(T: Foo), TypeOutlives(T: 'a). }
+   = note: forall<'a, T> { WellFormed(S<'a, T>) :- WellFormed(T: Foo), TypeOutlives(T: 'a). }
 
 error: program clause dump
   --> $DIR/lower_env2.rs:11:1
index 46e083686895d8c615fcc75b0a3ec732481a1b45..a1fc83bfea8a3a0b5a6c7d4a034e92b6cb451eba 100644 (file)
@@ -4,7 +4,6 @@ error: program clause dump
 LL |     #[rustc_dump_env_program_clauses]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
    = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
 
 error: program clause dump
@@ -13,7 +12,6 @@ error: program clause dump
 LL |     #[rustc_dump_env_program_clauses]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: forall<'^0, ^1> { TypeOutlives(^1: '^0) :- FromEnv(&^1). }
    = note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). }
    = note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). }
    = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
index 91525c3ba55d4a239f6f457fc2e2f4028dd2b00d..0331c2fca16db3bb5987a3668978734d513bcd05 100644 (file)
@@ -7,7 +7,7 @@ LL | #[rustc_dump_program_clauses]
    = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). }
    = note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). }
    = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). }
-   = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
+   = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- WellFormed(T: std::marker::Sized), WellFormed(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). }
 
 error: aborting due to previous error
 
index 423c5573083012a0a70a5df5937972854e176c39..ed3bded398ae3955f9876f0ef1e967903e2cbfbe 100644 (file)
@@ -18,7 +18,7 @@ LL |     #[rustc_dump_program_clauses]
    = note: forall<Self, S, T, ^3> { ProjectionEq(<Self as Foo<S, T>>::Assoc == ^3) :- Normalize(<Self as Foo<S, T>>::Assoc -> ^3). }
    = note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
    = note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
-   = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- WellFormed(Self: Foo<S, T>). }
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.rs b/src/test/ui/const-generics/struct-with-invalid-const-param.rs
new file mode 100644 (file)
index 0000000..207b07b
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct S<const C: u8>(C); //~ ERROR expected type, found const parameter
+
+fn main() {}
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr
new file mode 100644 (file)
index 0000000..561464b
--- /dev/null
@@ -0,0 +1,15 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/struct-with-invalid-const-param.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0573]: expected type, found const parameter `C`
+  --> $DIR/struct-with-invalid-const-param.rs:4:23
+   |
+LL | struct S<const C: u8>(C);
+   |                       ^ help: a struct with a similar name exists: `S`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
index 77c370814f7afa7c77e7d00d9f94c598c3f7509c..b009ff9486be2bc17918e0924204f5fb864d646d 100644 (file)
@@ -2,11 +2,7 @@ warning: use of deprecated item 'std::sync::atomic::ATOMIC_ISIZE_INIT': the `new
   --> $DIR/atomic_initializers.rs:8:27
    |
 LL | static FOO: AtomicIsize = ATOMIC_ISIZE_INIT;
-   |                           ^^^^^^^^^^^^^^^^^
+   |                           ^^^^^^^^^^^^^^^^^ help: replace the use of the deprecated item: `AtomicIsize::new(0)`
    |
    = note: #[warn(deprecated)] on by default
-help: use of deprecated item 'std::sync::atomic::ATOMIC_ISIZE_INIT': the `new` function is now preferred
-   |
-LL | static FOO: AtomicIsize = AtomicIsize::new(0);
-   |                           ^^^^^^^^^^^^^^^^^^^
 
diff --git a/src/test/ui/deprecation/suggestion.fixed b/src/test/ui/deprecation/suggestion.fixed
new file mode 100644 (file)
index 0000000..eba72f8
--- /dev/null
@@ -0,0 +1,28 @@
+// run-rustfix
+
+#![feature(staged_api)]
+
+#![stable(since = "1.0.0", feature = "test")]
+
+#![deny(deprecated)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    #[rustc_deprecated(
+        since = "1.0.0",
+        reason = "replaced by `replacement`",
+        suggestion = "replacement",
+    )]
+    #[stable(since = "1.0.0", feature = "test")]
+    fn deprecated(&self) {}
+
+    fn replacement(&self) {}
+}
+
+fn main() {
+    let foo = Foo;
+
+    foo.replacement(); //~ ERROR use of deprecated
+}
diff --git a/src/test/ui/deprecation/suggestion.rs b/src/test/ui/deprecation/suggestion.rs
new file mode 100644 (file)
index 0000000..8f9791c
--- /dev/null
@@ -0,0 +1,28 @@
+// run-rustfix
+
+#![feature(staged_api)]
+
+#![stable(since = "1.0.0", feature = "test")]
+
+#![deny(deprecated)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    #[rustc_deprecated(
+        since = "1.0.0",
+        reason = "replaced by `replacement`",
+        suggestion = "replacement",
+    )]
+    #[stable(since = "1.0.0", feature = "test")]
+    fn deprecated(&self) {}
+
+    fn replacement(&self) {}
+}
+
+fn main() {
+    let foo = Foo;
+
+    foo.deprecated(); //~ ERROR use of deprecated
+}
diff --git a/src/test/ui/deprecation/suggestion.stderr b/src/test/ui/deprecation/suggestion.stderr
new file mode 100644 (file)
index 0000000..6aaabfe
--- /dev/null
@@ -0,0 +1,14 @@
+error: use of deprecated item 'Foo::deprecated': replaced by `replacement`
+  --> $DIR/suggestion.rs:27:9
+   |
+LL |     foo.deprecated();
+   |         ^^^^^^^^^^ help: replace the use of the deprecated item: `replacement`
+   |
+note: lint level defined here
+  --> $DIR/suggestion.rs:7:9
+   |
+LL | #![deny(deprecated)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
index bdcfaae60a010a3b59c3fb2c31cd3c9f00da7b55..b0ef4e1b25413c315c8de5df707a3ded89ec11ec 100644 (file)
@@ -3,6 +3,14 @@ error: expected type, found `1`
    |
 LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
    |                                       ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/E0423.rs:12:36
+   |
+LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+   |                                    ^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: expected expression, found `==`
   --> $DIR/E0423.rs:15:13
@@ -15,6 +23,14 @@ error: expected type, found `0`
    |
 LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
    |                                       ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/E0423.rs:21:32
+   |
+LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
+   |                                ^^^^^
+   = help: this might be indicative of a syntax error elsewhere
 
 error[E0423]: expected function, found struct `Foo`
   --> $DIR/E0423.rs:4:13
diff --git a/src/test/ui/imports/auxiliary/gensymed.rs b/src/test/ui/imports/auxiliary/gensymed.rs
new file mode 100644 (file)
index 0000000..bbb19f5
--- /dev/null
@@ -0,0 +1,3 @@
+// edition:2018
+
+mod std {}
diff --git a/src/test/ui/imports/gensymed.rs b/src/test/ui/imports/gensymed.rs
new file mode 100644 (file)
index 0000000..3174410
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-pass
+// edition:2018
+// aux-build:gensymed.rs
+
+extern crate gensymed;
+
+fn main() {}
index b4234245bfb384d00b948189e6dec3386711132a..6efc7f0c06e11c58686239a14fa0949094fda6a1 100644 (file)
@@ -2,10 +2,10 @@ error[E0026]: variant `MyOption::MySome` does not have a field named `x`
   --> $DIR/issue-17800.rs:8:28
    |
 LL |         MyOption::MySome { x: 42 } => (),
-   |                            ^^^^^
+   |                            ^
    |                            |
    |                            variant `MyOption::MySome` does not have this field
-   |                            help: did you mean: `0`
+   |                            help: a field with a similar name exists: `0`
 
 error: aborting due to previous error
 
index cbff5575ed20e33afe3eda930ea4d46e35c94389..a28ea0d09f8f0fca7452fabb99118a15dc7155b0 100644 (file)
@@ -88,6 +88,14 @@ error: expected type, found `4`
    |
 LL |     println!("{}", a: &mut 4);
    |                            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/issue-22644.rs:34:20
+   |
+LL |     println!("{}", a: &mut 4);
+   |                    ^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/issues/issue-23458.rs b/src/test/ui/issues/issue-23458.rs
new file mode 100644 (file)
index 0000000..90b3f1f
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(asm)]
+
+// only-x86_64
+
+fn main() {
+    unsafe {
+        asm!("int $3"); //~ ERROR too few operands for instruction
+                        //~| ERROR invalid operand in inline asm
+    }
+}
diff --git a/src/test/ui/issues/issue-23458.stderr b/src/test/ui/issues/issue-23458.stderr
new file mode 100644 (file)
index 0000000..aff0f82
--- /dev/null
@@ -0,0 +1,17 @@
+error: invalid operand in inline asm: 'int $3'
+  --> $DIR/issue-23458.rs:7:9
+   |
+LL |         asm!("int $3");
+   |         ^^^^^^^^^^^^^^^
+
+error: <inline asm>:1:2: error: too few operands for instruction
+        int 
+        ^
+
+  --> $DIR/issue-23458.rs:7:9
+   |
+LL |         asm!("int $3");
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-34255-1.rs b/src/test/ui/issues/issue-34255-1.rs
new file mode 100644 (file)
index 0000000..b107193
--- /dev/null
@@ -0,0 +1,10 @@
+enum Test {
+    Drill {
+        field: i32,
+    }
+}
+
+fn main() {
+    Test::Drill(field: 42);
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr
new file mode 100644 (file)
index 0000000..7899c8d
--- /dev/null
@@ -0,0 +1,16 @@
+error: expected type, found `42`
+  --> $DIR/issue-34255-1.rs:8:24
+   |
+LL |     Test::Drill(field: 42);
+   |                        ^^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/issue-34255-1.rs:8:17
+   |
+LL |     Test::Drill(field: 42);
+   |                 ^^^^^
+   = help: this might be indicative of a syntax error elsewhere
+
+error: aborting due to previous error
+
index 1b2948db2d6c3f4aa064aa5d310e003722592617..4d4b977374ef943e8c2e98a5b9abff141e6e5091 100644 (file)
@@ -2,7 +2,7 @@ error[E0026]: struct `SimpleStruct` does not have a field named `state`
   --> $DIR/issue-51102.rs:13:17
    |
 LL |                 state: 0,
-   |                 ^^^^^^^^ struct `SimpleStruct` does not have this field
+   |                 ^^^^^ struct `SimpleStruct` does not have this field
 
 error[E0025]: field `no_state_here` bound multiple times in the pattern
   --> $DIR/issue-51102.rs:24:17
@@ -16,7 +16,7 @@ error[E0026]: variant `SimpleEnum::NoState` does not have a field named `state`
   --> $DIR/issue-51102.rs:33:17
    |
 LL |                 state: 0
-   |                 ^^^^^^^^ variant `SimpleEnum::NoState` does not have this field
+   |                 ^^^^^ variant `SimpleEnum::NoState` does not have this field
 
 error: aborting due to 3 previous errors
 
index 408819813b075d0ee59549d72be7d62512f8e9f3..468cdf2dcf9218d4004d9b414d1adcb2b7f770ab 100644 (file)
@@ -5,7 +5,7 @@ LL |     A::A { fob } => { println!("{}", fob); }
    |            ^^^
    |            |
    |            variant `A::A` does not have this field
-   |            help: did you mean: `foo`
+   |            help: a field with a similar name exists: `foo`
 
 error: aborting due to previous error
 
index fa0a7ac002b2ff2eec0335544428d316ba6450fa..cb5a52a3e081a75668a83902803fca0418b88ddb 100644 (file)
@@ -13,6 +13,14 @@ error: expected type, found keyword `loop`
    |
 LL |     loop { break 'label: loop { break 'label 42; }; }
    |                          ^^^^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/lifetime_starts_expressions.rs:6:12
+   |
+LL |     loop { break 'label: loop { break 'label 42; }; }
+   |            ^^^^^^^^^^^^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: aborting due to 2 previous errors
 
index 1a2ad4a0c09454390d81ca71af28ca763106423a..ce51bbaa114fd5905487d4ff5e1c62758f4b7298 100644 (file)
@@ -10,7 +10,7 @@ error[E0026]: struct `S` does not have a field named `0x1`
   --> $DIR/numeric-fields.rs:7:17
    |
 LL |         S{0: a, 0x1: b, ..} => {}
-   |                 ^^^^^^ struct `S` does not have this field
+   |                 ^^^ struct `S` does not have this field
 
 error: aborting due to 2 previous errors
 
index b319c64f406f1da4f3bb8dd3be5c06d697fa913a..07f2e41ac4fb036e5ffc546feac71947a2ca4191 100644 (file)
@@ -3,6 +3,14 @@ error: expected type, found `3`
    |
 LL |         x: 3
    |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-in-for.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
   --> $DIR/struct-literal-in-for.rs:14:12
index 27672eeda830beedf2b501b3ac568d779f75edea..3dd61e74f12eda67e9808948cc727bda1b915b25 100644 (file)
@@ -3,6 +3,14 @@ error: expected type, found `3`
    |
 LL |         x: 3
    |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-in-if.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
   --> $DIR/struct-literal-in-if.rs:14:12
index 8a130f441a3eec1ca224e53cd334590b30a5aace..d48244654cd023dd43250ecc39e446d45132d8da 100644 (file)
@@ -3,6 +3,14 @@ error: expected type, found `3`
    |
 LL |         x: 3
    |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-in-while.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
   --> $DIR/struct-literal-in-while.rs:14:12
index 3505d00b64b76599446fe0a01a225ec4e656fe45..a8c93233dbc535408b4e55e670dcc5aa52cdb19d 100644 (file)
@@ -3,6 +3,14 @@ error: expected type, found `3`
    |
 LL |         x: 3
    |            ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/struct-literal-restrictions-in-lamda.rs:13:9
+   |
+LL |         x: 3
+   |         ^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `{`
   --> $DIR/struct-literal-restrictions-in-lamda.rs:14:12
index 1e7fd25d0da42dc0157a6d385f54d194e6e98d4f..cf7de578c7d42f514f3aa93656a1bb8686543b70 100644 (file)
@@ -20,7 +20,7 @@ error: cannot find derive macro `attr_proc_macra` in this scope
   --> $DIR/resolve-error.rs:44:10
    |
 LL | #[derive(attr_proc_macra)]
-   |          ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro`
+   |          ^^^^^^^^^^^^^^^
 
 error: cannot find macro `FooWithLongNama!` in this scope
   --> $DIR/resolve-error.rs:49:5
index 13752430e714b6364b5550ca58e17171153e47d4..e076419f68d47b9449960cdc01f2da6e7460324b 100644 (file)
@@ -4,7 +4,7 @@ error[E0423]: expected value, found struct `String`
 LL |     let _ = String.new();
    |             ^^^^^^----
    |             |
-   |             help: use `::` to access an associated function: `String::new`
+   |             help: use the path separator to refer to an item: `String::new`
 
 error: aborting due to previous error
 
index c8c624d548b6794163f09b0491b1455106db4b21..565866a682adaf65afb71ea91a7254aa8ab7a62c 100644 (file)
@@ -22,7 +22,7 @@ error[E0026]: struct `Foo` does not have a field named `absent`
   --> $DIR/struct-field-cfg.rs:16:42
    |
 LL |     let Foo { present: (), #[cfg(all())] absent: () } = foo;
-   |                                          ^^^^^^^^^^ struct `Foo` does not have this field
+   |                                          ^^^^^^ struct `Foo` does not have this field
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/suggestions/assoc-const-as-field.rs b/src/test/ui/suggestions/assoc-const-as-field.rs
new file mode 100644 (file)
index 0000000..678b589
--- /dev/null
@@ -0,0 +1,13 @@
+pub mod Mod {
+    pub struct Foo {}
+    impl Foo {
+        pub const BAR: usize = 42;
+    }
+}
+
+fn foo(_: usize) {}
+
+fn main() {
+    foo(Mod::Foo.Bar);
+    //~^ ERROR expected value, found
+}
diff --git a/src/test/ui/suggestions/assoc-const-as-field.stderr b/src/test/ui/suggestions/assoc-const-as-field.stderr
new file mode 100644 (file)
index 0000000..5e746ec
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0423]: expected value, found struct `Mod::Foo`
+  --> $DIR/assoc-const-as-field.rs:11:9
+   |
+LL |     foo(Mod::Foo.Bar);
+   |         ^^^^^^^^----
+   |         |
+   |         help: use the path separator to refer to an item: `Mod::Foo::Bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/suggestions/auxiliary/foo.rs b/src/test/ui/suggestions/auxiliary/foo.rs
new file mode 100644 (file)
index 0000000..e90bbef
--- /dev/null
@@ -0,0 +1,3 @@
+//! Contains a struct with almost the same name as itself, to trigger Levenshtein suggestions.
+
+pub struct Foo;
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr b/src/test/ui/suggestions/borrow-for-loop-head.nll.stderr
new file mode 100644 (file)
index 0000000..6450f7f
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |     for i in &a {
+   |              --
+   |              |
+   |              borrow of `a` occurs here
+   |              borrow later used here
+LL |         for j in a {
+   |                  ^ move out of `a` occurs here
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |     let a = vec![1, 2, 3];
+   |         - move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+LL |     for i in &a {
+LL |         for j in a {
+   |                  ^ value moved here, in previous iteration of loop
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.rs b/src/test/ui/suggestions/borrow-for-loop-head.rs
new file mode 100644 (file)
index 0000000..c2bda55
--- /dev/null
@@ -0,0 +1,10 @@
+fn main() {
+    let a = vec![1, 2, 3];
+    for i in &a {
+        for j in a {
+        //~^ ERROR cannot move out of `a` because it is borrowed
+        //~| ERROR use of moved value: `a`
+            println!("{} * {} = {}", i, j, i * j);
+        }
+    }
+}
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr
new file mode 100644 (file)
index 0000000..17ac3fe
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0505]: cannot move out of `a` because it is borrowed
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |     for i in &a {
+   |               - borrow of `a` occurs here
+LL |         for j in a {
+   |                  ^ move out of `a` occurs here
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrow-for-loop-head.rs:4:18
+   |
+LL |         for j in a {
+   |                  ^ value moved here in previous iteration of loop
+   |
+   = note: move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+help: consider borrowing this to avoid moving it into the for loop
+   |
+LL |         for j in &a {
+   |                  ^^
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/suggestions/no-extern-crate-in-type.rs b/src/test/ui/suggestions/no-extern-crate-in-type.rs
new file mode 100644 (file)
index 0000000..bb93ef4
--- /dev/null
@@ -0,0 +1,7 @@
+// aux-build:foo.rs
+
+extern crate foo;
+
+type Output = Option<Foo>; //~ ERROR cannot find type `Foo`
+
+fn main() {}
diff --git a/src/test/ui/suggestions/no-extern-crate-in-type.stderr b/src/test/ui/suggestions/no-extern-crate-in-type.stderr
new file mode 100644 (file)
index 0000000..d4a5a95
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0412]: cannot find type `Foo` in this scope
+  --> $DIR/no-extern-crate-in-type.rs:5:22
+   |
+LL | type Output = Option<Foo>;
+   |                      ^^^ not found in this scope
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use foo::Foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.rs b/src/test/ui/suggestions/type-ascription-instead-of-let.rs
new file mode 100644 (file)
index 0000000..0e1c307
--- /dev/null
@@ -0,0 +1,10 @@
+fn fun(x: i32) -> i32 { x }
+
+fn main() {
+    let closure_annotated = |value: i32| -> i32 {
+        temp: i32 = fun(5i32);
+        //~^ ERROR cannot find value `temp` in this scope
+        temp + value + 1
+        //~^ ERROR cannot find value `temp` in this scope
+    };
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-let.stderr b/src/test/ui/suggestions/type-ascription-instead-of-let.stderr
new file mode 100644 (file)
index 0000000..92e4b57
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0425]: cannot find value `temp` in this scope
+  --> $DIR/type-ascription-instead-of-let.rs:5:9
+   |
+LL |         temp: i32 = fun(5i32);
+   |         ^^^^
+   |         |
+   |         not found in this scope
+   |         help: maybe you meant to write an assignment here: `let temp`
+
+error[E0425]: cannot find value `temp` in this scope
+  --> $DIR/type-ascription-instead-of-let.rs:7:9
+   |
+LL |         temp + value + 1
+   |         ^^^^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.rs b/src/test/ui/suggestions/type-ascription-instead-of-method.rs
new file mode 100644 (file)
index 0000000..361729d
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    Box:new("foo".to_string())
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.stderr b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr
new file mode 100644 (file)
index 0000000..15ec087
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected type, found `"foo"`
+  --> $DIR/type-ascription-instead-of-method.rs:2:13
+   |
+LL |     Box:new("foo".to_string())
+   |        -    ^^^^^ expecting a type here because of type ascription
+   |        |
+   |        help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.rs b/src/test/ui/suggestions/type-ascription-instead-of-path.rs
new file mode 100644 (file)
index 0000000..4c0fe6d
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    std:io::stdin();
+    //~^ ERROR failed to resolve: use of undeclared type or module `io`
+    //~| ERROR expected value, found module
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-path.stderr b/src/test/ui/suggestions/type-ascription-instead-of-path.stderr
new file mode 100644 (file)
index 0000000..1beb822
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0433]: failed to resolve: use of undeclared type or module `io`
+  --> $DIR/type-ascription-instead-of-path.rs:2:9
+   |
+LL |     std:io::stdin();
+   |         ^^ use of undeclared type or module `io`
+
+error[E0423]: expected value, found module `std`
+  --> $DIR/type-ascription-instead-of-path.rs:2:5
+   |
+LL |     std:io::stdin();
+   |     ^^^- help: maybe you meant to write a path separator here: `::`
+   |     |
+   |     not a value
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0423, E0433.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.rs b/src/test/ui/suggestions/type-ascription-instead-of-variant.rs
new file mode 100644 (file)
index 0000000..b90867f
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = Option:Some("");
+    //~^ ERROR expected type, found
+}
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr
new file mode 100644 (file)
index 0000000..5719a66
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected type, found `""`
+  --> $DIR/type-ascription-instead-of-variant.rs:2:25
+   |
+LL |     let _ = Option:Some("");
+   |                   -     ^^ expecting a type here because of type ascription
+   |                   |
+   |                   help: maybe you meant to write a path separator here: `::`
+
+error: aborting due to previous error
+
index bc5a923a3f32fc43ab866e61d6a1ba1028c27d1f..2084cbcce4f6253ddd17027f2864c8b7498c288c 100644 (file)
@@ -11,6 +11,14 @@ error: expected type, found `0`
    |
 LL |     println!("test"): 0;
    |                       ^ expecting a type here because of type ascription
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/type-ascription-instead-of-statement-end.rs:9:5
+   |
+LL |     println!("test"): 0;
+   |     ^^^^^^^^^^^^^^^^
+   = help: this might be indicative of a syntax error elsewhere
 
 error: aborting due to 2 previous errors
 
index d7683aae841cdd923b157b8f1e4dfaa43eb890db..30fe327cac4ff59d0abc4dfd5c2f082d62804f62 100644 (file)
@@ -87,6 +87,7 @@
     Crate("fuchsia-zircon-sys"),
     Crate("getopts"),
     Crate("humantime"),
+    Crate("itertools"),
     Crate("jobserver"),
     Crate("kernel32-sys"),
     Crate("lazy_static"),
index ed2218f09d26b3ad12c58681e94245a65cef42d5..0be3ec839e9a2c9c1d9795414832388fd3368c6f 100644 (file)
@@ -54,6 +54,7 @@
     "src/libstd/f64.rs",
     // Integration test for platform-specific run-time feature detection:
     "src/libstd/tests/run-time-detect.rs" ,
+    "src/libstd/net/test.rs",
     "src/libstd/sys_common/mod.rs",
     "src/libstd/sys_common/net.rs",
     "src/libterm", // Not sure how to make this crate portable, but test crate needs it.