about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-09-21 22:09:47 +0000
committerbors <bors@rust-lang.org>2024-09-21 22:09:47 +0000
commit764e6aec81517cde60214ccd00a709a34eb0c07d (patch)
tree098f6fe0dcc9a44cb5280b813bda474854d0a1e5
parent1d68e6dd1deef26c5aeb91aee554edbee8b6d5e2 (diff)
parent52f146d363504d25b5e2fe468cadc2f50315da91 (diff)
downloadrust-764e6aec81517cde60214ccd00a709a34eb0c07d.tar.gz
rust-764e6aec81517cde60214ccd00a709a34eb0c07d.zip
Auto merge of #130674 - compiler-errors:rollup-yu105fl, r=compiler-errors
Rollup of 8 pull requests

Successful merges:

 - #127766 (add `extern "C-cmse-nonsecure-entry" fn` )
 - #129629 (Implement Return Type Notation (RTN)'s path form in where clauses)
 - #130408 (Avoid re-validating UTF-8 in `FromUtf8Error::into_utf8_lossy`)
 - #130651 (Add --enable-profiler to armhf dist)
 - #130653 (ABI compatibility: mention Result guarantee)
 - #130666 (Assert that `explicit_super_predicates_of` and `explicit_item_super_predicates` truly only contains bounds for the type itself)
 - #130667 (compiler: Accept "improper" ctypes in extern "rust-cold" fn)
 - #130673 (Parser: recover from `:::` to `::`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs27
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs80
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs18
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0775.md7
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0776.md4
-rw-r--r--compiler/rustc_error_codes/src/lib.rs1
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs67
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs181
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs336
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs128
-rw-r--r--compiler/rustc_lint/src/types.rs5
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs1
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs10
-rw-r--r--compiler/rustc_parse/src/parser/item.rs6
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs21
-rw-r--r--compiler/rustc_parse/src/parser/path.rs25
-rw-r--r--compiler/rustc_passes/src/check_attr.rs24
-rw-r--r--compiler/rustc_resolve/src/late.rs36
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/abi.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs1
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs2
-rw-r--r--compiler/rustc_target/src/json.rs1
-rw-r--r--compiler/rustc_target/src/spec/abi/mod.rs23
-rw-r--r--compiler/rustc_target/src/spec/mod.rs5
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs1
-rw-r--r--compiler/stable_mir/src/abi.rs1
-rw-r--r--compiler/stable_mir/src/ty.rs1
-rw-r--r--library/alloc/src/string.rs26
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/string.rs37
-rw-r--r--library/core/src/primitive_docs.rs2
-rw-r--r--src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile2
-rw-r--r--src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs1
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs1
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/assembly/cmse.rs26
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs18
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr39
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bare-path.rs5
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr51
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs52
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs42
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs7
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr19
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs42
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr49
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs27
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr54
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs24
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr34
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-missing.rs25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr33
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs15
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr23
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs21
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr30
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs27
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs22
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr29
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr36
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-works.rs23
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-works.stderr11
-rw-r--r--tests/ui/attributes/issue-105594-invalid-attr-validation.rs6
-rw-r--r--tests/ui/attributes/issue-105594-invalid-attr-validation.stderr21
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs20
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs7
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr18
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr11
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs12
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs17
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs25
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs16
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr9
-rw-r--r--tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs14
-rw-r--r--tests/ui/parser/triple-colon-delegation.fixed44
-rw-r--r--tests/ui/parser/triple-colon-delegation.rs44
-rw-r--r--tests/ui/parser/triple-colon-delegation.stderr38
-rw-r--r--tests/ui/parser/triple-colon.fixed23
-rw-r--r--tests/ui/parser/triple-colon.rs23
-rw-r--r--tests/ui/parser/triple-colon.stderr146
-rw-r--r--tests/ui/print-calling-conventions.stdout1
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs1
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr14
-rw-r--r--tests/ui/suggestions/let-binding-init-expr-as-ty.rs4
-rw-r--r--tests/ui/suggestions/let-binding-init-expr-as-ty.stderr23
115 files changed, 2213 insertions, 455 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index a9d1ee5c9c1..6c966c9f73a 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -20,8 +20,8 @@ use super::errors::{
 };
 use super::LoweringContext;
 use crate::{
-    fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode,
-    ResolverAstLoweringExt,
+    fluent_generated as fluent, AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition,
+    ParamMode, ResolverAstLoweringExt,
 };
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
@@ -201,6 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 &sym.qself,
                                 &sym.path,
                                 ParamMode::Optional,
+                                AllowReturnTypeNotation::No,
                                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                                 None,
                             );
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index ac527df474a..97483e85f77 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -52,7 +52,7 @@ use rustc_target::spec::abi;
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
-use crate::{ImplTraitPosition, ResolverAstLoweringExt};
+use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};
 
 pub(crate) struct DelegationResults<'hir> {
     pub body_id: hir::BodyId,
@@ -340,6 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 &delegation.qself,
                 &delegation.path,
                 ParamMode::Optional,
+                AllowReturnTypeNotation::No,
                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                 None,
             );
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index e105026ebd1..974144cc8d9 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -23,7 +23,7 @@ use super::{
     GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
 };
 use crate::errors::YieldInClosure;
-use crate::{fluent_generated, FnDeclKind, ImplTraitPosition};
+use crate::{fluent_generated, AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition};
 
 impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -281,6 +281,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         qself,
                         path,
                         ParamMode::Optional,
+                        AllowReturnTypeNotation::No,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         None,
                     );
@@ -328,6 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             &se.qself,
                             &se.path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         )),
@@ -1291,6 +1293,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         qself,
                         path,
                         ParamMode::Optional,
+                        AllowReturnTypeNotation::No,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         None,
                     );
@@ -1311,6 +1314,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         qself,
                         path,
                         ParamMode::Optional,
+                        AllowReturnTypeNotation::No,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         None,
                     );
@@ -1336,6 +1340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     &se.qself,
                     &se.path,
                     ParamMode::Optional,
+                    AllowReturnTypeNotation::No,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                     None,
                 );
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index efd3ae336af..d13e26d2510 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -485,9 +485,23 @@ enum ParamMode {
     Optional,
 }
 
+#[derive(Copy, Clone, Debug)]
+enum AllowReturnTypeNotation {
+    /// Only in types, since RTN is denied later during HIR lowering.
+    Yes,
+    /// All other positions (path expr, method, use tree).
+    No,
+}
+
 enum GenericArgsMode {
+    /// Allow paren sugar, don't allow RTN.
     ParenSugar,
+    /// Allow RTN, don't allow paren sugar.
+    ReturnTypeNotation,
+    // Error if parenthesized generics or RTN are encountered.
     Err,
+    /// Silence errors when lowering generics. Only used with `Res::Err`.
+    Silence,
 }
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
@@ -1226,7 +1240,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         let id = self.lower_node_id(t.id);
-        let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
+        let qpath = self.lower_qpath(
+            t.id,
+            qself,
+            path,
+            param_mode,
+            AllowReturnTypeNotation::Yes,
+            itctx,
+            None,
+        );
         self.ty_path(id, t.span, qpath)
     }
 
@@ -2203,6 +2225,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             &None,
             &p.path,
             ParamMode::Explicit,
+            AllowReturnTypeNotation::No,
             itctx,
             Some(modifiers),
         ) {
@@ -2341,6 +2364,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     &None,
                     path,
                     ParamMode::Optional,
+                    AllowReturnTypeNotation::No,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                     None,
                 );
@@ -2419,6 +2443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 qself,
                 path,
                 ParamMode::Optional,
+                AllowReturnTypeNotation::No,
                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                 None,
             );
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index d82bdd526b7..584d94ebe2d 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -11,7 +11,7 @@ use super::errors::{
     ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
 };
 use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt};
-use crate::ImplTraitPosition;
+use crate::{AllowReturnTypeNotation, ImplTraitPosition};
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
@@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         );
@@ -55,6 +56,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         );
@@ -66,6 +68,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         );
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 2ab30eff6d8..03c8097e4c3 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
 use rustc_middle::span_bug;
+use rustc_session::parse::add_feature_diagnostics;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
@@ -15,10 +16,9 @@ use super::errors::{
     GenericTypeWithParentheses, UseAngleBrackets,
 };
 use super::{
-    GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode,
-    ResolverAstLoweringExt,
+    AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
+    LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt,
 };
-use crate::ImplTraitPosition;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     #[instrument(level = "trace", skip(self))]
@@ -28,6 +28,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         qself: &Option<ptr::P<QSelf>>,
         p: &Path,
         param_mode: ParamMode,
+        allow_return_type_notation: AllowReturnTypeNotation,
         itctx: ImplTraitContext,
         // modifiers of the impl/bound if this is a trait path
         modifiers: Option<ast::TraitBoundModifiers>,
@@ -103,8 +104,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         {
                             GenericArgsMode::ParenSugar
                         }
+                        Res::Def(DefKind::AssocFn, _) if i + 1 == proj_start => {
+                            match allow_return_type_notation {
+                                AllowReturnTypeNotation::Yes => GenericArgsMode::ReturnTypeNotation,
+                                AllowReturnTypeNotation::No => GenericArgsMode::Err,
+                            }
+                        }
                         // Avoid duplicated errors.
-                        Res::Err => GenericArgsMode::ParenSugar,
+                        Res::Err => GenericArgsMode::Silence,
                         // An error
                         _ => GenericArgsMode::Err,
                     };
@@ -164,11 +171,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
         // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
         for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
+            // If this is a type-dependent `T::method(..)`.
+            let generic_args_mode = if i + 1 == p.segments.len()
+                && matches!(allow_return_type_notation, AllowReturnTypeNotation::Yes)
+            {
+                GenericArgsMode::ReturnTypeNotation
+            } else {
+                GenericArgsMode::Err
+            };
+
             let hir_segment = self.arena.alloc(self.lower_path_segment(
                 p.span,
                 segment,
                 param_mode,
-                GenericArgsMode::Err,
+                generic_args_mode,
                 itctx,
                 None,
             ));
@@ -238,11 +254,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
                 }
                 GenericArgs::Parenthesized(data) => match generic_args_mode {
-                    GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data(
-                        data,
-                        itctx,
-                        bound_modifier_allowed_features,
-                    ),
+                    GenericArgsMode::ReturnTypeNotation => {
+                        let mut err = if !data.inputs.is_empty() {
+                            self.dcx().create_err(BadReturnTypeNotation::Inputs {
+                                span: data.inputs_span,
+                            })
+                        } else if let FnRetTy::Ty(ty) = &data.output {
+                            self.dcx().create_err(BadReturnTypeNotation::Output {
+                                span: data.inputs_span.shrink_to_hi().to(ty.span),
+                            })
+                        } else {
+                            self.dcx().create_err(BadReturnTypeNotation::NeedsDots {
+                                span: data.inputs_span,
+                            })
+                        };
+                        if !self.tcx.features().return_type_notation
+                            && self.tcx.sess.is_nightly_build()
+                        {
+                            add_feature_diagnostics(
+                                &mut err,
+                                &self.tcx.sess,
+                                sym::return_type_notation,
+                            );
+                        }
+                        err.emit();
+                        (
+                            GenericArgsCtor {
+                                args: Default::default(),
+                                constraints: &[],
+                                parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
+                                span: path_span,
+                            },
+                            false,
+                        )
+                    }
+                    GenericArgsMode::ParenSugar | GenericArgsMode::Silence => self
+                        .lower_parenthesized_parameter_data(
+                            data,
+                            itctx,
+                            bound_modifier_allowed_features,
+                        ),
                     GenericArgsMode::Err => {
                         // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
                         let sub = if !data.inputs.is_empty() {
@@ -279,7 +330,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                 },
                 GenericArgs::ParenthesizedElided(span) => {
-                    self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
+                    match generic_args_mode {
+                        GenericArgsMode::ReturnTypeNotation | GenericArgsMode::Silence => {
+                            // Ok
+                        }
+                        GenericArgsMode::ParenSugar | GenericArgsMode::Err => {
+                            self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
+                        }
+                    }
                     (
                         GenericArgsCtor {
                             args: Default::default(),
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 24cf3f061a5..8838b15d29d 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -61,6 +61,9 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call
         Conv::CCmseNonSecureCall => {
             sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented");
         }
+        Conv::CCmseNonSecureEntry => {
+            sess.dcx().fatal("C-cmse-nonsecure-entry call conv is not yet implemented");
+        }
 
         Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => {
             unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 26718792f5f..0fa8c9d3f19 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -422,6 +422,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         if let Conv::RiscvInterrupt { kind } = self.conv {
             func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str()));
         }
+        if let Conv::CCmseNonSecureEntry = self.conv {
+            func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"))
+        }
         attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs });
 
         let mut i = 0;
@@ -659,9 +662,11 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
 impl From<Conv> for llvm::CallConv {
     fn from(conv: Conv) -> Self {
         match conv {
-            Conv::C | Conv::Rust | Conv::CCmseNonSecureCall | Conv::RiscvInterrupt { .. } => {
-                llvm::CCallConv
-            }
+            Conv::C
+            | Conv::Rust
+            | Conv::CCmseNonSecureCall
+            | Conv::CCmseNonSecureEntry
+            | Conv::RiscvInterrupt { .. } => llvm::CCallConv,
             Conv::Cold => llvm::ColdCallConv,
             Conv::PreserveMost => llvm::PreserveMost,
             Conv::PreserveAll => llvm::PreserveAll,
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 6df63eec513..489259da856 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -483,9 +483,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
         let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
         attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
     }
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
-        to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));
-    }
     if let Some(align) = codegen_fn_attrs.alignment {
         llvm::set_alignment(llfn, align);
     }
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 137e481f08c..9bd8a84f5a3 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -195,24 +195,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     }
                 }
             }
-            sym::cmse_nonsecure_entry => {
-                if let Some(fn_sig) = fn_sig()
-                    && !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
-                {
-                    struct_span_code_err!(
-                        tcx.dcx(),
-                        attr.span,
-                        E0776,
-                        "`#[cmse_nonsecure_entry]` requires C ABI"
-                    )
-                    .emit();
-                }
-                if !tcx.sess.target.llvm_target.contains("thumbv8m") {
-                    struct_span_code_err!(tcx.dcx(), attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
-                    .emit();
-                }
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY
-            }
             sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
             sym::track_caller => {
                 let is_closure = tcx.is_closure_like(did.to_def_id());
diff --git a/compiler/rustc_error_codes/src/error_codes/E0775.md b/compiler/rustc_error_codes/src/error_codes/E0775.md
index 9bafd52f75c..efbd51e89ea 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0775.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0775.md
@@ -1,13 +1,14 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M
 extension.
 
 Erroneous code example:
 
-```compile_fail,E0775
+```ignore (no longer emitted)
 #![feature(cmse_nonsecure_entry)]
 
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function() {}
+pub extern "C-cmse-nonsecure-entry" fn entry_function() {}
 ```
 
 To fix this error, compile your code for a Rust target that supports the
diff --git a/compiler/rustc_error_codes/src/error_codes/E0776.md b/compiler/rustc_error_codes/src/error_codes/E0776.md
index d65beebe07c..e46d498d1c2 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0776.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0776.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `#[cmse_nonsecure_entry]` functions require a C ABI
 
 Erroneous code example:
 
-```compile_fail,E0776
+```ignore (no longer emitted)
 #![feature(cmse_nonsecure_entry)]
 
 #[no_mangle]
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 11cad0b8f97..8631de65ec8 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -681,4 +681,5 @@ E0800: 0800,
 //  E0723, // unstable feature in `const` context
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
 //  E0744, // merged into E0728
+//  E0776, // Removed; cmse_nonsecure_entry is now `C-cmse-nonsecure-entry`
 //  E0796, // unused error code. We use `static_mut_refs` lint instead.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 3b7e0d82d0f..fa5f152132a 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -551,10 +551,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         EncodeCrossCrate::No, experimental!(register_tool),
     ),
 
-    gated!(
-        cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, experimental!(cmse_nonsecure_entry)
-    ),
     // RFC 2632
     gated!(
         const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl,
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 40333c3953a..edc8e5f0752 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -395,7 +395,7 @@ declare_features! (
     (unstable, closure_lifetime_binder, "1.64.0", Some(97362)),
     /// Allows `#[track_caller]` on closures and coroutines.
     (unstable, closure_track_caller, "1.57.0", Some(87417)),
-    /// Allows to use the `#[cmse_nonsecure_entry]` attribute.
+    /// Allows `extern "C-cmse-nonsecure-entry" fn()`.
     (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
     /// Allows `async {}` expressions in const contexts.
     (unstable, const_async_blocks, "1.53.0", Some(85368)),
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 0fe1e348498..09d466339ff 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -37,7 +37,7 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
 
 hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here
 
-hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated {$what} of a trait with uninferred generic parameters
     .suggestion = use a fully qualified path with inferred lifetimes
 
 hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
@@ -48,6 +48,8 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh
 
 hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found}
 
+hir_analysis_bad_return_type_notation_position = return type notation not allowed in this position yet
+
 hir_analysis_cannot_capture_late_bound_const =
     cannot capture late-bound const parameter in {$what}
     .label = parameter defined here
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index d0b0c08aa79..14ea7816291 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -9,6 +9,8 @@ use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
+use crate::hir_ty_lowering::OnlySelfBounds;
+
 /// Collects together a list of type bounds. These lists of bounds occur in many places
 /// in Rust's syntax:
 ///
@@ -50,6 +52,7 @@ impl<'tcx> Bounds<'tcx> {
         span: Span,
         polarity: ty::PredicatePolarity,
         constness: ty::BoundConstness,
+        only_self_bounds: OnlySelfBounds,
     ) {
         let clause = (
             bound_trait_ref
@@ -66,7 +69,10 @@ impl<'tcx> Bounds<'tcx> {
             self.clauses.push(clause);
         }
 
-        if !tcx.features().effects {
+        // FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
+        // Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
+        // type bounds.
+        if !tcx.features().effects || only_self_bounds.0 {
             return;
         }
         // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ac9976148e2..4c59f7540ee 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -460,7 +460,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                                 [] => (generics.span, format!("<{lt_name}>")),
                                 [bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
                             };
-                            mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+                            mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
                                 fspan: lt_sp,
                                 first: sugg,
                                 sspan: span.with_hi(item_segment.ident.span.lo()),
@@ -502,11 +502,12 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
             }
             Ty::new_error(
                 self.tcx(),
-                self.tcx().dcx().emit_err(errors::AssociatedTypeTraitUninferredGenericParams {
+                self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
                     span,
                     inferred_sugg,
                     bound,
                     mpart_sugg,
+                    what: "type",
                 }),
             )
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index d62727e76b5..7a254c884c2 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -10,6 +10,7 @@ use rustc_span::Span;
 use rustc_type_ir::Upcast;
 use tracing::{debug, instrument};
 
+use super::predicates_of::assert_only_contains_predicates_from;
 use super::ItemCtxt;
 use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
 
@@ -56,6 +57,9 @@ fn associated_type_bounds<'tcx>(
         tcx.def_path_str(assoc_item_def_id.to_def_id()),
         all_bounds
     );
+
+    assert_only_contains_predicates_from(filter, all_bounds, item_ty);
+
     all_bounds
 }
 
@@ -108,18 +112,21 @@ pub(super) fn explicit_item_bounds_with_filter(
         Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
             let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item();
             let opaque_ty = item.expect_opaque_ty();
-            return ty::EarlyBinder::bind(opaque_type_bounds(
+            let item_ty = Ty::new_projection_from_args(
+                tcx,
+                def_id.to_def_id(),
+                ty::GenericArgs::identity_for_item(tcx, def_id),
+            );
+            let bounds = opaque_type_bounds(
                 tcx,
                 opaque_def_id.expect_local(),
                 opaque_ty.bounds,
-                Ty::new_projection_from_args(
-                    tcx,
-                    def_id.to_def_id(),
-                    ty::GenericArgs::identity_for_item(tcx, def_id),
-                ),
+                item_ty,
                 item.span,
                 filter,
-            ));
+            );
+            assert_only_contains_predicates_from(filter, bounds, item_ty);
+            return ty::EarlyBinder::bind(bounds);
         }
         Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
             tcx.def_span(def_id),
@@ -167,7 +174,9 @@ pub(super) fn explicit_item_bounds_with_filter(
         }) => {
             let args = GenericArgs::identity_for_item(tcx, def_id);
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
-            opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
+            let bounds = opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter);
+            assert_only_contains_predicates_from(filter, bounds, item_ty);
+            bounds
         }
         // Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're
         // asking for the item bounds of the *opaques* in a trait's default method signature, we
@@ -184,15 +193,18 @@ pub(super) fn explicit_item_bounds_with_filter(
             };
             let args = GenericArgs::identity_for_item(tcx, def_id);
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
-            tcx.arena.alloc_slice(
+            let bounds = &*tcx.arena.alloc_slice(
                 &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
                     .to_vec()
                     .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
-            )
+            );
+            assert_only_contains_predicates_from(filter, bounds, item_ty);
+            bounds
         }
         hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
         _ => bug!("item_bounds called on {:?}", def_id),
     };
+
     ty::EarlyBinder::bind(bounds)
 }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 7243e85ce98..67d8813d1f7 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -240,7 +240,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     for predicate in hir_generics.predicates {
         match predicate {
             hir::WherePredicate::BoundPredicate(bound_pred) => {
-                let ty = icx.lower_ty(bound_pred.bounded_ty);
+                let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
+
                 let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
                 // Keep the type around in a dummy predicate, in case of no bounds.
                 // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
@@ -676,9 +677,63 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
         _ => {}
     }
 
+    assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
+
     ty::EarlyBinder::bind(implied_bounds)
 }
 
+// Make sure when elaborating supertraits, probing for associated types, etc.,
+// we really truly are elaborating clauses that have `Self` as their self type.
+// This is very important since downstream code relies on this being correct.
+pub(super) fn assert_only_contains_predicates_from<'tcx>(
+    filter: PredicateFilter,
+    bounds: &'tcx [(ty::Clause<'tcx>, Span)],
+    ty: Ty<'tcx>,
+) {
+    if !cfg!(debug_assertions) {
+        return;
+    }
+
+    match filter {
+        PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
+            for (clause, _) in bounds {
+                match clause.kind().skip_binder() {
+                    ty::ClauseKind::Trait(trait_predicate) => {
+                        assert_eq!(
+                            trait_predicate.self_ty(),
+                            ty,
+                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                    ty::ClauseKind::Projection(projection_predicate) => {
+                        assert_eq!(
+                            projection_predicate.self_ty(),
+                            ty,
+                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                    ty::ClauseKind::TypeOutlives(outlives_predicate) => {
+                        assert_eq!(
+                            outlives_predicate.0, ty,
+                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+
+                    ty::ClauseKind::RegionOutlives(_)
+                    | ty::ClauseKind::ConstArgHasType(_, _)
+                    | ty::ClauseKind::WellFormed(_)
+                    | ty::ClauseKind::ConstEvaluatable(_) => {
+                        bug!(
+                            "unexpected non-`Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                }
+            }
+        }
+        PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
+    }
+}
+
 /// Returns the predicates defined on `item_def_id` of the form
 /// `X: Foo` where `X` is the type parameter `def_id`.
 #[instrument(level = "trace", skip(tcx))]
@@ -770,6 +825,10 @@ impl<'tcx> ItemCtxt<'tcx> {
                 continue;
             };
 
+            // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
+            // want to only consider predicates with `Self: ...`, but we don't want
+            // `OnlySelfBounds(true)` since we want to collect the nested associated
+            // type bound as well.
             let (only_self_bounds, assoc_name) = match filter {
                 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
                     (OnlySelfBounds(false), None)
@@ -780,14 +839,10 @@ impl<'tcx> ItemCtxt<'tcx> {
                 }
             };
 
-            // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
-            // want to only consider predicates with `Self: ...`, but we don't want
-            // `OnlySelfBounds(true)` since we want to collect the nested associated
-            // type bound as well.
             let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
                 ty
             } else if matches!(filter, PredicateFilter::All) {
-                self.lower_ty(predicate.bounded_ty)
+                self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty)
             } else {
                 continue;
             };
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 53dcede91c3..d1601446b6f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -889,7 +889,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                             (pair, r)
                         })
                         .unzip();
+
                 self.record_late_bound_vars(hir_id, binders);
+
+                // If this is an RTN type in the self type, then append those to the binder.
+                self.try_append_return_type_notation_params(hir_id, bounded_ty);
+
                 // Even if there are no lifetimes defined here, we still wrap it in a binder
                 // scope. If there happens to be a nested poly trait ref (an error), that
                 // will be `Concatenating` anyways, so we don't have to worry about the depth
@@ -1635,9 +1640,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             // }
             // ```
             // and a bound that looks like:
-            //    `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
+            //    `for<'a> T::Trait<'a, x(..): for<'b> Other<'b>>`
             // this is going to expand to something like:
-            //    `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
+            //    `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
             if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
             {
                 let bound_vars = if let Some(type_def_id) = type_def_id
@@ -1839,6 +1844,178 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id);
         assert_eq!(old_value, Some(bad_def));
     }
+
+    // When we have a return type notation type in a where clause, like
+    // `where <T as Trait>::method(..): Send`, we need to introduce new bound
+    // vars to the existing where clause's binder, to represent the lifetimes
+    // elided by the return-type-notation syntax.
+    //
+    // For example, given
+    // ```
+    // trait Foo {
+    //     async fn x<'r>();
+    // }
+    // ```
+    // and a bound that looks like:
+    //    `for<'a, 'b> <T as Trait<'a>>::x(): Other<'b>`
+    // this is going to expand to something like:
+    //    `for<'a, 'b, 'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`.
+    //
+    // We handle this similarly for associated-type-bound style return-type-notation
+    // in `visit_segment_args`.
+    fn try_append_return_type_notation_params(
+        &mut self,
+        hir_id: HirId,
+        hir_ty: &'tcx hir::Ty<'tcx>,
+    ) {
+        let hir::TyKind::Path(qpath) = hir_ty.kind else {
+            // We only care about path types here. All other self types
+            // (including nesting the RTN type in another type) don't do
+            // anything.
+            return;
+        };
+
+        let (mut bound_vars, item_def_id, item_segment) = match qpath {
+            // If we have a fully qualified method, then we don't need to do any special lookup.
+            hir::QPath::Resolved(_, path)
+                if let [.., item_segment] = &path.segments[..]
+                    && item_segment.args.is_some_and(|args| {
+                        matches!(
+                            args.parenthesized,
+                            hir::GenericArgsParentheses::ReturnTypeNotation
+                        )
+                    }) =>
+            {
+                match path.res {
+                    Res::Err => return,
+                    Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment),
+                    _ => bug!("only expected method resolution for fully qualified RTN"),
+                }
+            }
+
+            // If we have a type-dependent path, then we do need to do some lookup.
+            hir::QPath::TypeRelative(qself, item_segment)
+                if item_segment.args.is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                // First, ignore a qself that isn't a type or `Self` param. Those are the
+                // only ones that support `T::Assoc` anyways in HIR lowering.
+                let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else {
+                    return;
+                };
+                match path.res {
+                    Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
+                        // Get the generics of this type's hir owner. This is *different*
+                        // from the generics of the parameter's definition, since we want
+                        // to be able to resolve an RTN path on a nested body (e.g. method
+                        // inside an impl) using the where clauses on the method.
+                        // FIXME(return_type_notation): Think of some better way of doing this.
+                        let Some(generics) = self.tcx.hir_owner_node(hir_id.owner).generics()
+                        else {
+                            return;
+                        };
+
+                        // Look for the first bound that contains an associated type that
+                        // matches the segment that we're looking for. We ignore any subsequent
+                        // bounds since we'll be emitting a hard error in HIR lowering, so this
+                        // is purely speculative.
+                        let one_bound = generics.predicates.iter().find_map(|predicate| {
+                            let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
+                                return None;
+                            };
+                            let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
+                                predicate.bounded_ty.kind
+                            else {
+                                return None;
+                            };
+                            if bounded_path.res != path.res {
+                                return None;
+                            }
+                            predicate.bounds.iter().find_map(|bound| {
+                                let hir::GenericBound::Trait(trait_, _) = bound else {
+                                    return None;
+                                };
+                                BoundVarContext::supertrait_hrtb_vars(
+                                    self.tcx,
+                                    trait_.trait_ref.trait_def_id()?,
+                                    item_segment.ident,
+                                    ty::AssocKind::Fn,
+                                )
+                            })
+                        });
+                        let Some((bound_vars, assoc_item)) = one_bound else {
+                            return;
+                        };
+                        (bound_vars, assoc_item.def_id, item_segment)
+                    }
+                    // If we have a self type alias (in an impl), try to resolve an
+                    // associated item from one of the supertraits of the impl's trait.
+                    Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => {
+                        let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self
+                            .tcx
+                            .hir_node_by_def_id(impl_def_id.expect_local())
+                            .expect_item()
+                            .kind
+                        else {
+                            return;
+                        };
+                        let Some(trait_def_id) = trait_ref.trait_def_id() else {
+                            return;
+                        };
+                        let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars(
+                            self.tcx,
+                            trait_def_id,
+                            item_segment.ident,
+                            ty::AssocKind::Fn,
+                        ) else {
+                            return;
+                        };
+                        (bound_vars, assoc_item.def_id, item_segment)
+                    }
+                    _ => return,
+                }
+            }
+
+            _ => return,
+        };
+
+        // Append the early-bound vars on the function, and then the late-bound ones.
+        // We actually turn type parameters into higher-ranked types here, but we
+        // deny them later in HIR lowering.
+        bound_vars.extend(self.tcx.generics_of(item_def_id).own_params.iter().map(|param| {
+            match param.kind {
+                ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
+                    ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                ),
+                ty::GenericParamDefKind::Type { .. } => {
+                    ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name))
+                }
+                ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
+            }
+        }));
+        bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars());
+
+        // SUBTLE: Stash the old bound vars onto the *item segment* before appending
+        // the new bound vars. We do this because we need to know how many bound vars
+        // are present on the binder explicitly (i.e. not return-type-notation vars)
+        // to do bound var shifting correctly in HIR lowering.
+        //
+        // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
+        // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
+        // parent) will include `'a` AND all the early- and late-bound vars of the
+        // method. But when lowering the RTN type, we just want the list of vars
+        // we used to resolve the trait ref. We explicitly stored those back onto
+        // the item segment, since there's no other good place to put them.
+        //
+        // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
+        // And this is exercised in:
+        // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
+        let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap();
+        let existing_bound_vars_saved = existing_bound_vars.clone();
+        existing_bound_vars.extend(bound_vars);
+        self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
+    }
 }
 
 /// Detects late-bound lifetimes and inserts them into
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index e4e5f76ae32..4edb68e6199 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -780,14 +780,15 @@ pub(crate) struct PlaceholderNotAllowedItemSignatures {
 
 #[derive(Diagnostic)]
 #[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)]
-pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
+pub(crate) struct AssociatedItemTraitUninferredGenericParams {
     #[primary_span]
     pub span: Span,
     #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")]
     pub inferred_sugg: Option<Span>,
     pub bound: String,
     #[subdiagnostic]
-    pub mpart_sugg: Option<AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion>,
+    pub mpart_sugg: Option<AssociatedItemTraitUninferredGenericParamsMultipartSuggestion>,
+    pub what: &'static str,
 }
 
 #[derive(Subdiagnostic)]
@@ -795,7 +796,7 @@ pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
     hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion,
     applicability = "maybe-incorrect"
 )]
-pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
     #[suggestion_part(code = "{first}")]
     pub fspan: Span,
     pub first: String,
@@ -1693,3 +1694,10 @@ pub(crate) struct CmseCallGeneric {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_bad_return_type_notation_position)]
+pub(crate) struct BadReturnTypeNotation {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index bffe68f9b74..6f7f3128347 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -6,6 +6,7 @@ use rustc_errors::struct_span_code_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::HirId;
 use rustc_middle::bug;
 use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -15,6 +16,7 @@ use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
+use super::errors::GenericsArgsErrExtend;
 use crate::bounds::Bounds;
 use crate::errors;
 use crate::hir_ty_lowering::{
@@ -332,74 +334,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             .or_insert(constraint.span);
 
         let projection_term = if let ty::AssocKind::Fn = assoc_kind {
-            let mut emitted_bad_param_err = None;
-            // If we have an method return type bound, then we need to instantiate
-            // the method's early bound params with suitable late-bound params.
-            let mut num_bound_vars = candidate.bound_vars().len();
-            let args =
-                candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| {
-                    let arg = match param.kind {
-                        ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
-                            tcx,
-                            ty::INNERMOST,
-                            ty::BoundRegion {
-                                var: ty::BoundVar::from_usize(num_bound_vars),
-                                kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
-                            },
-                        )
-                        .into(),
-                        ty::GenericParamDefKind::Type { .. } => {
-                            let guar = *emitted_bad_param_err.get_or_insert_with(|| {
-                                self.dcx().emit_err(
-                                    crate::errors::ReturnTypeNotationIllegalParam::Type {
-                                        span: path_span,
-                                        param_span: tcx.def_span(param.def_id),
-                                    },
-                                )
-                            });
-                            Ty::new_error(tcx, guar).into()
-                        }
-                        ty::GenericParamDefKind::Const { .. } => {
-                            let guar = *emitted_bad_param_err.get_or_insert_with(|| {
-                                self.dcx().emit_err(
-                                    crate::errors::ReturnTypeNotationIllegalParam::Const {
-                                        span: path_span,
-                                        param_span: tcx.def_span(param.def_id),
-                                    },
-                                )
-                            });
-                            ty::Const::new_error(tcx, guar).into()
-                        }
-                    };
-                    num_bound_vars += 1;
-                    arg
-                });
-
-            // Next, we need to check that the return-type notation is being used on
-            // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
-            let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output();
-            let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
-                && tcx.is_impl_trait_in_trait(alias_ty.def_id)
-            {
-                alias_ty.into()
-            } else {
-                return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
-                    span: constraint.span,
-                    ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output),
-                    fn_span: tcx.hir().span_if_local(assoc_item.def_id),
-                    note: (),
-                }));
-            };
-
-            // Finally, move the fn return type's bound vars over to account for the early bound
-            // params (and trait ref's late bound params). This logic is very similar to
-            // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
-            // and it's no coincidence why.
-            let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
-            let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
-
             let bound_vars = tcx.late_bound_vars(constraint.hir_id);
-            ty::Binder::bind_with_vars(instantiation_output, bound_vars)
+            ty::Binder::bind_with_vars(
+                self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
+                bound_vars,
+            )
         } else {
             // Create the generic arguments for the associated type or constant by joining the
             // parent arguments (the arguments of the trait) and the own arguments (the ones of
@@ -525,6 +464,269 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
         Ok(())
     }
+
+    /// Lower a type, possibly specially handling the type if it's a return type notation
+    /// which we otherwise deny in other positions.
+    pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
+        let hir::TyKind::Path(qpath) = hir_ty.kind else {
+            return self.lower_ty(hir_ty);
+        };
+
+        let tcx = self.tcx();
+        match qpath {
+            hir::QPath::Resolved(opt_self_ty, path)
+                if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
+                    && item_segment.args.is_some_and(|args| {
+                        matches!(
+                            args.parenthesized,
+                            hir::GenericArgsParentheses::ReturnTypeNotation
+                        )
+                    }) =>
+            {
+                // We don't allow generics on the module segments.
+                let _ =
+                    self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
+
+                let item_def_id = match path.res {
+                    Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
+                    Res::Err => {
+                        return Ty::new_error_with_message(
+                            tcx,
+                            hir_ty.span,
+                            "failed to resolve RTN",
+                        );
+                    }
+                    _ => bug!("only expected method resolution for fully qualified RTN"),
+                };
+                let trait_def_id = tcx.parent(item_def_id);
+
+                // Good error for `where Trait::method(..): Send`.
+                let Some(self_ty) = opt_self_ty else {
+                    return self.error_missing_qpath_self_ty(
+                        trait_def_id,
+                        hir_ty.span,
+                        item_segment,
+                    );
+                };
+                let self_ty = self.lower_ty(self_ty);
+
+                let trait_ref = self.lower_mono_trait_ref(
+                    hir_ty.span,
+                    trait_def_id,
+                    self_ty,
+                    trait_segment,
+                    false,
+                    ty::BoundConstness::NotConst,
+                );
+
+                // SUBTLE: As noted at the end of `try_append_return_type_notation_params`
+                // in `resolve_bound_vars`, we stash the explicit bound vars of the where
+                // clause onto the item segment of the RTN type. This allows us to know
+                // how many bound vars are *not* coming from the signature of the function
+                // from lowering RTN itself.
+                //
+                // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
+                // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
+                // parent) will include `'a` AND all the early- and late-bound vars of the
+                // method. But when lowering the RTN type, we just want the list of vars
+                // we used to resolve the trait ref. We explicitly stored those back onto
+                // the item segment, since there's no other good place to put them.
+                let candidate =
+                    ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
+
+                match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
+                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
+                    Err(guar) => Ty::new_error(tcx, guar),
+                }
+            }
+            hir::QPath::TypeRelative(qself, item_segment)
+                if item_segment.args.is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                match self
+                    .resolve_type_relative_return_type_notation(
+                        qself,
+                        item_segment,
+                        hir_ty.hir_id,
+                        hir_ty.span,
+                    )
+                    .and_then(|(candidate, item_def_id)| {
+                        self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span)
+                    }) {
+                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
+                    Err(guar) => Ty::new_error(tcx, guar),
+                }
+            }
+            _ => self.lower_ty(hir_ty),
+        }
+    }
+
+    /// Perform type-dependent lookup for a *method* for return type notation.
+    /// This generally mirrors `<dyn HirTyLowerer>::lower_assoc_path`.
+    fn resolve_type_relative_return_type_notation(
+        &self,
+        qself: &'tcx hir::Ty<'tcx>,
+        item_segment: &'tcx hir::PathSegment<'tcx>,
+        qpath_hir_id: HirId,
+        span: Span,
+    ) -> Result<(ty::PolyTraitRef<'tcx>, DefId), ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let qself_ty = self.lower_ty(qself);
+        let assoc_ident = item_segment.ident;
+        let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
+            path.res
+        } else {
+            Res::Err
+        };
+
+        let bound = match (qself_ty.kind(), qself_res) {
+            (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
+                // `Self` in an impl of a trait -- we have a concrete self type and a
+                // trait reference.
+                let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
+                    // A cycle error occurred, most likely.
+                    self.dcx().span_bug(span, "expected cycle error");
+                };
+
+                self.probe_single_bound_for_assoc_item(
+                    || {
+                        traits::supertraits(
+                            tcx,
+                            ty::Binder::dummy(trait_ref.instantiate_identity()),
+                        )
+                    },
+                    AssocItemQSelf::SelfTyAlias,
+                    ty::AssocKind::Fn,
+                    assoc_ident,
+                    span,
+                    None,
+                )?
+            }
+            (
+                &ty::Param(_),
+                Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
+            ) => self.probe_single_ty_param_bound_for_assoc_item(
+                param_did.expect_local(),
+                qself.span,
+                ty::AssocKind::Fn,
+                assoc_ident,
+                span,
+            )?,
+            _ => {
+                if let Err(reported) = qself_ty.error_reported() {
+                    return Err(reported);
+                } else {
+                    // FIXME(return_type_notation): Provide some structured suggestion here.
+                    let err = struct_span_code_err!(
+                        self.dcx(),
+                        span,
+                        E0223,
+                        "ambiguous associated function"
+                    );
+                    return Err(err.emit());
+                }
+            }
+        };
+
+        // Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,
+        // which may happen via a higher-ranked where clause or supertrait.
+        // This is the same restrictions as associated types; even though we could
+        // support it, it just makes things a lot more difficult to support in
+        // `resolve_bound_vars`, since we'd need to introduce those as elided
+        // bound vars on the where clause too.
+        if bound.has_bound_vars() {
+            return Err(self.tcx().dcx().emit_err(
+                errors::AssociatedItemTraitUninferredGenericParams {
+                    span,
+                    inferred_sugg: Some(span.with_hi(item_segment.ident.span.lo())),
+                    bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder(),),
+                    mpart_sugg: None,
+                    what: "function",
+                },
+            ));
+        }
+
+        let trait_def_id = bound.def_id();
+        let assoc_ty = self
+            .probe_assoc_item(assoc_ident, ty::AssocKind::Fn, qpath_hir_id, span, trait_def_id)
+            .expect("failed to find associated type");
+
+        Ok((bound, assoc_ty.def_id))
+    }
+
+    /// Do the common parts of lowering an RTN type. This involves extending the
+    /// candidate binder to include all of the early- and late-bound vars that are
+    /// defined on the function itself, and constructing a projection to the RPITIT
+    /// return type of that function.
+    fn lower_return_type_notation_ty(
+        &self,
+        candidate: ty::PolyTraitRef<'tcx>,
+        item_def_id: DefId,
+        path_span: Span,
+    ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let mut emitted_bad_param_err = None;
+        // If we have an method return type bound, then we need to instantiate
+        // the method's early bound params with suitable late-bound params.
+        let mut num_bound_vars = candidate.bound_vars().len();
+        let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
+            let arg = match param.kind {
+                ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
+                    tcx,
+                    ty::INNERMOST,
+                    ty::BoundRegion {
+                        var: ty::BoundVar::from_usize(num_bound_vars),
+                        kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                    },
+                )
+                .into(),
+                ty::GenericParamDefKind::Type { .. } => {
+                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
+                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
+                            span: path_span,
+                            param_span: tcx.def_span(param.def_id),
+                        })
+                    });
+                    Ty::new_error(tcx, guar).into()
+                }
+                ty::GenericParamDefKind::Const { .. } => {
+                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
+                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
+                            span: path_span,
+                            param_span: tcx.def_span(param.def_id),
+                        })
+                    });
+                    ty::Const::new_error(tcx, guar).into()
+                }
+            };
+            num_bound_vars += 1;
+            arg
+        });
+
+        // Next, we need to check that the return-type notation is being used on
+        // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
+        let output = tcx.fn_sig(item_def_id).skip_binder().output();
+        let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
+            && tcx.is_impl_trait_in_trait(alias_ty.def_id)
+        {
+            alias_ty
+        } else {
+            return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
+                span: path_span,
+                ty: tcx.liberate_late_bound_regions(item_def_id, output),
+                fn_span: tcx.hir().span_if_local(item_def_id),
+                note: (),
+            }));
+        };
+
+        // Finally, move the fn return type's bound vars over to account for the early bound
+        // params (and trait ref's late bound params). This logic is very similar to
+        // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
+        // and it's no coincidence why.
+        let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
+        Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
+    }
 }
 
 /// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 7163352e8a4..35eebcb6be1 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -53,7 +53,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
 use tracing::{debug, debug_span, instrument};
 
 use crate::bounds::Bounds;
-use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
+use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy};
 use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
 use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
 use crate::middle::resolve_bound_vars as rbv;
@@ -719,6 +719,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             span,
             polarity,
             constness,
+            only_self_bounds,
         );
 
         let mut dup_constraints = FxIndexMap::default();
@@ -813,17 +814,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
-    /// Search for a trait bound on a type parameter whose trait defines the associated type given by `assoc_name`.
+    /// Search for a trait bound on a type parameter whose trait defines the associated item
+    /// given by `assoc_name` and `kind`.
     ///
     /// This fails if there is no such bound in the list of candidates or if there are multiple
     /// candidates in which case it reports ambiguity.
     ///
     /// `ty_param_def_id` is the `LocalDefId` of the type parameter.
     #[instrument(level = "debug", skip_all, ret)]
-    fn probe_single_ty_param_bound_for_assoc_ty(
+    fn probe_single_ty_param_bound_for_assoc_item(
         &self,
         ty_param_def_id: LocalDefId,
         ty_param_span: Span,
+        kind: ty::AssocKind,
         assoc_name: Ident,
         span: Span,
     ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
@@ -841,7 +844,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name)
             },
             AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
-            ty::AssocKind::Type,
+            kind,
             assoc_name,
             span,
             None,
@@ -1081,9 +1084,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             (
                 &ty::Param(_),
                 Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
-            ) => self.probe_single_ty_param_bound_for_assoc_ty(
+            ) => self.probe_single_ty_param_bound_for_assoc_item(
                 param_did.expect_local(),
                 qself.span,
+                ty::AssocKind::Type,
                 assoc_ident,
                 span,
             )?,
@@ -1545,48 +1549,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         debug!(?trait_def_id);
 
         let Some(self_ty) = opt_self_ty else {
-            let path_str = tcx.def_path_str(trait_def_id);
-
-            let def_id = self.item_def_id();
-            debug!(item_def_id = ?def_id);
-
-            // FIXME: document why/how this is different from `tcx.local_parent(def_id)`
-            let parent_def_id =
-                tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
-            debug!(?parent_def_id);
-
-            // If the trait in segment is the same as the trait defining the item,
-            // use the `<Self as ..>` syntax in the error.
-            let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
-            let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
-
-            let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
-                vec!["Self".to_string()]
-            } else {
-                // Find all the types that have an `impl` for the trait.
-                tcx.all_impls(trait_def_id)
-                    .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
-                    .filter(|header| {
-                        // Consider only accessible traits
-                        tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
-                            && header.polarity != ty::ImplPolarity::Negative
-                    })
-                    .map(|header| header.trait_ref.instantiate_identity().self_ty())
-                    // We don't care about blanket impls.
-                    .filter(|self_ty| !self_ty.has_non_region_param())
-                    .map(|self_ty| tcx.erase_regions(self_ty).to_string())
-                    .collect()
-            };
-            // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
-            // references the trait. Relevant for the first case in
-            // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
-            let reported = self.report_ambiguous_assoc_ty(
-                span,
-                &type_names,
-                &[path_str],
-                item_segment.ident.name,
-            );
-            return Ty::new_error(tcx, reported);
+            return self.error_missing_qpath_self_ty(trait_def_id, span, item_segment);
         };
         debug!(?self_ty);
 
@@ -1600,6 +1563,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         Ty::new_projection_from_args(tcx, item_def_id, item_args)
     }
 
+    fn error_missing_qpath_self_ty(
+        &self,
+        trait_def_id: DefId,
+        span: Span,
+        item_segment: &hir::PathSegment<'tcx>,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+        let path_str = tcx.def_path_str(trait_def_id);
+
+        let def_id = self.item_def_id();
+        debug!(item_def_id = ?def_id);
+
+        // FIXME: document why/how this is different from `tcx.local_parent(def_id)`
+        let parent_def_id =
+            tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
+        debug!(?parent_def_id);
+
+        // If the trait in segment is the same as the trait defining the item,
+        // use the `<Self as ..>` syntax in the error.
+        let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
+        let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
+
+        let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
+            vec!["Self".to_string()]
+        } else {
+            // Find all the types that have an `impl` for the trait.
+            tcx.all_impls(trait_def_id)
+                .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
+                .filter(|header| {
+                    // Consider only accessible traits
+                    tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
+                        && header.polarity != ty::ImplPolarity::Negative
+                })
+                .map(|header| header.trait_ref.instantiate_identity().self_ty())
+                // We don't care about blanket impls.
+                .filter(|self_ty| !self_ty.has_non_region_param())
+                .map(|self_ty| tcx.erase_regions(self_ty).to_string())
+                .collect()
+        };
+        // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
+        // references the trait. Relevant for the first case in
+        // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
+        let reported =
+            self.report_ambiguous_assoc_ty(span, &type_names, &[path_str], item_segment.ident.name);
+        Ty::new_error(tcx, reported)
+    }
+
     pub fn prohibit_generic_args<'a>(
         &self,
         segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
@@ -1930,7 +1940,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     .tcx()
                     .dcx()
                     .span_delayed_bug(path.span, "path with `Res::Err` but no error emitted");
-                Ty::new_error(self.tcx(), e)
+                Ty::new_error(tcx, e)
             }
             Res::Def(..) => {
                 assert_eq!(
@@ -2061,6 +2071,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 };
                 self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
             }
+            // If we encounter a fully qualified path with RTN generics, then it must have
+            // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
+            // it's certainly in an illegal position.
+            hir::TyKind::Path(hir::QPath::Resolved(_, path))
+                if path.segments.last().and_then(|segment| segment.args).is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
+                Ty::new_error(tcx, guar)
+            }
             hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
                 debug!(?maybe_qself, ?path);
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
@@ -2085,6 +2106,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 }
             }
+            // If we encounter a type relative path with RTN generics, then it must have
+            // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
+            // it's certainly in an illegal position.
+            hir::TyKind::Path(hir::QPath::TypeRelative(_, segment))
+                if segment.args.is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
+                Ty::new_error(tcx, guar)
+            }
             hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
                 debug!(?qself, ?segment);
                 let ty = self.lower_ty(qself);
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index f9d0cd49708..3d042f21745 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1320,7 +1320,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     }
 
     fn is_internal_abi(&self, abi: SpecAbi) -> bool {
-        matches!(abi, SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustIntrinsic)
+        matches!(
+            abi,
+            SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustCold | SpecAbi::RustIntrinsic
+        )
     }
 
     /// Find any fn-ptr types with external ABIs in `ty`.
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index b7d290e58d2..90dff0f5c7d 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -120,9 +120,7 @@ bitflags::bitflags! {
         /// #[ffi_const]: applies clang's `const` attribute to a foreign function
         /// declaration.
         const FFI_CONST                 = 1 << 12;
-        /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a
-        /// function as an entry function from Non-Secure code.
-        const CMSE_NONSECURE_ENTRY      = 1 << 13;
+        // (Bit 13 was used for `#[cmse_nonsecure_entry]`, but is now unused.)
         // (Bit 14 was used for `#[coverage(off)]`, but is now unused.)
         /// `#[used(linker)]`:
         /// indicates that neither LLVM nor the linker will eliminate this function.
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 9ed5dc87be4..941091b71d3 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1191,6 +1191,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
         | RiscvInterruptM
         | RiscvInterruptS
         | CCmseNonSecureCall
+        | CCmseNonSecureEntry
         | Unadjusted => false,
         Rust | RustCall | RustCold | RustIntrinsic => {
             tcx.sess.panic_strategy() == PanicStrategy::Unwind
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index f5aa8984f51..6cb851eb8df 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -670,7 +670,7 @@ parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call
 parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
 parse_parenthesized_lifetime_suggestion = remove the parentheses
 
-parse_path_single_colon = path separator must be a double colon
+parse_path_double_colon = path separator must be a double colon
     .suggestion = use a double colon instead
 
 parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index e3e7fcebaaa..e9fe2e6c1dd 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1571,7 +1571,7 @@ pub(crate) struct ExpectedFnPathFoundFnKeyword {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_path_single_colon)]
+#[diag(parse_path_double_colon)]
 pub(crate) struct PathSingleColon {
     #[primary_span]
     pub span: Span,
@@ -1584,6 +1584,14 @@ pub(crate) struct PathSingleColon {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_path_double_colon)]
+pub(crate) struct PathTripleColon {
+    #[primary_span]
+    #[suggestion(applicability = "maybe-incorrect", code = "", style = "verbose")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_colon_as_semi)]
 pub(crate) struct ColonAsSemi {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 104678e081c..afd9871a635 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -707,7 +707,7 @@ impl<'a> Parser<'a> {
             })
         };
 
-        let (ident, item_kind) = if self.eat(&token::PathSep) {
+        let (ident, item_kind) = if self.eat_path_sep() {
             let suffixes = if self.eat(&token::BinOp(token::Star)) {
                 None
             } else {
@@ -1054,7 +1054,7 @@ impl<'a> Parser<'a> {
         {
             // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
             let mod_sep_ctxt = self.token.span.ctxt();
-            if self.eat(&token::PathSep) {
+            if self.eat_path_sep() {
                 prefix
                     .segments
                     .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
@@ -1065,7 +1065,7 @@ impl<'a> Parser<'a> {
             // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
             prefix = self.parse_path(PathStyle::Mod)?;
 
-            if self.eat(&token::PathSep) {
+            if self.eat_path_sep() {
                 self.parse_use_tree_glob_or_nested()?
             } else {
                 // Recover from using a colon as path separator.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 9d9265d5318..3b58b2337f3 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1562,12 +1562,25 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Checks for `::` or, potentially, `:::` and then look ahead after it.
+    fn check_path_sep_and_look_ahead(&mut self, looker: impl Fn(&Token) -> bool) -> bool {
+        if self.check(&token::PathSep) {
+            if self.may_recover() && self.look_ahead(1, |t| t.kind == token::Colon) {
+                debug_assert!(!self.look_ahead(1, &looker), "Looker must not match on colon");
+                self.look_ahead(2, looker)
+            } else {
+                self.look_ahead(1, looker)
+            }
+        } else {
+            false
+        }
+    }
+
     /// `::{` or `::*`
     fn is_import_coupler(&mut self) -> bool {
-        self.check(&token::PathSep)
-            && self.look_ahead(1, |t| {
-                *t == token::OpenDelim(Delimiter::Brace) || *t == token::BinOp(token::Star)
-            })
+        self.check_path_sep_and_look_ahead(|t| {
+            matches!(t.kind, token::OpenDelim(Delimiter::Brace) | token::BinOp(token::Star))
+        })
     }
 
     // Debug view of the parser's token stream, up to `{lookahead}` tokens.
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 42039c621d6..961679b1f56 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -16,7 +16,7 @@ use tracing::debug;
 
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{Parser, Restrictions, TokenType};
-use crate::errors::PathSingleColon;
+use crate::errors::{PathSingleColon, PathTripleColon};
 use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
 use crate::{errors, maybe_whole};
 
@@ -210,7 +210,7 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
         let mut segments = ThinVec::new();
         let mod_sep_ctxt = self.token.span.ctxt();
-        if self.eat(&token::PathSep) {
+        if self.eat_path_sep() {
             segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
         }
         self.parse_path_segments(&mut segments, style, ty_generics)?;
@@ -246,7 +246,7 @@ impl<'a> Parser<'a> {
             }
             segments.push(segment);
 
-            if self.is_import_coupler() || !self.eat(&token::PathSep) {
+            if self.is_import_coupler() || !self.eat_path_sep() {
                 if style == PathStyle::Expr
                     && self.may_recover()
                     && self.token == token::Colon
@@ -272,6 +272,18 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Eat `::` or, potentially, `:::`.
+    #[must_use]
+    pub(super) fn eat_path_sep(&mut self) -> bool {
+        let result = self.eat(&token::PathSep);
+        if result && self.may_recover() {
+            if self.eat_noexpect(&token::Colon) {
+                self.dcx().emit_err(PathTripleColon { span: self.prev_token.span });
+            }
+        }
+        result
+    }
+
     pub(super) fn parse_path_segment(
         &mut self,
         style: PathStyle,
@@ -297,9 +309,7 @@ impl<'a> Parser<'a> {
 
         Ok(
             if style == PathStyle::Type && check_args_start(self)
-                || style != PathStyle::Mod
-                    && self.check(&token::PathSep)
-                    && self.look_ahead(1, |t| is_args_start(t))
+                || style != PathStyle::Mod && self.check_path_sep_and_look_ahead(is_args_start)
             {
                 // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
                 // it isn't, then we reset the unmatched angle bracket count as we're about to start
@@ -310,7 +320,8 @@ impl<'a> Parser<'a> {
 
                 // Generic arguments are found - `<`, `(`, `::<` or `::(`.
                 // First, eat `::` if it exists.
-                let _ = self.eat(&token::PathSep);
+                let _ = self.eat_path_sep();
+
                 let lo = self.token.span;
                 let args = if self.eat_lt() {
                     // `<'a, T, A = U>`
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 2f4dc8abfcd..841f255dc3a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -188,9 +188,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 | [sym::rustc_must_implement_one_of, ..]
                 | [sym::rustc_deny_explicit_impl, ..]
                 | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
-                [sym::cmse_nonsecure_entry, ..] => {
-                    self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
-                }
                 [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
                 [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
                 [sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
@@ -563,27 +560,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
-    fn check_cmse_nonsecure_entry(
-        &self,
-        hir_id: HirId,
-        attr: &Attribute,
-        span: Span,
-        target: Target,
-    ) {
-        match target {
-            Target::Fn
-            | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
-            _ => {
-                self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
-                    attr_span: attr.span,
-                    defn_span: span,
-                    on_crate: hir_id == CRATE_HIR_ID,
-                });
-            }
-        }
-    }
-
     /// Debugging aid for `object_lifetime_default` query.
     fn check_object_lifetime_default(&self, hir_id: HirId) {
         let tcx = self.tcx;
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index ac03a3ac42c..f1d9028f88c 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -404,6 +404,8 @@ pub(crate) enum PathSource<'a> {
     Delegation,
     /// An arg in a `use<'a, N>` precise-capturing bound.
     PreciseCapturingArg(Namespace),
+    // Paths that end with `(..)`, for return type notation.
+    ReturnTypeNotation,
 }
 
 impl<'a> PathSource<'a> {
@@ -413,7 +415,8 @@ impl<'a> PathSource<'a> {
             PathSource::Expr(..)
             | PathSource::Pat
             | PathSource::TupleStruct(..)
-            | PathSource::Delegation => ValueNS,
+            | PathSource::Delegation
+            | PathSource::ReturnTypeNotation => ValueNS,
             PathSource::TraitItem(ns) => ns,
             PathSource::PreciseCapturingArg(ns) => ns,
         }
@@ -425,7 +428,8 @@ impl<'a> PathSource<'a> {
             | PathSource::Expr(..)
             | PathSource::Pat
             | PathSource::Struct
-            | PathSource::TupleStruct(..) => true,
+            | PathSource::TupleStruct(..)
+            | PathSource::ReturnTypeNotation => true,
             PathSource::Trait(_)
             | PathSource::TraitItem(..)
             | PathSource::Delegation
@@ -471,7 +475,7 @@ impl<'a> PathSource<'a> {
                 },
                 _ => "value",
             },
-            PathSource::Delegation => "function",
+            PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
             PathSource::PreciseCapturingArg(..) => "type or const parameter",
         }
     }
@@ -540,6 +544,10 @@ impl<'a> PathSource<'a> {
                 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
                 _ => false,
             },
+            PathSource::ReturnTypeNotation => match res {
+                Res::Def(DefKind::AssocFn, _) => true,
+                _ => false,
+            },
             PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
             PathSource::PreciseCapturingArg(ValueNS) => {
                 matches!(res, Res::Def(DefKind::ConstParam, _))
@@ -565,8 +573,8 @@ impl<'a> PathSource<'a> {
             (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
             (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
             (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
-            (PathSource::TraitItem(..), true) => E0575,
-            (PathSource::TraitItem(..), false) => E0576,
+            (PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575,
+            (PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576,
             (PathSource::PreciseCapturingArg(..), true) => E0799,
             (PathSource::PreciseCapturingArg(..), false) => E0800,
         }
@@ -781,7 +789,20 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
             }
             TyKind::Path(qself, path) => {
                 self.diag_metadata.current_type_path = Some(ty);
-                self.smart_resolve_path(ty.id, qself, path, PathSource::Type);
+
+                // If we have a path that ends with `(..)`, then it must be
+                // return type notation. Resolve that path in the *value*
+                // namespace.
+                let source = if let Some(seg) = path.segments.last()
+                    && let Some(args) = &seg.args
+                    && matches!(**args, GenericArgs::ParenthesizedElided(..))
+                {
+                    PathSource::ReturnTypeNotation
+                } else {
+                    PathSource::Type
+                };
+
+                self.smart_resolve_path(ty.id, qself, path, source);
 
                 // Check whether we should interpret this as a bare trait object.
                 if qself.is_none()
@@ -1920,7 +1941,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 PathSource::Trait(..)
                 | PathSource::TraitItem(..)
                 | PathSource::Type
-                | PathSource::PreciseCapturingArg(..) => false,
+                | PathSource::PreciseCapturingArg(..)
+                | PathSource::ReturnTypeNotation => false,
                 PathSource::Expr(..)
                 | PathSource::Pat
                 | PathSource::Struct
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index f52cb010a87..e9c3b3ffc1d 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -470,6 +470,7 @@ impl RustcInternal for Abi {
             Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt,
             Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt,
             Abi::CCmseNonSecureCall => rustc_target::spec::abi::Abi::CCmseNonSecureCall,
+            Abi::CCmseNonSecureEntry => rustc_target::spec::abi::Abi::CCmseNonSecureEntry,
             Abi::System { unwind } => rustc_target::spec::abi::Abi::System { unwind },
             Abi::RustIntrinsic => rustc_target::spec::abi::Abi::RustIntrinsic,
             Abi::RustCall => rustc_target::spec::abi::Abi::RustCall,
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index 9f554ec6c35..06f01aebf9b 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -105,6 +105,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv {
             Conv::PreserveAll => CallConvention::PreserveAll,
             Conv::ArmAapcs => CallConvention::ArmAapcs,
             Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
+            Conv::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
             Conv::Msp430Intr => CallConvention::Msp430Intr,
             Conv::PtxKernel => CallConvention::PtxKernel,
             Conv::X86Fastcall => CallConvention::X86Fastcall,
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index efbb0f244fc..74bdf97ac44 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -910,6 +910,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::spec::abi::Abi {
             abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
             abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
             abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
+            abi::Abi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry,
             abi::Abi::System { unwind } => Abi::System { unwind },
             abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
             abi::Abi::RustCall => Abi::RustCall,
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 060ee4a1bc2..f4469467249 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -779,6 +779,7 @@ pub enum Conv {
     // Target-specific calling conventions.
     ArmAapcs,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
 
     Msp430Intr,
 
@@ -972,6 +973,7 @@ impl FromStr for Conv {
             "RustCold" => Ok(Conv::Rust),
             "ArmAapcs" => Ok(Conv::ArmAapcs),
             "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall),
+            "CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry),
             "Msp430Intr" => Ok(Conv::Msp430Intr),
             "PtxKernel" => Ok(Conv::PtxKernel),
             "X86Fastcall" => Ok(Conv::X86Fastcall),
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index 9436e34d380..5fcf5be101f 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -103,6 +103,7 @@ impl ToJson for crate::abi::call::Conv {
             Self::PreserveAll => "PreserveAll",
             Self::ArmAapcs => "ArmAapcs",
             Self::CCmseNonSecureCall => "CCmseNonSecureCall",
+            Self::CCmseNonSecureEntry => "CCmseNonSecureEntry",
             Self::Msp430Intr => "Msp430Intr",
             Self::PtxKernel => "PtxKernel",
             Self::X86Fastcall => "X86Fastcall",
diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs
index cc383f88fbc..cac0cf9959d 100644
--- a/compiler/rustc_target/src/spec/abi/mod.rs
+++ b/compiler/rustc_target/src/spec/abi/mod.rs
@@ -48,6 +48,7 @@ pub enum Abi {
     AvrInterrupt,
     AvrNonBlockingInterrupt,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
     System {
         unwind: bool,
     },
@@ -124,6 +125,7 @@ const AbiDatas: &[AbiData] = &[
     AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" },
     AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" },
     AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" },
+    AbiData { abi: Abi::CCmseNonSecureEntry, name: "C-cmse-nonsecure-entry" },
     AbiData { abi: Abi::System { unwind: false }, name: "system" },
     AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" },
     AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
@@ -244,6 +246,10 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
             feature: sym::abi_c_cmse_nonsecure_call,
             explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
         }),
+        "C-cmse-nonsecure-entry" => Err(AbiDisabled::Unstable {
+            feature: sym::cmse_nonsecure_entry,
+            explain: "C-cmse-nonsecure-entry ABI is experimental and subject to change",
+        }),
         _ => Err(AbiDisabled::Unrecognized),
     }
 }
@@ -286,15 +292,16 @@ impl Abi {
             AvrInterrupt => 23,
             AvrNonBlockingInterrupt => 24,
             CCmseNonSecureCall => 25,
+            CCmseNonSecureEntry => 26,
             // Cross-platform ABIs
-            System { unwind: false } => 26,
-            System { unwind: true } => 27,
-            RustIntrinsic => 28,
-            RustCall => 29,
-            Unadjusted => 30,
-            RustCold => 31,
-            RiscvInterruptM => 32,
-            RiscvInterruptS => 33,
+            System { unwind: false } => 27,
+            System { unwind: true } => 28,
+            RustIntrinsic => 29,
+            RustCall => 30,
+            Unadjusted => 31,
+            RustCold => 32,
+            RiscvInterruptM => 33,
+            RiscvInterruptS => 34,
         };
         debug_assert!(
             AbiDatas
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 1d478f84c43..ec4f5ef79d1 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2724,7 +2724,10 @@ impl Target {
             }
             X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
             Aapcs { .. } => "arm" == self.arch,
-            CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
+            CCmseNonSecureCall | CCmseNonSecureEntry => {
+                ["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"]
+                    .contains(&&self.llvm_target[..])
+            }
             Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 2d0c2e83690..00d38350b20 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -312,6 +312,7 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv {
         SysV64 { .. } => Conv::X86_64SysV,
         Aapcs { .. } => Conv::ArmAapcs,
         CCmseNonSecureCall => Conv::CCmseNonSecureCall,
+        CCmseNonSecureEntry => Conv::CCmseNonSecureEntry,
         PtxKernel => Conv::PtxKernel,
         Msp430Interrupt => Conv::Msp430Intr,
         X86Interrupt => Conv::X86Intr,
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index 317bec3050c..dc73d9c2188 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -433,6 +433,7 @@ pub enum CallConvention {
     // Target-specific calling conventions.
     ArmAapcs,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
 
     Msp430Intr,
 
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 5bad3d5ae7a..011d19f6143 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -1062,6 +1062,7 @@ pub enum Abi {
     AvrInterrupt,
     AvrNonBlockingInterrupt,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
     System { unwind: bool },
     RustIntrinsic,
     RustCall,
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index d58a016b502..83977350832 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2087,7 +2087,31 @@ impl FromUtf8Error {
     #[cfg(not(no_global_oom_handling))]
     #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")]
     pub fn into_utf8_lossy(self) -> String {
-        String::from_utf8_lossy_owned(self.bytes)
+        const REPLACEMENT: &str = "\u{FFFD}";
+
+        let mut res = {
+            let mut v = Vec::with_capacity(self.bytes.len());
+
+            // `Utf8Error::valid_up_to` returns the maximum index of validated
+            // UTF-8 bytes. Copy the valid bytes into the output buffer.
+            v.extend_from_slice(&self.bytes[..self.error.valid_up_to()]);
+
+            // SAFETY: This is safe because the only bytes present in the buffer
+            // were validated as UTF-8 by the call to `String::from_utf8` which
+            // produced this `FromUtf8Error`.
+            unsafe { String::from_utf8_unchecked(v) }
+        };
+
+        let iter = self.bytes[self.error.valid_up_to()..].utf8_chunks();
+
+        for chunk in iter {
+            res.push_str(chunk.valid());
+            if !chunk.invalid().is_empty() {
+                res.push_str(REPLACEMENT);
+            }
+        }
+
+        res
     }
 
     /// Returns the bytes that were attempted to convert to a `String`.
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index ffc9a233b66..1d07a7690da 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -28,6 +28,7 @@
 #![feature(iter_next_chunk)]
 #![feature(round_char_boundary)]
 #![feature(slice_partition_dedup)]
+#![feature(string_from_utf8_lossy_owned)]
 #![feature(string_remove_matches)]
 #![feature(const_btree_len)]
 #![feature(const_trait_impl)]
diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs
index dc03c4860e8..d996c55f946 100644
--- a/library/alloc/tests/string.rs
+++ b/library/alloc/tests/string.rs
@@ -115,6 +115,43 @@ fn test_from_utf8_lossy() {
 }
 
 #[test]
+fn test_fromutf8error_into_lossy() {
+    fn func(input: &[u8]) -> String {
+        String::from_utf8(input.to_owned()).unwrap_or_else(|e| e.into_utf8_lossy())
+    }
+
+    let xs = b"hello";
+    let ys = "hello".to_owned();
+    assert_eq!(func(xs), ys);
+
+    let xs = "ศไทย中华Việt Nam".as_bytes();
+    let ys = "ศไทย中华Việt Nam".to_owned();
+    assert_eq!(func(xs), ys);
+
+    let xs = b"Hello\xC2 There\xFF Goodbye";
+    assert_eq!(func(xs), "Hello\u{FFFD} There\u{FFFD} Goodbye".to_owned());
+
+    let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
+    assert_eq!(func(xs), "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye".to_owned());
+
+    let xs = b"\xF5foo\xF5\x80bar";
+    assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}\u{FFFD}bar".to_owned());
+
+    let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
+    assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz".to_owned());
+
+    let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
+    assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz".to_owned());
+
+    let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
+    assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar".to_owned());
+
+    // surrogates
+    let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
+    assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar".to_owned());
+}
+
+#[test]
 fn test_from_utf16() {
     let pairs = [
         (
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 5451e45f6c8..962da6643dd 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1761,6 +1761,8 @@ mod prim_ref {}
 /// - `i32` is ABI-compatible with `NonZero<i32>`, and similar for all other integer types.
 /// - If `T` is guaranteed to be subject to the [null pointer
 ///   optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible.
+///   Furthermore, if `U` satisfies the requirements [outlined here](result/index.html#representation),
+///   then `T` and `Result<T, U>` and `Result<U, T>` are all ABI-compatible.
 ///
 /// Furthermore, ABI compatibility satisfies the following general properties:
 ///
diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
index 855465aa38e..475542b3356 100644
--- a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
@@ -25,5 +25,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \
 
 ENV HOSTS=arm-unknown-linux-gnueabihf
 
-ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-full-tools --enable-profiler --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
index 338fbc4b2bf..ca95ccf33ac 100644
--- a/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
+++ b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
@@ -15,10 +15,10 @@ LLVM, the Rust compiler and the linker are providing
 TrustZone-M feature.
 
 One of the things provided, with this unstable feature, is the
-`cmse_nonsecure_entry` attribute.  This attribute marks a Secure function as an
+`C-cmse-nonsecure-entry` ABI. This ABI marks a Secure function as an
 entry function (see [section
 5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details).
-With this attribute, the compiler will do the following:
+With this ABI, the compiler will do the following:
 * add a special symbol on the function which is the `__acle_se_` prefix and the
   standard function name
 * constrain the number of parameters to avoid using the Non-Secure stack
@@ -38,11 +38,11 @@ gateway veneer.
 <!-- NOTE(ignore) this example is specific to thumbv8m targets -->
 
 ``` rust,ignore
+#![no_std]
 #![feature(cmse_nonsecure_entry)]
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(input: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
     input + 6
 }
 ```
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 2f4e764f4ce..26ab02558a1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -377,6 +377,7 @@ pub enum FnAbi {
     AvrNonBlockingInterrupt,
     C,
     CCmseNonsecureCall,
+    CCmseNonsecureEntry,
     CDecl,
     CDeclUnwind,
     CUnwind,
@@ -434,6 +435,7 @@ impl FnAbi {
             s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
             s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
             s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
+            s if *s == sym::C_dash_cmse_dash_nonsecure_dash_entry => FnAbi::CCmseNonsecureEntry,
             s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
             s if *s == sym::C => FnAbi::C,
             s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
@@ -477,6 +479,7 @@ impl FnAbi {
             FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt",
             FnAbi::C => "C",
             FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call",
+            FnAbi::CCmseNonsecureEntry => "C-cmse-nonsecure-entry",
             FnAbi::CDecl => "C-decl",
             FnAbi::CDeclUnwind => "cdecl-unwind",
             FnAbi::CUnwind => "C-unwind",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
index 1a06e0a3a0e..b0e417e6b33 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
@@ -32,6 +32,7 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
     "riscv-interrupt-m",
     "riscv-interrupt-s",
     "C-cmse-nonsecure-call",
+    "C-cmse-nonsecure-entry",
     "wasm",
     "system",
     "system-unwind",
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index 7eb8e4a5e2e..c066f504891 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -94,6 +94,7 @@ define_symbols! {
     avr_dash_interrupt = "avr-interrupt",
     avr_dash_non_dash_blocking_dash_interrupt = "avr-non-blocking-interrupt",
     C_dash_cmse_dash_nonsecure_dash_call = "C-cmse-nonsecure-call",
+    C_dash_cmse_dash_nonsecure_dash_entry = "C-cmse-nonsecure-entry",
     C_dash_unwind = "C-unwind",
     cdecl_dash_unwind = "cdecl-unwind",
     fastcall_dash_unwind = "fastcall-unwind",
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 427ed9116d3..3879f350e94 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -467,7 +467,6 @@ ui/closures/issue-87814-2.rs
 ui/closures/issue-90871.rs
 ui/closures/issue-97607.rs
 ui/closures/issue-99565.rs
-ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
 ui/codegen/auxiliary/issue-97708-aux.rs
 ui/codegen/issue-101585-128bit-repeat.rs
 ui/codegen/issue-16602-1.rs
diff --git a/tests/assembly/cmse.rs b/tests/assembly/cmse.rs
new file mode 100644
index 00000000000..acad77b2513
--- /dev/null
+++ b/tests/assembly/cmse.rs
@@ -0,0 +1,26 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
+//@ needs-llvm-components: arm
+#![crate_type = "lib"]
+#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+
+// CHECK-LABEL: __acle_se_entry_point
+// CHECK: bxns
+#[no_mangle]
+pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 {
+    0
+}
+
+// CHECK-LABEL: call_nonsecure
+// CHECK: blxns
+#[no_mangle]
+pub fn call_nonsecure(
+    f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64,
+) -> u64 {
+    unsafe { f(0, 1, 2, 3) }
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
index a8c8a85c5aa..af64901ace0 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
@@ -16,4 +16,22 @@ fn bar<T: Trait<method() -> (): Send>>() {}
 fn baz<T: Trait<method(): Send>>() {}
 //~^ ERROR return type notation arguments must be elided with `..`
 
+fn foo_path<T: Trait>() where T::method(i32): Send {}
+//~^ ERROR argument types not allowed with return type notation
+
+fn bar_path<T: Trait>() where T::method() -> (): Send {}
+//~^ ERROR return type not allowed with return type notation
+
+fn baz_path<T: Trait>() where T::method(): Send {}
+//~^ ERROR return type notation arguments must be elided with `..`
+
+fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
+//~^ ERROR expected associated type
+
+fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
+//~^ ERROR expected associated type
+
+fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
+//~^ ERROR expected associated type
+
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
index 7e1695984f1..68081470087 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
@@ -1,3 +1,21 @@
+error[E0575]: expected associated type, found associated function `Trait::method`
+  --> $DIR/bad-inputs-and-output.rs:28:36
+   |
+LL | fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
+
+error[E0575]: expected associated type, found associated function `Trait::method`
+  --> $DIR/bad-inputs-and-output.rs:31:36
+   |
+LL | fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
+
+error[E0575]: expected associated type, found associated function `Trait::method`
+  --> $DIR/bad-inputs-and-output.rs:34:36
+   |
+LL | fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^ not a associated type
+
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bad-inputs-and-output.rs:3:12
    |
@@ -25,5 +43,24 @@ error: return type notation arguments must be elided with `..`
 LL | fn baz<T: Trait<method(): Send>>() {}
    |                       ^^ help: add `..`: `(..)`
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: argument types not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:19:40
+   |
+LL | fn foo_path<T: Trait>() where T::method(i32): Send {}
+   |                                        ^^^^^ help: remove the input types: `()`
+
+error: return type not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:22:42
+   |
+LL | fn bar_path<T: Trait>() where T::method() -> (): Send {}
+   |                                          ^^^^^^ help: remove the return type
+
+error: return type notation arguments must be elided with `..`
+  --> $DIR/bad-inputs-and-output.rs:25:40
+   |
+LL | fn baz_path<T: Trait>() where T::method(): Send {}
+   |                                        ^^ help: add `..`: `(..)`
+
+error: aborting due to 9 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0575`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs b/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs
index f507d82afec..185c0523633 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs
@@ -10,17 +10,12 @@ trait Tr {
 fn foo<T: Tr>()
 where
     T::method(..): Send,
-    //~^ ERROR return type notation not allowed in this position yet
-    //~| ERROR expected type, found function
     <T as Tr>::method(..): Send,
-    //~^ ERROR return type notation not allowed in this position yet
-    //~| ERROR expected associated type, found associated function `Tr::method`
 {
     let _ = T::CONST::(..);
     //~^ ERROR return type notation not allowed in this position yet
     let _: T::method(..);
     //~^ ERROR return type notation not allowed in this position yet
-    //~| ERROR expected type, found function
 }
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr b/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr
index cb45de59c7e..dca2bdeab0a 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr
@@ -1,9 +1,3 @@
-error[E0575]: expected associated type, found associated function `Tr::method`
-  --> $DIR/bare-path.rs:15:5
-   |
-LL |     <T as Tr>::method(..): Send,
-   |     ^^^^^^^^^^^^^^^^^^^^^ not a associated type
-
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bare-path.rs:1:12
    |
@@ -14,53 +8,16 @@ LL | #![feature(return_type_notation)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:19:23
+  --> $DIR/bare-path.rs:15:23
    |
 LL |     let _ = T::CONST::(..);
    |                       ^^^^
 
 error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:21:21
+  --> $DIR/bare-path.rs:17:12
    |
 LL |     let _: T::method(..);
-   |                     ^^^^
-
-error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:12:14
-   |
-LL |     T::method(..): Send,
-   |              ^^^^
-
-error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:15:22
-   |
-LL |     <T as Tr>::method(..): Send,
-   |                      ^^^^
-
-error: expected type, found function
-  --> $DIR/bare-path.rs:12:8
-   |
-LL |     T::method(..): Send,
-   |        ^^^^^^ unexpected function
-   |
-note: the associated function is defined here
-  --> $DIR/bare-path.rs:7:5
-   |
-LL |     fn method() -> impl Sized;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: expected type, found function
-  --> $DIR/bare-path.rs:21:15
-   |
-LL |     let _: T::method(..);
-   |               ^^^^^^ unexpected function
-   |
-note: the associated function is defined here
-  --> $DIR/bare-path.rs:7:5
-   |
-LL |     fn method() -> impl Sized;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0575`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs
new file mode 100644
index 00000000000..d4f21f47c6c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs
@@ -0,0 +1,52 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait<'a> {
+    fn late<'b>(&'b self, _: &'a ()) -> impl Sized;
+    fn early<'b: 'b>(&'b self, _: &'a ()) -> impl Sized;
+}
+
+#[allow(refining_impl_trait_internal)]
+impl<'a> Trait<'a> for () {
+    fn late<'b>(&'b self, _: &'a ()) -> i32 { 1 }
+    fn early<'b: 'b>(&'b self, _: &'a ()) -> i32 { 1 }
+}
+
+trait Other<'c> {}
+impl Other<'_> for i32 {}
+
+fn test<T>(t: &T)
+where
+    T: for<'a, 'c> Trait<'a, late(..): Other<'c>>,
+    // which is basically:
+    // for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>,
+    T: for<'a, 'c> Trait<'a, early(..): Other<'c>>,
+    // which is basically:
+    // for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>,
+{
+    is_other_impl(t.late(&()));
+    is_other_impl(t.early(&()));
+}
+
+fn test_path<T>(t: &T)
+where
+T: for<'a> Trait<'a>,
+    for<'a, 'c> <T as Trait<'a>>::late(..): Other<'c>,
+    // which is basically:
+    // for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c>
+    for<'a, 'c> <T as Trait<'a>>::early(..): Other<'c>,
+    // which is basically:
+    // for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c>
+{
+    is_other_impl(t.late(&()));
+    is_other_impl(t.early(&()));
+}
+
+fn is_other_impl(_: impl for<'c> Other<'c>) {}
+
+fn main() {
+    test(&());
+    test(&());
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr
new file mode 100644
index 00000000000..c67231c07f7
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/higher-ranked-bound-works.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs
new file mode 100644
index 00000000000..9bdc2d00233
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs
@@ -0,0 +1,42 @@
+//@ check-pass
+
+#![allow(non_camel_case_types)]
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Foo {
+    type test;
+
+    fn test() -> impl Bar;
+}
+
+fn call_path<T: Foo>()
+where
+    T::test(..): Bar,
+{
+}
+
+fn call_bound<T: Foo<test(..): Bar>>() {}
+
+trait Bar {}
+struct NotBar;
+struct YesBar;
+impl Bar for YesBar {}
+
+impl Foo for () {
+    type test = NotBar;
+
+    // Use refinement here so we can observe `YesBar: Bar`.
+    #[allow(refining_impl_trait_internal)]
+    fn test() -> YesBar {
+        YesBar
+    }
+}
+
+fn main() {
+    // If `T::test(..)` resolved to the GAT (erroneously), then this would be
+    // an error since `<() as Foo>::bar` -- the associated type -- does not
+    // implement `Bar`, but the return type of the method does.
+    call_path::<()>();
+    call_bound::<()>();
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr
new file mode 100644
index 00000000000..f4ece074b28
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/namespace-conflict.rs:4:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
index d283c6eab37..35d6dd799c7 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
@@ -5,7 +5,10 @@ trait Trait {
     fn method() {}
 }
 
-fn test<T: Trait<method(..): Send>>() {}
-//~^ ERROR  return type notation used on function that is not `async` and does not return `impl Trait`
+fn bound<T: Trait<method(..): Send>>() {}
+//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait`
+
+fn path<T>() where T: Trait, T::method(..): Send {}
+//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait`
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
index 79ced3c96ed..e308c927bf0 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
@@ -8,15 +8,26 @@ LL | #![feature(return_type_notation)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: return type notation used on function that is not `async` and does not return `impl Trait`
-  --> $DIR/non-rpitit.rs:8:18
+  --> $DIR/non-rpitit.rs:8:19
    |
 LL |     fn method() {}
    |     ----------- this function must be `async` or return `impl Trait`
 ...
-LL | fn test<T: Trait<method(..): Send>>() {}
-   |                  ^^^^^^^^^^^^^^^^
+LL | fn bound<T: Trait<method(..): Send>>() {}
+   |                   ^^^^^^^^^^^^^^^^
    |
    = note: function returns `()`, which is not compatible with associated type return bounds
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: return type notation used on function that is not `async` and does not return `impl Trait`
+  --> $DIR/non-rpitit.rs:11:30
+   |
+LL |     fn method() {}
+   |     ----------- this function must be `async` or return `impl Trait`
+...
+LL | fn path<T>() where T: Trait, T::method(..): Send {}
+   |                              ^^^^^^^^^^^^^
+   |
+   = note: function returns `()`, which is not compatible with associated type return bounds
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs
new file mode 100644
index 00000000000..d94ec6b74d9
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs
@@ -0,0 +1,42 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+fn function() {}
+
+fn not_a_method()
+where
+    function(..): Send,
+    //~^ ERROR expected function, found function `function`
+    //~| ERROR return type notation not allowed in this position yet
+{
+}
+
+fn not_a_method_and_typoed()
+where
+    function(): Send,
+    //~^ ERROR expected type, found function `function`
+{
+}
+
+trait Tr {
+    fn method();
+}
+
+// Forgot the `T::`
+fn maybe_method_overlaps<T: Tr>()
+where
+    method(..): Send,
+    //~^ ERROR cannot find function `method` in this scope
+    //~| ERROR return type notation not allowed in this position yet
+{
+}
+
+// Forgot the `T::`, AND typoed `(..)` to `()`
+fn maybe_method_overlaps_and_typoed<T: Tr>()
+where
+    method(): Send,
+    //~^ ERROR cannot find type `method` in this scope
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr
new file mode 100644
index 00000000000..8add2d46296
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr
@@ -0,0 +1,49 @@
+error[E0575]: expected function, found function `function`
+  --> $DIR/not-a-method.rs:8:5
+   |
+LL |     function(..): Send,
+   |     ^^^^^^^^^^^^ not a function
+
+error[E0573]: expected type, found function `function`
+  --> $DIR/not-a-method.rs:16:5
+   |
+LL |     function(): Send,
+   |     ^^^^^^^^^^ not a type
+
+error[E0576]: cannot find function `method` in this scope
+  --> $DIR/not-a-method.rs:28:5
+   |
+LL |     method(..): Send,
+   |     ^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `method` in this scope
+  --> $DIR/not-a-method.rs:37:5
+   |
+LL |     method(): Send,
+   |     ^^^^^^ not found in this scope
+
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/not-a-method.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation not allowed in this position yet
+  --> $DIR/not-a-method.rs:8:5
+   |
+LL |     function(..): Send,
+   |     ^^^^^^^^^^^^
+
+error: return type notation not allowed in this position yet
+  --> $DIR/not-a-method.rs:28:5
+   |
+LL |     method(..): Send,
+   |     ^^^^^^^^^^
+
+error: aborting due to 6 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0412, E0573, E0575, E0576.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs
new file mode 100644
index 00000000000..cb42c33e364
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs
@@ -0,0 +1,27 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait A {
+    fn method() -> impl Sized;
+}
+trait B {
+    fn method() -> impl Sized;
+}
+
+fn ambiguous<T: A + B>()
+where
+    T::method(..): Send,
+    //~^ ERROR ambiguous associated function `method` in bounds of `T`
+{
+}
+
+trait Sub: A + B {}
+
+fn ambiguous_via_supertrait<T: Sub>()
+where
+    T::method(..): Send,
+    //~^ ERROR ambiguous associated function `method` in bounds of `T`
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr
new file mode 100644
index 00000000000..e841049ac66
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr
@@ -0,0 +1,54 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-ambiguous.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0221]: ambiguous associated function `method` in bounds of `T`
+  --> $DIR/path-ambiguous.rs:13:5
+   |
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `A`
+...
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `B`
+...
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^ ambiguous associated function `method`
+   |
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as B>::method(..): Send,
+   |     ~~~~~~~~~~
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as A>::method(..): Send,
+   |     ~~~~~~~~~~
+
+error[E0221]: ambiguous associated function `method` in bounds of `T`
+  --> $DIR/path-ambiguous.rs:22:5
+   |
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `A`
+...
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `B`
+...
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^ ambiguous associated function `method`
+   |
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as B>::method(..): Send,
+   |     ~~~~~~~~~~
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as A>::method(..): Send,
+   |     ~~~~~~~~~~
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0221`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs
new file mode 100644
index 00000000000..56abd167fb6
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+fn is_send(_: impl Send) {}
+
+struct W<T>(T);
+
+impl<T> W<T> {
+    fn test()
+    where
+        T: Trait,
+        T::method(..): Send,
+    {
+        is_send(T::method());
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr
new file mode 100644
index 00000000000..3db033d8cf5
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-constrained-in-method.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs
new file mode 100644
index 00000000000..a4d8f005371
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs
@@ -0,0 +1,25 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait A<'a> {
+    fn method() -> impl Sized;
+}
+trait B: for<'a> A<'a> {}
+
+fn higher_ranked<T>()
+where
+    T: for<'a> A<'a>,
+    T::method(..): Send,
+    //~^ ERROR cannot use the associated function of a trait with uninferred generic parameters
+{
+}
+
+fn higher_ranked_via_supertrait<T>()
+where
+    T: B,
+    T::method(..): Send,
+    //~^ ERROR cannot use the associated function of a trait with uninferred generic parameters
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr
new file mode 100644
index 00000000000..22de6165503
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr
@@ -0,0 +1,34 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-higher-ranked.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0212]: cannot use the associated function of a trait with uninferred generic parameters
+  --> $DIR/path-higher-ranked.rs:12:5
+   |
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     <T as A<'_>>::method(..): Send,
+   |     ~~~~~~~~~~~~~~
+
+error[E0212]: cannot use the associated function of a trait with uninferred generic parameters
+  --> $DIR/path-higher-ranked.rs:20:5
+   |
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     <T as A<'_>>::method(..): Send,
+   |     ~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0212`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs
new file mode 100644
index 00000000000..c1a7b95ca2d
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs
@@ -0,0 +1,25 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait A {
+    #[allow(non_camel_case_types)]
+    type bad;
+}
+
+fn fully_qualified<T: A>()
+where
+    <T as A>::method(..): Send,
+    //~^ ERROR cannot find method or associated constant `method` in trait `A`
+    <T as A>::bad(..): Send,
+    //~^ ERROR expected method or associated constant, found associated type `A::bad`
+{
+}
+
+fn type_dependent<T: A>()
+where
+    T::method(..): Send,
+    //~^ associated function `method` not found for `T`
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr
new file mode 100644
index 00000000000..0130c3bc614
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr
@@ -0,0 +1,33 @@
+error[E0576]: cannot find method or associated constant `method` in trait `A`
+  --> $DIR/path-missing.rs:11:15
+   |
+LL |     <T as A>::method(..): Send,
+   |               ^^^^^^ not found in `A`
+
+error[E0575]: expected method or associated constant, found associated type `A::bad`
+  --> $DIR/path-missing.rs:13:5
+   |
+LL |     <T as A>::bad(..): Send,
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-missing.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0220]: associated function `method` not found for `T`
+  --> $DIR/path-missing.rs:20:8
+   |
+LL |     T::method(..): Send,
+   |        ^^^^^^ associated function `method` not found
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0220, E0575, E0576.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs
new file mode 100644
index 00000000000..d2636789c10
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs
@@ -0,0 +1,15 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+fn test()
+where
+    Trait::method(..): Send,
+    //~^ ERROR ambiguous associated type
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr
new file mode 100644
index 00000000000..d66b0a109fc
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr
@@ -0,0 +1,23 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-no-qself.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0223]: ambiguous associated type
+  --> $DIR/path-no-qself.rs:10:5
+   |
+LL |     Trait::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
+   |
+LL |     <Example as Trait>::method: Send,
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs
new file mode 100644
index 00000000000..b0e6ea852b0
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs
@@ -0,0 +1,21 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+struct Adt;
+
+fn non_param_qself()
+where
+    <()>::method(..): Send,
+    //~^ ERROR ambiguous associated function
+    i32::method(..): Send,
+    //~^ ERROR ambiguous associated function
+    Adt::method(..): Send,
+    //~^ ERROR ambiguous associated function
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr
new file mode 100644
index 00000000000..cd1aa9813e3
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr
@@ -0,0 +1,30 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-non-param-qself.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0223]: ambiguous associated function
+  --> $DIR/path-non-param-qself.rs:12:5
+   |
+LL |     <()>::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^
+
+error[E0223]: ambiguous associated function
+  --> $DIR/path-non-param-qself.rs:14:5
+   |
+LL |     i32::method(..): Send,
+   |     ^^^^^^^^^^^^^^^
+
+error[E0223]: ambiguous associated function
+  --> $DIR/path-non-param-qself.rs:16:5
+   |
+LL |     Adt::method(..): Send,
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs
new file mode 100644
index 00000000000..0cf84457ba7
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Foo {
+    fn method() -> impl Sized;
+}
+
+trait Bar: Foo {
+    fn other()
+    where
+        Self::method(..): Send;
+}
+
+fn is_send(_: impl Send) {}
+
+impl<T: Foo> Bar for T {
+    fn other()
+    where
+        Self::method(..): Send,
+    {
+        is_send(Self::method());
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr
new file mode 100644
index 00000000000..ab33647583c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-self-qself.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs
new file mode 100644
index 00000000000..693a300eb1d
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs
@@ -0,0 +1,22 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Foo {
+    fn method<T>() -> impl Sized;
+}
+
+fn test<T: Foo>()
+where
+    <T as Foo>::method(..): Send,
+    //~^ ERROR return type notation is not allowed for functions that have type parameters
+{
+}
+
+fn test_type_dependent<T: Foo>()
+where
+    <T as Foo>::method(..): Send,
+    //~^ ERROR return type notation is not allowed for functions that have type parameters
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr
new file mode 100644
index 00000000000..0d33d4f97d7
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr
@@ -0,0 +1,29 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-type-param.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation is not allowed for functions that have type parameters
+  --> $DIR/path-type-param.rs:10:5
+   |
+LL |     fn method<T>() -> impl Sized;
+   |               - type parameter declared here
+...
+LL |     <T as Foo>::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: return type notation is not allowed for functions that have type parameters
+  --> $DIR/path-type-param.rs:17:5
+   |
+LL |     fn method<T>() -> impl Sized;
+   |               - type parameter declared here
+...
+LL |     <T as Foo>::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs
new file mode 100644
index 00000000000..a5b0b0e4e25
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs
@@ -0,0 +1,25 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+struct DoesntWork;
+impl Trait for DoesntWork {
+    fn method() -> impl Sized {
+        std::ptr::null_mut::<()>()
+        // This isn't `Send`.
+    }
+}
+
+fn test<T: Trait>()
+where
+    T::method(..): Send,
+{
+}
+
+fn main() {
+    test::<DoesntWork>();
+    //~^ ERROR `*mut ()` cannot be sent between threads safely
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr
new file mode 100644
index 00000000000..7d32a428555
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr
@@ -0,0 +1,36 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-unsatisfied.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: `*mut ()` cannot be sent between threads safely
+  --> $DIR/path-unsatisfied.rs:23:12
+   |
+LL |     fn method() -> impl Sized {
+   |                    ---------- within this `impl Sized`
+...
+LL |     test::<DoesntWork>();
+   |            ^^^^^^^^^^ `*mut ()` cannot be sent between threads safely
+   |
+   = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()`, which is required by `impl Sized: Send`
+note: required because it appears within the type `impl Sized`
+  --> $DIR/path-unsatisfied.rs:10:20
+   |
+LL |     fn method() -> impl Sized {
+   |                    ^^^^^^^^^^
+note: required by a bound in `test`
+  --> $DIR/path-unsatisfied.rs:18:20
+   |
+LL | fn test<T: Trait>()
+   |    ---- required by a bound in this function
+LL | where
+LL |     T::method(..): Send,
+   |                    ^^^^ required by this bound in `test`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-works.rs b/tests/ui/associated-type-bounds/return-type-notation/path-works.rs
new file mode 100644
index 00000000000..027bc89f13e
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-works.rs
@@ -0,0 +1,23 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+struct Works;
+impl Trait for Works {
+    fn method() -> impl Sized {}
+}
+
+fn test<T: Trait>()
+where
+    T::method(..): Send,
+{
+}
+
+fn main() {
+    test::<Works>();
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr
new file mode 100644
index 00000000000..b1ec8069ba0
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-works.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
index bea5faf7253..cb196471fd7 100644
--- a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
+++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
@@ -1,13 +1,7 @@
 // This checks that the attribute validation ICE in issue #105594 doesn't
 // recur.
-//
-//@ ignore-thumbv8m.base-none-eabi
-#![feature(cmse_nonsecure_entry)]
 
 fn main() {}
 
 #[track_caller] //~ ERROR attribute should be applied to a function
 static _A: () = ();
-
-#[cmse_nonsecure_entry] //~ ERROR attribute should be applied to a function
-static _B: () = (); //~| ERROR #[cmse_nonsecure_entry]` is only valid for targets
diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
index c6b2d6e7813..1248967c47b 100644
--- a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
+++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
@@ -1,26 +1,11 @@
 error[E0739]: attribute should be applied to a function definition
-  --> $DIR/issue-105594-invalid-attr-validation.rs:9:1
+  --> $DIR/issue-105594-invalid-attr-validation.rs:6:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 LL | static _A: () = ();
    | ------------------- not a function definition
 
-error: attribute should be applied to a function definition
-  --> $DIR/issue-105594-invalid-attr-validation.rs:12:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-LL | static _B: () = ();
-   | ------------------- not a function definition
-
-error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
-  --> $DIR/issue-105594-invalid-attr-validation.rs:12:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0739, E0775.
-For more information about an error, try `rustc --explain E0739`.
+For more information about this error, try `rustc --explain E0739`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs
new file mode 100644
index 00000000000..37c8319d98d
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs
@@ -0,0 +1,20 @@
+//@ build-pass
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+//@ needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items, intrinsics)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+impl Copy for u32 {}
+
+#[no_mangle]
+pub extern "C-cmse-nonsecure-entry" fn test(
+    f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32,
+    a: u32,
+    b: u32,
+    c: u32,
+) -> u32 {
+    f(a, b, c, 42)
+}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
index 02d5f20febc..6061451b2e9 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
@@ -1,10 +1,9 @@
 // gate-test-cmse_nonsecure_entry
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-//~^ ERROR [E0775]
-//~| ERROR [E0658]
-pub extern "C" fn entry_function(input: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+    //~^ ERROR [E0570]
+    //~| ERROR [E0658]
     input + 6
 }
 
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
index beb9716d590..dabf16cab30 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
@@ -1,20 +1,20 @@
-error[E0658]: the `#[cmse_nonsecure_entry]` attribute is an experimental feature
-  --> $DIR/gate_test.rs:4:1
+error[E0658]: C-cmse-nonsecure-entry ABI is experimental and subject to change
+  --> $DIR/gate_test.rs:4:12
    |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #75835 <https://github.com/rust-lang/rust/issues/75835> for more information
    = help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
   --> $DIR/gate_test.rs:4:1
    |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0658, E0775.
-For more information about an error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0570, E0658.
+For more information about an error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
deleted file mode 100644
index a839406cd0a..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Regression test for the ICE described in #83475.
-
-#![crate_type="lib"]
-
-#![feature(cmse_nonsecure_entry)]
-#[cmse_nonsecure_entry]
-//~^ ERROR: attribute should be applied to a function definition
-struct XEmpty2;
-//~^ NOTE: not a function definition
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr
deleted file mode 100644
index 26d3bfe7837..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: attribute should be applied to a function definition
-  --> $DIR/issue-83475.rs:6:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | struct XEmpty2;
-   | --------------- not a function definition
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
index e197f94096d..de6888fae62 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
@@ -3,14 +3,14 @@
 //@ needs-llvm-components: arm
 #![feature(cmse_nonsecure_entry, no_core, lang_items)]
 #![no_core]
-#[lang="sized"]
-trait Sized { }
-#[lang="copy"]
-trait Copy { }
+#![crate_type = "lib"]
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
 impl Copy for u32 {}
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
     d
 }
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
index e2da3ebb6ae..4413c461c04 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
@@ -3,14 +3,19 @@
 //@ needs-llvm-components: arm
 #![feature(cmse_nonsecure_entry, no_core, lang_items)]
 #![no_core]
-#[lang="sized"]
-trait Sized { }
-#[lang="copy"]
-trait Copy { }
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
 impl Copy for u32 {}
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(
+    _: u32,
+    _: u32,
+    _: u32,
+    _: u32,
+    e: u32,
+) -> u32 {
     e
 }
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr
new file mode 100644
index 00000000000..26409279fbe
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr
@@ -0,0 +1,9 @@
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
+  --> $DIR/trustzone-only.rs:20:1
+   |
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
index 87eccb4fc6e..a4ea7a1757d 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
@@ -1,10 +1,25 @@
-//@ ignore-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
+//@ revisions: x86 aarch64 thumb7
+//
+//@[x86] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86] needs-llvm-components: x86
+//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
+//@[aarch64] needs-llvm-components: aarch64
+//@[thumb7] compile-flags: --target thumbv7em-none-eabi
+//@[thumb7] needs-llvm-components: arm
+#![feature(no_core, lang_items, rustc_attrs, cmse_nonsecure_entry)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u32 {}
 
 #[no_mangle]
-#[cmse_nonsecure_entry] //~ ERROR [E0775]
-pub extern "C" fn entry_function(input: u32) -> u32 {
-    input + 6
+pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+    //~^ ERROR [E0570]
+    input
 }
 
 fn main() {}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr
deleted file mode 100644
index 3e6954394f4..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
-  --> $DIR/trustzone-only.rs:5:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0775`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr
new file mode 100644
index 00000000000..26409279fbe
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr
@@ -0,0 +1,9 @@
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
+  --> $DIR/trustzone-only.rs:20:1
+   |
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr
new file mode 100644
index 00000000000..26409279fbe
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr
@@ -0,0 +1,9 @@
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
+  --> $DIR/trustzone-only.rs:20:1
+   |
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
deleted file mode 100644
index db4f90e9923..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-//@ needs-llvm-components: arm
-#![feature(cmse_nonsecure_entry, no_core, lang_items)]
-#![no_core]
-#[lang = "sized"]
-trait Sized {}
-
-#[lang = "copy"]
-trait Copy {}
-
-#[no_mangle]
-#[cmse_nonsecure_entry]
-//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776]
-pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
-    d
-}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
deleted file mode 100644
index c3fae3d8bbb..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI
-  --> $DIR/wrong-abi.rs:12:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0776`.
diff --git a/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs b/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs
new file mode 100644
index 00000000000..dc929e14527
--- /dev/null
+++ b/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+#![feature(rust_cold_cc)]
+
+// extern "rust-cold" is a "Rust" ABI so we accept `repr(Rust)` types as arg/ret without warnings.
+
+pub extern "rust-cold" fn f(_: ()) -> Result<(), ()> {
+    Ok(())
+}
+
+extern "rust-cold" {
+    pub fn g(_: ()) -> Result<(), ()>;
+}
+
+fn main() {}
diff --git a/tests/ui/parser/triple-colon-delegation.fixed b/tests/ui/parser/triple-colon-delegation.fixed
new file mode 100644
index 00000000000..fbb614b57da
--- /dev/null
+++ b/tests/ui/parser/triple-colon-delegation.fixed
@@ -0,0 +1,44 @@
+//@ run-rustfix
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features, unused)]
+
+trait Trait {
+    fn foo(&self) {}
+}
+
+struct F;
+impl Trait for F {}
+
+pub mod to_reuse {
+    pub fn bar() {}
+}
+
+mod fn_to_other {
+    use super::*;
+
+    reuse Trait::foo; //~ ERROR path separator must be a double colon
+    reuse to_reuse::bar; //~ ERROR path separator must be a double colon
+}
+
+impl Trait for u8 {}
+
+struct S(u8);
+
+mod to_import {
+    pub fn check(arg: &u8) -> &u8 { arg }
+}
+
+impl Trait for S {
+    reuse Trait::* { //~ ERROR path separator must be a double colon
+        use to_import::check;
+
+        let _arr = Some(self.0).map(|x| [x * 2; 3]);
+        check(&self.0)
+    }
+}
+
+fn main() {
+    let s = S(0);
+    s.foo();
+}
diff --git a/tests/ui/parser/triple-colon-delegation.rs b/tests/ui/parser/triple-colon-delegation.rs
new file mode 100644
index 00000000000..9fbaa4477ae
--- /dev/null
+++ b/tests/ui/parser/triple-colon-delegation.rs
@@ -0,0 +1,44 @@
+//@ run-rustfix
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features, unused)]
+
+trait Trait {
+    fn foo(&self) {}
+}
+
+struct F;
+impl Trait for F {}
+
+pub mod to_reuse {
+    pub fn bar() {}
+}
+
+mod fn_to_other {
+    use super::*;
+
+    reuse Trait:::foo; //~ ERROR path separator must be a double colon
+    reuse to_reuse:::bar; //~ ERROR path separator must be a double colon
+}
+
+impl Trait for u8 {}
+
+struct S(u8);
+
+mod to_import {
+    pub fn check(arg: &u8) -> &u8 { arg }
+}
+
+impl Trait for S {
+    reuse Trait:::* { //~ ERROR path separator must be a double colon
+        use to_import::check;
+
+        let _arr = Some(self.0).map(|x| [x * 2; 3]);
+        check(&self.0)
+    }
+}
+
+fn main() {
+    let s = S(0);
+    s.foo();
+}
diff --git a/tests/ui/parser/triple-colon-delegation.stderr b/tests/ui/parser/triple-colon-delegation.stderr
new file mode 100644
index 00000000000..d748c7d92b5
--- /dev/null
+++ b/tests/ui/parser/triple-colon-delegation.stderr
@@ -0,0 +1,38 @@
+error: path separator must be a double colon
+  --> $DIR/triple-colon-delegation.rs:20:18
+   |
+LL |     reuse Trait:::foo;
+   |                  ^
+   |
+help: use a double colon instead
+   |
+LL -     reuse Trait:::foo;
+LL +     reuse Trait::foo;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon-delegation.rs:21:21
+   |
+LL |     reuse to_reuse:::bar;
+   |                     ^
+   |
+help: use a double colon instead
+   |
+LL -     reuse to_reuse:::bar;
+LL +     reuse to_reuse::bar;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon-delegation.rs:33:18
+   |
+LL |     reuse Trait:::* {
+   |                  ^
+   |
+help: use a double colon instead
+   |
+LL -     reuse Trait:::* {
+LL +     reuse Trait::* {
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/parser/triple-colon.fixed b/tests/ui/parser/triple-colon.fixed
new file mode 100644
index 00000000000..168e4c1f618
--- /dev/null
+++ b/tests/ui/parser/triple-colon.fixed
@@ -0,0 +1,23 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+use ::std::{cell as _}; //~ ERROR path separator must be a double colon
+use std::cell::*; //~ ERROR path separator must be a double colon
+use std::cell::Cell; //~ ERROR path separator must be a double colon
+use std::{cell as _}; //~ ERROR path separator must be a double colon
+
+mod foo{
+    use ::{}; //~ ERROR path separator must be a double colon
+    use ::*; //~ ERROR path separator must be a double colon
+}
+
+fn main() {
+    let c: ::std::cell::Cell::<u8> = Cell::<u8>::new(0);
+    //~^ ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+}
diff --git a/tests/ui/parser/triple-colon.rs b/tests/ui/parser/triple-colon.rs
new file mode 100644
index 00000000000..1a70012685f
--- /dev/null
+++ b/tests/ui/parser/triple-colon.rs
@@ -0,0 +1,23 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+use :::std::{cell as _}; //~ ERROR path separator must be a double colon
+use std::cell:::*; //~ ERROR path separator must be a double colon
+use std::cell:::Cell; //~ ERROR path separator must be a double colon
+use std:::{cell as _}; //~ ERROR path separator must be a double colon
+
+mod foo{
+    use :::{}; //~ ERROR path separator must be a double colon
+    use :::*; //~ ERROR path separator must be a double colon
+}
+
+fn main() {
+    let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+    //~^ ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+}
diff --git a/tests/ui/parser/triple-colon.stderr b/tests/ui/parser/triple-colon.stderr
new file mode 100644
index 00000000000..8d57fd7ebc9
--- /dev/null
+++ b/tests/ui/parser/triple-colon.stderr
@@ -0,0 +1,146 @@
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:5:7
+   |
+LL | use :::std::{cell as _};
+   |       ^
+   |
+help: use a double colon instead
+   |
+LL - use :::std::{cell as _};
+LL + use ::std::{cell as _};
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:6:16
+   |
+LL | use std::cell:::*;
+   |                ^
+   |
+help: use a double colon instead
+   |
+LL - use std::cell:::*;
+LL + use std::cell::*;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:7:16
+   |
+LL | use std::cell:::Cell;
+   |                ^
+   |
+help: use a double colon instead
+   |
+LL - use std::cell:::Cell;
+LL + use std::cell::Cell;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:8:10
+   |
+LL | use std:::{cell as _};
+   |          ^
+   |
+help: use a double colon instead
+   |
+LL - use std:::{cell as _};
+LL + use std::{cell as _};
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:11:11
+   |
+LL |     use :::{};
+   |           ^
+   |
+help: use a double colon instead
+   |
+LL -     use :::{};
+LL +     use ::{};
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:12:11
+   |
+LL |     use :::*;
+   |           ^
+   |
+help: use a double colon instead
+   |
+LL -     use :::*;
+LL +     use ::*;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:14
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |              ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: ::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:20
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                    ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:27
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                           ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:34
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                                  ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell:::Cell::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:48
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                                                ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell:::Cell:::<u8> = Cell::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:55
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                                                       ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>::new(0);
+   |
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout
index da67a57f420..4415b3c858e 100644
--- a/tests/ui/print-calling-conventions.stdout
+++ b/tests/ui/print-calling-conventions.stdout
@@ -1,5 +1,6 @@
 C
 C-cmse-nonsecure-call
+C-cmse-nonsecure-entry
 C-unwind
 Rust
 aapcs
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
index 348bf839b69..ea3cbabf302 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
@@ -39,7 +39,6 @@ impl const Foo for NonConstAdd {
 #[const_trait]
 trait Baz {
     type Qux: Add;
-    //~^ ERROR the trait bound
 }
 
 impl const Baz for NonConstAdd {
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
index 405212b52c7..c20b53c210f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -12,17 +12,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
    = note: the next trait solver must be enabled globally for the effects feature to work correctly
    = help: use `-Znext-solver` to enable
 
-error[E0277]: the trait bound `Add::{synthetic#0}: Compat` is not satisfied
-  --> $DIR/assoc-type.rs:41:15
-   |
-LL |     type Qux: Add;
-   |               ^^^ the trait `Compat` is not implemented for `Add::{synthetic#0}`
-   |
-help: consider further restricting the associated type
-   |
-LL | trait Baz where Add::{synthetic#0}: Compat {
-   |           ++++++++++++++++++++++++++++++++
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
index 06ee421fc32..71e5a0c728d 100644
--- a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
@@ -1,8 +1,8 @@
 pub fn foo(num: i32) -> i32 {
     let foo: i32::from_be(num);
     //~^ ERROR expected type, found local variable `num`
-    //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
-    //~| ERROR ambiguous associated type
+    //~| ERROR argument types not allowed with return type notation
+    //~| ERROR return type notation not allowed in this position yet
     foo
 }
 
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
index b90ae051fb7..83a5441e3c0 100644
--- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
@@ -6,29 +6,22 @@ LL |     let foo: i32::from_be(num);
    |            |
    |            help: use `=` if you meant to assign
 
-error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/let-binding-init-expr-as-ty.rs:2:19
+error: argument types not allowed with return type notation
+  --> $DIR/let-binding-init-expr-as-ty.rs:2:26
    |
 LL |     let foo: i32::from_be(num);
-   |                   ^^^^^^^^^^^^ only `Fn` traits may use parentheses
+   |                          ^^^^^ help: remove the input types: `()`
    |
-help: use angle brackets instead
-   |
-LL |     let foo: i32::from_be<num>;
-   |                          ~   ~
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0223]: ambiguous associated type
+error: return type notation not allowed in this position yet
   --> $DIR/let-binding-init-expr-as-ty.rs:2:14
    |
 LL |     let foo: i32::from_be(num);
    |              ^^^^^^^^^^^^^^^^^
-   |
-help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path
-   |
-LL |     let foo: <i32 as Example>::from_be;
-   |              ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0214, E0223, E0573.
-For more information about an error, try `rustc --explain E0214`.
+For more information about this error, try `rustc --explain E0573`.