diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 960d53a62f539..6c204b894a6ad 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -1250,7 +1250,8 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
         #[cfg(windows)]
         if let Some(msg) = info.payload().downcast_ref::<String>() {
             if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
-                early_error_no_abort(ErrorOutputType::default(), msg.as_str());
+                // the error code is already going to be reported when the panic unwinds up the stack
+                let _ = early_error_no_abort(ErrorOutputType::default(), msg.as_str());
                 return;
             }
         };
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 0f36047361998..d58555272424c 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1740,7 +1740,7 @@ impl DelayedDiagnostic {
     }
 
     fn decorate(mut self) -> Diagnostic {
-        self.inner.note(format!("delayed at {}", self.note));
+        self.inner.note(format!("delayed at {}\n{}", self.inner.emitted_at, self.note));
         self.inner
     }
 }
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 545310ad35167..b88ba04b27379 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -530,19 +530,18 @@ impl<'tcx> InferCtxt<'tcx> {
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
         let span = cause.span;
-
-        let mut obligations = vec![];
         let prev = self.inner.borrow_mut().opaque_types().register(
             OpaqueTypeKey { def_id, substs },
             OpaqueHiddenType { ty: hidden_ty, span },
             origin,
         );
-        if let Some(prev) = prev {
-            obligations = self
-                .at(&cause, param_env)
+        let mut obligations = if let Some(prev) = prev {
+            self.at(&cause, param_env)
                 .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
-                .obligations;
-        }
+                .obligations
+        } else {
+            Vec::new()
+        };
 
         let item_bounds = tcx.explicit_item_bounds(def_id);
 
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index eb175e96997b3..0fe140e08d26a 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -103,8 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             && let ty = cx.typeck_results().expr_ty(&await_expr)
             && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
             && cx.tcx.ty_is_opaque_future(ty)
-            // FIXME: This also includes non-async fns that return `impl Future`.
             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
+            && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn)
+            // Check that this `impl Future` actually comes from an `async fn`
+            && cx.tcx.asyncness(async_fn_def_id).is_async()
             && check_must_use_def(
                 cx,
                 async_fn_def_id,
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 1da94dd79179c..5c71910a955d8 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -101,7 +101,7 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
 /// pass will be named after the type, and it will consist of a main
 /// loop that goes over each available MIR and applies `run_pass`.
 pub trait MirPass<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 594cbd8977ebb..746e3d9652db6 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -12,7 +12,7 @@ use rustc_session::config::OutputType;
 pub struct Marker(pub &'static str);
 
 impl<'tcx> MirPass<'tcx> for Marker {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0
     }
 
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index e1b65823a5a9c..710eed3ed3808 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -6,7 +6,7 @@ use crate::{validate, MirPass};
 
 /// Just like `MirPass`, except it cannot mutate `Body`.
 pub trait MirLint<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
@@ -26,7 +26,7 @@ impl<'tcx, T> MirPass<'tcx> for Lint<T>
 where
     T: MirLint<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0.name()
     }
 
@@ -49,7 +49,7 @@ impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel<T>
 where
     T: MirPass<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.1.name()
     }
 
@@ -121,7 +121,7 @@ fn run_passes_inner<'tcx>(
                 validate_body(tcx, body, format!("before pass {}", name));
             }
 
-            pass.run_pass(tcx, body);
+            tcx.sess.time(name, || pass.run_pass(tcx, body));
 
             if dump_enabled {
                 dump_mir_for_pass(tcx, body, &name, true);
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 1b96df3aed5be..e59219321b7ff 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -74,7 +74,7 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 }
 
 impl<'tcx> MirPass<'tcx> for SimplifyCfg {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         &self.name()
     }
 
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index c10180ee3f489..eafe57a0c0207 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -250,13 +250,13 @@ where
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
+    debug_dump(tcx, "INITIAL PARTITIONING", &initial_partitioning.codegen_units);
 
     // Merge until we have at most `max_cgu_count` codegen units.
     {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
         partitioner.merge_codegen_units(cx, &mut initial_partitioning);
-        debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
+        debug_dump(tcx, "POST MERGING", &initial_partitioning.codegen_units);
     }
 
     // In the next step, we use the inlining map to determine which additional
@@ -272,7 +272,7 @@ where
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
+    debug_dump(tcx, "POST INLINING", &post_inlining.codegen_units);
 
     // Next we try to make as many symbols "internal" as possible, so LLVM has
     // more freedom to optimize.
@@ -322,6 +322,8 @@ where
 
     result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 
+    debug_dump(tcx, "FINAL", &result);
+
     result
 }
 
@@ -346,33 +348,37 @@ struct PostInliningPartitioning<'tcx> {
     internalization_candidates: FxHashSet<MonoItem<'tcx>>,
 }
 
-fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I)
-where
-    I: Iterator<Item = &'a CodegenUnit<'tcx>>,
-    'tcx: 'a,
-{
+fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
     let dump = move || {
         use std::fmt::Write;
 
+        let num_cgus = cgus.len();
+        let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
+        let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
+        let ratio = max as f64 / min as f64;
+
         let s = &mut String::new();
-        let _ = writeln!(s, "{label}");
+        let _ = writeln!(
+            s,
+            "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
+        );
         for cgu in cgus {
             let _ =
-                writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
+                writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
 
             for (mono_item, linkage) in cgu.items() {
                 let symbol_name = mono_item.symbol_name(tcx).name;
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
 
-                let _ = writeln!(
+                let _ = with_no_trimmed_paths!(writeln!(
                     s,
                     " - {} [{:?}] [{}] estimated size {}",
                     mono_item,
                     linkage,
                     symbol_hash,
                     mono_item.size_estimate(tcx)
-                );
+                ));
             }
 
             let _ = writeln!(s);
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 3002f23da75cc..bcef0f7185fbf 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -238,6 +238,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
 
 impl<'a> Parser<'a> {
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index d91d920140dd4..4f593083b6f3a 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1732,6 +1732,7 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
+#[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"]
 pub fn early_error_no_abort(
     output: config::ErrorOutputType,
     msg: impl Into<DiagnosticMessage>,
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index ca45683d3d6b5..2bb688b921c9b 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -986,7 +986,7 @@ pub trait PointerLike {}
 #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 pub trait ConstParamTy: StructuralEq {}
 
-/// Derive macro generating an impl of the trait `Copy`.
+/// Derive macro generating an impl of the trait `ConstParamTy`.
 #[rustc_builtin_macro]
 #[unstable(feature = "adt_const_params", issue = "95174")]
 #[cfg(not(bootstrap))]
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 7f03381690141..0a9850146e5a3 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -386,6 +386,21 @@ fn offset_of() {
     // Layout of tuples is unstable
     assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
     assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
+
+    #[repr(C)]
+    struct Generic<T> {
+        x: u8,
+        y: u32,
+        z: T
+    }
+
+    // Ensure that this type of generics works
+    fn offs_of_z<T>() -> usize {
+        offset_of!(Generic<T>, z)
+    }
+
+    assert_eq!(offset_of!(Generic<u8>, z), 8);
+    assert_eq!(offs_of_z::<u8>(), 8);
 }
 
 #[test]
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 1ab5565fdb8d9..9ac652887a029 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -89,9 +89,9 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.73"
+version = "1.0.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
 
 [[package]]
 name = "cfg-if"
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 5c37fab547070..cf7c6596c0238 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -942,7 +942,6 @@ impl<'a> Builder<'a> {
         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
     }
 
-    /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
     pub fn doc_rust_lang_org_channel(&self) -> String {
         let channel = match &*self.config.channel {
             "stable" => &self.version,
diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml
index 5c795928bdc9a..d5dd511b1d31f 100644
--- a/tests/rustdoc-gui/source-code-page.goml
+++ b/tests/rustdoc-gui/source-code-page.goml
@@ -40,24 +40,24 @@ define-function: (
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "color": "rgb(92, 103, 115)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(112, 128, 144)",
+    "color": "#5c6773",
+    "background_color": "transparent",
+    "highlight_color": "#708090",
     "highlight_background_color": "rgba(255, 236, 164, 0.06)",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "color": "rgb(59, 145, 226)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(59, 145, 226)",
-    "highlight_background_color": "rgb(10, 4, 47)",
+    "color": "#3b91e2",
+    "background_color": "transparent",
+    "highlight_color": "#3b91e2",
+    "highlight_background_color": "#0a042f",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "color": "rgb(198, 126, 45)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(198, 126, 45)",
-    "highlight_background_color": "rgb(253, 255, 211)",
+    "color": "#c67e2d",
+    "background_color": "transparent",
+    "highlight_color": "#c67e2d",
+    "highlight_background_color": "#fdffd3",
 })
 
 // This is to ensure that the content is correctly align with the line numbers.
diff --git a/tests/ui/lint/unused/auxiliary/must-use-foreign.rs b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
new file mode 100644
index 0000000000000..f773f09c3821b
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+use std::future::Future;
+
+pub struct Manager;
+
+impl Manager {
+    #[must_use]
+    pub async fn new() -> (Self, impl Future<Output = ()>) {
+        (Manager, async {})
+    }
+}
diff --git a/tests/ui/lint/unused/must-use-foreign.rs b/tests/ui/lint/unused/must-use-foreign.rs
new file mode 100644
index 0000000000000..21a1105856218
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-foreign.rs
@@ -0,0 +1,15 @@
+// edition:2021
+// aux-build:must-use-foreign.rs
+// check-pass
+
+extern crate must_use_foreign;
+
+use must_use_foreign::Manager;
+
+async fn async_main() {
+    Manager::new().await.1.await;
+}
+
+fn main() {
+    let _ = async_main();
+}
diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs
index 4be93aa155ad9..6355f47f037c7 100644
--- a/tests/ui/lint/unused/unused-async.rs
+++ b/tests/ui/lint/unused/unused-async.rs
@@ -33,7 +33,7 @@ async fn test() {
     foo().await; //~ ERROR unused output of future returned by `foo` that must be used
     bar(); //~ ERROR unused return value of `bar` that must be used
     //~^ ERROR unused implementer of `Future` that must be used
-    bar().await; //~ ERROR unused output of future returned by `bar` that must be used
+    bar().await; // ok, it's not an async fn
     baz(); //~ ERROR unused implementer of `Future` that must be used
     baz().await; // ok
 }
diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr
index 1c3702ba265c0..e93a40658f3c2 100644
--- a/tests/ui/lint/unused/unused-async.stderr
+++ b/tests/ui/lint/unused/unused-async.stderr
@@ -52,17 +52,6 @@ help: use `let _ = ...` to ignore the resulting value
 LL |     let _ = bar();
    |     +++++++
 
-error: unused output of future returned by `bar` that must be used
-  --> $DIR/unused-async.rs:36:5
-   |
-LL |     bar().await;
-   |     ^^^^^^^^^^^
-   |
-help: use `let _ = ...` to ignore the resulting value
-   |
-LL |     let _ = bar().await;
-   |     +++++++
-
 error: unused implementer of `Future` that must be used
   --> $DIR/unused-async.rs:37:5
    |
@@ -71,5 +60,5 @@ LL |     baz();
    |
    = note: futures do nothing unless you `.await` or poll them
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs
index a0269ca2d1251..89e73b8c6b84d 100644
--- a/tests/ui/offset-of/offset-of-dst-field.rs
+++ b/tests/ui/offset-of/offset-of-dst-field.rs
@@ -26,8 +26,23 @@ struct Gamma {
     z: Extern,
 }
 
+struct Delta<T: ?Sized> {
+    x: u8,
+    y: u16,
+    z: T,
+}
+
 fn main() {
     offset_of!(Alpha, z); //~ ERROR the size for values of type
     offset_of!(Beta, z); //~ ERROR the size for values of type
     offset_of!(Gamma, z); //~ ERROR the size for values of type
 }
+
+fn delta() {
+    offset_of!(Delta<Alpha>, z); //~ ERROR the size for values of type
+    offset_of!(Delta<Extern>, z); //~ ERROR the size for values of type
+}
+
+fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+    offset_of!(Delta<T>, z) //~ ERROR the size for values of type
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
index e6e0f49923620..992eab3d4bdf0 100644
--- a/tests/ui/offset-of/offset-of-dst-field.stderr
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:30:5
+  --> $DIR/offset-of-dst-field.rs:36:5
    |
 LL |     offset_of!(Alpha, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -8,7 +8,7 @@ LL |     offset_of!(Alpha, z);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:31:5
+  --> $DIR/offset-of-dst-field.rs:37:5
    |
 LL |     offset_of!(Beta, z);
    |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -17,7 +17,7 @@ LL |     offset_of!(Beta, z);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `Extern` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:32:5
+  --> $DIR/offset-of-dst-field.rs:38:5
    |
 LL |     offset_of!(Gamma, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -25,6 +25,44 @@ LL |     offset_of!(Gamma, z);
    = help: the trait `Sized` is not implemented for `Extern`
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors
+error[E0277]: the size for values of type `Extern` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:43:5
+   |
+LL |     offset_of!(Delta<Extern>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `Extern`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:42:5
+   |
+LL |     offset_of!(Delta<Alpha>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `Alpha`
+  --> $DIR/offset-of-dst-field.rs:5:8
+   |
+LL | struct Alpha {
+   |        ^^^^^
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:47:5
+   |
+LL | fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+   |                             - this type parameter needs to be `std::marker::Sized`
+LL |     offset_of!(Delta<T>, z)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+LL + fn generic_with_maybe_sized<T>() -> usize {
+   |
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs
new file mode 100644
index 0000000000000..50c2e93841f9f
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.rs
@@ -0,0 +1,20 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+
+fn main() {
+    let _: u8 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u16 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u32 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u64 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: isize = offset_of!(S, v); //~ ERROR mismatched types
+    let _: usize = offset_of!(S, v);
+
+    offset_of!(S, v) //~ ERROR mismatched types
+}
diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr
new file mode 100644
index 0000000000000..6f8c94750299e
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.stderr
@@ -0,0 +1,64 @@
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:12:17
+   |
+LL |     let _: u8 = offset_of!(S, v);
+   |            --   ^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:13:18
+   |
+LL |     let _: u16 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u16`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:14:18
+   |
+LL |     let _: u32 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:15:18
+   |
+LL |     let _: u64 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:16:20
+   |
+LL |     let _: isize = offset_of!(S, v);
+   |            -----   ^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:19:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+...
+LL |     offset_of!(S, v)
+   |     ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
index 0291b7825cabc..6b1a16ba62b67 100644
--- a/tests/ui/offset-of/offset-of-private.rs
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -8,9 +8,21 @@ mod m {
         pub public: u8,
         private: u8,
     }
+    #[repr(C)]
+    pub struct FooTuple(pub u8, u8);
+    #[repr(C)]
+    struct Bar {
+        pub public: u8,
+        private: u8,
+    }
 }
 
 fn main() {
     offset_of!(m::Foo, public);
     offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
+    offset_of!(m::FooTuple, 0);
+    offset_of!(m::FooTuple, 1); //~ ERROR field `1` of struct `FooTuple` is private
+    offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private
+    offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private
+    //~| ERROR field `private` of struct `Bar` is private
 }
diff --git a/tests/ui/offset-of/offset-of-private.stderr b/tests/ui/offset-of/offset-of-private.stderr
index 8a186dd5a02e7..0674b58f8608c 100644
--- a/tests/ui/offset-of/offset-of-private.stderr
+++ b/tests/ui/offset-of/offset-of-private.stderr
@@ -1,9 +1,46 @@
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:25:19
+   |
+LL |     offset_of!(m::Bar, public);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:19
+   |
+LL |     offset_of!(m::Bar, private);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
 error[E0616]: field `private` of struct `Foo` is private
-  --> $DIR/offset-of-private.rs:15:24
+  --> $DIR/offset-of-private.rs:22:24
    |
 LL |     offset_of!(m::Foo, private);
    |                        ^^^^^^^ private field
 
-error: aborting due to previous error
+error[E0616]: field `1` of struct `FooTuple` is private
+  --> $DIR/offset-of-private.rs:24:29
+   |
+LL |     offset_of!(m::FooTuple, 1);
+   |                             ^ private field
+
+error[E0616]: field `private` of struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:24
+   |
+LL |     offset_of!(m::Bar, private);
+   |                        ^^^^^^^ private field
+
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0616`.
+Some errors have detailed explanations: E0603, E0616.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs
new file mode 100644
index 0000000000000..dbeef0e74dc37
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.rs
@@ -0,0 +1,58 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct C<T> {
+    v: T,
+    w: T,
+}
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+impl S {
+    fn v_offs() -> usize {
+        offset_of!(Self, v)
+    }
+    fn v_offs_wrong_syntax() {
+        offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::`
+        offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self`
+        //~| no field `Self` on type `S`
+    }
+    fn offs_in_c() -> usize {
+        offset_of!(C<Self>, w)
+    }
+    fn offs_in_c_colon() -> usize {
+        offset_of!(C::<Self>, w)
+    }
+}
+
+mod m {
+    use std::mem::offset_of;
+    fn off() {
+        offset_of!(self::S, v); //~ ERROR cannot find type `S` in module
+        offset_of!(super::S, v);
+        offset_of!(crate::S, v);
+    }
+    impl super::n::T {
+        fn v_offs_self() -> usize {
+            offset_of!(Self, v) //~ ERROR field `v` of struct `T` is private
+        }
+    }
+}
+
+mod n {
+    pub struct T { v: u8, }
+}
+
+fn main() {
+    offset_of!(self::S, v);
+    offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope
+
+    offset_of!(S, self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `S`
+    offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `u8`
+}
diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr
new file mode 100644
index 0000000000000..df555463f9884
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.stderr
@@ -0,0 +1,79 @@
+error: no rules expected the token `::`
+  --> $DIR/offset-of-self.rs:20:30
+   |
+LL |         offset_of!(Self, Self::v);
+   |                              ^^ no rules expected this token in macro call
+   |
+   = note: while trying to match sequence start
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^ expected identifier, found keyword
+
+error[E0412]: cannot find type `S` in module `self`
+  --> $DIR/offset-of-self.rs:35:26
+   |
+LL |         offset_of!(self::S, v);
+   |                          ^ not found in `self`
+   |
+help: consider importing this struct
+   |
+LL +     use S;
+   |
+help: if you import `S`, refer to it directly
+   |
+LL -         offset_of!(self::S, v);
+LL +         offset_of!(S, v);
+   |
+
+error[E0411]: cannot find type `Self` in this scope
+  --> $DIR/offset-of-self.rs:52:16
+   |
+LL | fn main() {
+   |    ---- `Self` not allowed in a function
+LL |     offset_of!(self::S, v);
+LL |     offset_of!(Self, v);
+   |                ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error[E0609]: no field `Self` on type `S`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^
+
+error[E0616]: field `v` of struct `T` is private
+  --> $DIR/offset-of-self.rs:41:30
+   |
+LL |             offset_of!(Self, v)
+   |                              ^ private field
+
+error[E0609]: no field `self` on type `S`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^
+
+error[E0609]: no field `self` on type `u8`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0411, E0412, E0609, E0616.
+For more information about an error, try `rustc --explain E0411`.