about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-11 04:17:59 +0000
committerbors <bors@rust-lang.org>2023-03-11 04:17:59 +0000
commit19c53768af6e48514238e4224b5bf5ecd51bc7b1 (patch)
treedcad99f978c904d3aa291e228060729425904476
parent6dfaa143662ddfd6ed2fecadef20eae0ec5d267d (diff)
parentf74bb35dad1474cdc8bef411ab95cb04fb6a7bdd (diff)
downloadrust-19c53768af6e48514238e4224b5bf5ecd51bc7b1.tar.gz
rust-19c53768af6e48514238e4224b5bf5ecd51bc7b1.zip
Auto merge of #108998 - matthiaskrgr:rollup-sxbdulg, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #106921 (Add documentation about the memory layout of `Cell`)
 - #108828 (Emit alias-eq when equating numeric var and projection)
 - #108834 (Do not ICE when we have fn pointer `Fn` obligations with bound vars in the self type)
 - #108900 (fix(lexer): print whitespace warning for \x0c)
 - #108930 (feat: implement better error for manual impl of `Fn*` traits)
 - #108937 (improve readability of winnowing)
 - #108947 (Don't even try to combine consts with incompatible types)
 - #108976 (Update triagebot rust-analyzer team mention)
 - #108983 (Forbid `#[target_feature]` on safe default implementations)

Failed merges:

 - #108950 (Directly construct Inherited in typeck.)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs2
-rw-r--r--compiler/rustc_hir_analysis/locales/en-US.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs107
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs7
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs31
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs48
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs22
-rw-r--r--compiler/rustc_lexer/src/unescape.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs9
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_parse/locales/en-US.ftl2
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs107
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs6
-rw-r--r--library/core/src/cell.rs6
-rw-r--r--tests/ui/const-generics/type_mismatch.rs1
-rw-r--r--tests/ui/const-generics/type_mismatch.stderr18
-rw-r--r--tests/ui/const-generics/type_not_in_scope.rs1
-rw-r--r--tests/ui/const-generics/type_not_in_scope.stderr14
-rw-r--r--tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr6
-rw-r--r--tests/ui/fn/issue-39259.rs13
-rw-r--r--tests/ui/fn/issue-39259.stderr15
-rw-r--r--tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr19
-rw-r--r--tests/ui/higher-rank-trait-bounds/fn-ptr.rs14
-rw-r--r--tests/ui/issues/issue-66667-function-cmp-cycle.rs3
-rw-r--r--tests/ui/issues/issue-66667-function-cmp-cycle.stderr34
-rw-r--r--tests/ui/lifetimes/issue-95023.stderr6
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs6
-rw-r--r--tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr11
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs12
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr11
-rw-r--r--tests/ui/str/str-escape.rs22
-rw-r--r--tests/ui/str/str-escape.stderr20
-rw-r--r--tests/ui/traits/issue-87558.stderr6
-rw-r--r--tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs21
-rw-r--r--tests/ui/traits/new-solver/int-var-alias-eq.rs18
-rw-r--r--tests/ui/transmutability/issue-101739-1.rs2
-rw-r--r--tests/ui/transmutability/issue-101739-1.stderr12
-rw-r--r--tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs2
-rw-r--r--tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr9
-rw-r--r--triagebot.toml2
45 files changed, 534 insertions, 181 deletions
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 576e90ae66b..679dc0866f2 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -442,7 +442,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
 pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
     if let DefKind::AssocFn = tcx.def_kind(id) {
         let parent_id = tcx.local_parent(id);
-        if let DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
+        if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
             tcx.sess
                 .struct_span_err(
                     attr_span,
diff --git a/compiler/rustc_hir_analysis/locales/en-US.ftl b/compiler/rustc_hir_analysis/locales/en-US.ftl
index df428816444..dbe15ed5e9b 100644
--- a/compiler/rustc_hir_analysis/locales/en-US.ftl
+++ b/compiler/rustc_hir_analysis/locales/en-US.ftl
@@ -42,6 +42,9 @@ hir_analysis_assoc_type_binding_not_allowed =
     associated type bindings are not allowed here
     .label = associated type not allowed here
 
+hir_analysis_parenthesized_fn_trait_expansion =
+    parenthesized trait syntax expands to `{$expanded_type}`
+
 hir_analysis_typeof_reserved_keyword_used =
     `typeof` is a reserved keyword but unimplemented
     .suggestion = consider replacing `typeof(...)` with an actual type
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index c49e4d9d581..156334fe785 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -1,10 +1,14 @@
 use crate::astconv::AstConv;
-use crate::errors::{ManualImplementation, MissingTypeParams};
+use crate::errors::{
+    AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
+    ParenthesizedFnTraitExpansion,
+};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::traits::FulfillmentError;
+use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::parse::feature_err;
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -78,43 +82,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             // Do not suggest the other syntax if we are in trait impl:
             // the desugaring would contain an associated type constraint.
             if !is_impl {
-                let args = trait_segment
-                    .args
-                    .as_ref()
-                    .and_then(|args| args.args.get(0))
-                    .and_then(|arg| match arg {
-                        hir::GenericArg::Type(ty) => match ty.kind {
-                            hir::TyKind::Tup(t) => t
-                                .iter()
-                                .map(|e| sess.source_map().span_to_snippet(e.span))
-                                .collect::<Result<Vec<_>, _>>()
-                                .map(|a| a.join(", ")),
-                            _ => sess.source_map().span_to_snippet(ty.span),
-                        }
-                        .map(|s| format!("({})", s))
-                        .ok(),
-                        _ => None,
-                    })
-                    .unwrap_or_else(|| "()".to_string());
-                let ret = trait_segment
-                    .args()
-                    .bindings
-                    .iter()
-                    .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
-                        (true, hir::TypeBindingKind::Equality { term }) => {
-                            let span = match term {
-                                hir::Term::Ty(ty) => ty.span,
-                                hir::Term::Const(c) => self.tcx().hir().span(c.hir_id),
-                            };
-                            sess.source_map().span_to_snippet(span).ok()
-                        }
-                        _ => None,
-                    })
-                    .unwrap_or_else(|| "()".to_string());
                 err.span_suggestion(
                     span,
                     "use parenthetical notation instead",
-                    format!("{}{} -> {}", trait_segment.ident, args, ret),
+                    fn_trait_to_string(self.tcx(), trait_segment, true),
                     Applicability::MaybeIncorrect,
                 );
             }
@@ -629,3 +600,69 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         err.emit();
     }
 }
+
+/// Emits an error regarding forbidden type binding associations
+pub fn prohibit_assoc_ty_binding(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    segment: Option<(&hir::PathSegment<'_>, Span)>,
+) {
+    tcx.sess.emit_err(AssocTypeBindingNotAllowed { span, fn_trait_expansion: if let Some((segment, span)) = segment && segment.args().parenthesized {
+        Some(ParenthesizedFnTraitExpansion { span, expanded_type: fn_trait_to_string(tcx, segment, false) })
+    } else {
+        None
+    }});
+}
+
+pub(crate) fn fn_trait_to_string(
+    tcx: TyCtxt<'_>,
+    trait_segment: &hir::PathSegment<'_>,
+    parenthesized: bool,
+) -> String {
+    let args = trait_segment
+        .args
+        .as_ref()
+        .and_then(|args| args.args.get(0))
+        .and_then(|arg| match arg {
+            hir::GenericArg::Type(ty) => match ty.kind {
+                hir::TyKind::Tup(t) => t
+                    .iter()
+                    .map(|e| tcx.sess.source_map().span_to_snippet(e.span))
+                    .collect::<Result<Vec<_>, _>>()
+                    .map(|a| a.join(", ")),
+                _ => tcx.sess.source_map().span_to_snippet(ty.span),
+            }
+            .map(|s| {
+                // `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma
+                if parenthesized || s.is_empty() { format!("({})", s) } else { format!("({},)", s) }
+            })
+            .ok(),
+            _ => None,
+        })
+        .unwrap_or_else(|| "()".to_string());
+
+    let ret = trait_segment
+        .args()
+        .bindings
+        .iter()
+        .find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
+            (true, hir::TypeBindingKind::Equality { term }) => {
+                let span = match term {
+                    hir::Term::Ty(ty) => ty.span,
+                    hir::Term::Const(c) => tcx.hir().span(c.hir_id),
+                };
+
+                (span != tcx.hir().span(trait_segment.hir_id))
+                    .then_some(tcx.sess.source_map().span_to_snippet(span).ok())
+                    .flatten()
+            }
+            _ => None,
+        })
+        .unwrap_or_else(|| "()".to_string());
+
+    if parenthesized {
+        format!("{}{} -> {}", trait_segment.ident, args, ret)
+    } else {
+        format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 7f6518ffd71..2f4963f6bc3 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -1,9 +1,8 @@
 use super::IsMethodCall;
 use crate::astconv::{
-    CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
-    GenericArgCountResult, GenericArgPosition,
+    errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound,
+    GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
 };
-use crate::errors::AssocTypeBindingNotAllowed;
 use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
 use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
@@ -433,7 +432,7 @@ pub(crate) fn check_generic_arg_count(
         (gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
 
     if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
-            prohibit_assoc_ty_binding(tcx, b.span);
+             prohibit_assoc_ty_binding(tcx, b.span, None);
         }
 
     let explicit_late_bound =
@@ -589,11 +588,6 @@ pub(crate) fn check_generic_arg_count(
     }
 }
 
-/// Emits an error regarding forbidden type binding associations
-pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
-    tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });
-}
-
 /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
 /// are present. This is used both for datatypes and function calls.
 pub(crate) fn prohibit_explicit_late_bound_lifetimes(
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 899029d98e0..5db404608b3 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -5,9 +5,8 @@
 mod errors;
 pub mod generics;
 
-use crate::astconv::generics::{
-    check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
-};
+use crate::astconv::errors::prohibit_assoc_ty_binding;
+use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
 use crate::bounds::Bounds;
 use crate::collect::HirPlaceholderCollector;
 use crate::errors::{
@@ -295,7 +294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             ty::BoundConstness::NotConst,
         );
         if let Some(b) = item_segment.args().bindings.first() {
-            prohibit_assoc_ty_binding(self.tcx(), b.span);
+            prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
         }
 
         substs
@@ -631,7 +630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         );
 
         if let Some(b) = item_segment.args().bindings.first() {
-            prohibit_assoc_ty_binding(self.tcx(), b.span);
+            prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
         }
 
         args
@@ -825,7 +824,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             constness,
         );
         if let Some(b) = trait_segment.args().bindings.first() {
-            prohibit_assoc_ty_binding(self.tcx(), b.span);
+            prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
         }
         self.tcx().mk_trait_ref(trait_def_id, substs)
     }
@@ -2596,7 +2595,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         for segment in segments {
             // Only emit the first error to avoid overloading the user with error messages.
             if let Some(b) = segment.args().bindings.first() {
-                prohibit_assoc_ty_binding(self.tcx(), b.span);
+                prohibit_assoc_ty_binding(self.tcx(), b.span, None);
                 return true;
             }
         }
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index dd40706f1d3..8a697b4c514 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -129,6 +129,18 @@ pub struct AssocTypeBindingNotAllowed {
     #[primary_span]
     #[label]
     pub span: Span,
+
+    #[subdiagnostic]
+    pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(hir_analysis_parenthesized_fn_trait_expansion)]
+pub struct ParenthesizedFnTraitExpansion {
+    #[primary_span]
+    pub span: Span,
+
+    pub expanded_type: String,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index eecded557a5..37783bc91bb 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -148,10 +148,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         rhs_ty,
                         op,
                     );
-                    self.demand_suptype(expr.span, builtin_return_ty, return_ty);
+                    self.demand_eqtype(expr.span, builtin_return_ty, return_ty);
+                    builtin_return_ty
+                } else {
+                    return_ty
                 }
-
-                return_ty
             }
         }
     }
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index a43330e2d4e..8ac82653c0e 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -411,15 +411,28 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
                 }
             }
 
-            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
-                CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
-                t,
-            ),
-
-            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
-                CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
-                t,
-            ),
+            ty::Infer(ty::IntVar(vid)) => {
+                let nt = self.infcx.opportunistic_resolve_int_var(vid);
+                if nt != t {
+                    return self.fold_ty(nt);
+                } else {
+                    self.canonicalize_ty_var(
+                        CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
+                        t,
+                    )
+                }
+            }
+            ty::Infer(ty::FloatVar(vid)) => {
+                let nt = self.infcx.opportunistic_resolve_float_var(vid);
+                if nt != t {
+                    return self.fold_ty(nt);
+                } else {
+                    self.canonicalize_ty_var(
+                        CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
+                        t,
+                    )
+                }
+            }
 
             ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("encountered a fresh type during canonicalization")
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 33292e871b1..a2332797e86 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -34,7 +34,6 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::infer::canonical::OriginalQueryValues;
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -119,20 +118,30 @@ impl<'tcx> InferCtxt<'tcx> {
                 self.unify_float_variable(!a_is_expected, v_id, v)
             }
 
-            // All other cases of inference are errors
-            (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
-                Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
+            // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm.
+            (
+                ty::Alias(AliasKind::Projection, _),
+                ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
+            )
+            | (
+                ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)),
+                ty::Alias(AliasKind::Projection, _),
+            ) if self.tcx.trait_solver_next() => {
+                bug!()
             }
 
-            (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
+            (_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
+                if self.tcx.trait_solver_next() =>
+            {
                 relation.register_type_equate_obligation(a, b);
-                Ok(b)
-            }
-            (_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
-                relation.register_type_equate_obligation(b, a);
                 Ok(a)
             }
 
+            // All other cases of inference are errors
+            (&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
+                Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
+            }
+
             _ => ty::relate::super_relate_tys(relation, a, b),
         }
     }
@@ -161,9 +170,9 @@ impl<'tcx> InferCtxt<'tcx> {
         //
         // This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
         // ourselves with a check to find bugs being required for code to compile because it made inference progress.
-        self.probe(|_| {
+        let compatible_types = self.probe(|_| {
             if a.ty() == b.ty() {
-                return;
+                return Ok(());
             }
 
             // We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
@@ -173,15 +182,24 @@ impl<'tcx> InferCtxt<'tcx> {
                 (relation.param_env(), a.ty(), b.ty()),
                 &mut OriginalQueryValues::default(),
             );
-
-            if let Err(NoSolution) = self.tcx.check_tys_might_be_eq(canonical) {
+            self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
                 self.tcx.sess.delay_span_bug(
                     DUMMY_SP,
                     &format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
-                );
-            }
+                )
+            })
         });
 
+        // If the consts have differing types, just bail with a const error with
+        // the expected const's type. Specifically, we don't want const infer vars
+        // to do any type shapeshifting before and after resolution.
+        if let Err(guar) = compatible_types {
+            return Ok(self.tcx.const_error_with_guaranteed(
+                if relation.a_is_expected() { a.ty() } else { b.ty() },
+                guar,
+            ));
+        }
+
         match (a.kind(), b.kind()) {
             (
                 ty::ConstKind::Infer(InferConst::Var(a_vid)),
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 4a2a5557313..4a834957959 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1363,6 +1363,28 @@ impl<'tcx> InferCtxt<'tcx> {
         self.inner.borrow_mut().const_unification_table().find(var)
     }
 
+    /// Resolves an int var to a rigid int type, if it was constrained to one,
+    /// or else the root int var in the unification table.
+    pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
+        let mut inner = self.inner.borrow_mut();
+        if let Some(value) = inner.int_unification_table().probe_value(vid) {
+            value.to_type(self.tcx)
+        } else {
+            self.tcx.mk_int_var(inner.int_unification_table().find(vid))
+        }
+    }
+
+    /// Resolves a float var to a rigid int type, if it was constrained to one,
+    /// or else the root float var in the unification table.
+    pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
+        let mut inner = self.inner.borrow_mut();
+        if let Some(value) = inner.float_unification_table().probe_value(vid) {
+            value.to_type(self.tcx)
+        } else {
+            self.tcx.mk_float_var(inner.float_unification_table().find(vid))
+        }
+    }
+
     /// Where possible, replaces type/const variables in
     /// `value` with their final value. Note that region variables
     /// are unaffected. If a type/const variable has not been unified, it
diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index 8507ca9d89e..bb4d91247b8 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -298,10 +298,10 @@ where
         }
         let tail = &tail[first_non_space..];
         if let Some(c) = tail.chars().nth(0) {
-            // For error reporting, we would like the span to contain the character that was not
-            // skipped. The +1 is necessary to account for the leading \ that started the escape.
-            let end = start + first_non_space + c.len_utf8() + 1;
             if c.is_whitespace() {
+                // For error reporting, we would like the span to contain the character that was not
+                // skipped. The +1 is necessary to account for the leading \ that started the escape.
+                let end = start + first_non_space + c.len_utf8() + 1;
                 callback(start..end, Err(EscapeError::UnskippedWhitespaceWarning));
             }
         }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 5d0cf23280b..42101f6b931 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -135,6 +135,9 @@ impl<'tcx> Const<'tcx> {
                 _,
                 &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
             )) => {
+                // Use the type from the param's definition, since we can resolve it,
+                // not the expected parameter type from WithOptConstParam.
+                let param_ty = tcx.type_of(def_id).subst_identity();
                 match tcx.named_bound_var(expr.hir_id) {
                     Some(rbv::ResolvedArg::EarlyBound(_)) => {
                         // Find the name and index of the const parameter by indexing the generics of
@@ -143,14 +146,14 @@ impl<'tcx> Const<'tcx> {
                         let generics = tcx.generics_of(item_def_id);
                         let index = generics.param_def_id_to_index[&def_id];
                         let name = tcx.item_name(def_id);
-                        Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
+                        Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
                     }
                     Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
                         ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
-                        ty,
+                        param_ty,
                     )),
                     Some(rbv::ResolvedArg::Error(guar)) => {
-                        Some(tcx.const_error_with_guaranteed(ty, guar))
+                        Some(tcx.const_error_with_guaranteed(param_ty, guar))
                     }
                     arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
                 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 8cc8a0573bb..d9bfacd6e3c 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -995,7 +995,7 @@ impl<'tcx> Term<'tcx> {
 
     pub fn is_infer(&self) -> bool {
         match self.unpack() {
-            TermKind::Ty(ty) => ty.is_ty_or_numeric_infer(),
+            TermKind::Ty(ty) => ty.is_ty_var(),
             TermKind::Const(ct) => ct.is_ct_infer(),
         }
     }
diff --git a/compiler/rustc_parse/locales/en-US.ftl b/compiler/rustc_parse/locales/en-US.ftl
index 5c7dc1e2abf..ab7931d74d7 100644
--- a/compiler/rustc_parse/locales/en-US.ftl
+++ b/compiler/rustc_parse/locales/en-US.ftl
@@ -709,7 +709,7 @@ parse_zero_chars = empty character literal
 parse_lone_slash = invalid trailing slash in literal
     .label = {parse_lone_slash}
 
-parse_unskipped_whitespace = non-ASCII whitespace symbol '{$ch}' is not skipped
+parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
     .label = {parse_unskipped_whitespace}
 
 parse_multiple_skipped_lines = multiple lines skipped by escaped newline
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
index 981a8f45e45..7ee4f332306 100644
--- a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
@@ -278,16 +278,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
                     Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
                 }
             }
-            ty::Infer(ty::IntVar(_)) => {
-                let nt = self.infcx.shallow_resolve(t);
+            ty::Infer(ty::IntVar(vid)) => {
+                let nt = self.infcx.opportunistic_resolve_int_var(vid);
                 if nt != t {
                     return self.fold_ty(nt);
                 } else {
                     CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
                 }
             }
-            ty::Infer(ty::FloatVar(_)) => {
-                let nt = self.infcx.shallow_resolve(t);
+            ty::Infer(ty::FloatVar(vid)) => {
+                let nt = self.infcx.opportunistic_resolve_float_var(vid);
                 if nt != t {
                     return self.fold_ty(nt);
                 } else {
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 21c158fd0fd..ee41d840bae 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -601,10 +601,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!(?obligation, "confirm_fn_pointer_candidate");
 
         let tcx = self.tcx();
-        let self_ty = self
+
+        let Some(self_ty) = self
             .infcx
-            .shallow_resolve(obligation.self_ty().no_bound_vars())
-            .expect("fn pointer should not capture bound vars from predicate");
+            .shallow_resolve(obligation.self_ty().no_bound_vars()) else
+        {
+            // FIXME: Ideally we'd support `for<'a> fn(&'a ()): Fn(&'a ())`,
+            // but we do not currently. Luckily, such a bound is not
+            // particularly useful, so we don't expect users to write
+            // them often.
+            return Err(SelectionError::Unimplemented);
+        };
+
         let sig = self_ty.fn_sig(tcx);
         let trait_ref = closure_trait_ref_and_return_type(
             tcx,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 48c3b3601b4..ba4df2b3720 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -465,14 +465,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         if candidates.len() > 1 {
             let mut i = 0;
             while i < candidates.len() {
-                let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
+                let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| {
                     self.candidate_should_be_dropped_in_favor_of(
                         &candidates[i],
                         &candidates[j],
                         needs_infer,
-                    )
+                    ) == DropVictim::Yes
                 });
-                if is_dup {
+                if should_drop_i {
                     debug!(candidate = ?candidates[i], "Dropping candidate #{}/{}", i, candidates.len());
                     candidates.swap_remove(i);
                 } else {
@@ -1842,16 +1842,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ProjectionMatchesProjection::No
         }
     }
+}
 
-    ///////////////////////////////////////////////////////////////////////////
-    // WINNOW
-    //
-    // Winnowing is the process of attempting to resolve ambiguity by
-    // probing further. During the winnowing process, we unify all
-    // type variables and then we also attempt to evaluate recursive
-    // bounds to see if they are satisfied.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+enum DropVictim {
+    Yes,
+    No,
+}
 
-    /// Returns `true` if `victim` should be dropped in favor of
+/// ## Winnowing
+///
+/// Winnowing is the process of attempting to resolve ambiguity by
+/// probing further. During the winnowing process, we unify all
+/// type variables and then we also attempt to evaluate recursive
+/// bounds to see if they are satisfied.
+impl<'tcx> SelectionContext<'_, 'tcx> {
+    /// Returns `DropVictim::Yes` if `victim` should be dropped in favor of
     /// `other`. Generally speaking we will drop duplicate
     /// candidates and prefer where-clause candidates.
     ///
@@ -1861,9 +1867,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         victim: &EvaluatedCandidate<'tcx>,
         other: &EvaluatedCandidate<'tcx>,
         needs_infer: bool,
-    ) -> bool {
+    ) -> DropVictim {
         if victim.candidate == other.candidate {
-            return true;
+            return DropVictim::Yes;
         }
 
         // Check if a bound would previously have been removed when normalizing
@@ -1887,11 +1893,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // FIXME(@jswrenn): this should probably be more sophisticated
-            (TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => false,
+            (TransmutabilityCandidate, _) | (_, TransmutabilityCandidate) => DropVictim::No,
 
             // (*)
-            (BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => true,
-            (_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => false,
+            (BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_), _) => {
+                DropVictim::Yes
+            }
+            (_, BuiltinCandidate { has_nested: false } | ConstDestructCandidate(_)) => {
+                DropVictim::No
+            }
 
             (ParamCandidate(other), ParamCandidate(victim)) => {
                 let same_except_bound_vars = other.skip_binder().trait_ref
@@ -1905,28 +1915,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // or the current one if tied (they should both evaluate to the same answer). This is
                     // probably best characterized as a "hack", since we might prefer to just do our
                     // best to *not* create essentially duplicate candidates in the first place.
-                    other.bound_vars().len() <= victim.bound_vars().len()
+                    if other.bound_vars().len() <= victim.bound_vars().len() {
+                        DropVictim::Yes
+                    } else {
+                        DropVictim::No
+                    }
                 } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
                     && victim.skip_binder().constness == ty::BoundConstness::NotConst
                     && other.skip_binder().polarity == victim.skip_binder().polarity
                 {
                     // Drop otherwise equivalent non-const candidates in favor of const candidates.
-                    true
+                    DropVictim::Yes
                 } else {
-                    false
+                    DropVictim::No
                 }
             }
 
             // Drop otherwise equivalent non-const fn pointer candidates
-            (FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true,
+            (FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => DropVictim::Yes,
 
-            // Global bounds from the where clause should be ignored
-            // here (see issue #50825). Otherwise, we have a where
-            // clause so don't go around looking for impls.
-            // Arbitrarily give param candidates priority
-            // over projection and object candidates.
             (
-                ParamCandidate(ref cand),
+                ParamCandidate(ref other_cand),
                 ImplCandidate(..)
                 | ClosureCandidate { .. }
                 | GeneratorCandidate
@@ -1939,11 +1948,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | TraitAliasCandidate
                 | ObjectCandidate(_)
                 | ProjectionCandidate(..),
-            ) => !is_global(cand),
-            (ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref cand)) => {
+            ) => {
+                if is_global(other_cand) {
+                    DropVictim::No
+                } else {
+                    // We have a where clause so don't go around looking
+                    // for impls. Arbitrarily give param candidates priority
+                    // over projection and object candidates.
+                    //
+                    // Global bounds from the where clause should be ignored
+                    // here (see issue #50825).
+                    DropVictim::Yes
+                }
+            }
+            (ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref victim_cand)) => {
                 // Prefer these to a global where-clause bound
                 // (see issue #50825).
-                is_global(cand)
+                if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
             }
             (
                 ImplCandidate(_)
@@ -1956,18 +1977,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { has_nested: true }
                 | TraitAliasCandidate,
-                ParamCandidate(ref cand),
+                ParamCandidate(ref victim_cand),
             ) => {
                 // Prefer these to a global where-clause bound
                 // (see issue #50825).
-                is_global(cand) && other.evaluation.must_apply_modulo_regions()
+                if is_global(victim_cand) && other.evaluation.must_apply_modulo_regions() {
+                    DropVictim::Yes
+                } else {
+                    DropVictim::No
+                }
             }
 
             (ProjectionCandidate(i, _), ProjectionCandidate(j, _))
             | (ObjectCandidate(i), ObjectCandidate(j)) => {
                 // Arbitrarily pick the lower numbered candidate for backwards
                 // compatibility reasons. Don't let this affect inference.
-                i < j && !needs_infer
+                if i < j && !needs_infer { DropVictim::Yes } else { DropVictim::No }
             }
             (ObjectCandidate(_), ProjectionCandidate(..))
             | (ProjectionCandidate(..), ObjectCandidate(_)) => {
@@ -1987,7 +2012,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { .. }
                 | TraitAliasCandidate,
-            ) => true,
+            ) => DropVictim::Yes,
 
             (
                 ImplCandidate(..)
@@ -2001,7 +2026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | BuiltinCandidate { .. }
                 | TraitAliasCandidate,
                 ObjectCandidate(_) | ProjectionCandidate(..),
-            ) => false,
+            ) => DropVictim::No,
 
             (&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
                 // See if we can toss out `victim` based on specialization.
@@ -2014,7 +2039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let tcx = self.tcx();
                 if other.evaluation.must_apply_modulo_regions() {
                     if tcx.specializes((other_def, victim_def)) {
-                        return true;
+                        return DropVictim::Yes;
                     }
                 }
 
@@ -2060,13 +2085,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             // will then correctly report an inference error, since the
                             // existence of multiple marker trait impls tells us nothing
                             // about which one should actually apply.
-                            !needs_infer
+                            if needs_infer { DropVictim::No } else { DropVictim::Yes }
                         }
-                        Some(_) => true,
-                        None => false,
+                        Some(_) => DropVictim::Yes,
+                        None => DropVictim::No,
                     }
                 } else {
-                    false
+                    DropVictim::No
                 }
             }
 
@@ -2092,10 +2117,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { has_nested: true }
                 | TraitAliasCandidate,
-            ) => false,
+            ) => DropVictim::No,
         }
     }
+}
 
+impl<'tcx> SelectionContext<'_, 'tcx> {
     fn sized_conditions(
         &mut self,
         obligation: &TraitObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index d1d6a7a90cf..fcfb60b2603 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -99,10 +99,10 @@ pub fn translate_substs<'tcx>(
             }
 
             fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
-                |_| {
+                |()| {
                     bug!(
-                        "When translating substitutions for specialization, the expected \
-                         specialization failed to hold"
+                        "When translating substitutions from {source_impl:?} to {target_impl:?}, \
+                        the expected specialization failed to hold"
                     )
                 },
             )
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 897d03595d7..9d1720acf36 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -209,6 +209,12 @@ pub use once::OnceCell;
 
 /// A mutable memory location.
 ///
+/// # Memory layout
+///
+/// `Cell<T>` has the same [memory layout and caveats as
+/// `UnsafeCell<T>`](UnsafeCell#memory-layout). In particular, this means that
+/// `Cell<T>` has the same in-memory representation as its inner type `T`.
+///
 /// # Examples
 ///
 /// In this example, you can see that `Cell<T>` enables mutation inside an
diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs
index 4a7534e3713..daa13277be0 100644
--- a/tests/ui/const-generics/type_mismatch.rs
+++ b/tests/ui/const-generics/type_mismatch.rs
@@ -1,5 +1,6 @@
 fn foo<const N: usize>() -> [u8; N] {
     bar::<N>() //~ ERROR mismatched types
+    //~^ ERROR the constant `N` is not of type `u8`
 }
 
 fn bar<const N: u8>() -> [u8; N] {}
diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr
index b28ae8f7e71..6d8955e411e 100644
--- a/tests/ui/const-generics/type_mismatch.stderr
+++ b/tests/ui/const-generics/type_mismatch.stderr
@@ -1,3 +1,15 @@
+error: the constant `N` is not of type `u8`
+  --> $DIR/type_mismatch.rs:2:5
+   |
+LL |     bar::<N>()
+   |     ^^^^^^^^
+   |
+note: required by a bound in `bar`
+  --> $DIR/type_mismatch.rs:6:8
+   |
+LL | fn bar<const N: u8>() -> [u8; N] {}
+   |        ^^^^^^^^^^^ required by this bound in `bar`
+
 error[E0308]: mismatched types
   --> $DIR/type_mismatch.rs:2:11
    |
@@ -5,7 +17,7 @@ LL |     bar::<N>()
    |           ^ expected `u8`, found `usize`
 
 error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:5:26
+  --> $DIR/type_mismatch.rs:6:26
    |
 LL | fn bar<const N: u8>() -> [u8; N] {}
    |    ---                   ^^^^^^^ expected `[u8; N]`, found `()`
@@ -13,11 +25,11 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
    |    implicitly returns `()` as its body has no tail or `return` expression
 
 error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:5:31
+  --> $DIR/type_mismatch.rs:6:31
    |
 LL | fn bar<const N: u8>() -> [u8; N] {}
    |                               ^ expected `usize`, found `u8`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/type_not_in_scope.rs b/tests/ui/const-generics/type_not_in_scope.rs
index 5933701808b..917abaed15e 100644
--- a/tests/ui/const-generics/type_not_in_scope.rs
+++ b/tests/ui/const-generics/type_not_in_scope.rs
@@ -6,6 +6,5 @@ impl X {
 }
 fn getn<const N: cfg_attr>() -> [u8; N] {}
 //~^ ERROR expected type, found built-in attribute `cfg_attr`
-//~| ERROR mismatched types
 
 fn main() {}
diff --git a/tests/ui/const-generics/type_not_in_scope.stderr b/tests/ui/const-generics/type_not_in_scope.stderr
index 5f45550a627..5eb81ca0522 100644
--- a/tests/ui/const-generics/type_not_in_scope.stderr
+++ b/tests/ui/const-generics/type_not_in_scope.stderr
@@ -10,15 +10,7 @@ error[E0573]: expected type, found built-in attribute `cfg_attr`
 LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
    |                  ^^^^^^^^ not a type
 
-error[E0308]: mismatched types
-  --> $DIR/type_not_in_scope.rs:7:33
-   |
-LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
-   |    ----                         ^^^^^^^ expected `[u8; N]`, found `()`
-   |    |
-   |    implicitly returns `()` as its body has no tail or `return` expression
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0412, E0573.
-For more information about an error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0412, E0573.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
index f647380ef9b..b1613f638d3 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
@@ -64,6 +64,12 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | impl FnOnce() for Foo1 {
    |      ^^^^^^^^ associated type not allowed here
+   |
+help: parenthesized trait syntax expands to `FnOnce<(), Output=()>`
+  --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:16:6
+   |
+LL | impl FnOnce() for Foo1 {
+   |      ^^^^^^^^
 
 error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:23:6
diff --git a/tests/ui/fn/issue-39259.rs b/tests/ui/fn/issue-39259.rs
new file mode 100644
index 00000000000..5872f1007b0
--- /dev/null
+++ b/tests/ui/fn/issue-39259.rs
@@ -0,0 +1,13 @@
+#![feature(fn_traits)]
+#![feature(unboxed_closures)]
+
+struct S;
+
+impl Fn(u32) -> u32 for S {
+//~^ ERROR associated type bindings are not allowed here [E0229]
+    fn call(&self) -> u32 {
+        5
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/fn/issue-39259.stderr b/tests/ui/fn/issue-39259.stderr
new file mode 100644
index 00000000000..b656b76bfe4
--- /dev/null
+++ b/tests/ui/fn/issue-39259.stderr
@@ -0,0 +1,15 @@
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-39259.rs:6:17
+   |
+LL | impl Fn(u32) -> u32 for S {
+   |                 ^^^ associated type not allowed here
+   |
+help: parenthesized trait syntax expands to `Fn<(u32,), Output=u32>`
+  --> $DIR/issue-39259.rs:6:6
+   |
+LL | impl Fn(u32) -> u32 for S {
+   |      ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr b/tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr
new file mode 100644
index 00000000000..9af6bc45c7a
--- /dev/null
+++ b/tests/ui/higher-rank-trait-bounds/fn-ptr.classic.stderr
@@ -0,0 +1,19 @@
+error[E0277]: expected a `Fn<(&'w (),)>` closure, found `fn(&'w ())`
+  --> $DIR/fn-ptr.rs:12:5
+   |
+LL |     ice();
+   |     ^^^ expected an `Fn<(&'w (),)>` closure, found `fn(&'w ())`
+   |
+   = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())`
+note: required by a bound in `ice`
+  --> $DIR/fn-ptr.rs:7:25
+   |
+LL | fn ice()
+   |    --- required by a bound in this function
+LL | where
+LL |     for<'w> fn(&'w ()): Fn(&'w ()),
+   |                         ^^^^^^^^^^ required by this bound in `ice`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-rank-trait-bounds/fn-ptr.rs b/tests/ui/higher-rank-trait-bounds/fn-ptr.rs
new file mode 100644
index 00000000000..853160f9612
--- /dev/null
+++ b/tests/ui/higher-rank-trait-bounds/fn-ptr.rs
@@ -0,0 +1,14 @@
+// revisions: classic next
+//[next] compile-flags: -Ztrait-solver=next
+//[next] check-pass
+
+fn ice()
+where
+    for<'w> fn(&'w ()): Fn(&'w ()),
+{
+}
+
+fn main() {
+    ice();
+    //[classic]~^ ERROR expected a `Fn<(&'w (),)>` closure, found `fn(&'w ())`
+}
diff --git a/tests/ui/issues/issue-66667-function-cmp-cycle.rs b/tests/ui/issues/issue-66667-function-cmp-cycle.rs
index 7b025be11a0..b4f09fbbb04 100644
--- a/tests/ui/issues/issue-66667-function-cmp-cycle.rs
+++ b/tests/ui/issues/issue-66667-function-cmp-cycle.rs
@@ -1,16 +1,19 @@
 fn first() {
     second == 1 //~ ERROR binary operation
     //~^ ERROR mismatched types
+    //~| ERROR mismatched types
 }
 
 fn second() {
     first == 1 //~ ERROR binary operation
     //~^ ERROR mismatched types
+    //~| ERROR mismatched types
 }
 
 fn bar() {
     bar == 1 //~ ERROR binary operation
     //~^ ERROR mismatched types
+    //~| ERROR mismatched types
 }
 
 fn main() {}
diff --git a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr
index 887699ef5ce..d9a960ce197 100644
--- a/tests/ui/issues/issue-66667-function-cmp-cycle.stderr
+++ b/tests/ui/issues/issue-66667-function-cmp-cycle.stderr
@@ -15,8 +15,16 @@ LL |     second == 1
    = note: expected fn item `fn() {second}`
                  found type `{integer}`
 
+error[E0308]: mismatched types
+  --> $DIR/issue-66667-function-cmp-cycle.rs:2:5
+   |
+LL | fn first() {
+   |            - help: try adding a return type: `-> bool`
+LL |     second == 1
+   |     ^^^^^^^^^^^ expected `()`, found `bool`
+
 error[E0369]: binary operation `==` cannot be applied to type `fn() {first}`
-  --> $DIR/issue-66667-function-cmp-cycle.rs:7:11
+  --> $DIR/issue-66667-function-cmp-cycle.rs:8:11
    |
 LL |     first == 1
    |     ----- ^^ - {integer}
@@ -24,7 +32,7 @@ LL |     first == 1
    |     fn() {first}
 
 error[E0308]: mismatched types
-  --> $DIR/issue-66667-function-cmp-cycle.rs:7:14
+  --> $DIR/issue-66667-function-cmp-cycle.rs:8:14
    |
 LL |     first == 1
    |              ^ expected fn item, found integer
@@ -32,8 +40,16 @@ LL |     first == 1
    = note: expected fn item `fn() {first}`
                  found type `{integer}`
 
+error[E0308]: mismatched types
+  --> $DIR/issue-66667-function-cmp-cycle.rs:8:5
+   |
+LL | fn second() {
+   |             - help: try adding a return type: `-> bool`
+LL |     first == 1
+   |     ^^^^^^^^^^ expected `()`, found `bool`
+
 error[E0369]: binary operation `==` cannot be applied to type `fn() {bar}`
-  --> $DIR/issue-66667-function-cmp-cycle.rs:12:9
+  --> $DIR/issue-66667-function-cmp-cycle.rs:14:9
    |
 LL |     bar == 1
    |     --- ^^ - {integer}
@@ -41,7 +57,7 @@ LL |     bar == 1
    |     fn() {bar}
 
 error[E0308]: mismatched types
-  --> $DIR/issue-66667-function-cmp-cycle.rs:12:12
+  --> $DIR/issue-66667-function-cmp-cycle.rs:14:12
    |
 LL |     bar == 1
    |            ^ expected fn item, found integer
@@ -49,7 +65,15 @@ LL |     bar == 1
    = note: expected fn item `fn() {bar}`
                  found type `{integer}`
 
-error: aborting due to 6 previous errors
+error[E0308]: mismatched types
+  --> $DIR/issue-66667-function-cmp-cycle.rs:14:5
+   |
+LL | fn bar() {
+   |          - help: try adding a return type: `-> bool`
+LL |     bar == 1
+   |     ^^^^^^^^ expected `()`, found `bool`
+
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0308, E0369.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr
index 35c3797c77a..5b93eff8614 100644
--- a/tests/ui/lifetimes/issue-95023.stderr
+++ b/tests/ui/lifetimes/issue-95023.stderr
@@ -25,6 +25,12 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | impl Fn(&isize) for Error {
    |      ^^^^^^^^^^ associated type not allowed here
+   |
+help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>`
+  --> $DIR/issue-95023.rs:3:6
+   |
+LL | impl Fn(&isize) for Error {
+   |      ^^^^^^^^^^
 
 error[E0220]: associated type `B` not found for `Self`
   --> $DIR/issue-95023.rs:6:44
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs
index 7314fa8cced..9108f27b5f7 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.rs
@@ -18,4 +18,10 @@ impl Foo for Bar {
     unsafe fn unsf_foo(&self) {}
 }
 
+trait Qux {
+    #[target_feature(enable = "sse2")]
+    //~^ ERROR cannot be applied to safe trait method
+    fn foo(&self) {}
+}
+
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
index 07d6e090059..eb0f18edd34 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/trait-impl.stderr
@@ -1,4 +1,13 @@
 error: `#[target_feature(..)]` cannot be applied to safe trait method
+  --> $DIR/trait-impl.rs:22:5
+   |
+LL |     #[target_feature(enable = "sse2")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method
+LL |
+LL |     fn foo(&self) {}
+   |     ------------- not an `unsafe` function
+
+error: `#[target_feature(..)]` cannot be applied to safe trait method
   --> $DIR/trait-impl.rs:13:5
    |
 LL |     #[target_feature(enable = "sse2")]
@@ -7,5 +16,5 @@ LL |
 LL |     fn foo(&self) {}
    |     ------------- not an `unsafe` function
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
new file mode 100644
index 00000000000..582b480aa25
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
@@ -0,0 +1,12 @@
+#![feature(min_specialization)]
+
+// An impl that has an erroneous const substitution should not specialize one
+// that is well-formed.
+
+struct S<const L: usize>;
+
+impl<const N: i32> Copy for S<N> {}
+impl<const M: usize> Copy for S<M> {}
+//~^ ERROR conflicting implementations of trait `Copy` for type `S<_>`
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
new file mode 100644
index 00000000000..a3906a9a22f
--- /dev/null
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
+  --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
+   |
+LL | impl<const N: i32> Copy for S<N> {}
+   | -------------------------------- first implementation here
+LL | impl<const M: usize> Copy for S<M> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/str/str-escape.rs b/tests/ui/str/str-escape.rs
index 0264632fd24..10a72421f24 100644
--- a/tests/ui/str/str-escape.rs
+++ b/tests/ui/str/str-escape.rs
@@ -1,11 +1,31 @@
 // check-pass
+// ignore-tidy-tab
+
 fn main() {
     let s = "\
 
              ";
     //~^^^ WARNING multiple lines skipped by escaped newline
+    assert_eq!(s, "");
+
     let s = "foo\
              bar
              ";
-    //~^^^ WARNING non-ASCII whitespace symbol '\u{a0}' is not skipped
+    //~^^^ WARNING whitespace symbol '\u{a0}' is not skipped
+    assert_eq!(s, "foo           bar\n             ");
+
+    let s = "a\
+ b";
+    assert_eq!(s, "ab");
+
+    let s = "a\
+	b";
+    assert_eq!(s, "ab");
+
+    let s = "a\
+    b";
+    //~^^ WARNING whitespace symbol '\u{c}' is not skipped
+    // '\x0c' is ASCII whitespace, but it may not need skipped
+    // discussion: https://github.com/rust-lang/rust/pull/108403
+    assert_eq!(s, "a\x0cb");
 }
diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr
index b2501f1a214..43b4f7e36f6 100644
--- a/tests/ui/str/str-escape.stderr
+++ b/tests/ui/str/str-escape.stderr
@@ -1,5 +1,5 @@
 warning: multiple lines skipped by escaped newline
-  --> $DIR/str-escape.rs:3:14
+  --> $DIR/str-escape.rs:5:14
    |
 LL |       let s = "\
    |  ______________^
@@ -7,15 +7,25 @@ LL | |
 LL | |              ";
    | |_____________^ skipping everything up to and including this point
 
-warning: non-ASCII whitespace symbol '\u{a0}' is not skipped
-  --> $DIR/str-escape.rs:7:17
+warning: whitespace symbol '\u{a0}' is not skipped
+  --> $DIR/str-escape.rs:11:17
    |
 LL |       let s = "foo\
    |  _________________^
 LL | |              bar
-   | |   ^ non-ASCII whitespace symbol '\u{a0}' is not skipped
+   | |   ^ whitespace symbol '\u{a0}' is not skipped
    | |___|
    | 
 
-warning: 2 warnings emitted
+warning: whitespace symbol '\u{c}' is not skipped
+  --> $DIR/str-escape.rs:25:15
+   |
+LL |       let s = "a\
+   |  _______________^
+LL | |     b";
+   | |    ^- whitespace symbol '\u{c}' is not skipped
+   | |____|
+   | 
+
+warning: 3 warnings emitted
 
diff --git a/tests/ui/traits/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr
index 494274d8c30..b647f9794bd 100644
--- a/tests/ui/traits/issue-87558.stderr
+++ b/tests/ui/traits/issue-87558.stderr
@@ -17,6 +17,12 @@ error[E0229]: associated type bindings are not allowed here
    |
 LL | impl Fn(&isize) for Error {
    |      ^^^^^^^^^^ associated type not allowed here
+   |
+help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>`
+  --> $DIR/issue-87558.rs:3:6
+   |
+LL | impl Fn(&isize) for Error {
+   |      ^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs b/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
new file mode 100644
index 00000000000..3f7316a2279
--- /dev/null
+++ b/tests/ui/traits/new-solver/canonical-int-var-eq-in-response.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Mirror {
+    type Assoc;
+}
+
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+trait Test {}
+impl Test for i64 {}
+impl Test for u64 {}
+
+fn mirror_me<T: Mirror>(t: T, s: <T as Mirror>::Assoc) where <T as Mirror>::Assoc: Test {}
+
+fn main() {
+    let mut x = 0;
+    mirror_me(x, 1);
+    x = 1i64;
+}
diff --git a/tests/ui/traits/new-solver/int-var-alias-eq.rs b/tests/ui/traits/new-solver/int-var-alias-eq.rs
new file mode 100644
index 00000000000..2da387db4a9
--- /dev/null
+++ b/tests/ui/traits/new-solver/int-var-alias-eq.rs
@@ -0,0 +1,18 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+// HIR typeck ends up equating `<_#0i as Add>::Output == _#0i`.
+// Want to make sure that we emit an alias-eq goal for this,
+// instead of treating it as a type error and bailing.
+
+fn test() {
+    // fallback
+    let x = 1 + 2;
+}
+
+fn test2() -> u32 {
+    // expectation from return ty
+    1 + 2
+}
+
+fn main() {}
diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs
index bcb8b158edf..2b966609108 100644
--- a/tests/ui/transmutability/issue-101739-1.rs
+++ b/tests/ui/transmutability/issue-101739-1.rs
@@ -6,7 +6,7 @@ mod assert {
     pub fn is_transmutable<Src, Context, const ASSUME_ALIGNMENT: bool>()
     where
         Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
-        //~^ ERROR mismatched types
+        //~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume`
     {
     }
 }
diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr
index 7c6b533ef5f..f0fa93722b8 100644
--- a/tests/ui/transmutability/issue-101739-1.stderr
+++ b/tests/ui/transmutability/issue-101739-1.stderr
@@ -4,13 +4,15 @@ error[E0412]: cannot find type `Dst` in this scope
 LL |         Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
    |         ^^^ not found in this scope
 
-error[E0308]: mismatched types
-  --> $DIR/issue-101739-1.rs:8:50
+error: the constant `ASSUME_ALIGNMENT` is not of type `Assume`
+  --> $DIR/issue-101739-1.rs:8:14
    |
 LL |         Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
-   |                                                  ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by a bound in `BikeshedIntrinsicFrom`
+  --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0412.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs b/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs
index 5ff567cd07c..3b261062f78 100644
--- a/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs
+++ b/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs
@@ -1,5 +1,5 @@
 // compile-flags: -Ztrait-solver=next
-// known-bug: unknown
+// check-pass
 
 fn main() {
     (0u8 + 0u8) as char;
diff --git a/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr b/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr
deleted file mode 100644
index 6b09ccd5214..00000000000
--- a/tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0271]: type mismatch resolving `char == <u8 as Add>::Output`
-  --> $DIR/cast-checks-handling-projections.rs:5:5
-   |
-LL |     (0u8 + 0u8) as char;
-   |     ^^^^^^^^^^^ types differ
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/triagebot.toml b/triagebot.toml
index e39a0b06b97..0388ce9fc98 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -430,7 +430,7 @@ message = "The Miri subtree was changed"
 cc = ["@rust-lang/miri"]
 
 [mentions."src/tools/rust-analyzer"]
-cc = ["@rust-lang/wg-rls-2"]
+cc = ["@rust-lang/rust-analyzer"]
 
 [mentions."src/tools/rustfmt"]
 cc = ["@rust-lang/rustfmt"]