about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-10-15 00:54:10 +0000
committerbors <bors@rust-lang.org>2019-10-15 00:54:10 +0000
commite369d87b015a84653343032833d65d0545fd3f26 (patch)
treed58c82d0b3d84633a9452fa78a4c3c136cfa229b
parente413dc36a83a5aad3ab6270373000693a917e92b (diff)
parent9422feb43395a7a1df60d6e81b5ead87abc90b4b (diff)
downloadrust-e369d87b015a84653343032833d65d0545fd3f26.tar.gz
rust-e369d87b015a84653343032833d65d0545fd3f26.zip
Auto merge of #65422 - tmandry:rollup-r5u3mlc, r=tmandry
Rollup of 10 pull requests

Successful merges:

 - #65170 (rustc_metadata: Privatize private code and remove dead code)
 - #65260 (Optimize `LexicalResolve::expansion`.)
 - #65261 (Remove `Option` from `TokenStream`)
 - #65332 (std::fmt: reorder docs)
 - #65340 (Several changes to the codegen backend organization)
 - #65365 (Include const generic arguments in metadata)
 - #65398 (Bring attention to suggestions when the only difference is capitalization)
 - #65410 (syntax: add parser recovery for intersection- / and-patterns `p1 @ p2`)
 - #65415 (Remove an outdated test output file)
 - #65416 (Minor sync changes)

Failed merges:

r? @ghost
-rw-r--r--src/liballoc/fmt.rs366
-rw-r--r--src/librustc/infer/lexical_region_resolve/mod.rs26
-rw-r--r--src/librustc/middle/cstore.rs7
-rw-r--r--src/librustc/session/config.rs3
-rw-r--r--src/librustc/ty/context.rs8
-rw-r--r--src/librustc/ty/mod.rs3
-rw-r--r--src/librustc_codegen_llvm/builder.rs1
-rw-r--r--src/librustc_codegen_llvm/callee.rs2
-rw-r--r--src/librustc_codegen_llvm/common.rs42
-rw-r--r--src/librustc_codegen_llvm/context.rs25
-rw-r--r--src/librustc_codegen_llvm/error_codes.rs38
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs6
-rw-r--r--src/librustc_codegen_llvm/lib.rs13
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs7
-rw-r--r--src/librustc_codegen_ssa/README.md2
-rw-r--r--src/librustc_codegen_ssa/back/write.rs6
-rw-r--r--src/librustc_codegen_ssa/base.rs17
-rw-r--r--src/librustc_codegen_ssa/callee.rs53
-rw-r--r--src/librustc_codegen_ssa/common.rs5
-rw-r--r--src/librustc_codegen_ssa/error_codes.rs35
-rw-r--r--src/librustc_codegen_ssa/lib.rs12
-rw-r--r--src/librustc_codegen_ssa/meth.rs12
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs8
-rw-r--r--src/librustc_codegen_ssa/mir/mod.rs4
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs4
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs17
-rw-r--r--src/librustc_codegen_ssa/traits/backend.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/builder.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/consts.rs4
-rw-r--r--src/librustc_codegen_ssa/traits/debuginfo.rs2
-rw-r--r--src/librustc_codegen_ssa/traits/declare.rs4
-rw-r--r--src/librustc_codegen_ssa/traits/misc.rs8
-rw-r--r--src/librustc_codegen_ssa/traits/mod.rs1
-rw-r--r--src/librustc_codegen_utils/codegen_backend.rs1
-rw-r--r--src/librustc_codegen_utils/lib.rs5
-rw-r--r--src/librustc_data_structures/sync.rs51
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_errors/annotate_snippet_emitter_writer.rs4
-rw-r--r--src/librustc_errors/emitter.rs49
-rw-r--r--src/librustc_errors/lib.rs32
-rw-r--r--src/librustc_interface/passes.rs26
-rw-r--r--src/librustc_metadata/creader.rs88
-rw-r--r--src/librustc_metadata/cstore.rs130
-rw-r--r--src/librustc_metadata/cstore_impl.rs26
-rw-r--r--src/librustc_metadata/decoder.rs144
-rw-r--r--src/librustc_metadata/dependency_format.rs2
-rw-r--r--src/librustc_metadata/dynamic_lib.rs61
-rw-r--r--src/librustc_metadata/encoder.rs51
-rw-r--r--src/librustc_metadata/foreign_modules.rs2
-rw-r--r--src/librustc_metadata/index.rs14
-rw-r--r--src/librustc_metadata/link_args.rs2
-rw-r--r--src/librustc_metadata/locator.rs89
-rw-r--r--src/librustc_metadata/native_libs.rs4
-rw-r--r--src/librustc_metadata/schema.rs62
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs6
-rw-r--r--src/librustc_resolve/lib.rs11
-rw-r--r--src/libsyntax/attr/mod.rs2
-rw-r--r--src/libsyntax/ext/expand.rs4
-rw-r--r--src/libsyntax/ext/mbe/transcribe.rs2
-rw-r--r--src/libsyntax/ext/placeholders.rs16
-rw-r--r--src/libsyntax/ext/proc_macro_server.rs2
-rw-r--r--src/libsyntax/json.rs6
-rw-r--r--src/libsyntax/mut_visit.rs6
-rw-r--r--src/libsyntax/parse/attr.rs2
-rw-r--r--src/libsyntax/parse/parser.rs4
-rw-r--r--src/libsyntax/parse/parser/pat.rs60
-rw-r--r--src/libsyntax/print/pprust.rs3
-rw-r--r--src/libsyntax/source_map.rs3
-rw-r--r--src/libsyntax/tokenstream.rs224
-rw-r--r--src/libsyntax_ext/plugin_macro_defs.rs2
-rw-r--r--src/test/ui/const-generics/auxiliary/const_generic_lib.rs9
-rw-r--r--src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs10
-rw-r--r--src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr21
-rw-r--r--src/test/ui/const-generics/const-argument-cross-crate.rs12
-rw-r--r--src/test/ui/const-generics/const-parameter-uppercase-lint.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr4
-rw-r--r--src/test/ui/error-codes/E0423.stderr2
-rw-r--r--src/test/ui/expr_attr_paren_order.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr16
-rw-r--r--src/test/ui/hygiene/globs.stderr2
-rw-r--r--src/test/ui/hygiene/rustc-macro-transparency.stderr2
-rw-r--r--src/test/ui/issues/issue-10200.stderr2
-rw-r--r--src/test/ui/issues/issue-17546.stderr4
-rw-r--r--src/test/ui/issues/issue-17718-const-naming.stderr2
-rw-r--r--src/test/ui/issues/issue-46332.stderr2
-rw-r--r--src/test/ui/lint/lint-non-camel-case-types.stderr10
-rw-r--r--src/test/ui/lint/lint-non-snake-case-functions.stderr6
-rw-r--r--src/test/ui/lint/lint-non-uppercase-statics.stderr2
-rw-r--r--src/test/ui/lint/lint-uppercase-variables.stderr6
-rw-r--r--src/test/ui/lint/not_found.stderr2
-rw-r--r--src/test/ui/lint/reasons.stderr2
-rw-r--r--src/test/ui/lint/use_suggestion_json.stderr2
-rw-r--r--src/test/ui/parser/intersection-patterns.rs40
-rw-r--r--src/test/ui/parser/intersection-patterns.stderr33
-rw-r--r--src/test/ui/resolve/issue-21221-1.stderr2
-rw-r--r--src/test/ui/resolve/levenshtein.stderr4
-rw-r--r--src/test/ui/rust-2018/issue-52202-use-suggestions.stderr2
98 files changed, 1099 insertions, 1049 deletions
diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs
index 68cbc366d7b..1e39b7f822e 100644
--- a/src/liballoc/fmt.rs
+++ b/src/liballoc/fmt.rs
@@ -80,24 +80,187 @@
 //! arguments which have names. Like with positional parameters, it is not
 //! valid to provide named parameters that are unused by the format string.
 //!
-//! ## Argument types
+//! # Formatting Parameters
+//!
+//! Each argument being formatted can be transformed by a number of formatting
+//! parameters (corresponding to `format_spec` in the syntax above). These
+//! parameters affect the string representation of what's being formatted.
+//!
+//! ## Fill/Alignment
+//!
+//! The fill character is provided normally in conjunction with the
+//! [`width`](#width)
+//! parameter. This indicates that if the value being formatted is smaller than
+//! `width` some extra characters will be printed around it. The extra
+//! characters are specified by `fill`, and the alignment can be one of the
+//! following options:
+//!
+//! * `<` - the argument is left-aligned in `width` columns
+//! * `^` - the argument is center-aligned in `width` columns
+//! * `>` - the argument is right-aligned in `width` columns
+//!
+//! Note that alignment may not be implemented by some types. In particular, it
+//! is not generally implemented for the `Debug` trait.  A good way to ensure
+//! padding is applied is to format your input, then use this resulting string
+//! to pad your output.
+//!
+//! ## Sign/`#`/`0`
+//!
+//! These can all be interpreted as flags for a particular formatter.
+//!
+//! * `+` - This is intended for numeric types and indicates that the sign
+//!         should always be printed. Positive signs are never printed by
+//!         default, and the negative sign is only printed by default for the
+//!         `Signed` trait. This flag indicates that the correct sign (`+` or `-`)
+//!         should always be printed.
+//! * `-` - Currently not used
+//! * `#` - This flag is indicates that the "alternate" form of printing should
+//!         be used. The alternate forms are:
+//!     * `#?` - pretty-print the [`Debug`] formatting
+//!     * `#x` - precedes the argument with a `0x`
+//!     * `#X` - precedes the argument with a `0x`
+//!     * `#b` - precedes the argument with a `0b`
+//!     * `#o` - precedes the argument with a `0o`
+//! * `0` - This is used to indicate for integer formats that the padding should
+//!         both be done with a `0` character as well as be sign-aware. A format
+//!         like `{:08}` would yield `00000001` for the integer `1`, while the
+//!         same format would yield `-0000001` for the integer `-1`. Notice that
+//!         the negative version has one fewer zero than the positive version.
+//!         Note that padding zeroes are always placed after the sign (if any)
+//!         and before the digits. When used together with the `#` flag, a similar
+//!         rule applies: padding zeroes are inserted after the prefix but before
+//!         the digits.
+//!
+//! ## Width
+//!
+//! This is a parameter for the "minimum width" that the format should take up.
+//! If the value's string does not fill up this many characters, then the
+//! padding specified by fill/alignment will be used to take up the required
+//! space.
+//!
+//! The default [fill/alignment](#fillalignment) for non-numerics is a space and
+//! left-aligned. The
+//! defaults for numeric formatters is also a space but with right-alignment. If
+//! the `0` flag is specified for numerics, then the implicit fill character is
+//! `0`.
+//!
+//! The value for the width can also be provided as a [`usize`] in the list of
+//! parameters by using the dollar syntax indicating that the second argument is
+//! a [`usize`] specifying the width, for example:
+//!
+//! ```
+//! // All of these print "Hello x    !"
+//! println!("Hello {:5}!", "x");
+//! println!("Hello {:1$}!", "x", 5);
+//! println!("Hello {1:0$}!", 5, "x");
+//! println!("Hello {:width$}!", "x", width = 5);
+//! ```
+//!
+//! Referring to an argument with the dollar syntax does not affect the "next
+//! argument" counter, so it's usually a good idea to refer to arguments by
+//! position, or use named arguments.
+//!
+//! ## Precision
+//!
+//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
+//! longer than this width, then it is truncated down to this many characters and that truncated
+//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
+//!
+//! For integral types, this is ignored.
+//!
+//! For floating-point types, this indicates how many digits after the decimal point should be
+//! printed.
+//!
+//! There are three possible ways to specify the desired `precision`:
+//!
+//! 1. An integer `.N`:
+//!
+//!    the integer `N` itself is the precision.
+//!
+//! 2. An integer or name followed by dollar sign `.N$`:
+//!
+//!    use format *argument* `N` (which must be a `usize`) as the precision.
+//!
+//! 3. An asterisk `.*`:
+//!
+//!    `.*` means that this `{...}` is associated with *two* format inputs rather than one: the
+//!    first input holds the `usize` precision, and the second holds the value to print. Note that
+//!    in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
+//!    to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
+//!
+//! For example, the following calls all print the same thing `Hello x is 0.01000`:
+//!
+//! ```
+//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
+//! println!("Hello {0} is {1:.5}", "x", 0.01);
+//!
+//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
+//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
+//!
+//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
+//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
+//!
+//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
+//! //                          specified in first of next two args (5)}
+//! println!("Hello {} is {:.*}",    "x", 5, 0.01);
+//!
+//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
+//! //                          specified in its predecessor (5)}
+//! println!("Hello {} is {2:.*}",   "x", 5, 0.01);
+//!
+//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
+//! //                          in arg "prec" (5)}
+//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
+//! ```
 //!
-//! Each argument's type is dictated by the format string.
-//! There are various parameters which require a particular type, however.
-//! An example is the `{:.*}` syntax, which sets the number of decimal places
-//! in floating-point types:
+//! While these:
 //!
 //! ```
-//! let formatted_number = format!("{:.*}", 2, 1.234567);
+//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
+//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
+//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
+//! ```
 //!
-//! assert_eq!("1.23", formatted_number)
+//! print two significantly different things:
+//!
+//! ```text
+//! Hello, `1234.560` has 3 fractional digits
+//! Hello, `123` has 3 characters
+//! Hello, `     123` has 3 right-aligned characters
 //! ```
 //!
-//! If this syntax is used, then the number of characters to print precedes the
-//! actual object being formatted, and the number of characters must have the
-//! type [`usize`].
+//! # Escaping
+//!
+//! The literal characters `{` and `}` may be included in a string by preceding
+//! them with the same character. For example, the `{` character is escaped with
+//! `{{` and the `}` character is escaped with `}}`.
+//!
+//! # Syntax
+//!
+//! To summarize, you can find the full grammar of format strings.
+//! The syntax for the formatting language used is drawn from other languages,
+//! so it should not be too alien. Arguments are formatted with Python-like
+//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like
+//! `%`. The actual grammar for the formatting syntax is:
+//!
+//! ```text
+//! format_string := <text> [ maybe-format <text> ] *
+//! maybe-format := '{' '{' | '}' '}' | <format>
+//! format := '{' [ argument ] [ ':' format_spec ] '}'
+//! argument := integer | identifier
+//!
+//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
+//! fill := character
+//! align := '<' | '^' | '>'
+//! sign := '+' | '-'
+//! width := count
+//! precision := count | '*'
+//! type := identifier | '?' | ''
+//! count := parameter | integer
+//! parameter := argument '$'
+//! ```
 //!
-//! ## Formatting traits
+//! # Formatting traits
 //!
 //! When requesting that an argument be formatted with a particular type, you
 //! are actually requesting that an argument ascribes to a particular trait.
@@ -220,7 +383,7 @@
 //! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\"");
 //! ```
 //!
-//! ## Related macros
+//! # Related macros
 //!
 //! There are a number of related macros in the [`format!`] family. The ones that
 //! are currently implemented are:
@@ -300,185 +463,6 @@
 //! it would internally pass around this structure until it has been determined
 //! where output should go to.
 //!
-//! # Syntax
-//!
-//! The syntax for the formatting language used is drawn from other languages,
-//! so it should not be too alien. Arguments are formatted with Python-like
-//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like
-//! `%`. The actual grammar for the formatting syntax is:
-//!
-//! ```text
-//! format_string := <text> [ maybe-format <text> ] *
-//! maybe-format := '{' '{' | '}' '}' | <format>
-//! format := '{' [ argument ] [ ':' format_spec ] '}'
-//! argument := integer | identifier
-//!
-//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
-//! fill := character
-//! align := '<' | '^' | '>'
-//! sign := '+' | '-'
-//! width := count
-//! precision := count | '*'
-//! type := identifier | '?' | ''
-//! count := parameter | integer
-//! parameter := argument '$'
-//! ```
-//!
-//! # Formatting Parameters
-//!
-//! Each argument being formatted can be transformed by a number of formatting
-//! parameters (corresponding to `format_spec` in the syntax above). These
-//! parameters affect the string representation of what's being formatted.
-//!
-//! ## Fill/Alignment
-//!
-//! The fill character is provided normally in conjunction with the
-//! [`width`](#width)
-//! parameter. This indicates that if the value being formatted is smaller than
-//! `width` some extra characters will be printed around it. The extra
-//! characters are specified by `fill`, and the alignment can be one of the
-//! following options:
-//!
-//! * `<` - the argument is left-aligned in `width` columns
-//! * `^` - the argument is center-aligned in `width` columns
-//! * `>` - the argument is right-aligned in `width` columns
-//!
-//! Note that alignment may not be implemented by some types. In particular, it
-//! is not generally implemented for the `Debug` trait.  A good way to ensure
-//! padding is applied is to format your input, then use this resulting string
-//! to pad your output.
-//!
-//! ## Sign/`#`/`0`
-//!
-//! These can all be interpreted as flags for a particular formatter.
-//!
-//! * `+` - This is intended for numeric types and indicates that the sign
-//!         should always be printed. Positive signs are never printed by
-//!         default, and the negative sign is only printed by default for the
-//!         `Signed` trait. This flag indicates that the correct sign (`+` or `-`)
-//!         should always be printed.
-//! * `-` - Currently not used
-//! * `#` - This flag is indicates that the "alternate" form of printing should
-//!         be used. The alternate forms are:
-//!     * `#?` - pretty-print the [`Debug`] formatting
-//!     * `#x` - precedes the argument with a `0x`
-//!     * `#X` - precedes the argument with a `0x`
-//!     * `#b` - precedes the argument with a `0b`
-//!     * `#o` - precedes the argument with a `0o`
-//! * `0` - This is used to indicate for integer formats that the padding should
-//!         both be done with a `0` character as well as be sign-aware. A format
-//!         like `{:08}` would yield `00000001` for the integer `1`, while the
-//!         same format would yield `-0000001` for the integer `-1`. Notice that
-//!         the negative version has one fewer zero than the positive version.
-//!         Note that padding zeroes are always placed after the sign (if any)
-//!         and before the digits. When used together with the `#` flag, a similar
-//!         rule applies: padding zeroes are inserted after the prefix but before
-//!         the digits.
-//!
-//! ## Width
-//!
-//! This is a parameter for the "minimum width" that the format should take up.
-//! If the value's string does not fill up this many characters, then the
-//! padding specified by fill/alignment will be used to take up the required
-//! space.
-//!
-//! The default [fill/alignment](#fillalignment) for non-numerics is a space and
-//! left-aligned. The
-//! defaults for numeric formatters is also a space but with right-alignment. If
-//! the `0` flag is specified for numerics, then the implicit fill character is
-//! `0`.
-//!
-//! The value for the width can also be provided as a [`usize`] in the list of
-//! parameters by using the dollar syntax indicating that the second argument is
-//! a [`usize`] specifying the width, for example:
-//!
-//! ```
-//! // All of these print "Hello x    !"
-//! println!("Hello {:5}!", "x");
-//! println!("Hello {:1$}!", "x", 5);
-//! println!("Hello {1:0$}!", 5, "x");
-//! println!("Hello {:width$}!", "x", width = 5);
-//! ```
-//!
-//! Referring to an argument with the dollar syntax does not affect the "next
-//! argument" counter, so it's usually a good idea to refer to arguments by
-//! position, or use named arguments.
-//!
-//! ## Precision
-//!
-//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
-//! longer than this width, then it is truncated down to this many characters and that truncated
-//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
-//!
-//! For integral types, this is ignored.
-//!
-//! For floating-point types, this indicates how many digits after the decimal point should be
-//! printed.
-//!
-//! There are three possible ways to specify the desired `precision`:
-//!
-//! 1. An integer `.N`:
-//!
-//!    the integer `N` itself is the precision.
-//!
-//! 2. An integer or name followed by dollar sign `.N$`:
-//!
-//!    use format *argument* `N` (which must be a `usize`) as the precision.
-//!
-//! 3. An asterisk `.*`:
-//!
-//!    `.*` means that this `{...}` is associated with *two* format inputs rather than one: the
-//!    first input holds the `usize` precision, and the second holds the value to print. Note that
-//!    in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
-//!    to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
-//!
-//! For example, the following calls all print the same thing `Hello x is 0.01000`:
-//!
-//! ```
-//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
-//! println!("Hello {0} is {1:.5}", "x", 0.01);
-//!
-//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
-//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
-//!
-//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
-//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
-//!
-//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
-//! //                          specified in first of next two args (5)}
-//! println!("Hello {} is {:.*}",    "x", 5, 0.01);
-//!
-//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
-//! //                          specified in its predecessor (5)}
-//! println!("Hello {} is {2:.*}",   "x", 5, 0.01);
-//!
-//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
-//! //                          in arg "prec" (5)}
-//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
-//! ```
-//!
-//! While these:
-//!
-//! ```
-//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
-//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
-//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
-//! ```
-//!
-//! print two significantly different things:
-//!
-//! ```text
-//! Hello, `1234.560` has 3 fractional digits
-//! Hello, `123` has 3 characters
-//! Hello, `     123` has 3 right-aligned characters
-//! ```
-//!
-//! # Escaping
-//!
-//! The literal characters `{` and `}` may be included in a string by preceding
-//! them with the same character. For example, the `{` character is escaped with
-//! `{{` and the `}` character is escaped with `}}`.
-//!
 //! [`usize`]: ../../std/primitive.usize.html
 //! [`isize`]: ../../std/primitive.isize.html
 //! [`i8`]: ../../std/primitive.i8.html
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index f11f94c428e..6f55ade1e86 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -304,7 +304,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
     }
 
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
-        self.iterate_until_fixed_point("Expansion", |constraint| {
+        self.iterate_until_fixed_point(|constraint| {
             debug!("expansion: constraint={:?}", constraint);
             let (a_region, b_vid, b_data, retain) = match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
@@ -360,13 +360,21 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         match *b_data {
             VarValue::Value(cur_region) => {
                 // Identical scopes can show up quite often, if the fixed point
-                // iteration converges slowly, skip them
+                // iteration converges slowly. Skip them. This is purely an
+                // optimization.
                 if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) {
                     if a_scope == cur_scope {
                         return false;
                     }
                 }
 
+                // This is a specialized version of the `lub_concrete_regions`
+                // check below for a common case, here purely as an
+                // optimization.
+                if let ReEmpty = a_region {
+                    return false;
+                }
+
                 let mut lub = self.lub_concrete_regions(a_region, cur_region);
                 if lub == cur_region {
                     return false;
@@ -407,8 +415,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
     /// Returns the smallest region `c` such that `a <= c` and `b <= c`.
     fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
-        let tcx = self.tcx();
-
         match (a, b) {
             (&ty::ReClosureBound(..), _)
             | (_, &ty::ReClosureBound(..))
@@ -468,7 +474,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
                 // otherwise, we don't know what the free region is,
                 // so we must conservatively say the LUB is static:
-                tcx.lifetimes.re_static
+                self.tcx().lifetimes.re_static
             }
 
             (&ReScope(a_id), &ReScope(b_id)) => {
@@ -476,7 +482,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 // subtype of the region corresponding to an inner
                 // block.
                 let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id);
-                tcx.mk_region(ReScope(lub))
+                self.tcx().mk_region(ReScope(lub))
             }
 
             (&ReEarlyBound(_), &ReEarlyBound(_))
@@ -490,7 +496,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 if a == b {
                     a
                 } else {
-                    tcx.lifetimes.re_static
+                    self.tcx().lifetimes.re_static
                 }
             }
         }
@@ -860,7 +866,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
-    fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
+    fn iterate_until_fixed_point<F>(&self, mut body: F)
     where
         F: FnMut(&Constraint<'tcx>) -> (bool, bool),
     {
@@ -870,7 +876,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         while changed {
             changed = false;
             iteration += 1;
-            debug!("---- {} Iteration {}{}", "#", tag, iteration);
+            debug!("---- Expansion iteration {}", iteration);
             constraints.retain(|constraint| {
                 let (edge_changed, retain) = body(constraint);
                 if edge_changed {
@@ -880,7 +886,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 retain
             });
         }
-        debug!("---- {} Complete after {} iteration(s)", tag, iteration);
+        debug!("---- Expansion complete after {} iteration(s)", iteration);
     }
 
     fn bound_is_met(
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 065959ed09f..2170a288c92 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -32,6 +32,12 @@ pub struct CrateSource {
     pub rmeta: Option<(PathBuf, PathKind)>,
 }
 
+impl CrateSource {
+    pub fn paths(&self) -> impl Iterator<Item = &PathBuf> {
+        self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0)
+    }
+}
+
 #[derive(RustcEncodable, RustcDecodable, Copy, Clone,
          Ord, PartialOrd, Eq, PartialEq, Debug, HashStable)]
 pub enum DepKind {
@@ -208,7 +214,6 @@ pub trait CrateStore {
     fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
     fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
-    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
     fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics;
     fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
 
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 84102cea8ad..2517141542d 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -23,7 +23,7 @@ use syntax::feature_gate::UnstableFeatures;
 use syntax::source_map::SourceMap;
 
 use errors::emitter::HumanReadableErrorType;
-use errors::{ColorConfig, FatalError, Handler};
+use errors::{ColorConfig, FatalError, Handler, SourceMapperDyn};
 
 use getopts;
 
@@ -1857,6 +1857,7 @@ struct NullEmitter;
 
 impl errors::emitter::Emitter for NullEmitter {
     fn emit_diagnostic(&mut self, _: &errors::Diagnostic) {}
+    fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> { None }
 }
 
 // Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index cd52f8fa92c..256194cfb00 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -43,7 +43,7 @@ use crate::ty::subst::{UserSubsts, GenericArgKind};
 use crate::ty::{BoundVar, BindingMode};
 use crate::ty::CanonicalPolyFnSig;
 use crate::util::common::ErrorReported;
-use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet};
+use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet, NodeMap};
 use crate::util::nodemap::{FxHashMap, FxHashSet};
 use crate::util::profiling::SelfProfilerRef;
 
@@ -1051,6 +1051,9 @@ pub struct GlobalCtxt<'tcx> {
     /// Common consts, pre-interned for your convenience.
     pub consts: CommonConsts<'tcx>,
 
+    /// Resolutions of `extern crate` items produced by resolver.
+    extern_crate_map: NodeMap<CrateNum>,
+
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
     trait_map: FxHashMap<DefIndex,
@@ -1274,6 +1277,7 @@ impl<'tcx> TyCtxt<'tcx> {
             types: common_types,
             lifetimes: common_lifetimes,
             consts: common_consts,
+            extern_crate_map: resolutions.extern_crate_map,
             trait_map,
             export_map: resolutions.export_map.into_iter().map(|(k, v)| {
                 let exports: Vec<_> = v.into_iter().map(|e| {
@@ -2951,7 +2955,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
     };
     providers.extern_mod_stmt_cnum = |tcx, id| {
         let id = tcx.hir().as_local_node_id(id).unwrap();
-        tcx.cstore.extern_mod_stmt_cnum_untracked(id)
+        tcx.extern_crate_map.get(&id).cloned()
     };
     providers.all_crate_nums = |tcx, cnum| {
         assert_eq!(cnum, LOCAL_CRATE);
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 3692caada57..00b5fa23047 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -28,7 +28,7 @@ use crate::ty::subst::{Subst, InternalSubsts, SubstsRef};
 use crate::ty::util::{IntTypeExt, Discr};
 use crate::ty::walk::TypeWalker;
 use crate::util::captures::Captures;
-use crate::util::nodemap::{NodeSet, DefIdMap, FxHashMap};
+use crate::util::nodemap::{NodeMap, NodeSet, DefIdMap, FxHashMap};
 use arena::SyncDroplessArena;
 use crate::session::DataTypeKind;
 
@@ -121,6 +121,7 @@ mod sty;
 
 #[derive(Clone)]
 pub struct Resolutions {
+    pub extern_crate_map: NodeMap<CrateNum>,
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
     pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 71a6067fd48..98be0ae4433 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -52,6 +52,7 @@ const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr();
 
 impl BackendTypes for Builder<'_, 'll, 'tcx> {
     type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
+    type Function = <CodegenCx<'ll, 'tcx> as BackendTypes>::Function;
     type BasicBlock = <CodegenCx<'ll, 'tcx> as BackendTypes>::BasicBlock;
     type Type = <CodegenCx<'ll, 'tcx> as BackendTypes>::Type;
     type Funclet = <CodegenCx<'ll, 'tcx> as BackendTypes>::Funclet;
diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs
index 35d5107842d..08fa23f2a7c 100644
--- a/src/librustc_codegen_llvm/callee.rs
+++ b/src/librustc_codegen_llvm/callee.rs
@@ -33,7 +33,7 @@ pub fn get_fn(
     assert!(!instance.substs.has_param_types());
 
     let sig = instance.fn_sig(cx.tcx());
-    if let Some(&llfn) = cx.instances().borrow().get(&instance) {
+    if let Some(&llfn) = cx.instances.borrow().get(&instance) {
         return llfn;
     }
 
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 6fbea9646b8..a1a5232d588 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -2,7 +2,7 @@
 
 //! Code that is useful in various codegen modules.
 
-use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef};
+use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt};
 use crate::abi;
 use crate::consts;
 use crate::type_::Type;
@@ -86,6 +86,8 @@ impl Funclet<'ll> {
 
 impl BackendTypes for CodegenCx<'ll, 'tcx> {
     type Value = &'ll Value;
+    type Function = &'ll Value;
+
     type BasicBlock = &'ll BasicBlock;
     type Type = &'ll Type;
     type Funclet = Funclet<'ll>;
@@ -243,33 +245,23 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         struct_in_context(self.llcx, elts, packed)
     }
 
-    fn const_to_uint(&self, v: &'ll Value) -> u64 {
-        unsafe {
+    fn const_to_opt_uint(&self, v: &'ll Value) -> Option<u64> {
+        try_as_const_integral(v).map(|v| unsafe {
             llvm::LLVMConstIntGetZExtValue(v)
-        }
-    }
-
-    fn is_const_integral(&self, v: &'ll Value) -> bool {
-        unsafe {
-            llvm::LLVMIsAConstantInt(v).is_some()
-        }
+        })
     }
 
     fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option<u128> {
-        unsafe {
-            if self.is_const_integral(v) {
-                let (mut lo, mut hi) = (0u64, 0u64);
-                let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
-                                                           &mut hi, &mut lo);
-                if success {
-                    Some(hi_lo_to_u128(lo, hi))
-                } else {
-                    None
-                }
+        try_as_const_integral(v).and_then(|v| unsafe {
+            let (mut lo, mut hi) = (0u64, 0u64);
+            let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
+                                                        &mut hi, &mut lo);
+            if success {
+                Some(hi_lo_to_u128(lo, hi))
             } else {
                 None
             }
-        }
+        })
     }
 
     fn scalar_to_backend(
@@ -305,7 +297,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                         }
                     }
                     Some(GlobalAlloc::Function(fn_instance)) => {
-                        self.get_fn(fn_instance)
+                        self.get_fn_addr(fn_instance)
                     }
                     Some(GlobalAlloc::Static(def_id)) => {
                         assert!(self.tcx.is_static(def_id));
@@ -386,3 +378,9 @@ pub fn struct_in_context(
 fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
     ((hi as u128) << 64) | (lo as u128)
 }
+
+fn try_as_const_integral(v: &'ll Value) -> Option<&'ll ConstantInt> {
+    unsafe {
+        llvm::LLVMIsAConstantInt(v)
+    }
+}
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 7ca226914a5..2da93877172 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -20,7 +20,6 @@ use rustc::ty::layout::{
 use rustc::ty::{self, Ty, TyCtxt, Instance};
 use rustc::util::nodemap::FxHashMap;
 use rustc_target::spec::{HasTargetSpec, Target};
-use rustc_codegen_ssa::callee::resolve_and_get_fn;
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use crate::callee::get_fn;
 
@@ -327,11 +326,11 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         &self.vtables
     }
 
-    fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, &'ll Value>> {
-        &self.instances
+    fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value {
+        get_fn(self, instance)
     }
 
-    fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value {
+    fn get_fn_addr(&self, instance: Instance<'tcx>) -> &'ll Value {
         get_fn(self, instance)
     }
 
@@ -362,7 +361,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         let tcx = self.tcx;
         let llfn = match tcx.lang_items().eh_personality() {
             Some(def_id) if !wants_msvc_seh(self.sess()) => {
-                resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
+                self.get_fn_addr(
+                    ty::Instance::resolve(
+                        tcx,
+                        ty::ParamEnv::reveal_all(),
+                        def_id,
+                        tcx.intern_substs(&[]),
+                    ).unwrap()
+                )
             }
             _ => {
                 let name = if wants_msvc_seh(self.sess()) {
@@ -390,7 +396,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         let tcx = self.tcx;
         assert!(self.sess().target.target.options.custom_unwind_resume);
         if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
-            let llfn = resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
+            let llfn = self.get_fn_addr(
+                ty::Instance::resolve(
+                    tcx,
+                    ty::ParamEnv::reveal_all(),
+                    def_id,
+                    tcx.intern_substs(&[]),
+                ).unwrap()
+            );
             unwresume.set(Some(llfn));
             return llfn;
         }
diff --git a/src/librustc_codegen_llvm/error_codes.rs b/src/librustc_codegen_llvm/error_codes.rs
deleted file mode 100644
index 042e51ed2ba..00000000000
--- a/src/librustc_codegen_llvm/error_codes.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-register_diagnostics! {
-
-E0511: r##"
-Invalid monomorphization of an intrinsic function was used. Erroneous code
-example:
-
-```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
-#![feature(platform_intrinsics)]
-
-extern "platform-intrinsic" {
-    fn simd_add<T>(a: T, b: T) -> T;
-}
-
-fn main() {
-    unsafe { simd_add(0, 1); }
-    // error: invalid monomorphization of `simd_add` intrinsic
-}
-```
-
-The generic type has to be a SIMD type. Example:
-
-```
-#![feature(repr_simd)]
-#![feature(platform_intrinsics)]
-
-#[repr(simd)]
-#[derive(Copy, Clone)]
-struct i32x2(i32, i32);
-
-extern "platform-intrinsic" {
-    fn simd_add<T>(a: T, b: T) -> T;
-}
-
-unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok!
-```
-"##,
-
-}
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 68d9af09c42..3df8d4c2690 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -20,9 +20,9 @@ use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc::hir;
 use syntax::ast::{self, FloatTy};
 
+use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
 use rustc_codegen_ssa::traits::*;
 
-use rustc::session::Session;
 use syntax_pos::Span;
 
 use std::cmp::Ordering;
@@ -1026,10 +1026,6 @@ fn get_rust_try_fn<'ll, 'tcx>(
     rust_try
 }
 
-fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
-    span_err!(a, b, E0511, "{}", c);
-}
-
 fn generic_simd_intrinsic(
     bx: &mut Builder<'a, 'll, 'tcx>,
     name: &str,
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 52797e64f7d..fde04a68457 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -38,7 +38,7 @@ extern crate rustc_fs_util;
 extern crate rustc_driver as _;
 
 #[macro_use] extern crate log;
-#[macro_use] extern crate syntax;
+extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
 
@@ -64,8 +64,6 @@ use rustc::util::common::ErrorReported;
 use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 
-mod error_codes;
-
 mod back {
     pub mod archive;
     pub mod bytecode;
@@ -258,10 +256,6 @@ impl CodegenBackend for LlvmCodegenBackend {
         llvm_util::print_version();
     }
 
-    fn diagnostics(&self) -> &[(&'static str, &'static str)] {
-        &error_codes::DIAGNOSTICS
-    }
-
     fn target_features(&self, sess: &Session) -> Vec<Symbol> {
         target_features(sess)
     }
@@ -271,15 +265,10 @@ impl CodegenBackend for LlvmCodegenBackend {
     }
 
     fn provide(&self, providers: &mut ty::query::Providers<'_>) {
-        rustc_codegen_utils::symbol_names::provide(providers);
-        rustc_codegen_ssa::back::symbol_export::provide(providers);
-        rustc_codegen_ssa::base::provide_both(providers);
         attributes::provide(providers);
     }
 
     fn provide_extern(&self, providers: &mut ty::query::Providers<'_>) {
-        rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
-        rustc_codegen_ssa::base::provide_both(providers);
         attributes::provide_extern(providers);
     }
 
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index b07214fdc03..a2313b933a6 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -510,6 +510,7 @@ extern { pub type Module; }
 extern { pub type Context; }
 extern { pub type Type; }
 extern { pub type Value; }
+extern { pub type ConstantInt; }
 extern { pub type Metadata; }
 extern { pub type BasicBlock; }
 #[repr(C)]
@@ -719,8 +720,8 @@ extern "C" {
     pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value;
     pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value;
     pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value;
-    pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong;
-    pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool,
+    pub fn LLVMConstIntGetZExtValue(ConstantVal: &ConstantInt) -> c_ulonglong;
+    pub fn LLVMRustConstInt128Get(ConstantVal: &ConstantInt, SExt: bool,
                                   high: &mut u64, low: &mut u64) -> bool;
 
 
@@ -1666,7 +1667,7 @@ extern "C" {
     #[allow(improper_ctypes)]
     pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
 
-    pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>;
+    pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>;
 
     pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind;
     pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>;
diff --git a/src/librustc_codegen_ssa/README.md b/src/librustc_codegen_ssa/README.md
index c8bb2e7ee99..a09a0c22c1b 100644
--- a/src/librustc_codegen_ssa/README.md
+++ b/src/librustc_codegen_ssa/README.md
@@ -84,7 +84,7 @@ pub trait BuilderMethods<'a, 'tcx>:
 {
     fn new_block<'b>(
         cx: &'a Self::CodegenCx,
-        llfn: Self::Value,
+        llfn: Self::Function,
         name: &'b str
     ) -> Self;
     /* ... */
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 481db26e1a8..ef3b115890f 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -22,7 +22,8 @@ use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry};
 use rustc::util::profiling::SelfProfilerRef;
 use rustc_fs_util::link_or_copy;
 use rustc_data_structures::svh::Svh;
-use rustc_errors::{Handler, Level, FatalError, DiagnosticId};
+use rustc_data_structures::sync::Lrc;
+use rustc_errors::{Handler, Level, FatalError, DiagnosticId, SourceMapperDyn};
 use rustc_errors::emitter::{Emitter};
 use rustc_target::spec::MergeFunctions;
 use syntax::attr;
@@ -1681,6 +1682,9 @@ impl Emitter for SharedEmitter {
         }
         drop(self.sender.send(SharedEmitterMessage::AbortIfErrors));
     }
+    fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> {
+        None
+    }
 }
 
 impl SharedEmitterMain {
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 935087714a7..1c441ca7cbf 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -36,7 +36,6 @@ 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::callee;
 use crate::common::{RealPredicate, TypeKind, IntPredicate};
 use crate::meth;
 use crate::mir;
@@ -377,8 +376,7 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     let sig = instance.fn_sig(cx.tcx());
     let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
 
-    let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(||
-        bug!("Instance `{:?}` not already declared", instance));
+    let lldecl = cx.get_fn(instance);
 
     let mir = cx.tcx().instance_mir(instance.def);
     mir::codegen_mir::<Bx>(cx, lldecl, &mir, instance, sig);
@@ -400,7 +398,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
         return;
     }
 
-    let main_llfn = cx.get_fn(instance);
+    let main_llfn = cx.get_fn_addr(instance);
 
     let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1);
     match et {
@@ -455,10 +453,13 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &'
 
         let (start_fn, args) = if use_start_lang_item {
             let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None);
-            let start_fn = callee::resolve_and_get_fn(
-                cx,
-                start_def_id,
-                cx.tcx().intern_substs(&[main_ret_ty.into()]),
+            let start_fn = cx.get_fn_addr(
+                ty::Instance::resolve(
+                    cx.tcx(),
+                    ty::ParamEnv::reveal_all(),
+                    start_def_id,
+                    cx.tcx().intern_substs(&[main_ret_ty.into()]),
+                ).unwrap()
             );
             (start_fn, vec![bx.pointercast(rust_main, cx.type_ptr_to(cx.type_i8p())),
                             arg_argc, arg_argv])
diff --git a/src/librustc_codegen_ssa/callee.rs b/src/librustc_codegen_ssa/callee.rs
deleted file mode 100644
index 6ba6774cbf8..00000000000
--- a/src/librustc_codegen_ssa/callee.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use crate::traits::*;
-use rustc::ty;
-use rustc::ty::subst::SubstsRef;
-use rustc::hir::def_id::DefId;
-
-pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>(
-    cx: &Cx,
-    def_id: DefId,
-    substs: SubstsRef<'tcx>,
-) -> Cx::Value {
-    cx.get_fn(
-        ty::Instance::resolve(
-            cx.tcx(),
-            ty::ParamEnv::reveal_all(),
-            def_id,
-            substs
-        ).unwrap()
-    )
-}
-
-pub fn resolve_and_get_fn_for_ptr<'tcx,
-    Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
->(
-    cx: &Cx,
-    def_id: DefId,
-    substs: SubstsRef<'tcx>,
-) -> Cx::Value {
-    cx.get_fn(
-        ty::Instance::resolve_for_fn_ptr(
-            cx.tcx(),
-            ty::ParamEnv::reveal_all(),
-            def_id,
-            substs
-        ).unwrap()
-    )
-}
-
-pub fn resolve_and_get_fn_for_vtable<'tcx,
-    Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx>
->(
-    cx: &Cx,
-    def_id: DefId,
-    substs: SubstsRef<'tcx>,
-) -> Cx::Value {
-    cx.get_fn(
-        ty::Instance::resolve_for_vtable(
-            cx.tcx(),
-            ty::ParamEnv::reveal_all(),
-            def_id,
-            substs
-        ).unwrap()
-    )
-}
diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs
index e3aa35ef4eb..ac39ca98476 100644
--- a/src/librustc_codegen_ssa/common.rs
+++ b/src/librustc_codegen_ssa/common.rs
@@ -1,6 +1,7 @@
 #![allow(non_camel_case_types, non_snake_case)]
 
 use rustc::ty::{Ty, TyCtxt};
+use rustc::session::Session;
 use syntax_pos::Span;
 
 use rustc::hir::def_id::DefId;
@@ -200,3 +201,7 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
     }
 }
+
+pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
+    span_err!(a, b, E0511, "{}", c);
+}
diff --git a/src/librustc_codegen_ssa/error_codes.rs b/src/librustc_codegen_ssa/error_codes.rs
index 8ff41c275a8..02e26d8f6ec 100644
--- a/src/librustc_codegen_ssa/error_codes.rs
+++ b/src/librustc_codegen_ssa/error_codes.rs
@@ -1,5 +1,40 @@
 syntax::register_diagnostics! {
 
+E0511: r##"
+Invalid monomorphization of an intrinsic function was used. Erroneous code
+example:
+
+```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
+#![feature(platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(a: T, b: T) -> T;
+}
+
+fn main() {
+    unsafe { simd_add(0, 1); }
+    // error: invalid monomorphization of `simd_add` intrinsic
+}
+```
+
+The generic type has to be a SIMD type. Example:
+
+```
+#![feature(repr_simd)]
+#![feature(platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct i32x2(i32, i32);
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(a: T, b: T) -> T;
+}
+
+unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok!
+```
+"##,
+
 E0668: r##"
 Malformed inline assembly rejected by LLVM.
 
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index d700001430e..0221a04b045 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -27,6 +27,7 @@ use rustc::dep_graph::WorkProduct;
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::middle::lang_items::LangItem;
 use rustc::hir::def_id::CrateNum;
+use rustc::ty::query::Providers;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::svh::Svh;
@@ -41,7 +42,6 @@ pub mod traits;
 pub mod mir;
 pub mod debuginfo;
 pub mod base;
-pub mod callee;
 pub mod glue;
 pub mod meth;
 pub mod mono_item;
@@ -156,3 +156,13 @@ pub struct CodegenResults {
     pub linker_info: back::linker::LinkerInfo,
     pub crate_info: CrateInfo,
 }
+
+pub fn provide(providers: &mut Providers<'_>) {
+    crate::back::symbol_export::provide(providers);
+    crate::base::provide_both(providers);
+}
+
+pub fn provide_extern(providers: &mut Providers<'_>) {
+    crate::back::symbol_export::provide_extern(providers);
+    crate::base::provide_both(providers);
+}
diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs
index 7fe9f5f2513..266d2e5b18d 100644
--- a/src/librustc_codegen_ssa/meth.rs
+++ b/src/librustc_codegen_ssa/meth.rs
@@ -1,6 +1,5 @@
 use rustc_target::abi::call::FnType;
 
-use crate::callee;
 use crate::traits::*;
 
 use rustc::ty::{self, Ty, Instance};
@@ -92,7 +91,14 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
 
     let methods = methods.cloned().map(|opt_mth| {
         opt_mth.map_or(nullptr, |(def_id, substs)| {
-            callee::resolve_and_get_fn_for_vtable(cx, def_id, substs)
+            cx.get_fn_addr(
+                ty::Instance::resolve_for_vtable(
+                    cx.tcx(),
+                    ty::ParamEnv::reveal_all(),
+                    def_id,
+                    substs,
+                ).unwrap()
+            )
         })
     });
 
@@ -102,7 +108,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
     // `get_vtable` in rust_mir/interpret/traits.rs
     // /////////////////////////////////////////////////////////////////////////////////////////////
     let components: Vec<_> = [
-        cx.get_fn(Instance::resolve_drop_in_place(cx.tcx(), ty)),
+        cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)),
         cx.const_usize(layout.size.bytes()),
         cx.const_usize(layout.align.abi.bytes())
     ].iter().cloned().chain(methods).collect();
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index b0df81ba1ab..dc77d025c00 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -358,7 +358,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty)
             }
             _ => {
-                (bx.get_fn(drop_fn),
+                (bx.get_fn_addr(drop_fn),
                  FnType::of_instance(&bx, drop_fn))
             }
         };
@@ -460,7 +460,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
         let instance = ty::Instance::mono(bx.tcx(), def_id);
         let fn_ty = FnType::of_instance(&bx, instance);
-        let llfn = bx.get_fn(instance);
+        let llfn = bx.get_fn_addr(instance);
 
         // Codegen the actual panic invoke/call.
         helper.do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup);
@@ -576,7 +576,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
                 let instance = ty::Instance::mono(bx.tcx(), def_id);
                 let fn_ty = FnType::of_instance(&bx, instance);
-                let llfn = bx.get_fn(instance);
+                let llfn = bx.get_fn_addr(instance);
 
                 if let Some((_, target)) = destination.as_ref() {
                     helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
@@ -793,7 +793,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         let fn_ptr = match (llfn, instance) {
             (Some(llfn), _) => llfn,
-            (None, Some(instance)) => bx.get_fn(instance),
+            (None, Some(instance)) => bx.get_fn_addr(instance),
             _ => span_bug!(span, "no llfn for call"),
         };
 
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index d5612d7b072..1a2e796a5b7 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -30,7 +30,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
 
     debug_context: FunctionDebugContext<Bx::DIScope>,
 
-    llfn: Bx::Value,
+    llfn: Bx::Function,
 
     cx: &'a Bx::CodegenCx,
 
@@ -183,7 +183,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
 
 pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx,
-    llfn: Bx::Value,
+    llfn: Bx::Function,
     mir: &'a Body<'tcx>,
     instance: Instance<'tcx>,
     sig: ty::FnSig<'tcx>,
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 2d97f828f07..1d1bc2a81a2 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -394,8 +394,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         // Statically compute the offset if we can, otherwise just use the element size,
         // as this will yield the lowest alignment.
         let layout = self.layout.field(bx, 0);
-        let offset = if bx.is_const_integral(llindex) {
-            layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size)
+        let offset = if let Some(llindex) = bx.const_to_opt_uint(llindex) {
+            layout.size.checked_mul(llindex, bx).unwrap_or(layout.size)
         } else {
             layout.size
         };
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 978e7218aa7..27442bb6bff 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -10,7 +10,6 @@ use syntax::source_map::{DUMMY_SP, Span};
 
 use crate::base;
 use crate::MemFlags;
-use crate::callee;
 use crate::common::{self, RealPredicate, IntPredicate};
 
 use crate::traits::*;
@@ -95,7 +94,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     let size = bx.const_usize(dest.layout.size.bytes());
 
                     // Use llvm.memset.p0i8.* to initialize all zero arrays
-                    if bx.cx().is_const_integral(v) && bx.cx().const_to_uint(v) == 0 {
+                    if bx.cx().const_to_opt_uint(v) == Some(0) {
                         let fill = bx.cx().const_u8(0);
                         bx.memset(start, fill, size, dest.align, MemFlags::empty());
                         return bx;
@@ -190,7 +189,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     bug!("reifying a fn ptr that requires const arguments");
                                 }
                                 OperandValue::Immediate(
-                                    callee::resolve_and_get_fn_for_ptr(bx.cx(), def_id, substs))
+                                    bx.get_fn_addr(
+                                        ty::Instance::resolve_for_fn_ptr(
+                                            bx.tcx(),
+                                            ty::ParamEnv::reveal_all(),
+                                            def_id,
+                                            substs
+                                        ).unwrap()
+                                    )
+                                )
                             }
                             _ => {
                                 bug!("{} cannot be reified to a fn ptr", operand.layout.ty)
@@ -205,7 +212,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     def_id,
                                     substs,
                                     ty::ClosureKind::FnOnce);
-                                OperandValue::Immediate(bx.cx().get_fn(instance))
+                                OperandValue::Immediate(bx.cx().get_fn_addr(instance))
                             }
                             _ => {
                                 bug!("{} cannot be cast to a fn ptr", operand.layout.ty)
@@ -488,7 +495,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 };
                 let instance = ty::Instance::mono(bx.tcx(), def_id);
-                let r = bx.cx().get_fn(instance);
+                let r = bx.cx().get_fn_addr(instance);
                 let call = bx.call(r, &[llsize, llalign], None);
                 let val = bx.pointercast(call, llty_ptr);
 
diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs
index cb197f51460..a7faf4eaf10 100644
--- a/src/librustc_codegen_ssa/traits/backend.rs
+++ b/src/librustc_codegen_ssa/traits/backend.rs
@@ -14,6 +14,8 @@ use syntax_pos::symbol::InternedString;
 
 pub trait BackendTypes {
     type Value: CodegenObject;
+    type Function: CodegenObject;
+
     type BasicBlock: Copy;
     type Type: CodegenObject;
     type Funclet;
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index 1886701fb3a..62b5bcbb6c9 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -34,7 +34,7 @@ pub trait BuilderMethods<'a, 'tcx>:
     + HasTargetSpec
 
 {
-    fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self;
+    fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &'b str) -> Self;
     fn with_cx(cx: &'a Self::CodegenCx) -> Self;
     fn build_sibling_block(&self, name: &str) -> Self;
     fn cx(&self) -> &Self::CodegenCx;
diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs
index e7ce03f1836..95ada60fae0 100644
--- a/src/librustc_codegen_ssa/traits/consts.rs
+++ b/src/librustc_codegen_ssa/traits/consts.rs
@@ -21,11 +21,9 @@ pub trait ConstMethods<'tcx>: BackendTypes {
 
     fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;
 
-    fn const_to_uint(&self, v: Self::Value) -> u64;
+    fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64>;
     fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128>;
 
-    fn is_const_integral(&self, v: Self::Value) -> bool;
-
     fn scalar_to_backend(
         &self,
         cv: Scalar,
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index e75f247da96..989e6cf9dca 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -20,7 +20,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
         &self,
         instance: Instance<'tcx>,
         sig: ty::FnSig<'tcx>,
-        llfn: Self::Value,
+        llfn: Self::Function,
         mir: &mir::Body<'_>,
     ) -> FunctionDebugContext<Self::DIScope>;
 
diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs
index 624a982b619..cd42044e48d 100644
--- a/src/librustc_codegen_ssa/traits/declare.rs
+++ b/src/librustc_codegen_ssa/traits/declare.rs
@@ -17,13 +17,13 @@ pub trait DeclareMethods<'tcx>: BackendTypes {
     ///
     /// If there’s a value with the same name already declared, the function will
     /// update the declaration and return existing Value instead.
-    fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Value;
+    fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Function;
 
     /// Declare a Rust function.
     ///
     /// If there’s a value with the same name already declared, the function will
     /// update the declaration and return existing Value instead.
-    fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Value;
+    fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Function;
 
     /// Declare a global with an intention to define it.
     ///
diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs
index 46c88a6113e..658ddd00280 100644
--- a/src/librustc_codegen_ssa/traits/misc.rs
+++ b/src/librustc_codegen_ssa/traits/misc.rs
@@ -11,14 +11,14 @@ pub trait MiscMethods<'tcx>: BackendTypes {
         &self,
     ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
     fn check_overflow(&self) -> bool;
-    fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>;
-    fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value;
+    fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function;
+    fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value;
     fn eh_personality(&self) -> Self::Value;
     fn eh_unwind_resume(&self) -> Self::Value;
     fn sess(&self) -> &Session;
     fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
     fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
-    fn set_frame_pointer_elimination(&self, llfn: Self::Value);
-    fn apply_target_cpu_attr(&self, llfn: Self::Value);
+    fn set_frame_pointer_elimination(&self, llfn: Self::Function);
+    fn apply_target_cpu_attr(&self, llfn: Self::Function);
     fn create_used_variable(&self);
 }
diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs
index efe4a255701..4318ef16494 100644
--- a/src/librustc_codegen_ssa/traits/mod.rs
+++ b/src/librustc_codegen_ssa/traits/mod.rs
@@ -88,6 +88,7 @@ pub trait HasCodegen<'tcx>:
     type CodegenCx: CodegenMethods<'tcx>
         + BackendTypes<
             Value = Self::Value,
+            Function = Self::Function,
             BasicBlock = Self::BasicBlock,
             Type = Self::Type,
             Funclet = Self::Funclet,
diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs
index 2e3af8431ee..1077c1f4263 100644
--- a/src/librustc_codegen_utils/codegen_backend.rs
+++ b/src/librustc_codegen_utils/codegen_backend.rs
@@ -25,7 +25,6 @@ pub trait CodegenBackend {
     fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
     fn print_passes(&self) {}
     fn print_version(&self) {}
-    fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
 
     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync>;
     fn provide(&self, _providers: &mut Providers<'_>);
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index 1201446afb5..66920342ff6 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -18,6 +18,7 @@
 extern crate rustc;
 
 use rustc::ty::TyCtxt;
+use rustc::ty::query::Providers;
 use rustc::hir::def_id::LOCAL_CRATE;
 use syntax::symbol::sym;
 
@@ -37,3 +38,7 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
         }
     }
 }
+
+pub fn provide(providers: &mut Providers<'_>) {
+    crate::symbol_names::provide(providers);
+}
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index 3277b85c281..9622c290039 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -1,6 +1,6 @@
 //! This module defines types which are thread safe if cfg!(parallel_compiler) is true.
 //!
-//! `Lrc` is an alias of either Rc or Arc.
+//! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise.
 //!
 //! `Lock` is a mutex.
 //! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true,
@@ -12,7 +12,7 @@
 //!
 //! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false.
 //!
-//! `MTRef` is a immutable reference if cfg!(parallel_compiler), and an mutable reference otherwise.
+//! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise.
 //!
 //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync
 //! depending on the value of cfg!(parallel_compiler).
@@ -23,29 +23,6 @@ use std::marker::PhantomData;
 use std::ops::{Deref, DerefMut};
 use crate::owning_ref::{Erased, OwningRef};
 
-pub fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
-    where A: FnOnce() -> RA,
-          B: FnOnce() -> RB
-{
-    (oper_a(), oper_b())
-}
-
-pub struct SerialScope;
-
-impl SerialScope {
-    pub fn spawn<F>(&self, f: F)
-        where F: FnOnce(&SerialScope)
-    {
-        f(self)
-    }
-}
-
-pub fn serial_scope<F, R>(f: F) -> R
-    where F: FnOnce(&SerialScope) -> R
-{
-    f(&SerialScope)
-}
-
 pub use std::sync::atomic::Ordering::SeqCst;
 pub use std::sync::atomic::Ordering;
 
@@ -176,8 +153,28 @@ cfg_if! {
         pub type AtomicU32 = Atomic<u32>;
         pub type AtomicU64 = Atomic<u64>;
 
-        pub use self::serial_join as join;
-        pub use self::serial_scope as scope;
+        pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
+            where A: FnOnce() -> RA,
+                  B: FnOnce() -> RB
+        {
+            (oper_a(), oper_b())
+        }
+
+        pub struct SerialScope;
+
+        impl SerialScope {
+            pub fn spawn<F>(&self, f: F)
+                where F: FnOnce(&SerialScope)
+            {
+                f(self)
+            }
+        }
+
+        pub fn scope<F, R>(f: F) -> R
+            where F: FnOnce(&SerialScope) -> R
+        {
+            f(&SerialScope)
+        }
 
         #[macro_export]
         macro_rules! parallel {
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 806afbd1af6..f33cb4e215d 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -616,7 +616,7 @@ impl RustcDefaultCalls {
                     let mut v = Vec::new();
                     locator::list_file_metadata(&sess.target.target,
                                                 path,
-                                                &*cstore.metadata_loader,
+                                                cstore,
                                                 &mut v)
                             .unwrap();
                     println!("{}", String::from_utf8(v).unwrap());
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index 0281d10fd93..16a1a28cd3a 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -49,6 +49,10 @@ impl Emitter for AnnotateSnippetEmitterWriter {
                                    &suggestions);
     }
 
+    fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> {
+        self.source_map.as_ref()
+    }
+
     fn should_show_explain(&self) -> bool {
         !self.short_message
     }
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 68f933363da..84400091100 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -13,7 +13,7 @@ use syntax_pos::{SourceFile, Span, MultiSpan};
 
 use crate::{
     Level, CodeSuggestion, Diagnostic, SubDiagnostic,
-    SuggestionStyle, SourceMapperDyn, DiagnosticId,
+    SuggestionStyle, SourceMapper, SourceMapperDyn, DiagnosticId,
 };
 use crate::Level::Error;
 use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
@@ -192,6 +192,8 @@ pub trait Emitter {
         true
     }
 
+    fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>>;
+
     /// Formats the substitutions of the primary_span
     ///
     /// The are a lot of conditions to this method, but in short:
@@ -204,7 +206,7 @@ pub trait Emitter {
     ///   we return the original `primary_span` and the original suggestions.
     fn primary_span_formatted<'a>(
         &mut self,
-        db: &'a Diagnostic
+        db: &'a Diagnostic,
     ) -> (MultiSpan, &'a [CodeSuggestion]) {
         let mut primary_span = db.span.clone();
         if let Some((sugg, rest)) = db.suggestions.split_first() {
@@ -234,7 +236,20 @@ pub trait Emitter {
                     format!("help: {}", sugg.msg)
                 } else {
                     // Show the default suggestion text with the substitution
-                    format!("help: {}: `{}`", sugg.msg, substitution)
+                    format!(
+                        "help: {}{}: `{}`",
+                        sugg.msg,
+                        if self.source_map().map(|sm| is_case_difference(
+                            &**sm,
+                            substitution,
+                            sugg.substitutions[0].parts[0].span,
+                        )).unwrap_or(false) {
+                            " (notice the capitalization)"
+                        } else {
+                            ""
+                        },
+                        substitution,
+                    )
                 };
                 primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg);
 
@@ -382,6 +397,10 @@ pub trait Emitter {
 }
 
 impl Emitter for EmitterWriter {
+    fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> {
+        self.sm.as_ref()
+    }
+
     fn emit_diagnostic(&mut self, db: &Diagnostic) {
         let mut children = db.children.clone();
         let (mut primary_span, suggestions) = self.primary_span_formatted(&db);
@@ -1461,7 +1480,9 @@ impl EmitterWriter {
         let suggestions = suggestion.splice_lines(&**sm);
 
         let mut row_num = 2;
-        for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
+        let mut notice_capitalization = false;
+        for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) {
+            notice_capitalization |= only_capitalization;
             // Only show underline if the suggestion spans a single line and doesn't cover the
             // entirety of the code output. If you have multiple replacements in the same line
             // of code, show the underline.
@@ -1552,7 +1573,10 @@ impl EmitterWriter {
         }
         if suggestions.len() > MAX_SUGGESTIONS {
             let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
-            buffer.puts(row_num, 0, &msg, Style::NoStyle);
+            buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
+        } else if notice_capitalization {
+            let msg = "notice the capitalization difference";
+            buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
         }
         emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
         Ok(())
@@ -2034,3 +2058,18 @@ impl<'a> Drop for WritableDst<'a> {
         }
     }
 }
+
+/// Whether the original and suggested code are visually similar enough to warrant extra wording.
+pub fn is_case_difference(sm: &dyn SourceMapper, suggested: &str, sp: Span) -> bool {
+    // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode.
+    let found = sm.span_to_snippet(sp).unwrap();
+    let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z'];
+    // All the chars that differ in capitalization are confusable (above):
+    let confusable = found.chars().zip(suggested.chars()).filter(|(f, s)| f != s).all(|(f, s)| {
+        (ascii_confusables.contains(&f) || ascii_confusables.contains(&s))
+    });
+    confusable && found.to_lowercase() == suggested.to_lowercase()
+            // FIXME: We sometimes suggest the same thing we already have, which is a
+            //        bug, but be defensive against that here.
+            && found != suggested
+}
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 2fae584c153..63df052a225 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -13,7 +13,7 @@ pub use emitter::ColorConfig;
 
 use Level::*;
 
-use emitter::{Emitter, EmitterWriter};
+use emitter::{Emitter, EmitterWriter, is_case_difference};
 use registry::Registry;
 
 use rustc_data_structures::sync::{self, Lrc, Lock};
@@ -37,13 +37,16 @@ pub mod registry;
 mod styled_buffer;
 mod lock;
 
-use syntax_pos::{BytePos,
-                 Loc,
-                 FileLinesResult,
-                 SourceFile,
-                 FileName,
-                 MultiSpan,
-                 Span};
+use syntax_pos::{
+    BytePos,
+    FileLinesResult,
+    FileName,
+    Loc,
+    MultiSpan,
+    SourceFile,
+    Span,
+    SpanSnippetError,
+};
 
 /// Indicates the confidence in the correctness of a suggestion.
 ///
@@ -147,6 +150,7 @@ pub trait SourceMapper {
     fn lookup_char_pos(&self, pos: BytePos) -> Loc;
     fn span_to_lines(&self, sp: Span) -> FileLinesResult;
     fn span_to_string(&self, sp: Span) -> String;
+    fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError>;
     fn span_to_filename(&self, sp: Span) -> FileName;
     fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>;
     fn call_span_if_macro(&self, sp: Span) -> Span;
@@ -155,9 +159,12 @@ pub trait SourceMapper {
 }
 
 impl CodeSuggestion {
-    /// Returns the assembled code suggestions and whether they should be shown with an underline.
-    pub fn splice_lines(&self, cm: &SourceMapperDyn)
-                        -> Vec<(String, Vec<SubstitutionPart>)> {
+    /// Returns the assembled code suggestions, whether they should be shown with an underline
+    /// and whether the substitution only differs in capitalization.
+    pub fn splice_lines(
+        &self,
+        cm: &SourceMapperDyn,
+    ) -> Vec<(String, Vec<SubstitutionPart>, bool)> {
         use syntax_pos::{CharPos, Pos};
 
         fn push_trailing(buf: &mut String,
@@ -232,6 +239,7 @@ impl CodeSuggestion {
                 prev_hi = cm.lookup_char_pos(part.span.hi());
                 prev_line = fm.get_line(prev_hi.line - 1);
             }
+            let only_capitalization = is_case_difference(cm, &buf, bounding_span);
             // if the replacement already ends with a newline, don't print the next line
             if !buf.ends_with('\n') {
                 push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None);
@@ -240,7 +248,7 @@ impl CodeSuggestion {
             while buf.ends_with('\n') {
                 buf.pop();
             }
-            (buf, substitution.parts)
+            (buf, substitution.parts, only_capitalization)
         }).collect()
     }
 }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 328798862b8..396c5610251 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -130,7 +130,7 @@ pub fn configure_and_expand(
     let crate_name = crate_name.to_string();
     let (result, resolver) = BoxedResolver::new(static move || {
         let sess = &*sess;
-        let mut crate_loader = CrateLoader::new(sess, &*cstore, &crate_name);
+        let crate_loader = CrateLoader::new(sess, &*cstore, &crate_name);
         let resolver_arenas = Resolver::arenas();
         let res = configure_and_expand_inner(
             sess,
@@ -138,7 +138,7 @@ pub fn configure_and_expand(
             krate,
             &crate_name,
             &resolver_arenas,
-            &mut crate_loader,
+            &crate_loader,
             plugin_info,
         );
         let mut resolver = match res {
@@ -169,6 +169,7 @@ impl ExpansionResult {
         ExpansionResult {
             defs: Steal::new(resolver.definitions),
             resolutions: Steal::new(Resolutions {
+                extern_crate_map: resolver.extern_crate_map,
                 export_map: resolver.export_map,
                 trait_map: resolver.trait_map,
                 glob_map: resolver.glob_map,
@@ -187,6 +188,7 @@ impl ExpansionResult {
         ExpansionResult {
             defs: Steal::new(resolver.definitions.clone()),
             resolutions: Steal::new(Resolutions {
+                extern_crate_map: resolver.extern_crate_map.clone(),
                 export_map: resolver.export_map.clone(),
                 trait_map: resolver.trait_map.clone(),
                 glob_map: resolver.glob_map.clone(),
@@ -319,7 +321,7 @@ fn configure_and_expand_inner<'a>(
     mut krate: ast::Crate,
     crate_name: &str,
     resolver_arenas: &'a ResolverArenas<'a>,
-    crate_loader: &'a mut CrateLoader<'a>,
+    crate_loader: &'a CrateLoader<'a>,
     plugin_info: PluginInfo,
 ) -> Result<(ast::Crate, Resolver<'a>)> {
     time(sess, "pre-AST-expansion lint checks", || {
@@ -663,16 +665,15 @@ fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames:
 
         if sess.binary_dep_depinfo() {
             for cnum in compiler.cstore.crates_untracked() {
-                let metadata = compiler.cstore.crate_data_as_rc_any(cnum);
-                let metadata = metadata.downcast_ref::<cstore::CrateMetadata>().unwrap();
-                if let Some((path, _)) = &metadata.source.dylib {
-                    files.push(escape_dep_filename(&FileName::Real(path.clone())));
+                let source = compiler.cstore.crate_source_untracked(cnum);
+                if let Some((path, _)) = source.dylib {
+                    files.push(escape_dep_filename(&FileName::Real(path)));
                 }
-                if let Some((path, _)) = &metadata.source.rlib {
-                    files.push(escape_dep_filename(&FileName::Real(path.clone())));
+                if let Some((path, _)) = source.rlib {
+                    files.push(escape_dep_filename(&FileName::Real(path)));
                 }
-                if let Some((path, _)) = &metadata.source.rmeta {
-                    files.push(escape_dep_filename(&FileName::Real(path.clone())));
+                if let Some((path, _)) = source.rmeta {
+                    files.push(escape_dep_filename(&FileName::Real(path)));
                 }
             }
         }
@@ -790,10 +791,13 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
     cstore::provide(providers);
     lint::provide(providers);
     rustc_lint::provide(providers);
+    rustc_codegen_utils::provide(providers);
+    rustc_codegen_ssa::provide(providers);
 }
 
 pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) {
     cstore::provide_extern(providers);
+    rustc_codegen_ssa::provide_extern(providers);
 }
 
 declare_box_region_type!(
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 50a2187c937..9850121d2ce 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -1,6 +1,6 @@
 //! Validates all used crates and extern libraries and loads their metadata
 
-use crate::cstore::{self, CStore, CrateSource, MetadataBlob};
+use crate::cstore::{self, CStore, MetadataBlob};
 use crate::locator::{self, CratePaths};
 use crate::schema::{CrateRoot, CrateDep};
 use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell};
@@ -14,7 +14,7 @@ use rustc::session::{Session, CrateDisambiguator};
 use rustc::session::config::{Sanitizer, self};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 use rustc::session::search_paths::PathKind;
-use rustc::middle::cstore::{ExternCrate, ExternCrateSource};
+use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource};
 use rustc::util::common::record_time;
 use rustc::util::nodemap::FxHashSet;
 use rustc::hir::map::Definitions;
@@ -33,15 +33,13 @@ use syntax_pos::{Span, DUMMY_SP};
 use log::{debug, info, log_enabled};
 use proc_macro::bridge::client::ProcMacro;
 
-pub struct Library {
-    pub dylib: Option<(PathBuf, PathKind)>,
-    pub rlib: Option<(PathBuf, PathKind)>,
-    pub rmeta: Option<(PathBuf, PathKind)>,
+crate struct Library {
+    pub source: CrateSource,
     pub metadata: MetadataBlob,
 }
 
 pub struct CrateLoader<'a> {
-    pub sess: &'a Session,
+    sess: &'a Session,
     cstore: &'a CStore,
     local_crate_name: Symbol,
 }
@@ -189,7 +187,7 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn register_crate(
-        &mut self,
+        &self,
         host_lib: Option<Library>,
         root: Option<&CratePaths>,
         span: Span,
@@ -197,10 +195,10 @@ impl<'a> CrateLoader<'a> {
         dep_kind: DepKind,
         name: Symbol
     ) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
-        let _prof_timer =
-            self.sess.prof.generic_activity("metadata_register_crate");
+        let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
 
-        let crate_root = lib.metadata.get_root();
+        let Library { source, metadata } = lib;
+        let crate_root = metadata.get_root();
         self.verify_no_symbol_conflicts(span, &crate_root);
 
         let private_dep = self.sess.opts.externs.get(&name.as_str())
@@ -218,28 +216,22 @@ impl<'a> CrateLoader<'a> {
         let root = if let Some(root) = root {
             root
         } else {
-            crate_paths = CratePaths {
-                ident: crate_root.name.to_string(),
-                dylib: lib.dylib.clone().map(|p| p.0),
-                rlib:  lib.rlib.clone().map(|p| p.0),
-                rmeta: lib.rmeta.clone().map(|p| p.0),
-            };
+            crate_paths = CratePaths { name: crate_root.name, source: source.clone() };
             &crate_paths
         };
 
-        let Library { dylib, rlib, rmeta, metadata } = lib;
         let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
 
         let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
 
         let raw_proc_macros =  crate_root.proc_macro_data.map(|_| {
             let temp_root;
-            let (dlsym_dylib, dlsym_root) = match &host_lib {
+            let (dlsym_source, dlsym_root) = match &host_lib {
                 Some(host_lib) =>
-                    (&host_lib.dylib, { temp_root = host_lib.metadata.get_root(); &temp_root }),
-                None => (&dylib, &crate_root),
+                    (&host_lib.source, { temp_root = host_lib.metadata.get_root(); &temp_root }),
+                None => (&source, &crate_root),
             };
-            let dlsym_dylib = dlsym_dylib.as_ref().expect("no dylib for a proc-macro crate");
+            let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
             self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator, span)
         });
 
@@ -268,13 +260,8 @@ impl<'a> CrateLoader<'a> {
             source_map_import_info: RwLock::new(vec![]),
             alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index),
             dep_kind: Lock::new(dep_kind),
-            source: cstore::CrateSource {
-                dylib,
-                rlib,
-                rmeta,
-            },
+            source,
             private_dep,
-            span,
             raw_proc_macros,
             dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
         };
@@ -285,7 +272,7 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn load_proc_macro<'b>(
-        &mut self,
+        &self,
         locate_ctxt: &mut locator::Context<'b>,
         path_kind: PathKind,
     ) -> Option<(LoadResult, Option<Library>)>
@@ -340,7 +327,7 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn resolve_crate<'b>(
-        &'b mut self,
+        &'b self,
         name: Symbol,
         span: Span,
         dep_kind: DepKind,
@@ -350,7 +337,7 @@ impl<'a> CrateLoader<'a> {
     }
 
     fn maybe_resolve_crate<'b>(
-        &'b mut self,
+        &'b self,
         name: Symbol,
         span: Span,
         mut dep_kind: DepKind,
@@ -410,7 +397,7 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn load(&mut self, locate_ctxt: &mut locator::Context<'_>) -> Option<LoadResult> {
+    fn load(&self, locate_ctxt: &mut locator::Context<'_>) -> Option<LoadResult> {
         let library = locate_ctxt.maybe_load_library_crate()?;
 
         // In the case that we're loading a crate, but not matching
@@ -437,7 +424,7 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn update_extern_crate(&mut self,
+    fn update_extern_crate(&self,
                            cnum: CrateNum,
                            mut extern_crate: ExternCrate,
                            visited: &mut FxHashSet<(CrateNum, bool)>)
@@ -479,7 +466,7 @@ impl<'a> CrateLoader<'a> {
     }
 
     // Go through the crate metadata and load any crates that it references
-    fn resolve_crate_deps(&mut self,
+    fn resolve_crate_deps(&self,
                           root: &CratePaths,
                           crate_root: &CrateRoot<'_>,
                           metadata: &MetadataBlob,
@@ -509,7 +496,7 @@ impl<'a> CrateLoader<'a> {
         })).collect()
     }
 
-    fn read_extension_crate(&mut self, name: Symbol, span: Span) -> ExtensionCrate {
+    fn read_extension_crate(&self, name: Symbol, span: Span) -> ExtensionCrate {
         info!("read extension crate `{}`", name);
         let target_triple = self.sess.opts.target_triple.clone();
         let host_triple = TargetTriple::from_triple(config::host_triple());
@@ -559,7 +546,7 @@ impl<'a> CrateLoader<'a> {
                 (data.source.dylib.clone(), PMDSource::Registered(data))
             }
             LoadResult::Loaded(library) => {
-                let dylib = library.dylib.clone();
+                let dylib = library.source.dylib.clone();
                 let metadata = PMDSource::Owned(library);
                 (dylib, metadata)
             }
@@ -605,7 +592,7 @@ impl<'a> CrateLoader<'a> {
 
     /// Look for a plugin registrar. Returns library path, crate
     /// SVH and DefIndex of the registrar function.
-    pub fn find_plugin_registrar(&mut self,
+    pub fn find_plugin_registrar(&self,
                                  span: Span,
                                  name: Symbol)
                                  -> Option<(PathBuf, CrateDisambiguator)> {
@@ -638,7 +625,7 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
+    fn inject_panic_runtime(&self, krate: &ast::Crate) {
         // If we're only compiling an rlib, then there's no need to select a
         // panic runtime, so we just skip this section entirely.
         let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| {
@@ -719,7 +706,7 @@ impl<'a> CrateLoader<'a> {
                                   &|data| data.root.needs_panic_runtime);
     }
 
-    fn inject_sanitizer_runtime(&mut self) {
+    fn inject_sanitizer_runtime(&self) {
         if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer {
             // Sanitizers can only be used on some tested platforms with
             // executables linked to `std`
@@ -817,7 +804,7 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn inject_profiler_runtime(&mut self) {
+    fn inject_profiler_runtime(&self) {
         if self.sess.opts.debugging_opts.profile ||
            self.sess.opts.cg.profile_generate.enabled()
         {
@@ -834,7 +821,7 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
+    fn inject_allocator_crate(&self, krate: &ast::Crate) {
         let has_global_allocator = match &*global_allocator_spans(krate) {
             [span1, span2, ..] => {
                 self.sess.struct_span_err(*span2, "cannot define multiple global allocators")
@@ -973,7 +960,7 @@ impl<'a> CrateLoader<'a> {
 }
 
 impl<'a> CrateLoader<'a> {
-    pub fn postprocess(&mut self, krate: &ast::Crate) {
+    pub fn postprocess(&self, krate: &ast::Crate) {
         self.inject_sanitizer_runtime();
         self.inject_profiler_runtime();
         self.inject_allocator_crate(krate);
@@ -984,9 +971,7 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    pub fn process_extern_crate(
-        &mut self, item: &ast::Item, definitions: &Definitions,
-    ) -> CrateNum {
+    pub fn process_extern_crate(&self, item: &ast::Item, definitions: &Definitions) -> CrateNum {
         match item.kind {
             ast::ItemKind::ExternCrate(orig_name) => {
                 debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
@@ -1019,18 +1004,13 @@ impl<'a> CrateLoader<'a> {
                     },
                     &mut FxHashSet::default(),
                 );
-                self.cstore.add_extern_mod_stmt_cnum(item.id, cnum);
                 cnum
             }
             _ => bug!(),
         }
     }
 
-    pub fn process_path_extern(
-        &mut self,
-        name: Symbol,
-        span: Span,
-    ) -> CrateNum {
+    pub fn process_path_extern(&self, name: Symbol, span: Span) -> CrateNum {
         let cnum = self.resolve_crate(name, span, DepKind::Explicit, None).0;
 
         self.update_extern_crate(
@@ -1048,11 +1028,7 @@ impl<'a> CrateLoader<'a> {
         cnum
     }
 
-    pub fn maybe_process_path_extern(
-        &mut self,
-        name: Symbol,
-        span: Span,
-    ) -> Option<CrateNum> {
+    pub fn maybe_process_path_extern(&self, name: Symbol, span: Span) -> Option<CrateNum> {
         let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?.0;
 
         self.update_extern_crate(
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 98a08e501f1..a5a458e49a3 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -5,19 +5,15 @@ use crate::schema;
 use rustc::dep_graph::DepNodeIndex;
 use rustc::hir::def_id::{CrateNum, DefIndex};
 use rustc::hir::map::definitions::DefPathTable;
-use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
+use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoader};
 use rustc::mir::interpret::AllocDecodingState;
 use rustc_index::vec::IndexVec;
-use rustc::util::nodemap::{FxHashMap, NodeMap};
-
-use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell};
+use rustc::util::nodemap::FxHashMap;
+use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell};
 use syntax::ast;
 use syntax::ext::base::SyntaxExtension;
 use syntax_pos;
-
-pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
-pub use rustc::middle::cstore::NativeLibraryKind::*;
-pub use rustc::middle::cstore::{CrateSource, LibSource, ForeignModule};
+use proc_macro::bridge::client::ProcMacro;
 
 pub use crate::cstore_impl::{provide, provide_extern};
 
@@ -25,17 +21,13 @@ pub use crate::cstore_impl::{provide, provide_extern};
 // local crate numbers (as generated during this session). Each external
 // crate may refer to types in other external crates, and each has their
 // own crate numbers.
-pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
+crate type CrateNumMap = IndexVec<CrateNum, CrateNum>;
 
-pub use rustc_data_structures::sync::MetadataRef;
-use syntax_pos::Span;
-use proc_macro::bridge::client::ProcMacro;
-
-pub struct MetadataBlob(pub MetadataRef);
+crate struct MetadataBlob(pub MetadataRef);
 
 /// Holds information about a syntax_pos::SourceFile imported from another crate.
 /// See `imported_source_files()` for more information.
-pub struct ImportedSourceFile {
+crate struct ImportedSourceFile {
     /// This SourceFile's byte-offset within the source_map of its original crate
     pub original_start_pos: syntax_pos::BytePos,
     /// The end of this SourceFile within the source_map of its original crate
@@ -45,59 +37,66 @@ pub struct ImportedSourceFile {
 }
 
 pub struct CrateMetadata {
-    /// Information about the extern crate that caused this crate to
-    /// be loaded. If this is `None`, then the crate was injected
-    /// (e.g., by the allocator)
-    pub extern_crate: Lock<Option<ExternCrate>>,
-
-    pub blob: MetadataBlob,
-    pub cnum_map: CrateNumMap,
-    pub cnum: CrateNum,
-    pub dependencies: Lock<Vec<CrateNum>>,
-    pub source_map_import_info: RwLock<Vec<ImportedSourceFile>>,
+    /// The primary crate data - binary metadata blob.
+    crate blob: MetadataBlob,
 
-    /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
-    pub alloc_decoding_state: AllocDecodingState,
-
-    // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
-    // lifetime is only used behind `Lazy`, and therefore acts like an
-    // universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
-    // is being used to decode those values.
-    pub root: schema::CrateRoot<'static>,
+    // --- Some data pre-decoded from the metadata blob, usually for performance ---
 
+    /// Properties of the whole crate.
+    /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
+    /// lifetime is only used behind `Lazy`, and therefore acts like an
+    /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
+    /// is being used to decode those values.
+    crate root: schema::CrateRoot<'static>,
     /// For each definition in this crate, we encode a key. When the
     /// crate is loaded, we read all the keys and put them in this
     /// hashmap, which gives the reverse mapping. This allows us to
     /// quickly retrace a `DefPath`, which is needed for incremental
     /// compilation support.
-    pub def_path_table: Lrc<DefPathTable>,
-
-    pub trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>,
-
-    pub dep_kind: Lock<DepKind>,
-    pub source: CrateSource,
-
+    crate def_path_table: Lrc<DefPathTable>,
+    /// Trait impl data.
+    /// FIXME: Used only from queries and can use query cache,
+    /// so pre-decoding can probably be avoided.
+    crate trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>,
+    /// Proc macro descriptions for this crate, if it's a proc macro crate.
+    crate raw_proc_macros: Option<&'static [ProcMacro]>,
+    /// Source maps for code from the crate.
+    crate source_map_import_info: RwLock<Vec<ImportedSourceFile>>,
+    /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
+    crate alloc_decoding_state: AllocDecodingState,
+    /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
+    /// It is initialized on the first access in `get_crate_dep_node_index()`.
+    /// Do not access the value directly, as it might not have been initialized yet.
+    /// The field must always be initialized to `DepNodeIndex::INVALID`.
+    crate dep_node_index: AtomicCell<DepNodeIndex>,
+
+    // --- Other significant crate properties ---
+
+    /// ID of this crate, from the current compilation session's point of view.
+    crate cnum: CrateNum,
+    /// Maps crate IDs as they are were seen from this crate's compilation sessions into
+    /// IDs as they are seen from the current compilation session.
+    crate cnum_map: CrateNumMap,
+    /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
+    crate dependencies: Lock<Vec<CrateNum>>,
+    /// How to link (or not link) this crate to the currently compiled crate.
+    crate dep_kind: Lock<DepKind>,
+    /// Filesystem location of this crate.
+    crate source: CrateSource,
     /// Whether or not this crate should be consider a private dependency
     /// for purposes of the 'exported_private_dependencies' lint
-    pub private_dep: bool,
+    crate private_dep: bool,
 
-    pub span: Span,
+    // --- Data used only for improving diagnostics ---
 
-    pub raw_proc_macros: Option<&'static [ProcMacro]>,
-
-    /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
-    /// It is initialized on the first access in `get_crate_dep_node_index()`.
-    /// Do not access the value directly, as it might not have been initialized
-    /// yet.
-    /// The field must always be initialized to `DepNodeIndex::INVALID`.
-    pub(super) dep_node_index: AtomicCell<DepNodeIndex>,
+    /// Information about the `extern crate` item or path that caused this crate to be loaded.
+    /// If this is `None`, then the crate was injected (e.g., by the allocator).
+    crate extern_crate: Lock<Option<ExternCrate>>,
 }
 
 pub struct CStore {
     metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
-    /// Map from NodeId's of local extern crate statements to crate numbers
-    extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
-    pub metadata_loader: Box<dyn MetadataLoader + Sync>,
+    crate metadata_loader: Box<dyn MetadataLoader + Sync>,
 }
 
 pub enum LoadedMacro {
@@ -113,30 +112,29 @@ impl CStore {
             // corresponding `CrateNum`. This first entry will always remain
             // `None`.
             metas: RwLock::new(IndexVec::from_elem_n(None, 1)),
-            extern_mod_crate_map: Default::default(),
             metadata_loader,
         }
     }
 
-    pub(super) fn alloc_new_crate_num(&self) -> CrateNum {
+    crate fn alloc_new_crate_num(&self) -> CrateNum {
         let mut metas = self.metas.borrow_mut();
         let cnum = CrateNum::new(metas.len());
         metas.push(None);
         cnum
     }
 
-    pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
+    crate fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
         self.metas.borrow()[cnum].clone()
             .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
     }
 
-    pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
+    crate fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
         let mut metas = self.metas.borrow_mut();
         assert!(metas[cnum].is_none(), "Overwriting crate metadata entry");
         metas[cnum] = Some(data);
     }
 
-    pub(super) fn iter_crate_data<I>(&self, mut i: I)
+    crate fn iter_crate_data<I>(&self, mut i: I)
         where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
     {
         for (k, v) in self.metas.borrow().iter_enumerated() {
@@ -146,16 +144,14 @@ impl CStore {
         }
     }
 
-    pub(super) fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
+    crate fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
         let mut ordering = Vec::new();
         self.push_dependencies_in_postorder(&mut ordering, krate);
         ordering.reverse();
         ordering
     }
 
-    pub(super) fn push_dependencies_in_postorder(&self,
-                                                 ordering: &mut Vec<CrateNum>,
-                                                 krate: CrateNum) {
+    crate fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
         if ordering.contains(&krate) {
             return;
         }
@@ -170,7 +166,7 @@ impl CStore {
         ordering.push(krate);
     }
 
-    pub(super) fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
+    crate fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
         let mut ordering = Vec::new();
         for (num, v) in self.metas.borrow().iter_enumerated() {
             if let &Some(_) = v {
@@ -179,12 +175,4 @@ impl CStore {
         }
         return ordering
     }
-
-    pub(super) fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
-        self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
-    }
-
-    pub(super) fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
-        self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
-    }
 }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 642a7632b3d..fd011265da7 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -6,8 +6,7 @@ use crate::foreign_modules;
 use crate::schema;
 
 use rustc::ty::query::QueryConfig;
-use rustc::middle::cstore::{CrateStore, DepKind,
-                            EncodedMetadata, NativeLibraryKind};
+use rustc::middle::cstore::{CrateSource, CrateStore, DepKind, EncodedMetadata, NativeLibraryKind};
 use rustc::middle::exported_symbols::ExportedSymbol;
 use rustc::middle::stability::DeprecationEntry;
 use rustc::middle::dependency_format::Linkage;
@@ -414,12 +413,6 @@ impl cstore::CStore {
         }
     }
 
-    pub fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind {
-        let data = self.get_crate_data(cnum);
-        let r = *data.dep_kind.lock();
-        r
-    }
-
     pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition {
         self.get_crate_data(cnum).root.edition
     }
@@ -428,14 +421,6 @@ impl cstore::CStore {
         self.get_crate_data(def.krate).get_struct_field_names(def.index, sess)
     }
 
-    pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind {
-        self.get_crate_data(def.krate).get_ctor_kind(def.index)
-    }
-
-    pub fn item_attrs_untracked(&self, def: DefId, sess: &Session) -> Lrc<[ast::Attribute]> {
-        self.get_crate_data(def.krate).get_item_attrs(def.index, sess)
-    }
-
     pub fn item_children_untracked(
         &self,
         def_id: DefId,
@@ -493,6 +478,10 @@ impl cstore::CStore {
     pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem {
         self.get_crate_data(def.krate).get_associated_item(def.index)
     }
+
+    pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource {
+        self.get_crate_data(cnum).source.clone()
+    }
 }
 
 impl CrateStore for cstore::CStore {
@@ -549,11 +538,6 @@ impl CrateStore for cstore::CStore {
         result
     }
 
-    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>
-    {
-        self.do_extern_mod_stmt_cnum(emod_id)
-    }
-
     fn postorder_cnums_untracked(&self) -> Vec<CrateNum> {
         self.do_postorder_cnums_untracked()
     }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 132ef7d4241..6969d608d76 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1,13 +1,13 @@
 // Decoding metadata from a single crate's metadata
 
-use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
+use crate::cstore::{self, CrateMetadata, MetadataBlob};
 use crate::schema::*;
 
 use rustc_index::vec::IndexVec;
 use rustc_data_structures::sync::{Lrc, ReadGuard};
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir;
-use rustc::middle::cstore::LinkagePreference;
+use rustc::middle::cstore::{LinkagePreference, NativeLibrary, ForeignModule};
 use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -38,7 +38,7 @@ use log::debug;
 use proc_macro::bridge::client::ProcMacro;
 use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro};
 
-pub struct DecodeContext<'a, 'tcx> {
+crate struct DecodeContext<'a, 'tcx> {
     opaque: opaque::Decoder<'a>,
     cdata: Option<&'a CrateMetadata>,
     sess: Option<&'tcx Session>,
@@ -54,7 +54,7 @@ pub struct DecodeContext<'a, 'tcx> {
 }
 
 /// Abstract over the various ways one can create metadata decoders.
-pub trait Metadata<'a, 'tcx>: Copy {
+crate trait Metadata<'a, 'tcx>: Copy {
     fn raw_bytes(self) -> &'a [u8];
     fn cdata(self) -> Option<&'a CrateMetadata> { None }
     fn sess(self) -> Option<&'tcx Session> { None }
@@ -130,7 +130,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) {
 }
 
 impl<'a, 'tcx, T: Decodable> Lazy<T> {
-    pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
+    crate fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
         let mut dcx = meta.decoder(self.position);
         dcx.lazy_state = LazyState::NodeStart(self.position);
         T::decode(&mut dcx).unwrap()
@@ -138,7 +138,7 @@ impl<'a, 'tcx, T: Decodable> Lazy<T> {
 }
 
 impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
-    pub fn decode<M: Metadata<'a, 'tcx>>(
+    crate fn decode<M: Metadata<'a, 'tcx>>(
         self,
         meta: M,
     ) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x {
@@ -149,11 +149,11 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
 }
 
 impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
-    pub fn tcx(&self) -> TyCtxt<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx.expect("missing TyCtxt in DecodeContext")
     }
 
-    pub fn cdata(&self) -> &'a CrateMetadata {
+    fn cdata(&self) -> &'a CrateMetadata {
         self.cdata.expect("missing CrateMetadata in DecodeContext")
     }
 
@@ -379,15 +379,15 @@ for DecodeContext<'a, 'tcx> {
 implement_ty_decoder!( DecodeContext<'a, 'tcx> );
 
 impl<'tcx> MetadataBlob {
-    pub fn is_compatible(&self) -> bool {
+    crate fn is_compatible(&self) -> bool {
         self.raw_bytes().starts_with(METADATA_HEADER)
     }
 
-    pub fn get_rustc_version(&self) -> String {
+    crate fn get_rustc_version(&self) -> String {
         Lazy::<String>::from_position(METADATA_HEADER.len() + 4).decode(self)
     }
 
-    pub fn get_root(&self) -> CrateRoot<'tcx> {
+    crate fn get_root(&self) -> CrateRoot<'tcx> {
         let slice = self.raw_bytes();
         let offset = METADATA_HEADER.len();
         let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) |
@@ -396,7 +396,7 @@ impl<'tcx> MetadataBlob {
         Lazy::<CrateRoot<'tcx>>::from_position(pos).decode(self)
     }
 
-    pub fn list_crate_metadata(&self,
+    crate fn list_crate_metadata(&self,
                                out: &mut dyn io::Write) -> io::Result<()> {
         write!(out, "=External Dependencies=\n")?;
         let root = self.get_root();
@@ -449,7 +449,7 @@ impl<'tcx> EntryKind<'tcx> {
 }
 
 impl<'a, 'tcx> CrateMetadata {
-    pub fn is_proc_macro_crate(&self) -> bool {
+    crate fn is_proc_macro_crate(&self) -> bool {
         self.root.proc_macro_decls_static.is_some()
     }
 
@@ -499,7 +499,7 @@ impl<'a, 'tcx> CrateMetadata {
         &self.raw_proc_macros.unwrap()[pos]
     }
 
-    pub fn item_name(&self, item_index: DefIndex) -> Symbol {
+    crate fn item_name(&self, item_index: DefIndex) -> Symbol {
         if !self.is_proc_macro(item_index) {
             self.def_key(item_index)
                 .disambiguated_data
@@ -512,7 +512,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
+    crate fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
         if !self.is_proc_macro(index) {
             self.entry(index).kind.def_kind()
         } else {
@@ -522,7 +522,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
+    crate fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
         self.entry(index).span.decode((self, sess))
     }
 
@@ -556,7 +556,7 @@ impl<'a, 'tcx> CrateMetadata {
         )
     }
 
-    pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
+    crate fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
         match self.entry(item_id).kind {
             EntryKind::Trait(data) => {
                 let data = data.decode((self, sess));
@@ -622,7 +622,7 @@ impl<'a, 'tcx> CrateMetadata {
         )
     }
 
-    pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef {
+    crate fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef {
         let item = self.entry(item_id);
         let did = self.local_def_id(item_id);
 
@@ -647,7 +647,7 @@ impl<'a, 'tcx> CrateMetadata {
         tcx.alloc_adt_def(did, kind, variants, repr)
     }
 
-    pub fn get_predicates(
+    crate fn get_predicates(
         &self,
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
@@ -655,7 +655,7 @@ impl<'a, 'tcx> CrateMetadata {
         self.entry(item_id).predicates.unwrap().decode((self, tcx))
 }
 
-    pub fn get_predicates_defined_on(
+    crate fn get_predicates_defined_on(
         &self,
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
@@ -663,7 +663,7 @@ impl<'a, 'tcx> CrateMetadata {
         self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx))
     }
 
-    pub fn get_super_predicates(
+    crate fn get_super_predicates(
         &self,
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
@@ -677,30 +677,27 @@ impl<'a, 'tcx> CrateMetadata {
         super_predicates.decode((self, tcx))
     }
 
-    pub fn get_generics(&self,
-                        item_id: DefIndex,
-                        sess: &Session)
-                        -> ty::Generics {
+    crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
         self.entry(item_id).generics.unwrap().decode((self, sess))
     }
 
-    pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+    crate fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         self.entry(id).ty.unwrap().decode((self, tcx))
     }
 
-    pub fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
+    crate fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
         match self.is_proc_macro(id) {
             true => self.root.proc_macro_stability.clone(),
             false => self.entry(id).stability.map(|stab| stab.decode(self)),
         }
     }
 
-    pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
+    crate fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
         self.entry_unless_proc_macro(id)
             .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self)))
     }
 
-    pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
+    crate fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
         match self.is_proc_macro(id) {
             true => ty::Visibility::Public,
             false => self.entry(id).visibility.decode(self),
@@ -714,30 +711,31 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
+    crate fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
         self.get_impl_data(id).parent_impl
     }
 
-    pub fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity {
+    crate fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity {
         self.get_impl_data(id).polarity
     }
 
-    pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
+    crate fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness {
         self.get_impl_data(id).defaultness
     }
 
-    pub fn get_coerce_unsized_info(&self,
-                                   id: DefIndex)
-                                   -> Option<ty::adjustment::CoerceUnsizedInfo> {
+    crate fn get_coerce_unsized_info(
+        &self,
+        id: DefIndex,
+    ) -> Option<ty::adjustment::CoerceUnsizedInfo> {
         self.get_impl_data(id).coerce_unsized_info
     }
 
-    pub fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
+    crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
         self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx)))
     }
 
     /// Iterates over all the stability attributes in the given crate.
-    pub fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option<ast::Name>)] {
+    crate fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option<ast::Name>)] {
         // FIXME: For a proc macro crate, not sure whether we should return the "host"
         // features or an empty Vec. Both don't cause ICEs.
         tcx.arena.alloc_from_iter(self.root
@@ -746,7 +744,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     /// Iterates over the language items in the given crate.
-    pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
+    crate fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
         if self.is_proc_macro_crate() {
             // Proc macro crates do not export any lang-items to the target.
             &[]
@@ -759,7 +757,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     /// Iterates over the diagnostic items in the given crate.
-    pub fn get_diagnostic_items(
+    crate fn get_diagnostic_items(
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx FxHashMap<Symbol, DefId> {
@@ -776,7 +774,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     /// Iterates over each child of the given item.
-    pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
+    crate fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
         where F: FnMut(def::Export<hir::HirId>)
     {
         if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) {
@@ -911,12 +909,12 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
+    crate fn is_item_mir_available(&self, id: DefIndex) -> bool {
         !self.is_proc_macro(id) &&
         self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
     }
 
-    pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
+    crate fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
         self.entry_unless_proc_macro(id)
             .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx))))
             .unwrap_or_else(|| {
@@ -924,7 +922,7 @@ impl<'a, 'tcx> CrateMetadata {
             })
     }
 
-    pub fn get_promoted_mir(
+    crate fn get_promoted_mir(
         &self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
@@ -936,7 +934,7 @@ impl<'a, 'tcx> CrateMetadata {
             })
     }
 
-    pub fn mir_const_qualif(&self, id: DefIndex) -> u8 {
+    crate fn mir_const_qualif(&self, id: DefIndex) -> u8 {
         match self.entry(id).kind {
             EntryKind::Const(qualif, _) |
             EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) |
@@ -947,7 +945,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem {
+    crate fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem {
         let item = self.entry(id);
         let def_key = self.def_key(id);
         let parent = self.local_def_id(def_key.parent.unwrap());
@@ -981,11 +979,11 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
+    crate fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
         self.entry(id).variances.decode(self).collect()
     }
 
-    pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
+    crate fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
         match self.entry(node_id).kind {
             EntryKind::Struct(data, _) |
             EntryKind::Union(data, _) |
@@ -994,7 +992,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
+    crate fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
         match self.entry(node_id).kind {
             EntryKind::Struct(data, _) => {
                 data.decode(self).ctor.map(|index| self.local_def_id(index))
@@ -1006,8 +1004,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-
-    pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
+    crate fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
         // The attributes for a tuple struct/variant are attached to the definition, not the ctor;
         // we assume that someone passing in a tuple struct ctor is actually wanting to
         // look at the definition
@@ -1022,7 +1019,11 @@ impl<'a, 'tcx> CrateMetadata {
         Lrc::from(self.get_attributes(&item, sess))
     }
 
-    pub fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<ast::Name>> {
+    crate fn get_struct_field_names(
+        &self,
+        id: DefIndex,
+        sess: &Session,
+    ) -> Vec<Spanned<ast::Name>> {
         self.entry(id)
             .children
             .decode(self)
@@ -1049,7 +1050,7 @@ impl<'a, 'tcx> CrateMetadata {
         None
     }
 
-    pub fn get_inherent_implementations_for_type(
+    crate fn get_inherent_implementations_for_type(
         &self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
@@ -1060,7 +1061,7 @@ impl<'a, 'tcx> CrateMetadata {
                                       .map(|index| self.local_def_id(index)))
     }
 
-    pub fn get_implementations_for_trait(
+    crate fn get_implementations_for_trait(
         &self,
         tcx: TyCtxt<'tcx>,
         filter: Option<DefId>,
@@ -1091,7 +1092,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
+    crate fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
         let def_key = self.def_key(id);
         match def_key.disambiguated_data.data {
             DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (),
@@ -1108,7 +1109,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
 
-    pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
+    crate fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
         if self.is_proc_macro_crate() {
             // Proc macro crates do not have any *target* native libraries.
             vec![]
@@ -1117,7 +1118,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
+    crate fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
         if self.is_proc_macro_crate() {
             // Proc macro crates do not have any *target* foreign modules.
             &[]
@@ -1126,7 +1127,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_dylib_dependency_formats(
+    crate fn get_dylib_dependency_formats(
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx [(CrateNum, LinkagePreference)] {
@@ -1140,7 +1141,7 @@ impl<'a, 'tcx> CrateMetadata {
             }))
     }
 
-    pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
+    crate fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
         if self.is_proc_macro_crate() {
             // Proc macro crates do not depend on any target weak lang-items.
             &[]
@@ -1151,7 +1152,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_fn_param_names(&self, id: DefIndex) -> Vec<ast::Name> {
+    crate fn get_fn_param_names(&self, id: DefIndex) -> Vec<ast::Name> {
         let param_names = match self.entry(id).kind {
             EntryKind::Fn(data) |
             EntryKind::ForeignFn(data) => data.decode(self).param_names,
@@ -1161,7 +1162,7 @@ impl<'a, 'tcx> CrateMetadata {
         param_names.decode(self).collect()
     }
 
-    pub fn exported_symbols(
+    crate fn exported_symbols(
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
@@ -1174,7 +1175,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_rendered_const(&self, id: DefIndex) -> String {
+    crate fn get_rendered_const(&self, id: DefIndex) -> String {
         match self.entry(id).kind {
             EntryKind::Const(_, data) |
             EntryKind::AssocConst(_, _, data) => data.decode(self).0,
@@ -1182,7 +1183,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_macro(&self, id: DefIndex) -> MacroDef {
+    crate fn get_macro(&self, id: DefIndex) -> MacroDef {
         let entry = self.entry(id);
         match entry.kind {
             EntryKind::MacroDef(macro_def) => macro_def.decode(self),
@@ -1200,7 +1201,7 @@ impl<'a, 'tcx> CrateMetadata {
         constness == hir::Constness::Const
     }
 
-    pub fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
+    crate fn asyncness(&self, id: DefIndex) -> hir::IsAsync {
          match self.entry(id).kind {
             EntryKind::Fn(data) => data.decode(self).asyncness,
             EntryKind::Method(data) => data.decode(self).fn_data.asyncness,
@@ -1209,7 +1210,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn is_foreign_item(&self, id: DefIndex) -> bool {
+    crate fn is_foreign_item(&self, id: DefIndex) -> bool {
         match self.entry(id).kind {
             EntryKind::ForeignImmStatic |
             EntryKind::ForeignMutStatic |
@@ -1228,7 +1229,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
+    crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
         let sig = match self.entry(id).kind {
             EntryKind::Fn(data) |
             EntryKind::ForeignFn(data) => data.decode(self).sig,
@@ -1242,7 +1243,7 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     #[inline]
-    pub fn def_key(&self, index: DefIndex) -> DefKey {
+    crate fn def_key(&self, index: DefIndex) -> DefKey {
         let mut key = self.def_path_table.def_key(index);
         if self.is_proc_macro(index) {
             let name = self.raw_proc_macro(index).name();
@@ -1252,13 +1253,13 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     // Returns the path leading to the thing with this `id`.
-    pub fn def_path(&self, id: DefIndex) -> DefPath {
+    crate fn def_path(&self, id: DefIndex) -> DefPath {
         debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
         DefPath::make(self.cnum, id, |parent| self.def_key(parent))
     }
 
     #[inline]
-    pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
+    crate fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
         self.def_path_table.def_path_hash(index)
     }
 
@@ -1287,9 +1288,10 @@ impl<'a, 'tcx> CrateMetadata {
     ///
     /// Proc macro crates don't currently export spans, so this function does not have
     /// to work for them.
-    pub fn imported_source_files(&'a self,
-                                 local_source_map: &source_map::SourceMap)
-                                 -> ReadGuard<'a, Vec<cstore::ImportedSourceFile>> {
+    fn imported_source_files(
+        &'a self,
+        local_source_map: &source_map::SourceMap,
+    ) -> ReadGuard<'a, Vec<cstore::ImportedSourceFile>> {
         {
             let source_files = self.source_map_import_info.borrow();
             if !source_files.is_empty() {
diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs
index 9a30623b33d..7f76a9730e1 100644
--- a/src/librustc_metadata/dependency_format.rs
+++ b/src/librustc_metadata/dependency_format.rs
@@ -60,7 +60,7 @@ use rustc::ty::TyCtxt;
 use rustc::util::nodemap::FxHashMap;
 use rustc_target::spec::PanicStrategy;
 
-pub fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
+crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
     tcx.sess.crate_types.borrow().iter().map(|&ty| {
         let linkage = calculate_type(tcx, ty);
         verify_ok(tcx, &linkage);
diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs
index 4c279361ff5..3871eb89f7b 100644
--- a/src/librustc_metadata/dynamic_lib.rs
+++ b/src/librustc_metadata/dynamic_lib.rs
@@ -32,30 +32,6 @@ impl DynamicLibrary {
         }
     }
 
-    /// Loads a dynamic library into the global namespace (RTLD_GLOBAL on Unix)
-    /// and do it now (don't use RTLD_LAZY on Unix).
-    pub fn open_global_now(filename: &Path) -> Result<DynamicLibrary, String> {
-        let maybe_library = dl::open_global_now(filename.as_os_str());
-        match maybe_library {
-            Err(err) => Err(err),
-            Ok(handle) => Ok(DynamicLibrary { handle })
-        }
-    }
-
-    /// Returns the environment variable for this process's dynamic library
-    /// search path
-    pub fn envvar() -> &'static str {
-        if cfg!(windows) {
-            "PATH"
-        } else if cfg!(target_os = "macos") {
-            "DYLD_LIBRARY_PATH"
-        } else if cfg!(target_os = "haiku") {
-            "LIBRARY_PATH"
-        } else {
-            "LD_LIBRARY_PATH"
-        }
-    }
-
     /// Accesses the value at the symbol of the dynamic library.
     pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
         // This function should have a lifetime constraint of 'a on
@@ -83,7 +59,7 @@ mod dl {
     use std::ptr;
     use std::str;
 
-    pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
+    pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
         check_for_errors_in(|| {
             unsafe {
                 match filename {
@@ -94,13 +70,6 @@ mod dl {
         })
     }
 
-    pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> {
-        check_for_errors_in(|| unsafe {
-            let s = CString::new(filename.as_bytes()).unwrap();
-            libc::dlopen(s.as_ptr(), libc::RTLD_GLOBAL | libc::RTLD_NOW) as *mut u8
-        })
-    }
-
     unsafe fn open_external(filename: &OsStr) -> *mut u8 {
         let s = CString::new(filename.as_bytes()).unwrap();
         libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8
@@ -110,8 +79,8 @@ mod dl {
         libc::dlopen(ptr::null(), libc::RTLD_LAZY) as *mut u8
     }
 
-    pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
-        F: FnOnce() -> T,
+    fn check_for_errors_in<T, F>(f: F) -> Result<T, String>
+        where F: FnOnce() -> T,
     {
         use std::sync::{Mutex, Once};
         static INIT: Once = Once::new();
@@ -139,14 +108,15 @@ mod dl {
         }
     }
 
-    pub unsafe fn symbol(handle: *mut u8,
-                         symbol: *const libc::c_char)
-                         -> Result<*mut u8, String> {
+    pub(super) unsafe fn symbol(
+        handle: *mut u8,
+        symbol: *const libc::c_char,
+    ) -> Result<*mut u8, String> {
         check_for_errors_in(|| {
             libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8
         })
     }
-    pub unsafe fn close(handle: *mut u8) {
+    pub(super) unsafe fn close(handle: *mut u8) {
         libc::dlclose(handle as *mut libc::c_void); ()
     }
 }
@@ -178,11 +148,7 @@ mod dl {
         fn FreeLibrary(handle: HMODULE) -> BOOL;
     }
 
-    pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> {
-        open(Some(filename))
-    }
-
-    pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
+    pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
         // disable "dll load failed" error dialog.
         let prev_error_mode = unsafe {
             // SEM_FAILCRITICALERRORS 0x01
@@ -225,14 +191,15 @@ mod dl {
         result
     }
 
-    pub unsafe fn symbol(handle: *mut u8,
-                         symbol: *const c_char)
-                         -> Result<*mut u8, String> {
+    pub(super) unsafe fn symbol(
+        handle: *mut u8,
+        symbol: *const c_char,
+    ) -> Result<*mut u8, String> {
         let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8;
         ptr_result(ptr)
     }
 
-    pub unsafe fn close(handle: *mut u8) {
+    pub(super) unsafe fn close(handle: *mut u8) {
         FreeLibrary(handle as HMODULE);
     }
 
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index bbfbba2e0d8..03a14f88645 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -5,7 +5,7 @@ use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
                             EncodedMetadata, ForeignModule};
 use rustc::hir::def::CtorKind;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE};
-use rustc::hir::GenericParamKind;
+use rustc::hir::{GenericParamKind, AnonConst};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_index::vec::IndexVec;
@@ -42,9 +42,9 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 use rustc::hir::intravisit;
 
-pub struct EncodeContext<'tcx> {
+struct EncodeContext<'tcx> {
     opaque: opaque::Encoder,
-    pub tcx: TyCtxt<'tcx>,
+    tcx: TyCtxt<'tcx>,
 
     entries_index: Index<'tcx>,
 
@@ -313,11 +313,12 @@ impl<'tcx> EncodeContext<'tcx> {
     /// the `Entry` (which may point to other encoded information)
     /// and will then record the `Lazy<Entry>` for use in the index.
     // FIXME(eddyb) remove this.
-    pub fn record<DATA>(&mut self,
-                        id: DefId,
-                        op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>,
-                        data: DATA)
-    {
+    fn record<DATA>(
+        &mut self,
+        id: DefId,
+        op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>,
+        data: DATA,
+    ) {
         assert!(id.is_local());
 
         let entry = op(self, data);
@@ -1711,6 +1712,11 @@ impl Visitor<'tcx> for EncodeContext<'tcx> {
         intravisit::walk_expr(self, ex);
         self.encode_info_for_expr(ex);
     }
+    fn visit_anon_const(&mut self, c: &'tcx AnonConst) {
+        intravisit::walk_anon_const(self, c);
+        let def_id = self.tcx.hir().local_def_id(c.hir_id);
+        self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
+    }
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         intravisit::walk_item(self, item);
         let def_id = self.tcx.hir().local_def_id(item.hir_id);
@@ -1728,25 +1734,10 @@ impl Visitor<'tcx> for EncodeContext<'tcx> {
                           EncodeContext::encode_info_for_foreign_item,
                           (def_id, ni));
     }
-    fn visit_variant(&mut self,
-                     v: &'tcx hir::Variant,
-                     g: &'tcx hir::Generics,
-                     id: hir::HirId) {
-        intravisit::walk_variant(self, v, g, id);
-
-        if let Some(ref discr) = v.disr_expr {
-            let def_id = self.tcx.hir().local_def_id(discr.hir_id);
-            self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
-        }
-    }
     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
         intravisit::walk_generics(self, generics);
         self.encode_info_for_generics(generics);
     }
-    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
-        intravisit::walk_ty(self, ty);
-        self.encode_info_for_ty(ty);
-    }
     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
         let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
         self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
@@ -1784,16 +1775,6 @@ impl EncodeContext<'tcx> {
         }
     }
 
-    fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
-        match ty.kind {
-            hir::TyKind::Array(_, ref length) => {
-                let def_id = self.tcx.hir().local_def_id(length.hir_id);
-                self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
-            }
-            _ => {}
-        }
-    }
-
     fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
         match expr.kind {
             hir::ExprKind::Closure(..) => {
@@ -1920,7 +1901,7 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
 // will allow us to slice the metadata to the precise length that we just
 // generated regardless of trailing bytes that end up in it.
 
-pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
+crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
     let mut encoder = opaque::Encoder::new(vec![]);
     encoder.emit_raw_bytes(METADATA_HEADER);
 
@@ -1962,7 +1943,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
     EncodedMetadata { raw_data: result }
 }
 
-pub fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
+fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
     let ty = tcx.type_of(did);
     match ty.kind {
         ty::Adt(ref def, _) => return def.repr,
diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs
index 8a4f6e6f17a..fa1402584ed 100644
--- a/src/librustc_metadata/foreign_modules.rs
+++ b/src/librustc_metadata/foreign_modules.rs
@@ -3,7 +3,7 @@ use rustc::hir;
 use rustc::middle::cstore::ForeignModule;
 use rustc::ty::TyCtxt;
 
-pub fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
+crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
     let mut collector = Collector {
         tcx,
         modules: Vec::new(),
diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs
index 6f248f22cf2..037f9d35630 100644
--- a/src/librustc_metadata/index.rs
+++ b/src/librustc_metadata/index.rs
@@ -7,7 +7,7 @@ use std::u32;
 use log::debug;
 
 /// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
-pub trait FixedSizeEncoding {
+trait FixedSizeEncoding {
     const BYTE_LEN: usize;
 
     // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead,
@@ -75,25 +75,25 @@ impl FixedSizeEncoding for u32 {
 /// `u32::MAX`. Whenever an index is visited, we fill in the
 /// appropriate spot by calling `record_position`. We should never
 /// visit the same index twice.
-pub struct Index<'tcx> {
+crate struct Index<'tcx> {
     positions: Vec<u8>,
     _marker: PhantomData<&'tcx ()>,
 }
 
 impl Index<'tcx> {
-    pub fn new(max_index: usize) -> Self {
+    crate fn new(max_index: usize) -> Self {
         Index {
             positions: vec![0xff; max_index * 4],
             _marker: PhantomData,
         }
     }
 
-    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'tcx>>) {
+    crate fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'tcx>>) {
         assert!(def_id.is_local());
         self.record_index(def_id.index, entry);
     }
 
-    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'tcx>>) {
+    fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'tcx>>) {
         assert!(entry.position < (u32::MAX as usize));
         let position = entry.position as u32;
         let array_index = item.index();
@@ -108,7 +108,7 @@ impl Index<'tcx> {
         position.write_to_bytes_at(positions, array_index)
     }
 
-    pub fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> {
+    crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> {
         let pos = buf.position();
 
         // First we write the length of the lower range ...
@@ -123,7 +123,7 @@ impl Lazy<[Index<'tcx>]> {
     /// Given the metadata, extract out the offset of a particular
     /// DefIndex (if any).
     #[inline(never)]
-    pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
+    crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
         let bytes = &bytes[self.position..];
         debug!("Index::lookup: index={:?} len={:?}",
                def_index,
diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs
index 527d4421fca..4291f3a4ae3 100644
--- a/src/librustc_metadata/link_args.rs
+++ b/src/librustc_metadata/link_args.rs
@@ -4,7 +4,7 @@ use rustc::ty::TyCtxt;
 use rustc_target::spec::abi::Abi;
 use syntax::symbol::sym;
 
-pub fn collect(tcx: TyCtxt<'_>) -> Vec<String> {
+crate fn collect(tcx: TyCtxt<'_>) -> Vec<String> {
     let mut collector = Collector {
         args: Vec::new(),
     };
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 8df236c41cf..05676dad334 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -212,13 +212,14 @@
 //! no means all of the necessary details. Take a look at the rest of
 //! metadata::locator or metadata::creader for all the juicy details!
 
-use crate::cstore::{MetadataRef, MetadataBlob};
+use crate::cstore::{MetadataBlob, CStore};
 use crate::creader::Library;
 use crate::schema::{METADATA_HEADER, rustc_version};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::svh::Svh;
-use rustc::middle::cstore::MetadataLoader;
+use rustc_data_structures::sync::MetadataRef;
+use rustc::middle::cstore::{CrateSource, MetadataLoader};
 use rustc::session::{config, Session};
 use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
 use rustc::session::search_paths::PathKind;
@@ -245,13 +246,13 @@ use rustc_data_structures::owning_ref::OwningRef;
 use log::{debug, info, warn};
 
 #[derive(Clone)]
-pub struct CrateMismatch {
+crate struct CrateMismatch {
     path: PathBuf,
     got: String,
 }
 
 #[derive(Clone)]
-pub struct Context<'a> {
+crate struct Context<'a> {
     pub sess: &'a Session,
     pub span: Span,
     pub crate_name: Symbol,
@@ -272,11 +273,9 @@ pub struct Context<'a> {
     pub metadata_loader: &'a dyn MetadataLoader,
 }
 
-pub struct CratePaths {
-    pub ident: String,
-    pub dylib: Option<PathBuf>,
-    pub rlib: Option<PathBuf>,
-    pub rmeta: Option<PathBuf>,
+crate struct CratePaths {
+    pub name: Symbol,
+    pub source: CrateSource,
 }
 
 #[derive(Copy, Clone, PartialEq)]
@@ -296,14 +295,8 @@ impl fmt::Display for CrateFlavor {
     }
 }
 
-impl CratePaths {
-    fn paths(&self) -> Vec<PathBuf> {
-        self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).cloned().collect()
-    }
-}
-
 impl<'a> Context<'a> {
-    pub fn reset(&mut self) {
+    crate fn reset(&mut self) {
         self.rejected_via_hash.clear();
         self.rejected_via_triple.clear();
         self.rejected_via_kind.clear();
@@ -311,7 +304,7 @@ impl<'a> Context<'a> {
         self.rejected_via_filename.clear();
     }
 
-    pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
+    crate fn maybe_load_library_crate(&mut self) -> Option<Library> {
         let mut seen_paths = FxHashSet::default();
         match self.extra_filename {
             Some(s) => self.find_library_crate(s, &mut seen_paths)
@@ -320,10 +313,10 @@ impl<'a> Context<'a> {
         }
     }
 
-    pub fn report_errs(self) -> ! {
+    crate fn report_errs(self) -> ! {
         let add = match self.root {
             None => String::new(),
-            Some(r) => format!(" which `{}` depends on", r.ident),
+            Some(r) => format!(" which `{}` depends on", r.name),
         };
         let mut msg = "the following crate versions were found:".to_string();
         let mut err = if !self.rejected_via_hash.is_empty() {
@@ -341,8 +334,8 @@ impl<'a> Context<'a> {
             match self.root {
                 None => {}
                 Some(r) => {
-                    for path in r.paths().iter() {
-                        msg.push_str(&format!("\ncrate `{}`: {}", r.ident, path.display()));
+                    for path in r.source.paths() {
+                        msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display()));
                     }
                 }
             }
@@ -534,18 +527,8 @@ impl<'a> Context<'a> {
         // search is being performed for.
         let mut libraries = FxHashMap::default();
         for (_hash, (rlibs, rmetas, dylibs)) in candidates {
-            let mut slot = None;
-            let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot);
-            let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot);
-            let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot);
-            if let Some((h, m)) = slot {
-                libraries.insert(h,
-                                 Library {
-                                     dylib,
-                                     rlib,
-                                     rmeta,
-                                     metadata: m,
-                                 });
+            if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs) {
+                libraries.insert(svh, lib);
             }
         }
 
@@ -563,7 +546,7 @@ impl<'a> Context<'a> {
                                                self.crate_name);
                 let candidates = libraries.iter().filter_map(|(_, lib)| {
                     let crate_name = &lib.metadata.get_root().name.as_str();
-                    match &(&lib.dylib, &lib.rlib) {
+                    match &(&lib.source.dylib, &lib.source.rlib) {
                         &(&Some((ref pd, _)), &Some((ref pr, _))) => {
                             Some(format!("\ncrate `{}`: {}\n{:>padding$}",
                                          crate_name,
@@ -584,6 +567,21 @@ impl<'a> Context<'a> {
         }
     }
 
+    fn extract_lib(
+        &mut self,
+        rlibs: FxHashMap<PathBuf, PathKind>,
+        rmetas: FxHashMap<PathBuf, PathKind>,
+        dylibs: FxHashMap<PathBuf, PathKind>,
+    ) -> Option<(Svh, Library)> {
+        let mut slot = None;
+        let source = CrateSource {
+            rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot),
+            rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot),
+            dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot),
+        };
+        slot.map(|(svh, metadata)| (svh, Library { source, metadata }))
+    }
+
     // Attempts to extract *one* library from the set `m`. If the set has no
     // elements, `None` is returned. If the set has more than one element, then
     // the errors and notes are emitted about the set of libraries.
@@ -828,23 +826,8 @@ impl<'a> Context<'a> {
             }
         };
 
-        // Extract the rlib/dylib pair.
-        let mut slot = None;
-        let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot);
-        let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot);
-        let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot);
-
-        if rlib.is_none() && rmeta.is_none() && dylib.is_none() {
-            return None;
-        }
-        slot.map(|(_, metadata)|
-            Library {
-                dylib,
-                rlib,
-                rmeta,
-                metadata,
-            }
-        )
+        // Extract the dylib/rlib/rmeta triple.
+        self.extract_lib(rlibs, rmetas, dylibs).map(|(_, lib)| lib)
     }
 }
 
@@ -931,7 +914,7 @@ fn get_metadata_section_imp(target: &Target,
 /// A diagnostic function for dumping crate metadata to an output stream.
 pub fn list_file_metadata(target: &Target,
                           path: &Path,
-                          loader: &dyn MetadataLoader,
+                          cstore: &CStore,
                           out: &mut dyn io::Write)
                           -> io::Result<()> {
     let filename = path.file_name().unwrap().to_str().unwrap();
@@ -942,7 +925,7 @@ pub fn list_file_metadata(target: &Target,
     } else {
         CrateFlavor::Dylib
     };
-    match get_metadata_section(target, flavor, path, loader) {
+    match get_metadata_section(target, flavor, path, &*cstore.metadata_loader) {
         Ok(metadata) => metadata.list_crate_metadata(out),
         Err(msg) => write!(out, "{}\n", msg),
     }
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 24ed8fcd8dd..9e4c2685f11 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -11,7 +11,7 @@ use syntax::feature_gate::{self, GateIssue};
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::{span_err, struct_span_err};
 
-pub fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
+crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
     let mut collector = Collector {
         tcx,
         libs: Vec::new(),
@@ -21,7 +21,7 @@ pub fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
     return collector.libs;
 }
 
-pub fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
+crate fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
     match lib.cfg {
         Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
         None => true,
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 4fe9c466cb6..d3539e71401 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -21,7 +21,7 @@ use syntax_pos::{self, Span};
 
 use std::marker::PhantomData;
 
-pub fn rustc_version() -> String {
+crate fn rustc_version() -> String {
     format!("rustc {}",
             option_env!("CFG_VERSION").unwrap_or("unknown version"))
 }
@@ -29,7 +29,7 @@ pub fn rustc_version() -> String {
 /// Metadata encoding version.
 /// N.B., increment this if you change the format of metadata such that
 /// the rustc version can't be found to compare with `rustc_version()`.
-pub const METADATA_VERSION: u8 = 4;
+const METADATA_VERSION: u8 = 4;
 
 /// Metadata header which includes `METADATA_VERSION`.
 /// To get older versions of rustc to ignore this metadata,
@@ -39,12 +39,12 @@ pub const METADATA_VERSION: u8 = 4;
 /// This header is followed by the position of the `CrateRoot`,
 /// which is encoded as a 32-bit big-endian unsigned integer,
 /// and further followed by the rustc version string.
-pub const METADATA_HEADER: &[u8; 12] =
+crate const METADATA_HEADER: &[u8; 12] =
     &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
 
 /// Additional metadata for a `Lazy<T>` where `T` may not be `Sized`,
 /// e.g. for `Lazy<[T]>`, this is the length (count of `T` values).
-pub trait LazyMeta {
+crate trait LazyMeta {
     type Meta: Copy + 'static;
 
     /// Returns the minimum encoded size.
@@ -98,7 +98,7 @@ impl<T> LazyMeta for [T] {
 #[must_use]
 // FIXME(#59875) the `Meta` parameter only exists to dodge
 // invariance wrt `T` (coming from the `meta: T::Meta` field).
-pub struct Lazy<T, Meta = <T as LazyMeta>::Meta>
+crate struct Lazy<T, Meta = <T as LazyMeta>::Meta>
     where T: ?Sized + LazyMeta<Meta = Meta>,
           Meta: 'static + Copy,
 {
@@ -108,7 +108,7 @@ pub struct Lazy<T, Meta = <T as LazyMeta>::Meta>
 }
 
 impl<T: ?Sized + LazyMeta> Lazy<T> {
-    pub fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy<T> {
+    crate fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy<T> {
         Lazy {
             position,
             meta,
@@ -118,13 +118,13 @@ impl<T: ?Sized + LazyMeta> Lazy<T> {
 }
 
 impl<T> Lazy<T> {
-    pub fn from_position(position: usize) -> Lazy<T> {
+    crate fn from_position(position: usize) -> Lazy<T> {
         Lazy::from_position_and_meta(position, ())
     }
 }
 
 impl<T> Lazy<[T]> {
-    pub fn empty() -> Lazy<[T]> {
+    crate fn empty() -> Lazy<[T]> {
         Lazy::from_position_and_meta(0, 0)
     }
 }
@@ -141,7 +141,7 @@ impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedDecodable for Lazy<T>
 
 /// Encoding / decoding state for `Lazy`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum LazyState {
+crate enum LazyState {
     /// Outside of a metadata node.
     NoNode,
 
@@ -156,7 +156,7 @@ pub enum LazyState {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct CrateRoot<'tcx> {
+crate struct CrateRoot<'tcx> {
     pub name: Symbol,
     pub triple: TargetTriple,
     pub extra_filename: String,
@@ -202,7 +202,7 @@ pub struct CrateRoot<'tcx> {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct CrateDep {
+crate struct CrateDep {
     pub name: ast::Name,
     pub hash: Svh,
     pub kind: DepKind,
@@ -210,13 +210,13 @@ pub struct CrateDep {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct TraitImpls {
+crate struct TraitImpls {
     pub trait_id: (u32, DefIndex),
     pub impls: Lazy<[DefIndex]>,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct Entry<'tcx> {
+crate struct Entry<'tcx> {
     pub kind: EntryKind<'tcx>,
     pub visibility: Lazy<ty::Visibility>,
     pub span: Lazy<Span>,
@@ -237,7 +237,7 @@ pub struct Entry<'tcx> {
 }
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
-pub enum EntryKind<'tcx> {
+crate enum EntryKind<'tcx> {
     Const(ConstQualif, Lazy<RenderedConst>),
     ImmStatic,
     MutStatic,
@@ -272,28 +272,28 @@ pub enum EntryKind<'tcx> {
 
 /// Additional data for EntryKind::Const and EntryKind::AssocConst
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
-pub struct ConstQualif {
+crate struct ConstQualif {
     pub mir: u8,
 }
 
 /// Contains a constant which has been rendered to a String.
 /// Used by rustdoc.
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct RenderedConst(pub String);
+crate struct RenderedConst(pub String);
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct ModData {
+crate struct ModData {
     pub reexports: Lazy<[def::Export<hir::HirId>]>,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct MacroDef {
+crate struct MacroDef {
     pub body: String,
     pub legacy: bool,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct FnData<'tcx> {
+crate struct FnData<'tcx> {
     pub asyncness: hir::IsAsync,
     pub constness: hir::Constness,
     pub param_names: Lazy<[ast::Name]>,
@@ -301,7 +301,7 @@ pub struct FnData<'tcx> {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct VariantData<'tcx> {
+crate struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
     pub discr: ty::VariantDiscr,
     /// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
@@ -312,7 +312,7 @@ pub struct VariantData<'tcx> {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct TraitData<'tcx> {
+crate struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
     pub paren_sugar: bool,
     pub has_auto_impl: bool,
@@ -321,12 +321,12 @@ pub struct TraitData<'tcx> {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct TraitAliasData<'tcx> {
+crate struct TraitAliasData<'tcx> {
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct ImplData<'tcx> {
+crate struct ImplData<'tcx> {
     pub polarity: ty::ImplPolarity,
     pub defaultness: hir::Defaultness,
     pub parent_impl: Option<DefId>,
@@ -341,7 +341,7 @@ pub struct ImplData<'tcx> {
 /// is a trait or an impl and whether, in a trait, it has
 /// a default, or an in impl, whether it's marked "default".
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
-pub enum AssocContainer {
+crate enum AssocContainer {
     TraitRequired,
     TraitWithDefault,
     ImplDefault,
@@ -349,7 +349,7 @@ pub enum AssocContainer {
 }
 
 impl AssocContainer {
-    pub fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer {
+    crate fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer {
         match *self {
             AssocContainer::TraitRequired |
             AssocContainer::TraitWithDefault => ty::TraitContainer(def_id),
@@ -359,7 +359,7 @@ impl AssocContainer {
         }
     }
 
-    pub fn defaultness(&self) -> hir::Defaultness {
+    crate fn defaultness(&self) -> hir::Defaultness {
         match *self {
             AssocContainer::TraitRequired => hir::Defaultness::Default {
                 has_value: false,
@@ -376,22 +376,22 @@ impl AssocContainer {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct MethodData<'tcx> {
+crate struct MethodData<'tcx> {
     pub fn_data: FnData<'tcx>,
     pub container: AssocContainer,
     pub has_self: bool,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct ClosureData<'tcx> {
+crate struct ClosureData<'tcx> {
     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct GeneratorData<'tcx> {
+crate struct GeneratorData<'tcx> {
     pub layout: mir::GeneratorLayout<'tcx>,
 }
 
 // Tags used for encoding Spans:
-pub const TAG_VALID_SPAN: u8 = 0;
-pub const TAG_INVALID_SPAN: u8 = 1;
+crate const TAG_VALID_SPAN: u8 = 0;
+crate const TAG_INVALID_SPAN: u8 = 1;
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 2b8965aa5d4..1f86aafbddf 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -104,8 +104,7 @@ impl<'a> Resolver<'a> {
             return self.module_map[&def_id]
         }
 
-        let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only();
-        if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
+        if let Some(&module) = self.extern_module_map.get(&def_id) {
             return module;
         }
 
@@ -121,7 +120,7 @@ impl<'a> Resolver<'a> {
         let module = self.arenas.alloc_module(ModuleData::new(
             parent, kind, def_id, ExpnId::root(), DUMMY_SP
         ));
-        self.extern_module_map.insert((def_id, macros_only), module);
+        self.extern_module_map.insert(def_id, module);
         module
     }
 
@@ -618,6 +617,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                     let crate_id = self.r.crate_loader.process_extern_crate(
                         item, &self.r.definitions
                     );
+                    self.r.extern_crate_map.insert(item.id, crate_id);
                     self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
                 };
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index e3c272e12fe..5f77bcfeb7f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -26,7 +26,7 @@ use rustc::session::Session;
 use rustc::lint;
 use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap};
 use rustc::hir::def::Namespace::*;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::{TraitMap, GlobMap};
 use rustc::ty::{self, DefIdTree};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
@@ -855,6 +855,8 @@ pub struct Resolver<'a> {
     /// Resolutions for labels (node IDs of their corresponding blocks or loops).
     label_res_map: NodeMap<NodeId>,
 
+    /// `CrateNum` resolutions of `extern crate` items.
+    pub extern_crate_map: NodeMap<CrateNum>,
     pub export_map: ExportMap<NodeId>,
     pub trait_map: TraitMap,
 
@@ -878,7 +880,7 @@ pub struct Resolver<'a> {
     /// language items.
     empty_module: Module<'a>,
     module_map: FxHashMap<DefId, Module<'a>>,
-    extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>,
+    extern_module_map: FxHashMap<DefId, Module<'a>>,
     binding_parent_modules: FxHashMap<PtrKey<'a, NameBinding<'a>>, Module<'a>>,
 
     /// Maps glob imports to the names of items actually imported.
@@ -900,7 +902,7 @@ pub struct Resolver<'a> {
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
 
-    crate_loader: &'a mut CrateLoader<'a>,
+    crate_loader: &'a CrateLoader<'a>,
     macro_names: FxHashSet<Ident>,
     builtin_macros: FxHashMap<Name, SyntaxExtension>,
     macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
@@ -1070,7 +1072,7 @@ impl<'a> Resolver<'a> {
                cstore: &'a CStore,
                krate: &Crate,
                crate_name: &str,
-               crate_loader: &'a mut CrateLoader<'a>,
+               crate_loader: &'a CrateLoader<'a>,
                arenas: &'a ResolverArenas<'a>)
                -> Resolver<'a> {
         let root_def_id = DefId::local(CRATE_DEF_INDEX);
@@ -1155,6 +1157,7 @@ impl<'a> Resolver<'a> {
             partial_res_map: Default::default(),
             import_res_map: Default::default(),
             label_res_map: Default::default(),
+            extern_crate_map: Default::default(),
             export_map: FxHashMap::default(),
             trait_map: Default::default(),
             empty_module,
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index 7bef693a5be..c2c883fd20e 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -551,7 +551,7 @@ impl MetaItem {
 impl MetaItemKind {
     pub fn tokens(&self, span: Span) -> TokenStream {
         match *self {
-            MetaItemKind::Word => TokenStream::empty(),
+            MetaItemKind::Word => TokenStream::default(),
             MetaItemKind::NameValue(ref lit) => {
                 let mut vec = vec![TokenTree::token(token::Eq, span).into()];
                 lit.tokens().append_to_tree_and_joint_vec(&mut vec);
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1e44f3dd5e5..9fcd918cef1 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -676,12 +676,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
             }
             Some(TokenTree::Token(..)) => {}
-            None => return TokenStream::empty(),
+            None => return TokenStream::default(),
         }
         self.cx.span_err(span, "custom attribute invocations must be \
             of the form `#[foo]` or `#[foo(..)]`, the macro name must only be \
             followed by a delimiter token");
-        TokenStream::empty()
+        TokenStream::default()
     }
 
     fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
diff --git a/src/libsyntax/ext/mbe/transcribe.rs b/src/libsyntax/ext/mbe/transcribe.rs
index ba818ebd35c..da930436d81 100644
--- a/src/libsyntax/ext/mbe/transcribe.rs
+++ b/src/libsyntax/ext/mbe/transcribe.rs
@@ -95,7 +95,7 @@ pub(super) fn transcribe(
 ) -> TokenStream {
     // Nothing for us to transcribe...
     if src.is_empty() {
-        return TokenStream::empty();
+        return TokenStream::default();
     }
 
     // We descend into the RHS (`src`), expanding things as we go. This stack contains the things
diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs
index 8eecef1020d..4fae25bbde6 100644
--- a/src/libsyntax/ext/placeholders.rs
+++ b/src/libsyntax/ext/placeholders.rs
@@ -15,7 +15,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
     fn mac_placeholder() -> ast::Mac {
         ast::Mac {
             path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
-            tts: TokenStream::empty().into(),
+            tts: TokenStream::default().into(),
             delim: ast::MacDelimiter::Brace,
             span: DUMMY_SP,
             prior_type_ascription: None,
@@ -32,12 +32,12 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
         attrs: ThinVec::new(),
         kind: ast::ExprKind::Mac(mac_placeholder()),
     });
-    let ty = P(ast::Ty {
+    let ty = || P(ast::Ty {
         id,
         kind: ast::TyKind::Mac(mac_placeholder()),
         span,
     });
-    let pat = P(ast::Pat {
+    let pat = || P(ast::Pat {
         id,
         kind: ast::PatKind::Mac(mac_placeholder()),
         span,
@@ -83,7 +83,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
                 body: expr_placeholder(),
                 guard: None,
                 id,
-                pat,
+                pat: pat(),
                 span,
                 is_placeholder: true,
             }
@@ -105,7 +105,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
                 id,
                 ident,
                 is_shorthand: false,
-                pat,
+                pat: pat(),
                 span,
                 is_placeholder: true,
             }
@@ -124,9 +124,9 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
             ast::Param {
                 attrs: Default::default(),
                 id,
-                pat,
+                pat: pat(),
                 span,
-                ty,
+                ty: ty(),
                 is_placeholder: true,
             }
         ]),
@@ -136,7 +136,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
                 id,
                 ident: None,
                 span,
-                ty,
+                ty: ty(),
                 vis,
                 is_placeholder: true,
             }
diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs
index 65037c4a0b8..08142ba6c58 100644
--- a/src/libsyntax/ext/proc_macro_server.rs
+++ b/src/libsyntax/ext/proc_macro_server.rs
@@ -394,7 +394,7 @@ impl server::Types for Rustc<'_> {
 
 impl server::TokenStream for Rustc<'_> {
     fn new(&mut self) -> Self::TokenStream {
-        TokenStream::empty()
+        TokenStream::default()
     }
     fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
         stream.is_empty()
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index 2423e1070fc..4cf987417b8 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -12,7 +12,7 @@
 use crate::source_map::{SourceMap, FilePathMapping};
 
 use errors::registry::Registry;
-use errors::{SubDiagnostic, CodeSuggestion, SourceMapper};
+use errors::{SubDiagnostic, CodeSuggestion, SourceMapper, SourceMapperDyn};
 use errors::{DiagnosticId, Applicability};
 use errors::emitter::{Emitter, HumanReadableErrorType};
 
@@ -113,6 +113,10 @@ impl Emitter for JsonEmitter {
         }
     }
 
+    fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> {
+        Some(&self.sm)
+    }
+
     fn should_show_explain(&self) -> bool {
         match self.json_rendered {
             HumanReadableErrorType::Short(_) => false,
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 3923b9f297b..60ee17d09b7 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -610,10 +610,8 @@ pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
 }
 
 pub fn noop_visit_tts<T: MutVisitor>(TokenStream(tts): &mut TokenStream, vis: &mut T) {
-    visit_opt(tts, |tts| {
-        let tts = Lrc::make_mut(tts);
-        visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree));
-    })
+    let tts = Lrc::make_mut(tts);
+    visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree));
 }
 
 // Applies ident visitor if it's an ident; applies other visits to interpolated nodes.
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index e74f3045db8..0963efcfc8a 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -203,7 +203,7 @@ impl<'a> Parser<'a> {
                 };
                 TokenStream::from_streams(smallvec![eq.into(), tokens])
             } else {
-                TokenStream::empty()
+                TokenStream::default()
             };
             ast::AttrItem { path, tokens }
         })
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 400bf0f3856..478cfefc224 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1273,7 +1273,7 @@ impl<'a> Parser<'a> {
             // This can happen due to a bad interaction of two unrelated recovery mechanisms with
             // mismatched delimiters *and* recovery lookahead on the likely typo `pub ident(`
             // (#62881).
-            return Ok((ret?, TokenStream::new(vec![])));
+            return Ok((ret?, TokenStream::default()));
         } else {
             &mut self.token_cursor.stack[prev].last_token
         };
@@ -1288,7 +1288,7 @@ impl<'a> Parser<'a> {
                 // This can happen due to a bad interaction of two unrelated recovery mechanisms
                 // with mismatched delimiters *and* recovery lookahead on the likely typo
                 // `pub ident(` (#62895, different but similar to the case above).
-                return Ok((ret?, TokenStream::new(vec![])));
+                return Ok((ret?, TokenStream::default()));
             }
         };
 
diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs
index 48f9e301610..e288346a329 100644
--- a/src/libsyntax/parse/parser/pat.rs
+++ b/src/libsyntax/parse/parser/pat.rs
@@ -367,6 +367,7 @@ impl<'a> Parser<'a> {
 
         let pat = self.mk_pat(lo.to(self.prev_span), pat);
         let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
+        let pat = self.recover_intersection_pat(pat)?;
 
         if !allow_range_pat {
             self.ban_pat_range_if_ambiguous(&pat)?
@@ -375,6 +376,65 @@ impl<'a> Parser<'a> {
         Ok(pat)
     }
 
+    /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`.
+    ///
+    /// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs`
+    /// should already have been parsed by now  at this point,
+    /// if the next token is `@` then we can try to parse the more general form.
+    ///
+    /// Consult `parse_pat_ident` for the `binding` grammar.
+    ///
+    /// The notion of intersection patterns are found in
+    /// e.g. [F#][and] where they are called AND-patterns.
+    ///
+    /// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching
+    fn recover_intersection_pat(&mut self, lhs: P<Pat>) -> PResult<'a, P<Pat>> {
+        if self.token.kind != token::At {
+            // Next token is not `@` so it's not going to be an intersection pattern.
+            return Ok(lhs);
+        }
+
+        // At this point we attempt to parse `@ $pat_rhs` and emit an error.
+        self.bump(); // `@`
+        let mut rhs = self.parse_pat(None)?;
+        let sp = lhs.span.to(rhs.span);
+
+        if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind {
+            // The user inverted the order, so help them fix that.
+            let mut applicability = Applicability::MachineApplicable;
+            lhs.walk(&mut |p| match p.kind {
+                // `check_match` is unhappy if the subpattern has a binding anywhere.
+                PatKind::Ident(..) => {
+                    applicability = Applicability::MaybeIncorrect;
+                    false // Short-circuit.
+                },
+                _ => true,
+            });
+
+            let lhs_span = lhs.span;
+            // Move the LHS into the RHS as a subpattern.
+            // The RHS is now the full pattern.
+            *sub = Some(lhs);
+
+            self.struct_span_err(sp, "pattern on wrong side of `@`")
+                .span_label(lhs_span, "pattern on the left, should be on the right")
+                .span_label(rhs.span, "binding on the right, should be on the left")
+                .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability)
+                .emit();
+        } else {
+            // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`.
+            rhs.kind = PatKind::Wild;
+            self.struct_span_err(sp, "left-hand side of `@` must be a binding")
+                .span_label(lhs.span, "interpreted as a pattern, not a binding")
+                .span_label(rhs.span, "also a pattern")
+                .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`")
+                .emit();
+        }
+
+        rhs.span = sp;
+        Ok(rhs)
+    }
+
     /// Ban a range pattern if it has an ambiguous interpretation.
     fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> {
         match pat.kind {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 7d4ffe493d7..68dd90b54ab 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2381,7 +2381,8 @@ impl<'a> State<'a> {
                 }
                 self.print_ident(ident);
                 if let Some(ref p) = *sub {
-                    self.s.word("@");
+                    self.s.space();
+                    self.s.word_space("@");
                     self.print_pat(p);
                 }
             }
diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs
index 5e569f9dae3..1501adc5971 100644
--- a/src/libsyntax/source_map.rs
+++ b/src/libsyntax/source_map.rs
@@ -970,6 +970,9 @@ impl SourceMapper for SourceMap {
     fn span_to_string(&self, sp: Span) -> String {
         self.span_to_string(sp)
     }
+    fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
+        self.span_to_snippet(sp)
+    }
     fn span_to_filename(&self, sp: Span) -> FileName {
         self.span_to_filename(sp)
     }
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index 970bacdde13..0ff1c26bac2 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -136,13 +136,8 @@ impl TokenTree {
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
-///
-/// The use of `Option` is an optimization that avoids the need for an
-/// allocation when the stream is empty. However, it is not guaranteed that an
-/// empty stream is represented with `None`; it may be represented as a `Some`
-/// around an empty `Vec`.
-#[derive(Clone, Debug)]
-pub struct TokenStream(pub Option<Lrc<Vec<TreeAndJoint>>>);
+#[derive(Clone, Debug, Default)]
+pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
 
 pub type TreeAndJoint = (TokenTree, IsJoint);
 
@@ -163,36 +158,34 @@ impl TokenStream {
     /// separating the two arguments with a comma for diagnostic suggestions.
     pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
         // Used to suggest if a user writes `foo!(a b);`
-        if let Some(ref stream) = self.0 {
-            let mut suggestion = None;
-            let mut iter = stream.iter().enumerate().peekable();
-            while let Some((pos, ts)) = iter.next() {
-                if let Some((_, next)) = iter.peek() {
-                    let sp = match (&ts, &next) {
-                        (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue,
-                        ((TokenTree::Token(token_left), NonJoint),
-                         (TokenTree::Token(token_right), _))
-                        if ((token_left.is_ident() && !token_left.is_reserved_ident())
-                            || token_left.is_lit()) &&
-                            ((token_right.is_ident() && !token_right.is_reserved_ident())
-                            || token_right.is_lit()) => token_left.span,
-                        ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(),
-                        _ => continue,
-                    };
-                    let sp = sp.shrink_to_hi();
-                    let comma = (TokenTree::token(token::Comma, sp), NonJoint);
-                    suggestion = Some((pos, comma, sp));
-                }
-            }
-            if let Some((pos, comma, sp)) = suggestion {
-                let mut new_stream = vec![];
-                let parts = stream.split_at(pos + 1);
-                new_stream.extend_from_slice(parts.0);
-                new_stream.push(comma);
-                new_stream.extend_from_slice(parts.1);
-                return Some((TokenStream::new(new_stream), sp));
+        let mut suggestion = None;
+        let mut iter = self.0.iter().enumerate().peekable();
+        while let Some((pos, ts)) = iter.next() {
+            if let Some((_, next)) = iter.peek() {
+                let sp = match (&ts, &next) {
+                    (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue,
+                    ((TokenTree::Token(token_left), NonJoint),
+                     (TokenTree::Token(token_right), _))
+                    if ((token_left.is_ident() && !token_left.is_reserved_ident())
+                        || token_left.is_lit()) &&
+                        ((token_right.is_ident() && !token_right.is_reserved_ident())
+                        || token_right.is_lit()) => token_left.span,
+                    ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(),
+                    _ => continue,
+                };
+                let sp = sp.shrink_to_hi();
+                let comma = (TokenTree::token(token::Comma, sp), NonJoint);
+                suggestion = Some((pos, comma, sp));
             }
         }
+        if let Some((pos, comma, sp)) = suggestion {
+            let mut new_stream = vec![];
+            let parts = self.0.split_at(pos + 1);
+            new_stream.extend_from_slice(parts.0);
+            new_stream.push(comma);
+            new_stream.extend_from_slice(parts.1);
+            return Some((TokenStream::new(new_stream), sp));
+        }
         None
     }
 }
@@ -224,28 +217,21 @@ impl PartialEq<TokenStream> for TokenStream {
 }
 
 impl TokenStream {
-    pub fn len(&self) -> usize {
-        if let Some(ref slice) = self.0 {
-            slice.len()
-        } else {
-            0
-        }
+    pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
+        TokenStream(Lrc::new(streams))
     }
 
-    pub fn empty() -> TokenStream {
-        TokenStream(None)
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
     }
 
-    pub fn is_empty(&self) -> bool {
-        match self.0 {
-            None => true,
-            Some(ref stream) => stream.is_empty(),
-        }
+    pub fn len(&self) -> usize {
+        self.0.len()
     }
 
     pub(crate) fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream {
         match streams.len() {
-            0 => TokenStream::empty(),
+            0 => TokenStream::default(),
             1 => streams.pop().unwrap(),
             _ => {
                 // We are going to extend the first stream in `streams` with
@@ -269,41 +255,24 @@ impl TokenStream {
                 // Get the first stream. If it's `None`, create an empty
                 // stream.
                 let mut iter = streams.drain();
-                let mut first_stream_lrc = match iter.next().unwrap().0 {
-                    Some(first_stream_lrc) => first_stream_lrc,
-                    None => Lrc::new(vec![]),
-                };
+                let mut first_stream_lrc = iter.next().unwrap().0;
 
                 // Append the elements to the first stream, after reserving
                 // space for them.
                 let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc);
                 first_vec_mut.reserve(num_appends);
                 for stream in iter {
-                    if let Some(stream) = stream.0 {
-                        first_vec_mut.extend(stream.iter().cloned());
-                    }
+                    first_vec_mut.extend(stream.0.iter().cloned());
                 }
 
                 // Create the final `TokenStream`.
-                match first_vec_mut.len() {
-                    0 => TokenStream(None),
-                    _ => TokenStream(Some(first_stream_lrc)),
-                }
+                TokenStream(first_stream_lrc)
             }
         }
     }
 
-    pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
-        match streams.len() {
-            0 => TokenStream(None),
-            _ => TokenStream(Some(Lrc::new(streams))),
-        }
-    }
-
     pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
-        if let Some(stream) = self.0 {
-            vec.extend(stream.iter().cloned());
-        }
+        vec.extend(self.0.iter().cloned());
     }
 
     pub fn trees(&self) -> Cursor {
@@ -370,24 +339,22 @@ impl TokenStream {
     }
 
     pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        TokenStream(self.0.map(|stream| {
-            Lrc::new(
-                stream
-                    .iter()
-                    .enumerate()
-                    .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
-                    .collect())
-        }))
+        TokenStream(Lrc::new(
+            self.0
+                .iter()
+                .enumerate()
+                .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
+                .collect()
+        ))
     }
 
     pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        TokenStream(self.0.map(|stream| {
-            Lrc::new(
-                stream
-                    .iter()
-                    .map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
-                    .collect())
-        }))
+        TokenStream(Lrc::new(
+            self.0
+                .iter()
+                .map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
+                .collect()
+        ))
     }
 }
 
@@ -405,44 +372,43 @@ impl TokenStreamBuilder {
 
         // If `self` is not empty and the last tree within the last stream is a
         // token tree marked with `Joint`...
-        if let Some(TokenStream(Some(ref mut last_stream_lrc))) = self.0.last_mut() {
+        if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut() {
             if let Some((TokenTree::Token(last_token), Joint)) = last_stream_lrc.last() {
 
                 // ...and `stream` is not empty and the first tree within it is
                 // a token tree...
-                if let TokenStream(Some(ref mut stream_lrc)) = stream {
-                    if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() {
-
-                        // ...and the two tokens can be glued together...
-                        if let Some(glued_tok) = last_token.glue(&token) {
-
-                            // ...then do so, by overwriting the last token
-                            // tree in `self` and removing the first token tree
-                            // from `stream`. This requires using `make_mut()`
-                            // on the last stream in `self` and on `stream`,
-                            // and in practice this doesn't cause cloning 99.9%
-                            // of the time.
-
-                            // Overwrite the last token tree with the merged
-                            // token.
-                            let last_vec_mut = Lrc::make_mut(last_stream_lrc);
-                            *last_vec_mut.last_mut().unwrap() =
-                                (TokenTree::Token(glued_tok), *is_joint);
-
-                            // Remove the first token tree from `stream`. (This
-                            // is almost always the only tree in `stream`.)
-                            let stream_vec_mut = Lrc::make_mut(stream_lrc);
-                            stream_vec_mut.remove(0);
-
-                            // Don't push `stream` if it's empty -- that could
-                            // block subsequent token gluing, by getting
-                            // between two token trees that should be glued
-                            // together.
-                            if !stream.is_empty() {
-                                self.0.push(stream);
-                            }
-                            return;
+                let TokenStream(ref mut stream_lrc) = stream;
+                if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() {
+
+                    // ...and the two tokens can be glued together...
+                    if let Some(glued_tok) = last_token.glue(&token) {
+
+                        // ...then do so, by overwriting the last token
+                        // tree in `self` and removing the first token tree
+                        // from `stream`. This requires using `make_mut()`
+                        // on the last stream in `self` and on `stream`,
+                        // and in practice this doesn't cause cloning 99.9%
+                        // of the time.
+
+                        // Overwrite the last token tree with the merged
+                        // token.
+                        let last_vec_mut = Lrc::make_mut(last_stream_lrc);
+                        *last_vec_mut.last_mut().unwrap() =
+                            (TokenTree::Token(glued_tok), *is_joint);
+
+                        // Remove the first token tree from `stream`. (This
+                        // is almost always the only tree in `stream`.)
+                        let stream_vec_mut = Lrc::make_mut(stream_lrc);
+                        stream_vec_mut.remove(0);
+
+                        // Don't push `stream` if it's empty -- that could
+                        // block subsequent token gluing, by getting
+                        // between two token trees that should be glued
+                        // together.
+                        if !stream.is_empty() {
+                            self.0.push(stream);
                         }
+                        return;
                     }
                 }
             }
@@ -475,16 +441,11 @@ impl Cursor {
     }
 
     pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
-        match self.stream.0 {
-            None => None,
-            Some(ref stream) => {
-                if self.index < stream.len() {
-                    self.index += 1;
-                    Some(stream[self.index - 1].clone())
-                } else {
-                    None
-                }
-            }
+        if self.index < self.stream.len() {
+            self.index += 1;
+            Some(self.stream.0[self.index - 1].clone())
+        } else {
+            None
         }
     }
 
@@ -493,16 +454,13 @@ impl Cursor {
             return;
         }
         let index = self.index;
-        let stream = mem::replace(&mut self.stream, TokenStream(None));
+        let stream = mem::take(&mut self.stream);
         *self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees();
         self.index = index;
     }
 
     pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
-        match self.stream.0 {
-            None => None,
-            Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
-        }
+        self.stream.0[self.index ..].get(n).map(|(tree, _)| tree.clone())
     }
 }
 
diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs
index 315babceae3..62c7e188eba 100644
--- a/src/libsyntax_ext/plugin_macro_defs.rs
+++ b/src/libsyntax_ext/plugin_macro_defs.rs
@@ -20,7 +20,7 @@ fn plugin_macro_def(name: Name, span: Span) -> P<Item> {
         attr::mk_word_item(Ident::new(sym::rustc_builtin_macro, span)));
 
     let parens: TreeAndJoint = TokenTree::Delimited(
-        DelimSpan::from_single(span), token::Paren, TokenStream::empty()
+        DelimSpan::from_single(span), token::Paren, TokenStream::default()
     ).into();
     let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens];
 
diff --git a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs
new file mode 100644
index 00000000000..901fb5dd054
--- /dev/null
+++ b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs
@@ -0,0 +1,9 @@
+#![feature(const_generics)]
+
+pub struct Struct<const N: usize>(pub [u8; N]);
+
+pub type Alias = Struct<2>;
+
+pub fn function(value: Struct<3>) -> u8 {
+    value.0[0]
+}
diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs
new file mode 100644
index 00000000000..d863d097d5c
--- /dev/null
+++ b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs
@@ -0,0 +1,10 @@
+// aux-build:const_generic_lib.rs
+
+extern crate const_generic_lib;
+
+fn main() {
+    let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
+    //~^ ERROR mismatched types
+    let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr
new file mode 100644
index 00000000000..b7fd29ce706
--- /dev/null
+++ b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/const-argument-cross-crate-mismatch.rs:6:41
+   |
+LL |     let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `3usize`, found `2usize`
+   |
+   = note: expected type `const_generic_lib::Struct<3usize>`
+              found type `const_generic_lib::Struct<_: usize>`
+
+error[E0308]: mismatched types
+  --> $DIR/const-argument-cross-crate-mismatch.rs:8:39
+   |
+LL |     let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2usize`, found `3usize`
+   |
+   = note: expected type `const_generic_lib::Struct<2usize>`
+              found type `const_generic_lib::Struct<_: usize>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/const-argument-cross-crate.rs b/src/test/ui/const-generics/const-argument-cross-crate.rs
new file mode 100644
index 00000000000..98cf39a7ee1
--- /dev/null
+++ b/src/test/ui/const-generics/const-argument-cross-crate.rs
@@ -0,0 +1,12 @@
+// run-pass
+// aux-build:const_generic_lib.rs
+
+extern crate const_generic_lib;
+
+struct Container(const_generic_lib::Alias);
+
+fn main() {
+    let res = const_generic_lib::function(const_generic_lib::Struct([14u8, 1u8, 2u8]));
+    assert_eq!(res, 14u8);
+    let _ = Container(const_generic_lib::Struct([0u8, 1u8]));
+}
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr
index fddb06981bc..32cf8d8a01a 100644
--- a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr
+++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr
@@ -10,7 +10,7 @@ error: const parameter `x` should have an upper case name
   --> $DIR/const-parameter-uppercase-lint.rs:6:15
    |
 LL | fn noop<const x: u32>() {
-   |               ^ help: convert the identifier to upper case: `X`
+   |               ^ help: convert the identifier to upper case (notice the capitalization): `X`
    |
 note: lint level defined here
   --> $DIR/const-parameter-uppercase-lint.rs:4:9
diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
index d8826d4072a..ef68bf52cf3 100644
--- a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
+++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
@@ -55,7 +55,7 @@ LL |     let z = ManyVariants::Three();
    |             ^^^^^^^^^^^^^^^^^^^
 LL |     let z = ManyVariants::Four();
    |             ^^^^^^^^^^^^^^^^^^
-and 6 other candidates
+     and 6 other candidates
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
index 8d3a86df023..cb350a1faee 100644
--- a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
+++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr
@@ -13,7 +13,7 @@ LL | fn setup() -> Determine { Set }
    |               ^^^^^^^^^
 LL | fn setup() -> PutDown { Set }
    |               ^^^^^^^
-and 3 other candidates
+     and 3 other candidates
 
 error[E0425]: cannot find value `Set` in this scope
   --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21
@@ -30,7 +30,7 @@ LL | use Determine::Set;
    |
 LL | use PutDown::Set;
    |
-and 3 other candidates
+     and 3 other candidates
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index ce631ca4bf7..754006bc217 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -34,7 +34,7 @@ LL |     let f = Foo();
    |             ^^^
    |             |
    |             did you mean `Foo { /* fields */ }`?
-   |             help: a function with a similar name exists: `foo`
+   |             help: a function with a similar name exists (notice the capitalization): `foo`
 
 error[E0423]: expected value, found struct `T`
   --> $DIR/E0423.rs:14:8
diff --git a/src/test/ui/expr_attr_paren_order.stderr b/src/test/ui/expr_attr_paren_order.stderr
index 89f615f53dd..57a9350c089 100644
--- a/src/test/ui/expr_attr_paren_order.stderr
+++ b/src/test/ui/expr_attr_paren_order.stderr
@@ -2,7 +2,7 @@ error: variable `X` should have a snake case name
   --> $DIR/expr_attr_paren_order.rs:19:17
    |
 LL |             let X = 0;
-   |                 ^ help: convert the identifier to snake case: `x`
+   |                 ^ help: convert the identifier to snake case (notice the capitalization): `x`
    |
 note: lint level defined here
   --> $DIR/expr_attr_paren_order.rs:17:17
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr
deleted file mode 100644
index d77fbc1e823..00000000000
--- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0005]: refutable pattern in local binding: `Err(_)` not covered
-  --> $DIR/feature-gate-exhaustive-patterns.rs:7:9
-   |
-LL |     let Ok(_x) = foo();
-   |         ^^^^^^ pattern `Err(_)` not covered
-   |
-   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
-   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     if let Ok(_x) = foo() { /* */ }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0005`.
diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr
index 7e0f4e4e0b8..7acb266f49c 100644
--- a/src/test/ui/hygiene/globs.stderr
+++ b/src/test/ui/hygiene/globs.stderr
@@ -34,7 +34,7 @@ LL | use foo::test2::test::g;
    |
 LL | use foo::test::g;
    |
-and 2 other candidates
+     and 2 other candidates
 
 error[E0425]: cannot find function `f` in this scope
   --> $DIR/globs.rs:61:12
diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr
index 5eacfdf8dee..45a2efebbb8 100644
--- a/src/test/ui/hygiene/rustc-macro-transparency.stderr
+++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr
@@ -2,7 +2,7 @@ error[E0425]: cannot find value `Opaque` in this scope
   --> $DIR/rustc-macro-transparency.rs:26:5
    |
 LL |     Opaque;
-   |     ^^^^^^ help: a local variable with a similar name exists: `opaque`
+   |     ^^^^^^ help: a local variable with a similar name exists (notice the capitalization): `opaque`
 
 error[E0423]: expected value, found macro `semitransparent`
   --> $DIR/rustc-macro-transparency.rs:29:5
diff --git a/src/test/ui/issues/issue-10200.stderr b/src/test/ui/issues/issue-10200.stderr
index 544716e89b3..b1057d45869 100644
--- a/src/test/ui/issues/issue-10200.stderr
+++ b/src/test/ui/issues/issue-10200.stderr
@@ -2,7 +2,7 @@ error[E0532]: expected tuple struct/variant, found function `foo`
   --> $DIR/issue-10200.rs:6:9
    |
 LL |         foo(x)
-   |         ^^^ help: a tuple struct with a similar name exists: `Foo`
+   |         ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index e27f49b4a3f..1f71e159f18 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -27,7 +27,7 @@ LL |     use std::prelude::v1::Result;
    |
 LL |     use std::result::Result;
    |
-and 1 other candidates
+     and 1 other candidates
 
 error[E0573]: expected type, found variant `Result`
   --> $DIR/issue-17546.rs:28:13
@@ -44,7 +44,7 @@ LL | use std::prelude::v1::Result;
    |
 LL | use std::result::Result;
    |
-and 1 other candidates
+     and 1 other candidates
 
 error[E0573]: expected type, found variant `NoResult`
   --> $DIR/issue-17546.rs:33:15
diff --git a/src/test/ui/issues/issue-17718-const-naming.stderr b/src/test/ui/issues/issue-17718-const-naming.stderr
index 1fe1821292c..e320c436f5b 100644
--- a/src/test/ui/issues/issue-17718-const-naming.stderr
+++ b/src/test/ui/issues/issue-17718-const-naming.stderr
@@ -15,7 +15,7 @@ error: constant `foo` should have an upper case name
   --> $DIR/issue-17718-const-naming.rs:4:7
    |
 LL | const foo: isize = 3;
-   |       ^^^ help: convert the identifier to upper case: `FOO`
+   |       ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO`
    |
 note: lint level defined here
   --> $DIR/issue-17718-const-naming.rs:2:9
diff --git a/src/test/ui/issues/issue-46332.stderr b/src/test/ui/issues/issue-46332.stderr
index 812a50000d1..c7e9d71700e 100644
--- a/src/test/ui/issues/issue-46332.stderr
+++ b/src/test/ui/issues/issue-46332.stderr
@@ -2,7 +2,7 @@ error[E0422]: cannot find struct, variant or union type `TyUInt` in this scope
   --> $DIR/issue-46332.rs:9:5
    |
 LL |     TyUInt {};
-   |     ^^^^^^ help: a struct with a similar name exists: `TyUint`
+   |     ^^^^^^ help: a struct with a similar name exists (notice the capitalization): `TyUint`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr
index 432a16debc6..177f8c8fe9b 100644
--- a/src/test/ui/lint/lint-non-camel-case-types.stderr
+++ b/src/test/ui/lint/lint-non-camel-case-types.stderr
@@ -14,25 +14,25 @@ error: type `foo` should have an upper camel case name
   --> $DIR/lint-non-camel-case-types.rs:7:8
    |
 LL | struct foo {
-   |        ^^^ help: convert the identifier to upper camel case: `Foo`
+   |        ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo`
 
 error: type `foo2` should have an upper camel case name
   --> $DIR/lint-non-camel-case-types.rs:11:6
    |
 LL | enum foo2 {
-   |      ^^^^ help: convert the identifier to upper camel case: `Foo2`
+   |      ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo2`
 
 error: type `foo3` should have an upper camel case name
   --> $DIR/lint-non-camel-case-types.rs:15:8
    |
 LL | struct foo3 {
-   |        ^^^^ help: convert the identifier to upper camel case: `Foo3`
+   |        ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo3`
 
 error: type `foo4` should have an upper camel case name
   --> $DIR/lint-non-camel-case-types.rs:19:6
    |
 LL | type foo4 = isize;
-   |      ^^^^ help: convert the identifier to upper camel case: `Foo4`
+   |      ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo4`
 
 error: variant `bar` should have an upper camel case name
   --> $DIR/lint-non-camel-case-types.rs:22:5
@@ -44,7 +44,7 @@ error: trait `foo6` should have an upper camel case name
   --> $DIR/lint-non-camel-case-types.rs:25:7
    |
 LL | trait foo6 {
-   |       ^^^^ help: convert the identifier to upper camel case: `Foo6`
+   |       ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo6`
 
 error: type parameter `ty` should have an upper camel case name
   --> $DIR/lint-non-camel-case-types.rs:29:6
diff --git a/src/test/ui/lint/lint-non-snake-case-functions.stderr b/src/test/ui/lint/lint-non-snake-case-functions.stderr
index 49cbfa94126..c5eca89debb 100644
--- a/src/test/ui/lint/lint-non-snake-case-functions.stderr
+++ b/src/test/ui/lint/lint-non-snake-case-functions.stderr
@@ -38,7 +38,7 @@ error: trait method `a_b_C` should have a snake case name
   --> $DIR/lint-non-snake-case-functions.rs:25:8
    |
 LL |     fn a_b_C(&self) {}
-   |        ^^^^^ help: convert the identifier to snake case: `a_b_c`
+   |        ^^^^^ help: convert the identifier to snake case (notice the capitalization): `a_b_c`
 
 error: trait method `something__else` should have a snake case name
   --> $DIR/lint-non-snake-case-functions.rs:28:8
@@ -50,13 +50,13 @@ error: function `Cookie` should have a snake case name
   --> $DIR/lint-non-snake-case-functions.rs:38:4
    |
 LL | fn Cookie() {}
-   |    ^^^^^^ help: convert the identifier to snake case: `cookie`
+   |    ^^^^^^ help: convert the identifier to snake case (notice the capitalization): `cookie`
 
 error: function `bi_S_Cuit` should have a snake case name
   --> $DIR/lint-non-snake-case-functions.rs:41:8
    |
 LL | pub fn bi_S_Cuit() {}
-   |        ^^^^^^^^^ help: convert the identifier to snake case: `bi_s_cuit`
+   |        ^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `bi_s_cuit`
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/lint/lint-non-uppercase-statics.stderr b/src/test/ui/lint/lint-non-uppercase-statics.stderr
index 8b477276efc..ceb83d08f27 100644
--- a/src/test/ui/lint/lint-non-uppercase-statics.stderr
+++ b/src/test/ui/lint/lint-non-uppercase-statics.stderr
@@ -2,7 +2,7 @@ error: static variable `foo` should have an upper case name
   --> $DIR/lint-non-uppercase-statics.rs:4:8
    |
 LL | static foo: isize = 1;
-   |        ^^^ help: convert the identifier to upper case: `FOO`
+   |        ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO`
    |
 note: lint level defined here
   --> $DIR/lint-non-uppercase-statics.rs:1:11
diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr
index 9ea3795f89e..f614d5d71f8 100644
--- a/src/test/ui/lint/lint-uppercase-variables.stderr
+++ b/src/test/ui/lint/lint-uppercase-variables.stderr
@@ -21,7 +21,7 @@ error: structure field `X` should have a snake case name
   --> $DIR/lint-uppercase-variables.rs:10:5
    |
 LL |     X: usize
-   |     ^ help: convert the identifier to snake case: `x`
+   |     ^ help: convert the identifier to snake case (notice the capitalization): `x`
    |
 note: lint level defined here
   --> $DIR/lint-uppercase-variables.rs:3:9
@@ -33,7 +33,7 @@ error: variable `Xx` should have a snake case name
   --> $DIR/lint-uppercase-variables.rs:13:9
    |
 LL | fn test(Xx: usize) {
-   |         ^^ help: convert the identifier to snake case: `xx`
+   |         ^^ help: convert the identifier to snake case (notice the capitalization): `xx`
 
 error: variable `Test` should have a snake case name
   --> $DIR/lint-uppercase-variables.rs:18:9
@@ -45,7 +45,7 @@ error: variable `Foo` should have a snake case name
   --> $DIR/lint-uppercase-variables.rs:22:9
    |
 LL |         Foo => {}
-   |         ^^^ help: convert the identifier to snake case: `foo`
+   |         ^^^ help: convert the identifier to snake case (notice the capitalization): `foo`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr
index 70d49a4e69c..5016d9b97d6 100644
--- a/src/test/ui/lint/not_found.stderr
+++ b/src/test/ui/lint/not_found.stderr
@@ -16,5 +16,5 @@ warning: unknown lint: `Warnings`
   --> $DIR/not_found.rs:10:8
    |
 LL | #[deny(Warnings)]
-   |        ^^^^^^^^ help: did you mean: `warnings`
+   |        ^^^^^^^^ help: did you mean (notice the capitalization): `warnings`
 
diff --git a/src/test/ui/lint/reasons.stderr b/src/test/ui/lint/reasons.stderr
index cb5f4ddf47b..139b3f13fd6 100644
--- a/src/test/ui/lint/reasons.stderr
+++ b/src/test/ui/lint/reasons.stderr
@@ -15,7 +15,7 @@ warning: variable `Social_exchange_psychology` should have a snake case name
   --> $DIR/reasons.rs:30:9
    |
 LL |     let Social_exchange_psychology = CheaterDetectionMechanism {};
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `social_exchange_psychology`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `social_exchange_psychology`
    |
    = note: people shouldn't have to change their usual style habits
            to contribute to our project
diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr
index 678c88849b5..1da5acc9661 100644
--- a/src/test/ui/lint/use_suggestion_json.stderr
+++ b/src/test/ui/lint/use_suggestion_json.stderr
@@ -395,7 +395,7 @@ mod foo {
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
 \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::hash_map::Iter;\u001b[0m
 \u001b[0m   \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m
-\u001b[0mand 8 other candidates\u001b[0m
+\u001b[0m     and 8 other candidates\u001b[0m
 
 "
 }
diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns.rs
new file mode 100644
index 00000000000..adb607cf6b9
--- /dev/null
+++ b/src/test/ui/parser/intersection-patterns.rs
@@ -0,0 +1,40 @@
+// This tests the parser recovery in `recover_intersection_pat`
+// and serves as a regression test for the diagnostics issue #65400.
+//
+// The general idea is that for `$pat_lhs @ $pat_rhs` where
+// `$pat_lhs` is not generated by `ref? mut? $ident` we want
+// to suggest either switching the order or note that intersection
+// patterns are not allowed.
+
+fn main() {
+    let s: Option<u8> = None;
+
+    match s {
+        Some(x) @ y => {}
+        //~^ ERROR pattern on wrong side of `@`
+        //~| pattern on the left, should be on the right
+        //~| binding on the right, should be on the left
+        //~| HELP switch the order
+        //~| SUGGESTION y @ Some(x)
+        _ => {}
+    }
+
+    match s {
+        Some(x) @ Some(y) => {}
+        //~^ ERROR left-hand side of `@` must be a binding
+        //~| interpreted as a pattern, not a binding
+        //~| also a pattern
+        //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+        _ => {}
+    }
+
+    match 2 {
+        1 ..= 5 @ e => {}
+        //~^ ERROR pattern on wrong side of `@`
+        //~| pattern on the left, should be on the right
+        //~| binding on the right, should be on the left
+        //~| HELP switch the order
+        //~| SUGGESTION e @ 1 ..=5
+        _ => {}
+    }
+}
diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns.stderr
new file mode 100644
index 00000000000..f5bfee5bbd6
--- /dev/null
+++ b/src/test/ui/parser/intersection-patterns.stderr
@@ -0,0 +1,33 @@
+error: pattern on wrong side of `@`
+  --> $DIR/intersection-patterns.rs:13:9
+   |
+LL |         Some(x) @ y => {}
+   |         -------^^^-
+   |         |         |
+   |         |         binding on the right, should be on the left
+   |         pattern on the left, should be on the right
+   |         help: switch the order: `y @ Some(x)`
+
+error: left-hand side of `@` must be a binding
+  --> $DIR/intersection-patterns.rs:23:9
+   |
+LL |         Some(x) @ Some(y) => {}
+   |         -------^^^-------
+   |         |         |
+   |         |         also a pattern
+   |         interpreted as a pattern, not a binding
+   |
+   = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+error: pattern on wrong side of `@`
+  --> $DIR/intersection-patterns.rs:32:9
+   |
+LL |         1 ..= 5 @ e => {}
+   |         -------^^^-
+   |         |         |
+   |         |         binding on the right, should be on the left
+   |         pattern on the left, should be on the right
+   |         help: switch the order: `e @ 1 ..=5`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr
index d00d87393aa..513e02f74e3 100644
--- a/src/test/ui/resolve/issue-21221-1.stderr
+++ b/src/test/ui/resolve/issue-21221-1.stderr
@@ -27,7 +27,7 @@ LL | use mul3::Mul;
    |
 LL | use mul4::Mul;
    |
-and 2 other candidates
+     and 2 other candidates
 
 error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope
   --> $DIR/issue-21221-1.rs:63:6
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
index 2e3c0f5448e..e693a0ef91f 100644
--- a/src/test/ui/resolve/levenshtein.stderr
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -38,13 +38,13 @@ error[E0412]: cannot find type `first` in module `m`
   --> $DIR/levenshtein.rs:28:15
    |
 LL |     let b: m::first = m::second; // Misspelled item in module.
-   |               ^^^^^ help: a struct with a similar name exists: `First`
+   |               ^^^^^ help: a struct with a similar name exists (notice the capitalization): `First`
 
 error[E0425]: cannot find value `second` in module `m`
   --> $DIR/levenshtein.rs:28:26
    |
 LL |     let b: m::first = m::second; // Misspelled item in module.
-   |                          ^^^^^^ help: a unit struct with a similar name exists: `Second`
+   |                          ^^^^^^ help: a unit struct with a similar name exists (notice the capitalization): `Second`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
index 030fa56dcff..973c486970e 100644
--- a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
+++ b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr
@@ -13,7 +13,7 @@ LL | use std::collections::hash_map::Drain;
    |
 LL | use std::collections::hash_set::Drain;
    |
-and 3 other candidates
+     and 3 other candidates
 
 error: aborting due to previous error