about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs19
-rw-r--r--compiler/rustc_codegen_gcc/messages.ftl3
-rw-r--r--compiler/rustc_codegen_gcc/src/attributes.rs22
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs36
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs24
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl6
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs23
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs24
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs30
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl5
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs45
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs26
-rw-r--r--compiler/rustc_feature/src/removed.rs4
-rw-r--r--compiler/rustc_feature/src/unstable.rs17
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors/precise_captures.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs49
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs5
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_session/src/session.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/src/target_features.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_type_ir/src/interner.rs2
-rw-r--r--compiler/rustc_type_ir/src/relate.rs10
30 files changed, 230 insertions, 203 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index b26797f4203..35af4d63cc7 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1573,11 +1573,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // Feature gate for RPITIT + use<..>
         match origin {
             rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
-                if let Some(span) = bounds.iter().find_map(|bound| match *bound {
-                    ast::GenericBound::Use(_, span) => Some(span),
-                    _ => None,
-                }) {
-                    self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span });
+                if !self.tcx.features().precise_capturing_in_traits
+                    && let Some(span) = bounds.iter().find_map(|bound| match *bound {
+                        ast::GenericBound::Use(_, span) => Some(span),
+                        _ => None,
+                    })
+                {
+                    let mut diag =
+                        self.tcx.dcx().create_err(errors::NoPreciseCapturesOnRpitit { span });
+                    add_feature_diagnostics(
+                        &mut diag,
+                        self.tcx.sess,
+                        sym::precise_capturing_in_traits,
+                    );
+                    diag.emit();
                 }
             }
             _ => {}
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 0235384445e..bbae59ea7a5 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -8,9 +8,6 @@ codegen_gcc_invalid_minimum_alignment =
 codegen_gcc_lto_not_supported =
     LTO is not supported. You may get a linker error.
 
-codegen_gcc_tied_target_features = the target features {$features} must all be either enabled or disabled together
-    .help = add the missing features in a `target_feature` attribute
-
 codegen_gcc_unwinding_inline_asm =
     GCC backend does not support unwinding from inline asm
 
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
index 5fdf2680aac..d20e13e15b9 100644
--- a/compiler/rustc_codegen_gcc/src/attributes.rs
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -7,11 +7,9 @@ use rustc_attr::InstructionSetAttr;
 #[cfg(feature = "master")]
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty;
-use rustc_span::symbol::sym;
 
 use crate::context::CodegenCx;
-use crate::errors::TiedTargetFeatures;
-use crate::gcc_util::{check_tied_features, to_gcc_features};
+use crate::gcc_util::to_gcc_features;
 
 /// Get GCC attribute for the provided inline heuristic.
 #[cfg(feature = "master")]
@@ -72,26 +70,10 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
         }
     }
 
-    let function_features = codegen_fn_attrs
+    let mut function_features = codegen_fn_attrs
         .target_features
         .iter()
         .map(|features| features.name.as_str())
-        .collect::<Vec<&str>>();
-
-    if let Some(features) = check_tied_features(
-        cx.tcx.sess,
-        &function_features.iter().map(|features| (*features, true)).collect(),
-    ) {
-        let span = cx
-            .tcx
-            .get_attr(instance.def_id(), sym::target_feature)
-            .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
-        cx.tcx.dcx().create_err(TiedTargetFeatures { features: features.join(", "), span }).emit();
-        return;
-    }
-
-    let mut function_features = function_features
-        .iter()
         .flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter())
         .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match *x {
             InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO(antoyo): support removing feature.
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index 6bada3d334c..dc1895f437b 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -1,9 +1,6 @@
-use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
 
-use crate::fluent_generated as fluent;
-
 #[derive(Diagnostic)]
 #[diag(codegen_gcc_unknown_ctarget_feature_prefix)]
 #[note]
@@ -46,15 +43,6 @@ pub(crate) struct InvalidMinimumAlignment {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc_tied_target_features)]
-#[help]
-pub(crate) struct TiedTargetFeatures {
-    #[primary_span]
-    pub span: Span,
-    pub features: String,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_gcc_copy_bitcode)]
 pub(crate) struct CopyBitcode {
     pub err: std::io::Error,
@@ -78,27 +66,3 @@ pub(crate) struct LtoDylib;
 pub(crate) struct LtoBitcodeFromRlib {
     pub gcc_err: String,
 }
-
-pub(crate) struct TargetFeatureDisableOrEnable<'a> {
-    pub features: &'a [&'a str],
-    pub span: Option<Span>,
-    pub missing_features: Option<MissingFeatures>,
-}
-
-#[derive(Subdiagnostic)]
-#[help(codegen_gcc_missing_features)]
-pub(crate) struct MissingFeatures;
-
-impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
-    fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
-        let mut diag = Diag::new(dcx, level, fluent::codegen_gcc_target_feature_disable_or_enable);
-        if let Some(span) = self.span {
-            diag.span(span);
-        };
-        if let Some(missing_features) = self.missing_features {
-            diag.subdiagnostic(missing_features);
-        }
-        diag.arg("features", self.features.join(", "));
-        diag
-    }
-}
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 01dd1a8856a..3104088e0d5 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -1,15 +1,14 @@
 #[cfg(feature = "master")]
 use gccjit::Context;
+use rustc_codegen_ssa::codegen_attrs::check_tied_features;
+use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::bug;
 use rustc_session::Session;
 use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
 use smallvec::{SmallVec, smallvec};
 
-use crate::errors::{
-    PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
-    UnknownCTargetFeaturePrefix,
-};
+use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
 
 /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
 /// `--target` and similar).
@@ -185,23 +184,6 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]>
     }
 }
 
-// Given a map from target_features to whether they are enabled or disabled,
-// ensure only valid combinations are allowed.
-pub fn check_tied_features(
-    sess: &Session,
-    features: &FxHashMap<&str, bool>,
-) -> Option<&'static [&'static str]> {
-    for tied in sess.target.tied_target_features() {
-        // Tied features must be set to the same value, or not set at all
-        let mut tied_iter = tied.iter();
-        let enabled = features.get(tied_iter.next().unwrap());
-        if tied_iter.any(|feature| enabled != features.get(feature)) {
-            return Some(tied);
-        }
-    }
-    None
-}
-
 fn arch_to_gcc(name: &str) -> &str {
     match name {
         "M68020" => "68020",
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index df2198df14b..0950e4bb26b 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -33,9 +33,6 @@ codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type wit
 codegen_llvm_mismatch_data_layout =
     data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`
 
-codegen_llvm_missing_features =
-    add the missing features in a `target_feature` attribute
-
 codegen_llvm_multiple_source_dicompileunit = multiple source DICompileUnits found
 codegen_llvm_multiple_source_dicompileunit_with_llvm_err = multiple source DICompileUnits found: {$llvm_err}
 
@@ -63,9 +60,6 @@ codegen_llvm_serialize_module_with_llvm_err = failed to serialize module {$name}
 codegen_llvm_symbol_already_defined =
     symbol `{$symbol_name}` is already defined
 
-codegen_llvm_target_feature_disable_or_enable =
-    the target features {$features} must all be either enabled or disabled together
-
 codegen_llvm_target_machine = could not create LLVM TargetMachine for triple: {$triple}
 codegen_llvm_target_machine_with_llvm_err = could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}
 
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 489259da856..2c5ec9dad59 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -6,12 +6,11 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
-use rustc_span::symbol::sym;
 use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector};
 use smallvec::SmallVec;
 
 use crate::context::CodegenCx;
-use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable};
+use crate::errors::SanitizerMemtagRequiresMte;
 use crate::llvm::AttributePlace::Function;
 use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
 use crate::value::Value;
@@ -502,26 +501,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
     let function_features =
         codegen_fn_attrs.target_features.iter().map(|f| f.name.as_str()).collect::<Vec<&str>>();
 
-    if let Some(f) = llvm_util::check_tied_features(
-        cx.tcx.sess,
-        &function_features.iter().map(|f| (*f, true)).collect(),
-    ) {
-        let span = cx
-            .tcx
-            .get_attrs(instance.def_id(), sym::target_feature)
-            .next()
-            .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
-        cx.tcx
-            .dcx()
-            .create_err(TargetFeatureDisableOrEnable {
-                features: f,
-                span: Some(span),
-                missing_features: Some(MissingFeatures),
-            })
-            .emit();
-        return;
-    }
-
     let function_features = function_features
         .iter()
         // Convert to LLVMFeatures and filter out unavailable ones
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index bb481d2a308..0d436e1891e 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -80,30 +80,6 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
     }
 }
 
-pub(crate) struct TargetFeatureDisableOrEnable<'a> {
-    pub features: &'a [&'a str],
-    pub span: Option<Span>,
-    pub missing_features: Option<MissingFeatures>,
-}
-
-#[derive(Subdiagnostic)]
-#[help(codegen_llvm_missing_features)]
-pub(crate) struct MissingFeatures;
-
-impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
-    fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
-        let mut diag = Diag::new(dcx, level, fluent::codegen_llvm_target_feature_disable_or_enable);
-        if let Some(span) = self.span {
-            diag.span(span);
-        };
-        if let Some(missing_features) = self.missing_features {
-            diag.subdiagnostic(missing_features);
-        }
-        diag.arg("features", self.features.join(", "));
-        diag
-    }
-}
-
 #[derive(Diagnostic)]
 #[diag(codegen_llvm_lto_disallowed)]
 pub(crate) struct LtoDisallowed;
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index bd847cd0068..57936215ff1 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -6,6 +6,7 @@ use std::{ptr, slice, str};
 
 use libc::c_int;
 use rustc_codegen_ssa::base::wants_wasm_eh;
+use rustc_codegen_ssa::codegen_attrs::check_tied_features;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::unord::UnordSet;
@@ -19,8 +20,8 @@ use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATU
 
 use crate::back::write::create_informational_target_machine;
 use crate::errors::{
-    FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable,
-    UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
+    FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, UnknownCTargetFeature,
+    UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
 };
 use crate::llvm;
 
@@ -247,7 +248,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")),
         ("aarch64", "paca") => Some(LLVMFeature::new("pauth")),
         ("aarch64", "pacg") => Some(LLVMFeature::new("pauth")),
-        ("aarch64", "sve-b16b16") => Some(LLVMFeature::new("b16b16")),
+        // Before LLVM 20 those two features were packaged together as b16b16
+        ("aarch64", "sve-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
+        ("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
         ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")),
         // Rust ties fp and neon together.
         ("aarch64", "neon") => {
@@ -276,25 +279,6 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
     }
 }
 
-/// Given a map from target_features to whether they are enabled or disabled,
-/// ensure only valid combinations are allowed.
-pub(crate) fn check_tied_features(
-    sess: &Session,
-    features: &FxHashMap<&str, bool>,
-) -> Option<&'static [&'static str]> {
-    if !features.is_empty() {
-        for tied in sess.target.tied_target_features() {
-            // Tied features must be set to the same value, or not set at all
-            let mut tied_iter = tied.iter();
-            let enabled = features.get(tied_iter.next().unwrap());
-            if tied_iter.any(|f| enabled != features.get(f)) {
-                return Some(tied);
-            }
-        }
-    }
-    None
-}
-
 /// Used to generate cfg variables and apply features
 /// Must express features in the way Rust understands them
 pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
@@ -685,7 +669,7 @@ pub(crate) fn global_llvm_features(
         features.extend(feats);
 
         if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
-            sess.dcx().emit_err(TargetFeatureDisableOrEnable {
+            sess.dcx().emit_err(rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable {
                 features: f,
                 span: None,
                 missing_features: None,
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index f02b0f72674..d07274920fe 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -183,6 +183,8 @@ codegen_ssa_metadata_object_file_write = error writing metadata object file: {$e
 
 codegen_ssa_missing_cpp_build_tool_component = or a necessary component may be missing from the "C++ build tools" workload
 
+codegen_ssa_missing_features = add the missing features in a `target_feature` attribute
+
 codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering
 
 codegen_ssa_missing_query_depgraph =
@@ -238,6 +240,9 @@ codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` fa
 
 codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
 
+codegen_ssa_target_feature_disable_or_enable =
+    the target features {$features} must all be either enabled or disabled together
+
 codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method
     .label = cannot be applied to safe trait method
     .label_def = not an `unsafe` function
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 8d634ca4655..d536419ab3c 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,5 +1,6 @@
 use rustc_ast::{MetaItemInner, MetaItemKind, ast, attr};
 use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr, list_contains_name};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::codes::*;
 use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
 use rustc_hir as hir;
@@ -13,13 +14,13 @@ use rustc_middle::middle::codegen_fn_attrs::{
 use rustc_middle::mir::mono::Linkage;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self as ty, TyCtxt};
-use rustc_session::lint;
 use rustc_session::parse::feature_err;
+use rustc_session::{Session, lint};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, sym};
 use rustc_target::spec::{SanitizerSet, abi};
 
-use crate::errors;
+use crate::errors::{self, MissingFeatures, TargetFeatureDisableOrEnable};
 use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
 
 fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
@@ -662,9 +663,49 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         }
     }
 
+    if let Some(features) = check_tied_features(
+        tcx.sess,
+        &codegen_fn_attrs
+            .target_features
+            .iter()
+            .map(|features| (features.name.as_str(), true))
+            .collect(),
+    ) {
+        let span = tcx
+            .get_attrs(did, sym::target_feature)
+            .next()
+            .map_or_else(|| tcx.def_span(did), |a| a.span);
+        tcx.dcx()
+            .create_err(TargetFeatureDisableOrEnable {
+                features,
+                span: Some(span),
+                missing_features: Some(MissingFeatures),
+            })
+            .emit();
+    }
+
     codegen_fn_attrs
 }
 
+/// Given a map from target_features to whether they are enabled or disabled, ensure only valid
+/// combinations are allowed.
+pub fn check_tied_features(
+    sess: &Session,
+    features: &FxHashMap<&str, bool>,
+) -> Option<&'static [&'static str]> {
+    if !features.is_empty() {
+        for tied in sess.target.tied_target_features() {
+            // Tied features must be set to the same value, or not set at all
+            let mut tied_iter = tied.iter();
+            let enabled = features.get(tied_iter.next().unwrap());
+            if tied_iter.any(|f| enabled != features.get(f)) {
+                return Some(tied);
+            }
+        }
+    }
+    None
+}
+
 /// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
 /// applied to the method prototype.
 fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index ab909abcead..d67cf0e3a6d 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -9,7 +9,7 @@ use rustc_errors::codes::*;
 use rustc_errors::{
     Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
 };
-use rustc_macros::Diagnostic;
+use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::LayoutError;
 use rustc_span::{Span, Symbol};
@@ -1068,3 +1068,27 @@ pub(crate) struct ErrorCreatingImportLibrary<'a> {
     pub lib_name: &'a str,
     pub error: String,
 }
+
+pub struct TargetFeatureDisableOrEnable<'a> {
+    pub features: &'a [&'a str],
+    pub span: Option<Span>,
+    pub missing_features: Option<MissingFeatures>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(codegen_ssa_missing_features)]
+pub struct MissingFeatures;
+
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
+    fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
+        let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_target_feature_disable_or_enable);
+        if let Some(span) = self.span {
+            diag.span(span);
+        };
+        if let Some(missing_features) = self.missing_features {
+            diag.subdiagnostic(missing_features);
+        }
+        diag.arg("features", self.features.join(", "));
+        diag
+    }
+}
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 0cd0963d4e3..c275ad31b87 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -154,6 +154,10 @@ declare_features! (
     /// then removed. But there was no utility storing it separately, so now
     /// it's in this list.
     (removed, no_stack_check, "1.0.0", None, None),
+    /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe).
+    /// Renamed to `dyn_compatible_for_dispatch`.
+    (removed, object_safe_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561),
+     Some("renamed to `dyn_compatible_for_dispatch`")),
     /// Allows using `#[on_unimplemented(..)]` on traits.
     /// (Moved to `rustc_attrs`.)
     (removed, on_unimplemented, "1.40.0", None, None),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 380e36fe405..1331be53035 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -259,6 +259,14 @@ declare_features! (
     (unstable, doc_notable_trait, "1.52.0", Some(45040)),
     /// Allows using the `may_dangle` attribute (RFC 1327).
     (unstable, dropck_eyepatch, "1.10.0", Some(34761)),
+    /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1].
+    /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
+    /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
+    ///
+    /// Renamed from `object_safe_for_dispatch`.
+    ///
+    /// [^1]: Formerly known as "object safe".
+    (unstable, dyn_compatible_for_dispatch, "CURRENT_RUSTC_VERSION", Some(43561)),
     /// Allows using the `#[fundamental]` attribute.
     (unstable, fundamental, "1.0.0", Some(29635)),
     /// Allows using `#[link_name="llvm.*"]`.
@@ -546,13 +554,6 @@ declare_features! (
     (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)),
     /// Allows `for<T>` binders in where-clauses
     (incomplete, non_lifetime_binders, "1.69.0", Some(108185)),
-    /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1].
-    /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
-    /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
-    ///
-    /// [^1]: Formerly known as "object safe".
-    // FIXME(dyn_compat_renaming): Rename feature.
-    (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)),
     /// Allows using enums in offset_of!
     (unstable, offset_of_enum, "1.75.0", Some(120141)),
     /// Allows using fields with slice type in offset_of!
@@ -565,6 +566,8 @@ declare_features! (
     (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)),
     /// Allows postfix match `expr.match { ... }`
     (unstable, postfix_match, "1.79.0", Some(121618)),
+    /// Allows `use<..>` precise capturign on impl Trait in traits.
+    (unstable, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
     (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index c73826c489f..a80dc87c622 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -259,6 +259,9 @@ hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetim
 hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
     .label = type parameter declared here
 
+hir_analysis_lifetime_implicitly_captured = `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
+    .param_label = all lifetime parameters originating from a trait are captured implicitly
+
 hir_analysis_lifetime_must_be_first = lifetime parameter `{$name}` must be listed before non-lifetime parameters
     .label = move the lifetime before this parameter
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index eb62ff86c71..d0063b449f8 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -589,15 +589,22 @@ fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDe
                                 param_span: tcx.def_span(def_id),
                             });
                         } else {
-                            // If the `use_span` is actually just the param itself, then we must
-                            // have not duplicated the lifetime but captured the original.
-                            // The "effective" `use_span` will be the span of the opaque itself,
-                            // and the param span will be the def span of the param.
-                            tcx.dcx().emit_err(errors::LifetimeNotCaptured {
-                                opaque_span,
-                                use_span: opaque_span,
-                                param_span: use_span,
-                            });
+                            if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait {
+                                tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured {
+                                    opaque_span,
+                                    param_span: tcx.def_span(param.def_id),
+                                });
+                            } else {
+                                // If the `use_span` is actually just the param itself, then we must
+                                // have not duplicated the lifetime but captured the original.
+                                // The "effective" `use_span` will be the span of the opaque itself,
+                                // and the param span will be the def span of the param.
+                                tcx.dcx().emit_err(errors::LifetimeNotCaptured {
+                                    opaque_span,
+                                    use_span: opaque_span,
+                                    param_span: use_span,
+                                });
+                            }
                         }
                         continue;
                     }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 80334c6efe7..2d6b9813271 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -64,6 +64,10 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
         return;
     };
 
+    if hidden_tys.items().any(|(_, &ty)| ty.skip_binder().references_error()) {
+        return;
+    }
+
     let mut collector = ImplTraitInTraitCollector { tcx, types: FxIndexSet::default() };
     trait_m_sig.visit_with(&mut collector);
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 69d36426447..eea5a16ac6f 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -199,7 +199,7 @@ fn check_object_overlap<'tcx>(
         for component_def_id in component_def_ids {
             if !tcx.is_dyn_compatible(component_def_id) {
                 // FIXME(dyn_compat_renaming): Rename test and update comment.
-                // Without the 'object_safe_for_dispatch' feature this is an error
+                // Without the 'dyn_compatible_for_dispatch' feature this is an error
                 // which will be reported by wfcheck. Ignore it here.
                 // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
                 // With the feature enabled, the trait is not implemented automatically,
diff --git a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
index b6cffb90805..8a83866b7fa 100644
--- a/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
+++ b/compiler/rustc_hir_analysis/src/errors/precise_captures.rs
@@ -35,6 +35,15 @@ pub(crate) struct LifetimeNotCaptured {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_lifetime_implicitly_captured)]
+pub(crate) struct LifetimeImplicitlyCaptured {
+    #[primary_span]
+    pub opaque_span: Span,
+    #[label(hir_analysis_param_label)]
+    pub param_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(hir_analysis_bad_precise_capture)]
 pub(crate) struct BadPreciseCapture {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 12bb9a3f9e0..02cfb57b836 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -5,6 +5,7 @@
 
 use itertools::Itertools;
 use rustc_arena::DroplessArena;
+use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
@@ -63,8 +64,29 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
             let crate_map = tcx.crate_variances(());
             return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
         }
+        DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
+            Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+                return variance_of_opaque(
+                    tcx,
+                    opaque_def_id.expect_local(),
+                    ForceCaptureTraitArgs::Yes,
+                );
+            }
+            None | Some(ty::ImplTraitInTraitData::Impl { .. }) => {}
+        },
         DefKind::OpaqueTy => {
-            return variance_of_opaque(tcx, item_def_id);
+            let force_capture_trait_args = if let hir::OpaqueTyOrigin::FnReturn {
+                parent: _,
+                in_trait_or_impl: Some(hir::RpitContext::Trait),
+            } =
+                tcx.hir_node_by_def_id(item_def_id).expect_opaque_ty().origin
+            {
+                ForceCaptureTraitArgs::Yes
+            } else {
+                ForceCaptureTraitArgs::No
+            };
+
+            return variance_of_opaque(tcx, item_def_id, force_capture_trait_args);
         }
         _ => {}
     }
@@ -73,8 +95,18 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
     span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
 }
 
+#[derive(Debug, Copy, Clone)]
+enum ForceCaptureTraitArgs {
+    Yes,
+    No,
+}
+
 #[instrument(level = "trace", skip(tcx), ret)]
-fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
+fn variance_of_opaque(
+    tcx: TyCtxt<'_>,
+    item_def_id: LocalDefId,
+    force_capture_trait_args: ForceCaptureTraitArgs,
+) -> &[ty::Variance] {
     let generics = tcx.generics_of(item_def_id);
 
     // Opaque types may only use regions that are bound. So for
@@ -115,9 +147,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         #[instrument(level = "trace", skip(self), ret)]
         fn visit_ty(&mut self, t: Ty<'tcx>) {
             match t.kind() {
-                ty::Alias(_, ty::AliasTy { def_id, args, .. })
-                    if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
-                {
+                ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
                     self.visit_opaque(*def_id, args);
                 }
                 _ => t.super_visit_with(self),
@@ -135,6 +165,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         let mut generics = generics;
         while let Some(def_id) = generics.parent {
             generics = tcx.generics_of(def_id);
+
+            // Don't mark trait params generic if we're in an RPITIT.
+            if matches!(force_capture_trait_args, ForceCaptureTraitArgs::Yes)
+                && generics.parent.is_none()
+            {
+                debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
+                break;
+            }
+
             for param in &generics.own_params {
                 match param.kind {
                     ty::GenericParamDefKind::Lifetime => {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 610c682d3a4..afe03531861 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1100,9 +1100,12 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def
         | DefKind::Fn
         | DefKind::Ctor(..)
         | DefKind::AssocFn => true,
+        DefKind::AssocTy => {
+            // Only encode variances for RPITITs (for traits)
+            matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. }))
+        }
         DefKind::Mod
         | DefKind::Field
-        | DefKind::AssocTy
         | DefKind::AssocConst
         | DefKind::TyParam
         | DefKind::ConstParam
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 90265f67bc1..590e1d336f3 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -539,6 +539,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
         self.trait_def(trait_def_id).implement_via_object
     }
 
+    fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
+        self.is_impl_trait_in_trait(def_id)
+    }
+
     fn delay_bug(self, msg: impl ToString) -> ErrorGuaranteed {
         self.dcx().span_delayed_bug(DUMMY_SP, msg.to_string())
     }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index d67e69fe0fb..27879d817b2 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -454,6 +454,8 @@ impl Session {
         let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple());
         let fallback_sysroot_paths = filesearch::sysroot_candidates()
             .into_iter()
+            // Ignore sysroot candidate if it was the same as the sysroot path we just used.
+            .filter(|sysroot| *sysroot != self.sysroot)
             .map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple()));
         let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths);
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 1527600e764..8e0009695db 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -777,6 +777,7 @@ symbols! {
         dropck_eyepatch,
         dropck_parametricity,
         dylib,
+        dyn_compatible_for_dispatch,
         dyn_metadata,
         dyn_star,
         dyn_trait,
@@ -1479,6 +1480,7 @@ symbols! {
         powif64,
         pre_dash_lto: "pre-lto",
         precise_capturing,
+        precise_capturing_in_traits,
         precise_pointer_size_matching,
         pref_align_of,
         prefetch_read_data,
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 0a98b363b1a..e92366d5c5c 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -191,6 +191,8 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("sm4", Stable, &["neon"]),
     // FEAT_SME
     ("sme", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
+    // FEAT_SME_B16B16
+    ("sme-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16", "sme2", "sve-b16b16"]),
     // FEAT_SME_F16F16
     ("sme-f16f16", Unstable(sym::aarch64_unstable_target_feature), &["sme2"]),
     // FEAT_SME_F64F64
@@ -227,7 +229,7 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     //
     // "For backwards compatibility, Neon and VFP are required in the latest architectures."
     ("sve", Stable, &["neon"]),
-    // FEAT_SVE_B16B16 (SVE or SME Instructions)
+    // FEAT_SVE_B16B16 (SVE or SME Z-targeting instructions)
     ("sve-b16b16", Unstable(sym::aarch64_unstable_target_feature), &["bf16"]),
     // FEAT_SVE2
     ("sve2", Stable, &["sve"]),
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index d5d7681a8d6..45e7de942fb 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -1,12 +1,8 @@
-//! "Object safety" refers to the ability for a trait to be converted
-//! to an object. In general, traits may only be converted to an
-//! object if all of their methods meet certain criteria. In particular,
-//! they must:
+//! "Dyn-compatibility"[^1] refers to the ability for a trait to be converted
+//! to a trait object. In general, traits may only be converted to a trait
+//! object if certain criteria are met.
 //!
-//!   - have a suitable receiver from which we can extract a vtable and coerce to a "thin" version
-//!     that doesn't contain the vtable;
-//!   - not reference the erased type `Self` except for in this receiver;
-//!   - not have generic type parameters.
+//! [^1]: Formerly known as "object safety".
 
 use std::iter;
 use std::ops::ControlFlow;
@@ -506,8 +502,8 @@ fn virtual_call_violations_for_method<'tcx>(
 
 /// This code checks that `receiver_is_dispatchable` is correctly implemented.
 ///
-/// This check is outlined from the object safety check to avoid cycles with
-/// layout computation, which relies on knowing whether methods are object safe.
+/// This check is outlined from the dyn-compatibility check to avoid cycles with
+/// layout computation, which relies on knowing whether methods are dyn-compatible.
 fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) {
     if !is_vtable_safe_method(tcx, trait_def_id, method) {
         return;
@@ -643,8 +639,8 @@ fn object_ty_for_trait<'tcx>(
 /// contained by the trait object, because the object that needs to be coerced is behind
 /// a pointer.
 ///
-/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result
-/// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch
+/// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result in
+/// a new check that `Trait` is dyn-compatible, creating a cycle (until dyn_compatible_for_dispatch
 /// is stabilized, see tracking issue <https://github.com/rust-lang/rust/issues/43561>).
 /// Instead, we fudge a little by introducing a new type parameter `U` such that
 /// `Self: Unsize<U>` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`.
@@ -678,7 +674,7 @@ fn receiver_is_dispatchable<'tcx>(
 
     // the type `U` in the query
     // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now.
-    // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can
+    // FIXME(mikeyhew) this is a total hack. Once dyn_compatible_for_dispatch is stabilized, we can
     // replace this with `dyn Trait`
     let unsized_self_ty: Ty<'tcx> =
         Ty::new_param(tcx, u32::MAX, Symbol::intern("RustaceansAreAwesome"));
@@ -865,7 +861,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
     }
 
     fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
-        // Constants can only influence object safety if they are generic and reference `Self`.
+        // Constants can only influence dyn-compatibility if they are generic and reference `Self`.
         // This is only possible for unevaluated constants, so we walk these here.
         self.tcx.expand_abstract_consts(ct).super_visit_with(self)
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 084b61115db..20adda6f0de 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -881,7 +881,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         }
 
                         if let Some(principal) = data.principal() {
-                            if !self.infcx.tcx.features().object_safe_for_dispatch {
+                            if !self.infcx.tcx.features().dyn_compatible_for_dispatch {
                                 principal.with_self_ty(self.tcx(), self_ty)
                             } else if self.tcx().is_dyn_compatible(principal.def_id()) {
                                 principal.with_self_ty(self.tcx(), self_ty)
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 7e140ecfee0..a849cdfe125 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -829,7 +829,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 // obligations that don't refer to Self and
                 // checking those
 
-                let defer_to_coercion = tcx.features().object_safe_for_dispatch;
+                let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch;
 
                 if !defer_to_coercion {
                     if let Some(principal) = data.principal_def_id() {
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index a72e7b482a6..f06017d7e5c 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -261,6 +261,8 @@ pub trait Interner:
 
     fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
 
+    fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
+
     fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed;
 
     fn is_general_coroutine(self, coroutine_def_id: Self::DefId) -> bool;
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index 1302906adab..e1f3e493e36 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -254,6 +254,16 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
                     b.args,
                     false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
                 )?,
+                ty::Projection if relation.cx().is_impl_trait_in_trait(a.def_id) => {
+                    relate_args_with_variances(
+                        relation,
+                        a.def_id,
+                        relation.cx().variances_of(a.def_id),
+                        a.args,
+                        b.args,
+                        false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
+                    )?
+                }
                 ty::Projection | ty::Weak | ty::Inherent => {
                     relate_args_invariantly(relation, a.args, b.args)?
                 }