]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #66507 - ecstatic-morse:const-if-match, r=oli-obk
authorbors <bors@rust-lang.org>
Sat, 23 Nov 2019 01:13:41 +0000 (01:13 +0000)
committerbors <bors@rust-lang.org>
Sat, 23 Nov 2019 01:13:41 +0000 (01:13 +0000)
Enable `if` and `match` in constants behind a feature flag

This PR is an initial implementation of #49146. It introduces a `const_if_match` feature flag and does the following if it is enabled:
- Allows `Downcast` projections, `SwitchInt` terminators and `FakeRead`s for matched places through the MIR const-checker.
- Allows `if` and `match` expressions through the HIR const-checker.
- Stops converting `&&` to `&` and `||` to `|` in `const` and `static` items.

As a result, the following operations are now allowed in a const context behind the feature flag:
- `if` and `match`
- short circuiting logic operators (`&&` and `||`)
- the `assert` and `debug_assert` macros (if the `const_panic` feature flag is also enabled)

However, the following operations remain forbidden:
- `while`, `loop` and `for` (see #52000)
- the `?` operator (calls `From::from` on its error variant)
- the `assert_eq` and `assert_ne` macros, along with their `debug` variants (calls `fmt::Debug`)

This PR is possible now that we use dataflow for const qualification (see #64470 and #66385).

r? @oli-obk
cc @rust-lang/wg-const-eval @eddyb

173 files changed:
Cargo.lock
src/libcore/cmp.rs
src/libcore/iter/traits/iterator.rs
src/librustc/hir/mod.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_misc.rs [deleted file]
src/librustc/ich/impls_syntax.rs
src/librustc/ich/impls_ty.rs
src/librustc/ich/mod.rs
src/librustc/infer/canonical/canonicalizer.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/outlives/obligations.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/pointer.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/auto_trait.rs
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/traits/util.rs
src/librustc/ty/error.rs
src/librustc/ty/instance.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/debuginfo/doc.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_ssa/base.rs
src/librustc_codegen_ssa/meth.rs
src/librustc_codegen_ssa/mir/constant.rs
src/librustc_codegen_ssa/mir/operand.rs
src/librustc_codegen_ssa/mir/place.rs
src/librustc_codegen_ssa/mir/rvalue.rs
src/librustc_codegen_ssa/traits/backend.rs
src/librustc_codegen_ssa/traits/builder.rs
src/librustc_codegen_ssa/traits/mod.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_error_codes/error_codes/E0015.md
src/librustc_error_codes/error_codes/E0023.md
src/librustc_error_codes/error_codes/E0033.md
src/librustc_error_codes/error_codes/E0038.md
src/librustc_error_codes/error_codes/E0057.md
src/librustc_error_codes/error_codes/E0061.md
src/librustc_errors/diagnostic.rs
src/librustc_interface/interface.rs
src/librustc_interface/passes.rs
src/librustc_interface/tests.rs
src/librustc_interface/util.rs
src/librustc_macros/src/hash_stable.rs
src/librustc_macros/src/lib.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/borrow_check/borrow_set.rs
src/librustc_mir/borrow_check/conflict_errors.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/place_ext.rs
src/librustc_mir/build/expr/as_constant.rs
src/librustc_mir/build/expr/as_place.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/build/expr/category.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/check_consts/qualifs.rs
src/librustc_mir/transform/check_consts/validation.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/transform/simplify_try.rs [new file with mode: 0644]
src/librustc_parse/config.rs [new file with mode: 0644]
src/librustc_parse/lib.rs
src/librustc_parse/parser/diagnostics.rs
src/librustc_parse/parser/item.rs
src/librustc_parse/parser/mod.rs
src/librustc_parse/parser/module.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/late.rs
src/librustc_target/Cargo.toml
src/librustc_target/abi/mod.rs
src/librustc_target/spec/abi.rs
src/librustc_target/spec/mod.rs
src/librustc_typeck/check/pat.rs
src/librustc_typeck/check/writeback.rs
src/librustdoc/html/highlight.rs
src/librustdoc/passes/check_code_block_syntax.rs
src/librustdoc/test.rs
src/libsyntax/Cargo.toml
src/libsyntax/ast.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/mut_visit.rs
src/libsyntax/print/pprust/tests.rs
src/libsyntax/sess.rs
src/libsyntax/token.rs
src/libsyntax/visit.rs
src/libsyntax_expand/build.rs
src/libsyntax_expand/config.rs [deleted file]
src/libsyntax_expand/expand.rs
src/libsyntax_expand/lib.rs
src/libsyntax_expand/mbe/macro_parser.rs
src/libsyntax_expand/parse/lexer/tests.rs
src/libsyntax_expand/parse/tests.rs
src/libsyntax_expand/placeholders.rs
src/libsyntax_expand/tests.rs
src/libsyntax_pos/edition.rs
src/libsyntax_pos/hygiene.rs
src/libsyntax_pos/lib.rs
src/libsyntax_pos/symbol.rs
src/test/codegen/match.rs
src/test/codegen/try_identity.rs [new file with mode: 0644]
src/test/mir-opt/const_prop/read_immutable_static.rs
src/test/mir-opt/simplify_try.rs [new file with mode: 0644]
src/test/run-make-fulldeps/pretty-print-path-suffix/Makefile [deleted file]
src/test/run-make-fulldeps/pretty-print-path-suffix/foo.pp [deleted file]
src/test/run-make-fulldeps/pretty-print-path-suffix/foo_method.pp [deleted file]
src/test/run-make-fulldeps/pretty-print-path-suffix/input.rs [deleted file]
src/test/run-make-fulldeps/pretty-print-path-suffix/nest_foo.pp [deleted file]
src/test/ui-fulldeps/ast_stmt_expr_attr.rs
src/test/ui-fulldeps/mod_dir_path_canonicalized.rs
src/test/ui-fulldeps/pprust-expr-roundtrip.rs
src/test/ui/ast-json/ast-json-output.stdout
src/test/ui/consts/const-fn-not-safe-for-const.stderr
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/projection_qualif.stderr
src/test/ui/issues/issue-17718-const-bad-values.stderr
src/test/ui/issues/issue-17718-references.stderr
src/test/ui/issues/issue-18118-2.stderr
src/test/ui/issues/issue-28433.stderr
src/test/ui/issues/issue-60075.rs
src/test/ui/issues/issue-60075.stderr
src/test/ui/parser/issue-32446.stderr
src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs [new file with mode: 0644]
src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs [new file with mode: 0644]
src/test/ui/parser/macro/trait-non-item-macros.rs
src/test/ui/parser/macro/trait-non-item-macros.stderr
src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
src/test/ui/parser/trait-pub-assoc-const.stderr
src/test/ui/parser/trait-pub-assoc-ty.stderr
src/test/ui/parser/trait-pub-method.stderr
src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
src/test/ui/thread-local-in-ctfe.rs
src/test/ui/thread-local-in-ctfe.stderr
src/test/ui/traits/principal-less-trait-objects.rs
src/tools/miri

index d5d66f899871049012046dbeda5dae8454a3f232..93cfc5448597c7a80c4fd673b418d7a045f35a19 100644 (file)
@@ -587,9 +587,9 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f75b10a18fb53549fdd090846eb01c7f8593914494d1faabc4d3005c436e417a"
+checksum = "d7d8975604ebad8b6660796802377eb6495045c5606168fc1b8d19a4dd9bfa46"
 dependencies = [
  "diff",
  "filetime",
@@ -3709,6 +3709,7 @@ dependencies = [
  "arena",
  "either",
  "graphviz",
+ "itertools 0.8.0",
  "log",
  "log_settings",
  "polonius-engine",
@@ -3837,6 +3838,7 @@ dependencies = [
  "log",
  "rustc_data_structures",
  "rustc_index",
+ "rustc_macros",
  "serialize",
  "syntax_pos",
 ]
@@ -4404,6 +4406,7 @@ dependencies = [
  "rustc_errors",
  "rustc_index",
  "rustc_lexer",
+ "rustc_macros",
  "scoped-tls",
  "serialize",
  "smallvec 1.0.0",
@@ -4560,9 +4563,9 @@ dependencies = [
 
 [[package]]
 name = "tester"
-version = "0.5.1"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd0d1044cb5ca390e9c93f8c35abd2c55484397dfd786f189321aa34605ee6ab"
+checksum = "7647e6d732eb84375d8e7abda37818f81861ddbfc7235e33f4983cb254b71e4f"
 dependencies = [
  "getopts",
  "libc",
index 1e2e595f1dd0a7035ee7dfdbdc8852861e3c5170..eb5121dd0e0812cd7e5b77129a189b2e98c00129 100644 (file)
 /// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
 /// we allow `BookFormat`s to be compared with `Book`s.
 ///
-/// You can also combine these implementations to let the `==` operator work with
-/// two different types:
-///
-/// ```
+/// A comparison like the one above, which ignores some fields of the struct,
+/// can be dangerous. It can easily lead to an unintended violation of the
+/// requirements for a partial equivalence relation. For example, if we kept
+/// the above implementation of `PartialEq<Book>` for `BookFormat` and added an
+/// implementation of `PartialEq<Book>` for `Book` (either via a `#[derive]` or
+/// via the manual implementation from the first example) then the result would
+/// violate transitivity:
+///
+/// ```should_panic
 /// #[derive(PartialEq)]
 /// enum BookFormat {
 ///     Paperback,
 ///     Ebook,
 /// }
 ///
+/// #[derive(PartialEq)]
 /// struct Book {
 ///     isbn: i32,
 ///     format: BookFormat,
 ///     }
 /// }
 ///
-/// impl PartialEq for Book {
-///     fn eq(&self, other: &Book) -> bool {
-///         self.isbn == other.isbn
-///     }
-/// }
+/// fn main() {
+///     let b1 = Book { isbn: 1, format: BookFormat::Paperback };
+///     let b2 = Book { isbn: 2, format: BookFormat::Paperback };
 ///
-/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
-/// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
+///     assert!(b1 == BookFormat::Paperback);
+///     assert!(BookFormat::Paperback == b2);
 ///
-/// assert!(b1 == BookFormat::Paperback);
-/// assert!(BookFormat::Ebook != b1);
-/// assert!(b1 == b2);
+///     // The following should hold by transitivity but doesn't.
+///     assert!(b1 == b2); // <-- PANICS
+/// }
 /// ```
 ///
 /// # Examples
index b7a35568e3fc52a1beb20dab004ab969e14b3c0d..61e8b07511a6741f0f86993ea0907db9f1a55d3d 100644 (file)
@@ -1255,7 +1255,7 @@ fn fuse(self) -> Fuse<Self> where Self: Sized {
         Fuse::new(self)
     }
 
-    /// Do something with each element of an iterator, passing the value on.
+    /// Does something with each element of an iterator, passing the value on.
     ///
     /// When using iterators, you'll often chain several of them together.
     /// While working on such code, you might want to check out what's
@@ -1548,7 +1548,7 @@ fn extend<'a, T, B: Extend<T>>(
         (left, right)
     }
 
-    /// Reorder the elements of this iterator *in-place* according to the given predicate,
+    /// Reorders the elements of this iterator *in-place* according to the given predicate,
     /// such that all those that return `true` precede all those that return `false`.
     /// Returns the number of `true` elements found.
     ///
index 6f34b42d91c1fbccc4cc19f48b4b931b0ba42983..64d22ae9435712dbdf4be923e25c8274bc15f2d8 100644 (file)
@@ -1932,8 +1932,9 @@ pub enum ImplItemKind {
 /// Bindings like `A: Debug` are represented as a special type `A =
 /// $::Debug` that is understood by the astconv code.
 ///
-/// FIXME(alexreg) -- why have a separate type for the binding case,
-/// wouldn't it be better to make the `ty` field an enum like:
+/// FIXME(alexreg): why have a separate type for the binding case,
+/// wouldn't it be better to make the `ty` field an enum like the
+/// following?
 ///
 /// ```
 /// enum TypeBindingKind {
@@ -2065,7 +2066,7 @@ pub enum TyKind {
     Err,
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
 pub struct InlineAsmOutput {
     pub constraint: Symbol,
     pub is_rw: bool,
@@ -2075,7 +2076,7 @@ pub struct InlineAsmOutput {
 
 // NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR,
 // it needs to be `Clone` and use plain `Vec<T>` instead of `HirVec<T>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
 pub struct InlineAsmInner {
     pub asm: Symbol,
     pub asm_str_style: StrStyle,
index 816e93698bce961ad6a2a483afc001633ea59995..39d1f850f45efa26f23934341ba36a02fa86c0cd 100644 (file)
@@ -213,11 +213,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
     }
 }
 
-impl_stable_hash_for!(enum ast::CrateSugar {
-    JustCrate,
-    PubCrate,
-});
-
 impl<'a> HashStable<StableHashingContext<'a>> for hir::VisibilityKind {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         mem::discriminant(self).hash_stable(hcx, hasher);
diff --git a/src/librustc/ich/impls_misc.rs b/src/librustc/ich/impls_misc.rs
deleted file mode 100644 (file)
index 4173051..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-//! This module contains `HashStable` implementations for various data types
-//! that don't fit into any of the other impls_xxx modules.
-
-impl_stable_hash_for!(enum ::rustc_target::spec::PanicStrategy {
-    Abort,
-    Unwind
-});
index b3d82e5522cf2400d9c15b87fd3afa023efe1426..f8bf8f4ab8a2f7b4e7e974e5acca8bc7558d09a5 100644 (file)
 use syntax::feature_gate;
 use syntax::token;
 use syntax::tokenstream;
-use syntax_pos::symbol::SymbolStr;
 use syntax_pos::SourceFile;
 
 use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
 
 use smallvec::SmallVec;
-use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
-
-impl<'a> HashStable<StableHashingContext<'a>> for SymbolStr {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let str = self as &str;
-        str.hash_stable(hcx, hasher)
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for SymbolStr {
-    type KeyType = SymbolStr;
-
-    #[inline]
-    fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a>)
-                          -> SymbolStr {
-        self.clone()
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.as_str().hash_stable(hcx, hasher);
-    }
-}
-
-impl<'a> ToStableHashKey<StableHashingContext<'a>> for ast::Name {
-    type KeyType = SymbolStr;
-
-    #[inline]
-    fn to_stable_hash_key(&self,
-                          _: &StableHashingContext<'a>)
-                          -> SymbolStr {
-        self.as_str()
-    }
-}
-
-impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
-    Att,
-    Intel
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::MacroKind {
-    Bang,
-    Attr,
-    Derive,
-});
-
-
-impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
-    Cdecl,
-    Stdcall,
-    Fastcall,
-    Vectorcall,
-    Thiscall,
-    Aapcs,
-    Win64,
-    SysV64,
-    PtxKernel,
-    Msp430Interrupt,
-    X86Interrupt,
-    AmdGpuKernel,
-    EfiApi,
-    Rust,
-    C,
-    System,
-    RustIntrinsic,
-    RustCall,
-    PlatformIntrinsic,
-    Unadjusted
-});
-
-impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
-impl_stable_hash_for!(struct ::syntax::attr::Stability {
-    level,
-    feature,
-    rustc_depr,
-    promotable,
-    allow_const_fn_ptr,
-    const_stability
-});
-
-impl_stable_hash_for!(enum ::syntax::edition::Edition {
-    Edition2015,
-    Edition2018,
-});
-
-impl<'a> HashStable<StableHashingContext<'a>>
-for ::syntax::attr::StabilityLevel {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            ::syntax::attr::StabilityLevel::Unstable { ref reason, ref issue, ref is_soft } => {
-                reason.hash_stable(hcx, hasher);
-                issue.hash_stable(hcx, hasher);
-                is_soft.hash_stable(hcx, hasher);
-            }
-            ::syntax::attr::StabilityLevel::Stable { ref since } => {
-                since.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason, suggestion });
-
-impl_stable_hash_for!(enum ::syntax::attr::IntType {
-    SignedInt(int_ty),
-    UnsignedInt(uint_ty)
-});
-
-impl_stable_hash_for!(enum ::syntax::ast::LitIntType {
-    Signed(int_ty),
-    Unsigned(int_ty),
-    Unsuffixed
-});
-
-impl_stable_hash_for!(enum ::syntax::ast::LitFloatType {
-    Suffixed(float_ty),
-    Unsuffixed
-});
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 impl_stable_hash_for!(struct ::syntax::ast::Lit {
     kind,
@@ -146,32 +23,9 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
     span
 });
 
-impl_stable_hash_for!(enum ::syntax::ast::LitKind {
-    Str(value, style),
-    ByteStr(value),
-    Byte(value),
-    Char(value),
-    Int(value, lit_int_type),
-    Float(value, lit_float_type),
-    Bool(value),
-    Err(value)
-});
-
 impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
 
-impl_stable_hash_for!(enum ::syntax::ast::IntTy { Isize, I8, I16, I32, I64, I128 });
-impl_stable_hash_for!(enum ::syntax::ast::UintTy { Usize, U8, U16, U32, U64, U128 });
-impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
-impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
-impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
-impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
 impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, ident });
-impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
-impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
-impl_stable_hash_for!(enum ::syntax::ast::Movability { Static, Movable });
-impl_stable_hash_for!(enum ::syntax::ast::CaptureBy { Value, Ref });
-impl_stable_hash_for!(enum ::syntax::ast::IsAuto { Yes, No });
-impl_stable_hash_for!(enum ::syntax::ast::ImplPolarity { Positive, Negative });
 
 impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
@@ -255,25 +109,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
     }
 }
 
-impl_stable_hash_for!(enum token::LitKind {
-    Bool,
-    Byte,
-    Char,
-    Integer,
-    Float,
-    Str,
-    ByteStr,
-    StrRaw(n),
-    ByteStrRaw(n),
-    Err
-});
-
-impl_stable_hash_for!(struct token::Lit {
-    kind,
-    symbol,
-    suffix
-});
-
 impl<'a> HashStable<StableHashingContext<'a>> for token::TokenKind {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -359,12 +194,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
     NameValue(lit)
 });
 
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
-    Transparent,
-    SemiTransparent,
-    Opaque,
-});
-
 impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData {
     kind,
     parent -> _,
@@ -376,43 +205,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
     edition
 });
 
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
-    Root,
-    Macro(kind, descr),
-    AstPass(kind),
-    Desugaring(kind)
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::AstPass {
-    StdImports,
-    TestHarness,
-    ProcMacroHarness,
-    PluginMacroDefs,
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
-    CondTemporary,
-    Async,
-    Await,
-    QuestionMark,
-    OpaqueTy,
-    ForLoop,
-    TryBlock
-});
-
-impl_stable_hash_for!(enum ::syntax_pos::FileName {
-    Real(pb),
-    Macros(s),
-    QuoteExpansion(s),
-    Anon(s),
-    MacroExpansion(s),
-    ProcMacroSourceCode(s),
-    CliCrateAttr(s),
-    CfgSpec(s),
-    Custom(s),
-    DocTest(pb, line),
-});
-
 impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         let SourceFile {
index c643baf11254c8178a9edee5d39e41edbc755576..7f50d859cde3a544ca2d56255db2cf42ea0890df 100644 (file)
@@ -159,11 +159,6 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
     }
 }
 
-impl_stable_hash_for!(enum ::syntax::ast::Mutability {
-    Immutable,
-    Mutable
-});
-
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for region::Scope {
     type KeyType = region::Scope;
 
index f3fc7ec8fda1530b4d9fe6295e01ce1967c818d0..9e985ffb14ca77d1edff44453d2da8c212ce72cd 100644 (file)
@@ -10,7 +10,6 @@
 mod hcx;
 
 mod impls_hir;
-mod impls_misc;
 mod impls_ty;
 mod impls_syntax;
 
index e782ec592958974d02e68977b7f519c55913a08f..1fa814dc14efb52702a778007b3f6305946f5862 100644 (file)
@@ -306,7 +306,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
             ty::ReLateBound(index, ..) => {
                 if index >= self.binder_index {
-                    bug!("escaping late bound region during canonicalization")
+                    bug!("escaping late-bound region during canonicalization");
                 } else {
                     r
                 }
@@ -336,7 +336,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
                 .canonicalize_free_region(self, r),
 
             ty::ReClosureBound(..) => {
-                bug!("closure bound region encountered during canonicalization")
+                bug!("closure bound region encountered during canonicalization");
             }
         }
     }
@@ -346,14 +346,14 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::Infer(ty::TyVar(vid)) => {
                 debug!("canonical: type var found with vid {:?}", vid);
                 match self.infcx.unwrap().probe_ty_var(vid) {
-                    // `t` could be a float / int variable: canonicalize that instead
+                    // `t` could be a float / int variable; canonicalize that instead.
                     Ok(t) => {
                         debug!("(resolved to {:?})", t);
                         self.fold_ty(t)
                     }
 
                     // `TyVar(vid)` is unresolved, track its universe index in the canonicalized
-                    // result
+                    // result.
                     Err(mut ui) => {
                         if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk {
                             // FIXME: perf problem described in #55921.
index f2607b23527a1d2d743eadde441badf0ee8720ff..0f93ef6b1a9e457a4c6b2f3679f0dfe7d286d7de 100644 (file)
 use super::lexical_region_resolve::RegionResolutionError;
 use super::region_constraints::GenericKind;
 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
-use crate::infer::{self, SuppressRegionErrors};
 
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::hir::Node;
+use crate::infer::{self, SuppressRegionErrors};
 use crate::infer::opaque_types;
 use crate::middle::region;
-use crate::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause};
-use crate::traits::{ObligationCauseCode};
+use crate::traits::{
+    IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
+};
 use crate::ty::error::TypeError;
 use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
+
 use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
-use std::{cmp, fmt};
+use rustc_error_codes::*;
 use syntax_pos::{Pos, Span};
 
-use rustc_error_codes::*;
+use std::{cmp, fmt};
 
 mod note;
 
@@ -1270,7 +1272,7 @@ pub fn note_type_err(
     }
 
     /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
-    /// suggest it.
+    /// suggests it.
     fn suggest_as_ref_where_appropriate(
         &self,
         span: Span,
index f7806188775fa80f37a956f40961128925789f66..f9443376a935ac6bef69f64c604c18802f790ced 100644 (file)
@@ -221,7 +221,7 @@ pub fn type_must_outlive(
 }
 
 /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
-/// obligation into a series of `'a: 'b` constraints and "verifys", as
+/// obligation into a series of `'a: 'b` constraints and "verify"s, as
 /// described on the module comment. The final constraints are emitted
 /// via a "delegate" of type `D` -- this is usually the `infcx`, which
 /// accrues them into the `region_obligations` code, but for NLL we
index 5f605756438c0945ebefe05a51bb08318c953970..4fe82f03b036eee2846573d585028c711a0b22e3 100644 (file)
@@ -248,7 +248,7 @@ fn from(kind: InterpError<'tcx>) -> Self {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
 pub enum PanicInfo<O> {
     Panic {
         msg: Symbol,
index 7c77b2c0711b9ee698c6d6fda501fcaefd9de304..78320c769f680f388550b61cd11ce0730b58e113 100644 (file)
@@ -1,11 +1,12 @@
-use std::fmt::{self, Display};
-use std::convert::TryFrom;
+use super::{AllocId, InterpResult};
 
 use crate::mir;
 use crate::ty::layout::{self, HasDataLayout, Size};
+
 use rustc_macros::HashStable;
 
-use super::{AllocId, InterpResult};
+use std::convert::TryFrom;
+use std::fmt::{self, Display};
 
 /// Used by `check_in_alloc` to indicate context of check
 #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
@@ -74,8 +75,8 @@ fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
     fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
         // FIXME: is it possible to over/underflow here?
         if i < 0 {
-            // Trickery to ensure that i64::min_value() works fine: compute n = -i.
-            // This formula only works for true negative values, it overflows for zero!
+            // Trickery to ensure that `i64::min_value()` works fine: compute `n = -i`.
+            // This formula only works for true negative values; it overflows for zero!
             let n = u64::max_value() - (i as u64) + 1;
             let res = val.overflowing_sub(n);
             self.truncate_to_ptr(res)
@@ -105,7 +106,7 @@ impl<T: layout::HasDataLayout> PointerArithmetic for T {}
 ///
 /// Defaults to the index based and loosely coupled `AllocId`.
 ///
-/// Pointer is also generic over the `Tag` associated with each pointer,
+/// `Pointer` is also generic over the `Tag` associated with each pointer,
 /// which is used to do provenance tracking during execution.
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
          RustcEncodable, RustcDecodable, Hash, HashStable)]
@@ -129,7 +130,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-/// Produces a `Pointer` which points to the beginning of the `Allocation`.
+/// Produces a `Pointer` that points to the beginning of the `Allocation`.
 impl From<AllocId> for Pointer {
     #[inline(always)]
     fn from(alloc_id: AllocId) -> Self {
index b7d0f538db5dc243b5a06a4fb61f7066efc1149a..bd793fd07bf22e00ad04a9ccf8016778f281bd09 100644 (file)
@@ -7,7 +7,7 @@
 use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
 use crate::hir;
-use crate::mir::interpret::{PanicInfo, Scalar};
+use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
@@ -292,7 +292,7 @@ pub fn local_kind(&self, local: Local) -> LocalKind {
     pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
-            if self.local_decls[local].is_user_variable.is_some() {
+            if self.local_decls[local].is_user_variable() {
                 None
             } else {
                 Some(local)
@@ -305,7 +305,7 @@ pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
     pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
-            if self.local_decls[local].is_user_variable.is_some() {
+            if self.local_decls[local].is_user_variable() {
                 Some(local)
             } else {
                 None
@@ -319,7 +319,7 @@ pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
         (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
             let decl = &self.local_decls[local];
-            if decl.is_user_variable.is_some() && decl.mutability == Mutability::Mut {
+            if decl.is_user_variable() && decl.mutability == Mutability::Mut {
                 Some(local)
             } else {
                 None
@@ -333,7 +333,7 @@ pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a
         (1..self.local_decls.len()).filter_map(move |index| {
             let local = Local::new(index);
             let decl = &self.local_decls[local];
-            if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
+            if (decl.is_user_variable() || index < self.arg_count + 1)
                 && decl.mutability == Mutability::Mut
             {
                 Some(local)
@@ -689,14 +689,8 @@ pub struct LocalDecl<'tcx> {
     /// Temporaries and the return place are always mutable.
     pub mutability: Mutability,
 
-    /// `Some(binding_mode)` if this corresponds to a user-declared local variable.
-    ///
-    /// This is solely used for local diagnostics when generating
-    /// warnings/errors when compiling the current crate, and
-    /// therefore it need not be visible across crates. pnkfelix
-    /// currently hypothesized we *need* to wrap this in a
-    /// `ClearCrossCrate` as long as it carries as `HirId`.
-    pub is_user_variable: Option<ClearCrossCrate<BindingForm<'tcx>>>,
+    // FIXME(matthewjasper) Don't store in this in `Body`
+    pub local_info: LocalInfo<'tcx>,
 
     /// `true` if this is an internal local.
     ///
@@ -721,6 +715,7 @@ pub struct LocalDecl<'tcx> {
     /// then it is a temporary created for evaluation of some
     /// subexpression of some block's tail expression (with no
     /// intervening statement context).
+    // FIXME(matthewjasper) Don't store in this in `Body`
     pub is_block_tail: Option<BlockTailInfo>,
 
     /// The type of this local.
@@ -730,6 +725,7 @@ pub struct LocalDecl<'tcx> {
     /// e.g., via `let x: T`, then we carry that type here. The MIR
     /// borrow checker needs this information since it can affect
     /// region inference.
+    // FIXME(matthewjasper) Don't store in this in `Body`
     pub user_ty: UserTypeProjections,
 
     /// The name of the local, used in debuginfo and pretty-printing.
@@ -824,6 +820,21 @@ pub struct LocalDecl<'tcx> {
     pub visibility_scope: SourceScope,
 }
 
+/// Extra information about a local that's used for diagnostics.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub enum LocalInfo<'tcx> {
+    /// A user-defined local variable or function parameter
+    ///
+    /// The `BindingForm` is solely used for local diagnostics when generating
+    /// warnings/errors when compiling the current crate, and therefore it need
+    /// not be visible across crates.
+    User(ClearCrossCrate<BindingForm<'tcx>>),
+    /// A temporary created that references the static with the given `DefId`.
+    StaticRef { def_id: DefId, is_thread_local: bool },
+    /// Any other temporary, the return place, or an anonymous function parameter.
+    Other,
+}
+
 impl<'tcx> LocalDecl<'tcx> {
     /// Returns `true` only if local is a binding that can itself be
     /// made mutable via the addition of the `mut` keyword, namely
@@ -832,15 +843,17 @@ impl<'tcx> LocalDecl<'tcx> {
     /// - `let x = ...`,
     /// - or `match ... { C(x) => ... }`
     pub fn can_be_made_mutable(&self) -> bool {
-        match self.is_user_variable {
-            Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+        match self.local_info {
+            LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
                 binding_mode: ty::BindingMode::BindByValue(_),
                 opt_ty_info: _,
                 opt_match_place: _,
                 pat_span: _,
             }))) => true,
 
-            Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm))) => true,
+            LocalInfo::User(
+                ClearCrossCrate::Set(BindingForm::ImplicitSelf(ImplicitSelfKind::Imm)),
+            ) => true,
 
             _ => false,
         }
@@ -850,26 +863,54 @@ pub fn can_be_made_mutable(&self) -> bool {
     /// `ref mut ident` binding. (Such bindings cannot be made into
     /// mutable bindings, but the inverse does not necessarily hold).
     pub fn is_nonref_binding(&self) -> bool {
-        match self.is_user_variable {
-            Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+        match self.local_info {
+            LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
                 binding_mode: ty::BindingMode::BindByValue(_),
                 opt_ty_info: _,
                 opt_match_place: _,
                 pat_span: _,
             }))) => true,
 
-            Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,
+            LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,
 
             _ => false,
         }
     }
 
+    /// Returns `true` if this variable is a named variable or function
+    /// parameter declared by the user.
+    #[inline]
+    pub fn is_user_variable(&self) -> bool {
+        match self.local_info {
+            LocalInfo::User(_) => true,
+            _ => false,
+        }
+    }
+
     /// Returns `true` if this is a reference to a variable bound in a `match`
     /// expression that is used to access said variable for the guard of the
     /// match arm.
     pub fn is_ref_for_guard(&self) -> bool {
-        match self.is_user_variable {
-            Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
+        match self.local_info {
+            LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
+            _ => false,
+        }
+    }
+
+    /// Returns `Some` if this is a reference to a static item that is used to
+    /// access that static
+    pub fn is_ref_to_static(&self) -> bool {
+        match self.local_info {
+            LocalInfo::StaticRef { .. } => true,
+            _ => false,
+        }
+    }
+
+    /// Returns `Some` if this is a reference to a static item that is used to
+    /// access that static
+    pub fn is_ref_to_thread_local(&self) -> bool {
+        match self.local_info {
+            LocalInfo::StaticRef { is_thread_local, .. } => is_thread_local,
             _ => false,
         }
     }
@@ -918,7 +959,7 @@ fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -
             source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal,
-            is_user_variable: None,
+            local_info: LocalInfo::Other,
             is_block_tail: None,
         }
     }
@@ -937,7 +978,7 @@ pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
             internal: false,
             is_block_tail: None,
             name: None, // FIXME maybe we do want some name here?
-            is_user_variable: None,
+            local_info: LocalInfo::Other,
         }
     }
 }
@@ -999,7 +1040,7 @@ pub struct Terminator<'tcx> {
     pub kind: TerminatorKind<'tcx>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
 pub enum TerminatorKind<'tcx> {
     /// Block should have one successor in the graph; we jump there.
     Goto { target: BasicBlock },
@@ -1528,7 +1569,7 @@ pub fn replace_nop(&mut self) -> Self {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub enum StatementKind<'tcx> {
     /// Write the RHS Rvalue to the LHS Place.
     Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
@@ -1594,7 +1635,7 @@ pub enum RetagKind {
 }
 
 /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
 pub enum FakeReadCause {
     /// Inject a fake read of the borrowed input at the end of each guards
     /// code.
@@ -1636,7 +1677,7 @@ pub enum FakeReadCause {
     ForIndex,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
 pub struct InlineAsm<'tcx> {
     pub asm: hir::InlineAsmInner,
     pub outputs: Box<[Place<'tcx>]>,
@@ -2068,7 +2109,7 @@ pub fn to_copy(&self) -> Self {
 ///////////////////////////////////////////////////////////////////////////
 /// Rvalues
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
 pub enum Rvalue<'tcx> {
     /// x (either a move or copy, depending on type of x)
     Use(Operand<'tcx>),
@@ -2341,6 +2382,24 @@ pub struct Constant<'tcx> {
     pub literal: &'tcx ty::Const<'tcx>,
 }
 
+impl Constant<'tcx> {
+    pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
+        match self.literal.val.try_to_scalar() {
+            Some(Scalar::Ptr(ptr)) => match tcx.alloc_map.lock().get(ptr.alloc_id) {
+                Some(GlobalAlloc::Static(def_id)) => Some(def_id),
+                Some(_) => None,
+                None => {
+                    tcx.sess.delay_span_bug(
+                        DUMMY_SP, "MIR cannot contain dangling const pointers",
+                    );
+                    None
+                },
+            },
+            _ => None,
+        }
+    }
+}
+
 /// A collection of projections into user types.
 ///
 /// They are projections because a binding can occur a part of a
@@ -2444,7 +2503,7 @@ pub fn variant(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx, field: Fi
 /// * `let (x, _): T = ...` -- here, the `projs` vector would contain
 ///   `field[0]` (aka `.0`), indicating that the type of `s` is
 ///   determined by finding the type of the `.0` field from `T`.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
 pub struct UserTypeProjection {
     pub base: UserTypeAnnotationIndex,
     pub projs: Vec<ProjectionKind>,
index ccf7d8fbf8668ed83603befccb698538c4f37630..a66a49f103f68f0d6a4b66747a7b733c1e01f535 100644 (file)
@@ -81,7 +81,7 @@ pub fn projection_ty_core<V, T>(
                 let ty = self.ty
                              .builtin_deref(true)
                              .unwrap_or_else(|| {
-                                 bug!("deref projection of non-dereferencable ty {:?}", self)
+                                 bug!("deref projection of non-dereferenceable ty {:?}", self)
                              })
                              .ty;
                 PlaceTy::from_ty(ty)
index 6a41b843e5794dd2ee0b2eadd57b75cfb8112379..fc0e77aab43a4d9a38cebb573df5d6ba3475679c 100644 (file)
@@ -691,7 +691,7 @@ fn super_local_decl(&mut self,
                     source_info,
                     visibility_scope,
                     internal: _,
-                    is_user_variable: _,
+                    local_info: _,
                     is_block_tail: _,
                 } = local_decl;
 
index b9b6a5f2342e25ed46564966b02b50264397e6e2..2b1dfcaf68cec9f190878d4c57d9f457451c6353 100644 (file)
@@ -1,13 +1,10 @@
 //! Contains infrastructure for configuring the compiler, including parsing
 //! command-line options.
 
-// ignore-tidy-filelength
-
 use crate::lint;
 use crate::middle::cstore;
 use crate::session::{early_error, early_warn, Session};
 use crate::session::search_paths::SearchPath;
-use crate::hir::map as hir_map;
 
 use rustc_data_structures::fx::FxHashSet;
 
@@ -444,7 +441,7 @@ pub struct Options {
         // by the compiler.
         json_artifact_notifications: bool [TRACKED],
 
-        pretty: Option<(PpMode, Option<UserIdentifiedItem>)> [UNTRACKED],
+        pretty: Option<PpMode> [UNTRACKED],
     }
 );
 
@@ -1203,7 +1200,7 @@ fn parse_symbol_mangling_version(
     force_frame_pointers: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "force use of the frame pointers"),
     debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
-        "explicitly enable the cfg(debug_assertions) directive"),
+        "explicitly enable the `cfg(debug_assertions)` directive"),
     inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
         "set the threshold for inlining a function (default: 225)"),
     panic: Option<PanicStrategy> = (None, parse_panic_strategy,
@@ -2562,7 +2559,7 @@ fn parse_pretty(
     matches: &getopts::Matches,
     debugging_opts: &DebuggingOptions,
     efmt: ErrorOutputType,
-) -> Option<(PpMode, Option<UserIdentifiedItem>)> {
+) -> Option<PpMode> {
     let pretty = if debugging_opts.unstable_options {
         matches.opt_default("pretty", "normal").map(|a| {
             // stable pretty-print variants only
@@ -2585,13 +2582,10 @@ fn parse_pretty_inner(
         efmt: ErrorOutputType,
         name: &str,
         extended: bool,
-    ) -> (PpMode, Option<UserIdentifiedItem>) {
+    ) -> PpMode {
         use PpMode::*;
         use PpSourceMode::*;
-        let mut split = name.splitn(2, '=');
-        let first = split.next().unwrap();
-        let opt_second = split.next();
-        let first = match (first, extended) {
+        let first = match (name, extended) {
             ("normal", _) => PpmSource(PpmNormal),
             ("identified", _) => PpmSource(PpmIdentified),
             ("everybody_loops", true) => PpmSource(PpmEveryBodyLoops),
@@ -2619,8 +2613,7 @@ fn parse_pretty_inner(
                 }
             }
         };
-        let opt_second = opt_second.and_then(|s| s.parse::<UserIdentifiedItem>().ok());
-        (first, opt_second)
+        first
     }
 }
 
@@ -2752,13 +2745,13 @@ pub enum PpMode {
 }
 
 impl PpMode {
-    pub fn needs_ast_map(&self, opt_uii: &Option<UserIdentifiedItem>) -> bool {
+    pub fn needs_ast_map(&self) -> bool {
         use PpMode::*;
         use PpSourceMode::*;
         match *self {
             PpmSource(PpmNormal) |
             PpmSource(PpmEveryBodyLoops) |
-            PpmSource(PpmIdentified) => opt_uii.is_some(),
+            PpmSource(PpmIdentified) => false,
 
             PpmSource(PpmExpanded) |
             PpmSource(PpmExpandedIdentified) |
@@ -2780,102 +2773,6 @@ pub fn needs_analysis(&self) -> bool {
     }
 }
 
-#[derive(Clone, Debug)]
-pub enum UserIdentifiedItem {
-    ItemViaNode(ast::NodeId),
-    ItemViaPath(Vec<String>),
-}
-
-impl FromStr for UserIdentifiedItem {
-    type Err = ();
-    fn from_str(s: &str) -> Result<UserIdentifiedItem, ()> {
-        use UserIdentifiedItem::*;
-        Ok(s.parse()
-            .map(ast::NodeId::from_u32)
-            .map(ItemViaNode)
-            .unwrap_or_else(|_| ItemViaPath(s.split("::").map(|s| s.to_string()).collect())))
-    }
-}
-
-pub enum NodesMatchingUII<'a> {
-    NodesMatchingDirect(std::option::IntoIter<ast::NodeId>),
-    NodesMatchingSuffix(Box<dyn Iterator<Item = ast::NodeId> + 'a>),
-}
-
-impl<'a> Iterator for NodesMatchingUII<'a> {
-    type Item = ast::NodeId;
-
-    fn next(&mut self) -> Option<ast::NodeId> {
-        use NodesMatchingUII::*;
-        match self {
-            &mut NodesMatchingDirect(ref mut iter) => iter.next(),
-            &mut NodesMatchingSuffix(ref mut iter) => iter.next(),
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        use NodesMatchingUII::*;
-        match self {
-            &NodesMatchingDirect(ref iter) => iter.size_hint(),
-            &NodesMatchingSuffix(ref iter) => iter.size_hint(),
-        }
-    }
-}
-
-impl UserIdentifiedItem {
-    pub fn reconstructed_input(&self) -> String {
-        use UserIdentifiedItem::*;
-        match *self {
-            ItemViaNode(node_id) => node_id.to_string(),
-            ItemViaPath(ref parts) => parts.join("::"),
-        }
-    }
-
-    pub fn all_matching_node_ids<'a, 'hir>(&'a self,
-                                       map: &'a hir_map::Map<'hir>)
-                                       -> NodesMatchingUII<'a> {
-        use UserIdentifiedItem::*;
-        use NodesMatchingUII::*;
-        match *self {
-            ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()),
-            ItemViaPath(ref parts) => {
-                NodesMatchingSuffix(Box::new(map.nodes_matching_suffix(&parts)))
-            }
-        }
-    }
-
-    pub fn to_one_node_id(self,
-                      user_option: &str,
-                      sess: &Session,
-                      map: &hir_map::Map<'_>)
-                      -> ast::NodeId {
-        let fail_because = |is_wrong_because| -> ast::NodeId {
-            let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \
-                                   {}, which {}",
-                                  user_option,
-                                  self.reconstructed_input(),
-                                  is_wrong_because);
-            sess.fatal(&message)
-        };
-
-        let mut saw_node = ast::DUMMY_NODE_ID;
-        let mut seen = 0;
-        for node in self.all_matching_node_ids(map) {
-            saw_node = node;
-            seen += 1;
-            if seen > 1 {
-                fail_because("does not resolve uniquely");
-            }
-        }
-        if seen == 0 {
-            fail_because("does not resolve to any item");
-        }
-
-        assert!(seen == 1);
-        return saw_node;
-    }
-}
-
 /// Command-line arguments passed to the compiler have to be incorporated with
 /// the dependency tracking system for incremental compilation. This module
 /// provides some utilities to make this more convenient.
index 1af20188ab5db64a338e8d88c64c30157ff78873..af6522df61e04a8d9c04149f6ed410707505b5da 100644 (file)
@@ -24,7 +24,7 @@
 use syntax::feature_gate;
 use errors::json::JsonEmitter;
 use syntax::source_map;
-use syntax::sess::{ParseSess, ProcessCfgMod};
+use syntax::sess::ParseSess;
 use syntax_pos::{MultiSpan, Span};
 
 use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
@@ -925,7 +925,6 @@ pub fn build_session(
     sopts: config::Options,
     local_crate_source_file: Option<PathBuf>,
     registry: errors::registry::Registry,
-    process_cfg_mod: ProcessCfgMod,
 ) -> Session {
     let file_path_mapping = sopts.file_path_mapping();
 
@@ -936,7 +935,6 @@ pub fn build_session(
         Lrc::new(source_map::SourceMap::new(file_path_mapping)),
         DiagnosticOutput::Default,
         Default::default(),
-        process_cfg_mod,
     )
 }
 
@@ -1015,7 +1013,6 @@ pub fn build_session_with_source_map(
     source_map: Lrc<source_map::SourceMap>,
     diagnostics_output: DiagnosticOutput,
     lint_caps: FxHashMap<lint::LintId, lint::Level>,
-    process_cfg_mod: ProcessCfgMod,
 ) -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -1061,7 +1058,6 @@ pub fn build_session_with_source_map(
         diagnostic_handler,
         source_map,
         lint_caps,
-        process_cfg_mod,
     )
 }
 
@@ -1071,7 +1067,6 @@ fn build_session_(
     span_diagnostic: errors::Handler,
     source_map: Lrc<source_map::SourceMap>,
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
-    process_cfg_mod: ProcessCfgMod,
 ) -> Session {
     let self_profiler =
         if let SwitchWithOptPath::Enabled(ref d) = sopts.debugging_opts.self_profile {
@@ -1109,7 +1104,6 @@ fn build_session_(
     let parse_sess = ParseSess::with_span_handler(
         span_diagnostic,
         source_map,
-        process_cfg_mod,
     );
     let sysroot = match &sopts.maybe_sysroot {
         Some(sysroot) => sysroot.clone(),
index 9faf58aee6f924df18f04aa53cff54bf93cffda8..479bffc3ea00d6f0a802e7279abdbe105e8b6804 100644 (file)
@@ -1,18 +1,18 @@
-//! Support code for rustdoc and external tools . You really don't
-//! want to be using this unless you need to.
+//! Support code for rustdoc and external tools.
+//! You really don't want to be using this unless you need to.
 
 use super::*;
 
-use std::collections::hash_map::Entry;
-use std::collections::VecDeque;
-
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::InferCtxt;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-
 use crate::ty::fold::TypeFolder;
 use crate::ty::{Region, RegionVid};
 
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+
+use std::collections::hash_map::Entry;
+use std::collections::VecDeque;
+
 // FIXME(twk): this is obviously not nice to duplicate like that
 #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
 pub enum RegionTarget<'tcx> {
@@ -233,43 +233,45 @@ pub fn find_auto_trait_generics<A>(
 }
 
 impl AutoTraitFinder<'tcx> {
-    // The core logic responsible for computing the bounds for our synthesized impl.
-    //
-    // To calculate the bounds, we call SelectionContext.select in a loop. Like FulfillmentContext,
-    // we recursively select the nested obligations of predicates we encounter. However, whenever we
-    // encounter an UnimplementedError involving a type parameter, we add it to our ParamEnv. Since
-    // our goal is to determine when a particular type implements an auto trait, Unimplemented
-    // errors tell us what conditions need to be met.
-    //
-    // This method ends up working somewhat similarly to FulfillmentContext, but with a few key
-    // differences. FulfillmentContext works under the assumption that it's dealing with concrete
-    // user code. According, it considers all possible ways that a Predicate could be met - which
-    // isn't always what we want for a synthesized impl. For example, given the predicate 'T:
-    // Iterator', FulfillmentContext can end up reporting an Unimplemented error for T:
-    // IntoIterator - since there's an implementation of Iteratpr where T: IntoIterator,
-    // FulfillmentContext will drive SelectionContext to consider that impl before giving up. If we
-    // were to rely on FulfillmentContext's decision, we might end up synthesizing an impl like
-    // this:
-    // 'impl<T> Send for Foo<T> where T: IntoIterator'
-    //
-    // While it might be technically true that Foo implements Send where T: IntoIterator,
-    // the bound is overly restrictive - it's really only necessary that T: Iterator.
-    //
-    // For this reason, evaluate_predicates handles predicates with type variables specially. When
-    // we encounter an Unimplemented error for a bound such as 'T: Iterator', we immediately add it
-    // to our ParamEnv, and add it to our stack for recursive evaluation. When we later select it,
-    // we'll pick up any nested bounds, without ever inferring that 'T: IntoIterator' needs to
-    // hold.
-    //
-    // One additional consideration is supertrait bounds. Normally, a ParamEnv is only ever
-    // constructed once for a given type. As part of the construction process, the ParamEnv will
-    // have any supertrait bounds normalized - e.g., if we have a type 'struct Foo<T: Copy>', the
-    // ParamEnv will contain 'T: Copy' and 'T: Clone', since 'Copy: Clone'. When we construct our
-    // own ParamEnv, we need to do this ourselves, through traits::elaborate_predicates, or else
-    // SelectionContext will choke on the missing predicates. However, this should never show up in
-    // the final synthesized generics: we don't want our generated docs page to contain something
-    // like 'T: Copy + Clone', as that's redundant. Therefore, we keep track of a separate
-    // 'user_env', which only holds the predicates that will actually be displayed to the user.
+    /// The core logic responsible for computing the bounds for our synthesized impl.
+    ///
+    /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like
+    /// `FulfillmentContext`, we recursively select the nested obligations of predicates we
+    /// encounter. However, whenever we encounter an `UnimplementedError` involving a type
+    /// parameter, we add it to our `ParamEnv`. Since our goal is to determine when a particular
+    /// type implements an auto trait, Unimplemented errors tell us what conditions need to be met.
+    ///
+    /// This method ends up working somewhat similarly to `FulfillmentContext`, but with a few key
+    /// differences. `FulfillmentContext` works under the assumption that it's dealing with concrete
+    /// user code. According, it considers all possible ways that a `Predicate` could be met, which
+    /// isn't always what we want for a synthesized impl. For example, given the predicate `T:
+    /// Iterator`, `FulfillmentContext` can end up reporting an Unimplemented error for `T:
+    /// IntoIterator` -- since there's an implementation of `Iterator` where `T: IntoIterator`,
+    /// `FulfillmentContext` will drive `SelectionContext` to consider that impl before giving up.
+    /// If we were to rely on `FulfillmentContext`s decision, we might end up synthesizing an impl
+    /// like this:
+    ///
+    ///     impl<T> Send for Foo<T> where T: IntoIterator
+    ///
+    /// While it might be technically true that Foo implements Send where `T: IntoIterator`,
+    /// the bound is overly restrictive - it's really only necessary that `T: Iterator`.
+    ///
+    /// For this reason, `evaluate_predicates` handles predicates with type variables specially.
+    /// When we encounter an `Unimplemented` error for a bound such as `T: Iterator`, we immediately
+    /// add it to our `ParamEnv`, and add it to our stack for recursive evaluation. When we later
+    /// select it, we'll pick up any nested bounds, without ever inferring that `T: IntoIterator`
+    /// needs to hold.
+    ///
+    /// One additional consideration is supertrait bounds. Normally, a `ParamEnv` is only ever
+    /// constructed once for a given type. As part of the construction process, the `ParamEnv` will
+    /// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo<T: Copy>`, the
+    /// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our
+    /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or
+    /// else `SelectionContext` will choke on the missing predicates. However, this should never
+    /// show up in the final synthesized generics: we don't want our generated docs page to contain
+    /// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a
+    /// separate `user_env`, which only holds the predicates that will actually be displayed to the
+    /// user.
     fn evaluate_predicates(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
@@ -307,7 +309,7 @@ fn evaluate_predicates(
                 continue;
             }
 
-            // Call infcx.resolve_vars_if_possible to see if we can
+            // Call `infcx.resolve_vars_if_possible` to see if we can
             // get rid of any inference variables.
             let obligation = infcx.resolve_vars_if_possible(
                 &Obligation::new(dummy_cause.clone(), new_env, pred)
@@ -316,14 +318,14 @@ fn evaluate_predicates(
 
             match &result {
                 &Ok(Some(ref vtable)) => {
-                    // If we see an explicit negative impl (e.g., 'impl !Send for MyStruct'),
+                    // If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
                     // we immediately bail out, since it's impossible for us to continue.
                     match vtable {
                         Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => {
-                            // Blame tidy for the weird bracket placement
+                            // Blame 'tidy' for the weird bracket placement.
                             if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative
                             {
-                                debug!("evaluate_nested_obligations: Found explicit negative impl\
+                                debug!("evaluate_nested_obligations: found explicit negative impl\
                                         {:?}, bailing out", impl_def_id);
                                 return None;
                             }
@@ -356,7 +358,7 @@ fn evaluate_predicates(
                         predicates.push_back(pred);
                     } else {
                         debug!(
-                            "evaluate_nested_obligations: Unimplemented found, bailing: \
+                            "evaluate_nested_obligations: `Unimplemented` found, bailing: \
                              {:?} {:?} {:?}",
                             ty,
                             pred,
@@ -392,29 +394,29 @@ fn evaluate_predicates(
         return Some((new_env, final_user_env));
     }
 
-    // This method is designed to work around the following issue:
-    // When we compute auto trait bounds, we repeatedly call SelectionContext.select,
-    // progressively building a ParamEnv based on the results we get.
-    // However, our usage of SelectionContext differs from its normal use within the compiler,
-    // in that we capture and re-reprocess predicates from Unimplemented errors.
-    //
-    // This can lead to a corner case when dealing with region parameters.
-    // During our selection loop in evaluate_predicates, we might end up with
-    // two trait predicates that differ only in their region parameters:
-    // one containing a HRTB lifetime parameter, and one containing a 'normal'
-    // lifetime parameter. For example:
-    //
-    // T as MyTrait<'a>
-    // T as MyTrait<'static>
-    //
-    // If we put both of these predicates in our computed ParamEnv, we'll
-    // confuse SelectionContext, since it will (correctly) view both as being applicable.
-    //
-    // To solve this, we pick the 'more strict' lifetime bound - i.e., the HRTB
-    // Our end goal is to generate a user-visible description of the conditions
-    // under which a type implements an auto trait. A trait predicate involving
-    // a HRTB means that the type needs to work with any choice of lifetime,
-    // not just one specific lifetime (e.g., 'static).
+    /// This method is designed to work around the following issue:
+    /// When we compute auto trait bounds, we repeatedly call `SelectionContext.select`,
+    /// progressively building a `ParamEnv` based on the results we get.
+    /// However, our usage of `SelectionContext` differs from its normal use within the compiler,
+    /// in that we capture and re-reprocess predicates from `Unimplemented` errors.
+    ///
+    /// This can lead to a corner case when dealing with region parameters.
+    /// During our selection loop in `evaluate_predicates`, we might end up with
+    /// two trait predicates that differ only in their region parameters:
+    /// one containing a HRTB lifetime parameter, and one containing a 'normal'
+    /// lifetime parameter. For example:
+    ///
+    ///     T as MyTrait<'a>
+    ///     T as MyTrait<'static>
+    ///
+    /// If we put both of these predicates in our computed `ParamEnv`, we'll
+    /// confuse `SelectionContext`, since it will (correctly) view both as being applicable.
+    ///
+    /// To solve this, we pick the 'more strict' lifetime bound -- i.e., the HRTB
+    /// Our end goal is to generate a user-visible description of the conditions
+    /// under which a type implements an auto trait. A trait predicate involving
+    /// a HRTB means that the type needs to work with any choice of lifetime,
+    /// not just one specific lifetime (e.g., `'static`).
     fn add_user_pred<'c>(
         &self,
         user_computed_preds: &mut FxHashSet<ty::Predicate<'c>>,
@@ -430,7 +432,7 @@ fn add_user_pred<'c>(
 
                         if !new_substs.types().eq(old_substs.types()) {
                             // We can't compare lifetimes if the types are different,
-                            // so skip checking old_pred
+                            // so skip checking `old_pred`.
                             return true;
                         }
 
@@ -438,8 +440,8 @@ fn add_user_pred<'c>(
                             new_substs.regions().zip(old_substs.regions())
                         {
                             match (new_region, old_region) {
-                                // If both predicates have an 'ReLateBound' (a HRTB) in the
-                                // same spot, we do nothing
+                                // If both predicates have an `ReLateBound` (a HRTB) in the
+                                // same spot, we do nothing.
                                 (
                                     ty::RegionKind::ReLateBound(_, _),
                                     ty::RegionKind::ReLateBound(_, _),
@@ -463,13 +465,13 @@ fn add_user_pred<'c>(
                                     // varaible).
                                     //
                                     // In both cases, we want to remove the old predicate,
-                                    // from user_computed_preds, and replace it with the new
+                                    // from `user_computed_preds`, and replace it with the new
                                     // one. Having both the old and the new
-                                    // predicate in a ParamEnv would confuse SelectionContext
+                                    // predicate in a `ParamEnv` would confuse `SelectionContext`.
                                     //
                                     // We're currently in the predicate passed to 'retain',
-                                    // so we return 'false' to remove the old predicate from
-                                    // user_computed_preds
+                                    // so we return `false` to remove the old predicate from
+                                    // `user_computed_preds`.
                                     return false;
                                 }
                                 (_, ty::RegionKind::ReLateBound(_, _)) |
@@ -486,8 +488,8 @@ fn add_user_pred<'c>(
                                     // predicate has some other type of region.
                                     //
                                     // We want to leave the old
-                                    // predicate in user_computed_preds, and skip adding
-                                    // new_pred to user_computed_params.
+                                    // predicate in `user_computed_preds`, and skip adding
+                                    // new_pred to `user_computed_params`.
                                     should_add_new = false
                                 },
                                 _ => {}
@@ -505,8 +507,8 @@ fn add_user_pred<'c>(
         }
     }
 
-    // This is very similar to handle_lifetimes. However, instead of matching ty::Region's
-    // to each other, we match ty::RegionVid's to ty::Region's
+    /// This is very similar to `handle_lifetimes`. However, instead of matching `ty::Region`s
+    /// to each other, we match `ty::RegionVid`s to `ty::Region`s.
     fn map_vid_to_region<'cx>(
         &self,
         regions: &RegionConstraintData<'cx>,
@@ -573,7 +575,7 @@ fn map_vid_to_region<'cx>(
                             finished_map.insert(v1, r1);
                         }
                         (&RegionTarget::Region(_), &RegionTarget::RegionVid(_)) => {
-                            // Do nothing - we don't care about regions that are smaller than vids
+                            // Do nothing; we don't care about regions that are smaller than vids.
                         }
                         (&RegionTarget::RegionVid(_), &RegionTarget::RegionVid(_)) => {
                             if let Entry::Occupied(v) = vid_map.entry(*smaller) {
index 3aa355ce11a8a2ccbc4ada0a4c1c28b705111084..d94e004db29789ae02a6b1c56d72e688ced9ba60 100644 (file)
@@ -191,23 +191,23 @@ pub enum ObligationCauseCode<'tcx> {
     /// Obligation incurred due to a coercion.
     Coercion { source: Ty<'tcx>, target: Ty<'tcx> },
 
-    // Various cases where expressions must be sized/copy/etc:
-    /// L = X implies that L is Sized
+    /// Various cases where expressions must be `Sized` / `Copy` / etc.
+    /// `L = X` implies that `L` is `Sized`.
     AssignmentLhsSized,
-    /// (x1, .., xn) must be Sized
+    /// `(x1, .., xn)` must be `Sized`.
     TupleInitializerSized,
-    /// S { ... } must be Sized
+    /// `S { ... }` must be `Sized`.
     StructInitializerSized,
-    /// Type of each variable must be Sized
+    /// Type of each variable must be `Sized`.
     VariableType(hir::HirId),
-    /// Argument type must be Sized
+    /// Argument type must be `Sized`.
     SizedArgumentType,
-    /// Return type must be Sized
+    /// Return type must be `Sized`.
     SizedReturnType,
-    /// Yield type must be Sized
+    /// Yield type must be `Sized`.
     SizedYieldType,
-    /// [T,..n] --> T must be Copy. If `true`, suggest `const_in_array_repeat_expressions` feature
-    /// flag.
+    /// `[T, ..n]` implies that `T` must be `Copy`.
+    /// If `true`, suggest `const_in_array_repeat_expressions` feature flag.
     RepeatVec(bool),
 
     /// Types of fields (other than the last, except for packed structs) in a struct must be sized.
@@ -216,7 +216,7 @@ pub enum ObligationCauseCode<'tcx> {
     /// Constant expressions must be sized.
     ConstSized,
 
-    /// Static items must have `Sync` type
+    /// `static` items must have `Sync` type.
     SharedStatic,
 
     BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
@@ -602,7 +602,7 @@ pub enum Vtable<'tcx, N> {
 /// the impl's type parameters.
 ///
 /// The type parameter `N` indicates the type used for "nested
-/// obligations" that are required by the impl. During type check, this
+/// obligations" that are required by the impl. During type-check, this
 /// is `Obligation`, as one might expect. During codegen, however, this
 /// is `()`, because codegen only requires a shallow resolution of an
 /// impl, and nested obligations are satisfied later.
@@ -1046,8 +1046,7 @@ fn vtable_methods<'tcx>(
                     return None;
                 }
 
-                // the method may have some early-bound lifetimes, add
-                // regions for those
+                // The method may have some early-bound lifetimes; add regions for those.
                 let substs = trait_ref.map_bound(|trait_ref|
                     InternalSubsts::for_item(tcx, def_id, |param, _|
                         match param.kind {
@@ -1060,15 +1059,15 @@ fn vtable_methods<'tcx>(
                     )
                 );
 
-                // the trait type may have higher-ranked lifetimes in it;
-                // so erase them if they appear, so that we get the type
-                // at some particular call site
+                // The trait type may have higher-ranked lifetimes in it;
+                // erase them if they appear, so that we get the type
+                // at some particular call site.
                 let substs = tcx.normalize_erasing_late_bound_regions(
                     ty::ParamEnv::reveal_all(),
                     &substs
                 );
 
-                // It's possible that the method relies on where clauses that
+                // It's possible that the method relies on where-clauses that
                 // do not hold for this particular set of type parameters.
                 // Note that this method could then never be called, so we
                 // do not want to try and codegen it, in that case (see #23435).
index ffc94cf2b125eb870905c98e4f9bdb64b79dfa3c..283fa56d11f4f05a805ded364d7f7362c91b3bf1 100644 (file)
@@ -157,7 +157,7 @@ pub fn intercrate_ambiguity_hint(&self) -> String {
 struct TraitObligationStack<'prev, 'tcx> {
     obligation: &'prev TraitObligation<'tcx>,
 
-    /// Trait ref from `obligation` but "freshened" with the
+    /// The trait ref from `obligation` but "freshened" with the
     /// selection-context's freshener. Used to check for recursion.
     fresh_trait_ref: ty::PolyTraitRef<'tcx>,
 
@@ -193,11 +193,11 @@ struct TraitObligationStack<'prev, 'tcx> {
 
     previous: TraitObligationStackList<'prev, 'tcx>,
 
-    /// Number of parent frames plus one -- so the topmost frame has depth 1.
+    /// The number of parent frames plus one (thus, the topmost frame has depth 1).
     depth: usize,
 
-    /// Depth-first number of this node in the search graph -- a
-    /// pre-order index.  Basically a freshly incremented counter.
+    /// The depth-first number of this node in the search graph -- a
+    /// pre-order index. Basically, a freshly incremented counter.
     dfn: usize,
 }
 
@@ -239,9 +239,9 @@ pub struct SelectionCache<'tcx> {
 ///    }
 ///    fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
 ///
-/// we can't just use the impl to resolve the <T as AsDebug> obligation
-/// - a type from another crate (that doesn't implement fmt::Debug) could
-/// implement AsDebug.
+/// we can't just use the impl to resolve the `<T as AsDebug>` obligation
+/// -- a type from another crate (that doesn't implement `fmt::Debug`) could
+/// implement `AsDebug`.
 ///
 /// Because where-clauses match the type exactly, multiple clauses can
 /// only match if there are unresolved variables, and we can mostly just
@@ -266,10 +266,10 @@ pub struct SelectionCache<'tcx> {
 ///    }
 ///    fn main() { foo(false); }
 ///
-/// Here the obligation <T as Foo<$0>> can be matched by both the blanket
-/// impl and the where-clause. We select the where-clause and unify $0=bool,
+/// Here the obligation `<T as Foo<$0>>` can be matched by both the blanket
+/// impl and the where-clause. We select the where-clause and unify `$0=bool`,
 /// so the program prints "false". However, if the where-clause is omitted,
-/// the blanket impl is selected, we unify $0=(), and the program prints
+/// the blanket impl is selected, we unify `$0=()`, and the program prints
 /// "()".
 ///
 /// Exactly the same issues apply to projection and object candidates, except
@@ -282,8 +282,8 @@ pub struct SelectionCache<'tcx> {
 /// parameter environment.
 #[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)]
 enum SelectionCandidate<'tcx> {
-    /// If has_nested is false, there are no *further* obligations
     BuiltinCandidate {
+        /// `false` if there are no *further* obligations.
         has_nested: bool,
     },
     ParamCandidate(ty::PolyTraitRef<'tcx>),
@@ -303,7 +303,7 @@ enum SelectionCandidate<'tcx> {
     GeneratorCandidate,
 
     /// Implementation of a `Fn`-family trait by one of the anonymous
-    /// types generated for a fn pointer type (e.g., `fn(int)->int`)
+    /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
     FnPointerCandidate,
 
     TraitAliasCandidate(DefId),
@@ -339,11 +339,11 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 }
 
 struct SelectionCandidateSet<'tcx> {
-    // a list of candidates that definitely apply to the current
+    // A list of candidates that definitely apply to the current
     // obligation (meaning: types unify).
     vec: Vec<SelectionCandidate<'tcx>>,
 
-    // if this is true, then there were candidates that might or might
+    // If `true`, then there were candidates that might or might
     // not have applied, but we couldn't tell. This occurs when some
     // of the input types are type variables, in which case there are
     // various "builtin" rules that might or might not trigger.
@@ -358,7 +358,7 @@ struct EvaluatedCandidate<'tcx> {
 
 /// When does the builtin impl for `T: Trait` apply?
 enum BuiltinImplConditions<'tcx> {
-    /// The impl is conditional on T1,T2,.. : Trait
+    /// The impl is conditional on `T1, T2, ...: Trait`.
     Where(ty::Binder<Vec<Ty<'tcx>>>),
     /// There is no built-in impl. There may be some other
     /// candidate (a where-clause or user-defined impl).
@@ -381,15 +381,15 @@ enum BuiltinImplConditions<'tcx> {
 ///     the categories it's easy to see that the unions are correct.
 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, HashStable)]
 pub enum EvaluationResult {
-    /// Evaluation successful
+    /// Evaluation successful.
     EvaluatedToOk,
-    /// Evaluation successful, but there were unevaluated region obligations
+    /// Evaluation successful, but there were unevaluated region obligations.
     EvaluatedToOkModuloRegions,
-    /// Evaluation is known to be ambiguous - it *might* hold for some
+    /// Evaluation is known to be ambiguous -- it *might* hold for some
     /// assignment of inference variables, but it might not.
     ///
-    /// While this has the same meaning as `EvaluatedToUnknown` - we can't
-    /// know whether this obligation holds or not - it is the result we
+    /// While this has the same meaning as `EvaluatedToUnknown` -- we can't
+    /// know whether this obligation holds or not -- it is the result we
     /// would get with an empty stack, and therefore is cacheable.
     EvaluatedToAmbig,
     /// Evaluation failed because of recursion involving inference
@@ -404,29 +404,29 @@ pub enum EvaluationResult {
     /// We know this branch can't be a part of a minimal proof-tree for
     /// the "root" of our cycle, because then we could cut out the recursion
     /// and maintain a valid proof tree. However, this does not mean
-    /// that all the obligations on this branch do not hold - it's possible
+    /// that all the obligations on this branch do not hold -- it's possible
     /// that we entered this branch "speculatively", and that there
     /// might be some other way to prove this obligation that does not
-    /// go through this cycle - so we can't cache this as a failure.
+    /// go through this cycle -- so we can't cache this as a failure.
     ///
     /// For example, suppose we have this:
     ///
     /// ```rust,ignore (pseudo-Rust)
-    ///     pub trait Trait { fn xyz(); }
-    ///     // This impl is "useless", but we can still have
-    ///     // an `impl Trait for SomeUnsizedType` somewhere.
-    ///     impl<T: Trait + Sized> Trait for T { fn xyz() {} }
+    /// pub trait Trait { fn xyz(); }
+    /// // This impl is "useless", but we can still have
+    /// // an `impl Trait for SomeUnsizedType` somewhere.
+    /// impl<T: Trait + Sized> Trait for T { fn xyz() {} }
     ///
-    ///     pub fn foo<T: Trait + ?Sized>() {
-    ///         <T as Trait>::xyz();
-    ///     }
+    /// pub fn foo<T: Trait + ?Sized>() {
+    ///     <T as Trait>::xyz();
+    /// }
     /// ```
     ///
     /// When checking `foo`, we have to prove `T: Trait`. This basically
     /// translates into this:
     ///
     /// ```plain,ignore
-    ///     (T: Trait + Sized â†’_\impl T: Trait), T: Trait âŠ¢ T: Trait
+    /// (T: Trait + Sized â†’_\impl T: Trait), T: Trait âŠ¢ T: Trait
     /// ```
     ///
     /// When we try to prove it, we first go the first option, which
@@ -594,7 +594,7 @@ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
     // 1. If no applicable impl or parameter bound can be found.
     // 2. If the output type parameters in the obligation do not match
     //    those specified by the impl/bound. For example, if the obligation
-    //    is `Vec<Foo>:Iterable<Bar>`, but the impl specifies
+    //    is `Vec<Foo>: Iterable<Bar>`, but the impl specifies
     //    `impl<T> Iterable<T> for Vec<T>`, than an error would result.
 
     /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
@@ -723,10 +723,10 @@ fn evaluate_predicate_recursively<'o>(
         debug!("evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
             previous_stack.head(), obligation);
 
-        // Previous_stack stores a TraitObligatiom, while 'obligation' is
-        // a PredicateObligation. These are distinct types, so we can't
-        // use any Option combinator method that would force them to be
-        // the same
+        // `previous_stack` stores a `TraitObligatiom`, while `obligation` is
+        // a `PredicateObligation`. These are distinct types, so we can't
+        // use any `Option` combinator method that would force them to be
+        // the same.
         match previous_stack.head() {
             Some(h) => self.check_recursion_limit(&obligation, h.obligation)?,
             None => self.check_recursion_limit(&obligation, &obligation)?
@@ -740,7 +740,7 @@ fn evaluate_predicate_recursively<'o>(
             }
 
             ty::Predicate::Subtype(ref p) => {
-                // does this code ever run?
+                // Does this code ever run?
                 match self.infcx
                     .subtype_predicate(&obligation.cause, obligation.param_env, p)
                 {
@@ -768,8 +768,7 @@ fn evaluate_predicate_recursively<'o>(
             },
 
             ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => {
-                // we do not consider region relationships when
-                // evaluating trait matches
+                // We do not consider region relationships when evaluating trait matches.
                 Ok(EvaluatedToOkModuloRegions)
             }
 
@@ -953,7 +952,7 @@ fn check_evaluation_cycle(
         stack: &TraitObligationStack<'_, 'tcx>,
     ) -> Option<EvaluationResult> {
         if let Some(cycle_depth) = stack.iter()
-            .skip(1) // skip top-most frame
+            .skip(1) // Skip top-most frame.
             .find(|prev| stack.obligation.param_env == prev.obligation.param_env &&
                   stack.fresh_trait_ref == prev.fresh_trait_ref)
             .map(|stack| stack.depth)
@@ -1030,8 +1029,8 @@ fn evaluate_stack<'o>(
             .skip_binder()
             .input_types()
             .any(|ty| ty.is_fresh());
-        // this check was an imperfect workaround for a bug n the old
-        // intercrate mode, it should be removed when that goes away.
+        // This check was an imperfect workaround for a bug in the old
+        // intercrate mode; it should be removed when that goes away.
         if unbound_input_types && self.intercrate == Some(IntercrateMode::Issue43355) {
             debug!(
                 "evaluate_stack({:?}) --> unbound argument, intercrate -->  ambiguous",
@@ -1083,7 +1082,7 @@ fn evaluate_stack<'o>(
     }
 
     /// For defaulted traits, we use a co-inductive strategy to solve, so
-    /// that recursion is ok. This routine returns true if the top of the
+    /// that recursion is ok. This routine returns `true` if the top of the
     /// stack (`cycle[0]`):
     ///
     /// - is a defaulted trait,
@@ -1107,7 +1106,7 @@ fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
         result
     }
 
-    /// Further evaluate `candidate` to decide whether all type parameters match and whether nested
+    /// Further evaluates `candidate` to decide whether all type parameters match and whether nested
     /// obligations are met. Returns whether `candidate` remains viable after this further
     /// scrutiny.
     fn evaluate_candidate<'o>(
@@ -1199,26 +1198,26 @@ fn insert_evaluation_cache(
             .insert(trait_ref, WithDepNode::new(dep_node, result));
     }
 
-    // For various reasons, it's possible for a subobligation
-    // to have a *lower* recursion_depth than the obligation used to create it.
-    // Projection sub-obligations may be returned from the projection cache,
-    // which results in obligations with an 'old' recursion_depth.
-    // Additionally, methods like ty::wf::obligations and
-    // InferCtxt.subtype_predicate produce subobligations without
-    // taking in a 'parent' depth, causing the generated subobligations
-    // to have a recursion_depth of 0
-    //
-    // To ensure that obligation_depth never decreasees, we force all subobligations
-    // to have at least the depth of the original obligation.
+    /// For various reasons, it's possible for a subobligation
+    /// to have a *lower* recursion_depth than the obligation used to create it.
+    /// Projection sub-obligations may be returned from the projection cache,
+    /// which results in obligations with an 'old' `recursion_depth`.
+    /// Additionally, methods like `ty::wf::obligations` and
+    /// `InferCtxt.subtype_predicate` produce subobligations without
+    /// taking in a 'parent' depth, causing the generated subobligations
+    /// to have a `recursion_depth` of `0`.
+    ///
+    /// To ensure that obligation_depth never decreasees, we force all subobligations
+    /// to have at least the depth of the original obligation.
     fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(&self, it: I,
                                                                            min_depth: usize) {
         it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
     }
 
-    // Check that the recursion limit has not been exceeded.
-    //
-    // The weird return type of this function allows it to be used with the 'try' (?)
-    // operator within certain functions
+    /// Checks that the recursion limit has not been exceeded.
+    ///
+    /// The weird return type of this function allows it to be used with the `try` (`?`)
+    /// operator within certain functions.
     fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
         &self,
         obligation: &Obligation<'tcx, T>,
@@ -1256,7 +1255,6 @@ fn candidate_from_obligation<'o>(
         // not update) the cache.
         self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
 
-
         // Check the cache. Note that we freshen the trait-ref
         // separately rather than using `stack.fresh_trait_ref` --
         // this is because we want the unbound variables to be
@@ -1436,10 +1434,10 @@ fn candidate_from_obligation_no_cache<'o>(
         // candidate set is *individually* applicable. Now we have to
         // figure out if they contain mutual incompatibilities. This
         // frequently arises if we have an unconstrained input type --
-        // for example, we are looking for $0:Eq where $0 is some
+        // for example, we are looking for `$0: Eq` where `$0` is some
         // unconstrained type variable. In that case, we'll get a
-        // candidate which assumes $0 == int, one that assumes $0 ==
-        // usize, etc. This spells an ambiguity.
+        // candidate which assumes $0 == int, one that assumes `$0 ==
+        // usize`, etc. This spells an ambiguity.
 
         // If there is more than one candidate, first winnow them down
         // by considering extra conditions (nested obligations and so
@@ -1453,8 +1451,8 @@ fn candidate_from_obligation_no_cache<'o>(
         // and we were to see some code `foo.push_clone()` where `boo`
         // is a `Vec<Bar>` and `Bar` does not implement `Clone`.  If
         // we were to winnow, we'd wind up with zero candidates.
-        // Instead, we select the right impl now but report `Bar does
-        // not implement Clone`.
+        // Instead, we select the right impl now but report "`Bar` does
+        // not implement `Clone`".
         if candidates.len() == 1 {
             return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
         }
@@ -1586,7 +1584,7 @@ fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
         // avoid us having to fear that coherence results "pollute"
         // the master cache. Since coherence executes pretty quickly,
         // it's not worth going to more trouble to increase the
-        // hit-rate I don't think.
+        // hit-rate, I don't think.
         if self.intercrate.is_some() {
             return false;
         }
@@ -1617,13 +1615,13 @@ fn check_candidate_cache(
     }
 
     /// Determines whether can we safely cache the result
-    /// of selecting an obligation. This is almost always 'true',
-    /// except when dealing with certain ParamCandidates.
+    /// of selecting an obligation. This is almost always `true`,
+    /// except when dealing with certain `ParamCandidate`s.
     ///
-    /// Ordinarily, a ParamCandidate will contain no inference variables,
-    /// since it was usually produced directly from a DefId. However,
+    /// Ordinarily, a `ParamCandidate` will contain no inference variables,
+    /// since it was usually produced directly from a `DefId`. However,
     /// certain cases (currently only librustdoc's blanket impl finder),
-    /// a ParamEnv may be explicitly constructed with inference types.
+    /// a `ParamEnv` may be explicitly constructed with inference types.
     /// When this is the case, we do *not* want to cache the resulting selection
     /// candidate. This is due to the fact that it might not always be possible
     /// to equate the obligation's trait ref and the candidate's trait ref,
@@ -1631,7 +1629,7 @@ fn check_candidate_cache(
     ///
     /// Because of this, we always want to re-run the full selection
     /// process for our obligation the next time we see it, since
-    /// we might end up picking a different SelectionCandidate (or none at all)
+    /// we might end up picking a different `SelectionCandidate` (or none at all).
     fn can_cache_candidate(&self,
         result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>
      ) -> bool {
@@ -1662,15 +1660,14 @@ fn insert_candidate_cache(
 
         if self.can_use_global_caches(param_env) {
             if let Err(Overflow) = candidate {
-                // Don't cache overflow globally; we only produce this
-                // in certain modes.
+                // Don't cache overflow globally; we only produce this in certain modes.
             } else if !trait_ref.has_local_value() {
                 if !candidate.has_local_value() {
                     debug!(
                         "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
                         trait_ref, candidate,
                     );
-                    // This may overwrite the cache with the same value
+                    // This may overwrite the cache with the same value.
                     tcx.selection_cache
                         .hashmap
                         .borrow_mut()
@@ -1755,7 +1752,7 @@ fn assemble_candidates<'o>(
         } else {
             if lang_items.clone_trait() == Some(def_id) {
                 // Same builtin conditions as `Copy`, i.e., every type which has builtin support
-                // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone`
+                // for `Copy` also has builtin support for `Clone`, and tuples/arrays of `Clone`
                 // types have builtin support for `Clone`.
                 let clone_conditions = self.copy_clone_conditions(obligation);
                 self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?;
@@ -1786,7 +1783,7 @@ fn assemble_candidates_from_projected_tys(
     ) {
         debug!("assemble_candidates_for_projected_tys({:?})", obligation);
 
-        // before we go into the whole placeholder thing, just
+        // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind {
             ty::Projection(_) | ty::Opaque(..) => {}
@@ -1907,10 +1904,10 @@ fn match_projection(
             self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
     }
 
-    /// Given an obligation like `<SomeTrait for T>`, search the obligations that the caller
+    /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
     /// supplied to find out whether it is listed among them.
     ///
-    /// Never affects inference environment.
+    /// Never affects the inference environment.
     fn assemble_candidates_from_caller_bounds<'o>(
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
@@ -2052,7 +2049,7 @@ fn assemble_closure_candidates(
         Ok(())
     }
 
-    /// Implement one of the `Fn()` family for a fn pointer.
+    /// Implements one of the `Fn()` family for a fn pointer.
     fn assemble_fn_pointer_candidates(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -2067,14 +2064,14 @@ fn assemble_fn_pointer_candidates(
             return Ok(());
         }
 
-        // Okay to skip binder because what we are inspecting doesn't involve bound regions
+        // Okay to skip binder because what we are inspecting doesn't involve bound regions.
         let self_ty = *obligation.self_ty().skip_binder();
         match self_ty.kind {
             ty::Infer(ty::TyVar(_)) => {
                 debug!("assemble_fn_pointer_candidates: ambiguous self-type");
-                candidates.ambiguous = true; // could wind up being a fn() type
+                candidates.ambiguous = true; // Could wind up being a fn() type.
             }
-            // provide an impl, but only for suitable `fn` pointers
+            // Provide an impl, but only for suitable `fn` pointers.
             ty::FnDef(..) | ty::FnPtr(_) => {
                 if let ty::FnSig {
                     unsafety: hir::Unsafety::Normal,
@@ -2092,7 +2089,7 @@ fn assemble_fn_pointer_candidates(
         Ok(())
     }
 
-    /// Search for impls that might apply to `obligation`.
+    /// Searches for impls that might apply to `obligation`.
     fn assemble_candidates_from_impls(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -2160,7 +2157,7 @@ fn assemble_candidates_from_auto_impls(
                     // this path.
                 }
                 ty::Infer(ty::TyVar(_)) => {
-                    // the auto impl might apply, we don't know
+                    // The auto impl might apply; we don't know.
                     candidates.ambiguous = true;
                 }
                 ty::Generator(_, _, movability)
@@ -2188,7 +2185,7 @@ fn assemble_candidates_from_auto_impls(
         Ok(())
     }
 
-    /// Search for impls that might apply to `obligation`.
+    /// Searches for impls that might apply to `obligation`.
     fn assemble_candidates_from_object_ty(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -2226,7 +2223,7 @@ fn assemble_candidates_from_object_ty(
                             return;
                         }
                     } else {
-                        // Only auto-trait bounds exist.
+                        // Only auto trait bounds exist.
                         return;
                     }
                 }
@@ -2247,7 +2244,7 @@ fn assemble_candidates_from_object_ty(
             // we are looking for. Specifically, do not only check for the
             // correct trait, but also the correct type parameters.
             // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
-            // but `Foo` is declared as `trait Foo : Bar<u32>`.
+            // but `Foo` is declared as `trait Foo: Bar<u32>`.
             let upcast_trait_refs = util::supertraits(self.tcx(), poly_trait_ref)
                 .filter(|upcast_trait_ref| {
                     self.infcx.probe(|_| {
@@ -2267,7 +2264,7 @@ fn assemble_candidates_from_object_ty(
         })
     }
 
-    /// Search for unsizing that might apply to `obligation`.
+    /// Searches for unsizing that might apply to `obligation`.
     fn assemble_candidates_for_unsizing(
         &mut self,
         obligation: &TraitObligation<'tcx>,
@@ -2311,11 +2308,11 @@ fn assemble_candidates_for_unsizing(
             (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
                 // Upcasts permit two things:
                 //
-                // 1. Dropping builtin bounds, e.g., `Foo+Send` to `Foo`
-                // 2. Tightening the region bound, e.g., `Foo+'a` to `Foo+'b` if `'a : 'b`
+                // 1. Dropping auto traits, e.g., `Foo + Send` to `Foo`
+                // 2. Tightening the region bound, e.g., `Foo + 'a` to `Foo + 'b` if `'a: 'b`
                 //
                 // Note that neither of these changes requires any
-                // change at runtime.  Eventually this will be
+                // change at runtime. Eventually this will be
                 // generalized.
                 //
                 // We always upcast when we can because of reason
@@ -2326,11 +2323,11 @@ fn assemble_candidates_for_unsizing(
                     .all(|b| data_a.auto_traits().any(|a| a == b))
             }
 
-            // T -> Trait.
+            // `T` -> `Trait`
             (_, &ty::Dynamic(..)) => true,
 
-            // Ambiguous handling is below T -> Trait, because inference
-            // variables can still implement Unsize<Trait> and nested
+            // Ambiguous handling is below `T` -> `Trait`, because inference
+            // variables can still implement `Unsize<Trait>` and nested
             // obligations will have the final say (likely deferred).
             (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
                 debug!("assemble_candidates_for_unsizing: ambiguous");
@@ -2338,15 +2335,15 @@ fn assemble_candidates_for_unsizing(
                 false
             }
 
-            // [T; n] -> [T].
+            // `[T; n]` -> `[T]`
             (&ty::Array(..), &ty::Slice(_)) => true,
 
-            // Struct<T> -> Struct<U>.
+            // `Struct<T>` -> `Struct<U>`
             (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
                 def_id_a == def_id_b
             }
 
-            // (.., T) -> (.., U).
+            // `(.., T)` -> `(.., U)`
             (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => tys_a.len() == tys_b.len(),
 
             _ => false,
@@ -2404,7 +2401,7 @@ fn candidate_should_be_dropped_in_favor_of(
             |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
 
         match other.candidate {
-            // Prefer BuiltinCandidate { has_nested: false } to anything else.
+            // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
             // This is a fix for #53123 and prevents winnowing from accidentally extending the
             // lifetime of a variable.
             BuiltinCandidate { has_nested: false } => true,
@@ -2415,7 +2412,7 @@ fn candidate_should_be_dropped_in_favor_of(
                          when there are other valid candidates"
                     );
                 }
-                // Prefer BuiltinCandidate { has_nested: false } to anything else.
+                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
                 // This is a fix for #53123 and prevents winnowing from accidentally extending the
                 // lifetime of a variable.
                 BuiltinCandidate { has_nested: false } => false,
@@ -2446,7 +2443,7 @@ fn candidate_should_be_dropped_in_favor_of(
                          when there are other valid candidates"
                     );
                 }
-                // Prefer BuiltinCandidate { has_nested: false } to anything else.
+                // Prefer `BuiltinCandidate { has_nested: false }` to anything else.
                 // This is a fix for #53123 and prevents winnowing from accidentally extending the
                 // lifetime of a variable.
                 BuiltinCandidate { has_nested: false } => false,
@@ -2468,7 +2465,7 @@ fn candidate_should_be_dropped_in_favor_of(
             ImplCandidate(other_def) => {
                 // See if we can toss out `victim` based on specialization.
                 // This requires us to know *for sure* that the `other` impl applies
-                // i.e., EvaluatedToOk:
+                // i.e., `EvaluatedToOk`.
                 if other.evaluation.must_apply_modulo_regions() {
                     match victim.candidate {
                         ImplCandidate(victim_def) => {
@@ -2496,7 +2493,7 @@ fn candidate_should_be_dropped_in_favor_of(
                 match victim.candidate {
                     ParamCandidate(ref cand) => {
                         // Prefer these to a global where-clause bound
-                        // (see issue #50825)
+                        // (see issue #50825).
                         is_global(cand) && other.evaluation.must_apply_modulo_regions()
                     }
                     _ => false,
@@ -2754,7 +2751,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
                 types.skip_binder().to_vec()
             }
 
-            // for `PhantomData<T>`, we pass `T`
+            // For `PhantomData<T>`, we pass `T`.
             ty::Adt(def, substs) if def.is_phantom_data() => substs.types().collect(),
 
             ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect(),
@@ -2894,11 +2891,9 @@ fn confirm_candidate(
             }
 
             BuiltinObjectCandidate => {
-                // This indicates something like `(Trait+Send) :
-                // Send`. In this case, we know that this holds
-                // because that's what the object type is telling us,
-                // and there's really no additional obligations to
-                // prove and no types in particular to unify etc.
+                // This indicates something like `Trait + Send: Send`. In this case, we know that
+                // this holds because that's what the object type is telling us, and there's really
+                // no additional obligations to prove and no types in particular to unify, etc.
                 Ok(VtableParam(Vec::new()))
             }
 
@@ -3152,7 +3147,7 @@ fn confirm_object_candidate(
             // We want to find the first supertrait in the list of
             // supertraits that we can unify with, and do that
             // unification. We know that there is exactly one in the list
-            // where we can unify because otherwise select would have
+            // where we can unify, because otherwise select would have
             // reported an ambiguity. (When we do find a match, also
             // record it for later.)
             let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(
@@ -3166,7 +3161,7 @@ fn confirm_object_candidate(
                 },
             );
 
-            // Additionally, for each of the nonmatching predicates that
+            // Additionally, for each of the non-matching predicates that
             // we pass over, we sum up the set of number of vtable
             // entries, so that we can compute the offset for the selected
             // trait.
@@ -3354,7 +3349,7 @@ fn confirm_closure_candidate(
             trait_ref,
         )?);
 
-        // FIXME: chalk
+        // FIXME: Chalk
 
         if !self.tcx().sess.opts.debugging_opts.chalk {
             obligations.push(Obligation::new(
@@ -3421,7 +3416,7 @@ fn confirm_builtin_unsize_candidate(
     ) -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
 
-        // assemble_candidates_for_unsizing should ensure there are no late bound
+        // `assemble_candidates_for_unsizing` should ensure there are no late-bound
         // regions here. See the comment there for more details.
         let source = self.infcx
             .shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
@@ -3442,20 +3437,20 @@ fn confirm_builtin_unsize_candidate(
         match (&source.kind, &target.kind) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
             (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
-                // See assemble_candidates_for_unsizing for more info.
+                // See `assemble_candidates_for_unsizing` for more info.
                 let existential_predicates = data_a.map_bound(|data_a| {
                     let iter =
                         data_a.principal().map(|x| ty::ExistentialPredicate::Trait(x))
-                        .into_iter().chain(
-                            data_a
-                                .projection_bounds()
-                                .map(|x| ty::ExistentialPredicate::Projection(x)),
-                        )
-                        .chain(
-                            data_b
-                                .auto_traits()
-                                .map(ty::ExistentialPredicate::AutoTrait),
-                        );
+                            .into_iter().chain(
+                                data_a
+                                    .projection_bounds()
+                                    .map(|x| ty::ExistentialPredicate::Projection(x)),
+                            )
+                            .chain(
+                                data_b
+                                    .auto_traits()
+                                    .map(ty::ExistentialPredicate::AutoTrait),
+                            );
                     tcx.mk_existential_predicates(iter)
                 });
                 let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
@@ -3463,20 +3458,19 @@ fn confirm_builtin_unsize_candidate(
                 // Require that the traits involved in this upcast are **equal**;
                 // only the **lifetime bound** is changed.
                 //
-                // FIXME: This condition is arguably too strong -- it
-                // would suffice for the source trait to be a
-                // *subtype* of the target trait. In particular
-                // changing from something like `for<'a, 'b> Foo<'a,
-                // 'b>` to `for<'a> Foo<'a, 'a>` should be
+                // FIXME: This condition is arguably too strong -- it would
+                // suffice for the source trait to be a *subtype* of the target
+                // trait. In particular, changing from something like
+                // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
                 // permitted. And, indeed, in the in commit
                 // 904a0bde93f0348f69914ee90b1f8b6e4e0d7cbc, this
-                // condition was loosened. However, when the leak check was added
-                // back, using subtype here actually guies the coercion code in
-                // such a way that it accepts `old-lub-glb-object.rs`. This is probably
-                // a good thing, but I've modified this to `.eq` because I want
-                // to continue rejecting that test (as we have done for quite some time)
-                // before we are firmly comfortable with what our behavior
-                // should be there. -nikomatsakis
+                // condition was loosened. However, when the leak check was
+                // added back, using subtype here actually guides the coercion
+                // code in such a way that it accepts `old-lub-glb-object.rs`.
+                // This is probably a good thing, but I've modified this to `.eq`
+                // because I want to continue rejecting that test (as we have
+                // done for quite some time) before we are firmly comfortable
+                // with what our behavior should be there. -nikomatsakis
                 let InferOk { obligations, .. } = self.infcx
                     .at(&obligation.cause, obligation.param_env)
                     .eq(target, source_trait) // FIXME -- see below
@@ -3498,7 +3492,7 @@ fn confirm_builtin_unsize_candidate(
                 ));
             }
 
-            // T -> Trait.
+            // `T` -> `Trait`
             (_, &ty::Dynamic(ref data, r)) => {
                 let mut object_dids = data.auto_traits()
                     .chain(data.principal_def_id());
@@ -3522,32 +3516,34 @@ fn confirm_builtin_unsize_candidate(
                 };
 
                 // Create obligations:
-                //  - Casting T to Trait
+                //  - Casting `T` to `Trait`
                 //  - For all the various builtin bounds attached to the object cast. (In other
-                //  words, if the object type is Foo+Send, this would create an obligation for the
-                //  Send check.)
+                //  words, if the object type is `Foo + Send`, this would create an obligation for
+                //  the `Send` check.)
                 //  - Projection predicates
                 nested.extend(
                     data.iter()
-                        .map(|d| predicate_to_obligation(d.with_self_ty(tcx, source))),
+                        .map(|predicate|
+                            predicate_to_obligation(predicate.with_self_ty(tcx, source))
+                        ),
                 );
 
                 // We can only make objects from sized types.
-                let tr = ty::TraitRef {
-                    def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
-                    substs: tcx.mk_substs_trait(source, &[]),
-                };
+                let tr = ty::TraitRef::new(
+                    tcx.require_lang_item(lang_items::SizedTraitLangItem, None),
+                    tcx.mk_substs_trait(source, &[]),
+                );
                 nested.push(predicate_to_obligation(tr.to_predicate()));
 
-                // If the type is `Foo+'a`, ensures that the type
-                // being cast to `Foo+'a` outlives `'a`:
+                // If the type is `Foo + 'a`, ensure that the type
+                // being cast to `Foo + 'a` outlives `'a`:
                 let outlives = ty::OutlivesPredicate(source, r);
                 nested.push(predicate_to_obligation(
                     ty::Binder::dummy(outlives).to_predicate(),
                 ));
             }
 
-            // [T; n] -> [T].
+            // `[T; n]` -> `[T]`
             (&ty::Array(a, _), &ty::Slice(b)) => {
                 let InferOk { obligations, .. } = self.infcx
                     .at(&obligation.cause, obligation.param_env)
@@ -3556,10 +3552,10 @@ fn confirm_builtin_unsize_candidate(
                 nested.extend(obligations);
             }
 
-            // Struct<T> -> Struct<U>.
+            // `Struct<T>` -> `Struct<U>`
             (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
                 let fields = def.all_fields()
-                    .map(|f| tcx.type_of(f.did))
+                    .map(|field| tcx.type_of(field.did))
                     .collect::<Vec<_>>();
 
                 // The last field of the structure has to exist and contain type parameters.
@@ -3598,7 +3594,7 @@ fn confirm_builtin_unsize_candidate(
                     }
                 }
 
-                // Extract Field<T> and Field<U> from Struct<T> and Struct<U>.
+                // Extract `Field<T>` and `Field<U>` from `Struct<T>` and `Struct<U>`.
                 let inner_source = field.subst(tcx, substs_a);
                 let inner_target = field.subst(tcx, substs_b);
 
@@ -3618,7 +3614,7 @@ fn confirm_builtin_unsize_candidate(
                     .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
 
-                // Construct the nested Field<T>: Unsize<Field<U>> predicate.
+                // Construct the nested `Field<T>: Unsize<Field<U>>` predicate.
                 nested.push(tcx.predicate_for_trait_def(
                     obligation.param_env,
                     obligation.cause.clone(),
@@ -3629,7 +3625,7 @@ fn confirm_builtin_unsize_candidate(
                 ));
             }
 
-            // (.., T) -> (.., U).
+            // `(.., T)` -> `(.., U)`
             (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
                 assert_eq!(tys_a.len(), tys_b.len());
 
@@ -3652,7 +3648,7 @@ fn confirm_builtin_unsize_candidate(
                     .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
 
-                // Construct the nested T: Unsize<U> predicate.
+                // Construct the nested `T: Unsize<U>` predicate.
                 nested.push(tcx.predicate_for_trait_def(
                     obligation.param_env,
                     obligation.cause.clone(),
@@ -3969,7 +3965,7 @@ fn impl_or_trait_obligations(
         //
         // This code is hot enough that it's worth avoiding the allocation
         // required for the FxHashSet when possible. Special-casing lengths 0,
-        // 1 and 2 covers roughly 75--80% of the cases.
+        // 1 and 2 covers roughly 75-80% of the cases.
         if predicates.len() <= 1 {
             // No possibility of duplicates.
         } else if predicates.len() == 2 {
index d8b1effe09bf41de6cff5796c3e2856f2365991d..c15915a9d561fb572807605afba6511dc1c5bc5e 100644 (file)
@@ -80,7 +80,7 @@ fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
 ///////////////////////////////////////////////////////////////////////////
 
 /// "Elaboration" is the process of identifying all the predicates that
-/// are implied by a source predicate. Currently this basically means
+/// are implied by a source predicate. Currently, this basically means
 /// walking the "supertraits" and other similar assumptions. For example,
 /// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
 /// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
index 8e3ae0864aa0e043cf2a7fee5a17ab6c6941de29..be6d21564a0f1bd939feba5ac2ba062bab561532 100644 (file)
@@ -1,14 +1,15 @@
+use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt};
-use std::borrow::Cow;
-use std::fmt;
+
+use errors::{Applicability, DiagnosticBuilder};
 use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::errors::pluralize;
-use errors::{Applicability, DiagnosticBuilder};
 use syntax_pos::Span;
 
-use crate::hir;
+use std::borrow::Cow;
+use std::fmt;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
 pub struct ExpectedFound<T> {
index 7eee0a5e2b52cc5ddbe9ab9f1e8d3aa30045a216..777db38850fec87b4c4c1673ff5a41ec805d282e 100644 (file)
@@ -36,10 +36,10 @@ pub enum InstanceDef<'tcx> {
     ReifyShim(DefId),
 
     /// `<fn() as FnTrait>::call_*`
-    /// `DefId` is `FnTrait::call_*`
+    /// `DefId` is `FnTrait::call_*`.
     FnPtrShim(DefId, Ty<'tcx>),
 
-    /// `<Trait as Trait>::fn`
+    /// `<dyn Trait as Trait>::fn`
     Virtual(DefId, usize),
 
     /// `<[mut closure] as FnOnce>::call_once`
@@ -115,7 +115,7 @@ fn fn_sig_noadjust(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
     pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
         let mut fn_sig = self.fn_sig_noadjust(tcx);
         if let InstanceDef::VtableShim(..) = self.def {
-            // Modify fn(self, ...) to fn(self: *mut Self, ...)
+            // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
             fn_sig = fn_sig.map_bound(|mut fn_sig| {
                 let mut inputs_and_output = fn_sig.inputs_and_output.to_vec();
                 inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]);
index b9fc5f59b7bbc554f4813ad5ff39660d037e723c..b6050a5caf13e996e20f0fe248e205eea91473c1 100644 (file)
@@ -2103,8 +2103,8 @@ fn field(this: TyLayout<'tcx>, cx: &C, i: usize) -> C::TyLayout {
             ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
                 assert!(i < this.fields.count());
 
-                // Reuse the fat *T type as its own thin pointer data field.
-                // This provides information about e.g., DST struct pointees
+                // Reuse the fat `*T` type as its own thin pointer data field.
+                // This provides information about, e.g., DST struct pointees
                 // (which may have no non-DST form), and will work as long
                 // as the `Abi` or `FieldPlacement` is checked by users.
                 if i == 0 {
@@ -2327,158 +2327,6 @@ fn pointee_info_at(
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for Variants {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::Variants::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Single { index } => {
-                index.hash_stable(hcx, hasher);
-            }
-            Multiple {
-                ref discr,
-                ref discr_kind,
-                discr_index,
-                ref variants,
-            } => {
-                discr.hash_stable(hcx, hasher);
-                discr_kind.hash_stable(hcx, hasher);
-                discr_index.hash_stable(hcx, hasher);
-                variants.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::DiscriminantKind::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Tag => {}
-            Niche {
-                dataful_variant,
-                ref niche_variants,
-                niche_start,
-            } => {
-                dataful_variant.hash_stable(hcx, hasher);
-                niche_variants.start().hash_stable(hcx, hasher);
-                niche_variants.end().hash_stable(hcx, hasher);
-                niche_start.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for FieldPlacement {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::FieldPlacement::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Union(count) => {
-                count.hash_stable(hcx, hasher);
-            }
-            Array { count, stride } => {
-                count.hash_stable(hcx, hasher);
-                stride.hash_stable(hcx, hasher);
-            }
-            Arbitrary { ref offsets, ref memory_index } => {
-                offsets.hash_stable(hcx, hasher);
-                memory_index.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for VariantIdx {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.as_u32().hash_stable(hcx, hasher)
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for Abi {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        use crate::ty::layout::Abi::*;
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            Uninhabited => {}
-            Scalar(ref value) => {
-                value.hash_stable(hcx, hasher);
-            }
-            ScalarPair(ref a, ref b) => {
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher);
-            }
-            Vector { ref element, count } => {
-                element.hash_stable(hcx, hasher);
-                count.hash_stable(hcx, hasher);
-            }
-            Aggregate { sized } => {
-                sized.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
-impl<'a> HashStable<StableHashingContext<'a>> for Scalar {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let Scalar { value, ref valid_range } = *self;
-        value.hash_stable(hcx, hasher);
-        valid_range.start().hash_stable(hcx, hasher);
-        valid_range.end().hash_stable(hcx, hasher);
-    }
-}
-
-impl_stable_hash_for!(struct crate::ty::layout::Niche {
-    offset,
-    scalar
-});
-
-impl_stable_hash_for!(struct crate::ty::layout::LayoutDetails {
-    variants,
-    fields,
-    abi,
-    largest_niche,
-    size,
-    align
-});
-
-impl_stable_hash_for!(enum crate::ty::layout::Integer {
-    I8,
-    I16,
-    I32,
-    I64,
-    I128
-});
-
-impl_stable_hash_for!(enum crate::ty::layout::Primitive {
-    Int(integer, signed),
-    F32,
-    F64,
-    Pointer
-});
-
-impl_stable_hash_for!(struct crate::ty::layout::AbiAndPrefAlign {
-    abi,
-    pref
-});
-
-impl<'tcx> HashStable<StableHashingContext<'tcx>> for Align {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
-        self.bytes().hash_stable(hcx, hasher);
-    }
-}
-
-impl<'tcx> HashStable<StableHashingContext<'tcx>> for Size {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) {
-        self.bytes().hash_stable(hcx, hasher);
-    }
-}
-
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         use crate::ty::layout::LayoutError::*;
index d001916aca2db2f48c5fc550bdb735a4724cefdb..8ccfc467f4a0b08b8e1ea88b700cfa7acaaed031 100644 (file)
@@ -1923,17 +1923,17 @@ pub struct FieldDef {
 ///
 /// These are all interned (by `intern_adt_def`) into the `adt_defs` table.
 ///
-/// The initialism *"Adt"* stands for an [*algebraic data type (ADT)*][adt].
+/// The initialism *ADT* stands for an [*algebraic data type (ADT)*][adt].
 /// This is slightly wrong because `union`s are not ADTs.
 /// Moreover, Rust only allows recursive data types through indirection.
 ///
 /// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type
 pub struct AdtDef {
-    /// `DefId` of the struct, enum or union item.
+    /// The `DefId` of the struct, enum or union item.
     pub did: DefId,
     /// Variants of the ADT. If this is a struct or union, 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 of the ADT (e.g., is this a struct? is this non-exhaustive?).
     flags: AdtFlags,
     /// Repr options provided by the user.
     pub repr: ReprOptions,
@@ -1954,7 +1954,7 @@ fn cmp(&self, other: &AdtDef) -> Ordering {
 }
 
 impl PartialEq for AdtDef {
-    // AdtDef are always interned and this is part of TyS equality
+    // `AdtDef`s are always interned, and this is part of `TyS` equality.
     #[inline]
     fn eq(&self, other: &Self) -> bool { ptr::eq(self, other) }
 }
@@ -1976,7 +1976,6 @@ fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 
 impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx AdtDef {}
 
-
 impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         thread_local! {
index 369d0ee4d5b4491c4362e58e47e178457708ce52..efdf40fd6b8a46c1342d7dd60074079d753efaae 100644 (file)
@@ -281,7 +281,7 @@ fn relate<R: TypeRelation<'tcx>>(
         a: &ty::TraitRef<'tcx>,
         b: &ty::TraitRef<'tcx>,
     ) -> RelateResult<'tcx, ty::TraitRef<'tcx>> {
-        // Different traits cannot be related
+        // Different traits cannot be related.
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
@@ -297,7 +297,7 @@ fn relate<R: TypeRelation<'tcx>>(
         a: &ty::ExistentialTraitRef<'tcx>,
         b: &ty::ExistentialTraitRef<'tcx>,
     ) -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> {
-        // Different traits cannot be related
+        // Different traits cannot be related.
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
index 8fbd2e4e6b157d1e1e6d735561ecce0ea632c009..a0e66d340ae9d3af16d1a0b23fbad25306c05aa3 100644 (file)
@@ -4,12 +4,13 @@
 
 use crate::hir::def::Namespace;
 use crate::mir::ProjectionKind;
+use crate::mir::interpret;
 use crate::ty::{self, Lift, Ty, TyCtxt, InferConst};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::print::{FmtPrinter, Printer};
+
 use rustc_index::vec::{IndexVec, Idx};
 use smallvec::SmallVec;
-use crate::mir::interpret;
 
 use std::fmt;
 use std::rc::Rc;
index ab6a3bc83b1d2ce8c427762607d8e9057224d0fe..b72468a6ff98bfc9b73a7de171a8b7093fd3941f 100644 (file)
@@ -2,14 +2,14 @@
 
 #![allow(rustc::usage_of_ty_tykind)]
 
+use self::InferTy::*;
+use self::TyKind::*;
+
 use crate::hir;
 use crate::hir::def_id::DefId;
 use crate::infer::canonical::Canonical;
 use crate::mir::interpret::ConstValue;
 use crate::middle::region;
-use polonius_engine::Atom;
-use rustc_index::vec::Idx;
-use rustc_macros::HashStable;
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind};
 use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
 use crate::util::captures::Captures;
 use crate::mir::interpret::{Scalar, GlobalId};
 
+use polonius_engine::Atom;
+use rustc_index::vec::Idx;
+use rustc_macros::HashStable;
+use rustc_target::spec::abi;
 use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::cmp::Ordering;
 use std::marker::PhantomData;
 use std::ops::Range;
-use rustc_target::spec::abi;
 use syntax::ast::{self, Ident};
 use syntax::symbol::{kw, Symbol};
 
-use self::InferTy::*;
-use self::TyKind::*;
-
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
-#[derive(HashStable, TypeFoldable, Lift)]
+#[derive(
+    Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable,
+    HashStable, TypeFoldable, Lift,
+)]
 pub struct TypeAndMut<'tcx> {
     pub ty: Ty<'tcx>,
     pub mutbl: hir::Mutability,
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
-         RustcEncodable, RustcDecodable, Copy, HashStable)]
+#[derive(
+    Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy, HashStable,
+)]
 /// A "free" region `fr` can be interpreted as "some region
 /// at least as big as the scope `fr.scope`".
 pub struct FreeRegion {
@@ -45,8 +48,9 @@ pub struct FreeRegion {
     pub bound_region: BoundRegion,
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash,
-         RustcEncodable, RustcDecodable, Copy, HashStable)]
+#[derive(
+    Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy, HashStable,
+)]
 pub enum BoundRegion {
     /// An anonymous region parameter for a given fn (&T)
     BrAnon(u32),
@@ -471,18 +475,18 @@ pub fn sig(self, def_id: DefId, tcx: TyCtxt<'_>) -> GenSig<'tcx> {
 }
 
 impl<'tcx> GeneratorSubsts<'tcx> {
-    /// Generator have not been resumed yet
+    /// Generator has not been resumed yet.
     pub const UNRESUMED: usize = 0;
-    /// Generator has returned / is completed
+    /// Generator has returned or is completed.
     pub const RETURNED: usize = 1;
-    /// Generator has been poisoned
+    /// Generator has been poisoned.
     pub const POISONED: usize = 2;
 
     const UNRESUMED_NAME: &'static str = "Unresumed";
     const RETURNED_NAME: &'static str = "Returned";
     const POISONED_NAME: &'static str = "Panicked";
 
-    /// The valid variant indices of this Generator.
+    /// The valid variant indices of this generator.
     #[inline]
     pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
         // FIXME requires optimized MIR
@@ -490,7 +494,7 @@ pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantId
         (VariantIdx::new(0)..VariantIdx::new(num_variants))
     }
 
-    /// The discriminant for the given variant. Panics if the variant_index is
+    /// The discriminant for the given variant. Panics if the `variant_index` is
     /// out of range.
     #[inline]
     pub fn discriminant_for_variant(
@@ -505,7 +509,7 @@ pub fn discriminant_for_variant(
         Discr { val: variant_index.as_usize() as u128, ty: self.discr_ty(tcx) }
     }
 
-    /// The set of all discriminants for the Generator, enumerated with their
+    /// The set of all discriminants for the generator, enumerated with their
     /// variant indices.
     #[inline]
     pub fn discriminants(
@@ -670,12 +674,12 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
     pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
         match self[0] {
             ExistentialPredicate::Trait(tr) => Some(tr),
-            _ => None
+            _ => None,
         }
     }
 
     pub fn principal_def_id(&self) -> Option<DefId> {
-        self.principal().map(|d| d.def_id)
+        self.principal().map(|trait_ref| trait_ref.def_id)
     }
 
     #[inline]
@@ -684,7 +688,7 @@ impl Iterator<Item = ExistentialProjection<'tcx>> + 'a
     {
         self.iter().filter_map(|predicate| {
             match *predicate {
-                ExistentialPredicate::Projection(p) => Some(p),
+                ExistentialPredicate::Projection(projection) => Some(projection),
                 _ => None,
             }
         })
@@ -694,8 +698,8 @@ impl Iterator<Item = ExistentialProjection<'tcx>> + 'a
     pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
         self.iter().filter_map(|predicate| {
             match *predicate {
-                ExistentialPredicate::AutoTrait(d) => Some(d),
-                _ => None
+                ExistentialPredicate::AutoTrait(did) => Some(did),
+                _ => None,
             }
         })
     }
@@ -722,7 +726,8 @@ pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
     }
 
     pub fn iter<'a>(&'a self)
-        -> impl DoubleEndedIterator<Item = Binder<ExistentialPredicate<'tcx>>> + 'tcx {
+        -> impl DoubleEndedIterator<Item = Binder<ExistentialPredicate<'tcx>>> + 'tcx
+    {
         self.skip_binder().iter().cloned().map(Binder::bind)
     }
 }
@@ -751,7 +756,7 @@ pub struct TraitRef<'tcx> {
 
 impl<'tcx> TraitRef<'tcx> {
     pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> TraitRef<'tcx> {
-        TraitRef { def_id: def_id, substs: substs }
+        TraitRef { def_id, substs }
     }
 
     /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
@@ -822,7 +827,7 @@ pub struct ExistentialTraitRef<'tcx> {
 }
 
 impl<'tcx> ExistentialTraitRef<'tcx> {
-    pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'b {
+    pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'b {
         // Select only the "input types" from a trait-reference. For
         // now this is all the types that appear in the
         // trait-reference, but it should eventually exclude
@@ -1296,7 +1301,7 @@ pub enum RegionKind {
     /// A region variable. Should not exist after typeck.
     ReVar(RegionVid),
 
-    /// A placeholder region - basically the higher-ranked version of ReFree.
+    /// A placeholder region -- basically, the higher-ranked version of `ReFree`.
     /// Should not exist after typeck.
     RePlaceholder(ty::PlaceholderRegion),
 
@@ -1807,14 +1812,14 @@ pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match self.kind {
             Array(ty, _) | Slice(ty) => ty,
             Str => tcx.mk_mach_uint(ast::UintTy::U8),
-            _ => bug!("sequence_element_type called on non-sequence value: {}", self),
+            _ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
         }
     }
 
     pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match self.kind {
             Adt(def, substs) => def.non_enum_variant().fields[0].ty(tcx, substs),
-            _ => bug!("simd_type called on invalid type")
+            _ => bug!("`simd_type` called on invalid type"),
         }
     }
 
@@ -1823,7 +1828,7 @@ pub fn simd_size(&self, _tcx: TyCtxt<'tcx>) -> u64 {
         // allow `#[repr(simd)] struct Simd<T, const N: usize>([T; N]);`.
         match self.kind {
             Adt(def, _) => def.non_enum_variant().fields.len() as u64,
-            _ => bug!("simd_size called on invalid type")
+            _ => bug!("`simd_size` called on invalid type"),
         }
     }
 
@@ -1833,7 +1838,7 @@ pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
                 let variant = def.non_enum_variant();
                 (variant.fields.len() as u64, variant.fields[0].ty(tcx, substs))
             }
-            _ => bug!("simd_size_and_type called on invalid type")
+            _ => bug!("`simd_size_and_type` called on invalid type"),
         }
     }
 
@@ -1894,7 +1899,7 @@ pub fn is_box(&self) -> bool {
         }
     }
 
-    /// panics if called on any type other than `Box<T>`
+    /// Panics if called on any type other than `Box<T>`.
     pub fn boxed_ty(&self) -> Ty<'tcx> {
         match self.kind {
             Adt(def, substs) if def.is_box() => substs.type_at(0),
@@ -2114,7 +2119,8 @@ pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
     }
 
     /// If the type contains variants, returns the valid range of variant indices.
-    /// FIXME This requires the optimized MIR in the case of generators.
+    //
+    // FIXME: This requires the optimized MIR in the case of generators.
     #[inline]
     pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
         match self.kind {
@@ -2127,7 +2133,8 @@ pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
 
     /// If the type contains variants, returns the variant for `variant_index`.
     /// Panics if `variant_index` is out of range.
-    /// FIXME This requires the optimized MIR in the case of generators.
+    //
+    // FIXME: This requires the optimized MIR in the case of generators.
     #[inline]
     pub fn discriminant_for_variant(
         &self,
@@ -2142,7 +2149,7 @@ pub fn discriminant_for_variant(
         }
     }
 
-    /// Push onto `out` the regions directly referenced from this type (but not
+    /// Pushes onto `out` the regions directly referenced from this type (but not
     /// types reachable from this type via `walk_tys`). This ignores late-bound
     /// regions binders.
     pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) {
@@ -2255,7 +2262,7 @@ pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
             ty::Infer(ty::FreshTy(_)) |
             ty::Infer(ty::FreshIntTy(_)) |
             ty::Infer(ty::FreshFloatTy(_)) =>
-                bug!("is_trivially_sized applied to unexpected type: {:?}", self),
+                bug!("`is_trivially_sized` applied to unexpected type: {:?}", self),
         }
     }
 }
index 76afba220ce44a9eb2ae358ce235e4f29f5d627b..0c9fbfe6641897da94c4a5640657cdc43185d8bc 100644 (file)
@@ -333,14 +333,14 @@ pub fn struct_tail_with_normalize(self,
         ty
     }
 
-    /// Same as applying struct_tail on `source` and `target`, but only
+    /// Same as applying `struct_tail` on `source` and `target`, but only
     /// keeps going as long as the two types are instances of the same
     /// structure definitions.
     /// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
     /// whereas struct_tail produces `T`, and `Trait`, respectively.
     ///
     /// Should only be called if the types have no inference variables and do
-    /// not need their lifetimes preserved (e.g. as part of codegen); otherwise
+    /// not need their lifetimes preserved (e.g., as part of codegen); otherwise,
     /// normalization attempt may cause compiler bugs.
     pub fn struct_lockstep_tails_erasing_lifetimes(self,
                                                    source: Ty<'tcx>,
@@ -353,7 +353,7 @@ pub fn struct_lockstep_tails_erasing_lifetimes(self,
             source, target, |ty| tcx.normalize_erasing_regions(param_env, ty))
     }
 
-    /// Same as applying struct_tail on `source` and `target`, but only
+    /// Same as applying `struct_tail` on `source` and `target`, but only
     /// keeps going as long as the two types are instances of the same
     /// structure definitions.
     /// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
index 287d5705de8c7e3bd7089dbfee1ce799ffd329fe..804a7af41f39a8f814959f482cf5eedf9a168a3d 100644 (file)
@@ -1,16 +1,15 @@
-use crate::llvm::{self, AttributePlace};
 use crate::builder::Builder;
 use crate::context::CodegenCx;
+use crate::llvm::{self, AttributePlace};
 use crate::type_::Type;
+use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
-use crate::type_of::{LayoutLlvmExt};
+
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::mir::operand::OperandValue;
-use rustc_target::abi::call::ArgAbi;
-
 use rustc_codegen_ssa::traits::*;
-
+use rustc_target::abi::call::ArgAbi;
 use rustc_target::abi::{HasDataLayout, LayoutOf};
 use rustc::ty::{Ty};
 use rustc::ty::layout::{self};
@@ -202,7 +201,7 @@ fn store(
         if self.is_sized_indirect() {
             OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst)
         } else if self.is_unsized_indirect() {
-            bug!("unsized ArgAbi must be handled through store_fn_arg");
+            bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
         } else if let PassMode::Cast(cast) = self.mode {
             // FIXME(eddyb): Figure out when the simpler Store is safe, clang
             // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
@@ -232,10 +231,10 @@ fn store(
                 let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align);
                 bx.lifetime_start(llscratch, scratch_size);
 
-                // ...where we first store the value...
+                // ... where we first store the value...
                 bx.store(val, llscratch, scratch_align);
 
-                // ...and then memcpy it to the intended destination.
+                // ... and then memcpy it to the intended destination.
                 bx.memcpy(
                     dst.llval,
                     self.layout.align.abi,
index daccfc9b242f924da3e63444abd4c2c1b029334a..b3a8fa2988785da9ed8f028f46fcab63ebda7c0e 100644 (file)
 //! In order for link-time optimization to work properly, LLVM needs a unique
 //! type identifier that tells it across compilation units which types are the
 //! same as others. This type identifier is created by
-//! TypeMap::get_unique_type_id_of_type() using the following algorithm:
+//! `TypeMap::get_unique_type_id_of_type()` using the following algorithm:
 //!
 //! (1) Primitive types have their name as ID
 //! (2) Structs, enums and traits have a multipart identifier
index f1bf45111315213892301bddb3665cd0ccfcb2d5..2e16ae4c73f88283ee492ecfbe8ce65e40d9048b 100644 (file)
@@ -7,16 +7,16 @@
 use super::namespace::mangled_name_of_instance;
 use super::type_names::compute_debuginfo_type_name;
 use super::CrateDebugContext;
-use crate::abi;
-use crate::value::Value;
-use rustc_codegen_ssa::traits::*;
 
+use crate::abi;
+use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::{DIArray, DIType, DIFile, DIScope, DIDescriptor,
                       DICompositeType, DILexicalBlock, DIFlags, DebugEmissionKind};
 use crate::llvm_util;
+use crate::value::Value;
 
-use crate::common::CodegenCx;
+use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def::CtorKind;
@@ -36,6 +36,9 @@
 use rustc_fs_util::path_to_c_string;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_target::abi::HasDataLayout;
+use syntax::ast;
+use syntax::symbol::{Interner, Symbol};
+use syntax_pos::{self, Span, FileName};
 
 use libc::{c_uint, c_longlong};
 use std::collections::hash_map::Entry;
@@ -45,9 +48,6 @@
 use std::iter;
 use std::ptr;
 use std::path::{Path, PathBuf};
-use syntax::ast;
-use syntax::symbol::{Interner, Symbol};
-use syntax_pos::{self, Span, FileName};
 
 impl PartialEq for llvm::Metadata {
     fn eq(&self, other: &Self) -> bool {
@@ -70,7 +70,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 // From DWARF 5.
-// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
+// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1.
 const DW_LANG_RUST: c_uint = 0x1c;
 #[allow(non_upper_case_globals)]
 const DW_ATE_boolean: c_uint = 0x02;
@@ -91,70 +91,70 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
 pub struct UniqueTypeId(ast::Name);
 
-// The TypeMap is where the CrateDebugContext holds the type metadata nodes
-// created so far. The metadata nodes are indexed by UniqueTypeId, and, for
-// faster lookup, also by Ty. The TypeMap is responsible for creating
-// UniqueTypeIds.
+/// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
+/// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
+/// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating
+/// `UniqueTypeId`s.
 #[derive(Default)]
 pub struct TypeMap<'ll, 'tcx> {
-    // The UniqueTypeIds created so far
+    /// The `UniqueTypeId`s created so far.
     unique_id_interner: Interner,
-    // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
+    /// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
     unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
-    // A map from types to debuginfo metadata. This is a N:1 mapping.
+    /// A map from types to debuginfo metadata. This is an N:1 mapping.
     type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
-    // A map from types to UniqueTypeId. This is a N:1 mapping.
+    /// A map from types to `UniqueTypeId`. This is an N:1 mapping.
     type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>
 }
 
 impl TypeMap<'ll, 'tcx> {
-    // Adds a Ty to metadata mapping to the TypeMap. The method will fail if
-    // the mapping already exists.
+    /// Adds a Ty to metadata mapping to the TypeMap. The method will fail if
+    /// the mapping already exists.
     fn register_type_with_metadata(
         &mut self,
         type_: Ty<'tcx>,
         metadata: &'ll DIType,
     ) {
         if self.type_to_metadata.insert(type_, metadata).is_some() {
-            bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_);
+            bug!("type metadata for `Ty` '{}' is already in the `TypeMap`!", type_);
         }
     }
 
-    // Removes a Ty to metadata mapping
-    // This is useful when computing the metadata for a potentially
-    // recursive type (e.g. a function ptr of the form:
-    //
-    // fn foo() -> impl Copy { foo }
-    //
-    // This kind of type cannot be properly represented
-    // via LLVM debuginfo. As a workaround,
-    // we register a temporary Ty to metadata mapping
-    // for the function before we compute its actual metadata.
-    // If the metadata computation ends up recursing back to the
-    // original function, it will use the temporary mapping
-    // for the inner self-reference, preventing us from
-    // recursing forever.
-    //
-    // This function is used to remove the temporary metadata
-    // mapping after we've computed the actual metadata
+    /// Removes a `Ty`-to-metadata mapping.
+    /// This is useful when computing the metadata for a potentially
+    /// recursive type (e.g., a function pointer of the form:
+    ///
+    ///     fn foo() -> impl Copy { foo }
+    ///
+    /// This kind of type cannot be properly represented
+    /// via LLVM debuginfo. As a workaround,
+    /// we register a temporary Ty to metadata mapping
+    /// for the function before we compute its actual metadata.
+    /// If the metadata computation ends up recursing back to the
+    /// original function, it will use the temporary mapping
+    /// for the inner self-reference, preventing us from
+    /// recursing forever.
+    ///
+    /// This function is used to remove the temporary metadata
+    /// mapping after we've computed the actual metadata.
     fn remove_type(
         &mut self,
         type_: Ty<'tcx>,
     ) {
         if self.type_to_metadata.remove(type_).is_none() {
-            bug!("Type metadata Ty '{}' is not in the TypeMap!", type_);
+            bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", type_);
         }
     }
 
-    // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
-    // fail if the mapping already exists.
+    /// Adds a `UniqueTypeId` to metadata mapping to the `TypeMap`. The method will
+    /// fail if the mapping already exists.
     fn register_unique_id_with_metadata(
         &mut self,
         unique_type_id: UniqueTypeId,
         metadata: &'ll DIType,
     ) {
         if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
-            bug!("Type metadata for unique id '{}' is already in the TypeMap!",
+            bug!("type metadata for unique ID '{}' is already in the `TypeMap`!",
                  self.get_unique_type_id_as_string(unique_type_id));
         }
     }
@@ -167,23 +167,23 @@ fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'
         self.unique_id_to_metadata.get(&unique_type_id).cloned()
     }
 
-    // Get the string representation of a UniqueTypeId. This method will fail if
-    // the id is unknown.
+    /// Gets the string representation of a `UniqueTypeId`. This method will fail if
+    /// the ID is unknown.
     fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
         let UniqueTypeId(interner_key) = unique_type_id;
         self.unique_id_interner.get(interner_key)
     }
 
-    // Get the UniqueTypeId for the given type. If the UniqueTypeId for the given
-    // type has been requested before, this is just a table lookup. Otherwise an
-    // ID will be generated and stored for later lookup.
+    /// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given
+    /// type has been requested before, this is just a table lookup. Otherwise, an
+    /// ID will be generated and stored for later lookup.
     fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>,
                                       type_: Ty<'tcx>) -> UniqueTypeId {
-        // Let's see if we already have something in the cache
+        // Let's see if we already have something in the cache.
         if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() {
             return unique_type_id;
         }
-        // if not, generate one
+        // If not, generate one.
 
         // The hasher we are using to generate the UniqueTypeId. We want
         // something that provides more than the 64 bits of the DefaultHasher.
@@ -203,9 +203,9 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>,
         return UniqueTypeId(key);
     }
 
-    // Get the UniqueTypeId for an enum variant. Enum variants are not really
-    // types of their own, so they need special handling. We still need a
-    // UniqueTypeId for them, since to debuginfo they *are* real types.
+    /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
+    /// types of their own, so they need special handling. We still need a
+    /// `UniqueTypeId` for them, since to debuginfo they *are* real types.
     fn get_unique_type_id_of_enum_variant<'a>(&mut self,
                                               cx: &CodegenCx<'a, 'tcx>,
                                               enum_type: Ty<'tcx>,
@@ -219,9 +219,9 @@ fn get_unique_type_id_of_enum_variant<'a>(&mut self,
         UniqueTypeId(interner_key)
     }
 
-    // Get the unique type id string for an enum variant part.
-    // Variant parts are not types and shouldn't really have their own id,
-    // but it makes set_members_of_composite_type() simpler.
+    /// Gets the unique type ID string for an enum variant part.
+    /// Variant parts are not types and shouldn't really have their own ID,
+    /// but it makes `set_members_of_composite_type()` simpler.
     fn get_unique_type_id_str_of_enum_variant_part(&mut self, enum_type_id: UniqueTypeId) -> &str {
         let variant_part_type_id = format!("{}_variant_part",
                                            self.get_unique_type_id_as_string(enum_type_id));
@@ -230,11 +230,11 @@ fn get_unique_type_id_str_of_enum_variant_part(&mut self, enum_type_id: UniqueTy
     }
 }
 
-// A description of some recursive type. It can either be already finished (as
-// with FinalMetadata) or it is not yet finished, but contains all information
-// needed to generate the missing parts of the description. See the
-// documentation section on Recursive Types at the top of this file for more
-// information.
+/// A description of some recursive type. It can either be already finished (as
+/// with `FinalMetadata`) or it is not yet finished, but contains all information
+/// needed to generate the missing parts of the description. See the
+/// documentation section on Recursive Types at the top of this file for more
+/// information.
 enum RecursiveTypeDescription<'ll, 'tcx> {
     UnfinishedMetadata {
         unfinished_type: Ty<'tcx>,
@@ -255,7 +255,7 @@ fn create_and_register_recursive_type_forward_declaration(
     member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
 ) -> RecursiveTypeDescription<'ll, 'tcx> {
 
-    // Insert the stub into the TypeMap in order to allow for recursive references
+    // Insert the stub into the `TypeMap` in order to allow for recursive references.
     let mut type_map = debug_context(cx).type_map.borrow_mut();
     type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
     type_map.register_type_with_metadata(unfinished_type, metadata_stub);
@@ -270,9 +270,9 @@ fn create_and_register_recursive_type_forward_declaration(
 }
 
 impl RecursiveTypeDescription<'ll, 'tcx> {
-    // Finishes up the description of the type in question (mostly by providing
-    // descriptions of the fields of the given type) and returns the final type
-    // metadata.
+    /// Finishes up the description of the type in question (mostly by providing
+    /// descriptions of the fields of the given type) and returns the final type
+    /// metadata.
     fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
         match *self {
             FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
@@ -287,7 +287,7 @@ fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
                 // the TypeMap so that recursive references are possible. This
                 // will always be the case if the RecursiveTypeDescription has
                 // been properly created through the
-                // create_and_register_recursive_type_forward_declaration()
+                // `create_and_register_recursive_type_forward_declaration()`
                 // function.
                 {
                     let type_map = debug_context(cx).type_map.borrow();
@@ -314,8 +314,8 @@ fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
     }
 }
 
-// Returns from the enclosing function if the type metadata with the given
-// unique id can be found in the type map
+/// Returns from the enclosing function if the type metadata with the given
+/// unique ID can be found in the type map.
 macro_rules! return_if_metadata_created_in_meantime {
     ($cx: expr, $unique_type_id: expr) => (
         if let Some(metadata) = debug_context($cx).type_map
@@ -527,19 +527,19 @@ pub fn type_metadata(
     t: Ty<'tcx>,
     usage_site_span: Span,
 ) -> &'ll DIType {
-    // Get the unique type id of this type.
+    // Get the unique type ID of this type.
     let unique_type_id = {
         let mut type_map = debug_context(cx).type_map.borrow_mut();
-        // First, try to find the type in TypeMap. If we have seen it before, we
+        // First, try to find the type in `TypeMap`. If we have seen it before, we
         // can exit early here.
         match type_map.find_metadata_for_type(t) {
             Some(metadata) => {
                 return metadata;
             },
             None => {
-                // The Ty is not in the TypeMap but maybe we have already seen
+                // The Ty is not in the `TypeMap` but maybe we have already seen
                 // an equivalent type (e.g., only differing in region arguments).
-                // In order to find out, generate the unique type id and look
+                // In order to find out, generate the unique type ID and look
                 // that up.
                 let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
                 match type_map.find_metadata_for_unique_id(unique_type_id) {
@@ -647,15 +647,15 @@ pub fn type_metadata(
             //
             // fn foo() -> impl Copy { foo }
             //
-            // See TypeMap::remove_type for more detals
-            // about the workaround
+            // See `TypeMap::remove_type` for more detals
+            // about the workaround.
 
             let temp_type = {
                 unsafe {
                     // The choice of type here is pretty arbitrary -
                     // anything reading the debuginfo for a recursive
                     // type is going to see *somthing* weird - the only
-                    // question is what exactly it will see
+                    // question is what exactly it will see.
                     let (size, align) = cx.size_and_align_of(t);
                     llvm::LLVMRustDIBuilderCreateBasicType(
                         DIB(cx),
@@ -677,7 +677,7 @@ pub fn type_metadata(
             type_map.borrow_mut().remove_type(t);
 
 
-            // This is actually a function pointer, so wrap it in pointer DI
+            // This is actually a function pointer, so wrap it in pointer DI.
             MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
 
         }
@@ -743,14 +743,14 @@ pub fn type_metadata(
         let mut type_map = debug_context(cx).type_map.borrow_mut();
 
         if already_stored_in_typemap {
-            // Also make sure that we already have a TypeMap entry for the unique type id.
+            // Also make sure that we already have a `TypeMap` entry for the unique type ID.
             let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
                 Some(metadata) => metadata,
                 None => {
                     span_bug!(usage_site_span,
-                              "Expected type metadata for unique \
-                               type id '{}' to already be in \
-                               the debuginfo::TypeMap but it \
+                              "expected type metadata for unique \
+                               type ID '{}' to already be in \
+                               the `debuginfo::TypeMap` but it \
                                was not. (Ty = {})",
                               type_map.get_unique_type_id_as_string(unique_type_id),
                               t);
@@ -761,9 +761,9 @@ pub fn type_metadata(
                 Some(metadata) => {
                     if metadata != metadata_for_uid {
                         span_bug!(usage_site_span,
-                                  "Mismatch between Ty and \
-                                   UniqueTypeId maps in \
-                                   debuginfo::TypeMap. \
+                                  "mismatch between `Ty` and \
+                                   `UniqueTypeId` maps in \
+                                   `debuginfo::TypeMap`. \
                                    UniqueTypeId={}, Ty={}",
                                   type_map.get_unique_type_id_as_string(unique_type_id),
                                   t);
@@ -851,7 +851,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
         ty::Float(float_ty) => {
             (float_ty.name_str(), DW_ATE_float)
         },
-        _ => bug!("debuginfo::basic_type_metadata - t is invalid type")
+        _ => bug!("debuginfo::basic_type_metadata - `t` is invalid type")
     };
 
     let (size, align) = cx.size_and_align_of(t);
@@ -908,7 +908,7 @@ pub fn compile_unit_metadata(
     };
 
     // The OSX linker has an idiosyncrasy where it will ignore some debuginfo
-    // if multiple object files with the same DW_AT_name are linked together.
+    // if multiple object files with the same `DW_AT_name` are linked together.
     // As a workaround we generate unique names for each object file. Those do
     // not correspond to an actual source file but that should be harmless.
     if tcx.sess.target.target.options.is_like_osx {
@@ -935,11 +935,9 @@ pub fn compile_unit_metadata(
     //
     //    This should actually be
     //
-    //    ```
-    //      let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
-    //    ```
+    //        let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
     //
-    //    that is, we should set LLVM's emission kind to `LineTablesOnly` if
+    //    That is, we should set LLVM's emission kind to `LineTablesOnly` if
     //    we are compiling with "limited" debuginfo. However, some of the
     //    existing tools relied on slightly more debuginfo being generated than
     //    would be the case with `LineTablesOnly`, and we did not want to break
@@ -1029,8 +1027,8 @@ fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
     }
 }
 
-// Description of a type member, which can either be a regular field (as in
-// structs or tuples) or an enum variant.
+/// Description of a type member, which can either be a regular field (as in
+/// structs or tuples) or an enum variant.
 #[derive(Debug)]
 struct MemberDescription<'ll> {
     name: String,
@@ -1067,10 +1065,10 @@ fn into_metadata(self,
     }
 }
 
-// A factory for MemberDescriptions. It produces a list of member descriptions
-// for some record-like type. MemberDescriptionFactories are used to defer the
-// creation of type member descriptions in order to break cycles arising from
-// recursive type definitions.
+/// A factory for `MemberDescription`s. It produces a list of member descriptions
+/// for some record-like type. `MemberDescriptionFactory`s are used to defer the
+/// creation of type member descriptions in order to break cycles arising from
+/// recursive type definitions.
 enum MemberDescriptionFactory<'ll, 'tcx> {
     StructMDF(StructMemberDescriptionFactory<'tcx>),
     TupleMDF(TupleMemberDescriptionFactory<'tcx>),
@@ -1106,7 +1104,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
 // Structs
 //=-----------------------------------------------------------------------------
 
-// Creates MemberDescriptions for the fields of a struct
+/// Creates `MemberDescription`s for the fields of a struct.
 struct StructMemberDescriptionFactory<'tcx> {
     ty: Ty<'tcx>,
     variant: &'tcx ty::VariantDef,
@@ -1177,7 +1175,7 @@ fn prepare_struct_metadata(
 // Tuples
 //=-----------------------------------------------------------------------------
 
-// Creates MemberDescriptions for the fields of a tuple
+/// Creates `MemberDescription`s for the fields of a tuple.
 struct TupleMemberDescriptionFactory<'tcx> {
     ty: Ty<'tcx>,
     component_types: Vec<Ty<'tcx>>,
@@ -1300,14 +1298,14 @@ fn prepare_union_metadata(
 // Enums
 //=-----------------------------------------------------------------------------
 
-// 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. 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.
+/// 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. 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.
@@ -1318,11 +1316,11 @@ fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
         || llvm_util::get_major_version() < 8;
 }
 
-// Describes the members of an enum value: An enum is described as a union of
-// structs in DWARF. This MemberDescriptionFactory provides the description for
-// the members of this union; so for every variant of the given enum, this
-// factory will produce one MemberDescription (all with no name and a fixed
-// offset of zero bytes).
+/// Describes the members of an enum value; an enum is described as a union of
+/// structs in DWARF. This `MemberDescriptionFactory` provides the description for
+/// the members of this union; so for every variant of the given enum, this
+/// factory will produce one `MemberDescription` (all with no name and a fixed
+/// offset of zero bytes).
 struct EnumMemberDescriptionFactory<'ll, 'tcx> {
     enum_type: Ty<'tcx>,
     layout: TyLayout<'tcx>,
@@ -1456,7 +1454,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
             } => {
                 if fallback {
                     let variant = self.layout.for_variant(cx, dataful_variant);
-                    // Create a description of the non-null variant
+                    // Create a description of the non-null variant.
                     let (variant_type_metadata, member_description_factory) =
                         describe_enum_variant(cx,
                                               variant,
@@ -1566,9 +1564,9 @@ fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     }
 }
 
-// Creates MemberDescriptions for the fields of a single enum variant.
+// Creates `MemberDescription`s for the fields of a single enum variant.
 struct VariantMemberDescriptionFactory<'ll, 'tcx> {
-    // Cloned from the layout::Struct describing the variant.
+    /// Cloned from the `layout::Struct` describing the variant.
     offsets: Vec<layout::Size>,
     args: Vec<(String, Ty<'tcx>)>,
     discriminant_type_metadata: Option<&'ll DIType>,
@@ -1652,10 +1650,10 @@ fn field_name(&self, i: usize) -> String {
     }
 }
 
-// Returns a tuple of (1) type_metadata_stub of the variant, (2) a
-// MemberDescriptionFactory for producing the descriptions of the
-// fields of the variant. This is a rudimentary version of a full
-// RecursiveTypeDescription.
+/// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a
+/// `MemberDescriptionFactory` for producing the descriptions of the
+/// fields of the variant. This is a rudimentary version of a full
+/// `RecursiveTypeDescription`.
 fn describe_enum_variant(
     cx: &CodegenCx<'ll, 'tcx>,
     layout: layout::TyLayout<'tcx>,
@@ -2088,8 +2086,7 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>,
     }
 }
 
-// Compute the type parameters for a type, if any, for the given
-// metadata.
+/// Computes the type parameters for a type, if any, for the given metadata.
 fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> {
     if let ty::Adt(def, substs) = ty.kind {
         if !substs.types().next().is_none() {
@@ -2134,9 +2131,9 @@ fn get_parameter_names(cx: &CodegenCx<'_, '_>,
     }
 }
 
-// A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do
-// any caching, does not add any fields to the struct. This can be done later
-// with set_members_of_composite_type().
+/// A convenience wrapper around `LLVMRustDIBuilderCreateStructType()`. Does not do
+/// any caching, does not add any fields to the struct. This can be done later
+/// with `set_members_of_composite_type()`.
 fn create_struct_stub(
     cx: &CodegenCx<'ll, 'tcx>,
     struct_type: Ty<'tcx>,
@@ -2151,9 +2148,9 @@ fn create_struct_stub(
         debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
     );
     let metadata_stub = unsafe {
-        // LLVMRustDIBuilderCreateStructType() wants an empty array. A null
+        // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
-        // later on in llvm/lib/IR/Value.cpp.
+        // later on in `llvm/lib/IR/Value.cpp`.
         let empty_array = create_DIArray(DIB(cx), &[]);
 
         llvm::LLVMRustDIBuilderCreateStructType(
@@ -2189,9 +2186,9 @@ fn create_union_stub(
         debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
     );
     let metadata_stub = unsafe {
-        // LLVMRustDIBuilderCreateUnionType() wants an empty array. A null
+        // `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
-        // later on in llvm/lib/IR/Value.cpp.
+        // later on in `llvm/lib/IR/Value.cpp`.
         let empty_array = create_DIArray(DIB(cx), &[]);
 
         llvm::LLVMRustDIBuilderCreateUnionType(
@@ -2231,8 +2228,8 @@ pub fn create_global_var_metadata(
     }
 
     let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
-    // We may want to remove the namespace scope if we're in an extern block, see:
-    // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952
+    // We may want to remove the namespace scope if we're in an extern block (see
+    // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
     let var_scope = get_namespace_for_item(cx, def_id);
     let span = tcx.def_span(def_id);
 
@@ -2287,14 +2284,14 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
     let type_metadata = type_metadata(cx, ty, syntax_pos::DUMMY_SP);
 
     unsafe {
-        // LLVMRustDIBuilderCreateStructType() wants an empty array. A null
+        // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
-        // later on in llvm/lib/IR/Value.cpp.
+        // later on in `llvm/lib/IR/Value.cpp`.
         let empty_array = create_DIArray(DIB(cx), &[]);
 
         let name = const_cstr!("vtable");
 
-        // Create a new one each time.  We don't want metadata caching
+        // Create a new one each time. We don't want metadata caching
         // here, because each vtable will refer to a unique containing
         // type.
         let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
@@ -2327,7 +2324,7 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &
     }
 }
 
-// Creates an "extension" of an existing DIScope into another file.
+/// Creates an "extension" of an existing `DIScope` into another file.
 pub fn extend_scope_to_file(
     cx: &CodegenCx<'ll, '_>,
     scope_metadata: &'ll DIScope,
index 4277ce1d1f7546bd1f349abb3c705c400b865b8a..12ec4e107487405bcae9deeb2732cc9ceba4882b 100644 (file)
@@ -152,7 +152,7 @@ fn codegen_intrinsic_call(
                         match scalar.value {
                             Primitive::Int(..) => {
                                 if self.cx().size_of(ret_ty).bytes() < 4 {
-                                    // va_arg should not be called on a integer type
+                                    // `va_arg` should not be called on a integer type
                                     // less than 4 bytes in length. If it is, promote
                                     // the integer to a `i32` and truncate the result
                                     // back to the smaller type.
index faa7b588e56e30d0b42b04602a3d75d262ecac98..22693beb855d2143fee2f6a4262756bd3310bc7e 100644 (file)
@@ -1,21 +1,32 @@
 //! Codegen the completed AST to the LLVM IR.
 //!
-//! Some functions here, such as codegen_block and codegen_expr, return a value --
-//! the result of the codegen to LLVM -- while others, such as codegen_fn
-//! and mono_item, are called only for the side effect of adding a
+//! Some functions here, such as `codegen_block` and `codegen_expr`, return a value --
+//! the result of the codegen to LLVM -- while others, such as `codegen_fn`
+//! and `mono_item`, are called only for the side effect of adding a
 //! particular definition to the LLVM IR output we're producing.
 //!
 //! Hopefully useful general knowledge about codegen:
 //!
-//! * There's no way to find out the `Ty` type of a Value. Doing so
+//! * There's no way to find out the `Ty` type of a `Value`. Doing so
 //!   would be "trying to get the eggs out of an omelette" (credit:
 //!   pcwalton). You can, instead, find out its `llvm::Type` by calling `val_ty`,
 //!   but one `llvm::Type` corresponds to many `Ty`s; for instance, `tup(int, int,
 //!   int)` and `rec(x=int, y=int, z=int)` will have the same `llvm::Type`.
 
-use crate::{ModuleCodegen, ModuleKind, CachedModuleCodegen};
+use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind};
+use crate::back::write::{
+    OngoingCodegen, start_async_codegen, submit_pre_lto_module_to_llvm,
+    submit_post_lto_module_to_llvm,
+};
+use crate::common::{RealPredicate, TypeKind, IntPredicate};
+use crate::meth;
+use crate::mir;
+use crate::mir::operand::OperandValue;
+use crate::mir::place::PlaceRef;
+use crate::traits::*;
 
 use rustc::dep_graph::cgu_reuse_tracker::CguReuse;
+use rustc::hir;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::lang_items::StartFnLangItem;
@@ -23,6 +34,7 @@
 use rustc::mir::mono::{CodegenUnitNameBuilder, CodegenUnit, MonoItem};
 use rustc::ty::{self, Ty, TyCtxt, Instance};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
+use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::util::common::{time, print_time_passes_entry, set_time_depth, time_depth};
 use rustc::util::nodemap::FxHashMap;
 use rustc_index::vec::Idx;
 use rustc_codegen_utils::{symbol_names_test, check_for_rustc_errors_attr};
-use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
-use crate::mir::place::PlaceRef;
-use crate::back::write::{OngoingCodegen, start_async_codegen, submit_pre_lto_module_to_llvm,
-    submit_post_lto_module_to_llvm};
-use crate::{MemFlags, CrateInfo};
-use crate::common::{RealPredicate, TypeKind, IntPredicate};
-use crate::meth;
-use crate::mir;
-
-use crate::traits::*;
+use syntax::attr;
+use syntax_pos::Span;
 
 use std::cmp;
 use std::ops::{Deref, DerefMut};
 use std::time::{Instant, Duration};
-use syntax_pos::Span;
-use syntax::attr;
-use rustc::hir;
-
-use crate::mir::operand::OperandValue;
 
 pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
                                 signed: bool)
@@ -116,9 +115,8 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 /// Retrieves the information we are losing (making dynamic) in an unsizing
 /// adjustment.
 ///
-/// The `old_info` argument is a bit funny. It is intended for use
-/// in an upcast, where the new vtable for an object will be derived
-/// from the old one.
+/// The `old_info` argument is a bit odd. It is intended for use in an upcast,
+/// where the new vtable for an object will be derived from the old one.
 pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
     cx: &Cx,
     source: Ty<'tcx>,
@@ -140,16 +138,19 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
         (_, &ty::Dynamic(ref data, ..)) => {
             let vtable_ptr = cx.layout_of(cx.tcx().mk_mut_ptr(target))
                 .field(cx, FAT_PTR_EXTRA);
-            cx.const_ptrcast(meth::get_vtable(cx, source, data.principal()),
-                            cx.backend_type(vtable_ptr))
+            cx.const_ptrcast(
+                meth::get_vtable(cx, source, data.principal()),
+                cx.backend_type(vtable_ptr),
+            )
         }
-        _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
-                  source,
-                  target),
+        _ => bug!(
+            "unsized_info: invalid unsizing {:?} -> {:?}",
+            source, target
+        ),
     }
 }
 
-/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer.
+/// Coerces `src` to `dst_ty`. `src_ty` must be a thin pointer.
 pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     bx: &mut Bx,
     src: Bx::Value,
@@ -199,8 +200,8 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     }
 }
 
-/// Coerce `src`, which is a reference to a value of type `src_ty`,
-/// to a value of type `dst_ty` and store the result in `dst`
+/// Coerces `src`, which is a reference to a value of type `src_ty`,
+/// to a value of type `dst_ty`, and stores the result in `dst`.
 pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     bx: &mut Bx,
     src: PlaceRef<'tcx, Bx::Value>,
@@ -244,15 +245,17 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
                 if src_f.layout.ty == dst_f.layout.ty {
                     memcpy_ty(bx, dst_f.llval, dst_f.align, src_f.llval, src_f.align,
-                              src_f.layout, MemFlags::empty());
+                        src_f.layout, MemFlags::empty());
                 } else {
                     coerce_unsized_into(bx, src_f, dst_f);
                 }
             }
         }
-        _ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}",
-                  src_ty,
-                  dst_ty),
+        _ => bug!(
+            "coerce_unsized_into: invalid coercion {:?} -> {:?}",
+            src_ty,
+            dst_ty,
+        ),
     }
 }
 
index 692027390ec1b04eb157f1f04bd27dda6630eb88..c14618a15eaebf8f4133333209402d110ecb7751 100644 (file)
@@ -1,8 +1,7 @@
-use rustc_target::abi::call::FnAbi;
-
 use crate::traits::*;
 
 use rustc::ty::{self, Ty, Instance};
+use rustc_target::abi::call::FnAbi;
 
 #[derive(Copy, Clone, Debug)]
 pub struct VirtualIndex(u64);
@@ -20,7 +19,7 @@ pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
         self,
         bx: &mut Bx,
         llvtable: Bx::Value,
-        fn_abi: &FnAbi<'tcx, Ty<'tcx>>
+        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
     ) -> Bx::Value {
         // Load the data pointer from the object.
         debug!("get_fn({:?}, {:?})", llvtable, self);
@@ -33,7 +32,7 @@ pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
         let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
         let ptr = bx.load(gep, ptr_align);
         bx.nonnull_metadata(ptr);
-        // Vtable loads are invariant
+        // Vtable loads are invariant.
         bx.set_invariant_load(ptr);
         ptr
     }
@@ -41,7 +40,7 @@ pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
     pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
         self,
         bx: &mut Bx,
-        llvtable: Bx::Value
+        llvtable: Bx::Value,
     ) -> Bx::Value {
         // Load the data pointer from the object.
         debug!("get_int({:?}, {:?})", llvtable, self);
@@ -50,7 +49,7 @@ pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
         let usize_align = bx.tcx().data_layout.pointer_align.abi;
         let gep = bx.inbounds_gep(llvtable, &[bx.const_usize(self.0)]);
         let ptr = bx.load(gep, usize_align);
-        // Vtable loads are invariant
+        // Vtable loads are invariant.
         bx.set_invariant_load(ptr);
         ptr
     }
@@ -63,7 +62,7 @@ pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
 ///
 /// The `trait_ref` encodes the erased self type. Hence if we are
 /// making an object `Foo<dyn Trait>` from a value of type `Foo<T>`, then
-/// `trait_ref` would map `T:Trait`.
+/// `trait_ref` would map `T: Trait`.
 pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
     cx: &Cx,
     ty: Ty<'tcx>,
@@ -78,7 +77,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
         return val;
     }
 
-    // Not in the cache. Build it.
+    // Not in the cache; build it.
     let nullptr = cx.const_null(cx.type_i8p());
 
     let methods_root;
@@ -105,7 +104,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
     let layout = cx.layout_of(ty);
     // /////////////////////////////////////////////////////////////////////////////////////////////
     // If you touch this code, be sure to also make the corresponding changes to
-    // `get_vtable` in rust_mir/interpret/traits.rs
+    // `get_vtable` in `rust_mir/interpret/traits.rs`.
     // /////////////////////////////////////////////////////////////////////////////////////////////
     let components: Vec<_> = [
         cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)),
index 181787e398546c7ecca299fe414183f8989819bf..27891be6b82c5e45093cc7c9c6cac7c52c040cb8 100644 (file)
@@ -5,17 +5,40 @@
 use rustc::ty::layout::{self, HasTyCtxt};
 use syntax::source_map::Span;
 use crate::traits::*;
+use crate::mir::operand::OperandRef;
 
 use super::FunctionCx;
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
+    pub fn eval_mir_constant_to_operand(
+        &mut self,
+        bx: &mut Bx,
+        constant: &mir::Constant<'tcx>,
+    ) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
+        match constant.literal.val {
+            ty::ConstKind::Unevaluated(def_id, substs)
+                if self.cx.tcx().is_static(def_id) => {
+                    assert!(substs.is_empty(), "we don't support generic statics yet");
+                    let static_ = bx.get_static(def_id);
+                    // we treat operands referring to statics as if they were `&STATIC` instead
+                    let ptr_ty = self.cx.tcx().mk_mut_ptr(self.monomorphize(&constant.literal.ty));
+                    let layout = bx.layout_of(ptr_ty);
+                    Ok(OperandRef::from_immediate_or_packed_pair(bx, static_, layout))
+                }
+            _ => {
+                let val = self.eval_mir_constant(constant)?;
+                Ok(OperandRef::from_const(bx, val))
+            }
+        }
+    }
+
     pub fn eval_mir_constant(
         &mut self,
         constant: &mir::Constant<'tcx>,
     ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
         match constant.literal.val {
-            ty::ConstKind::Unevaluated(def_id, ref substs) => {
-                let substs = self.monomorphize(substs);
+            ty::ConstKind::Unevaluated(def_id, substs) => {
+                let substs = self.monomorphize(&substs);
                 let instance = ty::Instance::resolve(
                     self.cx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
                 ).unwrap();
index 78d09f834c68c9a147d4e987347af4da47a1b3e7..310b8aeb4db09d3de5830959c55dae1f72f9fcd5 100644 (file)
@@ -1,18 +1,17 @@
-use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
-use rustc::mir;
-use rustc::ty;
-use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size};
+use super::{FunctionCx, LocalRef};
+use super::place::PlaceRef;
 
-use crate::base;
 use crate::MemFlags;
+use crate::base;
 use crate::glue;
-
 use crate::traits::*;
 
-use std::fmt;
+use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
+use rustc::mir;
+use rustc::ty;
+use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size};
 
-use super::{FunctionCx, LocalRef};
-use super::place::PlaceRef;
+use std::fmt;
 
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
@@ -343,6 +342,7 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
             }
         }
     }
+
     pub fn store_unsized<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         self,
         bx: &mut Bx,
@@ -465,8 +465,7 @@ pub fn codegen_operand(
             }
 
             mir::Operand::Constant(ref constant) => {
-                self.eval_mir_constant(constant)
-                    .map(|c| OperandRef::from_const(bx, c))
+                self.eval_mir_constant_to_operand(bx, constant)
                     .unwrap_or_else(|err| {
                         match err {
                             // errored or at least linted
index d4e33ee8b6f33e904267ffcc1c462b32557fe29d..4df5bce95377bce8780415d5925e8d7e5aa0f8ff 100644 (file)
@@ -1,28 +1,28 @@
-use rustc::ty::{self, Instance, Ty};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
-use rustc::mir;
-use rustc::mir::tcx::PlaceTy;
+use super::{FunctionCx, LocalRef};
+use super::operand::OperandValue;
+
 use crate::MemFlags;
 use crate::common::IntPredicate;
 use crate::glue;
-
 use crate::traits::*;
 
-use super::{FunctionCx, LocalRef};
-use super::operand::OperandValue;
+use rustc::ty::{self, Instance, Ty};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
+use rustc::mir;
+use rustc::mir::tcx::PlaceTy;
 
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceRef<'tcx, V> {
-    /// Pointer to the contents of the place.
+    /// A pointer to the contents of the place.
     pub llval: V,
 
-    /// This place's extra data if it is unsized, or null.
+    /// This place's extra data if it is unsized, or `None` if null.
     pub llextra: Option<V>,
 
-    /// Monomorphized type of this place, including variant information.
+    /// The monomorphized type of this place, including variant information.
     pub layout: TyLayout<'tcx>,
 
-    /// What alignment we know for this place.
+    /// The alignment we know for this place.
     pub align: Align,
 }
 
@@ -107,7 +107,6 @@ pub fn len<Cx: ConstMethods<'tcx, Value = V>>(
             bug!("unexpected layout `{:#?}` in PlaceRef::len", self.layout)
         }
     }
-
 }
 
 impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
index 981fdf2298419822e543cf51e3fb48deb61a30aa..f7fb4a571401cf29f3f8c46b41175892d9f3f714 100644 (file)
@@ -1,22 +1,22 @@
+use super::{FunctionCx, LocalRef};
+use super::operand::{OperandRef, OperandValue};
+use super::place::PlaceRef;
+
+use crate::base;
+use crate::MemFlags;
+use crate::common::{self, RealPredicate, IntPredicate};
+use crate::traits::*;
+
 use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
 use rustc::mir;
 use rustc::middle::lang_items::ExchangeMallocFnLangItem;
 use rustc_apfloat::{ieee, Float, Status, Round};
-use std::{u128, i128};
 use syntax::symbol::sym;
 use syntax::source_map::{DUMMY_SP, Span};
 
-use crate::base;
-use crate::MemFlags;
-use crate::common::{self, RealPredicate, IntPredicate};
-
-use crate::traits::*;
-
-use super::{FunctionCx, LocalRef};
-use super::operand::{OperandRef, OperandValue};
-use super::place::PlaceRef;
+use std::{u128, i128};
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_rvalue(
@@ -31,8 +31,8 @@ pub fn codegen_rvalue(
         match *rvalue {
            mir::Rvalue::Use(ref operand) => {
                let cg_operand = self.codegen_operand(&mut bx, operand);
-               // FIXME: consider not copying constants through stack. (fixable by codegenning
-               // constants into OperandValue::Ref, why don’t we do that yet if we don’t?)
+               // FIXME: consider not copying constants through stack. (Fixable by codegen'ing
+               // constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?)
                cg_operand.val.store(&mut bx, dest);
                bx
            }
@@ -41,7 +41,7 @@ pub fn codegen_rvalue(
                 // The destination necessarily contains a fat pointer, so if
                 // it's a scalar pair, it's a fat pointer or newtype thereof.
                 if bx.cx().is_backend_scalar_pair(dest.layout) {
-                    // into-coerce of a thin pointer to a fat pointer - just
+                    // Into-coerce of a thin pointer to a fat pointer -- just
                     // use the operand path.
                     let (mut bx, temp) = self.codegen_rvalue_operand(bx, rvalue);
                     temp.val.store(&mut bx, dest);
@@ -56,10 +56,10 @@ pub fn codegen_rvalue(
                 match operand.val {
                     OperandValue::Pair(..) |
                     OperandValue::Immediate(_) => {
-                        // unsize from an immediate structure. We don't
+                        // Unsize from an immediate structure. We don't
                         // really need a temporary alloca here, but
                         // avoiding it would require us to have
-                        // `coerce_unsized_into` use extractvalue to
+                        // `coerce_unsized_into` use `extractvalue` to
                         // index into the struct, and this case isn't
                         // important enough for it.
                         debug!("codegen_rvalue: creating ugly alloca");
@@ -74,7 +74,7 @@ pub fn codegen_rvalue(
                         base::coerce_unsized_into(&mut bx, source, dest);
                     }
                     OperandValue::Ref(_, Some(_), _) => {
-                        bug!("unsized coercion on an unsized rvalue")
+                        bug!("unsized coercion on an unsized rvalue");
                     }
                 }
                 bx
@@ -160,7 +160,7 @@ pub fn codegen_rvalue_unsized(
                 bx
             }
 
-            _ => bug!("unsized assignment other than Rvalue::Use"),
+            _ => bug!("unsized assignment other than `Rvalue::Use`"),
         }
     }
 
@@ -220,17 +220,16 @@ pub fn codegen_rvalue_operand(
                         }
                     }
                     mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
-                        // this is a no-op at the LLVM level
+                        // This is a no-op at the LLVM level.
                         operand.val
                     }
                     mir::CastKind::Pointer(PointerCast::Unsize) => {
                         assert!(bx.cx().is_backend_scalar_pair(cast));
                         match operand.val {
                             OperandValue::Pair(lldata, llextra) => {
-                                // unsize from a fat pointer - this is a
+                                // unsize from a fat pointer -- this is a
                                 // "trait-object-to-supertrait" coercion, for
-                                // example,
-                                //   &'a fmt::Debug+Send => &'a fmt::Debug,
+                                // example, `&'a fmt::Debug + Send => &'a fmt::Debug`.
 
                                 // HACK(eddyb) have to bitcast pointers
                                 // until LLVM removes pointee types.
@@ -245,13 +244,13 @@ pub fn codegen_rvalue_operand(
                                 OperandValue::Pair(lldata, llextra)
                             }
                             OperandValue::Ref(..) => {
-                                bug!("by-ref operand {:?} in codegen_rvalue_operand",
+                                bug!("by-ref operand {:?} in `codegen_rvalue_operand`",
                                      operand);
                             }
                         }
                     }
-                    mir::CastKind::Pointer(PointerCast::MutToConstPointer)
-                    mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
+                    mir::CastKind::Pointer(PointerCast::MutToConstPointer) |
+                    mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
                         if let OperandValue::Pair(data_ptr, meta) = operand.val {
                             if bx.cx().is_backend_scalar_pair(cast) {
                                 let data_cast = bx.pointercast(data_ptr,
@@ -265,12 +264,12 @@ pub fn codegen_rvalue_operand(
                                 OperandValue::Immediate(llval)
                             }
                         } else {
-                            bug!("Unexpected non-Pair operand")
+                            bug!("unexpected non-pair operand");
                         }
                     }
-                    mir::CastKind::Pointer(PointerCast::MutToConstPointer)
-                    | mir::CastKind::Pointer(PointerCast::ArrayToPointer)
-                    mir::CastKind::Misc => {
+                    mir::CastKind::Pointer(PointerCast::MutToConstPointer) |
+                    mir::CastKind::Pointer(PointerCast::ArrayToPointer) |
+                    mir::CastKind::Misc => {
                         assert!(bx.cx().is_backend_immediate(cast));
                         let ll_t_out = bx.cx().immediate_backend_type(cast);
                         if operand.layout.abi.is_uninhabited() {
index 8ab8243afdab7c43f88038d0abffd89fd53fc773..cfaa6756261e4bb372db8949c35ff2a2072d4c2d 100644 (file)
@@ -1,17 +1,18 @@
-use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout};
-use rustc::ty::Ty;
-
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
+
+use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout};
+use rustc::ty::Ty;
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::session::{Session, config};
 use rustc::ty::TyCtxt;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
-use std::sync::Arc;
-use std::sync::mpsc;
 use syntax::expand::allocator::AllocatorKind;
 use syntax_pos::symbol::Symbol;
 
+use std::sync::Arc;
+use std::sync::mpsc;
+
 pub trait BackendTypes {
     type Value: CodegenObject;
     type Function: CodegenObject;
index ebbea6e7bf56dd2227aead1a156760517a79292b..31044d4eb4f275452137fbf49a82f1b4f35c5e78 100644 (file)
@@ -4,14 +4,17 @@
 use super::intrinsic::IntrinsicCallMethods;
 use super::type_::ArgAbiMethods;
 use super::{HasCodegen, StaticBuilderMethods};
+
 use crate::common::{AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate,
     SynchronizationScope};
 use crate::mir::operand::OperandRef;
 use crate::mir::place::PlaceRef;
 use crate::MemFlags;
+
 use rustc::ty::Ty;
 use rustc::ty::layout::{Align, Size, HasParamEnv};
-use rustc_target::spec::{HasTargetSpec};
+use rustc_target::spec::HasTargetSpec;
+
 use std::ops::Range;
 use std::iter::TrustedLen;
 
index 89982b9ea62bb4d2bb68c26e41a0b11ce0c628a7..9b673de8b078820776e96885ea1aa0db11082af7 100644 (file)
@@ -41,9 +41,9 @@
     ArgAbiMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods,
 };
 pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
-use rustc::ty::layout::{HasParamEnv, HasTyCtxt};
-use rustc_target::spec::{HasTargetSpec};
 
+use rustc::ty::layout::{HasParamEnv, HasTyCtxt};
+use rustc_target::spec::HasTargetSpec;
 
 use std::fmt;
 
index 092208cfe1db74d6c3ff2ed525d6f31f3042ced1..ce62021ac17116eb46d000f406fd3346ca0a16d1 100644 (file)
@@ -429,6 +429,16 @@ fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
     }
 }
 
+impl<T, CTX> HashStable<CTX> for ::std::ops::RangeInclusive<T>
+    where T: HashStable<CTX>
+{
+    #[inline]
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        self.start().hash_stable(ctx, hasher);
+        self.end().hash_stable(ctx, hasher);
+    }
+}
+
 impl<I: vec::Idx, T, CTX> HashStable<CTX> for vec::IndexVec<I, T>
     where T: HashStable<CTX>,
 {
index 6557be9f7ecd0845f71a981d32e0ec56da43c69c..ffca2bbc869b2e9f5cc83cc86913ba1ed2d62453 100644 (file)
@@ -285,8 +285,8 @@ pub fn run_compiler(
 
         compiler.parse()?;
 
-        if let Some((ppm, opt_uii)) = &sess.opts.pretty {
-            if ppm.needs_ast_map(&opt_uii) {
+        if let Some(ppm) = &sess.opts.pretty {
+            if ppm.needs_ast_map() {
                 compiler.global_ctxt()?.peek_mut().enter(|tcx| {
                     let expanded_crate = compiler.expansion()?.take().0;
                     pretty::print_after_hir_lowering(
@@ -294,7 +294,6 @@ pub fn run_compiler(
                         compiler.input(),
                         &expanded_crate,
                         *ppm,
-                        opt_uii.clone(),
                         compiler.output_file().as_ref().map(|p| &**p),
                     );
                     Ok(())
index e869607c970b0609876852f0e2d2fdf14e0d9de1..11603f6d9c121c10cfe739747fe2d92cde08e64f 100644 (file)
@@ -5,7 +5,7 @@
 use rustc::hir::print as pprust_hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::session::Session;
-use rustc::session::config::{PpMode, PpSourceMode, UserIdentifiedItem, Input};
+use rustc::session::config::{PpMode, PpSourceMode, Input};
 use rustc::ty::{self, TyCtxt};
 use rustc::util::common::ErrorReported;
 use rustc_mir::util::{write_mir_pretty, write_mir_graphviz};
@@ -19,7 +19,6 @@
 use std::io::Write;
 use std::path::Path;
 
-pub use self::UserIdentifiedItem::*;
 pub use self::PpSourceMode::*;
 pub use self::PpMode::*;
 use crate::abort_on_err;
@@ -444,14 +443,12 @@ pub fn print_after_hir_lowering<'tcx>(
     input: &Input,
     krate: &ast::Crate,
     ppm: PpMode,
-    opt_uii: Option<UserIdentifiedItem>,
     ofile: Option<&Path>,
 ) {
     if ppm.needs_analysis() {
         abort_on_err(print_with_analysis(
             tcx,
             ppm,
-            opt_uii,
             ofile
         ), tcx.sess);
         return;
@@ -461,8 +458,8 @@ pub fn print_after_hir_lowering<'tcx>(
 
     let mut out = String::new();
 
-    match (ppm, opt_uii) {
-            (PpmSource(s), _) => {
+    match ppm {
+            PpmSource(s) => {
                 // Silently ignores an identified node.
                 let out = &mut out;
                 let src = src.clone();
@@ -479,7 +476,7 @@ pub fn print_after_hir_lowering<'tcx>(
                 })
             }
 
-            (PpmHir(s), None) => {
+            PpmHir(s) => {
                 let out = &mut out;
                 let src = src.clone();
                 call_with_pp_support_hir(&s, tcx, move |annotation, krate| {
@@ -494,7 +491,7 @@ pub fn print_after_hir_lowering<'tcx>(
                 })
             }
 
-            (PpmHirTree(s), None) => {
+            PpmHirTree(s) => {
                 let out = &mut out;
                 call_with_pp_support_hir(&s, tcx, move |_annotation, krate| {
                     debug!("pretty printing source code {:?}", s);
@@ -502,44 +499,6 @@ pub fn print_after_hir_lowering<'tcx>(
                 });
             }
 
-            (PpmHir(s), Some(uii)) => {
-                let out = &mut out;
-                let src = src.clone();
-                call_with_pp_support_hir(&s, tcx, move |annotation, _| {
-                    debug!("pretty printing source code {:?}", s);
-                    let sess = annotation.sess();
-                    let hir_map = annotation.hir_map().expect("-Z unpretty missing HIR map");
-                    let mut pp_state = pprust_hir::State::new_from_input(sess.source_map(),
-                                                                         &sess.parse_sess,
-                                                                         src_name,
-                                                                         src,
-                                                                         annotation.pp_ann());
-                    for node_id in uii.all_matching_node_ids(hir_map) {
-                        let hir_id = tcx.hir().node_to_hir_id(node_id);
-                        let node = hir_map.get(hir_id);
-                        pp_state.print_node(node);
-                        pp_state.s.space();
-                        let path = annotation.node_path(hir_id)
-                            .expect("-Z unpretty missing node paths");
-                        pp_state.synth_comment(path);
-                        pp_state.s.hardbreak();
-                    }
-                    *out = pp_state.s.eof();
-                })
-            }
-
-            (PpmHirTree(s), Some(uii)) => {
-                let out = &mut out;
-                call_with_pp_support_hir(&s, tcx, move |_annotation, _krate| {
-                    debug!("pretty printing source code {:?}", s);
-                    for node_id in uii.all_matching_node_ids(tcx.hir()) {
-                        let hir_id = tcx.hir().node_to_hir_id(node_id);
-                        let node = tcx.hir().get(hir_id);
-                        out.push_str(&format!("{:#?}", node));
-                    }
-                })
-            }
-
             _ => unreachable!(),
         }
 
@@ -553,27 +512,17 @@ pub fn print_after_hir_lowering<'tcx>(
 fn print_with_analysis(
     tcx: TyCtxt<'_>,
     ppm: PpMode,
-    uii: Option<UserIdentifiedItem>,
     ofile: Option<&Path>,
 ) -> Result<(), ErrorReported> {
-    let nodeid = if let Some(uii) = uii {
-        debug!("pretty printing for {:?}", uii);
-        Some(uii.to_one_node_id("-Z unpretty", tcx.sess, tcx.hir()))
-    } else {
-        debug!("pretty printing for whole crate");
-        None
-    };
-
     let mut out = Vec::new();
 
     tcx.analysis(LOCAL_CRATE)?;
 
     match ppm {
         PpmMir | PpmMirCFG => {
-            let def_id = nodeid.map(|nid| tcx.hir().local_def_id_from_node_id(nid));
             match ppm {
-                PpmMir => write_mir_pretty(tcx, def_id, &mut out),
-                PpmMirCFG => write_mir_graphviz(tcx, def_id, &mut out),
+                PpmMir => write_mir_pretty(tcx, None, &mut out),
+                PpmMirCFG => write_mir_graphviz(tcx, None, &mut out),
                 _ => unreachable!(),
             }
         }
index 2bf59983fa93af05b6664b5f008515ce274c8b69..361cb425809d7a1f06d8b1ca00cd8cbe2b8c61c0 100644 (file)
@@ -1,14 +1,32 @@
-The only functions that can be called in static or constant expressions are
-`const` functions, and struct/enum constructors. `const` functions are only
-available on a nightly compiler. Rust currently does not support more general
-compile-time function execution.
+A constant item was initialized with something that is not a constant expression.
+
+Erroneous code example:
+
+```compile_fail,E0015
+fn create_some() -> Option<u8> {
+    Some(1)
+}
 
+const FOO: Option<u8> = create_some(); // error!
 ```
-const FOO: Option<u8> = Some(1); // enum constructor
-struct Bar {x: u8}
-const BAR: Bar = Bar {x: 1}; // struct constructor
+
+The only functions that can be called in static or constant expressions are
+`const` functions, and struct/enum constructors.
+
+To fix this error, you can declare `create_some` as a constant function:
+
 ```
+const fn create_some() -> Option<u8> { // declared as a const function
+    Some(1)
+}
 
-See [RFC 911] for more details on the design of `const fn`s.
+const FOO: Option<u8> = create_some(); // ok!
 
-[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+// These are also working:
+struct Bar {
+    x: u8,
+}
+
+const OTHER_FOO: Option<u8> = Some(1);
+const BAR: Bar = Bar {x: 1};
+```
index 23a9d22a60d823cc5ce2e66577c90809d29005f0..c1d85705da3a94b02c60b61bc124480f0ac921f1 100644 (file)
@@ -2,11 +2,18 @@ A pattern attempted to extract an incorrect number of fields from a variant.
 
 Erroneous code example:
 
-```
+```compile_fail,E0023
 enum Fruit {
     Apple(String, String),
     Pear(u32),
 }
+
+let x = Fruit::Apple(String::new(), String::new());
+
+match x {
+    Fruit::Apple(a) => {}, // error!
+    _ => {}
+}
 ```
 
 A pattern used to match against an enum variant must provide a sub-pattern for
index c49cedf2d586997ead2d2c0a2e0b813ade94e4bc..735a2d1f3fe85cbe9216790c44587fc7fd365412 100644 (file)
@@ -24,4 +24,4 @@ dereferencing the pointer.
 You can read more about trait objects in the [Trait Objects] section of the
 Reference.
 
-[Trait Objects]: https://doc.rust-lang.org/reference/types.html#trait-objects
\ No newline at end of file
+[Trait Objects]: https://doc.rust-lang.org/reference/types.html#trait-objects
index 21b5eb47480e62d85feec6a252ee5995a72038a3..25e380b02e647f0a1d7b45e43cd87ec142cb796c 100644 (file)
@@ -62,7 +62,7 @@ cause this problem.)
 In such a case, the compiler cannot predict the return type of `foo()` in a
 situation like the following:
 
-```compile_fail
+```compile_fail,E0038
 trait Trait {
     fn foo(&self) -> Self;
 }
@@ -183,7 +183,7 @@ fn call_foo(thing: Box<Trait>) {
 
 We don't just need to create a table of all implementations of all methods of
 `Trait`, we need to create such a table, for each different type fed to
-`foo()`. In this case this turns out to be (10 types implementing `Trait`)*(3
+`foo()`. In this case this turns out to be (10 types implementing `Trait`)\*(3
 types being fed to `foo()`) = 30 implementations!
 
 With real world traits these numbers can grow drastically.
index e11c07f835ad765fcefbea278127afcd1fa4c892..bb5e4b48d2debee167ef664ff0381a1f5a52270d 100644 (file)
@@ -1,8 +1,6 @@
-When invoking closures or other implementations of the function traits `Fn`,
-`FnMut` or `FnOnce` using call notation, the number of parameters passed to the
-function must match its definition.
+An invalid number of arguments was given when calling a closure.
 
-An example using a closure:
+Erroneous code example:
 
 ```compile_fail,E0057
 let f = |x| x * 3;
@@ -11,6 +9,10 @@ let b = f(4);       // this works!
 let c = f(2, 3);    // invalid, too many parameters
 ```
 
+When invoking closures or other implementations of the function traits `Fn`,
+`FnMut` or `FnOnce` using call notation, the number of parameters passed to the
+function must match its definition.
+
 A generic function must be treated similarly:
 
 ```
index 3386dff2c8513c2bde8e9bfb99f6d6119fbb41fe..143251c13b069dd7bec12b8a5eb2fa6828b0eeea 100644 (file)
@@ -1,3 +1,13 @@
+An invalid number of arguments was passed when calling a function.
+
+Erroneous code example:
+
+```compile_fail,E0061
+fn f(u: i32) {}
+
+f(); // error!
+```
+
 The number of arguments passed to a function must match the number of arguments
 specified in the function signature.
 
index 41ce2d8c440e60e070cd00f6aec34fc31017faec..27ea0039354e7163e35153fa1a646f81172743bd 100644 (file)
@@ -224,7 +224,7 @@ pub fn note_expected_found_extra(
             }));
         msg.push((format!("`{}", found_extra), Style::NoStyle));
 
-        // For now, just attach these as notes
+        // For now, just attach these as notes.
         self.highlighted_note(msg);
         self
     }
index c153de7103ac2cba88a02ba60d1e81c7903ac76d..70ed4aad7b4aa99a32a619963afd0907f9e2c385 100644 (file)
@@ -21,7 +21,6 @@
 use syntax::token;
 use syntax::source_map::{FileName, FileLoader, SourceMap};
 use syntax::sess::ParseSess;
-use syntax_expand::config::process_configure_mod;
 use syntax_pos::edition;
 
 pub type Result<T> = result::Result<T, ErrorReported>;
@@ -69,7 +68,7 @@ pub fn output_file(&self) -> &Option<PathBuf> {
 pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
     syntax::with_default_globals(move || {
         let cfg = cfgspecs.into_iter().map(|s| {
-            let sess = ParseSess::with_silent_emitter(process_configure_mod);
+            let sess = ParseSess::with_silent_emitter();
             let filename = FileName::cfg_spec_source_code(&s);
             let mut parser = new_parser_from_source_str(&sess, filename, s.to_string());
 
index 5df814da770ad50a6d8a670cd7fbfd78f1421aaa..36bd8345e4359a9666ff30d451d99a043e734a03 100644 (file)
@@ -388,7 +388,7 @@ fn configure_and_expand_inner<'a>(
     // If we're actually rustdoc then there's no need to actually compile
     // anything, so switch everything to just looping
     let mut should_loop = sess.opts.actually_rustdoc;
-    if let Some((PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops), _)) = sess.opts.pretty {
+    if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
         should_loop |= true;
     }
     if should_loop {
index 8c1dac21576f7b9f2ffaf856161499af8fdaeb3e..d39a5d3a073450a34ac27be7eda217dbb2c9354f 100644 (file)
@@ -17,7 +17,6 @@
 use syntax::symbol::sym;
 use syntax::edition::{Edition, DEFAULT_EDITION};
 use syntax;
-use syntax_expand::config::process_configure_mod;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{ColorConfig, emitter::HumanReadableErrorType, registry};
 
@@ -32,7 +31,7 @@ fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options
 fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
     let registry = registry::Registry::new(&[]);
     let (sessopts, cfg) = build_session_options_and_crate_config(matches);
-    let sess = build_session(sessopts, None, registry, process_configure_mod);
+    let sess = build_session(sessopts, None, registry);
     (sess, cfg)
 }
 
index 2b4320c04e6e5d3cab8405c76385257bd88319d4..d8e20e17ce835f927239b304185d818771f7e4a8 100644 (file)
@@ -31,7 +31,6 @@
 use syntax::source_map::{FileLoader, RealFileLoader, SourceMap};
 use syntax::symbol::{Symbol, sym};
 use syntax::{self, ast, attr};
-use syntax_expand::config::process_configure_mod;
 use syntax_pos::edition::Edition;
 #[cfg(not(parallel_compiler))]
 use std::{thread, panic};
@@ -81,7 +80,6 @@ pub fn create_session(
         source_map.clone(),
         diagnostic_output,
         lint_caps,
-        process_configure_mod,
     );
 
     sess.prof.register_queries(|profiler| {
index 735cfb11b365c4876c7d8720a98183a32ea5c734..3fb252cbf8d9c867939130d585f14a1ee3e3868d 100644 (file)
@@ -47,6 +47,44 @@ fn parse_attributes(field: &syn::Field) -> Attributes {
     attrs
 }
 
+pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    let generic: syn::GenericParam = parse_quote!(__CTX);
+    s.add_bounds(synstructure::AddBounds::Generics);
+    s.add_impl_generic(generic);
+    let body = s.each(|bi| {
+        let attrs = parse_attributes(bi.ast());
+        if attrs.ignore {
+             quote!{}
+        } else if let Some(project) = attrs.project {
+            quote!{
+                &#bi.#project.hash_stable(__hcx, __hasher);
+            }
+        } else {
+            quote!{
+                #bi.hash_stable(__hcx, __hasher);
+            }
+        }
+    });
+
+    let discriminant = match s.ast().data {
+        syn::Data::Enum(_) => quote! {
+            ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
+        },
+        syn::Data::Struct(_) => quote! {},
+        syn::Data::Union(_) => panic!("cannot derive on union"),
+    };
+
+    s.bound_impl(quote!(::rustc_data_structures::stable_hasher::HashStable<__CTX>), quote!{
+        fn hash_stable(
+            &self,
+            __hcx: &mut __CTX,
+            __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher) {
+            #discriminant
+            match *self { #body }
+        }
+    })
+}
+
 pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     let generic: syn::GenericParam = parse_quote!('__ctx);
     s.add_bounds(synstructure::AddBounds::Generics);
index dce3820d2842ca53f6dd501845ce86819350e97e..eee634ffebd928185c084202a969c13ce4d2b667 100644 (file)
@@ -25,5 +25,10 @@ pub fn symbols(input: TokenStream) -> TokenStream {
 }
 
 decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
+decl_derive!(
+    [HashStable_Generic, attributes(stable_hasher)] =>
+    hash_stable::hash_stable_generic_derive
+);
+
 decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
 decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
index 9bc6d32b7cb385a990e483a6a2431cfa9bbf1183..4afbb4d85d025c561a4400517a7146b83049ec99 100644 (file)
@@ -13,6 +13,7 @@ doctest = false
 arena = { path = "../libarena" }
 either = "1.5.0"
 dot = { path = "../libgraphviz", package = "graphviz" }
+itertools = "0.8"
 log = "0.4"
 log_settings = "0.1.1"
 polonius-engine  = "0.10.0"
index 98641031c1787514ca2e461d5bf8b36f3cf5e588..943234319906a28ea54cf6391604ef7e0567eb5f 100644 (file)
@@ -189,8 +189,8 @@ fn visit_assign(
         location: mir::Location,
     ) {
         if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
-            if borrowed_place.ignore_borrow(
-                self.tcx, self.body, &self.locals_state_at_exit) {
+            if borrowed_place.ignore_borrow(self.tcx, self.body, &self.locals_state_at_exit) {
+                debug!("ignoring_borrow of {:?}", borrowed_place);
                 return;
             }
 
index ebc25138a06191d452469d24d13bf59e38eb3493..3595312f3f41b41bfa13e92a5d8838a032c2a60f 100644 (file)
@@ -3,8 +3,8 @@
 use rustc::hir::{AsyncGeneratorKind, GeneratorKind};
 use rustc::mir::{
     self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
-    FakeReadCause, Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef,
-    ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
+    FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceBase,
+    PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
 };
 use rustc::ty::{self, Ty};
 use rustc_data_structures::fx::FxHashSet;
@@ -744,6 +744,17 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
                 projection: root_place_projection,
             }, borrow_span));
 
+        if let PlaceBase::Local(local) = borrow.borrowed_place.base {
+            if self.body.local_decls[local].is_ref_to_thread_local() {
+                let err = self.report_thread_local_value_does_not_live_long_enough(
+                    drop_span,
+                    borrow_span,
+                );
+                err.buffer(&mut self.errors_buffer);
+                return;
+            }
+        };
+
         if let StorageDeadOrDrop::Destructor(dropped_ty) =
             self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
         {
@@ -770,9 +781,6 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough(
             explanation
         );
         let err = match (place_desc, explanation) {
-            (Some(_), _) if self.is_place_thread_local(root_place) => {
-                self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
-            }
             // If the outlives constraint comes from inside the closure,
             // for example:
             //
@@ -1509,19 +1517,22 @@ pub(super) fn report_illegal_reassignment(
         // place being assigned later.
         let (place_description, assigned_span) = match local_decl {
             Some(LocalDecl {
-                is_user_variable: Some(ClearCrossCrate::Clear),
+                local_info: LocalInfo::User(ClearCrossCrate::Clear),
                 ..
             })
             | Some(LocalDecl {
-                is_user_variable:
-                    Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
-                        opt_match_place: None,
-                        ..
-                    }))),
+                local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                    opt_match_place: None,
+                    ..
+                }))),
+                ..
+            })
+            | Some(LocalDecl {
+                local_info: LocalInfo::StaticRef { .. },
                 ..
             })
             | Some(LocalDecl {
-                is_user_variable: None,
+                local_info: LocalInfo::Other,
                 ..
             })
             | None => (self.describe_place(place.as_ref()), assigned_span),
index 4036e9db33b34ca7cadad224c5407279b10634d3..3835503b0ef35fdf8597ad6e40e2ca75ed22cbc9 100644 (file)
@@ -3,7 +3,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::hir::GeneratorKind;
 use rustc::mir::{
-    AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
+    AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand,
     Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind,
     Static, StaticKind, Terminator, TerminatorKind,
 };
@@ -12,7 +12,6 @@
 use rustc::ty::print::Print;
 use rustc_errors::DiagnosticBuilder;
 use syntax_pos::Span;
-use syntax::symbol::sym;
 
 use super::borrow_set::BorrowData;
 use super::MirBorrowckCtxt;
@@ -178,6 +177,31 @@ fn append_place_to_string(
             } => {
                 buf.push_str(&self.infcx.tcx.item_name(*def_id).to_string());
             }
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: [ProjectionElem::Deref]
+            } if self.body.local_decls[local].is_ref_for_guard() => {
+                self.append_place_to_string(
+                    PlaceRef {
+                        base: &PlaceBase::Local(local),
+                        projection: &[],
+                    },
+                    buf,
+                    autoderef,
+                    &including_downcast,
+                )?;
+            },
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: [ProjectionElem::Deref]
+            } if self.body.local_decls[local].is_ref_to_static() => {
+                let local_info = &self.body.local_decls[local].local_info;
+                if let LocalInfo::StaticRef { def_id, .. } = *local_info {
+                    buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
+                } else {
+                    unreachable!();
+                }
+            },
             PlaceRef {
                 base,
                 projection: [proj_base @ .., elem],
@@ -208,32 +232,6 @@ fn append_place_to_string(
                                 )?;
                             } else {
                                 match (proj_base, base) {
-                                    ([], PlaceBase::Local(local)) => {
-                                        if self.body.local_decls[*local].is_ref_for_guard() {
-                                            self.append_place_to_string(
-                                                PlaceRef {
-                                                    base,
-                                                    projection: proj_base,
-                                                },
-                                                buf,
-                                                autoderef,
-                                                &including_downcast,
-                                            )?;
-                                        } else {
-                                            // FIXME deduplicate this and the _ => body below
-                                            buf.push_str(&"*");
-                                            self.append_place_to_string(
-                                                PlaceRef {
-                                                    base,
-                                                    projection: proj_base,
-                                                },
-                                                buf,
-                                                autoderef,
-                                                &including_downcast,
-                                            )?;
-                                        }
-                                    }
-
                                     _ => {
                                         buf.push_str(&"*");
                                         self.append_place_to_string(
@@ -440,30 +438,6 @@ fn describe_field_from_ty(
         }
     }
 
-    /// Checks if a place is a thread-local static.
-    pub fn is_place_thread_local(&self, place_ref: PlaceRef<'cx, 'tcx>) -> bool {
-        if let PlaceRef {
-            base: PlaceBase::Static(box Static {
-                kind: StaticKind::Static,
-                def_id,
-                ..
-            }),
-            projection: [],
-        } = place_ref {
-            let attrs = self.infcx.tcx.get_attrs(*def_id);
-            let is_thread_local = attrs.iter().any(|attr| attr.check_name(sym::thread_local));
-
-            debug!(
-                "is_place_thread_local: attrs={:?} is_thread_local={:?}",
-                attrs, is_thread_local
-            );
-            is_thread_local
-        } else {
-            debug!("is_place_thread_local: no");
-            false
-        }
-    }
-
     /// Add a note that a type does not implement `Copy`
     pub(super) fn note_type_does_not_implement_copy(
         &self,
index b8b4a1053e5b0a8a4fd4b50c666d80b092a6fdba..90e39286ec84d02d41479625d11b490abdfc0468 100644 (file)
@@ -308,7 +308,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     // would have a chance of erroneously adding non-user-defined mutable vars
     // to the set.
     let temporary_used_locals: FxHashSet<Local> = mbcx.used_mut.iter()
-        .filter(|&local| mbcx.body.local_decls[*local].is_user_variable.is_none())
+        .filter(|&local| !mbcx.body.local_decls[*local].is_user_variable())
         .cloned()
         .collect();
     // For the remaining unused locals that are marked as mutable, we avoid linting any that
@@ -1287,7 +1287,7 @@ fn propagate_closure_used_mut_upvar(&mut self, operand: &Operand<'tcx>) {
         match *operand {
             Operand::Move(ref place) | Operand::Copy(ref place) => {
                 match place.as_local() {
-                    Some(local) if self.body.local_decls[local].is_user_variable.is_none() => {
+                    Some(local) if !self.body.local_decls[local].is_user_variable() => {
                         if self.body.local_decls[local].ty.is_mutable_ptr() {
                             // The variable will be marked as mutable by the borrow.
                             return;
@@ -1399,7 +1399,8 @@ fn check_for_invalidation_at_exit(
     ) {
         debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = &borrow.borrowed_place;
-        let root_place = self.prefixes(place.as_ref(), PrefixSet::All).last().unwrap();
+        let deref = [ProjectionElem::Deref];
+        let mut root_place = PlaceRef { base: &place.base, projection: &[] };
 
         // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
         // we just know that all locals are dropped at function exit (otherwise
@@ -1407,26 +1408,20 @@ fn check_for_invalidation_at_exit(
         //
         // FIXME: allow thread-locals to borrow other thread locals?
 
-        assert!(root_place.projection.is_empty());
         let (might_be_alive, will_be_dropped) = match root_place.base {
-            PlaceBase::Static(box Static {
-                kind: StaticKind::Promoted(..),
-                ..
-            }) => {
+            PlaceBase::Static(_) => {
                 (true, false)
             }
-            PlaceBase::Static(box Static {
-                kind: StaticKind::Static,
-                ..
-            }) => {
-                // Thread-locals might be dropped after the function exits, but
-                // "true" statics will never be.
-                (true, self.is_place_thread_local(root_place))
-            }
-            PlaceBase::Local(_) => {
-                // Locals are always dropped at function exit, and if they
-                // have a destructor it would've been called already.
-                (false, self.locals_are_invalidated_at_exit)
+            PlaceBase::Local(local) => {
+                if self.body.local_decls[*local].is_ref_to_thread_local() {
+                    // Thread-locals might be dropped after the function exits
+                    // We have to dereference the outer reference because
+                    // borrows don't conflict behind shared references.
+                    root_place.projection = &deref;
+                    (true, true)
+                } else {
+                    (false, self.locals_are_invalidated_at_exit)
+                }
             }
         };
 
@@ -1883,16 +1878,6 @@ fn check_access_permissions(
         let error_access;
         let the_place_err;
 
-        // rust-lang/rust#21232, #54986: during period where we reject
-        // partial initialization, do not complain about mutability
-        // errors except for actual mutation (as opposed to an attempt
-        // to do a partial initialization).
-        let previously_initialized = if let PlaceBase::Local(local) = place.base {
-            self.is_local_ever_initialized(local, flow_state).is_some()
-        } else {
-            true
-        };
-
         match kind {
             Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique))
             | Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. }))
@@ -1966,8 +1951,18 @@ fn check_access_permissions(
             }
         }
 
+        // rust-lang/rust#21232, #54986: during period where we reject
+        // partial initialization, do not complain about mutability
+        // errors except for actual mutation (as opposed to an attempt
+        // to do a partial initialization).
+        let previously_initialized = if let PlaceBase::Local(local) = place.base {
+            self.is_local_ever_initialized(local, flow_state).is_some()
+        } else {
+            true
+        };
+
         // at this point, we have set up the error reporting state.
-        return if previously_initialized {
+        if previously_initialized {
             self.report_mutability_error(
                 place,
                 span,
@@ -1978,7 +1973,7 @@ fn check_access_permissions(
             true
         } else {
             false
-        };
+        }
     }
 
     fn is_local_ever_initialized(
index d9e958d9450017fec5973fab06b1e5844aea54f8..b1f63d729ba9b027ce5fb0fe79d51e9f4c0b7a5e 100644 (file)
@@ -104,13 +104,14 @@ fn append_to_grouped_errors(
                         //
                         // opt_match_place is None for let [mut] x = ... statements,
                         // whether or not the right-hand side is a place expression
-                        if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
-                            opt_match_place: Some((ref opt_match_place, match_span)),
-                            binding_mode: _,
-                            opt_ty_info: _,
-                            pat_span: _,
-                        }))) = local_decl.is_user_variable
-                        {
+                        if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                            VarBindingForm {
+                                opt_match_place: Some((ref opt_match_place, match_span)),
+                                binding_mode: _,
+                                opt_ty_info: _,
+                                pat_span: _,
+                            },
+                        ))) = local_decl.local_info {
                             let stmt_source_info = self.body.source_info(location);
                             self.append_binding_error(
                                 grouped_errors,
@@ -242,7 +243,7 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
             (
                 match kind {
                     IllegalMoveOriginKind::Static => {
-                        self.report_cannot_move_from_static(original_path, span)
+                        unreachable!();
                     }
                     IllegalMoveOriginKind::BorrowedContent { target_place } => {
                         self.report_cannot_move_from_borrowed_content(
@@ -272,12 +273,12 @@ fn report_cannot_move_from_static(
         place: &Place<'tcx>,
         span: Span
     ) -> DiagnosticBuilder<'a> {
-        let description = if place.projection.is_empty() {
+        let description = if place.projection.len() == 1 {
             format!("static item `{}`", self.describe_place(place.as_ref()).unwrap())
         } else {
             let base_static = PlaceRef {
                 base: &place.base,
-                projection: &place.projection[..1],
+                projection: &[ProjectionElem::Deref],
             };
 
             format!(
@@ -327,6 +328,8 @@ fn report_cannot_move_from_borrowed_content(
                     "variables bound in patterns cannot be moved from \
                      until after the end of the pattern guard");
                 return err;
+            } else if decl.is_ref_to_static() {
+                return self.report_cannot_move_from_static(move_place, span);
             }
         }
 
@@ -508,12 +511,12 @@ fn add_move_error_suggestions(
         let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
         for local in binds_to {
             let bind_to = &self.body.local_decls[*local];
-            if let Some(
+            if let LocalInfo::User(
                 ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
                     pat_span,
                     ..
                 }))
-            ) = bind_to.is_user_variable {
+            ) = bind_to.local_info {
                 if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
                 {
                     if pat_snippet.starts_with('&') {
index 11e89de810e5b1ac51d9bec631c7ef51fc03743e..404684c07a09c6a45805e10ab3534fcdda8b8c14 100644 (file)
@@ -1,9 +1,7 @@
 use rustc::hir;
 use rustc::hir::Node;
-use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Body};
-use rustc::mir::{
-    Mutability, Place, PlaceRef, PlaceBase, ProjectionElem, Static, StaticKind
-};
+use rustc::mir::{self, Body, ClearCrossCrate, Local, LocalInfo, Location};
+use rustc::mir::{Mutability, Place, PlaceRef, PlaceBase, ProjectionElem};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_index::vec::Idx;
 use syntax_pos::Span;
@@ -76,6 +74,31 @@ pub(super) fn report_mutability_error(
                 }
             }
 
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: [ProjectionElem::Deref],
+            } if self.body.local_decls[local].is_ref_for_guard() => {
+                item_msg = format!("`{}`", access_place_desc.unwrap());
+                reason = ", as it is immutable for the pattern guard".to_string();
+            }
+            PlaceRef {
+                base: &PlaceBase::Local(local),
+                projection: [ProjectionElem::Deref],
+            } if self.body.local_decls[local].is_ref_to_static() => {
+                if access_place.projection.len() == 1 {
+                    item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
+                    reason = String::new();
+                } else {
+                    item_msg = format!("`{}`", access_place_desc.unwrap());
+                    let local_info = &self.body.local_decls[local].local_info;
+                    if let LocalInfo::StaticRef { def_id, .. } = *local_info {
+                        let static_name = &self.infcx.tcx.item_name(def_id);
+                        reason = format!(", as `{}` is an immutable static item", static_name);
+                    } else {
+                        bug!("is_ref_to_static return true, but not ref to static?");
+                    }
+                }
+            }
             PlaceRef {
                 base: _,
                 projection: [proj_base @ .., ProjectionElem::Deref],
@@ -101,15 +124,6 @@ pub(super) fn report_mutability_error(
                         } else {
                             ", as `Fn` closures cannot mutate their captured variables".to_string()
                         }
-                } else if {
-                    if let (PlaceBase::Local(local), []) = (&the_place_err.base, proj_base) {
-                        self.body.local_decls[*local].is_ref_for_guard()
-                    } else {
-                        false
-                    }
-                } {
-                    item_msg = format!("`{}`", access_place_desc.unwrap());
-                    reason = ", as it is immutable for the pattern guard".to_string();
                 } else {
                     let source = self.borrowed_content_source(PlaceRef {
                         base: the_place_err.base,
@@ -133,37 +147,10 @@ pub(super) fn report_mutability_error(
             }
 
             PlaceRef {
-                base:
-                    PlaceBase::Static(box Static {
-                        kind: StaticKind::Promoted(..),
-                        ..
-                    }),
-                projection: [],
-            } => unreachable!(),
-
-            PlaceRef {
-                base:
-                    PlaceBase::Static(box Static {
-                        kind: StaticKind::Static,
-                        def_id,
-                        ..
-                    }),
-                projection: [],
-            } => {
-                if let PlaceRef {
-                    base: &PlaceBase::Static(_),
-                    projection: &[],
-                } = access_place.as_ref() {
-                    item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
-                    reason = String::new();
-                } else {
-                    item_msg = format!("`{}`", access_place_desc.unwrap());
-                    let static_name = &self.infcx.tcx.item_name(*def_id);
-                    reason = format!(", as `{}` is an immutable static item", static_name);
-                }
+                base: PlaceBase::Static(_),
+                ..
             }
-
-            PlaceRef {
+            | PlaceRef {
                 base: _,
                 projection: [.., ProjectionElem::Index(_)],
             }
@@ -257,15 +244,15 @@ pub(super) fn report_mutability_error(
                 projection: [],
             } if {
                 self.body.local_decls.get(*local).map(|local_decl| {
-                    if let ClearCrossCrate::Set(
+                    if let LocalInfo::User(ClearCrossCrate::Set(
                         mir::BindingForm::ImplicitSelf(kind)
-                    ) = local_decl.is_user_variable.as_ref().unwrap() {
+                    )) = local_decl.local_info {
                         // Check if the user variable is a `&mut self` and we can therefore
                         // suggest removing the `&mut`.
                         //
                         // Deliberately fall into this case for all implicit self types,
                         // so that we don't fall in to the next case with them.
-                        *kind == mir::ImplicitSelfKind::MutRef
+                        kind == mir::ImplicitSelfKind::MutRef
                     } else if Some(kw::SelfLower) == local_decl.name {
                         // Otherwise, check if the name is the self kewyord - in which case
                         // we have an explicit self. Do the same thing in this case and check
@@ -360,16 +347,7 @@ pub(super) fn report_mutability_error(
             PlaceRef {
                 base: PlaceBase::Local(local),
                 projection: [ProjectionElem::Deref],
-            } if {
-                if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
-                    self.body.local_decls[*local].is_user_variable
-                {
-                    true
-                } else {
-                    false
-                }
-            } =>
-            {
+            } if self.body.local_decls[*local].is_ref_for_guard() => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
                 err.note(
                     "variables bound in patterns are immutable until the end of the pattern guard",
@@ -384,38 +362,42 @@ pub(super) fn report_mutability_error(
             PlaceRef {
                 base: PlaceBase::Local(local),
                 projection: [ProjectionElem::Deref],
-            } if self.body.local_decls[*local].is_user_variable.is_some() =>
+            } if self.body.local_decls[*local].is_user_variable() =>
             {
                 let local_decl = &self.body.local_decls[*local];
-                let suggestion = match local_decl.is_user_variable.as_ref().unwrap() {
-                    ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_)) => {
+                let suggestion = match local_decl.local_info {
+                    LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => {
                         Some(suggest_ampmut_self(self.infcx.tcx, local_decl))
                     }
 
-                    ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
-                        binding_mode: ty::BindingMode::BindByValue(_),
-                        opt_ty_info,
-                        ..
-                    })) => Some(suggest_ampmut(
+                    LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
+                        mir::VarBindingForm {
+                            binding_mode: ty::BindingMode::BindByValue(_),
+                            opt_ty_info,
+                            ..
+                        },
+                    ))) => Some(suggest_ampmut(
                         self.infcx.tcx,
                         self.body,
                         *local,
                         local_decl,
-                        *opt_ty_info,
+                        opt_ty_info,
                     )),
 
-                    ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
-                        binding_mode: ty::BindingMode::BindByReference(_),
-                        ..
-                    })) => {
+                    LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
+                        mir::VarBindingForm {
+                            binding_mode: ty::BindingMode::BindByReference(_),
+                            ..
+                        },
+                    ))) => {
                         let pattern_span = local_decl.source_info.span;
                         suggest_ref_mut(self.infcx.tcx, pattern_span)
                             .map(|replacement| (pattern_span, replacement))
                     }
 
-                    ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => unreachable!(),
+                    LocalInfo::User(ClearCrossCrate::Clear) => bug!("saw cleared local state"),
 
-                    ClearCrossCrate::Clear => bug!("saw cleared local state"),
+                    _ => unreachable!(),
                 };
 
                 let (pointer_sigil, pointer_desc) = if local_decl.ty.is_region_ptr() {
index 9f20a24a183c91416112e39367ed83e07b49809e..99bcfa9bc25995a3babf96a08d11565e51b14463 100644 (file)
@@ -1387,7 +1387,7 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                     } else {
                         ConstraintCategory::Return
                     },
-                    Some(l) if !body.local_decls[l].is_user_variable.is_some() => {
+                    Some(l) if !body.local_decls[l].is_user_variable() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
@@ -1693,7 +1693,7 @@ fn check_call_dest(
                             ConstraintCategory::Return
                         }
                     }
-                    Some(l) if !body.local_decls[l].is_user_variable.is_some() => {
+                    Some(l) if !body.local_decls[l].is_user_variable() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
index f0d2927ba45e70af68034f845718d23260b51607..c62de2af55f449c5218f7df0cfdf04b0861bbebf 100644 (file)
@@ -1,6 +1,6 @@
 use rustc::hir;
 use rustc::mir::ProjectionElem;
-use rustc::mir::{Body, Place, PlaceBase, Mutability, Static, StaticKind};
+use rustc::mir::{Body, Place, PlaceBase, Mutability};
 use rustc::ty::{self, TyCtxt};
 use crate::borrow_check::borrow_set::LocalsStateAtExit;
 
@@ -25,7 +25,7 @@ fn ignore_borrow(
         body: &Body<'tcx>,
         locals_state_at_exit: &LocalsStateAtExit,
     ) -> bool {
-        let ignore = match self.base {
+        let local = match self.base {
             // 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
@@ -34,22 +34,22 @@ fn ignore_borrow(
             //
             // In particular, the variable cannot be mutated -- the "access checks" will fail --
             // so we don't have to worry about mutation while borrowed.
-            PlaceBase::Local(index) => {
+            PlaceBase::Local(local) => {
                 match locals_state_at_exit {
-                    LocalsStateAtExit::AllAreInvalidated => false,
+                    LocalsStateAtExit::AllAreInvalidated => local,
                     LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } => {
-                        let ignore = !has_storage_dead_or_moved.contains(index) &&
-                            body.local_decls[index].mutability == Mutability::Not;
-                        debug!("ignore_borrow: local {:?} => {:?}", index, ignore);
-                        ignore
+                        let ignore = !has_storage_dead_or_moved.contains(local) &&
+                            body.local_decls[local].mutability == Mutability::Not;
+                        debug!("ignore_borrow: local {:?} => {:?}", local, ignore);
+                        if ignore {
+                            return true;
+                        } else {
+                            local
+                        }
                     }
                 }
             }
-            PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) =>
-                false,
-            PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => {
-                tcx.is_mutable_static(def_id)
-            }
+            PlaceBase::Static(_) => return true,
         };
 
         for (i, elem) in self.projection.iter().enumerate() {
@@ -57,22 +57,33 @@ fn ignore_borrow(
 
             if *elem == ProjectionElem::Deref {
                 let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty;
-                if let ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Immutable) = ty.kind {
-                    // For both derefs of raw pointers and `&T`
-                    // references, the original path is `Copy` and
-                    // therefore not significant.  In particular,
-                    // there is nothing the user can do to the
-                    // original path that would invalidate the
-                    // newly created reference -- and if there
-                    // were, then the user could have copied the
-                    // original path into a new variable and
-                    // borrowed *that* one, leaving the original
-                    // path unborrowed.
-                    return true;
+                match ty.kind {
+                    ty::Ref(_, _, hir::Mutability::Immutable) if i == 0 => {
+                        // For references to thread-local statics, we do need
+                        // to track the borrow.
+                        if body.local_decls[local].is_ref_to_thread_local() {
+                            continue;
+                        }
+                        return true;
+                    }
+                    ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Immutable) => {
+                        // For both derefs of raw pointers and `&T`
+                        // references, the original path is `Copy` and
+                        // therefore not significant.  In particular,
+                        // there is nothing the user can do to the
+                        // original path that would invalidate the
+                        // newly created reference -- and if there
+                        // were, then the user could have copied the
+                        // original path into a new variable and
+                        // borrowed *that* one, leaving the original
+                        // path unborrowed.
+                        return true;
+                    }
+                    _ => {}
                 }
             }
         }
 
-        ignore
+        false
     }
 }
index 39bdc871d83c6deed23df26d770f9dd5eed88716..6db7ec65096ec1fc3777cad4ef50306a2ae2f117 100644 (file)
@@ -45,6 +45,13 @@ fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
                     literal,
                 }
             },
+            ExprKind::StaticRef { literal, .. } => {
+                Constant {
+                    span,
+                    user_ty: None,
+                    literal,
+                }
+            }
             _ => span_bug!(span, "expression is not a valid constant {:?}", kind),
         }
     }
index d3e013acc9e3a8ed17fee81e8beb06aa97b0f4cc..f66f1cb73666afdb428db5791c0e37cdb6da55d4 100644 (file)
@@ -197,13 +197,6 @@ fn expr_as_place(
                 };
                 block.and(place_builder)
             }
-            ExprKind::StaticRef { id } => block.and(PlaceBuilder::from(
-                PlaceBase::Static(Box::new(Static {
-                    ty: expr.ty,
-                    kind: StaticKind::Static,
-                    def_id: id,
-                }))
-            )),
 
             ExprKind::PlaceTypeAscription { source, user_ty } => {
                 let source = this.hir.mirror(source);
@@ -292,6 +285,7 @@ fn expr_as_place(
             | ExprKind::Continue { .. }
             | ExprKind::Return { .. }
             | ExprKind::Literal { .. }
+            | ExprKind::StaticRef { .. }
             | ExprKind::InlineAsm { .. }
             | ExprKind::Yield { .. }
             | ExprKind::Call { .. } => {
index f9b77a4b5dd2adcc52320aa57841ed895d013084..37eb0cc9d961e78a637d3d8d3a91e3f52fc2acdd 100644 (file)
@@ -270,6 +270,7 @@ fn expr_as_rvalue(
                 resume.and(this.unit_rvalue())
             }
             ExprKind::Literal { .. }
+            | ExprKind::StaticRef { .. }
             | ExprKind::Block { .. }
             | ExprKind::Match { .. }
             | ExprKind::NeverToAny { .. }
@@ -288,7 +289,6 @@ fn expr_as_rvalue(
             | ExprKind::Continue { .. }
             | ExprKind::Return { .. }
             | ExprKind::InlineAsm { .. }
-            | ExprKind::StaticRef { .. }
             | ExprKind::PlaceTypeAscription { .. }
             | ExprKind::ValueTypeAscription { .. } => {
                 // these do not have corresponding `Rvalue` variants,
index 18332ed68f8bd15ae65d7dba2c36fd7121bc5aef..4dad9ab498f63c06a5959b5a3f94255074f1f61b 100644 (file)
@@ -6,6 +6,7 @@
 use rustc::hir;
 use rustc::middle::region;
 use rustc::mir::*;
+use syntax_pos::symbol::sym;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr` into a fresh temporary. This is used when building
@@ -63,6 +64,10 @@ fn expr_as_temp(
             if let Some(tail_info) = this.block_context.currently_in_block_tail() {
                 local_decl = local_decl.block_tail(tail_info);
             }
+            if let ExprKind::StaticRef { def_id, .. } = expr.kind {
+                let is_thread_local = this.hir.tcx().has_attr(def_id, sym::thread_local);
+                local_decl.local_info = LocalInfo::StaticRef {def_id, is_thread_local };
+            }
             this.local_decls.push(local_decl)
         };
         let temp_place = &Place::from(temp);
index ae5289986e77cc537ccdef36cbca6e615950a892..270a1a6447435361555bcf3deed948b2ae45e62a 100644 (file)
@@ -40,7 +40,6 @@ pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
             | ExprKind::Index { .. }
             | ExprKind::SelfRef
             | ExprKind::VarRef { .. }
-            | ExprKind::StaticRef { .. }
             | ExprKind::PlaceTypeAscription { .. }
             | ExprKind::ValueTypeAscription { .. } => Some(Category::Place),
 
@@ -66,7 +65,8 @@ pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
             | ExprKind::Yield { .. }
             | ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
 
-            ExprKind::Literal { .. } => Some(Category::Constant),
+            ExprKind::Literal { .. }
+            | ExprKind::StaticRef { .. } => Some(Category::Constant),
 
             ExprKind::Loop { .. }
             | ExprKind::Block { .. }
index 404ca3204e6c0038ade679a506ecea8215c1ea78..e991181189f412bc8c7fc2974f5013a2ffeae748 100644 (file)
@@ -231,7 +231,7 @@ pub fn into_expr(
                         source_info,
                         visibility_scope: source_info.scope,
                         internal: true,
-                        is_user_variable: None,
+                        local_info: LocalInfo::Other,
                         is_block_tail: None,
                     });
                     let ptr_temp = Place::from(ptr_temp);
@@ -384,7 +384,6 @@ pub fn into_expr(
             // Avoid creating a temporary
             ExprKind::VarRef { .. } |
             ExprKind::SelfRef |
-            ExprKind::StaticRef { .. } |
             ExprKind::PlaceTypeAscription { .. } |
             ExprKind::ValueTypeAscription { .. } => {
                 debug_assert!(Category::of(&expr.kind) == Some(Category::Place));
@@ -426,6 +425,7 @@ pub fn into_expr(
             | ExprKind::Tuple { .. }
             | ExprKind::Closure { .. }
             | ExprKind::Literal { .. }
+            | ExprKind::StaticRef { .. }
             | ExprKind::Yield { .. } => {
                 debug_assert!(match Category::of(&expr.kind).unwrap() {
                     // should be handled above
index 667b37bbd80c83bf991f5120017c92f900cf34ba..ada547aa39c9e70f5920072b162220bbfbc9fa08 100644 (file)
@@ -458,10 +458,10 @@ pub fn place_into_pattern(
             for binding in &candidate.bindings {
                 let local = self.var_local_id(binding.var_id, OutsideGuard);
 
-                if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
                     opt_match_place: Some((ref mut match_place, _)),
                     ..
-                }))) = self.local_decls[local].is_user_variable
+                }))) = self.local_decls[local].local_info
                 {
                     *match_place = Some(initializer.clone());
                 } else {
@@ -1734,16 +1734,18 @@ fn declare_binding(
             visibility_scope,
             internal: false,
             is_block_tail: None,
-            is_user_variable: Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
-                binding_mode,
-                // hypothetically, `visit_bindings` could try to unzip
-                // an outermost hir::Ty as we descend, matching up
-                // idents in pat; but complex w/ unclear UI payoff.
-                // Instead, just abandon providing diagnostic info.
-                opt_ty_info: None,
-                opt_match_place,
-                pat_span,
-            }))),
+            local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                VarBindingForm {
+                    binding_mode,
+                    // hypothetically, `visit_bindings` could try to unzip
+                    // an outermost hir::Ty as we descend, matching up
+                    // idents in pat; but complex w/ unclear UI payoff.
+                    // Instead, just abandon providing diagnostic info.
+                    opt_ty_info: None,
+                    opt_match_place,
+                    pat_span,
+                },
+            ))),
         };
         let for_arm_body = self.local_decls.push(local);
         let locals = if has_guard.0 {
@@ -1758,7 +1760,7 @@ fn declare_binding(
                 visibility_scope,
                 internal: false,
                 is_block_tail: None,
-                is_user_variable: Some(ClearCrossCrate::Set(BindingForm::RefForGuard)),
+                local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)),
             });
             LocalsForNode::ForGuard {
                 ref_for_guard,
index fb605bb2b557b9e5defd21e5d4bedcc832ff41e1..6b458cc244c9e3195564c8cdd060c1206baf8964 100644 (file)
@@ -820,7 +820,7 @@ fn args_and_body(&mut self,
                 visibility_scope: source_info.scope,
                 name,
                 internal: false,
-                is_user_variable: None,
+                local_info: LocalInfo::Other,
                 is_block_tail: None,
             });
         }
@@ -855,17 +855,21 @@ fn args_and_body(&mut self,
                     } => {
                         self.local_decls[local].mutability = mutability;
                         self.local_decls[local].source_info.scope = self.source_scope;
-                        self.local_decls[local].is_user_variable =
+                        self.local_decls[local].local_info =
                             if let Some(kind) = self_binding {
-                                Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
+                                LocalInfo::User(ClearCrossCrate::Set(
+                                    BindingForm::ImplicitSelf(*kind),
+                                ))
                             } else {
                                 let binding_mode = ty::BindingMode::BindByValue(mutability.into());
-                                Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
-                                    binding_mode,
-                                    opt_ty_info,
-                                    opt_match_place: Some((Some(place.clone()), span)),
-                                    pat_span: span,
-                                })))
+                                LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                                    VarBindingForm {
+                                        binding_mode,
+                                        opt_ty_info,
+                                        opt_match_place: Some((Some(place.clone()), span)),
+                                        pat_span: span,
+                                    },
+                                )))
                             };
                         self.var_indices.insert(var, LocalsForNode::One(local));
                     }
index 5e64144df2cd1c371d93d4b1b995017f191f3fd3..402e5aeacbf245acb264ef3b5f12522b37a19e70 100644 (file)
@@ -209,7 +209,9 @@ fn kill_borrows_on_place(
             // local must conflict. This is purely an optimization so we don't have to call
             // `places_conflict` for every borrow.
             if place.projection.is_empty() {
-                trans.kill_all(other_borrows_of_local);
+                if !self.body.local_decls[local].is_ref_to_static() {
+                    trans.kill_all(other_borrows_of_local);
+                }
                 return;
             }
 
index e9777dab26e2a5cd5c52dc9352f4d3422244a2d5..8dda51cd7717249cb4b7c3f84685baf3b8e33890 100644 (file)
@@ -1,6 +1,7 @@
 use crate::hair::{self, *};
 use crate::hair::cx::Cx;
 use crate::hair::cx::to_ref::ToRef;
+
 use rustc::middle::region;
 use rustc::hir;
 use rustc::ty;
index 12b3108c5f2de9932f0d106b5d08e755d4c9dcdc..694a3fd04eeb1f73d322683f529bf9fbc3e92a5b 100644 (file)
@@ -5,7 +5,7 @@
 use crate::hair::util::UserAnnotatedTyHelpers;
 use rustc_index::vec::Idx;
 use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
-use rustc::mir::interpret::{GlobalId, ErrorHandled};
+use rustc::mir::interpret::{GlobalId, ErrorHandled, Scalar};
 use rustc::ty::{self, AdtKind, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability, PointerCast};
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
@@ -964,7 +964,29 @@ fn convert_path_expr<'a, 'tcx>(
             }
         }
 
-        Res::Def(DefKind::Static, id) => ExprKind::StaticRef { id },
+        // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is
+        // a constant reference (or constant raw pointer for `static mut`) in MIR
+        Res::Def(DefKind::Static, id) => {
+            let ty = cx.tcx.type_of(id);
+            let ty = if cx.tcx.is_mutable_static(id) {
+                cx.tcx.mk_mut_ptr(ty)
+            } else if cx.tcx.is_foreign_item(id) {
+                cx.tcx.mk_imm_ptr(ty)
+            } else {
+                cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_static, ty)
+            };
+            let ptr = cx.tcx.alloc_map.lock().create_static_alloc(id);
+            let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
+            ExprKind::Deref { arg: Expr {
+                ty,
+                temp_lifetime,
+                span: expr.span,
+                kind: ExprKind::StaticRef {
+                    literal: ty::Const::from_scalar(cx.tcx, Scalar::Ptr(ptr.into()), ty),
+                    def_id: id,
+                }
+            }.to_ref() }
+        },
 
         Res::Local(var_hir_id) => convert_var(cx, expr, var_hir_id),
 
index 78e3a17d76632163f74286203030cc1a62f7f603..47644d9ba83725c511a800c5a07b2a5521ce48fb 100644 (file)
@@ -208,9 +208,6 @@ pub enum ExprKind<'tcx> {
     },
     /// first argument, used for self in a closure
     SelfRef,
-    StaticRef {
-        id: DefId,
-    },
     Borrow {
         borrow_kind: BorrowKind,
         arg: ExprRef<'tcx>,
@@ -267,6 +264,14 @@ pub enum ExprKind<'tcx> {
         literal: &'tcx Const<'tcx>,
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
+    /// A literal containing the address of a `static`.
+    ///
+    /// This is only distinguished from `Literal` so that we can register some
+    /// info for diagnostics.
+    StaticRef {
+        literal: &'tcx Const<'tcx>,
+        def_id: DefId,
+    },
     InlineAsm {
         asm: &'tcx hir::InlineAsmInner,
         outputs: Vec<ExprRef<'tcx>>,
index e929b0855834e98a2e3834ae8f147bf18993eeb6..842ef915ad2267025cfa1a5a6ba945eeadd58f75 100644 (file)
@@ -47,7 +47,7 @@ fn may_leak(self) -> bool {
 #[derive(Debug, Copy, Clone)]
 pub enum AllocCheck {
     /// Allocation must be live and not a function pointer.
-    Dereferencable,
+    Dereferenceable,
     /// Allocations needs to be live, but may be a function pointer.
     Live,
     /// Allocation may be dead.
@@ -365,7 +365,7 @@ fn check_offset_align(offset: u64, align: Align) -> InterpResult<'static> {
             }
             Err(ptr) => {
                 let (allocation_size, alloc_align) =
-                    self.get_size_and_align(ptr.alloc_id, AllocCheck::Dereferencable)?;
+                    self.get_size_and_align(ptr.alloc_id, AllocCheck::Dereferenceable)?;
                 // Test bounds. This also ensures non-NULL.
                 // It is sufficient to check this for the end pointer. The addition
                 // checks for overflow.
@@ -569,7 +569,7 @@ pub fn get_size_and_align(
         // # Function pointers
         // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
         if let Ok(_) = self.get_fn_alloc(id) {
-            return if let AllocCheck::Dereferencable = liveness {
+            return if let AllocCheck::Dereferenceable = liveness {
                 // The caller requested no function pointers.
                 throw_unsup!(DerefFunctionPointer)
             } else {
index 62797b313045e54eeba26ebf0cec11cdaca0d2de..4f03b1320903a48f2eeee8fe52c0be58435514ba 100644 (file)
@@ -136,7 +136,7 @@ pub fn assert_immediate(self) -> Immediate<Tag>
 
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub struct OpTy<'tcx, Tag=()> {
-    op: Operand<Tag>, // Keep this private, it helps enforce invariants
+    op: Operand<Tag>, // Keep this private; it helps enforce invariants.
     pub layout: TyLayout<'tcx>,
 }
 
@@ -203,7 +203,7 @@ pub(super) fn from_known_layout<'tcx>(
             if cfg!(debug_assertions) {
                 let layout2 = compute()?;
                 assert_eq!(layout.details, layout2.details,
-                    "Mismatch in layout of supposedly equal-layout types {:?} and {:?}",
+                    "mismatch in layout of supposedly equal-layout types {:?} and {:?}",
                     layout.ty, layout2.ty);
             }
             Ok(layout)
index 088fbe1695efd3cedc0619341264bb4949518516..5b263f768013186ebab2d718c8c2159be6394600 100644 (file)
@@ -48,7 +48,7 @@ pub enum Place<Tag=(), Id=AllocId> {
 
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceTy<'tcx, Tag=()> {
-    place: Place<Tag>, // Keep this private, it helps enforce invariants
+    place: Place<Tag>, // Keep this private; it helps enforce invariants.
     pub layout: TyLayout<'tcx>,
 }
 
index e3b3df2674f417c0b23ed49f2d16c422b0a93e5c..3a7f47a2aaca915f66977ed206701d5c087b9361 100644 (file)
@@ -1,16 +1,16 @@
+use super::{InterpCx, Machine, MemoryKind, FnVal};
+
 use rustc::ty::{self, Ty, Instance, TypeFoldable};
 use rustc::ty::layout::{Size, Align, LayoutOf, HasDataLayout};
 use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,};
 
-use super::{InterpCx, Machine, MemoryKind, FnVal};
-
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
     /// objects.
     ///
-    /// The `trait_ref` encodes the erased self type. Hence if we are
+    /// The `trait_ref` encodes the erased self type. Hence, if we are
     /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
-    /// `trait_ref` would map `T:Trait`.
+    /// `trait_ref` would map `T: Trait`.
     pub fn get_vtable(
         &mut self,
         ty: Ty<'tcx>,
@@ -51,7 +51,7 @@ pub fn get_vtable(
         let ptr_align = self.tcx.data_layout.pointer_align.abi;
         // /////////////////////////////////////////////////////////////////////////////////////////
         // If you touch this code, be sure to also make the corresponding changes to
-        // `get_vtable` in rust_codegen_llvm/meth.rs
+        // `get_vtable` in `rust_codegen_llvm/meth.rs`.
         // /////////////////////////////////////////////////////////////////////////////////////////
         let vtable = self.memory.allocate(
             ptr_size * (3 + methods.len() as u64),
@@ -97,16 +97,16 @@ pub fn get_vtable(
         Ok(vtable)
     }
 
-    /// Resolve the function at the specified slot in the provided
+    /// Resolves the function at the specified slot in the provided
     /// vtable. An index of '0' corresponds to the first method
-    /// declared in the trait of the provided vtable
+    /// declared in the trait of the provided vtable.
     pub fn get_vtable_slot(
         &self,
         vtable: Scalar<M::PointerTag>,
         idx: usize
     ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
         let ptr_size = self.pointer_size();
-        // Skip over the 'drop_ptr', 'size', and 'align' fields
+        // Skip over the 'drop_ptr', 'size', and 'align' fields.
         let vtable_slot = vtable.ptr_offset(ptr_size * (idx as u64 + 3), self)?;
         let vtable_slot = self.memory.check_ptr_access(
             vtable_slot,
@@ -118,12 +118,12 @@ pub fn get_vtable_slot(
         Ok(self.memory.get_fn(fn_ptr)?)
     }
 
-    /// Returns the drop fn instance as well as the actual dynamic type
+    /// Returns the drop fn instance as well as the actual dynamic type.
     pub fn read_drop_type_from_vtable(
         &self,
         vtable: Scalar<M::PointerTag>,
     ) -> InterpResult<'tcx, (ty::Instance<'tcx>, Ty<'tcx>)> {
-        // we don't care about the pointee type, we just want a pointer
+        // We don't care about the pointee type; we just want a pointer.
         let vtable = self.memory.check_ptr_access(
             vtable,
             self.tcx.data_layout.pointer_size,
@@ -149,7 +149,7 @@ pub fn read_size_and_align_from_vtable(
         vtable: Scalar<M::PointerTag>,
     ) -> InterpResult<'tcx, (Size, Align)> {
         let pointer_size = self.pointer_size();
-        // We check for size = 3*ptr_size, that covers the drop fn (unused here),
+        // We check for `size = 3 * ptr_size`, which covers the drop fn (unused here),
         // the size, and the align (which we read below).
         let vtable = self.memory.check_ptr_access(
             vtable,
index d698b2e8d8f80d42f1d5fbb468eb824b2cdc7bd0..e358df2f213ba3047a52bc7c5082baf4bd0e623d 100644 (file)
@@ -286,7 +286,7 @@ fn check_wide_ptr_meta(
                     "non-integer slice length in wide pointer", self.path);
                 // We do not check that `len * elem_size <= isize::MAX`:
                 // that is only required for references, and there it falls out of the
-                // "dereferencable" check performed by Stacked Borrows.
+                // "dereferenceable" check performed by Stacked Borrows.
             }
             ty::Foreign(..) => {
                 // Unsized, but not wide.
@@ -404,7 +404,7 @@ fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<
                 if place.layout.is_unsized() {
                     self.check_wide_ptr_meta(place.meta, place.layout)?;
                 }
-                // Make sure this is dereferencable and all.
+                // Make sure this is dereferenceable and all.
                 let (size, align) = self.ecx.size_and_align_of(place.meta, place.layout)?
                     // for the purpose of validity, consider foreign types to have
                     // alignment and size determined by the layout (size will be 0,
index cbb6408126a4559db23d577fb5ba8bcffda8119d..f2707969517fe132b93fed06c760cb3ed8dd303e 100644 (file)
@@ -16,6 +16,7 @@
 #![feature(decl_macro)]
 #![feature(drain_filter)]
 #![feature(exhaustive_patterns)]
+#![feature(iter_order_by)]
 #![cfg_attr(bootstrap, feature(never_type))]
 #![feature(specialization)]
 #![feature(try_trait)]
index 49f27a8117ece7978ed02ac8528a628a2b751f4f..a4c4c7ff616d9865ef3718ae228d8912bbb1ade1 100644 (file)
@@ -1,5 +1,5 @@
 //! Mono Item Collection
-//! ===========================
+//! ====================
 //!
 //! This module is responsible for discovering all items that will contribute to
 //! to code generation of the crate. The important part here is that it not only
 //! this is not implemented however: a mono item will be produced
 //! regardless of whether it is actually needed or not.
 
+use crate::monomorphize;
+
 use rustc::hir::{self, CodegenFnAttrFlags};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
-
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::interpret::{AllocId, ConstValue};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::{MonoItem, InstantiationMode};
 use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled};
-
-use crate::monomorphize;
 use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
 use rustc::util::common::time;
 
@@ -530,7 +529,6 @@ struct MirNeighborCollector<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
-
     fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
         debug!("visiting rvalue {:?}", *rvalue);
 
@@ -698,7 +696,7 @@ fn visit_place_base(&mut self,
                 }
             }
             PlaceBase::Local(_) => {
-                // Locals have no relevance for collector
+                // Locals have no relevance for collector.
             }
         }
     }
@@ -752,7 +750,7 @@ fn visit_instance_use<'tcx>(
         ty::InstanceDef::ReifyShim(..) |
         ty::InstanceDef::Virtual(..) |
         ty::InstanceDef::DropGlue(_, None) => {
-            // don't need to emit shim if we are calling directly.
+            // Don't need to emit shim if we are calling directly.
             if !is_direct_call {
                 output.push(create_fn_mono_item(instance));
             }
@@ -769,8 +767,8 @@ fn visit_instance_use<'tcx>(
     }
 }
 
-// Returns true if we should codegen an instance in the local crate.
-// Returns false if we can just link to the upstream crate and therefore don't
+// Returns `true` if we should codegen an instance in the local crate.
+// Returns `false` if we can just link to the upstream crate and therefore don't
 // need a mono item.
 fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
     let def_id = match instance.def {
@@ -786,24 +784,24 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx
     };
 
     if tcx.is_foreign_item(def_id) {
-        // We can always link to foreign items
+        // We can always link to foreign items.
         return false;
     }
 
     if def_id.is_local() {
-        // local items cannot be referred to locally without monomorphizing them locally
+        // Local items cannot be referred to locally without monomorphizing them locally.
         return true;
     }
 
     if tcx.is_reachable_non_generic(def_id) ||
        is_available_upstream_generic(tcx, def_id, instance.substs) {
         // We can link to the item in question, no instance needed
-        // in this crate
+        // in this crate.
         return false;
     }
 
     if !tcx.is_mir_available(def_id) {
-        bug!("Cannot create local mono-item for {:?}", def_id)
+        bug!("cannot create local mono-item for {:?}", def_id)
     }
     return true;
 
@@ -823,7 +821,7 @@ fn is_available_upstream_generic<'tcx>(
 
         // If this instance has non-erasable parameters, it cannot be a shared
         // monomorphization. Non-generic instances are already handled above
-        // by `is_reachable_non_generic()`
+        // by `is_reachable_non_generic()`.
         if substs.non_erasable_generics().next().is_none() {
             return false
         }
@@ -836,7 +834,7 @@ fn is_available_upstream_generic<'tcx>(
     }
 }
 
-/// For given pair of source and target type that occur in an unsizing coercion,
+/// For given pair of source and target type that occur in an unsizing coercion,
 /// this function finds the pair of types that determines the vtable linking
 /// them.
 ///
@@ -930,10 +928,9 @@ fn find_vtable_types_for_unsizing<'tcx>(
                     source_fields.len() == target_fields.len());
 
             find_vtable_types_for_unsizing(tcx,
-                                           source_fields[coerce_index].ty(tcx,
-                                                                          source_substs),
-                                           target_fields[coerce_index].ty(tcx,
-                                                                          target_substs))
+                source_fields[coerce_index].ty(tcx, source_substs),
+                target_fields[coerce_index].ty(tcx, target_substs)
+            )
         }
         _ => bug!("find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
                   source_ty,
@@ -975,7 +972,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
             output.extend(methods);
         }
 
-        // Also add the destructor
+        // Also add the destructor.
         visit_drop_use(tcx, impl_ty, false, output);
     }
 }
@@ -995,14 +992,14 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
     fn visit_item(&mut self, item: &'v hir::Item) {
         match item.kind {
             hir::ItemKind::ExternCrate(..) |
-            hir::ItemKind::Use(..)         |
-            hir::ItemKind::ForeignMod(..)  |
-            hir::ItemKind::TyAlias(..)          |
-            hir::ItemKind::Trait(..)       |
-            hir::ItemKind::TraitAlias(..)  |
+            hir::ItemKind::Use(..) |
+            hir::ItemKind::ForeignMod(..) |
+            hir::ItemKind::TyAlias(..) |
+            hir::ItemKind::Trait(..) |
+            hir::ItemKind::TraitAlias(..) |
             hir::ItemKind::OpaqueTy(..) |
-            hir::ItemKind::Mod(..)         => {
-                // Nothing to do, just keep recursing...
+            hir::ItemKind::Mod(..) => {
+                // Nothing to do, just keep recursing.
             }
 
             hir::ItemKind::Impl(..) => {
@@ -1075,7 +1072,7 @@ fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) {
                 let def_id = self.tcx.hir().local_def_id(ii.hir_id);
                 self.push_if_root(def_id);
             }
-            _ => { /* Nothing to do here */ }
+            _ => { /* nothing to do here */ }
         }
     }
 }
@@ -1095,7 +1092,7 @@ fn is_root(&self, def_id: DefId) -> bool {
         }
     }
 
-    /// If `def_id` represents a root, then push it onto the list of
+    /// If `def_id` represents a root, pushes it onto the list of
     /// outputs. (Note that all roots must be monomorphic.)
     fn push_if_root(&mut self, def_id: DefId) {
         if self.is_root(def_id) {
@@ -1217,7 +1214,7 @@ fn create_mono_items_for_default_impls<'tcx>(
     }
 }
 
-/// Scan the miri alloc in order to find function calls, closures, and drop-glue
+/// Scans the miri alloc in order to find function calls, closures, and drop-glue.
 fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec<MonoItem<'tcx>>) {
     let alloc_kind = tcx.alloc_map.lock().get(alloc_id);
     match alloc_kind {
@@ -1244,7 +1241,7 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec<Mon
     }
 }
 
-/// Scan the MIR in order to find function calls, closures, and drop-glue
+/// Scans the MIR in order to find function calls, closures, and drop-glue.
 fn collect_neighbours<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
index b36cf49ef1e45bde977c78035f1847414945d540..db8caed629c171670d2a683b20a42824ba5af6d6 100644 (file)
@@ -22,7 +22,7 @@ pub fn custom_coerce_unsize_info<'tcx>(
             tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap()
         }
         vtable => {
-            bug!("invalid CoerceUnsized vtable: {:?}", vtable);
+            bug!("invalid `CoerceUnsized` vtable: {:?}", vtable);
         }
     }
 }
index 2913d6e59eb3f21e7b17703b38c09175ab2b1920..17f5e3d4e47a982a990117e2cb680e505da784da 100644 (file)
@@ -152,7 +152,7 @@ fn temp_decl(mutability: Mutability, ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
-        is_user_variable: None,
+        local_info: LocalInfo::Other,
         is_block_tail: None,
     }
 }
index aad14299c1d94105532ea4004cf4d0e920377a9a..9ed1ca740b8e727e94853f61dc622743d94156a9 100644 (file)
@@ -2,6 +2,7 @@
 
 use rustc::mir::*;
 use rustc::ty::{self, Ty};
+use rustc::hir::def_id::DefId;
 use syntax_pos::DUMMY_SP;
 
 use super::{ConstKind, Item as ConstCx};
@@ -32,7 +33,7 @@ pub trait Qualif {
     /// of the type.
     fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool;
 
-    fn in_static(_cx: &ConstCx<'_, 'tcx>, _static: &Static<'tcx>) -> bool {
+    fn in_static(_cx: &ConstCx<'_, 'tcx>, _def_id: DefId) -> bool {
         // FIXME(eddyb) should we do anything here for value properties?
         false
     }
@@ -86,18 +87,9 @@ fn in_place(
                 projection: [],
             } => per_local(*local),
             PlaceRef {
-                base: PlaceBase::Static(box Static {
-                    kind: StaticKind::Promoted(..),
-                    ..
-                }),
+                base: PlaceBase::Static(_),
                 projection: [],
             } => bug!("qualifying already promoted MIR"),
-            PlaceRef {
-                base: PlaceBase::Static(static_),
-                projection: [],
-            } => {
-                Self::in_static(cx, static_)
-            },
             PlaceRef {
                 base: _,
                 projection: [.., _],
@@ -115,7 +107,9 @@ fn in_operand(
             Operand::Move(ref place) => Self::in_place(cx, per_local, place.as_ref()),
 
             Operand::Constant(ref constant) => {
-                if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val {
+                if let Some(static_) = constant.check_static_ptr(cx.tcx) {
+                    Self::in_static(cx, static_)
+                } else if let ty::ConstKind::Unevaluated(def_id, _) = constant.literal.val {
                     // Don't peek inside trait associated constants.
                     if cx.tcx.trait_of_item(def_id).is_some() {
                         Self::in_any_value_of_ty(cx, constant.literal.ty)
index 21e7c9ce565f0103d99903f5b85f0ca1775c8e37..bee37f69a5ec5640a6c8ab09637e310da058ac3e 100644 (file)
@@ -1,6 +1,6 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
-use rustc::hir::HirId;
+use rustc::hir::{HirId, def_id::DefId};
 use rustc::middle::lang_items;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::*;
@@ -288,6 +288,15 @@ pub fn check_op(&mut self, op: impl NonConstOp) -> CheckOpResult {
         let span = self.span;
         self.check_op_spanned(op, span)
     }
+
+    fn check_static(&mut self, def_id: DefId, span: Span) -> CheckOpResult {
+        let is_thread_local = self.tcx.has_attr(def_id, sym::thread_local);
+        if is_thread_local {
+            self.check_op_spanned(ops::ThreadLocalAccess, span)
+        } else {
+            self.check_op_spanned(ops::StaticAccess, span)
+        }
+    }
 }
 
 impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
@@ -408,17 +417,21 @@ fn visit_place_base(
 
         match place_base {
             PlaceBase::Local(_) => {}
-            PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => {
+            PlaceBase::Static(_) => {
                 bug!("Promotion must be run after const validation");
             }
+        }
+    }
 
-            PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => {
-                let is_thread_local = self.tcx.has_attr(*def_id, sym::thread_local);
-                if is_thread_local {
-                    self.check_op(ops::ThreadLocalAccess);
-                } else if self.const_kind() != ConstKind::Static || !context.is_mutating_use() {
-                    self.check_op(ops::StaticAccess);
-                }
+    fn visit_operand(
+        &mut self,
+        op: &Operand<'tcx>,
+        location: Location,
+    ) {
+        self.super_operand(op, location);
+        if let Operand::Constant(c) = op {
+            if let Some(def_id) = c.check_static_ptr(self.tcx) {
+                self.check_static(def_id, self.span);
             }
         }
     }
@@ -497,14 +510,24 @@ fn visit_projection_elem(
 
         match elem {
             ProjectionElem::Deref => {
-                if context.is_mutating_use() {
-                    self.check_op(ops::MutDeref);
-                }
-
                 let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
                 if let ty::RawPtr(_) = base_ty.kind {
+                    if proj_base.is_empty() {
+                        if let (PlaceBase::Local(local), []) = (place_base, proj_base) {
+                            let decl = &self.body.local_decls[*local];
+                            if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
+                                let span = decl.source_info.span;
+                                self.check_static(def_id, span);
+                                return;
+                            }
+                        }
+                    }
                     self.check_op(ops::RawPtrDeref);
                 }
+
+                if context.is_mutating_use() {
+                    self.check_op(ops::MutDeref);
+                }
             }
 
             ProjectionElem::ConstantIndex {..} |
index 9374109c82e41398c7feab65a438f3546d5ce23d..b7cc4e9fcf66cb772cfe199f12c833343c358014 100644 (file)
@@ -206,25 +206,10 @@ fn visit_place(&mut self,
                 // Locals are safe.
             }
             PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => {
-                bug!("unsafety checking should happen before promotion")
+                bug!("unsafety checking should happen before promotion");
             }
-            PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => {
-                if self.tcx.is_mutable_static(def_id) {
-                    self.require_unsafe(
-                        "use of mutable static",
-                        "mutable statics can be mutated by multiple threads: aliasing \
-                        violations or data races will cause undefined behavior",
-                        UnsafetyViolationKind::General,
-                    );
-                } else if self.tcx.is_foreign_item(def_id) {
-                    self.require_unsafe(
-                        "use of extern static",
-                        "extern statics are not controlled by the Rust type system: \
-                        invalid data, aliasing violations or data races will cause \
-                        undefined behavior",
-                        UnsafetyViolationKind::General,
-                    );
-                }
+            PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => {
+                bug!("StaticKind::Static should not exist");
             }
         }
 
@@ -264,11 +249,31 @@ fn visit_place(&mut self,
             }
             let old_source_info = self.source_info;
             if let (PlaceBase::Local(local), []) = (&place.base, proj_base) {
-                if self.body.local_decls[*local].internal {
+                let decl = &self.body.local_decls[*local];
+                if decl.internal {
                     // Internal locals are used in the `move_val_init` desugaring.
                     // We want to check unsafety against the source info of the
                     // desugaring, rather than the source info of the RHS.
                     self.source_info = self.body.local_decls[*local].source_info;
+                } else if let LocalInfo::StaticRef { def_id, .. } = decl.local_info {
+                    if self.tcx.is_mutable_static(def_id) {
+                        self.require_unsafe(
+                            "use of mutable static",
+                            "mutable statics can be mutated by multiple threads: aliasing \
+                        violations or data races will cause undefined behavior",
+                            UnsafetyViolationKind::General,
+                        );
+                        return;
+                    } else if self.tcx.is_foreign_item(def_id) {
+                        self.require_unsafe(
+                            "use of extern static",
+                            "extern statics are not controlled by the Rust type system: \
+                        invalid data, aliasing violations or data races will cause \
+                        undefined behavior",
+                            UnsafetyViolationKind::General,
+                        );
+                        return;
+                    }
                 }
             }
             let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty;
index 37c239001a505f429a486a662fd11598a9078429..524b6b087908ce4b7ac57ac5e5e0ba79cac3a6f8 100644 (file)
@@ -432,7 +432,7 @@ fn replace_result_variable<'tcx>(
         visibility_scope: source_info.scope,
         internal: false,
         is_block_tail: None,
-        is_user_variable: None,
+        local_info: LocalInfo::Other
     };
     let new_ret_local = Local::new(body.local_decls.len());
     body.local_decls.push(new_ret);
@@ -967,7 +967,7 @@ fn create_generator_drop_shim<'tcx>(
         visibility_scope: source_info.scope,
         internal: false,
         is_block_tail: None,
-        is_user_variable: None,
+        local_info: LocalInfo::Other
     };
 
     make_generator_state_argument_indirect(tcx, def_id, &mut body);
@@ -985,7 +985,7 @@ fn create_generator_drop_shim<'tcx>(
         visibility_scope: source_info.scope,
         internal: false,
         is_block_tail: None,
-        is_user_variable: None,
+        local_info: LocalInfo::Other
     };
     if tcx.sess.opts.debugging_opts.mir_emit_retag {
         // Alias tracking must know we changed the type
index 897e37858a68edec0f07345321c5bc75a6ca1a03..2b2b52971ef0f7fde5ff9b06e89838534de944ee 100644 (file)
@@ -18,6 +18,7 @@
 pub mod check_consts;
 pub mod check_unsafety;
 pub mod simplify_branches;
+pub mod simplify_try;
 pub mod simplify;
 pub mod erase_regions;
 pub mod no_landing_pads;
@@ -305,6 +306,9 @@ fn run_optimization_passes<'tcx>(
         &copy_prop::CopyPropagation,
         &simplify_branches::SimplifyBranches::new("after-copy-prop"),
         &remove_noop_landing_pads::RemoveNoopLandingPads,
+        &simplify::SimplifyCfg::new("after-remove-noop-landing-pads"),
+        &simplify_try::SimplifyArmIdentity,
+        &simplify_try::SimplifyBranchSame,
         &simplify::SimplifyCfg::new("final"),
         &simplify::SimplifyLocals,
 
index c79d382a37480a9c6a5a1787bc458036a570077a..86ecfbb4fbea59af92f71b2bb0bf1ca70ba89b5d 100644 (file)
@@ -512,34 +512,9 @@ fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable>
                 projection: [],
             } => self.validate_local(*local),
             PlaceRef {
-                base: PlaceBase::Static(box Static {
-                    kind: StaticKind::Promoted { .. },
-                    ..
-                }),
+                base: PlaceBase::Static(_),
                 projection: [],
             } => bug!("qualifying already promoted MIR"),
-            PlaceRef {
-                base: PlaceBase::Static(box Static {
-                    kind: StaticKind::Static,
-                    def_id,
-                    ..
-                }),
-                projection: [],
-            } => {
-                // Only allow statics (not consts) to refer to other statics.
-                // FIXME(eddyb) does this matter at all for promotion?
-                let is_static = self.const_kind.map_or(false, |k| k.is_static());
-                if !is_static {
-                    return Err(Unpromotable);
-                }
-
-                let is_thread_local = self.tcx.has_attr(*def_id, sym::thread_local);
-                if is_thread_local {
-                    return Err(Unpromotable);
-                }
-
-                Ok(())
-            }
             PlaceRef {
                 base: _,
                 projection: [proj_base @ .., elem],
@@ -584,7 +559,23 @@ fn validate_operand(&self, operand: &Operand<'tcx>) -> Result<(), Unpromotable>
 
             // The qualifs for a constant (e.g. `HasMutInterior`) are checked in
             // `validate_rvalue` upon access.
-            Operand::Constant(_) => Ok(()),
+            Operand::Constant(c) => {
+                if let Some(def_id) = c.check_static_ptr(self.tcx) {
+                    // Only allow statics (not consts) to refer to other statics.
+                    // FIXME(eddyb) does this matter at all for promotion?
+                    let is_static = self.const_kind.map_or(false, |k| k.is_static());
+                    if !is_static {
+                        return Err(Unpromotable);
+                    }
+
+                    let is_thread_local = self.tcx.has_attr(def_id, sym::thread_local);
+                    if is_thread_local {
+                        return Err(Unpromotable);
+                    }
+                }
+
+                Ok(())
+            },
         }
     }
 
index 2bc44d2e5c142d3ee7ae901b1b73b61a682cc4bd..71f13c169d41eb12d278495f3a3581cc33864288 100644 (file)
@@ -251,7 +251,10 @@ fn check_operand(
         Operand::Move(place) | Operand::Copy(place) => {
             check_place(tcx, place, span, def_id, body)
         }
-        Operand::Constant(_) => Ok(()),
+        Operand::Constant(c) => match c.check_static_ptr(tcx) {
+            Some(_) => Err((span, "cannot access `static` items in const fn".into())),
+            None => Ok(()),
+        },
     }
 }
 
@@ -288,13 +291,7 @@ fn check_place(
         }
     }
 
-    match place.base {
-        PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => {
-            Err((span, "cannot access `static` items in const fn".into()))
-        }
-        PlaceBase::Local(_)
-        | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => Ok(()),
-    }
+    Ok(())
 }
 
 /// Returns whether `allow_internal_unstable(..., <feature_gate>, ...)` is present.
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
new file mode 100644 (file)
index 0000000..de5c2eb
--- /dev/null
@@ -0,0 +1,201 @@
+//! The general point of the optimizations provided here is to simplify something like:
+//!
+//! ```rust
+//! match x {
+//!     Ok(x) => Ok(x),
+//!     Err(x) => Err(x)
+//! }
+//! ```
+//!
+//! into just `x`.
+
+use crate::transform::{MirPass, MirSource, simplify};
+use rustc::ty::{TyCtxt, Ty};
+use rustc::mir::*;
+use rustc_target::abi::VariantIdx;
+use itertools::Itertools as _;
+
+/// Simplifies arms of form `Variant(x) => Variant(x)` to just a move.
+///
+/// This is done by transforming basic blocks where the statements match:
+///
+/// ```rust
+/// _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY );
+/// ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP;
+/// discriminant(_LOCAL_0) = VAR_IDX;
+/// ```
+///
+/// into:
+///
+/// ```rust
+/// _LOCAL_0 = move _LOCAL_1
+/// ```
+pub struct SimplifyArmIdentity;
+
+impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
+    fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        for bb in body.basic_blocks_mut() {
+            // Need 3 statements:
+            let (s0, s1, s2) = match &mut *bb.statements {
+                [s0, s1, s2] => (s0, s1, s2),
+                _ => continue,
+            };
+
+            // Pattern match on the form we want:
+            let (local_tmp_s0, local_1, vf_s0) = match match_get_variant_field(s0) {
+                None => continue,
+                Some(x) => x,
+            };
+            let (local_tmp_s1, local_0, vf_s1) = match match_set_variant_field(s1) {
+                None => continue,
+                Some(x) => x,
+            };
+            if local_tmp_s0 != local_tmp_s1
+                || vf_s0 != vf_s1
+                || Some((local_0, vf_s0.var_idx)) != match_set_discr(s2)
+            {
+                continue;
+            }
+
+            // Right shape; transform!
+            match &mut s0.kind {
+                StatementKind::Assign(box (place, rvalue)) => {
+                    *place = local_0.into();
+                    *rvalue = Rvalue::Use(Operand::Move(local_1.into()));
+                }
+                _ => unreachable!(),
+            }
+            s1.make_nop();
+            s2.make_nop();
+        }
+    }
+}
+
+/// Match on:
+/// ```rust
+/// _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY);
+/// ```
+fn match_get_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
+    match &stmt.kind {
+        StatementKind::Assign(box (place_into, rvalue_from)) => match rvalue_from {
+            Rvalue::Use(Operand::Copy(pf)) | Rvalue::Use(Operand::Move(pf)) => {
+                let local_into = place_into.as_local()?;
+                let (local_from, vf) = match_variant_field_place(&pf)?;
+                Some((local_into, local_from, vf))
+            }
+            _ => None,
+        },
+        _ => None,
+    }
+}
+
+/// Match on:
+/// ```rust
+/// ((_LOCAL_FROM as Variant).FIELD: TY) = move _LOCAL_INTO;
+/// ```
+fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
+    match &stmt.kind {
+        StatementKind::Assign(box (place_from, rvalue_into)) => match rvalue_into {
+            Rvalue::Use(Operand::Move(place_into)) => {
+                let local_into = place_into.as_local()?;
+                let (local_from, vf) = match_variant_field_place(&place_from)?;
+                Some((local_into, local_from, vf))
+            }
+            _ => None,
+        },
+        _ => None,
+    }
+}
+
+/// Match on:
+/// ```rust
+/// discriminant(_LOCAL_TO_SET) = VAR_IDX;
+/// ```
+fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)> {
+    match &stmt.kind {
+        StatementKind::SetDiscriminant { place, variant_index } => Some((
+            place.as_local()?,
+            *variant_index
+        )),
+        _ => None,
+    }
+}
+
+#[derive(PartialEq)]
+struct VarField<'tcx> {
+    field: Field,
+    field_ty: Ty<'tcx>,
+    var_idx: VariantIdx,
+}
+
+/// Match on `((_LOCAL as Variant).FIELD: TY)`.
+fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarField<'tcx>)> {
+    match place.as_ref() {
+        PlaceRef {
+            base: &PlaceBase::Local(local),
+            projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)],
+        } => Some((local, VarField { field, field_ty: ty, var_idx })),
+        _ => None,
+    }
+}
+
+/// Simplifies `SwitchInt(_) -> [targets]`,
+/// where all the `targets` have the same form,
+/// into `goto -> target_first`.
+pub struct SimplifyBranchSame;
+
+impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
+    fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        let mut did_remove_blocks = false;
+        let bbs = body.basic_blocks_mut();
+        for bb_idx in bbs.indices() {
+            let targets = match &bbs[bb_idx].terminator().kind {
+                TerminatorKind::SwitchInt { targets, .. } => targets,
+                _ => continue,
+            };
+
+            let mut iter_bbs_reachable = targets
+                .iter()
+                .map(|idx| (*idx, &bbs[*idx]))
+                .filter(|(_, bb)| {
+                    // Reaching `unreachable` is UB so assume it doesn't happen.
+                    bb.terminator().kind != TerminatorKind::Unreachable
+                    // But `asm!(...)` could abort the program,
+                    // so we cannot assume that the `unreachable` terminator itself is reachable.
+                    // FIXME(Centril): use a normalization pass instead of a check.
+                    || bb.statements.iter().any(|stmt| match stmt.kind {
+                        StatementKind::InlineAsm(..) => true,
+                        _ => false,
+                    })
+                })
+                .peekable();
+
+            // We want to `goto -> bb_first`.
+            let bb_first = iter_bbs_reachable
+                .peek()
+                .map(|(idx, _)| *idx)
+                .unwrap_or(targets[0]);
+
+            // All successor basic blocks should have the exact same form.
+            let all_successors_equivalent = iter_bbs_reachable
+                .map(|(_, bb)| bb)
+                .tuple_windows()
+                .all(|(bb_l, bb_r)| {
+                    bb_l.is_cleanup == bb_r.is_cleanup
+                    && bb_l.terminator().kind == bb_r.terminator().kind
+                    && bb_l.statements.iter().eq_by(&bb_r.statements, |x, y| x.kind == y.kind)
+                });
+
+            if all_successors_equivalent {
+                // Replace `SwitchInt(..) -> [bb_first, ..];` with a `goto -> bb_first;`.
+                bbs[bb_idx].terminator_mut().kind = TerminatorKind::Goto { target: bb_first };
+                did_remove_blocks = true;
+            }
+        }
+
+        if did_remove_blocks {
+            // We have dead blocks now, so remove those.
+            simplify::remove_dead_blocks(body);
+        }
+    }
+}
diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs
new file mode 100644 (file)
index 0000000..7ce555e
--- /dev/null
@@ -0,0 +1,375 @@
+//! Process the potential `cfg` attributes on a module.
+//! Also determine if the module should be included in this configuration.
+//!
+//! This module properly belongs in syntax_expand, but for now it's tied into
+//! parsing, so we leave it here to avoid complicated out-of-line dependencies.
+//!
+//! A principled solution to this wrong location would be to implement [#64197].
+//!
+//! [#64197]: https://github.com/rust-lang/rust/issues/64197
+
+use crate::validate_attr;
+use syntax::attr::HasAttrs;
+use syntax::feature_gate::{
+    feature_err,
+    EXPLAIN_STMT_ATTR_SYNTAX,
+    Features,
+    get_features,
+    GateIssue,
+};
+use syntax::attr;
+use syntax::ast;
+use syntax::edition::Edition;
+use syntax::mut_visit::*;
+use syntax::ptr::P;
+use syntax::sess::ParseSess;
+use syntax::util::map_in_place::MapInPlace;
+use syntax_pos::symbol::sym;
+
+use errors::Applicability;
+use smallvec::SmallVec;
+
+/// A folder that strips out items that do not belong in the current configuration.
+pub struct StripUnconfigured<'a> {
+    pub sess: &'a ParseSess,
+    pub features: Option<&'a Features>,
+}
+
+// `cfg_attr`-process the crate's attributes and compute the crate's features.
+pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition,
+                allow_features: &Option<Vec<String>>) -> (ast::Crate, Features) {
+    let features;
+    {
+        let mut strip_unconfigured = StripUnconfigured {
+            sess,
+            features: None,
+        };
+
+        let unconfigured_attrs = krate.attrs.clone();
+        let err_count = sess.span_diagnostic.err_count();
+        if let Some(attrs) = strip_unconfigured.configure(krate.attrs) {
+            krate.attrs = attrs;
+        } else { // the entire crate is unconfigured
+            krate.attrs = Vec::new();
+            krate.module.items = Vec::new();
+            return (krate, Features::new());
+        }
+
+        features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features);
+
+        // Avoid reconfiguring malformed `cfg_attr`s
+        if err_count == sess.span_diagnostic.err_count() {
+            strip_unconfigured.features = Some(&features);
+            strip_unconfigured.configure(unconfigured_attrs);
+        }
+    }
+
+    (krate, features)
+}
+
+#[macro_export]
+macro_rules! configure {
+    ($this:ident, $node:ident) => {
+        match $this.configure($node) {
+            Some(node) => node,
+            None => return Default::default(),
+        }
+    }
+}
+
+impl<'a> StripUnconfigured<'a> {
+    pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
+        self.process_cfg_attrs(&mut node);
+        if self.in_cfg(node.attrs()) { Some(node) } else { None }
+    }
+
+    /// Parse and expand all `cfg_attr` attributes into a list of attributes
+    /// that are within each `cfg_attr` that has a true configuration predicate.
+    ///
+    /// Gives compiler warnigns if any `cfg_attr` does not contain any
+    /// attributes and is in the original source code. Gives compiler errors if
+    /// the syntax of any `cfg_attr` is incorrect.
+    pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: &mut T) {
+        node.visit_attrs(|attrs| {
+            attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
+        });
+    }
+
+    /// Parse and expand a single `cfg_attr` attribute into a list of attributes
+    /// when the configuration predicate is true, or otherwise expand into an
+    /// empty list of attributes.
+    ///
+    /// Gives a compiler warning when the `cfg_attr` contains no attributes and
+    /// is in the original source file. Gives a compiler error if the syntax of
+    /// the attribute is incorrect.
+    fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
+        if !attr.has_name(sym::cfg_attr) {
+            return vec![attr];
+        }
+        if attr.get_normal_item().tokens.is_empty() {
+            self.sess.span_diagnostic
+                .struct_span_err(
+                    attr.span,
+                    "malformed `cfg_attr` attribute input",
+                ).span_suggestion(
+                    attr.span,
+                    "missing condition and attribute",
+                    "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(),
+                    Applicability::HasPlaceholders,
+                ).note("for more information, visit \
+                       <https://doc.rust-lang.org/reference/conditional-compilation.html\
+                       #the-cfg_attr-attribute>")
+                .emit();
+            return vec![];
+        }
+
+        let res = crate::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr());
+        let (cfg_predicate, expanded_attrs) = match res {
+            Ok(result) => result,
+            Err(mut e) => {
+                e.emit();
+                return vec![];
+            }
+        };
+
+        // Lint on zero attributes in source.
+        if expanded_attrs.is_empty() {
+            return vec![attr];
+        }
+
+        // At this point we know the attribute is considered used.
+        attr::mark_used(&attr);
+
+        if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
+            // We call `process_cfg_attr` recursively in case there's a
+            // `cfg_attr` inside of another `cfg_attr`. E.g.
+            //  `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
+            expanded_attrs.into_iter()
+            .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item(
+                attr.style,
+                item,
+                span,
+            )))
+            .collect()
+        } else {
+            vec![]
+        }
+    }
+
+    /// Determines if a node with the given attributes should be included in this configuration.
+    pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool {
+        attrs.iter().all(|attr| {
+            if !is_cfg(attr) {
+                return true;
+            }
+
+            let error = |span, msg, suggestion: &str| {
+                let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
+                if !suggestion.is_empty() {
+                    err.span_suggestion(
+                        span,
+                        "expected syntax is",
+                        suggestion.into(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                err.emit();
+                true
+            };
+
+            let meta_item = match validate_attr::parse_meta(self.sess, attr) {
+                Ok(meta_item) => meta_item,
+                Err(mut err) => { err.emit(); return true; }
+            };
+            let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() {
+                nested_meta_items
+            } else {
+                return error(meta_item.span, "`cfg` is not followed by parentheses",
+                                             "cfg(/* predicate */)");
+            };
+
+            if nested_meta_items.is_empty() {
+                return error(meta_item.span, "`cfg` predicate is not specified", "");
+            } else if nested_meta_items.len() > 1 {
+                return error(nested_meta_items.last().unwrap().span(),
+                             "multiple `cfg` predicates are specified", "");
+            }
+
+            match nested_meta_items[0].meta_item() {
+                Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
+                None => error(nested_meta_items[0].span(),
+                              "`cfg` predicate key cannot be a literal", ""),
+            }
+        })
+    }
+
+    /// Visit attributes on expression and statements (but not attributes on items in blocks).
+    fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
+        // flag the offending attributes
+        for attr in attrs.iter() {
+            self.maybe_emit_expr_attr_err(attr);
+        }
+    }
+
+    /// If attributes are not allowed on expressions, emit an error for `attr`
+    pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) {
+        if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
+            let mut err = feature_err(self.sess,
+                                      sym::stmt_expr_attributes,
+                                      attr.span,
+                                      GateIssue::Language,
+                                      EXPLAIN_STMT_ATTR_SYNTAX);
+
+            if attr.is_doc_comment() {
+                err.help("`///` is for documentation comments. For a plain comment, use `//`.");
+            }
+
+            err.emit();
+        }
+    }
+
+    pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
+        let ast::ForeignMod { abi: _, items } = foreign_mod;
+        items.flat_map_in_place(|item| self.configure(item));
+    }
+
+    pub fn configure_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
+        params.flat_map_in_place(|param| self.configure(param));
+    }
+
+    fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
+        match vdata {
+            ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) =>
+                fields.flat_map_in_place(|field| self.configure(field)),
+            ast::VariantData::Unit(_) => {}
+        }
+    }
+
+    pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) {
+        match item {
+            ast::ItemKind::Struct(def, _generics) |
+            ast::ItemKind::Union(def, _generics) => self.configure_variant_data(def),
+            ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
+                variants.flat_map_in_place(|variant| self.configure(variant));
+                for variant in variants {
+                    self.configure_variant_data(&mut variant.data);
+                }
+            }
+            _ => {}
+        }
+    }
+
+    pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) {
+        match expr_kind {
+            ast::ExprKind::Match(_m, arms) => {
+                arms.flat_map_in_place(|arm| self.configure(arm));
+            }
+            ast::ExprKind::Struct(_path, fields, _base) => {
+                fields.flat_map_in_place(|field| self.configure(field));
+            }
+            _ => {}
+        }
+    }
+
+    pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
+        self.visit_expr_attrs(expr.attrs());
+
+        // If an expr is valid to cfg away it will have been removed by the
+        // outer stmt or expression folder before descending in here.
+        // Anything else is always required, and thus has to error out
+        // in case of a cfg attr.
+        //
+        // N.B., this is intentionally not part of the visit_expr() function
+        //     in order for filter_map_expr() to be able to avoid this check
+        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
+            let msg = "removing an expression is not supported in this position";
+            self.sess.span_diagnostic.span_err(attr.span, msg);
+        }
+
+        self.process_cfg_attrs(expr)
+    }
+
+    pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
+        if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind {
+            fields.flat_map_in_place(|field| self.configure(field));
+        }
+    }
+
+    pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
+        fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
+    }
+}
+
+impl<'a> MutVisitor for StripUnconfigured<'a> {
+    fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
+        self.configure_foreign_mod(foreign_mod);
+        noop_visit_foreign_mod(foreign_mod, self);
+    }
+
+    fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
+        self.configure_item_kind(item);
+        noop_visit_item_kind(item, self);
+    }
+
+    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
+        self.configure_expr(expr);
+        self.configure_expr_kind(&mut expr.kind);
+        noop_visit_expr(expr, self);
+    }
+
+    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
+        let mut expr = configure!(self, expr);
+        self.configure_expr_kind(&mut expr.kind);
+        noop_visit_expr(&mut expr, self);
+        Some(expr)
+    }
+
+    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
+        noop_flat_map_stmt(configure!(self, stmt), self)
+    }
+
+    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+        noop_flat_map_item(configure!(self, item), self)
+    }
+
+    fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
+        noop_flat_map_impl_item(configure!(self, item), self)
+    }
+
+    fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
+        noop_flat_map_trait_item(configure!(self, item), self)
+    }
+
+    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
+        // Don't configure interpolated AST (cf. issue #34171).
+        // Interpolated AST will get configured once the surrounding tokens are parsed.
+    }
+
+    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
+        self.configure_pat(pat);
+        noop_visit_pat(pat, self)
+    }
+
+    fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
+        self.configure_fn_decl(&mut fn_decl);
+        noop_visit_fn_decl(fn_decl, self);
+    }
+}
+
+fn is_cfg(attr: &ast::Attribute) -> bool {
+    attr.check_name(sym::cfg)
+}
+
+/// Process the potential `cfg` attributes on a module.
+/// Also determine if the module should be included in this configuration.
+pub fn process_configure_mod(
+    sess: &ParseSess,
+    cfg_mods: bool,
+    attrs: &[ast::Attribute],
+) -> (bool, Vec<ast::Attribute>) {
+    // Don't perform gated feature checking.
+    let mut strip_unconfigured = StripUnconfigured { sess, features: None };
+    let mut attrs = attrs.to_owned();
+    strip_unconfigured.process_cfg_attrs(&mut attrs);
+    (!cfg_mods || strip_unconfigured.in_cfg(&attrs), attrs)
+}
index 3a983404220a4a60fbbd154c1efb4fd23477ef40..1215c7a199a98816d90e73fb3ef5f57f31d78764 100644 (file)
@@ -25,6 +25,8 @@
 use parser::{Parser, emit_unclosed_delims, make_unclosed_delims_error};
 pub mod lexer;
 pub mod validate_attr;
+#[macro_use]
+pub mod config;
 
 #[derive(Clone)]
 pub struct Directory<'a> {
index 5036759da3f0cf626180d6581362c8591d639d29..eab35a86c69e45b8dd4ed13ce463e17f071bdd68 100644 (file)
@@ -1189,26 +1189,6 @@ pub(super) fn recover_closing_delimiter(
         }
     }
 
-    /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid.
-    pub(super) fn eat_bad_pub(&mut self) {
-        // When `unclosed_delims` is populated, it means that the code being parsed is already
-        // quite malformed, which might mean that, for example, a pub struct definition could be
-        // parsed as being a trait item, which is invalid and this error would trigger
-        // unconditionally, resulting in misleading diagnostics. Because of this, we only attempt
-        // this nice to have recovery for code that is otherwise well formed.
-        if self.token.is_keyword(kw::Pub) && self.unclosed_delims.is_empty() {
-            match self.parse_visibility(false) {
-                Ok(vis) => {
-                    self.diagnostic()
-                        .struct_span_err(vis.span, "unnecessary visibility qualifier")
-                        .span_label(vis.span, "`pub` not permitted here")
-                        .emit();
-                }
-                Err(mut err) => err.emit(),
-            }
-        }
-    }
-
     /// Eats tokens until we can be relatively sure we reached the end of the
     /// statement. This is something of a best-effort heuristic.
     ///
index 20b96d5cd62f6a6060fd7303526afe1d8ff1c31b..13645e7144a9bfc72ad8f9c2858d0b9cdc7376c3 100644 (file)
@@ -1,4 +1,4 @@
-use super::{Parser, PathStyle};
+use super::{Parser, PathStyle, FollowedByType};
 use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim};
 
 use crate::maybe_whole;
@@ -87,7 +87,7 @@ fn parse_item_implementation(
 
         let lo = self.token.span;
 
-        let vis = self.parse_visibility(false)?;
+        let vis = self.parse_visibility(FollowedByType::No)?;
 
         if self.eat_keyword(kw::Use) {
             // USE ITEM
@@ -696,7 +696,7 @@ fn parse_impl_item_(
         mut attrs: Vec<Attribute>,
     ) -> PResult<'a, ImplItem> {
         let lo = self.token.span;
-        let vis = self.parse_visibility(false)?;
+        let vis = self.parse_visibility(FollowedByType::No)?;
         let defaultness = self.parse_defaultness();
         let (name, kind, generics) = if self.eat_keyword(kw::Type) {
             let (name, ty, generics) = self.parse_type_alias()?;
@@ -883,7 +883,7 @@ fn parse_trait_item_(
         mut attrs: Vec<Attribute>,
     ) -> PResult<'a, TraitItem> {
         let lo = self.token.span;
-        self.eat_bad_pub();
+        let vis = self.parse_visibility(FollowedByType::No)?;
         let (name, kind, generics) = if self.eat_keyword(kw::Type) {
             self.parse_trait_item_assoc_ty()?
         } else if self.is_const_item() {
@@ -899,6 +899,7 @@ fn parse_trait_item_(
             id: DUMMY_NODE_ID,
             ident: name,
             attrs,
+            vis,
             generics,
             kind,
             span: lo.to(self.prev_span),
@@ -1129,7 +1130,7 @@ pub fn parse_foreign_item(&mut self, extern_sp: Span) -> PResult<'a, ForeignItem
 
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
-        let visibility = self.parse_visibility(false)?;
+        let visibility = self.parse_visibility(FollowedByType::No)?;
 
         // FOREIGN STATIC ITEM
         // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
@@ -1339,7 +1340,7 @@ fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
             let variant_attrs = self.parse_outer_attributes()?;
             let vlo = self.token.span;
 
-            self.eat_bad_pub();
+            let vis = self.parse_visibility(FollowedByType::No)?;
             let ident = self.parse_ident()?;
 
             let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
@@ -1366,6 +1367,7 @@ fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
 
             let vr = ast::Variant {
                 ident,
+                vis,
                 id: DUMMY_NODE_ID,
                 attrs: variant_attrs,
                 data: struct_def,
@@ -1519,7 +1521,7 @@ fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
         self.parse_paren_comma_seq(|p| {
             let attrs = p.parse_outer_attributes()?;
             let lo = p.token.span;
-            let vis = p.parse_visibility(true)?;
+            let vis = p.parse_visibility(FollowedByType::Yes)?;
             let ty = p.parse_ty()?;
             Ok(StructField {
                 span: lo.to(ty.span),
@@ -1537,7 +1539,7 @@ fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
     fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
-        let vis = self.parse_visibility(false)?;
+        let vis = self.parse_visibility(FollowedByType::No)?;
         self.parse_single_struct_field(lo, vis, attrs)
     }
 
index d5ec46114980659ad45b76ce1ae95ec76b08b710..d810117662c655c0c60287f479957efd69e67181 100644 (file)
@@ -348,6 +348,8 @@ fn none() -> SeqSep {
     }
 }
 
+pub enum FollowedByType { Yes, No }
+
 impl<'a> Parser<'a> {
     pub fn new(
         sess: &'a ParseSess,
@@ -1120,7 +1122,7 @@ fn is_crate_vis(&self) -> bool {
     /// If the following element can't be a tuple (i.e., it's a function definition), then
     /// it's not a tuple struct field), and the contents within the parentheses isn't valid,
     /// so emit a proper diagnostic.
-    pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> {
+    pub fn parse_visibility(&mut self, fbt: FollowedByType) -> PResult<'a, Visibility> {
         maybe_whole!(self, NtVis, |x| x);
 
         self.expected_tokens.push(TokenType::Keyword(kw::Crate));
@@ -1175,7 +1177,9 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
                     id: ast::DUMMY_NODE_ID,
                 };
                 return Ok(respan(lo.to(self.prev_span), vis));
-            } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct.
+            } else if let FollowedByType::No = fbt {
+                // Provide this diagnostic if a type cannot follow;
+                // in particular, if this is not a tuple struct.
                 self.recover_incorrect_vis_restriction()?;
                 // Emit diagnostic, but continue with public visibility.
             }
index 3110f15e80b6ed80a49693dbc14b6ca66f99855c..59d7c2b423972c895d4fa1e70cf592286e472e7a 100644 (file)
@@ -40,8 +40,7 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
 
     /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
     pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> {
-        // HACK(Centril): See documentation on `ParseSess::process_cfg_mod`.
-        let (in_cfg, outer_attrs) = (self.sess.process_cfg_mod)(
+        let (in_cfg, outer_attrs) = crate::config::process_configure_mod(
             self.sess,
             self.cfg_mods,
             outer_attrs,
index c4032ec5dd0dba67110440e051d6d1c6bc7d8bfd..e189b7175f91dc3eca52de8dfb84c7b9fe2f970d 100644 (file)
@@ -529,6 +529,7 @@ fn visit_item(&mut self, item: &'a Item) {
             }
             ItemKind::Enum(ref def, _) => {
                 for variant in &def.variants {
+                    self.invalid_visibility(&variant.vis, None);
                     for field in variant.data.fields() {
                         self.invalid_visibility(&field.vis, None);
                     }
@@ -751,6 +752,11 @@ fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         }
         visit::walk_impl_item(self, ii);
     }
+
+    fn visit_trait_item(&mut self, ti: &'a TraitItem) {
+        self.invalid_visibility(&ti.vis, None);
+        visit::walk_trait_item(self, ti);
+    }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
index f48df7faea25aa74f952437c729233772ca1ad34..666c482c680462bb6ff213a0b0658004c8919656 100644 (file)
@@ -69,6 +69,7 @@ fn descr(self) -> &'static str {
 /// Denotes whether the context for the set of already bound bindings is a `Product`
 /// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
 /// See those functions for more information.
+#[derive(PartialEq)]
 enum PatBoundCtx {
     /// A product pattern context, e.g., `Variant(a, b)`.
     Product,
@@ -1417,21 +1418,12 @@ fn fresh_binding(
         // later passes make about or-patterns.)
         let ident = ident.modern_and_legacy();
 
-        // Walk outwards the stack of products / or-patterns and
-        // find out if the identifier has been bound in any of these.
-        let mut already_bound_and = false;
-        let mut already_bound_or = false;
-        for (is_sum, set) in bindings.iter_mut().rev() {
-            match (is_sum, set.get(&ident).cloned()) {
-                // Already bound in a product pattern, e.g. `(a, a)` which is not allowed.
-                (PatBoundCtx::Product, Some(..)) => already_bound_and = true,
-                // Already bound in an or-pattern, e.g. `V1(a) | V2(a)`.
-                // This is *required* for consistency which is checked later.
-                (PatBoundCtx::Or, Some(..)) => already_bound_or = true,
-                // Not already bound here.
-                _ => {}
-            }
-        }
+        let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident));
+        // Already bound in a product pattern? e.g. `(a, a)` which is not allowed.
+        let already_bound_and = bound_iter.clone().any(|(ctx, _)| *ctx == PatBoundCtx::Product);
+        // Already bound in an or-pattern? e.g. `V1(a) | V2(a)`.
+        // This is *required* for consistency which is checked later.
+        let already_bound_or = bound_iter.any(|(ctx, _)| *ctx == PatBoundCtx::Or);
 
         if already_bound_and {
             // Overlap in a product pattern somewhere; report an error.
index c73d0adea38da79490443e2d073a25ee3115206e..0e0732490fbbdc1ce201c3cb438b8e1437f0eaad 100644 (file)
@@ -12,6 +12,7 @@ path = "lib.rs"
 bitflags = "1.2.1"
 log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../libserialize", package = "serialize" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_index = { path = "../librustc_index" }
index 2d7e05037ba0d7f99fb404731c609e914fbeb75e..ac781819cc35e7e652a28dda3bc60f7ffb0a2515 100644 (file)
@@ -6,6 +6,7 @@
 use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive};
 
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_macros::HashStable_Generic;
 use syntax_pos::Span;
 
 pub mod call;
@@ -242,6 +243,7 @@ pub enum Endian {
 
 /// Size of a type in bytes.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(HashStable_Generic)]
 pub struct Size {
     raw: u64
 }
@@ -365,6 +367,7 @@ fn add_assign(&mut self, other: Size) {
 
 /// Alignment of a type in bytes (always a power of two).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(HashStable_Generic)]
 pub struct Align {
     pow2: u8,
 }
@@ -423,6 +426,7 @@ pub fn restrict_for_offset(self, offset: Size) -> Align {
 
 /// A pair of aligments, ABI-mandated and preferred.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(HashStable_Generic)]
 pub struct AbiAndPrefAlign {
     pub abi: Align,
     pub pref: Align,
@@ -452,7 +456,7 @@ pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
 }
 
 /// Integers, also used for enum discriminants.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStable_Generic)]
 pub enum Integer {
     I8,
     I16,
@@ -533,7 +537,7 @@ pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
 }
 
 /// Fundamental unit of memory access and layout.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Primitive {
     /// The `bool` is the signedness of the `Integer` type.
     ///
@@ -588,6 +592,7 @@ pub fn is_int(self) -> bool {
 
 /// Information about one scalar component of a Rust type.
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(HashStable_Generic)]
 pub struct Scalar {
     pub value: Primitive,
 
@@ -636,7 +641,7 @@ pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: &C) -> Range<u128> {
 }
 
 /// Describes how the fields of a type are located in memory.
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum FieldPlacement {
     /// All fields start at no offset. The `usize` is the field count.
     ///
@@ -752,7 +757,7 @@ pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item=usize>+'a
 
 /// Describes how values of the type are passed by target ABIs,
 /// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Abi {
     Uninhabited,
     Scalar(Scalar),
@@ -800,10 +805,12 @@ pub fn is_uninhabited(&self) -> bool {
 }
 
 rustc_index::newtype_index! {
-    pub struct VariantIdx { .. }
+    pub struct VariantIdx {
+        derive [HashStable_Generic]
+    }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Variants {
     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
     Single {
@@ -821,7 +828,7 @@ pub enum Variants {
     },
 }
 
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum DiscriminantKind {
     /// Integer tag holding the discriminant value itself.
     Tag,
@@ -842,7 +849,7 @@ pub enum DiscriminantKind {
     },
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct Niche {
     pub offset: Size,
     pub scalar: Scalar,
@@ -906,7 +913,7 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
     }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct LayoutDetails {
     pub variants: Variants,
     pub fields: FieldPlacement,
index 3a24d30966f638be5c3e6ba824c29e923e716e3a..736358a995b640ea1f82efc040e4007d0b9d4821 100644 (file)
@@ -1,9 +1,12 @@
 use std::fmt;
 
+use rustc_macros::HashStable_Generic;
+
 #[cfg(test)]
 mod tests;
 
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable,
+         Clone, Copy, Debug, HashStable_Generic)]
 pub enum Abi {
     // N.B., this ordering MUST match the AbiDatas array below.
     // (This is ensured by the test indices_are_correct().)
index 4cd2f13d09cbd3d0d6eff7c7865ce33bfc228a03..716aef056a35b6a79e9d18edc0d6a47f0d18f3ca 100644 (file)
@@ -42,6 +42,8 @@
 use std::str::FromStr;
 use crate::spec::abi::{Abi, lookup as lookup_abi};
 
+use rustc_macros::HashStable_Generic;
+
 pub mod abi;
 mod android_base;
 mod apple_base;
@@ -153,7 +155,7 @@ pub fn desc(&self) -> &str {
     ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum PanicStrategy {
     Unwind,
     Abort,
index bba30ebbbe7bb41eb0e0c65d39e19f213bdc688d..9dd3bc624a51afc14cb320ab95144f4cc1fc26d4 100644 (file)
@@ -538,7 +538,7 @@ fn borrow_pat_suggestion(
         }
     }
 
-    pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat) -> bool {
+    pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat) -> bool {
         if let PatKind::Binding(..) = inner.kind {
             if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {
                 if let ty::Dynamic(..) = mt.ty.kind {
@@ -1075,7 +1075,7 @@ fn check_pat_box(
         discrim_span: Option<Span>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        let (box_ty, inner_ty) = if self.check_dereferencable(span, expected, &inner) {
+        let (box_ty, inner_ty) = if self.check_dereferenceable(span, expected, &inner) {
             // Here, `demand::subtype` is good enough, but I don't
             // think any errors can be introduced by using `demand::eqtype`.
             let inner_ty = self.next_ty_var(TypeVariableOrigin {
@@ -1103,7 +1103,7 @@ fn check_pat_ref(
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let expected = self.shallow_resolve(expected);
-        let (rptr_ty, inner_ty) = if self.check_dereferencable(pat.span, expected, &inner) {
+        let (rptr_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, &inner) {
             // `demand::subtype` would be good enough, but using `eqtype` turns
             // out to be equally general. See (note_1) for details.
 
index 3d380a5f1826cf585f4829e0a8034fe052569c3f..3113e9b241daa3f03225dc775bb2310e1af3cc22 100644 (file)
@@ -3,6 +3,7 @@
 // substitutions.
 
 use crate::check::FnCtxt;
+
 use rustc::hir;
 use rustc::hir::def_id::{DefId, DefIndex};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::nodemap::DefIdSet;
 use rustc_data_structures::sync::Lrc;
-use std::mem;
 use syntax::symbol::sym;
 use syntax_pos::Span;
 
+use std::mem;
+
 ///////////////////////////////////////////////////////////////////////////
 // Entry point
 
@@ -481,8 +483,10 @@ fn visit_opaque_types(&mut self, span: Span) {
             if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.kind {
                 if let hir::OpaqueTyOrigin::TypeAlias = opaque_defn.origin {
                     if def_id == defin_ty_def_id {
-                        debug!("Skipping adding concrete definition for opaque type {:?} {:?}",
-                               opaque_defn, defin_ty_def_id);
+                        debug!(
+                            "skipping adding concrete definition for opaque type {:?} {:?}",
+                            opaque_defn, defin_ty_def_id
+                        );
                         skip_add = true;
                     }
                 }
@@ -507,8 +511,8 @@ fn visit_opaque_types(&mut self, span: Span) {
                         if old.concrete_type != definition_ty || old.substs != opaque_defn.substs {
                             span_bug!(
                                 span,
-                                "visit_opaque_types tried to write different types for the same \
-                                opaque type: {:?}, {:?}, {:?}, {:?}",
+                                "`visit_opaque_types` tried to write different types for the same \
+                                 opaque type: {:?}, {:?}, {:?}, {:?}",
                                 def_id,
                                 definition_ty,
                                 opaque_defn,
index bf4a1440e1bf12fcf6f956c9bc3a892ee7be1b44..bfc82ad6e8b17318b1272a7dce6ea1c4ac1aa9ef 100644 (file)
@@ -16,7 +16,6 @@
 use syntax::sess::ParseSess;
 use syntax::source_map::SourceMap;
 use syntax::symbol::{kw, sym};
-use syntax_expand::config::process_configure_mod;
 use syntax_pos::{Span, FileName};
 
 /// Highlights `src`, returning the HTML output.
@@ -34,7 +33,7 @@ pub fn render_with_highlighting(
                class, tooltip).unwrap();
     }
 
-    let sess = ParseSess::with_silent_emitter(process_configure_mod);
+    let sess = ParseSess::with_silent_emitter();
     let fm = sess.source_map().new_source_file(
         FileName::Custom(String::from("rustdoc-highlighting")),
         src.to_owned(),
index 5c4c975cec051b1c91a2e8b46541ede12fa3bf5b..8d5463ddbd764447276ef055b050df46f559b44f 100644 (file)
@@ -3,7 +3,6 @@
 use syntax::token;
 use syntax::sess::ParseSess;
 use syntax::source_map::FilePathMapping;
-use syntax_expand::config::process_configure_mod;
 use syntax_pos::{InnerSpan, FileName};
 
 use crate::clean;
@@ -28,7 +27,7 @@ struct SyntaxChecker<'a, 'tcx> {
 
 impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
     fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) {
-        let sess = ParseSess::new(FilePathMapping::empty(), process_configure_mod);
+        let sess = ParseSess::new(FilePathMapping::empty());
         let source_file = sess.source_map().new_source_file(
             FileName::Custom(String::from("doctest")),
             dox[code_block.code].to_owned(),
index 98e18d666f1500c3906c408af38b6f453353c4b6..22f209b8bada1503f3d2531d0e95bbd396712492 100644 (file)
@@ -17,7 +17,6 @@
 use std::process::{self, Command, Stdio};
 use std::str;
 use syntax::symbol::sym;
-use syntax_expand::config::process_configure_mod;
 use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName};
 use tempfile::Builder as TempFileBuilder;
 use testing;
@@ -415,7 +414,7 @@ pub fn make_test(s: &str,
         let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
         // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
         let handler = Handler::with_emitter(false, None, box emitter);
-        let sess = ParseSess::with_span_handler(handler, cm, process_configure_mod);
+        let sess = ParseSess::with_span_handler(handler, cm);
 
         let mut found_main = false;
         let mut found_extern_crate = cratename.is_none();
index d96b5b7a3dde4028b4736a7b4fd60c5eaab96194..dff23076c82e637a7bd0807425ef3e020ada950e 100644 (file)
@@ -20,5 +20,6 @@ errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_index = { path = "../librustc_index" }
 rustc_lexer = { path = "../librustc_lexer" }
+rustc_macros = { path = "../librustc_macros" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_error_codes = { path = "../librustc_error_codes" }
index bbf00825acb3376874e809690c022a4edb79e796..142430769411fd82d6c73407464e4cc2efe1a731 100644 (file)
@@ -37,6 +37,7 @@
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_index::vec::Idx;
 use rustc_serialize::{self, Decoder, Encoder};
+use rustc_macros::HashStable_Generic;
 
 use std::fmt;
 
@@ -722,9 +723,8 @@ pub enum PatKind {
     Mac(Mac),
 }
 
-#[derive(
-    Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy,
-)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
+         RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum Mutability {
     Mutable,
     Immutable,
@@ -982,12 +982,12 @@ pub struct Arm {
 /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Field {
+    pub attrs: ThinVec<Attribute>,
+    pub id: NodeId,
+    pub span: Span,
     pub ident: Ident,
     pub expr: P<Expr>,
-    pub span: Span,
     pub is_shorthand: bool,
-    pub attrs: ThinVec<Attribute>,
-    pub id: NodeId,
     pub is_placeholder: bool,
 }
 
@@ -1328,7 +1328,7 @@ pub struct QSelf {
 }
 
 /// A capture clause used in closures and `async` blocks.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum CaptureBy {
     /// `move |x| y + x`.
     Value,
@@ -1339,7 +1339,7 @@ pub enum CaptureBy {
 /// The movability of a generator / closure literal:
 /// whether a generator contains self-references, causing it to be `!Unpin`.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
-         RustcEncodable, RustcDecodable, Debug, Copy)]
+         RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum Movability {
     /// May contain self-references, `!Unpin`.
     Static,
@@ -1400,7 +1400,7 @@ pub fn stream(&self) -> TokenStream {
 }
 
 // Clippy uses Hash and PartialEq
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq, HashStable_Generic)]
 pub enum StrStyle {
     /// A regular string, like `"foo"`.
     Cooked,
@@ -1451,7 +1451,7 @@ impl StrLit {
 
 // Clippy uses Hash and PartialEq
 /// Type of the integer literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
 pub enum LitIntType {
     /// e.g. `42_i32`.
     Signed(IntTy),
@@ -1462,7 +1462,7 @@ pub enum LitIntType {
 }
 
 /// Type of the float literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
 pub enum LitFloatType {
     /// A float literal with a suffix (`1f32` or `1E10f32`).
     Suffixed(FloatTy),
@@ -1474,7 +1474,7 @@ pub enum LitFloatType {
 ///
 /// E.g., `"foo"`, `42`, `12.34`, or `bool`.
 // Clippy uses Hash and PartialEq
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq, HashStable_Generic)]
 pub enum LitKind {
     /// A string literal (`"foo"`).
     Str(Symbol, StrStyle),
@@ -1567,12 +1567,14 @@ pub struct FnSig {
 /// signature) or provided (meaning it has a default implementation).
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct TraitItem {
+    pub attrs: Vec<Attribute>,
     pub id: NodeId,
+    pub span: Span,
+    pub vis: Visibility,
     pub ident: Ident,
-    pub attrs: Vec<Attribute>,
+
     pub generics: Generics,
     pub kind: TraitItemKind,
-    pub span: Span,
     /// See `Item::tokens` for what this is.
     pub tokens: Option<TokenStream>,
 }
@@ -1588,14 +1590,15 @@ pub enum TraitItemKind {
 /// Represents anything within an `impl` block.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ImplItem {
+    pub attrs: Vec<Attribute>,
     pub id: NodeId,
-    pub ident: Ident,
+    pub span: Span,
     pub vis: Visibility,
+    pub ident: Ident,
+
     pub defaultness: Defaultness,
-    pub attrs: Vec<Attribute>,
     pub generics: Generics,
     pub kind: ImplItemKind,
-    pub span: Span,
     /// See `Item::tokens` for what this is.
     pub tokens: Option<TokenStream>,
 }
@@ -1609,7 +1612,8 @@ pub enum ImplItemKind {
     Macro(Mac),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic,
+         RustcEncodable, RustcDecodable, Debug)]
 pub enum FloatTy {
     F32,
     F64,
@@ -1638,7 +1642,8 @@ pub fn bit_width(self) -> usize {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic,
+         RustcEncodable, RustcDecodable, Debug)]
 pub enum IntTy {
     Isize,
     I8,
@@ -1690,7 +1695,8 @@ pub fn bit_width(&self) -> Option<usize> {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic,
+         RustcEncodable, RustcDecodable, Copy, Debug)]
 pub enum UintTy {
     Usize,
     U8,
@@ -1863,7 +1869,7 @@ pub enum TraitObjectSyntax {
 /// Inline assembly dialect.
 ///
 /// E.g., `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum AsmDialect {
     Att,
     Intel,
@@ -2021,14 +2027,14 @@ pub fn c_variadic(&self) -> bool {
 }
 
 /// Is the trait definition an auto trait?
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum IsAuto {
     Yes,
     No,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
-         RustcEncodable, RustcDecodable, Debug)]
+         RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum Unsafety {
     Unsafe,
     Normal,
@@ -2085,7 +2091,7 @@ pub fn opt_return_id(self) -> Option<NodeId> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum Constness {
     Const,
     NotConst,
@@ -2093,13 +2099,13 @@ pub enum Constness {
 
 /// Item defaultness.
 /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum Defaultness {
     Default,
     Final,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum ImplPolarity {
     /// `impl Trait for Type`
     Positive,
@@ -2171,22 +2177,24 @@ pub struct GlobalAsm {
 pub struct EnumDef {
     pub variants: Vec<Variant>,
 }
-
 /// Enum variant.
 #[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,
+    /// Span
+    pub span: Span,
+    /// The visibility of the variant. Syntactically accepted but not semantically.
+    pub vis: Visibility,
+    /// Name of the variant.
+    pub ident: Ident,
+
     /// Fields and constructor id of the variant.
     pub data: VariantData,
     /// Explicit discriminant, e.g., `Foo = 1`.
     pub disr_expr: Option<AnonConst>,
-    /// Span
-    pub span: Span,
     /// Is a macro placeholder
     pub is_placeholder: bool,
 }
@@ -2233,7 +2241,7 @@ pub fn ident(&self) -> Ident {
 /// Distinguishes between `Attribute`s that decorate items and Attributes that
 /// are contained as statements within items. These two cases need to be
 /// distinguished for pretty-printing.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
 pub enum AttrStyle {
     Outer,
     Inner,
@@ -2331,7 +2339,7 @@ pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self {
     }
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum CrateSugar {
     /// Source is `pub(crate)`.
     PubCrate,
@@ -2365,12 +2373,13 @@ pub fn is_pub(&self) -> bool {
 /// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct StructField {
+    pub attrs: Vec<Attribute>,
+    pub id: NodeId,
     pub span: Span,
-    pub ident: Option<Ident>,
     pub vis: Visibility,
-    pub id: NodeId,
+    pub ident: Option<Ident>,
+
     pub ty: P<Ty>,
-    pub attrs: Vec<Attribute>,
     pub is_placeholder: bool,
 }
 
@@ -2414,12 +2423,13 @@ pub fn ctor_id(&self) -> Option<NodeId> {
 /// The name might be a dummy name in case of anonymous items.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Item {
-    pub ident: Ident,
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
-    pub kind: ItemKind,
-    pub vis: Visibility,
     pub span: Span,
+    pub vis: Visibility,
+    pub ident: Ident,
+
+    pub kind: ItemKind,
 
     /// Original tokens this item was parsed from. This isn't necessarily
     /// available for all items, although over time more and more items should
@@ -2576,12 +2586,13 @@ pub fn descriptive_variant(&self) -> &str {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ForeignItem {
-    pub ident: Ident,
     pub attrs: Vec<Attribute>,
-    pub kind: ForeignItemKind,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
+    pub ident: Ident,
+
+    pub kind: ForeignItemKind,
 }
 
 /// An item within an `extern` block.
index 767fcabc017eddb5c3a6beb2225c8e3d7f075c1d..c10541c8c7e75d367eaf8055937d46a4c5ec7c68 100644 (file)
@@ -9,6 +9,7 @@
 use std::num::NonZeroU32;
 use syntax_pos::hygiene::Transparency;
 use syntax_pos::{symbol::Symbol, symbol::sym, Span};
+use rustc_macros::HashStable_Generic;
 
 use super::{mark_used, MetaItemKind};
 
@@ -141,7 +142,8 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
 }
 
 /// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug,
+         PartialEq, Eq, Hash, HashStable_Generic)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
@@ -157,7 +159,8 @@ pub struct Stability {
 }
 
 /// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd,
+         Copy, Clone, Debug, Eq, Hash, HashStable_Generic)]
 pub enum StabilityLevel {
     // Reason for the current stability level and the relevant rust-lang issue
     Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
@@ -181,7 +184,8 @@ pub fn is_stable(&self) -> bool {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd,
+         Copy, Clone, Debug, Eq, Hash, HashStable_Generic)]
 pub struct RustcDeprecation {
     pub since: Symbol,
     pub reason: Symbol,
@@ -636,7 +640,7 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Clone)]
+#[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
 pub struct Deprecation {
     pub since: Option<Symbol>,
     pub note: Option<Symbol>,
@@ -763,7 +767,7 @@ pub enum ReprAttr {
     ReprAlign(u32),
 }
 
-#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone, HashStable_Generic)]
 pub enum IntType {
     SignedInt(ast::IntTy),
     UnsignedInt(ast::UintTy)
index da3c885b8609dc9e389ca0c24b8014276bb5793a..a7bd587ac9bfb108ed9cf885f6b69be280340c78 100644 (file)
@@ -472,16 +472,17 @@ pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis:
     items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
 }
 
-pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, vis: &mut T)
+pub fn noop_flat_map_variant<T: MutVisitor>(mut variant: Variant, visitor: &mut T)
     -> SmallVec<[Variant; 1]>
 {
-    let Variant { ident, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut 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);
+    let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
+    visitor.visit_ident(ident);
+    visitor.visit_vis(vis);
+    visit_attrs(attrs, visitor);
+    visitor.visit_id(id);
+    visitor.visit_variant_data(data);
+    visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
+    visitor.visit_span(span);
     smallvec![variant]
 }
 
@@ -916,32 +917,33 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
     }
 }
 
-pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, vis: &mut T)
+pub fn noop_flat_map_trait_item<T: MutVisitor>(mut item: TraitItem, visitor: &mut T)
     -> SmallVec<[TraitItem; 1]>
 {
-    let TraitItem { id, ident, attrs, generics, kind, span, tokens: _ } = &mut item;
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-    visit_attrs(attrs, vis);
-    vis.visit_generics(generics);
+    let TraitItem { id, ident, vis, attrs, generics, kind, span, tokens: _ } = &mut item;
+    visitor.visit_id(id);
+    visitor.visit_ident(ident);
+    visitor.visit_vis(vis);
+    visit_attrs(attrs, visitor);
+    visitor.visit_generics(generics);
     match kind {
         TraitItemKind::Const(ty, default) => {
-            vis.visit_ty(ty);
-            visit_opt(default, |default| vis.visit_expr(default));
+            visitor.visit_ty(ty);
+            visit_opt(default, |default| visitor.visit_expr(default));
         }
         TraitItemKind::Method(sig, body) => {
-            visit_fn_sig(sig, vis);
-            visit_opt(body, |body| vis.visit_block(body));
+            visit_fn_sig(sig, visitor);
+            visit_opt(body, |body| visitor.visit_block(body));
         }
         TraitItemKind::Type(bounds, default) => {
-            visit_bounds(bounds, vis);
-            visit_opt(default, |default| vis.visit_ty(default));
+            visit_bounds(bounds, visitor);
+            visit_opt(default, |default| visitor.visit_ty(default));
         }
         TraitItemKind::Macro(mac) => {
-            vis.visit_mac(mac);
+            visitor.visit_mac(mac);
         }
     }
-    vis.visit_span(span);
+    visitor.visit_span(span);
 
     smallvec![item]
 }
index 2c6dd0fb1c6dc05154407509a408784c005c760a..d7725acb5d45077deb8dd47be58eb9260c2e9388 100644 (file)
@@ -50,6 +50,7 @@ fn test_variant_to_string() {
 
         let var = ast::Variant {
             ident,
+            vis: source_map::respan(syntax_pos::DUMMY_SP, ast::VisibilityKind::Inherited),
             attrs: Vec::new(),
             id: ast::DUMMY_NODE_ID,
             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
index 953f0d1d190bbb3bbd5229b30d4bbc1ec87c9c94..740e9dfe45935909df20a56cc9512be812ef564c 100644 (file)
@@ -1,7 +1,7 @@
 //! Contains `ParseSess` which holds state living beyond what one `Parser` might.
 //! It also serves as an input to the parser itself.
 
-use crate::ast::{CrateConfig, NodeId, Attribute};
+use crate::ast::{CrateConfig, NodeId};
 use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId};
 use crate::source_map::{SourceMap, FilePathMapping};
 use crate::feature_gate::UnstableFeatures;
@@ -89,22 +89,10 @@ pub struct ParseSess {
     pub gated_spans: GatedSpans,
     /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors.
     pub reached_eof: Lock<bool>,
-    /// Process the potential `cfg` attributes on a module.
-    /// Also determine if the module should be included in this configuration.
-    ///
-    /// HACK(Centril): This is used to break a cyclic dependency between
-    /// the parser and cfg-stripping as defined in `syntax_expand::config`.
-    /// The dependency edge from the parser comes from `parse_item_mod`.
-    /// A principled solution to this hack would be to implement [#64197].
-    ///
-    /// [#64197]: https://github.com/rust-lang/rust/issues/64197
-    pub process_cfg_mod: ProcessCfgMod,
 }
 
-pub type ProcessCfgMod = fn(&ParseSess, bool, &[Attribute]) -> (bool, Vec<Attribute>);
-
 impl ParseSess {
-    pub fn new(file_path_mapping: FilePathMapping, process_cfg_mod: ProcessCfgMod) -> Self {
+    pub fn new(file_path_mapping: FilePathMapping) -> Self {
         let cm = Lrc::new(SourceMap::new(file_path_mapping));
         let handler = Handler::with_tty_emitter(
             ColorConfig::Auto,
@@ -112,17 +100,15 @@ pub fn new(file_path_mapping: FilePathMapping, process_cfg_mod: ProcessCfgMod) -
             None,
             Some(cm.clone()),
         );
-        ParseSess::with_span_handler(handler, cm, process_cfg_mod)
+        ParseSess::with_span_handler(handler, cm)
     }
 
     pub fn with_span_handler(
         handler: Handler,
         source_map: Lrc<SourceMap>,
-        process_cfg_mod: ProcessCfgMod,
     ) -> Self {
         Self {
             span_diagnostic: handler,
-            process_cfg_mod,
             unstable_features: UnstableFeatures::from_environment(),
             config: FxHashSet::default(),
             edition: ExpnId::root().expn_data().edition,
@@ -138,10 +124,10 @@ pub fn with_span_handler(
         }
     }
 
-    pub fn with_silent_emitter(process_cfg_mod: ProcessCfgMod) -> Self {
+    pub fn with_silent_emitter() -> Self {
         let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let handler = Handler::with_emitter(false, None, Box::new(SilentEmitter));
-        ParseSess::with_span_handler(handler, cm, process_cfg_mod)
+        ParseSess::with_span_handler(handler, cm)
     }
 
     #[inline]
index ab798e93d67fc009bb2208b86c5d400f44e9ae76..fd1623384a443e186e7e6083649e02b9fe1f27eb 100644 (file)
@@ -15,6 +15,7 @@
 use std::fmt;
 use std::mem;
 use rustc_data_structures::sync::Lrc;
+use rustc_macros::HashStable_Generic;
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum BinOpToken {
@@ -53,7 +54,7 @@ pub fn is_empty(self) -> bool {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum LitKind {
     Bool, // AST only, must never appear in a `Token`
     Byte,
@@ -68,7 +69,7 @@ pub enum LitKind {
 }
 
 /// A literal token.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub struct Lit {
     pub kind: LitKind,
     pub symbol: Symbol,
index 2597ffd750d775030c2e56c21e30f865806b218c..f7b06c55a3a2eb9ee7851a11f91466075196ba0c 100644 (file)
@@ -310,6 +310,7 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant)
     where V: Visitor<'a>,
 {
     visitor.visit_ident(variant.ident);
+    visitor.visit_vis(&variant.vis);
     visitor.visit_variant_data(&variant.data);
     walk_list!(visitor, visit_anon_const, &variant.disr_expr);
     walk_list!(visitor, visit_attribute, &variant.attrs);
@@ -581,6 +582,7 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
 }
 
 pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) {
+    visitor.visit_vis(&trait_item.vis);
     visitor.visit_ident(trait_item.ident);
     walk_list!(visitor, visit_attribute, &trait_item.attrs);
     visitor.visit_generics(&trait_item.generics);
index 105ffe3ee8a9f0ce1eccc30597ed27a2125f5b8b..7fe37f377a8d01493855d40fbfde084523fa7ab0 100644 (file)
@@ -582,12 +582,13 @@ pub fn item(&self, span: Span, name: Ident,
     }
 
     pub fn variant(&self, span: Span, ident: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant {
+        let vis_span = span.shrink_to_lo();
         let fields: Vec<_> = tys.into_iter().map(|ty| {
             ast::StructField {
                 span: ty.span,
                 ty,
                 ident: None,
-                vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
+                vis: respan(vis_span, ast::VisibilityKind::Inherited),
                 attrs: Vec::new(),
                 id: ast::DUMMY_NODE_ID,
                 is_placeholder: false,
@@ -606,6 +607,7 @@ pub fn variant(&self, span: Span, ident: Ident, tys: Vec<P<ast::Ty>> ) -> ast::V
             disr_expr: None,
             id: ast::DUMMY_NODE_ID,
             ident,
+            vis: respan(vis_span, ast::VisibilityKind::Inherited),
             span,
             is_placeholder: false,
         }
diff --git a/src/libsyntax_expand/config.rs b/src/libsyntax_expand/config.rs
deleted file mode 100644 (file)
index 7b927fb..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-use rustc_parse::validate_attr;
-use syntax::attr::HasAttrs;
-use syntax::feature_gate::{
-    feature_err,
-    EXPLAIN_STMT_ATTR_SYNTAX,
-    Features,
-    get_features,
-    GateIssue,
-};
-use syntax::attr;
-use syntax::ast;
-use syntax::edition::Edition;
-use syntax::mut_visit::*;
-use syntax::ptr::P;
-use syntax::sess::ParseSess;
-use syntax::util::map_in_place::MapInPlace;
-use syntax_pos::symbol::sym;
-
-use errors::Applicability;
-use smallvec::SmallVec;
-
-/// A folder that strips out items that do not belong in the current configuration.
-pub struct StripUnconfigured<'a> {
-    pub sess: &'a ParseSess,
-    pub features: Option<&'a Features>,
-}
-
-// `cfg_attr`-process the crate's attributes and compute the crate's features.
-pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition,
-                allow_features: &Option<Vec<String>>) -> (ast::Crate, Features) {
-    let features;
-    {
-        let mut strip_unconfigured = StripUnconfigured {
-            sess,
-            features: None,
-        };
-
-        let unconfigured_attrs = krate.attrs.clone();
-        let err_count = sess.span_diagnostic.err_count();
-        if let Some(attrs) = strip_unconfigured.configure(krate.attrs) {
-            krate.attrs = attrs;
-        } else { // the entire crate is unconfigured
-            krate.attrs = Vec::new();
-            krate.module.items = Vec::new();
-            return (krate, Features::new());
-        }
-
-        features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features);
-
-        // Avoid reconfiguring malformed `cfg_attr`s
-        if err_count == sess.span_diagnostic.err_count() {
-            strip_unconfigured.features = Some(&features);
-            strip_unconfigured.configure(unconfigured_attrs);
-        }
-    }
-
-    (krate, features)
-}
-
-#[macro_export]
-macro_rules! configure {
-    ($this:ident, $node:ident) => {
-        match $this.configure($node) {
-            Some(node) => node,
-            None => return Default::default(),
-        }
-    }
-}
-
-impl<'a> StripUnconfigured<'a> {
-    pub fn configure<T: HasAttrs>(&mut self, mut node: T) -> Option<T> {
-        self.process_cfg_attrs(&mut node);
-        if self.in_cfg(node.attrs()) { Some(node) } else { None }
-    }
-
-    /// Parse and expand all `cfg_attr` attributes into a list of attributes
-    /// that are within each `cfg_attr` that has a true configuration predicate.
-    ///
-    /// Gives compiler warnigns if any `cfg_attr` does not contain any
-    /// attributes and is in the original source code. Gives compiler errors if
-    /// the syntax of any `cfg_attr` is incorrect.
-    pub fn process_cfg_attrs<T: HasAttrs>(&mut self, node: &mut T) {
-        node.visit_attrs(|attrs| {
-            attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
-        });
-    }
-
-    /// Parse and expand a single `cfg_attr` attribute into a list of attributes
-    /// when the configuration predicate is true, or otherwise expand into an
-    /// empty list of attributes.
-    ///
-    /// Gives a compiler warning when the `cfg_attr` contains no attributes and
-    /// is in the original source file. Gives a compiler error if the syntax of
-    /// the attribute is incorrect.
-    fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec<ast::Attribute> {
-        if !attr.has_name(sym::cfg_attr) {
-            return vec![attr];
-        }
-        if attr.get_normal_item().tokens.is_empty() {
-            self.sess.span_diagnostic
-                .struct_span_err(
-                    attr.span,
-                    "malformed `cfg_attr` attribute input",
-                ).span_suggestion(
-                    attr.span,
-                    "missing condition and attribute",
-                    "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(),
-                    Applicability::HasPlaceholders,
-                ).note("for more information, visit \
-                       <https://doc.rust-lang.org/reference/conditional-compilation.html\
-                       #the-cfg_attr-attribute>")
-                .emit();
-            return vec![];
-        }
-
-        let res = rustc_parse::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr());
-        let (cfg_predicate, expanded_attrs) = match res {
-            Ok(result) => result,
-            Err(mut e) => {
-                e.emit();
-                return vec![];
-            }
-        };
-
-        // Lint on zero attributes in source.
-        if expanded_attrs.is_empty() {
-            return vec![attr];
-        }
-
-        // At this point we know the attribute is considered used.
-        attr::mark_used(&attr);
-
-        if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
-            // We call `process_cfg_attr` recursively in case there's a
-            // `cfg_attr` inside of another `cfg_attr`. E.g.
-            //  `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
-            expanded_attrs.into_iter()
-            .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item(
-                attr.style,
-                item,
-                span,
-            )))
-            .collect()
-        } else {
-            vec![]
-        }
-    }
-
-    /// Determines if a node with the given attributes should be included in this configuration.
-    pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool {
-        attrs.iter().all(|attr| {
-            if !is_cfg(attr) {
-                return true;
-            }
-
-            let error = |span, msg, suggestion: &str| {
-                let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
-                if !suggestion.is_empty() {
-                    err.span_suggestion(
-                        span,
-                        "expected syntax is",
-                        suggestion.into(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                err.emit();
-                true
-            };
-
-            let meta_item = match validate_attr::parse_meta(self.sess, attr) {
-                Ok(meta_item) => meta_item,
-                Err(mut err) => { err.emit(); return true; }
-            };
-            let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() {
-                nested_meta_items
-            } else {
-                return error(meta_item.span, "`cfg` is not followed by parentheses",
-                                             "cfg(/* predicate */)");
-            };
-
-            if nested_meta_items.is_empty() {
-                return error(meta_item.span, "`cfg` predicate is not specified", "");
-            } else if nested_meta_items.len() > 1 {
-                return error(nested_meta_items.last().unwrap().span(),
-                             "multiple `cfg` predicates are specified", "");
-            }
-
-            match nested_meta_items[0].meta_item() {
-                Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features),
-                None => error(nested_meta_items[0].span(),
-                              "`cfg` predicate key cannot be a literal", ""),
-            }
-        })
-    }
-
-    /// Visit attributes on expression and statements (but not attributes on items in blocks).
-    fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
-        // flag the offending attributes
-        for attr in attrs.iter() {
-            self.maybe_emit_expr_attr_err(attr);
-        }
-    }
-
-    /// If attributes are not allowed on expressions, emit an error for `attr`
-    pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) {
-        if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) {
-            let mut err = feature_err(self.sess,
-                                      sym::stmt_expr_attributes,
-                                      attr.span,
-                                      GateIssue::Language,
-                                      EXPLAIN_STMT_ATTR_SYNTAX);
-
-            if attr.is_doc_comment() {
-                err.help("`///` is for documentation comments. For a plain comment, use `//`.");
-            }
-
-            err.emit();
-        }
-    }
-
-    pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
-        let ast::ForeignMod { abi: _, items } = foreign_mod;
-        items.flat_map_in_place(|item| self.configure(item));
-    }
-
-    pub fn configure_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
-        params.flat_map_in_place(|param| self.configure(param));
-    }
-
-    fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
-        match vdata {
-            ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) =>
-                fields.flat_map_in_place(|field| self.configure(field)),
-            ast::VariantData::Unit(_) => {}
-        }
-    }
-
-    pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) {
-        match item {
-            ast::ItemKind::Struct(def, _generics) |
-            ast::ItemKind::Union(def, _generics) => self.configure_variant_data(def),
-            ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
-                variants.flat_map_in_place(|variant| self.configure(variant));
-                for variant in variants {
-                    self.configure_variant_data(&mut variant.data);
-                }
-            }
-            _ => {}
-        }
-    }
-
-    pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) {
-        match expr_kind {
-            ast::ExprKind::Match(_m, arms) => {
-                arms.flat_map_in_place(|arm| self.configure(arm));
-            }
-            ast::ExprKind::Struct(_path, fields, _base) => {
-                fields.flat_map_in_place(|field| self.configure(field));
-            }
-            _ => {}
-        }
-    }
-
-    pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
-        self.visit_expr_attrs(expr.attrs());
-
-        // If an expr is valid to cfg away it will have been removed by the
-        // outer stmt or expression folder before descending in here.
-        // Anything else is always required, and thus has to error out
-        // in case of a cfg attr.
-        //
-        // N.B., this is intentionally not part of the visit_expr() function
-        //     in order for filter_map_expr() to be able to avoid this check
-        if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
-            let msg = "removing an expression is not supported in this position";
-            self.sess.span_diagnostic.span_err(attr.span, msg);
-        }
-
-        self.process_cfg_attrs(expr)
-    }
-
-    pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
-        if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind {
-            fields.flat_map_in_place(|field| self.configure(field));
-        }
-    }
-
-    pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
-        fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
-    }
-}
-
-impl<'a> MutVisitor for StripUnconfigured<'a> {
-    fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
-        self.configure_foreign_mod(foreign_mod);
-        noop_visit_foreign_mod(foreign_mod, self);
-    }
-
-    fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
-        self.configure_item_kind(item);
-        noop_visit_item_kind(item, self);
-    }
-
-    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
-        self.configure_expr(expr);
-        self.configure_expr_kind(&mut expr.kind);
-        noop_visit_expr(expr, self);
-    }
-
-    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
-        let mut expr = configure!(self, expr);
-        self.configure_expr_kind(&mut expr.kind);
-        noop_visit_expr(&mut expr, self);
-        Some(expr)
-    }
-
-    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
-        noop_flat_map_stmt(configure!(self, stmt), self)
-    }
-
-    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
-        noop_flat_map_item(configure!(self, item), self)
-    }
-
-    fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
-        noop_flat_map_impl_item(configure!(self, item), self)
-    }
-
-    fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
-        noop_flat_map_trait_item(configure!(self, item), self)
-    }
-
-    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
-        // Don't configure interpolated AST (cf. issue #34171).
-        // Interpolated AST will get configured once the surrounding tokens are parsed.
-    }
-
-    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
-        self.configure_pat(pat);
-        noop_visit_pat(pat, self)
-    }
-
-    fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
-        self.configure_fn_decl(&mut fn_decl);
-        noop_visit_fn_decl(fn_decl, self);
-    }
-}
-
-fn is_cfg(attr: &ast::Attribute) -> bool {
-    attr.check_name(sym::cfg)
-}
-
-/// Process the potential `cfg` attributes on a module.
-/// Also determine if the module should be included in this configuration.
-pub fn process_configure_mod(
-    sess: &ParseSess,
-    cfg_mods: bool,
-    attrs: &[ast::Attribute],
-) -> (bool, Vec<ast::Attribute>) {
-    // Don't perform gated feature checking.
-    let mut strip_unconfigured = StripUnconfigured { sess, features: None };
-    let mut attrs = attrs.to_owned();
-    strip_unconfigured.process_cfg_attrs(&mut attrs);
-    (!cfg_mods || strip_unconfigured.in_cfg(&attrs), attrs)
-}
index 06aa5deb6e0184dd74231c0dd08aac951cd9a005..2532bbc0fe240d47294bd60362a2cda7e62d9f7c 100644 (file)
@@ -4,7 +4,7 @@
 use crate::mbe::macro_rules::annotate_err_with_kind;
 use crate::placeholders::{placeholder, PlaceholderExpander};
 use crate::config::StripUnconfigured;
-use crate::configure;
+use rustc_parse::configure;
 
 use rustc_parse::DirectoryOwnership;
 use rustc_parse::parser::Parser;
index 46d59dd249c3197b9198ddca30222b345faa3405..0aa34af7a762d32708429d2236d988d9e8f31517 100644 (file)
@@ -33,7 +33,7 @@ macro_rules! panictry {
 pub mod base;
 pub mod build;
 pub mod expand;
-#[macro_use] pub mod config;
+pub use rustc_parse::config;
 pub mod proc_macro;
 
 crate mod mbe;
index 0dcb2c39fdc4ddee22132c962a80ef248957ae12..bf7960f90660a86aa4b12f5c15d2eeca4bb8b49c 100644 (file)
@@ -77,7 +77,7 @@
 use crate::mbe::{self, TokenTree};
 
 use rustc_parse::Directory;
-use rustc_parse::parser::{Parser, PathStyle};
+use rustc_parse::parser::{Parser, PathStyle, FollowedByType};
 use syntax::ast::{Ident, Name};
 use syntax::print::pprust;
 use syntax::sess::ParseSess;
@@ -933,7 +933,7 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a,
         }
         sym::path => token::NtPath(p.parse_path(PathStyle::Type)?),
         sym::meta => token::NtMeta(p.parse_attr_item()?),
-        sym::vis => token::NtVis(p.parse_visibility(true)?),
+        sym::vis => token::NtVis(p.parse_visibility(FollowedByType::Yes)?),
         sym::lifetime => if p.check_lifetime() {
             token::NtLifetime(p.expect_lifetime().ident)
         } else {
index d8a1c359c950b8d66d882c6e2a3f9ebe8c894a6e..75e4ee805b200b71d5ea5357ae68e550f0546f48 100644 (file)
@@ -1,5 +1,3 @@
-use crate::config::process_configure_mod;
-
 use rustc_data_structures::sync::Lrc;
 use rustc_parse::lexer::StringReader;
 use syntax::token::{self, Token, TokenKind};
@@ -27,7 +25,6 @@ fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess {
     ParseSess::with_span_handler(
         Handler::with_emitter(true, None, Box::new(emitter)),
         sm,
-        process_configure_mod,
     )
 }
 
index 6091161799525b747522b5fcd50f5406fc82f6aa..08950ddefbaee3d03b73a9c9f6c80672ee063c3b 100644 (file)
@@ -1,4 +1,3 @@
-use crate::config::process_configure_mod;
 use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse};
 
 use rustc_parse::new_parser_from_source_str;
@@ -19,7 +18,7 @@
 use std::path::PathBuf;
 
 fn sess() -> ParseSess {
-    ParseSess::new(FilePathMapping::empty(), process_configure_mod)
+    ParseSess::new(FilePathMapping::empty())
 }
 
 /// Parses an item.
index e595888dae7d16802f2d10f66f3dd4890c72ff15..36a097000767bb8d6ccb840723504ed2d63c6865 100644 (file)
@@ -53,7 +53,7 @@ fn mac_placeholder() -> ast::Mac {
             tokens: None,
         })]),
         AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
-            id, span, ident, attrs, generics,
+            id, span, ident, vis, attrs, generics,
             kind: ast::TraitItemKind::Macro(mac_placeholder()),
             tokens: None,
         }]),
@@ -150,6 +150,7 @@ fn mac_placeholder() -> ast::Mac {
                 id,
                 ident,
                 span,
+                vis,
                 is_placeholder: true,
             }
         ])
index 2683620e84593cac36e8cc71ab46d125aec10ee6..425eb305845b4c7c915e674d2d89d1b5275cd81d 100644 (file)
@@ -1,4 +1,3 @@
-use crate::config::process_configure_mod;
 use rustc_parse::{source_file_to_stream, new_parser_from_source_str, parser::Parser};
 use syntax::ast;
 use syntax::tokenstream::TokenStream;
@@ -34,7 +33,7 @@ fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
 
 /// Maps a string to tts, using a made-up filename.
 crate fn string_to_stream(source_str: String) -> TokenStream {
-    let ps = ParseSess::new(FilePathMapping::empty(), process_configure_mod);
+    let ps = ParseSess::new(FilePathMapping::empty());
     source_file_to_stream(
         &ps,
         ps.source_map().new_source_file(PathBuf::from("bogofile").into(),
@@ -44,7 +43,7 @@ fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
 
 /// Parses a string, returns a crate.
 crate fn string_to_crate(source_str : String) -> ast::Crate {
-    let ps = ParseSess::new(FilePathMapping::empty(), process_configure_mod);
+    let ps = ParseSess::new(FilePathMapping::empty());
     with_error_checking_parse(source_str, &ps, |p| {
         p.parse_crate_mod()
     })
index 00cd00f2837849b10cbe646f4b7fcfc28796fada..727aad546f5f12d4661a730b440916534afd9367 100644 (file)
@@ -2,8 +2,11 @@
 use std::fmt;
 use std::str::FromStr;
 
+use rustc_macros::HashStable_Generic;
+
 /// The edition of the compiler (RFC 2052)
-#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)]
+#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug,
+         RustcEncodable, RustcDecodable, Eq, HashStable_Generic)]
 pub enum Edition {
     // editions must be kept in order, oldest to newest
 
index 2a48f8e44aa1259a2e7d6add29b70c9cc8589e16..eb420454f03d324cd8385720bc529a9a988d5752 100644 (file)
@@ -30,6 +30,7 @@
 use crate::edition::Edition;
 use crate::symbol::{kw, sym, Symbol};
 
+use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -58,7 +59,8 @@ struct SyntaxContextData {
 
 /// A property of a macro expansion that determines how identifiers
 /// produced by that expansion are resolved.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug,
+         RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum Transparency {
     /// Identifier produced by a transparent expansion is always resolved at call-site.
     /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
@@ -683,7 +685,7 @@ pub fn is_root(&self) -> bool {
 }
 
 /// Expansion kind.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum ExpnKind {
     /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
     Root,
@@ -707,7 +709,8 @@ pub fn descr(&self) -> Symbol {
 }
 
 /// The kind of macro invocation or definition.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable,
+         Hash, Debug, HashStable_Generic)]
 pub enum MacroKind {
     /// A bang macro `foo!()`.
     Bang,
@@ -742,7 +745,7 @@ pub fn article(self) -> &'static str {
 }
 
 /// The kind of AST transform.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum AstPass {
     StdImports,
     TestHarness,
@@ -762,7 +765,7 @@ fn descr(self) -> &'static str {
 }
 
 /// The kind of compiler desugaring.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum DesugaringKind {
     /// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`.
     /// However, we do not want to blame `c` for unreachability but rather say that `i`
index b88d6dbc3f3790434d0168bee1c99c2ae2a928f2..720ace90324b9580879f6242da8c9ecb1ca68f5c 100644 (file)
@@ -15,6 +15,7 @@
 #![feature(step_trait)]
 
 use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
+use rustc_macros::HashStable_Generic;
 
 pub mod source_map;
 
@@ -66,7 +67,8 @@ pub fn new(edition: Edition) -> Globals {
 scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);
 
 /// Differentiates between real files and common virtual files.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash,
+         RustcDecodable, RustcEncodable, HashStable_Generic)]
 pub enum FileName {
     Real(PathBuf),
     /// A macro. This includes the full name of the macro, so that there are no clashes.
index e7238caca8e4b685277932d2d62730767fc429f9..d20d520ac5578839bda37fd23ada7212fb5f21eb 100644 (file)
@@ -8,6 +8,7 @@
 use rustc_macros::symbols;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
+use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher};
 
 use std::cmp::{PartialEq, PartialOrd, Ord};
 use std::fmt;
@@ -942,6 +943,22 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
     }
 }
 
+impl<CTX> HashStable<CTX> for Symbol {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.as_str().hash_stable(hcx, hasher);
+    }
+}
+
+impl<CTX> ToStableHashKey<CTX> for Symbol {
+    type KeyType = SymbolStr;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr {
+        self.as_str()
+    }
+}
+
 // The `&'static str`s in this type actually point into the arena.
 #[derive(Default)]
 pub struct Interner {
@@ -1139,3 +1156,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self.string, f)
     }
 }
+
+impl<CTX> HashStable<CTX> for SymbolStr {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.string.hash_stable(hcx, hasher)
+    }
+}
+
+impl<CTX> ToStableHashKey<CTX> for SymbolStr {
+    type KeyType = SymbolStr;
+
+    #[inline]
+    fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr {
+        self.clone()
+    }
+}
index 145d4ba6b4c5a283ee3e3a6dfa479ef61549596a..b5ee5ba2394d93b24774eb0c35d14f9e05b42b07 100644 (file)
@@ -9,19 +9,21 @@ pub enum E {
 
 // CHECK-LABEL: @exhaustive_match
 #[no_mangle]
-pub fn exhaustive_match(e: E, unit: ()) {
+pub fn exhaustive_match(e: E) -> u8 {
 // CHECK: switch{{.*}}, label %[[OTHERWISE:[a-zA-Z0-9_]+]] [
 // CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]]
 // CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]]
 // CHECK-NEXT: ]
 // CHECK: [[B]]:
+// CHECK-NEXT: store i8 1, i8* %1, align 1
 // CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
 // CHECK: [[OTHERWISE]]:
 // CHECK-NEXT: unreachable
 // CHECK: [[A]]:
+// CHECK-NEXT: store i8 0, i8* %1, align 1
 // CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]]
     match e {
-        E::A => unit,
-        E::B => unit,
+        E::A => 0,
+        E::B => 1,
     }
 }
diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs
new file mode 100644 (file)
index 0000000..30e7adf
--- /dev/null
@@ -0,0 +1,17 @@
+// compile-flags: -C no-prepopulate-passes -Z mir-opt-level=2
+
+// Ensure that `x?` has no overhead on `Result<T, E>` due to identity `match`es in lowering.
+// This requires inlining to trigger the MIR optimizations in `SimplifyArmIdentity`.
+
+#![crate_type = "lib"]
+
+type R = Result<u64, i32>;
+
+#[no_mangle]
+fn try_identity(x: R) -> R {
+// CHECK: start:
+// CHECK-NOT: br {{.*}}
+// CHECK ret void
+    let y = x?;
+    Ok(y)
+}
index c2902dbd7c12953cbe598d5e7a6ff24ee23bb7f7..d14ec0397166f05cf2f9df071e8cc4e1ce227d26 100644 (file)
@@ -10,10 +10,12 @@ fn main() {
 // START rustc.main.ConstProp.before.mir
 //  bb0: {
 //      ...
-//      _2 = (FOO: u8);
+//      _3 = const Scalar(AllocId(0).0x0) : &u8;
+//      _2 = (*_3);
 //      ...
-//      _3 = (FOO: u8);
-//      _1 = Add(move _2, move _3);
+//      _5 = const Scalar(AllocId(0).0x0) : &u8;
+//      _4 = (*_5);
+//      _1 = Add(move _2, move _4);
 //      ...
 //  }
 // END rustc.main.ConstProp.before.mir
@@ -22,8 +24,8 @@ fn main() {
 //      ...
 //      _2 = const 2u8;
 //      ...
-//      _3 = const 2u8;
-//      _1 = Add(move _2, move _3);
+//      _4 = const 2u8;
+//      _1 = Add(move _2, move _4);
 //      ...
 //  }
 // END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
new file mode 100644 (file)
index 0000000..7911fbd
--- /dev/null
@@ -0,0 +1,193 @@
+fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
+    let y = x?;
+    Ok(y)
+}
+
+fn main() {
+    let _ = try_identity(Ok(0));
+}
+
+// END RUST SOURCE
+// START rustc.try_identity.SimplifyArmIdentity.before.mir
+// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+//     let mut _0: std::result::Result<u32, i32>;
+//     let _2: u32;
+//     let mut _3: std::result::Result<u32, i32>;
+//     let mut _4: std::result::Result<u32, i32>;
+//     let mut _5: isize;
+//     let _6: i32;
+//     let mut _7: !;
+//     let mut _8: i32;
+//     let mut _9: i32;
+//     let _10: u32;
+//     let mut _11: u32;
+//     scope 1 {
+//     }
+//     scope 2 {
+//         scope 3 {
+//             scope 7 {
+//             }
+//             scope 8 {
+//                 let mut _12: i32;
+//             }
+//         }
+//     }
+//     scope 4 {
+//         scope 5 {
+//         }
+//     }
+//     scope 6 {
+//     }
+//     bb0: {
+//         _5 = discriminant(_1);
+//         switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
+//     }
+//     bb1: {
+//         unreachable;
+//     }
+//     bb2: {
+//         _6 = ((_1 as Err).0: i32);
+//         ((_0 as Err).0: i32) = move _6;
+//         discriminant(_0) = 1;
+//         goto -> bb3;
+//     }
+//     bb3: {
+//         return;
+//     }
+//     bb4: {
+//         _10 = ((_1 as Ok).0: u32);
+//         ((_0 as Ok).0: u32) = move _10;
+//         discriminant(_0) = 0;
+//         goto -> bb3;
+//     }
+// }
+// END rustc.try_identity.SimplifyArmIdentity.before.mir
+
+// START rustc.try_identity.SimplifyArmIdentity.after.mir
+// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+//     let mut _0: std::result::Result<u32, i32>;
+//     let _2: u32;
+//     let mut _3: std::result::Result<u32, i32>;
+//     let mut _4: std::result::Result<u32, i32>;
+//     let mut _5: isize;
+//     let _6: i32;
+//     let mut _7: !;
+//     let mut _8: i32;
+//     let mut _9: i32;
+//     let _10: u32;
+//     let mut _11: u32;
+//     scope 1 {
+//     }
+//     scope 2 {
+//         scope 3 {
+//             scope 7 {
+//             }
+//             scope 8 {
+//                 let mut _12: i32;
+//             }
+//         }
+//     }
+//     scope 4 {
+//         scope 5 {
+//         }
+//     }
+//     scope 6 {
+//     }
+//     bb0: {
+//         _5 = discriminant(_1);
+//         switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
+//     }
+//     bb1: {
+//         unreachable;
+//     }
+//     bb2: {
+//         _0 = move _1;
+//         nop;
+//         nop;
+//         goto -> bb3;
+//     }
+//     bb3: {
+//         return;
+//     }
+//     bb4: {
+//         _0 = move _1;
+//         nop;
+//         nop;
+//         goto -> bb3;
+//     }
+// }
+// END rustc.try_identity.SimplifyArmIdentity.after.mir
+
+// START rustc.try_identity.SimplifyBranchSame.after.mir
+// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+//     let mut _0: std::result::Result<u32, i32>;
+//     let _2: u32;
+//     let mut _3: std::result::Result<u32, i32>;
+//     let mut _4: std::result::Result<u32, i32>;
+//     let mut _5: isize;
+//     let _6: i32;
+//     let mut _7: !;
+//     let mut _8: i32;
+//     let mut _9: i32;
+//     let _10: u32;
+//     let mut _11: u32;
+//     scope 1 {
+//     }
+//     scope 2 {
+//         scope 3 {
+//             scope 7 {
+//             }
+//             scope 8 {
+//                 let mut _12: i32;
+//             }
+//         }
+//     }
+//     scope 4 {
+//         scope 5 {
+//         }
+//     }
+//     scope 6 {
+//     }
+//     bb0: {
+//         _5 = discriminant(_1);
+//         goto -> bb2;
+//     }
+//     bb1: {
+//         return;
+//     }
+//     bb2: {
+//         _0 = move _1;
+//         nop;
+//         nop;
+//         goto -> bb1;
+//     }
+// }
+// END rustc.try_identity.SimplifyBranchSame.after.mir
+
+// START rustc.try_identity.SimplifyLocals.after.mir
+// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+//     let mut _0: std::result::Result<u32, i32>;
+//     let mut _2: isize;
+//     scope 1 {
+//     }
+//     scope 2 {
+//         scope 3 {
+//             scope 7 {
+//             }
+//             scope 8 {
+//             }
+//         }
+//     }
+//     scope 4 {
+//         scope 5 {
+//         }
+//     }
+//     scope 6 {
+//     }
+//     bb0: {
+//         _2 = discriminant(_1);
+//         _0 = move _1;
+//         return;
+//     }
+// }
+// END rustc.try_identity.SimplifyLocals.after.mir
diff --git a/src/test/run-make-fulldeps/pretty-print-path-suffix/Makefile b/src/test/run-make-fulldeps/pretty-print-path-suffix/Makefile
deleted file mode 100644 (file)
index 899457f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
--include ../tools.mk
-
-all:
-       $(RUSTC) -o $(TMPDIR)/foo.out -Z unpretty=hir=foo input.rs
-       $(RUSTC) -o $(TMPDIR)/nest_foo.out -Z unpretty=hir=nest::foo input.rs
-       $(RUSTC) -o $(TMPDIR)/foo_method.out -Z unpretty=hir=foo_method input.rs
-       diff -u $(TMPDIR)/foo.out foo.pp
-       diff -u $(TMPDIR)/nest_foo.out nest_foo.pp
-       diff -u $(TMPDIR)/foo_method.out foo_method.pp
diff --git a/src/test/run-make-fulldeps/pretty-print-path-suffix/foo.pp b/src/test/run-make-fulldeps/pretty-print-path-suffix/foo.pp
deleted file mode 100644 (file)
index fa754af..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-
-pub fn foo() -> i32 { 45 } /* foo */
-
-
-pub fn foo() -> &'static str { "i am a foo." } /* nest::foo */
diff --git a/src/test/run-make-fulldeps/pretty-print-path-suffix/foo_method.pp b/src/test/run-make-fulldeps/pretty-print-path-suffix/foo_method.pp
deleted file mode 100644 (file)
index 2408c3a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-fn foo_method(self: &Self)
- -> &'static str { return "i am very similar to foo."; } /*
-nest::{{impl}}::foo_method */
diff --git a/src/test/run-make-fulldeps/pretty-print-path-suffix/input.rs b/src/test/run-make-fulldeps/pretty-print-path-suffix/input.rs
deleted file mode 100644 (file)
index d075c46..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#![crate_type="lib"]
-
-pub fn
-foo() -> i32
-{ 45 }
-
-pub fn bar() -> &'static str { "i am not a foo." }
-
-pub mod nest {
-    pub fn foo() -> &'static str { "i am a foo." }
-
-    struct S;
-    impl S {
-        fn foo_method(&self) -> &'static str {
-            return "i am very similar to foo.";
-        }
-    }
-}
diff --git a/src/test/run-make-fulldeps/pretty-print-path-suffix/nest_foo.pp b/src/test/run-make-fulldeps/pretty-print-path-suffix/nest_foo.pp
deleted file mode 100644 (file)
index 0be3929..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-pub fn foo() -> &'static str { "i am a foo." } /* nest::foo */
index 0bf17302b069d50991f281ff6a87e9895b21096f..d6d49df63ef1556a5f7540fc0280b1fc96b5aa31 100644 (file)
@@ -22,7 +22,6 @@
 use syntax::ptr::P;
 use syntax::print::pprust;
 use syntax::token;
-use syntax_expand::config::process_configure_mod;
 use std::fmt;
 
 // Copied out of syntax::util::parser_testing
@@ -75,7 +74,7 @@ fn str_compare<T, F: Fn(&T) -> String>(e: &str, expected: &[T], actual: &[T], f:
 }
 
 fn sess() -> ParseSess {
-    ParseSess::new(FilePathMapping::empty(), process_configure_mod)
+    ParseSess::new(FilePathMapping::empty())
 }
 
 fn check_expr_attrs(es: &str, expected: &[&str]) {
index 2411b9634c32a63d24525536f74c2052a8b7b94a..cf675831cfe06e412e22adc17391a6f9ed1b65b4 100644 (file)
@@ -12,7 +12,6 @@
 use std::path::Path;
 use syntax::sess::ParseSess;
 use syntax::source_map::FilePathMapping;
-use syntax_expand::config::process_configure_mod;
 
 #[path = "mod_dir_simple/test.rs"]
 mod gravy;
@@ -24,7 +23,7 @@ pub fn main() {
 }
 
 fn parse() {
-    let parse_session = ParseSess::new(FilePathMapping::empty(), process_configure_mod);
+    let parse_session = ParseSess::new(FilePathMapping::empty());
 
     let path = Path::new(file!());
     let path = path.canonicalize().unwrap();
index 5da0297f64564a73c4dceca2c2a9a1c7fe32dc79..290562046e213df063851cf3c3d734b9ae76fdca 100644 (file)
@@ -33,7 +33,6 @@
 use syntax::mut_visit::{self, MutVisitor, visit_clobber};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax_expand::config::process_configure_mod;
 
 fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
     let src_as_string = src.to_string();
@@ -205,7 +204,7 @@ fn main() {
 }
 
 fn run() {
-    let ps = ParseSess::new(FilePathMapping::empty(), process_configure_mod);
+    let ps = ParseSess::new(FilePathMapping::empty());
 
     iter_exprs(2, &mut |mut e| {
         // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`,
index 64c9f69311582cfd8dfe7e59a2968f62f880d90d..b299fc558410de26a99969b83d90e9f82f0aeac4 100644 (file)
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}}
index ba5d58a51d2dd928613049c31f99bae7b4cd9892..2d4175ea8eb7da4c4af5bbd19768664e08e89683 100644 (file)
@@ -11,10 +11,10 @@ LL |     Y
    |     ^
 
 error[E0013]: constant functions cannot refer to statics, use a constant instead
-  --> $DIR/const-fn-not-safe-for-const.rs:25:5
+  --> $DIR/const-fn-not-safe-for-const.rs:25:6
    |
 LL |     &Y
-   |     ^^
+   |      ^
 
 error: aborting due to 3 previous errors
 
index 5ce21e378cd1e777c59f9b8229c6c83b8d5dab7d..cb1663ed22f9593fca18305b0100b9d0308e8f96 100644 (file)
@@ -116,10 +116,10 @@ LL | const fn foo25() -> u32 { BAR }
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
 
 error[E0723]: cannot access `static` items in const fn
-  --> $DIR/min_const_fn.rs:91:36
+  --> $DIR/min_const_fn.rs:91:37
    |
 LL | const fn foo26() -> &'static u32 { &BAR }
-   |                                    ^^^^
+   |                                     ^^^
    |
    = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
    = help: add `#![feature(const_fn)]` to the crate attributes to enable
index 0c09f7ec52fa20ff8cf25cd21aba8c7d54184e0b..0efb6bfd10a1707034db4289b0e41bef5e1eeef8 100644 (file)
@@ -4,20 +4,20 @@ error[E0017]: references in constants may only refer to immutable values
 LL |         let b: *mut u32 = &mut a;
    |                           ^^^^^^ constants require immutable values
 
-error[E0019]: constant contains unimplemented expression type
+error[E0658]: dereferencing raw pointers in constants is unstable
   --> $DIR/projection_qualif.rs:7:18
    |
 LL |         unsafe { *b = 5; }
    |                  ^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
+   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
 
-error[E0658]: dereferencing raw pointers in constants is unstable
+error[E0019]: constant contains unimplemented expression type
   --> $DIR/projection_qualif.rs:7:18
    |
 LL |         unsafe { *b = 5; }
    |                  ^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/51911
-   = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
 
 error: aborting due to 3 previous errors
 
index 7a49e89a1af701705cb7ac8e02c4899e852ad897..8d875d37d85f9ceeb143ba1fe1c7a8620372c9ec 100644 (file)
@@ -4,17 +4,17 @@ error[E0017]: references in constants may only refer to immutable values
 LL | const C1: &'static mut [usize] = &mut [];
    |                                  ^^^^^^^ constants require immutable values
 
-error[E0017]: references in constants may only refer to immutable values
-  --> $DIR/issue-17718-const-bad-values.rs:5:41
+error[E0013]: constants cannot refer to statics, use a constant instead
+  --> $DIR/issue-17718-const-bad-values.rs:5:46
    |
 LL | const C2: &'static mut usize = unsafe { &mut S };
-   |                                         ^^^^^^ constants require immutable values
+   |                                              ^
 
-error[E0013]: constants cannot refer to statics, use a constant instead
+error[E0017]: references in constants may only refer to immutable values
   --> $DIR/issue-17718-const-bad-values.rs:5:41
    |
 LL | const C2: &'static mut usize = unsafe { &mut S };
-   |                                         ^^^^^^
+   |                                         ^^^^^^ constants require immutable values
 
 error: aborting due to 3 previous errors
 
index 15c3e67f7a1a6c57e6ad928de4eb3f2b720acb50..27aad9c03cebea8c02834171349fbe9fb42d2e4b 100644 (file)
@@ -1,8 +1,8 @@
 error[E0013]: constants cannot refer to statics, use a constant instead
-  --> $DIR/issue-17718-references.rs:9:28
+  --> $DIR/issue-17718-references.rs:9:29
    |
 LL | const T2: &'static usize = &S;
-   |                            ^^
+   |                             ^
 
 error[E0013]: constants cannot refer to statics, use a constant instead
   --> $DIR/issue-17718-references.rs:14:19
index 4e848c261be330267b36257baedbad050b2d7880..d58822f16eb35b419d092ea65b9c0cc37d6041cd 100644 (file)
@@ -1,8 +1,8 @@
 error[E0013]: constants cannot refer to statics, use a constant instead
-  --> $DIR/issue-18118-2.rs:4:9
+  --> $DIR/issue-18118-2.rs:4:10
    |
 LL |         &p
-   |         ^^
+   |          ^
 
 error: aborting due to previous error
 
index 851bc5dfbdd9e20ebd4df7287d91b328fc91ae31..9f5f6333602f5889f6a3765edd10cb1a8914f0ed 100644 (file)
@@ -1,14 +1,15 @@
-error: unnecessary visibility qualifier
+error[E0449]: unnecessary visibility qualifier
   --> $DIR/issue-28433.rs:2:5
    |
 LL |     pub Duck,
-   |     ^^^ `pub` not permitted here
+   |     ^^^ `pub` not permitted here because it's implied
 
-error: unnecessary visibility qualifier
+error[E0449]: unnecessary visibility qualifier
   --> $DIR/issue-28433.rs:5:5
    |
 LL |     pub(crate) Dove
-   |     ^^^^^^^^^^ `pub` not permitted here
+   |     ^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0449`.
index 1f53a92793236f82808a1b9bcba3cf2c32cb8fcd..7d3fc83786e9d40619f520459f4842f50917fddd 100644 (file)
@@ -4,7 +4,7 @@ trait T {
     fn qux() -> Option<usize> {
         let _ = if true {
         });
-//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
+//~^ ERROR expected one of `async`
 //~| ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
 //~| ERROR expected identifier, found `;`
         Some(4)
index 39e3ad7b6b4fd221796bae5fdac95446edb3c824..e0b15130c337d5401a23fcc95847b2b0207d3472 100644 (file)
@@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
 LL |         });
    |          ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `;`
+error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;`
   --> $DIR/issue-60075.rs:6:11
    |
 LL |     fn qux() -> Option<usize> {
index ab37dd7c39dbe95a3d96eb14fdea1a365b8e4d75..70256a59231fb799b0fa6bd87146a9029875caad 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `...`
+error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...`
   --> $DIR/issue-32446.rs:4:11
    |
 LL | trait T { ... }
-   |           ^^^ expected one of 7 possible tokens
+   |           ^^^ expected one of 9 possible tokens
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs b/src/test/ui/parser/issue-65041-empty-vis-matcher-in-enum.rs
new file mode 100644 (file)
index 0000000..ef89e31
--- /dev/null
@@ -0,0 +1,28 @@
+// check-pass
+
+// Here we check that a `:vis` macro matcher subsititued for the empty visibility
+// (`VisibilityKind::Inherited`) is accepted when used before an enum variant.
+
+fn main() {}
+
+macro_rules! mac_variant {
+    ($vis:vis MARKER) => {
+        enum Enum {
+            $vis Unit,
+
+            $vis Tuple(u8, u16),
+
+            $vis Struct { f: u8 },
+        }
+    }
+}
+
+mac_variant!(MARKER);
+
+// We also accept visibilities on variants syntactically but not semantically.
+#[cfg(FALSE)]
+enum E {
+    pub U,
+    pub(crate) T(u8),
+    pub(super) T { f: String }
+}
diff --git a/src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs b/src/test/ui/parser/issue-65041-empty-vis-matcher-in-trait.rs
new file mode 100644 (file)
index 0000000..b08767b
--- /dev/null
@@ -0,0 +1,28 @@
+// check-pass
+
+// Here we check that a `:vis` macro matcher subsititued for the empty visibility
+// (`VisibilityKind::Inherited`) is accepted when used before an item in a trait.
+
+fn main() {}
+
+macro_rules! mac_in_trait {
+    ($vis:vis MARKER) => {
+        $vis fn beta() {}
+
+        $vis const GAMMA: u8;
+
+        $vis type Delta;
+    }
+}
+
+trait Alpha {
+    mac_in_trait!(MARKER);
+}
+
+// We also accept visibilities on items in traits syntactically but not semantically.
+#[cfg(FALSE)]
+trait Foo {
+    pub fn bar();
+    pub(crate) type baz;
+    pub(super) const QUUX: u8;
+}
index 958c90b7c0a16e2358c51fbee15a79d9d14f477c..5021886bf9881bef35bac787c2d09bc3e491cd0a 100644 (file)
@@ -1,6 +1,6 @@
 macro_rules! bah {
     ($a:expr) => ($a)
-    //~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
+    //~^ ERROR expected one of `async`
 }
 
 trait bar {
index dd97a3afa99fe30bec7883bf2b65107a5456ce84..0a433ab278e43b327de3daff1732efdabc31a856 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found `2`
+error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2`
   --> $DIR/trait-non-item-macros.rs:2:19
    |
 LL |     ($a:expr) => ($a)
-   |                   ^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`
+   |                   ^^ expected one of 8 possible tokens
 ...
 LL |     bah!(2);
    |     -------- in this macro invocation
index 795471954112704884a869090c29477d75bcb7f6..9f3d78d584d44d535216247499299fe5db934901 100644 (file)
@@ -1,7 +1,9 @@
 trait T {
+//~^ ERROR `main` function not found in crate `missing_close_brace_in_trait`
     fn foo(&self);
 
-pub(crate) struct Bar<T>(); //~ ERROR expected one of
+pub(crate) struct Bar<T>();
+//~^ ERROR expected one of
 
 impl T for Bar<usize> {
 fn foo(&self) {}
index 1bd8e445fadd344a8f94e4d8659939597424dd2d..cbaf9315e8540847a06d98b33fe2a4384938314e 100644 (file)
@@ -1,5 +1,5 @@
 error: this file contains an un-closed delimiter
-  --> $DIR/missing-close-brace-in-trait.rs:10:66
+  --> $DIR/missing-close-brace-in-trait.rs:12:66
    |
 LL | trait T {
    |         - un-closed delimiter
@@ -7,19 +7,24 @@ LL | trait T {
 LL | fn main() {}
    |                                                                  ^
 
-error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found keyword `pub`
-  --> $DIR/missing-close-brace-in-trait.rs:4:1
+error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct`
+  --> $DIR/missing-close-brace-in-trait.rs:5:12
    |
-LL | trait T {
-   |         - unclosed delimiter
-LL |     fn foo(&self);
-   |                   -
-   |                   |
-   |                   expected one of 7 possible tokens
-   |                   help: `}` may belong here
-LL | 
 LL | pub(crate) struct Bar<T>();
-   | ^^^ unexpected token
+   |            ^^^^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`
+
+error[E0601]: `main` function not found in crate `missing_close_brace_in_trait`
+  --> $DIR/missing-close-brace-in-trait.rs:1:1
+   |
+LL | / trait T {
+LL | |
+LL | |     fn foo(&self);
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |_________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-trait.rs`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0601`.
index 817692cc82c861893ab3e40e012b4fdaa35dba29..efd09a0364ee025c2c391d49371cbbfd633453dd 100644 (file)
@@ -1,8 +1,9 @@
-error: unnecessary visibility qualifier
+error[E0449]: unnecessary visibility qualifier
   --> $DIR/trait-pub-assoc-const.rs:2:5
    |
 LL |     pub const Foo: u32;
-   |     ^^^ `pub` not permitted here
+   |     ^^^ `pub` not permitted here because it's implied
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0449`.
index 400be6af22a82cdb7072a49fc1dda9121280ae8e..e76373f5c5f8f78b7f3094a2acac841c651a2a5e 100644 (file)
@@ -1,8 +1,9 @@
-error: unnecessary visibility qualifier
+error[E0449]: unnecessary visibility qualifier
   --> $DIR/trait-pub-assoc-ty.rs:2:5
    |
 LL |     pub type Foo;
-   |     ^^^ `pub` not permitted here
+   |     ^^^ `pub` not permitted here because it's implied
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0449`.
index b3617a4aa9b0143daafcf1cb9105c1fe18977670..0e3fe027cb5f822745605b5d01a804391edf040b 100644 (file)
@@ -1,8 +1,9 @@
-error: unnecessary visibility qualifier
+error[E0449]: unnecessary visibility qualifier
   --> $DIR/trait-pub-method.rs:2:5
    |
 LL |     pub fn foo();
-   |     ^^^ `pub` not permitted here
+   |     ^^^ `pub` not permitted here because it's implied
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0449`.
index 1dea40122656927d57648b81983b3c7757f342a5..721890db4fbd7f73b41b7bd482463fb6cd886f56 100644 (file)
@@ -1,6 +1,5 @@
-// Check that we can manually implement an object
-// unsafe trait for its trait object
-//
+// Check that we can manually implement an object-unsafe trait for its trait object.
+
 // run-pass
 
 #![feature(object_safe_for_dispatch)]
@@ -46,7 +45,7 @@ fn main() {
 
     let mut res = String::new();
 
-    // Directly call static
+    // Directly call static.
     res.push(Struct::stat()); // "A"
     res.push(<dyn Bad>::stat()); // "AC"
 
@@ -55,15 +54,13 @@ fn main() {
     // These look similar enough...
     let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) };
 
-    // Call virtual
+    // Call virtual.
     res.push(s.virt()); // "ACB"
     res.push(bad.virt()); // "ACBD"
 
-    // Indirectly call static
+    // Indirectly call static.
     res.push(s.indirect()); // "ACBDA"
     res.push(bad.indirect()); // "ACBDAC"
 
-    if &res != "ACBDAC" {
-        panic!();
-    }
+    assert_eq!(&res, "ACBDAC");
 }
index 722c3883fdda4da58bfb7ae106b7cb2d79a9982a..313d39de36b6a98d6f156642c9049a109c4f1d0d 100644 (file)
@@ -8,14 +8,12 @@
 
 static C: &u32 = &A;
 //~^ ERROR thread-local statics cannot be accessed at compile-time
-//~| ERROR thread-local variable borrowed past end of function
 
 const D: u32 = A;
 //~^ ERROR thread-local statics cannot be accessed at compile-time
 
 const E: &u32 = &A;
 //~^ ERROR thread-local statics cannot be accessed at compile-time
-//~| ERROR thread-local variable borrowed past end of function
 
 const fn f() -> u32 {
     A
index 2983ac3f60cf2fbbd951ba0124f3635a41a9c00b..9890597b7bd5bc23e95ab4908324c337f243f3f4 100644 (file)
@@ -5,45 +5,28 @@ LL | static B: u32 = A;
    |                 ^
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
-  --> $DIR/thread-local-in-ctfe.rs:9:18
+  --> $DIR/thread-local-in-ctfe.rs:9:19
    |
 LL | static C: &u32 = &A;
-   |                  ^^
-
-error[E0712]: thread-local variable borrowed past end of function
-  --> $DIR/thread-local-in-ctfe.rs:9:18
-   |
-LL | static C: &u32 = &A;
-   |                  ^^- end of enclosing function is here
-   |                  |
-   |                  thread-local variables cannot be borrowed beyond the end of the function
+   |                   ^
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
-  --> $DIR/thread-local-in-ctfe.rs:13:16
+  --> $DIR/thread-local-in-ctfe.rs:12:16
    |
 LL | const D: u32 = A;
    |                ^
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
-  --> $DIR/thread-local-in-ctfe.rs:16:17
-   |
-LL | const E: &u32 = &A;
-   |                 ^^
-
-error[E0712]: thread-local variable borrowed past end of function
-  --> $DIR/thread-local-in-ctfe.rs:16:17
+  --> $DIR/thread-local-in-ctfe.rs:15:18
    |
 LL | const E: &u32 = &A;
-   |                 ^^- end of enclosing function is here
-   |                 |
-   |                 thread-local variables cannot be borrowed beyond the end of the function
+   |                  ^
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
-  --> $DIR/thread-local-in-ctfe.rs:21:5
+  --> $DIR/thread-local-in-ctfe.rs:19:5
    |
 LL |     A
    |     ^
 
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0712`.
index 82624650a549950183429ba3f0f2e896a7fac5e1..82c76eb693a0d65efb5d29e00eff0357db9b0f73 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// Check that trait-objects without a principal codegen properly.
+// Check that trait objects without a principal codegen properly.
 
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::mem;
@@ -10,7 +10,7 @@
 struct SetOnDrop<'a>(&'a AtomicUsize, [u8; 64]);
 impl<'a> Drop for SetOnDrop<'a> {
     fn drop(&mut self) {
-        self.0.store(self.0.load(Ordering::Relaxed)+1, Ordering::Relaxed);
+        self.0.store(self.0.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
     }
 }
 
index 67a63f89d8c0e5b22fb52cc33274283819f41792..644e2a76a87a129f597dc40b47593fc8f72539cb 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 67a63f89d8c0e5b22fb52cc33274283819f41792
+Subproject commit 644e2a76a87a129f597dc40b47593fc8f72539cb