about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-23 22:44:44 +0000
committerbors <bors@rust-lang.org>2024-01-23 22:44:44 +0000
commit0b7730105fb7e008002f6ba29f87a55699f67744 (patch)
tree5dca2dde5b4baeebaa2cfe31e4ab8f3b96060671 /compiler
parent5d3d3479d774754856db2db3e439dfb88ef3c52f (diff)
parent3f2f8eee0220d905121a2da4e24a02a90ef15b84 (diff)
downloadrust-0b7730105fb7e008002f6ba29f87a55699f67744.tar.gz
rust-0b7730105fb7e008002f6ba29f87a55699f67744.zip
Auto merge of #120283 - fmease:rollup-rk0f6r5, r=fmease
Rollup of 9 pull requests

Successful merges:

 - #112806 (Small code improvements in `collect_intra_doc_links.rs`)
 - #119766 (Split tait and impl trait in assoc items logic)
 - #120139 (Do not normalize closure signature when building `FnOnce` shim)
 - #120160 (Manually implement derived `NonZero` traits.)
 - #120171 (Fix assume and assert in jump threading)
 - #120183 (Add `#[coverage(off)]` to closures introduced by `#[test]` and `#[bench]`)
 - #120195 (add several resolution test cases)
 - #120259 (Split Diagnostics for Uncommon Codepoints: Add List to Display Characters Involved)
 - #120261 (Provide structured suggestion to use trait objects in some cases of `if` arm type divergence)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs21
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs3
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs78
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs118
-rw-r--r--compiler/rustc_lint/messages.ftl5
-rw-r--r--compiler/rustc_lint/src/lints.rs5
-rw-r--r--compiler/rustc_lint/src/non_ascii_idents.rs12
-rw-r--r--compiler/rustc_middle/src/query/mod.rs9
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs18
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs4
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs17
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs3
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs5
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs7
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs213
22 files changed, 418 insertions, 126 deletions
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index f60b73fbe9b..3e9b06a5b05 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -6,6 +6,7 @@
 #![doc(rust_logo)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(array_windows)]
+#![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 4d44e340ae1..0631f796894 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -9,6 +9,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, Level};
 use rustc_expand::base::*;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
+use std::assert_matches::assert_matches;
 use std::iter;
 use thin_vec::{thin_vec, ThinVec};
 
@@ -182,6 +183,16 @@ pub fn expand_test_or_bench(
     // creates $name: $expr
     let field = |name, expr| cx.field_imm(sp, Ident::from_str_and_span(name, sp), expr);
 
+    // Adds `#[coverage(off)]` to a closure, so it won't be instrumented in
+    // `-Cinstrument-coverage` builds.
+    // This requires `#[allow_internal_unstable(coverage_attribute)]` on the
+    // corresponding macro declaration in `core::macros`.
+    let coverage_off = |mut expr: P<ast::Expr>| {
+        assert_matches!(expr.kind, ast::ExprKind::Closure(_));
+        expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp));
+        expr
+    };
+
     let test_fn = if is_bench {
         // A simple ident for a lambda
         let b = Ident::from_str_and_span("b", attr_sp);
@@ -190,8 +201,9 @@ pub fn expand_test_or_bench(
             sp,
             cx.expr_path(test_path("StaticBenchFn")),
             thin_vec![
+                // #[coverage(off)]
                 // |b| self::test::assert_test_result(
-                cx.lambda1(
+                coverage_off(cx.lambda1(
                     sp,
                     cx.expr_call(
                         sp,
@@ -206,7 +218,7 @@ pub fn expand_test_or_bench(
                         ],
                     ),
                     b,
-                ), // )
+                )), // )
             ],
         )
     } else {
@@ -214,8 +226,9 @@ pub fn expand_test_or_bench(
             sp,
             cx.expr_path(test_path("StaticTestFn")),
             thin_vec![
+                // #[coverage(off)]
                 // || {
-                cx.lambda0(
+                coverage_off(cx.lambda0(
                     sp,
                     // test::assert_test_result(
                     cx.expr_call(
@@ -230,7 +243,7 @@ pub fn expand_test_or_bench(
                             ), // )
                         ],
                     ), // }
-                ), // )
+                )), // )
             ],
         )
     };
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 881c0c0b56b..0afd6d0e670 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -682,7 +682,6 @@ fn codegen_stmt<'tcx>(
                                 args,
                                 ty::ClosureKind::FnOnce,
                             )
-                            .expect("failed to normalize and resolve closure during codegen")
                             .polymorphize(fx.tcx);
                             let func_ref = fx.get_function_ref(instance);
                             let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 02b51dfe5bf..266505d3f26 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -435,7 +435,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                     args,
                                     ty::ClosureKind::FnOnce,
                                 )
-                                .expect("failed to normalize and resolve closure during codegen")
                                 .polymorphize(bx.cx().tcx());
                                 OperandValue::Immediate(bx.cx().get_fn_addr(instance))
                             }
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index d296ff5928b..0cb5c634b22 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -117,8 +117,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             def_id,
                             args,
                             ty::ClosureKind::FnOnce,
-                        )
-                        .ok_or_else(|| err_inval!(TooGeneric))?;
+                        );
                         let fn_ptr = self.fn_ptr(FnVal::Instance(instance));
                         self.write_pointer(fn_ptr, dest)?;
                     }
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 39252dea283..f6679ae9bb3 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -110,6 +110,14 @@ impl IntoDiagnosticArg for char {
     }
 }
 
+impl IntoDiagnosticArg for Vec<char> {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::StrListSepByAnd(
+            self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
+        )
+    }
+}
+
 impl IntoDiagnosticArg for Symbol {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         self.to_ident_string().into_diagnostic_arg()
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index bfa9dc42422..3674a760cbf 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -530,9 +530,13 @@ pub(super) fn type_of_opaque(
         Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id) {
             Node::Item(item) => match item.kind {
                 ItemKind::OpaqueTy(OpaqueTy {
-                    origin: hir::OpaqueTyOrigin::TyAlias { .. },
+                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false },
                     ..
                 }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
+                ItemKind::OpaqueTy(OpaqueTy {
+                    origin: hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: true },
+                    ..
+                }) => opaque::find_opaque_ty_constraints_for_impl_trait_in_assoc_type(tcx, def_id),
                 // Opaque types desugared from `impl Trait`.
                 ItemKind::OpaqueTy(&OpaqueTy {
                     origin:
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 85093bc12b3..79cb384c5bd 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -23,6 +23,60 @@ pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed>
     res
 }
 
+/// Checks "defining uses" of opaque `impl Trait` in associated types.
+/// These can only be defined by associated items of the same trait.
+#[instrument(skip(tcx), level = "debug")]
+pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+) -> Ty<'_> {
+    let mut parent_def_id = def_id;
+    while tcx.def_kind(parent_def_id) == def::DefKind::OpaqueTy {
+        // Account for `type Alias = impl Trait<Foo = impl Trait>;` (#116031)
+        parent_def_id = tcx.local_parent(parent_def_id);
+    }
+    let impl_def_id = tcx.local_parent(parent_def_id);
+    match tcx.def_kind(impl_def_id) {
+        DefKind::Impl { .. } => {}
+        other => bug!("invalid impl trait in assoc type parent: {other:?}"),
+    }
+
+    let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
+
+    for &assoc_id in tcx.associated_item_def_ids(impl_def_id) {
+        let assoc = tcx.associated_item(assoc_id);
+        match assoc.kind {
+            ty::AssocKind::Const | ty::AssocKind::Fn => {
+                locator.check(assoc_id.expect_local(), ImplTraitSource::AssocTy)
+            }
+            // Associated types don't have bodies, so they can't constrain hidden types
+            ty::AssocKind::Type => {}
+        }
+    }
+
+    if let Some(hidden) = locator.found {
+        // Only check against typeck if we didn't already error
+        if !hidden.ty.references_error() {
+            for concrete_type in locator.typeck_types {
+                if concrete_type.ty != tcx.erase_regions(hidden.ty)
+                    && !(concrete_type, hidden).references_error()
+                {
+                    hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+                }
+            }
+        }
+
+        hidden.ty
+    } else {
+        let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType {
+            span: tcx.def_span(def_id),
+            name: tcx.item_name(parent_def_id.to_def_id()),
+            what: "impl",
+        });
+        Ty::new_error(tcx, reported)
+    }
+}
+
 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
 /// laid for "higher-order pattern unification".
 /// This ensures that inference is tractable.
@@ -128,9 +182,15 @@ struct TaitConstraintLocator<'tcx> {
     typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
 }
 
+#[derive(Debug)]
+enum ImplTraitSource {
+    AssocTy,
+    TyAlias,
+}
+
 impl TaitConstraintLocator<'_> {
     #[instrument(skip(self), level = "debug")]
-    fn check(&mut self, item_def_id: LocalDefId) {
+    fn check(&mut self, item_def_id: LocalDefId, source: ImplTraitSource) {
         // Don't try to check items that cannot possibly constrain the type.
         if !self.tcx.has_typeck_results(item_def_id) {
             debug!("no constraint: no typeck results");
@@ -182,7 +242,13 @@ impl TaitConstraintLocator<'_> {
                 continue;
             }
             constrained = true;
-            if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) {
+            let opaque_types_defined_by = match source {
+                ImplTraitSource::AssocTy => {
+                    self.tcx.impl_trait_in_assoc_types_defined_by(item_def_id)
+                }
+                ImplTraitSource::TyAlias => self.tcx.opaque_types_defined_by(item_def_id),
+            };
+            if !opaque_types_defined_by.contains(&self.def_id) {
                 self.tcx.dcx().emit_err(TaitForwardCompat {
                     span: hidden_type.span,
                     item_span: self
@@ -240,7 +306,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
         if let hir::ExprKind::Closure(closure) = ex.kind {
-            self.check(closure.def_id);
+            self.check(closure.def_id, ImplTraitSource::TyAlias);
         }
         intravisit::walk_expr(self, ex);
     }
@@ -248,7 +314,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         trace!(?it.owner_id);
         // The opaque type itself or its children are not within its reveal scope.
         if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id);
+            self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
             intravisit::walk_item(self, it);
         }
     }
@@ -256,13 +322,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         trace!(?it.owner_id);
         // The opaque type itself or its children are not within its reveal scope.
         if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id);
+            self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
             intravisit::walk_impl_item(self, it);
         }
     }
     fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
         trace!(?it.owner_id);
-        self.check(it.owner_id.def_id);
+        self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
         intravisit::walk_trait_item(self, it);
     }
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 9850892bd36..b6dfc34d3ac 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -44,7 +44,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
             || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
             || self.suggest_no_capture_closure(err, expected, expr_ty)
-            || self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty)
+            || self.suggest_boxing_when_appropriate(
+                err,
+                expr.peel_blocks().span,
+                expr.hir_id,
+                expected,
+                expr_ty,
+            )
             || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
             || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected)
             || self.suggest_clone_for_ref(err, expr, expr_ty, expected)
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index afb3c5c1e56..01cd3c57925 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -294,8 +294,9 @@ impl<T> Trait<T> for X {
                             );
                         }
                     }
-                    (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias))
-                        if alias.def_id.is_local()
+                    (_, ty::Alias(ty::Opaque, opaque_ty))
+                    | (ty::Alias(ty::Opaque, opaque_ty), _) => {
+                        if opaque_ty.def_id.is_local()
                             && matches!(
                                 tcx.def_kind(body_owner_def_id),
                                 DefKind::Fn
@@ -303,21 +304,74 @@ impl<T> Trait<T> for X {
                                     | DefKind::Const
                                     | DefKind::AssocFn
                                     | DefKind::AssocConst
-                            ) =>
-                    {
-                        if tcx.is_type_alias_impl_trait(alias.def_id) {
-                            if !tcx
+                            )
+                            && tcx.is_type_alias_impl_trait(opaque_ty.def_id)
+                            && !tcx
                                 .opaque_types_defined_by(body_owner_def_id.expect_local())
-                                .contains(&alias.def_id.expect_local())
-                            {
-                                let sp = tcx
-                                    .def_ident_span(body_owner_def_id)
-                                    .unwrap_or_else(|| tcx.def_span(body_owner_def_id));
-                                diag.span_note(
-                                    sp,
-                                    "\
-                                    this item must have the opaque type in its signature \
-                                    in order to be able to register hidden types",
+                                .contains(&opaque_ty.def_id.expect_local())
+                        {
+                            let sp = tcx
+                                .def_ident_span(body_owner_def_id)
+                                .unwrap_or_else(|| tcx.def_span(body_owner_def_id));
+                            diag.span_note(
+                                sp,
+                                "this item must have the opaque type in its signature in order to \
+                                 be able to register hidden types",
+                            );
+                        }
+                        // If two if arms can be coerced to a trait object, provide a structured
+                        // suggestion.
+                        let ObligationCauseCode::IfExpression(cause) = cause.code() else {
+                            return;
+                        };
+                        let hir::Node::Block(blk) = self.tcx.hir_node(cause.then_id) else {
+                            return;
+                        };
+                        let Some(then) = blk.expr else {
+                            return;
+                        };
+                        let hir::Node::Block(blk) = self.tcx.hir_node(cause.else_id) else {
+                            return;
+                        };
+                        let Some(else_) = blk.expr else {
+                            return;
+                        };
+                        let expected = match values.found.kind() {
+                            ty::Alias(..) => values.expected,
+                            _ => values.found,
+                        };
+                        let preds = tcx.explicit_item_bounds(opaque_ty.def_id);
+                        for (pred, _span) in preds.skip_binder() {
+                            let ty::ClauseKind::Trait(trait_predicate) = pred.kind().skip_binder()
+                            else {
+                                continue;
+                            };
+                            if trait_predicate.polarity != ty::ImplPolarity::Positive {
+                                continue;
+                            }
+                            let def_id = trait_predicate.def_id();
+                            let mut impl_def_ids = vec![];
+                            tcx.for_each_relevant_impl(def_id, expected, |did| {
+                                impl_def_ids.push(did)
+                            });
+                            if let [_] = &impl_def_ids[..] {
+                                let trait_name = tcx.item_name(def_id);
+                                diag.multipart_suggestion(
+                                    format!(
+                                        "`{expected}` implements `{trait_name}` so you can box \
+                                         both arms and coerce to the trait object \
+                                         `Box<dyn {trait_name}>`",
+                                    ),
+                                    vec![
+                                        (then.span.shrink_to_lo(), "Box::new(".to_string()),
+                                        (
+                                            then.span.shrink_to_hi(),
+                                            format!(") as Box<dyn {}>", tcx.def_path_str(def_id)),
+                                        ),
+                                        (else_.span.shrink_to_lo(), "Box::new(".to_string()),
+                                        (else_.span.shrink_to_hi(), ")".to_string()),
+                                    ],
+                                    MachineApplicable,
                                 );
                             }
                         }
@@ -330,6 +384,38 @@ impl<T> Trait<T> for X {
                             );
                         }
                     }
+                    (ty::Adt(_, _), ty::Adt(def, args))
+                        if let ObligationCauseCode::IfExpression(cause) = cause.code()
+                            && let hir::Node::Block(blk) = self.tcx.hir_node(cause.then_id)
+                            && let Some(then) = blk.expr
+                            && def.is_box()
+                            && let boxed_ty = args.type_at(0)
+                            && let ty::Dynamic(t, _, _) = boxed_ty.kind()
+                            && let Some(def_id) = t.principal_def_id()
+                            && let mut impl_def_ids = vec![]
+                            && let _ =
+                                tcx.for_each_relevant_impl(def_id, values.expected, |did| {
+                                    impl_def_ids.push(did)
+                                })
+                            && let [_] = &impl_def_ids[..] =>
+                    {
+                        // We have divergent if/else arms where the expected value is a type that
+                        // implements the trait of the found boxed trait object.
+                        diag.multipart_suggestion(
+                            format!(
+                                "`{}` implements `{}` so you can box it to coerce to the trait \
+                                 object `{}`",
+                                values.expected,
+                                tcx.item_name(def_id),
+                                values.found,
+                            ),
+                            vec![
+                                (then.span.shrink_to_lo(), "Box::new(".to_string()),
+                                (then.span.shrink_to_hi(), ")".to_string()),
+                            ],
+                            MachineApplicable,
+                        );
+                    }
                     _ => {}
                 }
                 debug!(
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 33f96139f20..5652a34103b 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -240,7 +240,10 @@ lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of
 
 lint_identifier_non_ascii_char = identifier contains non-ASCII characters
 
-lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
+lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len ->
+    [one] an uncommon Unicode codepoint
+    *[other] uncommon Unicode codepoints
+}: {$codepoints}
 
 lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
 
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 94ecc7d9587..e19bb1cb62f 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1107,7 +1107,10 @@ pub struct IdentifierNonAsciiChar;
 
 #[derive(LintDiagnostic)]
 #[diag(lint_identifier_uncommon_codepoints)]
-pub struct IdentifierUncommonCodepoints;
+pub struct IdentifierUncommonCodepoints {
+    pub codepoints: Vec<char>,
+    pub codepoints_len: usize,
+}
 
 #[derive(LintDiagnostic)]
 #[diag(lint_confusable_identifier_pair)]
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index 00f87a5af80..f78b32ce5e7 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -190,7 +190,17 @@ impl EarlyLintPass for NonAsciiIdents {
             if check_uncommon_codepoints
                 && !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
             {
-                cx.emit_span_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints);
+                let codepoints: Vec<_> = symbol_str
+                    .chars()
+                    .filter(|c| !GeneralSecurityProfile::identifier_allowed(*c))
+                    .collect();
+                let codepoints_len = codepoints.len();
+
+                cx.emit_span_lint(
+                    UNCOMMON_CODEPOINTS,
+                    sp,
+                    IdentifierUncommonCodepoints { codepoints, codepoints_len },
+                );
             }
         }
 
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index a9dc7f5d11a..23daefd5a65 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -343,6 +343,15 @@ rustc_queries! {
         }
     }
 
+    query impl_trait_in_assoc_types_defined_by(
+        key: LocalDefId
+    ) -> &'tcx ty::List<LocalDefId> {
+        desc {
+            |tcx| "computing the opaque types defined by `{}`",
+            tcx.def_path_str(key.to_def_id())
+        }
+    }
+
     /// Returns the list of bounds that can be used for
     /// `SelectionCandidate::ProjectionCandidate(_)` and
     /// `ProjectionTyCandidate::TraitDef`.
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index b6c3c34078f..293fdb026b6 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -530,12 +530,12 @@ impl<'tcx> Instance<'tcx> {
         def_id: DefId,
         args: ty::GenericArgsRef<'tcx>,
         requested_kind: ty::ClosureKind,
-    ) -> Option<Instance<'tcx>> {
+    ) -> Instance<'tcx> {
         let actual_kind = args.as_closure().kind();
 
         match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
             Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, args),
-            _ => Some(Instance::new(def_id, args)),
+            _ => Instance::new(def_id, args),
         }
     }
 
@@ -550,7 +550,7 @@ impl<'tcx> Instance<'tcx> {
         tcx: TyCtxt<'tcx>,
         closure_did: DefId,
         args: ty::GenericArgsRef<'tcx>,
-    ) -> Option<Instance<'tcx>> {
+    ) -> Instance<'tcx> {
         let fn_once = tcx.require_lang_item(LangItem::FnOnce, None);
         let call_once = tcx
             .associated_items(fn_once)
@@ -564,14 +564,12 @@ impl<'tcx> Instance<'tcx> {
 
         let self_ty = Ty::new_closure(tcx, closure_did, args);
 
-        let sig = args.as_closure().sig();
-        let sig =
-            tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?;
-        assert_eq!(sig.inputs().len(), 1);
-        let args = tcx.mk_args_trait(self_ty, [sig.inputs()[0].into()]);
+        let tupled_inputs_ty = args.as_closure().sig().map_bound(|sig| sig.inputs()[0]);
+        let tupled_inputs_ty = tcx.instantiate_bound_regions_with_erased(tupled_inputs_ty);
+        let args = tcx.mk_args_trait(self_ty, [tupled_inputs_ty.into()]);
 
-        debug!(?self_ty, ?sig);
-        Some(Instance { def, args })
+        debug!(?self_ty, args=?tupled_inputs_ty.tuple_fields());
+        Instance { def, args }
     }
 
     pub fn try_resolve_item_for_coroutine(
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 5428333a116..c669d3fd623 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -20,6 +20,10 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
             @call(mir_storage_dead, args) => {
                 Ok(StatementKind::StorageDead(self.parse_local(args[0])?))
             },
+            @call(mir_assume, args) => {
+                let op = self.parse_operand(args[0])?;
+                Ok(StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(op))))
+            },
             @call(mir_deinit, args) => {
                 Ok(StatementKind::Deinit(Box::new(self.parse_place(args[0])?)))
             },
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index e87f68a0905..7a70ed5cb7f 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -566,11 +566,6 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
         cost: &CostChecker<'_, 'tcx>,
         depth: usize,
     ) {
-        let register_opportunity = |c: Condition| {
-            debug!(?bb, ?c.target, "register");
-            self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target })
-        };
-
         let term = self.body.basic_blocks[bb].terminator();
         let place_to_flood = match term.kind {
             // We come from a target, so those are not possible.
@@ -592,16 +587,8 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
             // Flood the overwritten place, and progress through.
             TerminatorKind::Drop { place: destination, .. }
             | TerminatorKind::Call { destination, .. } => Some(destination),
-            // Treat as an `assume(cond == expected)`.
-            TerminatorKind::Assert { ref cond, expected, .. } => {
-                if let Some(place) = cond.place()
-                    && let Some(conditions) = state.try_get(place.as_ref(), self.map)
-                {
-                    let expected = if expected { ScalarInt::TRUE } else { ScalarInt::FALSE };
-                    conditions.iter_matches(expected).for_each(register_opportunity);
-                }
-                None
-            }
+            // Ignore, as this can be a no-op at codegen time.
+            TerminatorKind::Assert { .. } => None,
         };
 
         // We can recurse through this terminator.
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 3e090661414..8b991268819 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -783,8 +783,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                             def_id,
                             args,
                             ty::ClosureKind::FnOnce,
-                        )
-                        .expect("failed to normalize and resolve closure during codegen");
+                        );
                         if should_codegen_locally(self.tcx, &instance) {
                             self.output.push(create_fn_mono_item(self.tcx, instance, span));
                         }
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 10085f659b3..94a1fb33f99 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -464,7 +464,10 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
         let def_id = def.0.internal(&mut *tables, tcx);
         let args_ref = args.internal(&mut *tables, tcx);
         let closure_kind = kind.internal(&mut *tables, tcx);
-        Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables)
+        Some(
+            Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind)
+                .stable(&mut *tables),
+        )
     }
 
     fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6c39a38750e..90a38b26f73 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1028,6 +1028,7 @@ symbols! {
         minnumf32,
         minnumf64,
         mips_target_feature,
+        mir_assume,
         mir_basic_block,
         mir_call,
         mir_cast_transmute,
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index e5e31f7caaa..2d76cf994e4 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -265,7 +265,12 @@ fn resolve_associated_item<'tcx>(
                 match *rcvr_args.type_at(0).kind() {
                     ty::Closure(closure_def_id, args) => {
                         let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap();
-                        Instance::resolve_closure(tcx, closure_def_id, args, trait_closure_kind)
+                        Some(Instance::resolve_closure(
+                            tcx,
+                            closure_def_id,
+                            args,
+                            trait_closure_kind,
+                        ))
                     }
                     ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
                         def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_args.type_at(0)),
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 0bb833c66fa..ef67317a601 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -118,6 +118,69 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         }
         TaitInBodyFinder { collector: self }.visit_expr(body);
     }
+
+    fn visit_opaque_ty(&mut self, alias_ty: &ty::AliasTy<'tcx>) {
+        if !self.seen.insert(alias_ty.def_id.expect_local()) {
+            return;
+        }
+
+        // TAITs outside their defining scopes are ignored.
+        let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local());
+        trace!(?origin);
+        match origin {
+            rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
+            rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
+                if !in_assoc_ty {
+                    if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
+                        return;
+                    }
+                }
+            }
+        }
+
+        self.opaques.push(alias_ty.def_id.expect_local());
+
+        let parent_count = self.tcx.generics_of(alias_ty.def_id).parent_count;
+        // Only check that the parent generics of the TAIT/RPIT are unique.
+        // the args owned by the opaque are going to always be duplicate
+        // lifetime params for RPITs, and empty for TAITs.
+        match self
+            .tcx
+            .uses_unique_generic_params(&alias_ty.args[..parent_count], CheckRegions::FromFunction)
+        {
+            Ok(()) => {
+                // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
+                // supported at all, so this is sound to do, but once we want to support them, you'll
+                // start seeing the error below.
+
+                // Collect opaque types nested within the associated type bounds of this opaque type.
+                // We use identity args here, because we already know that the opaque type uses
+                // only generic parameters, and thus substituting would not give us more information.
+                for (pred, span) in self
+                    .tcx
+                    .explicit_item_bounds(alias_ty.def_id)
+                    .instantiate_identity_iter_copied()
+                {
+                    trace!(?pred);
+                    self.visit_spanned(span, pred);
+                }
+            }
+            Err(NotUniqueParam::NotParam(arg)) => {
+                self.tcx.dcx().emit_err(NotParam {
+                    arg,
+                    span: self.span(),
+                    opaque_span: self.tcx.def_span(alias_ty.def_id),
+                });
+            }
+            Err(NotUniqueParam::DuplicateParam(arg)) => {
+                self.tcx.dcx().emit_err(DuplicateArg {
+                    arg,
+                    span: self.span(),
+                    opaque_span: self.tcx.def_span(alias_ty.def_id),
+                });
+            }
+        }
+    }
 }
 
 impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
@@ -134,67 +197,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
         t.super_visit_with(self)?;
         match t.kind() {
             ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
-                if !self.seen.insert(alias_ty.def_id.expect_local()) {
-                    return ControlFlow::Continue(());
-                }
-
-                // TAITs outside their defining scopes are ignored.
-                let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local());
-                trace!(?origin);
-                match origin {
-                    rustc_hir::OpaqueTyOrigin::FnReturn(_)
-                    | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {}
-                    rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty } => {
-                        if !in_assoc_ty {
-                            if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
-                                return ControlFlow::Continue(());
-                            }
-                        }
-                    }
-                }
-
-                self.opaques.push(alias_ty.def_id.expect_local());
-
-                let parent_count = self.tcx.generics_of(alias_ty.def_id).parent_count;
-                // Only check that the parent generics of the TAIT/RPIT are unique.
-                // the args owned by the opaque are going to always be duplicate
-                // lifetime params for RPITs, and empty for TAITs.
-                match self.tcx.uses_unique_generic_params(
-                    &alias_ty.args[..parent_count],
-                    CheckRegions::FromFunction,
-                ) {
-                    Ok(()) => {
-                        // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
-                        // supported at all, so this is sound to do, but once we want to support them, you'll
-                        // start seeing the error below.
-
-                        // Collect opaque types nested within the associated type bounds of this opaque type.
-                        // We use identity args here, because we already know that the opaque type uses
-                        // only generic parameters, and thus substituting would not give us more information.
-                        for (pred, span) in self
-                            .tcx
-                            .explicit_item_bounds(alias_ty.def_id)
-                            .instantiate_identity_iter_copied()
-                        {
-                            trace!(?pred);
-                            self.visit_spanned(span, pred);
-                        }
-                    }
-                    Err(NotUniqueParam::NotParam(arg)) => {
-                        self.tcx.dcx().emit_err(NotParam {
-                            arg,
-                            span: self.span(),
-                            opaque_span: self.tcx.def_span(alias_ty.def_id),
-                        });
-                    }
-                    Err(NotUniqueParam::DuplicateParam(arg)) => {
-                        self.tcx.dcx().emit_err(DuplicateArg {
-                            arg,
-                            span: self.span(),
-                            opaque_span: self.tcx.def_span(alias_ty.def_id),
-                        });
-                    }
-                }
+                self.visit_opaque_ty(alias_ty);
             }
             ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
                 self.tcx
@@ -272,6 +275,91 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
     }
 }
 
+struct ImplTraitInAssocTypeCollector<'tcx>(OpaqueTypeCollector<'tcx>);
+
+impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for ImplTraitInAssocTypeCollector<'tcx> {
+    #[instrument(skip(self), ret, level = "trace")]
+    fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
+        let old = self.0.span;
+        self.0.span = Some(span);
+        value.visit_with(self);
+        self.0.span = old;
+
+        ControlFlow::Continue(())
+    }
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInAssocTypeCollector<'tcx> {
+    #[instrument(skip(self), ret, level = "trace")]
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
+        t.super_visit_with(self)?;
+        match t.kind() {
+            ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
+                self.0.visit_opaque_ty(alias_ty);
+            }
+            ty::Alias(ty::Projection, alias_ty) => {
+                // This avoids having to do normalization of `Self::AssocTy` by only
+                // supporting the case of a method defining opaque types from assoc types
+                // in the same impl block.
+                let parent_trait_ref = self
+                    .0
+                    .parent_trait_ref()
+                    .expect("impl trait in assoc type collector used on non-assoc item");
+                // If the trait ref of the associated item and the impl differs,
+                // then we can't use the impl's identity substitutions below, so
+                // just skip.
+                if alias_ty.trait_ref(self.0.tcx) == parent_trait_ref {
+                    let parent = self.0.parent().expect("we should have a parent here");
+
+                    for &assoc in self.0.tcx.associated_items(parent).in_definition_order() {
+                        trace!(?assoc);
+                        if assoc.trait_item_def_id != Some(alias_ty.def_id) {
+                            continue;
+                        }
+
+                        // If the type is further specializable, then the type_of
+                        // is not actually correct below.
+                        if !assoc.defaultness(self.0.tcx).is_final() {
+                            continue;
+                        }
+
+                        let impl_args = alias_ty.args.rebase_onto(
+                            self.0.tcx,
+                            parent_trait_ref.def_id,
+                            ty::GenericArgs::identity_for_item(self.0.tcx, parent),
+                        );
+
+                        if check_args_compatible(self.0.tcx, assoc, impl_args) {
+                            return self
+                                .0
+                                .tcx
+                                .type_of(assoc.def_id)
+                                .instantiate(self.0.tcx, impl_args)
+                                .visit_with(self);
+                        } else {
+                            self.0.tcx.dcx().span_delayed_bug(
+                                self.0.tcx.def_span(assoc.def_id),
+                                "item had incorrect args",
+                            );
+                        }
+                    }
+                }
+            }
+            _ => trace!(kind=?t.kind()),
+        }
+        ControlFlow::Continue(())
+    }
+}
+
+fn impl_trait_in_assoc_types_defined_by<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item: LocalDefId,
+) -> &'tcx ty::List<LocalDefId> {
+    let mut collector = ImplTraitInAssocTypeCollector(OpaqueTypeCollector::new(tcx, item));
+    super::sig_types::walk_types(tcx, item, &mut collector);
+    tcx.mk_local_def_ids(&collector.0.opaques)
+}
+
 fn opaque_types_defined_by<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: LocalDefId,
@@ -321,5 +409,6 @@ fn opaque_types_defined_by<'tcx>(
 }
 
 pub(super) fn provide(providers: &mut Providers) {
-    *providers = Providers { opaque_types_defined_by, ..*providers };
+    *providers =
+        Providers { opaque_types_defined_by, impl_trait_in_assoc_types_defined_by, ..*providers };
 }