diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index f51b0086dc8b6..8730aeb0f3bff 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -52,7 +52,10 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol {
         // when we try to compute the "horizontal trim".
         let lines = if kind == CommentKind::Block {
             // Whatever happens, we skip the first line.
-            let mut i = if lines[0].trim_start().starts_with('*') { 0 } else { 1 };
+            let mut i = lines
+                .get(0)
+                .map(|l| if l.trim_start().starts_with('*') { 0 } else { 1 })
+                .unwrap_or(0);
             let mut j = lines.len();
 
             while i < j && lines[i].trim().is_empty() {
diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs
index c89015b4c6bb3..c1f1b4e505c36 100644
--- a/compiler/rustc_expand/src/mbe.rs
+++ b/compiler/rustc_expand/src/mbe.rs
@@ -17,48 +17,24 @@ use rustc_data_structures::sync::Lrc;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-/// Contains the sub-token-trees of a "delimited" token tree such as `(a b c)`. The delimiter itself
-/// might be `NoDelim`.
+/// Contains the sub-token-trees of a "delimited" token tree such as `(a b c)`. The delimiters
+/// might be `NoDelim`, but they are not represented explicitly.
 #[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
 struct Delimited {
     delim: token::DelimToken,
-    /// Note: This contains the opening and closing delimiters tokens (e.g. `(` and `)`). Note that
-    /// these could be `NoDelim`. These token kinds must match `delim`, and the methods below
-    /// debug_assert this.
-    all_tts: Vec<TokenTree>,
+    /// FIXME: #67062 has details about why this is sub-optimal.
+    tts: Vec<TokenTree>,
 }
 
 impl Delimited {
-    /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter. Panics if
-    /// the delimiter is `NoDelim`.
-    fn open_tt(&self) -> &TokenTree {
-        let tt = self.all_tts.first().unwrap();
-        debug_assert!(matches!(
-            tt,
-            &TokenTree::Token(token::Token { kind: token::OpenDelim(d), .. }) if d == self.delim
-        ));
-        tt
+    /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter.
+    fn open_tt(&self, span: DelimSpan) -> TokenTree {
+        TokenTree::token(token::OpenDelim(self.delim), span.open)
     }
 
-    /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter. Panics if
-    /// the delimiter is `NoDelim`.
-    fn close_tt(&self) -> &TokenTree {
-        let tt = self.all_tts.last().unwrap();
-        debug_assert!(matches!(
-            tt,
-            &TokenTree::Token(token::Token { kind: token::CloseDelim(d), .. }) if d == self.delim
-        ));
-        tt
-    }
-
-    /// Returns the tts excluding the outer delimiters.
-    ///
-    /// FIXME: #67062 has details about why this is sub-optimal.
-    fn inner_tts(&self) -> &[TokenTree] {
-        // These functions are called for the assertions within them.
-        let _open_tt = self.open_tt();
-        let _close_tt = self.close_tt();
-        &self.all_tts[1..self.all_tts.len() - 1]
+    /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter.
+    fn close_tt(&self, span: DelimSpan) -> TokenTree {
+        TokenTree::token(token::CloseDelim(self.delim), span.close)
     }
 }
 
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 0e20e0970f401..fbacebf99c050 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -282,7 +282,7 @@ fn check_binders(
         // `MetaVarExpr` can not appear in the LHS of a macro arm
         TokenTree::MetaVarExpr(..) => {}
         TokenTree::Delimited(_, ref del) => {
-            for tt in del.inner_tts() {
+            for tt in &del.tts {
                 check_binders(sess, node_id, tt, macros, binders, ops, valid);
             }
         }
@@ -345,7 +345,7 @@ fn check_occurrences(
             check_ops_is_prefix(sess, node_id, macros, binders, ops, dl.entire(), name);
         }
         TokenTree::Delimited(_, ref del) => {
-            check_nested_occurrences(sess, node_id, del.inner_tts(), macros, binders, ops, valid);
+            check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, valid);
         }
         TokenTree::Sequence(_, ref seq) => {
             let ops = ops.push(seq.kleene);
@@ -432,20 +432,14 @@ fn check_nested_occurrences(
             {
                 let macro_rules = state == NestedMacroState::MacroRulesNotName;
                 state = NestedMacroState::Empty;
-                let rest = check_nested_macro(
-                    sess,
-                    node_id,
-                    macro_rules,
-                    del.inner_tts(),
-                    &nested_macros,
-                    valid,
-                );
+                let rest =
+                    check_nested_macro(sess, node_id, macro_rules, &del.tts, &nested_macros, valid);
                 // If we did not check the whole macro definition, then check the rest as if outside
                 // the macro definition.
                 check_nested_occurrences(
                     sess,
                     node_id,
-                    &del.inner_tts()[rest..],
+                    &del.tts[rest..],
                     macros,
                     binders,
                     ops,
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 604e25a14e6be..a137e0c92e8a2 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -151,9 +151,11 @@ pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec<Match
                 TokenTree::Token(token) => {
                     locs.push(MatcherLoc::Token { token: token.clone() });
                 }
-                TokenTree::Delimited(_, delimited) => {
+                TokenTree::Delimited(span, delimited) => {
                     locs.push(MatcherLoc::Delimited);
-                    inner(sess, &delimited.all_tts, locs, next_metavar, seq_depth);
+                    inner(sess, &[delimited.open_tt(*span)], locs, next_metavar, seq_depth);
+                    inner(sess, &delimited.tts, locs, next_metavar, seq_depth);
+                    inner(sess, &[delimited.close_tt(*span)], locs, next_metavar, seq_depth);
                 }
                 TokenTree::Sequence(_, seq) => {
                     // We can't determine `idx_first_after` and construct the final
@@ -293,7 +295,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
         .map(|tt| match tt {
             TokenTree::MetaVarDecl(..) => 1,
             TokenTree::Sequence(_, seq) => seq.num_captures,
-            TokenTree::Delimited(_, delim) => count_metavar_decls(delim.inner_tts()),
+            TokenTree::Delimited(_, delim) => count_metavar_decls(&delim.tts),
             TokenTree::Token(..) => 0,
             TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(),
         })
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 5dc086ee9e603..31dae6a2fb437 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -263,9 +263,7 @@ fn generic_extension<'cx, 'tt>(
 
                 // Ignore the delimiters on the RHS.
                 let rhs = match &rhses[i] {
-                    mbe::TokenTree::Delimited(_, delimited) => {
-                        delimited.inner_tts().to_vec().clone()
-                    }
+                    mbe::TokenTree::Delimited(_, delimited) => delimited.tts.to_vec(),
                     _ => cx.span_bug(sp, "malformed macro rhs"),
                 };
                 let arm_span = rhses[i].span();
@@ -470,17 +468,16 @@ pub fn compile_declarative_macro(
             .iter()
             .map(|m| {
                 if let MatchedTokenTree(ref tt) = *m {
-                    let mut tts = vec![];
-                    mbe::quoted::parse(
+                    let tt = mbe::quoted::parse(
                         tt.clone().into(),
                         true,
                         &sess.parse_sess,
                         def.id,
                         features,
                         edition,
-                        &mut tts,
-                    );
-                    let tt = tts.pop().unwrap();
+                    )
+                    .pop()
+                    .unwrap();
                     valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def, &tt);
                     return tt;
                 }
@@ -495,17 +492,16 @@ pub fn compile_declarative_macro(
             .iter()
             .map(|m| {
                 if let MatchedTokenTree(ref tt) = *m {
-                    let mut tts = vec![];
-                    mbe::quoted::parse(
+                    return mbe::quoted::parse(
                         tt.clone().into(),
                         false,
                         &sess.parse_sess,
                         def.id,
                         features,
                         edition,
-                        &mut tts,
-                    );
-                    return tts.pop().unwrap();
+                    )
+                    .pop()
+                    .unwrap();
                 }
                 sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
             })
@@ -544,7 +540,7 @@ pub fn compile_declarative_macro(
                 // Ignore the delimiters around the matcher.
                 match lhs {
                     mbe::TokenTree::Delimited(_, delimited) => {
-                        mbe::macro_parser::compute_locs(&sess.parse_sess, delimited.inner_tts())
+                        mbe::macro_parser::compute_locs(&sess.parse_sess, &delimited.tts)
                     }
                     _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "malformed macro lhs"),
                 }
@@ -576,7 +572,7 @@ fn check_lhs_nt_follows(
     // lhs is going to be like TokenTree::Delimited(...), where the
     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
     if let mbe::TokenTree::Delimited(_, delimited) = lhs {
-        check_matcher(sess, features, def, delimited.inner_tts())
+        check_matcher(sess, features, def, &delimited.tts)
     } else {
         let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
         sess.span_diagnostic.span_err(lhs.span(), msg);
@@ -597,7 +593,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
             | TokenTree::MetaVarDecl(..)
             | TokenTree::MetaVarExpr(..) => (),
             TokenTree::Delimited(_, ref del) => {
-                if !check_lhs_no_empty_seq(sess, del.inner_tts()) {
+                if !check_lhs_no_empty_seq(sess, &del.tts) {
                     return false;
                 }
             }
@@ -692,9 +688,9 @@ impl FirstSets {
                     | TokenTree::MetaVarExpr(..) => {
                         first.replace_with(tt.clone());
                     }
-                    TokenTree::Delimited(_span, ref delimited) => {
-                        build_recur(sets, delimited.inner_tts());
-                        first.replace_with(delimited.open_tt().clone());
+                    TokenTree::Delimited(span, ref delimited) => {
+                        build_recur(sets, &delimited.tts);
+                        first.replace_with(delimited.open_tt(span));
                     }
                     TokenTree::Sequence(sp, ref seq_rep) => {
                         let subfirst = build_recur(sets, &seq_rep.tts);
@@ -758,8 +754,8 @@ impl FirstSets {
                     first.add_one(tt.clone());
                     return first;
                 }
-                TokenTree::Delimited(_span, ref delimited) => {
-                    first.add_one(delimited.open_tt().clone());
+                TokenTree::Delimited(span, ref delimited) => {
+                    first.add_one(delimited.open_tt(span));
                     return first;
                 }
                 TokenTree::Sequence(sp, ref seq_rep) => {
@@ -945,9 +941,9 @@ fn check_matcher_core(
                     suffix_first = build_suffix_first();
                 }
             }
-            TokenTree::Delimited(_span, ref d) => {
-                let my_suffix = TokenSet::singleton(d.close_tt().clone());
-                check_matcher_core(sess, features, def, first_sets, d.inner_tts(), &my_suffix);
+            TokenTree::Delimited(span, ref d) => {
+                let my_suffix = TokenSet::singleton(d.close_tt(span));
+                check_matcher_core(sess, features, def, first_sets, &d.tts, &my_suffix);
                 // don't track non NT tokens
                 last.replace_with_irrelevant();
 
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 48abbd7c18e14..a99a18aae119a 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -45,8 +45,10 @@ pub(super) fn parse(
     node_id: NodeId,
     features: &Features,
     edition: Edition,
-    result: &mut Vec<TokenTree>,
-) {
+) -> Vec<TokenTree> {
+    // Will contain the final collection of `self::TokenTree`
+    let mut result = Vec::new();
+
     // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming
     // additional trees if need be.
     let mut trees = input.trees();
@@ -113,6 +115,7 @@ pub(super) fn parse(
             _ => result.push(tree),
         }
     }
+    result
 }
 
 /// Asks for the `macro_metavar_expr` feature if it is not already declared
@@ -205,8 +208,7 @@ fn parse_tree(
                     // If we didn't find a metavar expression above, then we must have a
                     // repetition sequence in the macro (e.g. `$(pat)*`).  Parse the
                     // contents of the sequence itself
-                    let mut sequence = vec![];
-                    parse(tts, parsing_patterns, sess, node_id, features, edition, &mut sequence);
+                    let sequence = parse(tts, parsing_patterns, sess, node_id, features, edition);
                     // Get the Kleene operator and optional separator
                     let (separator, kleene) =
                         parse_sep_and_kleene_op(&mut trees, delim_span.entire(), sess);
@@ -269,15 +271,13 @@ fn parse_tree(
 
         // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to
         // descend into the delimited set and further parse it.
-        tokenstream::TokenTree::Delimited(span, delim, tts) => {
-            let mut all_tts = vec![];
-            // Add the explicit open and close delimiters, which
-            // `tokenstream::TokenTree::Delimited` lacks.
-            all_tts.push(TokenTree::token(token::OpenDelim(delim), span.open));
-            parse(tts, parsing_patterns, sess, node_id, features, edition, &mut all_tts);
-            all_tts.push(TokenTree::token(token::CloseDelim(delim), span.close));
-            TokenTree::Delimited(span, Lrc::new(Delimited { delim, all_tts }))
-        }
+        tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
+            span,
+            Lrc::new(Delimited {
+                delim,
+                tts: parse(tts, parsing_patterns, sess, node_id, features, edition),
+            }),
+        ),
     }
 }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 508108df001ec..b1ab2cc45781a 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -10,7 +10,7 @@ use rustc_errors::{pluralize, PResult};
 use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_span::hygiene::{LocalExpnId, Transparency};
 use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 
 use smallvec::{smallvec, SmallVec};
 use std::mem;
@@ -34,14 +34,8 @@ enum Frame {
 
 impl Frame {
     /// Construct a new frame around the delimited set of tokens.
-    fn new(mut tts: Vec<mbe::TokenTree>) -> Frame {
-        // Need to add empty delimiters.
-        let open_tt = mbe::TokenTree::token(token::OpenDelim(token::NoDelim), DUMMY_SP);
-        let close_tt = mbe::TokenTree::token(token::CloseDelim(token::NoDelim), DUMMY_SP);
-        tts.insert(0, open_tt);
-        tts.push(close_tt);
-
-        let forest = Lrc::new(mbe::Delimited { delim: token::NoDelim, all_tts: tts });
+    fn new(tts: Vec<mbe::TokenTree>) -> Frame {
+        let forest = Lrc::new(mbe::Delimited { delim: token::NoDelim, tts });
         Frame::Delimited { forest, idx: 0, span: DelimSpan::dummy() }
     }
 }
@@ -52,7 +46,7 @@ impl Iterator for Frame {
     fn next(&mut self) -> Option<mbe::TokenTree> {
         match *self {
             Frame::Delimited { ref forest, ref mut idx, .. } => {
-                let res = forest.inner_tts().get(*idx).cloned();
+                let res = forest.tts.get(*idx).cloned();
                 *idx += 1;
                 res
             }
@@ -388,7 +382,7 @@ fn lockstep_iter_size(
     use mbe::TokenTree;
     match *tree {
         TokenTree::Delimited(_, ref delimited) => {
-            delimited.inner_tts().iter().fold(LockstepIterSize::Unconstrained, |size, tt| {
+            delimited.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| {
                 size.with(lockstep_iter_size(tt, interpolations, repeats))
             })
         }
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 28466315c8687..8340a0b360ef7 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -505,6 +505,8 @@ declare_features! (
     (active, static_nobundle, "1.16.0", Some(37403), None),
     /// Allows attributes on expressions and non-item statements.
     (active, stmt_expr_attributes, "1.6.0", Some(15701), None),
+    /// Allows lints part of the strict provenance effort.
+    (active, strict_provenance, "1.61.0", Some(95228), None),
     /// Allows the use of `#[target_feature]` on safe functions.
     (active, target_feature_11, "1.45.0", Some(69098), None),
     /// Allows using `#[thread_local]` on `static` items.
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 5704c6ed3b25d..89ce307d12cd7 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2648,6 +2648,96 @@ declare_lint! {
     };
 }
 
+declare_lint! {
+    /// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer
+    /// and a pointer.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(strict_provenance)]
+    /// #![warn(fuzzy_provenance_casts)]
+    ///
+    /// fn main() {
+    ///     let _dangling = 16_usize as *const u8;
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// This lint is part of the strict provenance effort, see [issue #95228].
+    /// Casting an integer to a pointer is considered bad style, as a pointer
+    /// contains, besides the *address* also a *provenance*, indicating what
+    /// memory the pointer is allowed to read/write. Casting an integer, which
+    /// doesn't have provenance, to a pointer requires the compiler to assign
+    /// (guess) provenance. The compiler assigns "all exposed valid" (see the
+    /// docs of [`ptr::from_exposed_addr`] for more information about this
+    /// "exposing"). This penalizes the optimiser and is not well suited for
+    /// dynamic analysis/dynamic program verification (e.g. Miri or CHERI
+    /// platforms).
+    ///
+    /// It is much better to use [`ptr::with_addr`] instead to specify the
+    /// provenance you want. If using this function is not possible because the
+    /// code relies on exposed provenance then there is as an escape hatch
+    /// [`ptr::from_exposed_addr`].
+    ///
+    /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
+    /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/ptr/fn.with_addr
+    /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr
+    pub FUZZY_PROVENANCE_CASTS,
+    Allow,
+    "a fuzzy integer to pointer cast is used",
+    @feature_gate = sym::strict_provenance;
+}
+
+declare_lint! {
+    /// The `lossy_provenance_casts` lint detects an `as` cast between a pointer
+    /// and an integer.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(strict_provenance)]
+    /// #![warn(lossy_provenance_casts)]
+    ///
+    /// fn main() {
+    ///     let x: u8 = 37;
+    ///     let _addr: usize = &x as *const u8 as usize;
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// This lint is part of the strict provenance effort, see [issue #95228].
+    /// Casting a pointer to an integer is a lossy operation, because beyond
+    /// just an *address* a pointer may be associated with a particular
+    /// *provenance*. This information is used by the optimiser and for dynamic
+    /// analysis/dynamic program verification (e.g. Miri or CHERI platforms).
+    ///
+    /// Since this cast is lossy, it is considered good style to use the
+    /// [`ptr::addr`] method instead, which has a similar effect, but doesn't
+    /// "expose" the pointer provenance. This improves optimisation potential.
+    /// See the docs of [`ptr::addr`] and [`ptr::expose_addr`] for more information
+    /// about exposing pointer provenance.
+    ///
+    /// If your code can't comply with strict provenance and needs to expose
+    /// the provenance, then there is [`ptr::expose_addr`] as an escape hatch,
+    /// which preserves the behaviour of `as usize` casts while being explicit
+    /// about the semantics.
+    ///
+    /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
+    /// [`ptr::addr`]: https://doc.rust-lang.org/core/ptr/fn.addr
+    /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/ptr/fn.expose_addr
+    pub LOSSY_PROVENANCE_CASTS,
+    Allow,
+    "a lossy pointer to integer cast is used",
+    @feature_gate = sym::strict_provenance;
+}
+
 declare_lint! {
     /// The `const_evaluatable_unchecked` lint detects a generic constant used
     /// in a type.
@@ -3101,6 +3191,8 @@ declare_lint_pass! {
         UNSAFE_OP_IN_UNSAFE_FN,
         INCOMPLETE_INCLUDE,
         CENUM_IMPL_DROP_CAST,
+        FUZZY_PROVENANCE_CASTS,
+        LOSSY_PROVENANCE_CASTS,
         CONST_EVALUATABLE_UNCHECKED,
         INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
         MUST_NOT_SUSPEND,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f5803aaa0786e..dc4d10f699c75 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1348,6 +1348,7 @@ symbols! {
         str_trim,
         str_trim_end,
         str_trim_start,
+        strict_provenance,
         stringify,
         stringify_macro,
         struct_field_attributes,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 9998c5bb087e1..ac98dd5801e40 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -36,6 +36,7 @@ use rustc_span::symbol::{kw, sym};
 use rustc_span::{ExpnKind, Span, DUMMY_SP};
 use std::fmt;
 use std::iter;
+use std::ops::ControlFlow;
 
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::query::normalize::AtExt as _;
@@ -2226,9 +2227,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
         post.dedup();
 
         if self.is_tainted_by_errors()
-            && crate_names.len() == 1
-            && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
-            && spans.len() == 0
+            && (crate_names.len() == 1
+                && spans.len() == 0
+                && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
+                || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
         {
             // Avoid complaining about other inference issues for expressions like
             // `42 >> 1`, where the types are still `{integer}`, but we want to
@@ -2666,3 +2668,17 @@ impl ArgKind {
         }
     }
 }
+
+struct HasNumericInferVisitor;
+
+impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor {
+    type BreakTy = ();
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::CONTINUE
+        }
+    }
+}
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 7ce428ea12466..6091b8fee00b6 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -807,11 +807,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
             // ptr -> *
             (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
-            (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
-            (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
 
-            // * -> ptr
-            (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
+            // ptr-addr-cast
+            (Ptr(m_expr), Int(t_c)) => {
+                self.lossy_provenance_ptr2int_lint(fcx, t_c);
+                self.check_ptr_addr_cast(fcx, m_expr)
+            }
+            (FnPtr, Int(_)) => {
+                // FIXME(#95489): there should eventually be a lint for these casts
+                Ok(CastKind::FnPtrAddrCast)
+            }
+            // addr-ptr-cast
+            (Int(_), Ptr(mt)) => {
+                self.fuzzy_provenance_int2ptr_lint(fcx);
+                self.check_addr_ptr_cast(fcx, mt)
+            }
+            // fn-ptr-cast
             (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
 
             // prim -> prim
@@ -973,6 +984,74 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             }
         }
     }
+
+    fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
+        fcx.tcx.struct_span_lint_hir(
+            lint::builtin::LOSSY_PROVENANCE_CASTS,
+            self.expr.hir_id,
+            self.span,
+            |err| {
+                let mut err = err.build(&format!(
+                    "under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`",
+                    self.expr_ty, self.cast_ty
+                ));
+
+                let msg = "use `.addr()` to obtain the address of a pointer";
+                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                    let scalar_cast = match t_c {
+                        ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
+                        _ => format!(" as {}", self.cast_ty),
+                    };
+                    err.span_suggestion(
+                        self.span,
+                        msg,
+                        format!("({}).addr(){}", snippet, scalar_cast),
+                        Applicability::MaybeIncorrect
+                    );
+                } else {
+                    err.help(msg);
+                }
+                err.help(
+                    "if you can't comply with strict provenance and need to expose the pointer\
+                    provenance you can use `.expose_addr()` instead"
+                );
+
+                err.emit();
+            },
+        );
+    }
+
+    fn fuzzy_provenance_int2ptr_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
+        fcx.tcx.struct_span_lint_hir(
+            lint::builtin::FUZZY_PROVENANCE_CASTS,
+            self.expr.hir_id,
+            self.span,
+            |err| {
+
+                let mut err = err.build(&format!(
+                    "strict provenance disallows casting integer `{}` to pointer `{}`",
+                    self.expr_ty, self.cast_ty
+                ));
+                let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
+                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                    err.span_suggestion(
+                        self.span,
+                        msg,
+                        format!("(...).with_addr({})", snippet),
+                        Applicability::HasPlaceholders,
+                    );
+                } else {
+                    err.help(msg);
+                }
+                err.help(
+                    "if you can't comply with strict provenance and don't have a pointer with \
+                    the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
+                 );
+
+                err.emit();
+            },
+        );
+    }
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index a56d4de03cd0e..e6faf1df3a810 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -163,6 +163,11 @@ use crate::str::from_boxed_utf8_unchecked;
 #[cfg(not(no_global_oom_handling))]
 use crate::vec::Vec;
 
+#[unstable(feature = "thin_box", issue = "92791")]
+pub use thin::ThinBox;
+
+mod thin;
+
 /// A pointer type for heap allocation.
 ///
 /// See the [module-level documentation](../../std/boxed/index.html) for more.
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
new file mode 100644
index 0000000000000..390030fa2b21c
--- /dev/null
+++ b/library/alloc/src/boxed/thin.rs
@@ -0,0 +1,215 @@
+// Based on
+// https://github.com/matthieu-m/rfc2580/blob/b58d1d3cba0d4b5e859d3617ea2d0943aaa31329/examples/thin.rs
+// by matthieu-m
+use crate::alloc::{self, Layout, LayoutError};
+use core::fmt::{self, Debug, Display, Formatter};
+use core::marker::{PhantomData, Unsize};
+use core::mem;
+use core::ops::{Deref, DerefMut};
+use core::ptr::Pointee;
+use core::ptr::{self, NonNull};
+
+/// ThinBox.
+///
+/// A thin pointer for heap allocation, regardless of T.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(thin_box)]
+/// use std::boxed::ThinBox;
+///
+/// let five = ThinBox::new(5);
+/// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]);
+///
+/// use std::mem::{size_of, size_of_val};
+/// let size_of_ptr = size_of::<*const ()>();
+/// assert_eq!(size_of_ptr, size_of_val(&five));
+/// assert_eq!(size_of_ptr, size_of_val(&thin_slice));
+/// ```
+#[unstable(feature = "thin_box", issue = "92791")]
+pub struct ThinBox<T: ?Sized> {
+    ptr: WithHeader<<T as Pointee>::Metadata>,
+    _marker: PhantomData<T>,
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T> ThinBox<T> {
+    /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
+    /// the stack.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(thin_box)]
+    /// use std::boxed::ThinBox;
+    ///
+    /// let five = ThinBox::new(5);
+    /// ```
+    #[cfg(not(no_global_oom_handling))]
+    pub fn new(value: T) -> Self {
+        let meta = ptr::metadata(&value);
+        let ptr = WithHeader::new(meta, value);
+        ThinBox { ptr, _marker: PhantomData }
+    }
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<Dyn: ?Sized> ThinBox<Dyn> {
+    /// Moves a type to the heap with its `Metadata` stored in the heap allocation instead of on
+    /// the stack.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(thin_box)]
+    /// use std::boxed::ThinBox;
+    ///
+    /// let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]);
+    /// ```
+    #[cfg(not(no_global_oom_handling))]
+    pub fn new_unsize<T>(value: T) -> Self
+    where
+        T: Unsize<Dyn>,
+    {
+        let meta = ptr::metadata(&value as &Dyn);
+        let ptr = WithHeader::new(meta, value);
+        ThinBox { ptr, _marker: PhantomData }
+    }
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T: ?Sized + Debug> Debug for ThinBox<T> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        Debug::fmt(self.deref(), f)
+    }
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T: ?Sized + Display> Display for ThinBox<T> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        Display::fmt(self.deref(), f)
+    }
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T: ?Sized> Deref for ThinBox<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        let value = self.data();
+        let metadata = self.meta();
+        let pointer = ptr::from_raw_parts(value as *const (), metadata);
+        unsafe { &*pointer }
+    }
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T: ?Sized> DerefMut for ThinBox<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        let value = self.data();
+        let metadata = self.meta();
+        let pointer = ptr::from_raw_parts_mut::<T>(value as *mut (), metadata);
+        unsafe { &mut *pointer }
+    }
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T: ?Sized> Drop for ThinBox<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let value = self.deref_mut();
+            let value = value as *mut T;
+            self.ptr.drop::<T>(value);
+        }
+    }
+}
+
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T: ?Sized> ThinBox<T> {
+    fn meta(&self) -> <T as Pointee>::Metadata {
+        //  Safety:
+        //  -   NonNull and valid.
+        unsafe { *self.ptr.header() }
+    }
+
+    fn data(&self) -> *mut u8 {
+        self.ptr.value()
+    }
+}
+
+/// A pointer to type-erased data, guaranteed to have a header `H` before the pointed-to location.
+struct WithHeader<H>(NonNull<u8>, PhantomData<H>);
+
+impl<H> WithHeader<H> {
+    #[cfg(not(no_global_oom_handling))]
+    fn new<T>(header: H, value: T) -> WithHeader<H> {
+        let value_layout = Layout::new::<T>();
+        let Ok((layout, value_offset)) = Self::alloc_layout(value_layout) else {
+            // We pass an empty layout here because we do not know which layout caused the
+            // arithmetic overflow in `Layout::extend` and `handle_alloc_error` takes `Layout` as
+            // its argument rather than `Result<Layout, LayoutError>`, also this function has been
+            // stable since 1.28 ._.
+            //
+            // On the other hand, look at this gorgeous turbofish!
+            alloc::handle_alloc_error(Layout::new::<()>());
+        };
+
+        unsafe {
+            let ptr = alloc::alloc(layout);
+
+            if ptr.is_null() {
+                alloc::handle_alloc_error(layout);
+            }
+            //  Safety:
+            //  -   The size is at least `aligned_header_size`.
+            let ptr = ptr.add(value_offset) as *mut _;
+
+            let ptr = NonNull::new_unchecked(ptr);
+
+            let result = WithHeader(ptr, PhantomData);
+            ptr::write(result.header(), header);
+            ptr::write(result.value().cast(), value);
+
+            result
+        }
+    }
+
+    //  Safety:
+    //  -   Assumes that `value` can be dereferenced.
+    unsafe fn drop<T: ?Sized>(&self, value: *mut T) {
+        unsafe {
+            // SAFETY: Layout must have been computable if we're in drop
+            let (layout, value_offset) =
+                Self::alloc_layout(Layout::for_value_raw(value)).unwrap_unchecked();
+
+            ptr::drop_in_place::<T>(value);
+            // We only drop the value because the Pointee trait requires that the metadata is copy
+            // aka trivially droppable
+            alloc::dealloc(self.0.as_ptr().sub(value_offset), layout);
+        }
+    }
+
+    fn header(&self) -> *mut H {
+        //  Safety:
+        //  - At least `size_of::<H>()` bytes are allocated ahead of the pointer.
+        //  - We know that H will be aligned because the middle pointer is aligned to the greater
+        //    of the alignment of the header and the data and the header size includes the padding
+        //    needed to align the header. Subtracting the header size from the aligned data pointer
+        //    will always result in an aligned header pointer, it just may not point to the
+        //    beginning of the allocation.
+        unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H }
+    }
+
+    fn value(&self) -> *mut u8 {
+        self.0.as_ptr()
+    }
+
+    const fn header_size() -> usize {
+        mem::size_of::<H>()
+    }
+
+    fn alloc_layout(value_layout: Layout) -> Result<(Layout, usize), LayoutError> {
+        Layout::new::<H>().extend(value_layout)
+    }
+}
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 2ddb5f231b1d6..c54001dceea49 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -120,6 +120,7 @@
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(pattern)]
 #![feature(ptr_internals)]
+#![feature(ptr_metadata)]
 #![feature(receiver_trait)]
 #![feature(set_ptr_value)]
 #![feature(slice_group_by)]
@@ -152,6 +153,7 @@
 #![feature(fundamental)]
 #![cfg_attr(not(test), feature(generator_trait))]
 #![feature(lang_items)]
+#![feature(let_else)]
 #![feature(min_specialization)]
 #![feature(negative_impls)]
 #![feature(never_type)]
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 16ceb8e373dcb..16d3b36859570 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -39,6 +39,7 @@
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(panic_update_hook)]
 #![feature(slice_flatten)]
+#![feature(thin_box)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
@@ -57,6 +58,7 @@ mod rc;
 mod slice;
 mod str;
 mod string;
+mod thin_box;
 mod vec;
 mod vec_deque;
 
diff --git a/library/alloc/tests/thin_box.rs b/library/alloc/tests/thin_box.rs
new file mode 100644
index 0000000000000..0fe6aaa4d0048
--- /dev/null
+++ b/library/alloc/tests/thin_box.rs
@@ -0,0 +1,26 @@
+use alloc::boxed::ThinBox;
+use core::mem::size_of;
+
+#[test]
+fn want_niche_optimization() {
+    fn uses_niche<T: ?Sized>() -> bool {
+        size_of::<*const ()>() == size_of::<Option<ThinBox<T>>>()
+    }
+
+    trait Tr {}
+    assert!(uses_niche::<dyn Tr>());
+    assert!(uses_niche::<[i32]>());
+    assert!(uses_niche::<i32>());
+}
+
+#[test]
+fn want_thin() {
+    fn is_thin<T: ?Sized>() -> bool {
+        size_of::<*const ()>() == size_of::<ThinBox<T>>()
+    }
+
+    trait Tr {}
+    assert!(is_thin::<dyn Tr>());
+    assert!(is_thin::<[i32]>());
+    assert!(is_thin::<i32>());
+}
diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md
index d8206e7893114..98fb7e9e41d7a 100644
--- a/library/core/src/macros/panic.md
+++ b/library/core/src/macros/panic.md
@@ -24,20 +24,30 @@ See also the macro [`compile_error!`], for raising errors during compilation.
 
 # When to use `panic!` vs `Result`
 
-The Rust model of error handling groups errors into two major categories:
-recoverable and unrecoverable errors. For a recoverable error, such as a file
-not found error, it’s reasonable to report the problem to the user and retry
-the operation. Unrecoverable errors are always symptoms of bugs, like trying to
-access a location beyond the end of an array.
+The Rust language provides two complementary systems for constructing /
+representing, reporting, propagating, reacting to, and discarding errors. These
+responsibilities are collectively known as "error handling." `panic!` and
+`Result` are similar in that they are each the primary interface of their
+respective error handling systems; however, the meaning these interfaces attach
+to their errors and the responsibilities they fulfill within their respective
+error handling systems differ.
 
-The Rust language and standard library provides `Result` and `panic!` as parts
-of two complementary systems for representing, reporting, propagating, reacting
-to, and discarding errors for in these two categories.
+The `panic!` macro is used to construct errors that represent a bug that has
+been detected in your program. With `panic!` you provide a message that
+describes the bug and the language then constructs an error with that message,
+reports it, and propagates it for you.
 
-The `panic!` macro is provided to represent unrecoverable errors, whereas the
-`Result` enum is provided to represent recoverable errors. For more detailed
-information about error handling check out the [book] or the [`std::result`]
-module docs.
+`Result` on the other hand is used to wrap other types that represent either
+the successful result of some computation, `Ok(T)`, or error types that
+represent an anticipated runtime failure mode of that computation, `Err(E)`.
+`Result` is used alongside user defined types which represent the various
+anticipated runtime failure modes that the associated computation could
+encounter. `Result` must be propagated manually, often with the the help of the
+`?` operator and `Try` trait, and they must be reported manually, often with
+the help of the `Error` trait.
+
+For more detailed information about error handling check out the [book] or the
+[`std::result`] module docs.
 
 [ounwrap]: Option::unwrap
 [runwrap]: Result::unwrap
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index c3cb71a5dee63..4fb94908c80fd 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -516,6 +516,14 @@ impl<T: Error> Error for Box<T> {
     }
 }
 
+#[unstable(feature = "thin_box", issue = "92791")]
+impl<T: ?Sized + crate::error::Error> crate::error::Error for crate::boxed::ThinBox<T> {
+    fn source(&self) -> Option<&(dyn crate::error::Error + 'static)> {
+        use core::ops::Deref;
+        self.deref().source()
+    }
+}
+
 #[stable(feature = "error_by_ref", since = "1.51.0")]
 impl<'a, T: Error + ?Sized> Error for &'a T {
     #[allow(deprecated, deprecated_in_future)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5ade65ad9c629..60e7c2af8e4a5 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -290,6 +290,7 @@
 #![feature(get_mut_unchecked)]
 #![feature(map_try_insert)]
 #![feature(new_uninit)]
+#![feature(thin_box)]
 #![feature(toowned_clone_into)]
 #![feature(try_reserve_kind)]
 #![feature(vec_into_raw_parts)]
diff --git a/src/doc/unstable-book/src/language-features/strict-provenance.md b/src/doc/unstable-book/src/language-features/strict-provenance.md
new file mode 100644
index 0000000000000..dc60f3f375d3c
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/strict-provenance.md
@@ -0,0 +1,22 @@
+# `strict_provenance`
+
+The tracking issue for this feature is: [#95228]
+
+[#95228]: https://github.com/rust-lang/rust/issues/95228
+-----
+
+The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints.
+These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model.
+The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`).
+
+## Example
+
+```rust
+#![feature(strict_provenance)]
+#![warn(fuzzy_provenance_casts)]
+
+fn main() {
+    let _dangling = 16_usize as *const u8;
+    //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8`
+}
+```
diff --git a/src/test/rustdoc/empty-doc-comment.rs b/src/test/rustdoc/empty-doc-comment.rs
new file mode 100644
index 0000000000000..b1dae930e066b
--- /dev/null
+++ b/src/test/rustdoc/empty-doc-comment.rs
@@ -0,0 +1,22 @@
+// Ensure that empty doc comments don't panic.
+
+/*!
+*/
+
+///
+///
+pub struct Foo;
+
+#[doc = "
+"]
+pub mod Mod {
+   //!
+   //!
+}
+
+/**
+*/
+pub mod Another {
+   #![doc = "
+"]
+}
diff --git a/src/test/ui/box/thin_align.rs b/src/test/ui/box/thin_align.rs
new file mode 100644
index 0000000000000..3c61d0090e42b
--- /dev/null
+++ b/src/test/ui/box/thin_align.rs
@@ -0,0 +1,26 @@
+#![feature(thin_box)]
+// run-pass
+use std::boxed::ThinBox;
+use std::error::Error;
+use std::ops::Deref;
+use std::fmt;
+
+fn main() {
+    let expected = "Foo error!";
+    let a: ThinBox<dyn Error> = ThinBox::new_unsize(Foo(expected));
+    let a = a.deref();
+    let msg = a.to_string();
+    assert_eq!(expected, msg);
+}
+
+#[derive(Debug)]
+#[repr(align(1024))]
+struct Foo(&'static str);
+
+impl fmt::Display for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
+
+impl Error for Foo {}
diff --git a/src/test/ui/box/thin_drop.rs b/src/test/ui/box/thin_drop.rs
new file mode 100644
index 0000000000000..965613c114e3a
--- /dev/null
+++ b/src/test/ui/box/thin_drop.rs
@@ -0,0 +1,37 @@
+#![feature(thin_box)]
+// run-pass
+use std::boxed::ThinBox;
+use std::error::Error;
+use std::ops::Deref;
+use std::fmt;
+
+fn main() {
+    let expected = "Foo error!";
+    let mut dropped = false;
+    {
+        let foo = Foo(expected, &mut dropped);
+        let a: ThinBox<dyn Error> = ThinBox::new_unsize(foo);
+        let a = a.deref();
+        let msg = a.to_string();
+        assert_eq!(expected, msg);
+    }
+    assert!(dropped);
+}
+
+#[derive(Debug)]
+#[repr(align(1024))]
+struct Foo<'a>(&'static str, &'a mut bool);
+
+impl Drop for Foo<'_> {
+    fn drop(&mut self) {
+        *self.1 = true;
+    }
+}
+
+impl fmt::Display for Foo<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
+
+impl Error for Foo<'_> {}
diff --git a/src/test/ui/box/thin_new.rs b/src/test/ui/box/thin_new.rs
new file mode 100644
index 0000000000000..53f46478be403
--- /dev/null
+++ b/src/test/ui/box/thin_new.rs
@@ -0,0 +1,30 @@
+#![feature(thin_box)]
+// run-pass
+use std::boxed::ThinBox;
+use std::error::Error;
+use std::{fmt, mem};
+
+fn main() {
+    let thin_error: ThinBox<dyn Error> = ThinBox::new_unsize(Foo);
+    assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error));
+    println!("{:?}", thin_error);
+
+    let thin = ThinBox::new(42i32);
+    assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin));
+    println!("{:?}", thin);
+
+    let thin_slice = ThinBox::<[i32]>::new_unsize([1, 2, 3, 4]);
+    assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_slice));
+    println!("{:?}", thin_slice);
+}
+
+#[derive(Debug)]
+struct Foo;
+
+impl fmt::Display for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "boooo!")
+    }
+}
+
+impl Error for Foo {}
diff --git a/src/test/ui/box/thin_zst.rs b/src/test/ui/box/thin_zst.rs
new file mode 100644
index 0000000000000..77c400d17bbe5
--- /dev/null
+++ b/src/test/ui/box/thin_zst.rs
@@ -0,0 +1,34 @@
+#![feature(thin_box)]
+// run-pass
+use std::boxed::ThinBox;
+use std::error::Error;
+use std::{fmt, mem};
+use std::ops::DerefMut;
+
+const EXPECTED: &str = "boooo!";
+
+fn main() {
+    let thin_error: ThinBox<dyn Error> = ThinBox::new_unsize(Foo);
+    assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_error));
+    let msg = thin_error.to_string();
+    assert_eq!(EXPECTED, msg);
+
+    let mut thin_concrete_error: ThinBox<Foo> = ThinBox::new(Foo);
+    assert_eq!(mem::size_of::<*const i32>(), mem::size_of_val(&thin_concrete_error));
+    let msg = thin_concrete_error.to_string();
+    assert_eq!(EXPECTED, msg);
+    let inner = thin_concrete_error.deref_mut();
+    let msg = inner.to_string();
+    assert_eq!(EXPECTED, msg);
+}
+
+#[derive(Debug)]
+struct Foo;
+
+impl fmt::Display for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", EXPECTED)
+    }
+}
+
+impl Error for Foo {}
diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
index a4b10a4c339f9..1b1ce67cb0c1f 100644
--- a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
+++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr
@@ -13,7 +13,7 @@ LL |     /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x
              BorrowError
              BorrowMutError
              Box<T>
-           and 42 others
+           and 43 others
    = note: required for the cast to the object type `dyn std::error::Error`
 
 error[E0277]: the trait bound `(): std::error::Error` is not satisfied
@@ -31,7 +31,7 @@ LL |     /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
              BorrowError
              BorrowMutError
              Box<T>
-           and 42 others
+           and 43 others
    = note: required for the cast to the object type `(dyn std::error::Error + 'static)`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-strict_provenance.rs b/src/test/ui/feature-gates/feature-gate-strict_provenance.rs
new file mode 100644
index 0000000000000..75d0ee5700d07
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-strict_provenance.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![deny(fuzzy_provenance_casts)]
+//~^ WARNING unknown lint: `fuzzy_provenance_casts`
+//~| WARNING unknown lint: `fuzzy_provenance_casts`
+//~| WARNING unknown lint: `fuzzy_provenance_casts`
+#![deny(lossy_provenance_casts)]
+//~^ WARNING unknown lint: `lossy_provenance_casts`
+//~| WARNING unknown lint: `lossy_provenance_casts`
+//~| WARNING unknown lint: `lossy_provenance_casts`
+
+fn main() {
+    // no warnings emitted since the lints are not activated
+
+    let _dangling = 16_usize as *const u8;
+
+    let x: u8 = 37;
+    let _addr: usize = &x as *const u8 as usize;
+}
diff --git a/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr
new file mode 100644
index 0000000000000..34bd240c304a7
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr
@@ -0,0 +1,63 @@
+warning: unknown lint: `fuzzy_provenance_casts`
+  --> $DIR/feature-gate-strict_provenance.rs:3:1
+   |
+LL | #![deny(fuzzy_provenance_casts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unknown_lints)]` on by default
+   = note: the `fuzzy_provenance_casts` lint is unstable
+   = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
+   = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+
+warning: unknown lint: `lossy_provenance_casts`
+  --> $DIR/feature-gate-strict_provenance.rs:7:1
+   |
+LL | #![deny(lossy_provenance_casts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `lossy_provenance_casts` lint is unstable
+   = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
+   = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+
+warning: unknown lint: `fuzzy_provenance_casts`
+  --> $DIR/feature-gate-strict_provenance.rs:3:1
+   |
+LL | #![deny(fuzzy_provenance_casts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `fuzzy_provenance_casts` lint is unstable
+   = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
+   = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+
+warning: unknown lint: `lossy_provenance_casts`
+  --> $DIR/feature-gate-strict_provenance.rs:7:1
+   |
+LL | #![deny(lossy_provenance_casts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `lossy_provenance_casts` lint is unstable
+   = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
+   = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+
+warning: unknown lint: `fuzzy_provenance_casts`
+  --> $DIR/feature-gate-strict_provenance.rs:3:1
+   |
+LL | #![deny(fuzzy_provenance_casts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `fuzzy_provenance_casts` lint is unstable
+   = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
+   = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+
+warning: unknown lint: `lossy_provenance_casts`
+  --> $DIR/feature-gate-strict_provenance.rs:7:1
+   |
+LL | #![deny(lossy_provenance_casts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the `lossy_provenance_casts` lint is unstable
+   = note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
+   = help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+
+warning: 6 warnings emitted
+
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
index a1cfee944c8bd..98fd13553c009 100644
--- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -104,6 +104,32 @@ fn main() {
             "attempted to instantiate uninhabited type `Bar`"
         );
 
+        test_panic_msg(
+            || mem::uninitialized::<[Foo; 2]>(),
+            "attempted to instantiate uninhabited type `[Foo; 2]`"
+        );
+        test_panic_msg(
+            || mem::zeroed::<[Foo; 2]>(),
+            "attempted to instantiate uninhabited type `[Foo; 2]`"
+        );
+        test_panic_msg(
+            || MaybeUninit::<[Foo; 2]>::uninit().assume_init(),
+            "attempted to instantiate uninhabited type `[Foo; 2]`"
+        );
+
+        test_panic_msg(
+            || mem::uninitialized::<[Bar; 2]>(),
+            "attempted to instantiate uninhabited type `[Bar; 2]`"
+        );
+        test_panic_msg(
+            || mem::zeroed::<[Bar; 2]>(),
+            "attempted to instantiate uninhabited type `[Bar; 2]`"
+        );
+        test_panic_msg(
+            || MaybeUninit::<[Bar; 2]>::uninit().assume_init(),
+            "attempted to instantiate uninhabited type `[Bar; 2]`"
+        );
+
         // Types that do not like zero-initialziation
         test_panic_msg(
             || mem::uninitialized::<fn()>(),
@@ -199,7 +225,9 @@ fn main() {
         let _val = mem::zeroed::<OneVariant>();
         let _val = mem::zeroed::<Option<&'static i32>>();
         let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>();
+        let _val = mem::zeroed::<[!; 0]>();
         let _val = mem::uninitialized::<MaybeUninit<bool>>();
+        let _val = mem::uninitialized::<[!; 0]>();
 
         // These are UB because they have not been officially blessed, but we await the resolution
         // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing
diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs
new file mode 100644
index 0000000000000..d2d72a68f1396
--- /dev/null
+++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.rs
@@ -0,0 +1,7 @@
+#![feature(strict_provenance)]
+#![deny(fuzzy_provenance_casts)]
+
+fn main() {
+    let dangling = 16_usize as *const u8;
+    //~^ ERROR strict provenance disallows casting integer `usize` to pointer `*const u8`
+}
diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
new file mode 100644
index 0000000000000..e50d243b6ad6d
--- /dev/null
+++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
@@ -0,0 +1,19 @@
+error: strict provenance disallows casting integer `usize` to pointer `*const u8`
+  --> $DIR/lint-strict-provenance-fuzzy-casts.rs:5:20
+   |
+LL |     let dangling = 16_usize as *const u8;
+   |                    ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-strict-provenance-fuzzy-casts.rs:2:9
+   |
+LL | #![deny(fuzzy_provenance_casts)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead
+help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
+   |
+LL |     let dangling = (...).with_addr(16_usize);
+   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs
new file mode 100644
index 0000000000000..3690fbc904d99
--- /dev/null
+++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.rs
@@ -0,0 +1,11 @@
+#![feature(strict_provenance)]
+#![deny(lossy_provenance_casts)]
+
+fn main() {
+    let x: u8 = 37;
+    let addr: usize = &x as *const u8 as usize;
+    //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
+
+    let addr_32bit = &x as *const u8 as u32;
+    //~^ ERROR under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
+}
diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr
new file mode 100644
index 0000000000000..489cb03ddd316
--- /dev/null
+++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr
@@ -0,0 +1,23 @@
+error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `usize`
+  --> $DIR/lint-strict-provenance-lossy-casts.rs:6:23
+   |
+LL |     let addr: usize = &x as *const u8 as usize;
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr()`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
+   |
+LL | #![deny(lossy_provenance_casts)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead
+
+error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32`
+  --> $DIR/lint-strict-provenance-lossy-casts.rs:9:22
+   |
+LL |     let addr_32bit = &x as *const u8 as u32;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32`
+   |
+   = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs
index cff6f29a15386..b4fef11f1e29a 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs
@@ -5,5 +5,40 @@ macro_rules! count {
     };
 }
 
+macro_rules! dollar_dollar {
+    () => {
+        macro_rules! bar {
+            ( $$( $$any:tt )* ) => { $$( $$any )* };
+            //~^ ERROR meta-variable expressions are unstable
+            //~| ERROR meta-variable expressions are unstable
+            //~| ERROR meta-variable expressions are unstable
+            //~| ERROR meta-variable expressions are unstable
+        }
+    };
+}
+
+macro_rules! index {
+    ( $( $e:stmt ),* ) => {
+        $( ${ignore(e)} ${index()} )*
+        //~^ ERROR meta-variable expressions are unstable
+        //~| ERROR meta-variable expressions are unstable
+    };
+}
+
+macro_rules! ignore {
+    ( $( $i:stmt ),* ) => {{
+        0 $( + 1 ${ignore(i)} )*
+        //~^ ERROR meta-variable expressions are unstable
+    }};
+}
+
+macro_rules! length {
+    ( $( $e:stmt ),* ) => {
+        $( ${ignore(e)} ${length()} )*
+        //~^ ERROR meta-variable expressions are unstable
+        //~| ERROR meta-variable expressions are unstable
+    };
+}
+
 fn main() {
 }
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
index f573194479314..ecf598b104d05 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
@@ -7,6 +7,87 @@ LL |         ${ count(e) }
    = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:11:16
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:11:20
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                    ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:11:39
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                                       ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:11:43
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                                           ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:22:13
+   |
+LL |         $( ${ignore(e)} ${index()} )*
+   |             ^^^^^^^^^^^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:22:26
+   |
+LL |         $( ${ignore(e)} ${index()} )*
+   |                          ^^^^^^^^^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:30:19
+   |
+LL |         0 $( + 1 ${ignore(i)} )*
+   |                   ^^^^^^^^^^^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:37:13
+   |
+LL |         $( ${ignore(e)} ${length()} )*
+   |             ^^^^^^^^^^^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:37:26
+   |
+LL |         $( ${ignore(e)} ${length()} )*
+   |                          ^^^^^^^^^^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/traits/no-fallback-multiple-impls.rs b/src/test/ui/traits/no-fallback-multiple-impls.rs
new file mode 100644
index 0000000000000..7ed3796f08b76
--- /dev/null
+++ b/src/test/ui/traits/no-fallback-multiple-impls.rs
@@ -0,0 +1,16 @@
+trait Fallback {
+    fn foo(&self) {}
+}
+
+impl Fallback for i32 {}
+
+impl Fallback for u64 {}
+
+impl Fallback for usize {}
+
+fn main() {
+    missing();
+    //~^ ERROR cannot find function `missing` in this scope
+    0.foo();
+    // But then we shouldn't report an inference ambiguity here...
+}
diff --git a/src/test/ui/traits/no-fallback-multiple-impls.stderr b/src/test/ui/traits/no-fallback-multiple-impls.stderr
new file mode 100644
index 0000000000000..61c9e5aaabdb4
--- /dev/null
+++ b/src/test/ui/traits/no-fallback-multiple-impls.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `missing` in this scope
+  --> $DIR/no-fallback-multiple-impls.rs:12:5
+   |
+LL |     missing();
+   |     ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/traits/test-2.rs b/src/test/ui/traits/test-2.rs
index d062de25ac8c1..342928e882a55 100644
--- a/src/test/ui/traits/test-2.rs
+++ b/src/test/ui/traits/test-2.rs
@@ -6,9 +6,9 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
 impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
 
 fn main() {
-    10.dup::<i32>(); //~ ERROR type annotations needed
+    10.dup::<i32>();
     //~^ ERROR this associated function takes 0 generic arguments but 1
-    10.blah::<i32, i32>(); //~ ERROR type annotations needed
+    10.blah::<i32, i32>();
     //~^ ERROR this associated function takes 1 generic argument but 2
     (Box::new(10) as Box<dyn bar>).dup();
     //~^ ERROR E0038
diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr
index 5eec012458450..77ea4e4e974eb 100644
--- a/src/test/ui/traits/test-2.stderr
+++ b/src/test/ui/traits/test-2.stderr
@@ -79,35 +79,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
    = note: required by cast to type `Box<dyn bar>`
 
-error[E0283]: type annotations needed
-  --> $DIR/test-2.rs:9:8
-   |
-LL |     10.dup::<i32>();
-   |        ^^^ cannot infer type for type `{integer}`
-   |
-note: multiple `impl`s satisfying `{integer}: bar` found
-  --> $DIR/test-2.rs:5:1
-   |
-LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-
-error[E0283]: type annotations needed
-  --> $DIR/test-2.rs:11:8
-   |
-LL |     10.blah::<i32, i32>();
-   |        ^^^^ cannot infer type for type `{integer}`
-   |
-note: multiple `impl`s satisfying `{integer}: bar` found
-  --> $DIR/test-2.rs:5:1
-   |
-LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0038, E0107, E0283.
+Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.