about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-03-21 21:57:38 +0000
committerbors <bors@rust-lang.org>2020-03-21 21:57:38 +0000
commitc6b172f7885cb83842fa15e4b0e2ff1647aebb40 (patch)
treec9c762cf63210999b8cdc8630b98efa02bc8a6ee
parent38114ff16e7856f98b2b4be7ab4cd29b38bed59a (diff)
parent17e6ed1fd97980146f63fb65e83da8702f294d31 (diff)
downloadrust-c6b172f7885cb83842fa15e4b0e2ff1647aebb40.tar.gz
rust-c6b172f7885cb83842fa15e4b0e2ff1647aebb40.zip
Auto merge of #70246 - Dylan-DPC:rollup-vt9wex2, r=Dylan-DPC
Rollup of 10 pull requests

Successful merges:

 - #70003 (symbol_names: treat ReifyShim like VtableShim.)
 - #70051 (Allow `hir().find` to return `None`)
 - #70126 (Fix ICE caused by truncating a negative ZST enum discriminant)
 - #70197 (For issue 53957: revise unit test to focus on underlying bug of 23076.)
 - #70215 (ast: Compress `AttrId` from `usize` to `u32`)
 - #70218 (Fix deprecated Error.description() usage in docs)
 - #70228 (Remove CARGO_BUILD_TARGET from bootstrap.py)
 - #70231 (Add explanation message for E0224)
 - #70232 (Tweak wording for std::io::Read::read function)
 - #70238 (Add a test for out-of-line module passed through a proc macro)

Failed merges:

r? @ghost
-rw-r--r--src/bootstrap/bootstrap.py4
-rw-r--r--src/librustc/hir/map/mod.rs32
-rw-r--r--src/librustc/hir/mod.rs7
-rw-r--r--src/librustc/query/mod.rs4
-rw-r--r--src/librustc/ty/instance.rs4
-rw-r--r--src/librustc_ast/ast.rs22
-rw-r--r--src/librustc_ast/attr/mod.rs8
-rw-r--r--src/librustc_codegen_ssa/mir/rvalue.rs7
-rw-r--r--src/librustc_error_codes/error_codes.rs2
-rw-r--r--src/librustc_error_codes/error_codes/E0224.md15
-rw-r--r--src/librustc_mir/interpret/cast.rs10
-rw-r--r--src/librustc_symbol_mangling/legacy.rs9
-rw-r--r--src/librustc_symbol_mangling/v0.rs13
-rw-r--r--src/libstd/error.rs2
-rw-r--r--src/libstd/io/mod.rs2
-rw-r--r--src/libstd/net/addr.rs23
-rw-r--r--src/test/ui/consts/cast-discriminant-zst-enum.rs47
-rw-r--r--src/test/ui/issues/issue-70041.rs13
-rw-r--r--src/test/ui/issues/issue-70041.stderr19
-rw-r--r--src/test/ui/parser/issue-68890-2.stderr1
-rw-r--r--src/test/ui/parser/macro/trait-object-macro-matcher.stderr1
-rw-r--r--src/test/ui/proc-macro/out-of-line-mod.rs13
-rw-r--r--src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr1
-rw-r--r--src/test/ui/traits/trait-object-macro-matcher.stderr3
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime-2.stderr1
-rw-r--r--src/test/ui/traits/trait-object-vs-lifetime.stderr2
-rw-r--r--src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr1
27 files changed, 208 insertions, 58 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 50e1726240f..d5efed61b54 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -664,6 +664,10 @@ class RustBuild(object):
         if self.clean and os.path.exists(build_dir):
             shutil.rmtree(build_dir)
         env = os.environ.copy()
+        # `CARGO_BUILD_TARGET` breaks bootstrap build.
+        # See also: <https://github.com/rust-lang/rust/issues/70208>.
+        if "CARGO_BUILD_TARGET" in env:
+            del env["CARGO_BUILD_TARGET"]
         env["RUSTC_BOOTSTRAP"] = '1'
         env["CARGO_TARGET_DIR"] = build_dir
         env["RUSTC"] = self.rustc()
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 13257e7bf47..49b7ce3445b 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -337,23 +337,28 @@ impl<'hir> Map<'hir> {
     }
 
     fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
-        Some(self.get_entry(id))
-    }
-
-    fn get_entry(&self, id: HirId) -> Entry<'hir> {
         if id.local_id == ItemLocalId::from_u32(0) {
             let owner = self.tcx.hir_owner(id.owner);
-            Entry { parent: owner.parent, node: owner.node }
+            owner.map(|owner| Entry { parent: owner.parent, node: owner.node })
         } else {
             let owner = self.tcx.hir_owner_nodes(id.owner);
-            let node = owner.nodes[id.local_id].as_ref().unwrap();
-            // FIXME(eddyb) use a single generic type insted of having both
-            // `Entry` and `ParentedNode`, which are effectively the same.
-            // Alternatively, rewrite code using `Entry` to use `ParentedNode`.
-            Entry { parent: HirId { owner: id.owner, local_id: node.parent }, node: node.node }
+            owner.and_then(|owner| {
+                let node = owner.nodes[id.local_id].as_ref();
+                // FIXME(eddyb) use a single generic type insted of having both
+                // `Entry` and `ParentedNode`, which are effectively the same.
+                // Alternatively, rewrite code using `Entry` to use `ParentedNode`.
+                node.map(|node| Entry {
+                    parent: HirId { owner: id.owner, local_id: node.parent },
+                    node: node.node,
+                })
+            })
         }
     }
 
+    fn get_entry(&self, id: HirId) -> Entry<'hir> {
+        self.find_entry(id).unwrap()
+    }
+
     pub fn item(&self, id: HirId) -> &'hir Item<'hir> {
         match self.find(id).unwrap() {
             Node::Item(item) => item,
@@ -376,7 +381,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
-        self.tcx.hir_owner_nodes(id.hir_id.owner).bodies.get(&id.hir_id.local_id).unwrap()
+        self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies.get(&id.hir_id.local_id).unwrap()
     }
 
     pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
@@ -536,8 +541,9 @@ impl<'hir> Map<'hir> {
 
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
-        let node = self.get_entry(hir_id).node;
-        if let Node::Crate(..) = node { None } else { Some(node) }
+        self.find_entry(hir_id).and_then(|entry| {
+            if let Node::Crate(..) = entry.node { None } else { Some(entry.node) }
+        })
     }
 
     /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index d9dfd2961ff..ce8e1f48daa 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -78,9 +78,8 @@ pub fn provide(providers: &mut Providers<'_>) {
         let module = hir.as_local_hir_id(id.to_def_id()).unwrap();
         &tcx.untracked_crate.modules[&module]
     };
-    providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature.unwrap();
-    providers.hir_owner_nodes = |tcx, id| {
-        tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_ref().map(|nodes| &**nodes).unwrap()
-    };
+    providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
+    providers.hir_owner_nodes =
+        |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_ref().map(|nodes| &**nodes);
     map::provide(providers);
 }
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index 00e40faa95c..54f5103f736 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -76,7 +76,7 @@ rustc_queries! {
         //
         // This can be conveniently accessed by methods on `tcx.hir()`.
         // Avoid calling this query directly.
-        query hir_owner(key: LocalDefId) -> &'tcx crate::hir::Owner<'tcx> {
+        query hir_owner(key: LocalDefId) -> Option<&'tcx crate::hir::Owner<'tcx>> {
             eval_always
             desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
         }
@@ -85,7 +85,7 @@ rustc_queries! {
         //
         // This can be conveniently accessed by methods on `tcx.hir()`.
         // Avoid calling this query directly.
-        query hir_owner_nodes(key: LocalDefId) -> &'tcx crate::hir::OwnerNodes<'tcx> {
+        query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx crate::hir::OwnerNodes<'tcx>> {
             eval_always
             desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
         }
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 13d58ea73ac..46372701a92 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -406,10 +406,6 @@ impl<'tcx> Instance<'tcx> {
             | InstanceDef::VtableShim(..) => Some(self.substs),
         }
     }
-
-    pub fn is_vtable_shim(&self) -> bool {
-        if let InstanceDef::VtableShim(..) = self.def { true } else { false }
-    }
 }
 
 fn needs_fn_once_adapter_shim(
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index e3077b9897c..b7b50617eaa 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -31,7 +31,6 @@ use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::thin_vec::ThinVec;
-use rustc_index::vec::Idx;
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::{self, Decoder, Encoder};
 use rustc_span::source_map::{respan, Spanned};
@@ -2251,27 +2250,22 @@ pub enum AttrStyle {
     Inner,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, Copy)]
-pub struct AttrId(pub usize);
-
-impl Idx for AttrId {
-    fn new(idx: usize) -> Self {
-        AttrId(idx)
-    }
-    fn index(self) -> usize {
-        self.0
+rustc_index::newtype_index! {
+    pub struct AttrId {
+        ENCODABLE = custom
+        DEBUG_FORMAT = "AttrId({})"
     }
 }
 
 impl rustc_serialize::Encodable for AttrId {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_unit()
+    fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
+        Ok(())
     }
 }
 
 impl rustc_serialize::Decodable for AttrId {
-    fn decode<D: Decoder>(d: &mut D) -> Result<AttrId, D::Error> {
-        d.read_nil().map(|_| crate::attr::mk_attr_id())
+    fn decode<D: Decoder>(_: &mut D) -> Result<AttrId, D::Error> {
+        Ok(crate::attr::mk_attr_id())
     }
 }
 
diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs
index 249311851fb..d53d7767785 100644
--- a/src/librustc_ast/attr/mod.rs
+++ b/src/librustc_ast/attr/mod.rs
@@ -366,14 +366,14 @@ pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem {
 }
 
 crate fn mk_attr_id() -> AttrId {
-    use std::sync::atomic::AtomicUsize;
+    use std::sync::atomic::AtomicU32;
     use std::sync::atomic::Ordering;
 
-    static NEXT_ATTR_ID: AtomicUsize = AtomicUsize::new(0);
+    static NEXT_ATTR_ID: AtomicU32 = AtomicU32::new(0);
 
     let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst);
-    assert!(id != ::std::usize::MAX);
-    AttrId(id)
+    assert!(id != u32::MAX);
+    AttrId::from_u32(id)
 }
 
 pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index 6d004606398..245df0846b5 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -293,7 +293,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 if let Some(discr) =
                                     operand.layout.ty.discriminant_for_variant(bx.tcx(), index)
                                 {
-                                    let discr_val = bx.cx().const_uint_big(ll_t_out, discr.val);
+                                    let discr_layout = bx.cx().layout_of(discr.ty);
+                                    let discr_t = bx.cx().immediate_backend_type(discr_layout);
+                                    let discr_val = bx.cx().const_uint_big(discr_t, discr.val);
+                                    let discr_val =
+                                        bx.intcast(discr_val, ll_t_out, discr.ty.is_signed());
+
                                     return (
                                         bx,
                                         OperandRef {
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 85339ab9aa1..33bfaddc39c 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -118,6 +118,7 @@ E0220: include_str!("./error_codes/E0220.md"),
 E0221: include_str!("./error_codes/E0221.md"),
 E0222: include_str!("./error_codes/E0222.md"),
 E0223: include_str!("./error_codes/E0223.md"),
+E0224: include_str!("./error_codes/E0224.md"),
 E0225: include_str!("./error_codes/E0225.md"),
 E0229: include_str!("./error_codes/E0229.md"),
 E0230: include_str!("./error_codes/E0230.md"),
@@ -469,7 +470,6 @@ E0748: include_str!("./error_codes/E0748.md"),
 //  E0217, // ambiguous associated type, defined in multiple supertraits
 //  E0218, // no associated type defined
 //  E0219, // associated type defined in higher-ranked supertrait
-    E0224, // at least one non-builtin train is required for an object type
     E0226, // only a single explicit lifetime bound is permitted
     E0227, // ambiguous lifetime bound, explicit lifetime bound required
     E0228, // explicit lifetime bound required
diff --git a/src/librustc_error_codes/error_codes/E0224.md b/src/librustc_error_codes/error_codes/E0224.md
new file mode 100644
index 00000000000..fd89c1d5256
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0224.md
@@ -0,0 +1,15 @@
+A trait object was declaired with no traits.
+
+Erroneous code example:
+
+```compile_fail,E0224
+type Foo = dyn 'static +;
+```
+
+Rust does not currently support this.
+
+To solve ensure the the trait object has at least one trait:
+
+```
+type Foo = dyn 'static + Copy;
+```
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 3cbb0667ff3..5c70b28a567 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -3,6 +3,7 @@ use rustc::ty::layout::{self, Size, TyLayout};
 use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable};
 use rustc_ast::ast::FloatTy;
 use rustc_span::symbol::sym;
+use rustc_target::abi::LayoutOf;
 
 use rustc::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
 use rustc::mir::CastKind;
@@ -134,7 +135,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             layout::Variants::Single { index } => {
                 if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) {
                     assert!(src.layout.is_zst());
-                    return Ok(Scalar::from_uint(discr.val, dest_layout.size).into());
+                    let discr_layout = self.layout_of(discr.ty)?;
+                    return Ok(self
+                        .cast_from_int_like(discr.val, discr_layout, dest_layout)?
+                        .into());
                 }
             }
             layout::Variants::Multiple { .. } => {}
@@ -171,10 +175,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // (b) cast from an integer-like (including bool, char, enums).
         // In both cases we want the bits.
         let bits = self.force_bits(src.to_scalar()?, src.layout.size)?;
-        Ok(self.cast_from_int(bits, src.layout, dest_layout)?.into())
+        Ok(self.cast_from_int_like(bits, src.layout, dest_layout)?.into())
     }
 
-    fn cast_from_int(
+    fn cast_from_int_like(
         &self,
         v: u128, // raw bits
         src_layout: TyLayout<'tcx>,
diff --git a/src/librustc_symbol_mangling/legacy.rs b/src/librustc_symbol_mangling/legacy.rs
index 0dedda9bb6b..7b082309f34 100644
--- a/src/librustc_symbol_mangling/legacy.rs
+++ b/src/librustc_symbol_mangling/legacy.rs
@@ -59,10 +59,14 @@ pub(super) fn mangle(
         .print_def_path(def_id, &[])
         .unwrap();
 
-    if instance.is_vtable_shim() {
+    if let ty::InstanceDef::VtableShim(..) = instance.def {
         let _ = printer.write_str("{{vtable-shim}}");
     }
 
+    if let ty::InstanceDef::ReifyShim(..) = instance.def {
+        let _ = printer.write_str("{{reify-shim}}");
+    }
+
     printer.path.finish(hash)
 }
 
@@ -123,7 +127,8 @@ fn get_symbol_hash<'tcx>(
         }
 
         // We want to avoid accidental collision between different types of instances.
-        // Especially, VtableShim may overlap with its original instance without this.
+        // Especially, `VtableShim`s and `ReifyShim`s may overlap with their original
+        // instances without this.
         discriminant(&instance.def).hash_stable(&mut hcx, &mut hasher);
     });
 
diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs
index ce6d0d9dc5b..e22a49061bb 100644
--- a/src/librustc_symbol_mangling/v0.rs
+++ b/src/librustc_symbol_mangling/v0.rs
@@ -34,8 +34,17 @@ pub(super) fn mangle(
         binders: vec![],
         out: String::from(prefix),
     };
-    cx = if instance.is_vtable_shim() {
-        cx.path_append_ns(|cx| cx.print_def_path(def_id, substs), 'S', 0, "").unwrap()
+
+    // Append `::{shim:...#0}` to shims that can coexist with a non-shim instance.
+    let shim_kind = match instance.def {
+        ty::InstanceDef::VtableShim(_) => Some("vtable"),
+        ty::InstanceDef::ReifyShim(_) => Some("reify"),
+
+        _ => None,
+    };
+
+    cx = if let Some(shim_kind) = shim_kind {
+        cx.path_append_ns(|cx| cx.print_def_path(def_id, substs), 'S', 0, shim_kind).unwrap()
     } else {
         cx.print_def_path(def_id, substs).unwrap()
     };
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 2a370f19296..b394f2efc2e 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -88,7 +88,7 @@ pub trait Error: Debug + Display {
     /// fn main() {
     ///     match get_super_error() {
     ///         Err(e) => {
-    ///             println!("Error: {}", e.description());
+    ///             println!("Error: {}", e);
     ///             println!("Caused by: {}", e.source().unwrap());
     ///         }
     ///         _ => println!("No error"),
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index dc831432c17..83c492fecf9 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -502,7 +502,7 @@ pub trait Read {
     /// how many bytes were read.
     ///
     /// This function does not provide any guarantees about whether it blocks
-    /// waiting for data, but if an object needs to block for a read but cannot
+    /// waiting for data, but if an object needs to block for a read and cannot,
     /// it will typically signal this via an [`Err`] return value.
     ///
     /// If the return value of this method is [`Ok(n)`], then it must be
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index 57cba6b1f7a..de6360cf020 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -989,11 +989,26 @@ mod tests {
         // s has been moved into the tsa call
     }
 
-    // FIXME: figure out why this fails on openbsd and fix it
     #[test]
-    #[cfg(not(any(windows, target_os = "openbsd")))]
-    fn to_socket_addr_str_bad() {
-        assert!(tsa("1200::AB00:1234::2552:7777:1313:34300").is_err());
+    fn bind_udp_socket_bad() {
+        // rust-lang/rust#53957: This is a regression test for a parsing problem
+        // discovered as part of issue rust-lang/rust#23076, where we were
+        // incorrectly parsing invalid input and then that would result in a
+        // successful `UdpSocket` binding when we would expect failure.
+        //
+        // At one time, this test was written as a call to `tsa` with
+        // INPUT_23076. However, that structure yields an unreliable test,
+        // because it ends up passing junk input to the DNS server, and some DNS
+        // servers will respond with `Ok` to such input, with the ip address of
+        // the DNS server itself.
+        //
+        // This form of the test is more robust: even when the DNS server
+        // returns its own address, it is still an error to bind a UDP socket to
+        // a non-local address, and so we still get an error here in that case.
+
+        const INPUT_23076: &'static str = "1200::AB00:1234::2552:7777:1313:34300";
+
+        assert!(crate::net::UdpSocket::bind(INPUT_23076).is_err())
     }
 
     #[test]
diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs
new file mode 100644
index 00000000000..a7725812011
--- /dev/null
+++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs
@@ -0,0 +1,47 @@
+// run-pass
+// Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32.
+
+#[derive(Copy, Clone)]
+enum Nums {
+    NegOne = -1,
+}
+
+const NEG_ONE_I8: i8 = Nums::NegOne as i8;
+const NEG_ONE_I16: i16 = Nums::NegOne as i16;
+const NEG_ONE_I32: i32 = Nums::NegOne as i32;
+const NEG_ONE_I64: i64 = Nums::NegOne as i64;
+const NEG_ONE_I128: i128 = Nums::NegOne as i128;
+
+#[inline(never)]
+fn identity<T>(t: T) -> T { t }
+
+fn test_as_arg(n: Nums) {
+    assert_eq!(-1i8, n as i8);
+    assert_eq!(-1i16, n as i16);
+    assert_eq!(-1i32, n as i32);
+    assert_eq!(-1i64, n as i64);
+    assert_eq!(-1i128, n as i128);
+}
+
+fn main() {
+    let kind = Nums::NegOne;
+    assert_eq!(-1i8, kind as i8);
+    assert_eq!(-1i16, kind as i16);
+    assert_eq!(-1i32, kind as i32);
+    assert_eq!(-1i64, kind as i64);
+    assert_eq!(-1i128, kind as i128);
+
+    assert_eq!(-1i8, identity(kind) as i8);
+    assert_eq!(-1i16, identity(kind) as i16);
+    assert_eq!(-1i32, identity(kind) as i32);
+    assert_eq!(-1i64, identity(kind) as i64);
+    assert_eq!(-1i128, identity(kind) as i128);
+
+    test_as_arg(Nums::NegOne);
+
+    assert_eq!(-1i8, NEG_ONE_I8);
+    assert_eq!(-1i16, NEG_ONE_I16);
+    assert_eq!(-1i32, NEG_ONE_I32);
+    assert_eq!(-1i64, NEG_ONE_I64);
+    assert_eq!(-1i128, NEG_ONE_I128);
+}
diff --git a/src/test/ui/issues/issue-70041.rs b/src/test/ui/issues/issue-70041.rs
new file mode 100644
index 00000000000..22e42295eed
--- /dev/null
+++ b/src/test/ui/issues/issue-70041.rs
@@ -0,0 +1,13 @@
+// compile-flags: --edition=2018
+// run-pass
+
+macro_rules! regex {
+    //~^ WARN unused macro definition
+    () => {};
+}
+
+#[allow(dead_code)]
+use regex;
+//~^ WARN unused import
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-70041.stderr b/src/test/ui/issues/issue-70041.stderr
new file mode 100644
index 00000000000..b180175c5ab
--- /dev/null
+++ b/src/test/ui/issues/issue-70041.stderr
@@ -0,0 +1,19 @@
+warning: unused macro definition
+  --> $DIR/issue-70041.rs:4:1
+   |
+LL | / macro_rules! regex {
+LL | |
+LL | |     () => {};
+LL | | }
+   | |_^
+   |
+   = note: `#[warn(unused_macros)]` on by default
+
+warning: unused import: `regex`
+  --> $DIR/issue-70041.rs:10:5
+   |
+LL | use regex;
+   |     ^^^^^
+   |
+   = note: `#[warn(unused_imports)]` on by default
+
diff --git a/src/test/ui/parser/issue-68890-2.stderr b/src/test/ui/parser/issue-68890-2.stderr
index d475c79cb27..967eee06e28 100644
--- a/src/test/ui/parser/issue-68890-2.stderr
+++ b/src/test/ui/parser/issue-68890-2.stderr
@@ -20,3 +20,4 @@ LL | type X<'a> = (?'a) +;
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0224`.
diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
index 230733371dd..a6fa9f8dddc 100644
--- a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
+++ b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr
@@ -20,3 +20,4 @@ LL |     m!('static);
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0224`.
diff --git a/src/test/ui/proc-macro/out-of-line-mod.rs b/src/test/ui/proc-macro/out-of-line-mod.rs
new file mode 100644
index 00000000000..658ed6c18e0
--- /dev/null
+++ b/src/test/ui/proc-macro/out-of-line-mod.rs
@@ -0,0 +1,13 @@
+// Out-of-line module is found on the filesystem if passed through a proc macro (issue #58818).
+
+// check-pass
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+mod outer {
+    identity! { mod inner; }
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr
index 6de79fa917b..594115d980c 100644
--- a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr
+++ b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr
@@ -12,3 +12,4 @@ LL | type _T1 = dyn _2;
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0224`.
diff --git a/src/test/ui/traits/trait-object-macro-matcher.stderr b/src/test/ui/traits/trait-object-macro-matcher.stderr
index a8511f63c16..cb48bd1258e 100644
--- a/src/test/ui/traits/trait-object-macro-matcher.stderr
+++ b/src/test/ui/traits/trait-object-macro-matcher.stderr
@@ -14,4 +14,5 @@ LL |     m!(dyn Copy + Send + 'static);
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0038`.
+Some errors have detailed explanations: E0038, E0224.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-object-vs-lifetime-2.stderr b/src/test/ui/traits/trait-object-vs-lifetime-2.stderr
index 014d380b63c..28b8e11f133 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime-2.stderr
+++ b/src/test/ui/traits/trait-object-vs-lifetime-2.stderr
@@ -6,3 +6,4 @@ LL |     dyn 'static +: 'static + Copy,
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0224`.
diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr
index 04529fb8cfa..ff3fc2a197c 100644
--- a/src/test/ui/traits/trait-object-vs-lifetime.stderr
+++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr
@@ -32,5 +32,5 @@ LL |     let _: S<dyn 'static +, 'static>;
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0107, E0747.
+Some errors have detailed explanations: E0107, E0224, E0747.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr
index 8cc97addc7d..48241088632 100644
--- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr
+++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr
@@ -12,3 +12,4 @@ LL | type _0 = dyn ?Sized;
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0224`.