about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis')
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs192
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs44
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs24
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/collect/dump.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs (renamed from compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs)558
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs533
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs19
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs2
13 files changed, 764 insertions, 661 deletions
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index e8237471e1b..88bd3339e4e 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -68,7 +68,14 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
             return None;
         }
 
-        if self.state.cur_ty.is_ty_var() {
+        // We want to support method and function calls for `impl Deref<Target = ..>`.
+        //
+        // To do so we don't eagerly bail if the current type is the hidden type of an
+        // opaque type and instead return `None` in `fn overloaded_deref_ty` if the
+        // opaque does not have a `Deref` item-bound.
+        if let &ty::Infer(ty::TyVar(vid)) = self.state.cur_ty.kind()
+            && !self.infcx.has_opaques_with_sub_unified_hidden_type(vid)
+        {
             return None;
         }
 
@@ -160,7 +167,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             self.param_env,
             ty::Binder::dummy(trait_ref),
         );
-        if !self.infcx.next_trait_solver() && !self.infcx.predicate_may_hold(&obligation) {
+        // We detect whether the self type implements `Deref` before trying to
+        // structurally normalize. We use `predicate_may_hold_opaque_types_jank`
+        // to support not-yet-defined opaque types. It will succeed for `impl Deref`
+        // but fail for `impl OtherTrait`.
+        if !self.infcx.predicate_may_hold_opaque_types_jank(&obligation) {
             debug!("overloaded_deref_ty: cannot match obligation");
             return None;
         }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index aa2d27ab809..bc3448be582 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -64,83 +64,159 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
         // it's usually worth updating that intrinsic's documentation
         // to note that it's safe to call, since
         // safe extern fns are otherwise unprecedented.
-        sym::abort
+
+        // tidy-alphabetical-start
+        | sym::abort
+        | sym::add_with_overflow
+        | sym::aggregate_raw_ptr
+        | sym::align_of
         | sym::assert_inhabited
-        | sym::assert_zero_valid
         | sym::assert_mem_uninitialized_valid
+        | sym::assert_zero_valid
+        | sym::autodiff
+        | sym::bitreverse
+        | sym::black_box
         | sym::box_new
         | sym::breakpoint
-        | sym::size_of
-        | sym::align_of
-        | sym::needs_drop
+        | sym::bswap
         | sym::caller_location
-        | sym::add_with_overflow
-        | sym::sub_with_overflow
-        | sym::mul_with_overflow
         | sym::carrying_mul_add
-        | sym::wrapping_add
-        | sym::wrapping_sub
-        | sym::wrapping_mul
-        | sym::saturating_add
-        | sym::saturating_sub
-        | sym::rotate_left
-        | sym::rotate_right
-        | sym::ctpop
+        | sym::ceilf16
+        | sym::ceilf32
+        | sym::ceilf64
+        | sym::ceilf128
+        | sym::cold_path
+        | sym::const_eval_select
+        | sym::contract_check_ensures
+        | sym::contract_check_requires
+        | sym::contract_checks
+        | sym::copysignf16
+        | sym::copysignf32
+        | sym::copysignf64
+        | sym::copysignf128
+        | sym::cosf16
+        | sym::cosf32
+        | sym::cosf64
+        | sym::cosf128
         | sym::ctlz
+        | sym::ctpop
         | sym::cttz
-        | sym::bswap
-        | sym::bitreverse
-        | sym::three_way_compare
         | sym::discriminant_value
-        | sym::type_id
-        | sym::type_id_eq
-        | sym::select_unpredictable
-        | sym::cold_path
-        | sym::ptr_guaranteed_cmp
-        | sym::minnumf16
-        | sym::minnumf32
-        | sym::minnumf64
-        | sym::minnumf128
-        | sym::minimumf16
-        | sym::minimumf32
-        | sym::minimumf64
-        | sym::minimumf128
-        | sym::maxnumf16
-        | sym::maxnumf32
-        | sym::maxnumf64
-        | sym::maxnumf128
+        | sym::exp2f16
+        | sym::exp2f32
+        | sym::exp2f64
+        | sym::exp2f128
+        | sym::expf16
+        | sym::expf32
+        | sym::expf64
+        | sym::expf128
+        | sym::fabsf16
+        | sym::fabsf32
+        | sym::fabsf64
+        | sym::fabsf128
+        | sym::fadd_algebraic
+        | sym::fdiv_algebraic
+        | sym::floorf16
+        | sym::floorf32
+        | sym::floorf64
+        | sym::floorf128
+        | sym::fmaf16
+        | sym::fmaf32
+        | sym::fmaf64
+        | sym::fmaf128
+        | sym::fmul_algebraic
+        | sym::fmuladdf16
+        | sym::fmuladdf32
+        | sym::fmuladdf64
+        | sym::fmuladdf128
+        | sym::forget
+        | sym::frem_algebraic
+        | sym::fsub_algebraic
+        | sym::is_val_statically_known
+        | sym::log2f16
+        | sym::log2f32
+        | sym::log2f64
+        | sym::log2f128
+        | sym::log10f16
+        | sym::log10f32
+        | sym::log10f64
+        | sym::log10f128
+        | sym::logf16
+        | sym::logf32
+        | sym::logf64
+        | sym::logf128
         | sym::maximumf16
         | sym::maximumf32
         | sym::maximumf64
         | sym::maximumf128
-        | sym::rustc_peek
-        | sym::type_name
-        | sym::forget
-        | sym::black_box
-        | sym::variant_count
-        | sym::is_val_statically_known
+        | sym::maxnumf16
+        | sym::maxnumf32
+        | sym::maxnumf64
+        | sym::maxnumf128
+        | sym::minimumf16
+        | sym::minimumf32
+        | sym::minimumf64
+        | sym::minimumf128
+        | sym::minnumf16
+        | sym::minnumf32
+        | sym::minnumf64
+        | sym::minnumf128
+        | sym::mul_with_overflow
+        | sym::needs_drop
+        | sym::powf16
+        | sym::powf32
+        | sym::powf64
+        | sym::powf128
+        | sym::powif16
+        | sym::powif32
+        | sym::powif64
+        | sym::powif128
+        | sym::prefetch_read_data
+        | sym::prefetch_read_instruction
+        | sym::prefetch_write_data
+        | sym::prefetch_write_instruction
+        | sym::ptr_guaranteed_cmp
         | sym::ptr_mask
-        | sym::aggregate_raw_ptr
         | sym::ptr_metadata
-        | sym::ub_checks
-        | sym::contract_checks
-        | sym::contract_check_requires
-        | sym::contract_check_ensures
-        | sym::fadd_algebraic
-        | sym::fsub_algebraic
-        | sym::fmul_algebraic
-        | sym::fdiv_algebraic
-        | sym::frem_algebraic
+        | sym::rotate_left
+        | sym::rotate_right
         | sym::round_ties_even_f16
         | sym::round_ties_even_f32
         | sym::round_ties_even_f64
         | sym::round_ties_even_f128
-        | sym::autodiff
-        | sym::prefetch_read_data
-        | sym::prefetch_write_data
-        | sym::prefetch_read_instruction
-        | sym::prefetch_write_instruction
-        | sym::const_eval_select => hir::Safety::Safe,
+        | sym::roundf16
+        | sym::roundf32
+        | sym::roundf64
+        | sym::roundf128
+        | sym::rustc_peek
+        | sym::saturating_add
+        | sym::saturating_sub
+        | sym::select_unpredictable
+        | sym::sinf16
+        | sym::sinf32
+        | sym::sinf64
+        | sym::sinf128
+        | sym::size_of
+        | sym::sqrtf16
+        | sym::sqrtf32
+        | sym::sqrtf64
+        | sym::sqrtf128
+        | sym::sub_with_overflow
+        | sym::three_way_compare
+        | sym::truncf16
+        | sym::truncf32
+        | sym::truncf64
+        | sym::truncf128
+        | sym::type_id
+        | sym::type_id_eq
+        | sym::type_name
+        | sym::ub_checks
+        | sym::variant_count
+        | sym::wrapping_add
+        | sym::wrapping_mul
+        | sym::wrapping_sub
+        // tidy-alphabetical-end
+        => hir::Safety::Safe,
         _ => hir::Safety::Unsafe,
     };
 
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 63d0f400aef..e70d5505aae 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -70,6 +70,7 @@ pub mod intrinsic;
 mod region;
 pub mod wfcheck;
 
+use std::borrow::Cow;
 use std::num::NonZero;
 
 pub use check::{check_abi, check_custom_abi};
@@ -86,7 +87,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::print::with_types_for_signature;
 use rustc_middle::ty::{
-    self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
+    self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
@@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
     assoc: ty::AssocItem,
 ) -> (String, String) {
     let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
+    let mut regions: FxIndexMap<Region<'tcx>, Vec<Region<'tcx>>> = FxIndexMap::default();
     let mut projections = vec![];
     for (predicate, _) in predicates {
         debug!("predicate {:?}", predicate);
@@ -351,20 +353,23 @@ fn bounds_from_generic_predicates<'tcx>(
             ty::ClauseKind::Projection(projection_pred) => {
                 projections.push(bound_predicate.rebind(projection_pred));
             }
+            ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => {
+                regions.entry(a).or_default().push(b);
+            }
             _ => {}
         }
     }
 
     let mut where_clauses = vec![];
     let generics = tcx.generics_of(assoc.def_id);
-    let types_str = generics
+    let params = generics
         .own_params
         .iter()
-        .filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
-        .map(|p| {
-            // we just checked that it's a type, so the unwrap can't fail
-            let ty = tcx.mk_param_from_def(p).as_type().unwrap();
-            if let Some(bounds) = types.get(&ty) {
+        .filter(|p| !p.kind.is_synthetic())
+        .map(|p| match tcx.mk_param_from_def(p).kind() {
+            ty::GenericArgKind::Type(ty) => {
+                let bounds =
+                    types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new()));
                 let mut bounds_str = vec![];
                 for bound in bounds.iter().copied() {
                     let mut projections_str = vec![];
@@ -377,7 +382,11 @@ fn bounds_from_generic_predicates<'tcx>(
                             projections_str.push(format!("{} = {}", name, p.term));
                         }
                     }
-                    let bound_def_path = tcx.def_path_str(bound);
+                    let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) {
+                        String::from("?Sized")
+                    } else {
+                        tcx.def_path_str(bound)
+                    };
                     if projections_str.is_empty() {
                         where_clauses.push(format!("{}: {}", ty, bound_def_path));
                     } else {
@@ -393,8 +402,21 @@ fn bounds_from_generic_predicates<'tcx>(
                 } else {
                     format!("{}: {}", ty, bounds_str.join(" + "))
                 }
-            } else {
-                ty.to_string()
+            }
+            ty::GenericArgKind::Const(ct) => {
+                format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder())
+            }
+            ty::GenericArgKind::Lifetime(region) => {
+                if let Some(v) = regions.get(&region)
+                    && !v.is_empty()
+                {
+                    format!(
+                        "{region}: {}",
+                        v.into_iter().map(Region::to_string).collect::<Vec<_>>().join(" + ")
+                    )
+                } else {
+                    region.to_string()
+                }
             }
         })
         .collect::<Vec<_>>();
@@ -409,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>(
     }
 
     let generics =
-        if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
+        if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) };
 
     let where_clauses = if where_clauses.is_empty() {
         "".to_string()
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 2ba7ed46f92..43e6f5fe104 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -467,8 +467,12 @@ fn resolve_local<'tcx>(
     // A, but the inner rvalues `a()` and `b()` have an extended lifetime
     // due to rule C.
 
-    if let_kind == LetKind::Super {
-        if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) {
+    let extend_initializer = match let_kind {
+        LetKind::Regular => true,
+        LetKind::Super
+            if let Some(scope) =
+                visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) =>
+        {
             // This expression was lifetime-extended by a parent let binding. E.g.
             //
             //     let a = {
@@ -481,7 +485,10 @@ fn resolve_local<'tcx>(
             // Processing of `let a` will have already decided to extend the lifetime of this
             // `super let` to its own var_scope. We use that scope.
             visitor.cx.var_parent = scope;
-        } else {
+            // Extend temporaries to live in the same scope as the parent `let`'s bindings.
+            true
+        }
+        LetKind::Super => {
             // This `super let` is not subject to lifetime extension from a parent let binding. E.g.
             //
             //     identity({ super let x = temp(); &x }).method();
@@ -493,10 +500,17 @@ fn resolve_local<'tcx>(
             if let Some(inner_scope) = visitor.cx.var_parent {
                 (visitor.cx.var_parent, _) = visitor.scope_tree.default_temporary_scope(inner_scope)
             }
+            // Don't lifetime-extend child `super let`s or block tail expressions' temporaries in
+            // the initializer when this `super let` is not itself extended by a parent `let`
+            // (#145784). Block tail expressions are temporary drop scopes in Editions 2024 and
+            // later, their temps shouldn't outlive the block in e.g. `f(pin!({ &temp() }))`.
+            false
         }
-    }
+    };
 
-    if let Some(expr) = init {
+    if let Some(expr) = init
+        && extend_initializer
+    {
         record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent);
 
         if let Some(pat) = pat {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index d33f1f3e12a..0a555c7f6e9 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -819,17 +819,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
             let span = tcx.def_span(param.def_id);
             let def_id = param.def_id.expect_local();
 
-            if tcx.features().unsized_const_params() {
-                enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
-                    wfcx.register_bound(
-                        ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
-                        wfcx.param_env,
-                        ty,
-                        tcx.require_lang_item(LangItem::UnsizedConstParamTy, span),
-                    );
-                    Ok(())
-                })
-            } else if tcx.features().adt_const_params() {
+            if tcx.features().adt_const_params() {
                 enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
                     wfcx.register_bound(
                         ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
@@ -880,7 +870,6 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
                     tcx,
                     tcx.param_env(param.def_id),
                     ty,
-                    LangItem::ConstParamTy,
                     cause,
                 ) {
                     // Can never implement `ConstParamTy`, don't suggest anything.
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 32b175611ce..0b9a01d6042 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -1,7 +1,6 @@
 //! Check properties that are required by built-in traits and set
 //! up data structures required by type-checking/codegen.
 
-use std::assert_matches::assert_matches;
 use std::collections::BTreeMap;
 
 use rustc_data_structures::fx::FxHashSet;
@@ -40,10 +39,7 @@ pub(super) fn check_trait<'tcx>(
     checker.check(lang_items.async_drop_trait(), visit_implementation_of_drop)?;
     checker.check(lang_items.copy_trait(), visit_implementation_of_copy)?;
     checker.check(lang_items.const_param_ty_trait(), |checker| {
-        visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
-    })?;
-    checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
-        visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
+        visit_implementation_of_const_param_ty(checker)
     })?;
     checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
     checker
@@ -138,12 +134,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
     }
 }
 
-fn visit_implementation_of_const_param_ty(
-    checker: &Checker<'_>,
-    kind: LangItem,
-) -> Result<(), ErrorGuaranteed> {
-    assert_matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
-
+fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
     let tcx = checker.tcx;
     let header = checker.impl_header;
     let impl_did = checker.impl_def_id;
@@ -157,7 +148,7 @@ fn visit_implementation_of_const_param_ty(
     }
 
     let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
-    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, kind, cause) {
+    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
         Ok(()) => Ok(()),
         Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
             let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index c3f965d8456..44cc2dec1cb 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -152,7 +152,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) {
                     );
                     continue;
                 };
-                let ty::Dynamic(data, _, _) = *ty.kind() else {
+                let ty::Dynamic(data, _) = *ty.kind() else {
                     tcx.dcx()
                         .span_err(attr.span(), "`rustc_dump_vtable` to type alias of dyn type");
                     continue;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
index 76b0ce985f0..81deb35920a 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
@@ -85,6 +85,12 @@ pub(crate) fn validate_cmse_abi<'tcx>(
                 return;
             };
 
+            // An `extern "cmse-nonsecure-entry"` function cannot be c-variadic. We run
+            // into https://github.com/rust-lang/rust/issues/132142 if we don't explicitly bail.
+            if decl.c_variadic {
+                return;
+            }
+
             match is_valid_cmse_inputs(tcx, fn_sig) {
                 Ok(Ok(())) => {}
                 Ok(Err(index)) => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
index 76bb59e3f09..c248cd7fec2 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
@@ -1,16 +1,22 @@
+use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{
+    Applicability, Diag, EmissionGuarantee, StashKey, Suggestions, struct_span_code_err,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
+use rustc_hir::def_id::DefId;
+use rustc_lint_defs::builtin::{BARE_TRAIT_OBJECTS, UNUSED_ASSOCIATED_TYPE_BOUNDS};
 use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
 use rustc_middle::ty::{
-    self, BottomUpFolder, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
+    self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable,
     TypeVisitableExt, Upcast,
 };
+use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility;
+use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
 use rustc_trait_selection::traits;
 use smallvec::{SmallVec, smallvec};
 use tracing::{debug, instrument};
@@ -28,11 +34,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         hir_id: hir::HirId,
         hir_bounds: &[hir::PolyTraitRef<'tcx>],
         lifetime: &hir::Lifetime,
-        representation: DynKind,
+        syntax: TraitObjectSyntax,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
         let dummy_self = tcx.types.trait_object_dummy_self;
 
+        match syntax {
+            TraitObjectSyntax::Dyn => {}
+            TraitObjectSyntax::None => {
+                match self.prohibit_or_lint_bare_trait_object_ty(span, hir_id, hir_bounds) {
+                    // Don't continue with type analysis if the `dyn` keyword is missing.
+                    // It generates confusing errors, especially if the user meant to use
+                    // another keyword like `impl`.
+                    Some(guar) => return Ty::new_error(tcx, guar),
+                    None => {}
+                }
+            }
+        }
+
         let mut user_written_bounds = Vec::new();
         let mut potential_assoc_types = Vec::new();
         for poly_trait_ref in hir_bounds.iter() {
@@ -47,10 +66,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
         }
 
-        let ast_bounds: Vec<_> =
-            hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect();
-
-        self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span);
+        self.add_default_traits(
+            &mut user_written_bounds,
+            dummy_self,
+            &hir_bounds
+                .iter()
+                .map(|&trait_ref| hir::GenericBound::Trait(trait_ref))
+                .collect::<Vec<_>>(),
+            None,
+            span,
+        );
 
         let (elaborated_trait_bounds, elaborated_projection_bounds) =
             traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
@@ -431,7 +456,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         };
         debug!(?region_bound);
 
-        Ty::new_dynamic(tcx, existential_predicates, region_bound, representation)
+        Ty::new_dynamic(tcx, existential_predicates, region_bound)
     }
 
     /// Check that elaborating the principal of a trait ref doesn't lead to projections
@@ -483,6 +508,521 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             },
         );
     }
+
+    /// Prohibit or lint against *bare* trait object types depending on the edition.
+    ///
+    /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
+    /// In edition 2021 and onward we emit a hard error for them.
+    fn prohibit_or_lint_bare_trait_object_ty(
+        &self,
+        span: Span,
+        hir_id: hir::HirId,
+        hir_bounds: &[hir::PolyTraitRef<'tcx>],
+    ) -> Option<ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let [poly_trait_ref, ..] = hir_bounds else { return None };
+
+        let in_path = match tcx.parent_hir_node(hir_id) {
+            hir::Node::Ty(hir::Ty {
+                kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)),
+                ..
+            })
+            | hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)),
+                ..
+            })
+            | hir::Node::PatExpr(hir::PatExpr {
+                kind: hir::PatExprKind::Path(hir::QPath::TypeRelative(qself, _)),
+                ..
+            }) if qself.hir_id == hir_id => true,
+            _ => false,
+        };
+        let needs_bracket = in_path
+            && !tcx
+                .sess
+                .source_map()
+                .span_to_prev_source(span)
+                .ok()
+                .is_some_and(|s| s.trim_end().ends_with('<'));
+
+        let is_global = poly_trait_ref.trait_ref.path.is_global();
+
+        let mut sugg = vec![(
+            span.shrink_to_lo(),
+            format!(
+                "{}dyn {}",
+                if needs_bracket { "<" } else { "" },
+                if is_global { "(" } else { "" },
+            ),
+        )];
+
+        if is_global || needs_bracket {
+            sugg.push((
+                span.shrink_to_hi(),
+                format!(
+                    "{}{}",
+                    if is_global { ")" } else { "" },
+                    if needs_bracket { ">" } else { "" },
+                ),
+            ));
+        }
+
+        if span.edition().at_least_rust_2021() {
+            let mut diag = rustc_errors::struct_span_code_err!(
+                self.dcx(),
+                span,
+                E0782,
+                "{}",
+                "expected a type, found a trait"
+            );
+            if span.can_be_used_for_suggestions()
+                && poly_trait_ref.trait_ref.trait_def_id().is_some()
+                && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag)
+                && !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag)
+            {
+                self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag);
+            }
+            // Check if the impl trait that we are considering is an impl of a local trait.
+            self.maybe_suggest_blanket_trait_impl(span, hir_id, &mut diag);
+            self.maybe_suggest_assoc_ty_bound(hir_id, &mut diag);
+            self.maybe_suggest_typoed_method(
+                hir_id,
+                poly_trait_ref.trait_ref.trait_def_id(),
+                &mut diag,
+            );
+            // In case there is an associated type with the same name
+            // Add the suggestion to this error
+            if let Some(mut sugg) =
+                self.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion)
+                && let Suggestions::Enabled(ref mut s1) = diag.suggestions
+                && let Suggestions::Enabled(ref mut s2) = sugg.suggestions
+            {
+                s1.append(s2);
+                sugg.cancel();
+            }
+            Some(diag.emit())
+        } else {
+            tcx.node_span_lint(BARE_TRAIT_OBJECTS, hir_id, span, |lint| {
+                lint.primary_message("trait objects without an explicit `dyn` are deprecated");
+                if span.can_be_used_for_suggestions() {
+                    lint.multipart_suggestion_verbose(
+                        "if this is a dyn-compatible trait, use `dyn`",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+                self.maybe_suggest_blanket_trait_impl(span, hir_id, lint);
+            });
+            None
+        }
+    }
+
+    /// For a struct or enum with an invalid bare trait object field, suggest turning
+    /// it into a generic type bound.
+    fn maybe_suggest_add_generic_impl_trait(
+        &self,
+        span: Span,
+        hir_id: hir::HirId,
+        diag: &mut Diag<'_>,
+    ) -> bool {
+        let tcx = self.tcx();
+
+        let parent_hir_id = tcx.parent_hir_id(hir_id);
+        let parent_item = tcx.hir_get_parent_item(hir_id).def_id;
+
+        let generics = match tcx.hir_node_by_def_id(parent_item) {
+            hir::Node::Item(hir::Item {
+                kind: hir::ItemKind::Struct(_, generics, variant),
+                ..
+            }) => {
+                if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) {
+                    return false;
+                }
+                generics
+            }
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics, def), .. }) => {
+                if !def
+                    .variants
+                    .iter()
+                    .flat_map(|variant| variant.data.fields().iter())
+                    .any(|field| field.hir_id == parent_hir_id)
+                {
+                    return false;
+                }
+                generics
+            }
+            _ => return false,
+        };
+
+        let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(span) else {
+            return false;
+        };
+
+        let param = "TUV"
+            .chars()
+            .map(|c| c.to_string())
+            .chain((0..).map(|i| format!("P{i}")))
+            .find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s))
+            .expect("we definitely can find at least one param name to generate");
+        let mut sugg = vec![(span, param.to_string())];
+        if let Some(insertion_span) = generics.span_for_param_suggestion() {
+            sugg.push((insertion_span, format!(", {param}: {}", rendered_ty)));
+        } else {
+            sugg.push((generics.where_clause_span, format!("<{param}: {}>", rendered_ty)));
+        }
+        diag.multipart_suggestion_verbose(
+            "you might be missing a type parameter",
+            sugg,
+            Applicability::MachineApplicable,
+        );
+        true
+    }
+
+    /// Make sure that we are in the condition to suggest the blanket implementation.
+    fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
+        &self,
+        span: Span,
+        hir_id: hir::HirId,
+        diag: &mut Diag<'_, G>,
+    ) {
+        let tcx = self.tcx();
+        let parent_id = tcx.hir_get_parent_item(hir_id).def_id;
+        if let hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }),
+            ..
+        }) = tcx.hir_node_by_def_id(parent_id)
+            && hir_id == impl_self_ty.hir_id
+        {
+            let Some(of_trait) = of_trait else {
+                diag.span_suggestion_verbose(
+                    impl_self_ty.span.shrink_to_hi(),
+                    "you might have intended to implement this trait for a given type",
+                    format!(" for /* Type */"),
+                    Applicability::HasPlaceholders,
+                );
+                return;
+            };
+            if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
+                return;
+            }
+            let of_trait_span = of_trait.trait_ref.path.span;
+            // make sure that we are not calling unwrap to abort during the compilation
+            let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else {
+                return;
+            };
+
+            let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(span) else {
+                return;
+            };
+            let sugg = self.add_generic_param_suggestion(generics, span, &impl_trait_name);
+            diag.multipart_suggestion(
+                format!(
+                    "alternatively use a blanket implementation to implement `{of_trait_name}` for \
+                     all types that also implement `{impl_trait_name}`"
+                ),
+                sugg,
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
+    /// Try our best to approximate when adding `dyn` would be helpful for a bare
+    /// trait object.
+    ///
+    /// Right now, this is if the type is either directly nested in another ty,
+    /// or if it's in the tail field within a struct. This approximates what the
+    /// user would've gotten on edition 2015, except for the case where we have
+    /// an *obvious* knock-on `Sized` error.
+    fn maybe_suggest_dyn_trait(
+        &self,
+        hir_id: hir::HirId,
+        sugg: Vec<(Span, String)>,
+        diag: &mut Diag<'_>,
+    ) -> bool {
+        let tcx = self.tcx();
+
+        // Look at the direct HIR parent, since we care about the relationship between
+        // the type and the thing that directly encloses it.
+        match tcx.parent_hir_node(hir_id) {
+            // These are all generally ok. Namely, when a trait object is nested
+            // into another expression or ty, it's either very certain that they
+            // missed the ty (e.g. `&Trait`) or it's not really possible to tell
+            // what their intention is, so let's not give confusing suggestions and
+            // just mention `dyn`. The user can make up their mind what to do here.
+            hir::Node::Ty(_)
+            | hir::Node::Expr(_)
+            | hir::Node::PatExpr(_)
+            | hir::Node::PathSegment(_)
+            | hir::Node::AssocItemConstraint(_)
+            | hir::Node::TraitRef(_)
+            | hir::Node::Item(_)
+            | hir::Node::WherePredicate(_) => {}
+
+            hir::Node::Field(field) => {
+                // Enums can't have unsized fields, fields can only have an unsized tail field.
+                if let hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Struct(_, _, variant), ..
+                }) = tcx.parent_hir_node(field.hir_id)
+                    && variant
+                        .fields()
+                        .last()
+                        .is_some_and(|tail_field| tail_field.hir_id == field.hir_id)
+                {
+                    // Ok
+                } else {
+                    return false;
+                }
+            }
+            _ => return false,
+        }
+
+        // FIXME: Only emit this suggestion if the trait is dyn-compatible.
+        diag.multipart_suggestion_verbose(
+            "you can add the `dyn` keyword if you want a trait object",
+            sugg,
+            Applicability::MachineApplicable,
+        );
+        true
+    }
+
+    fn add_generic_param_suggestion(
+        &self,
+        generics: &hir::Generics<'_>,
+        self_ty_span: Span,
+        impl_trait_name: &str,
+    ) -> Vec<(Span, String)> {
+        // check if the trait has generics, to make a correct suggestion
+        let param_name = generics.params.next_type_param_name(None);
+
+        let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
+            (span, format!(", {param_name}: {impl_trait_name}"))
+        } else {
+            (generics.span, format!("<{param_name}: {impl_trait_name}>"))
+        };
+        vec![(self_ty_span, param_name), add_generic_sugg]
+    }
+
+    /// Make sure that we are in the condition to suggest `impl Trait`.
+    fn maybe_suggest_impl_trait(
+        &self,
+        span: Span,
+        hir_id: hir::HirId,
+        hir_bounds: &[hir::PolyTraitRef<'tcx>],
+        diag: &mut Diag<'_>,
+    ) -> bool {
+        let tcx = self.tcx();
+        let parent_id = tcx.hir_get_parent_item(hir_id).def_id;
+        // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
+        //        and suggest `Trait0<Ty = impl Trait1>`.
+        // Functions are found in three different contexts.
+        // 1. Independent functions
+        // 2. Functions inside trait blocks
+        // 3. Functions inside impl blocks
+        let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) {
+            hir::Node::Item(hir::Item {
+                kind: hir::ItemKind::Fn { sig, generics, .. }, ..
+            }) => (sig, generics),
+            hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(sig, _),
+                generics,
+                ..
+            }) => (sig, generics),
+            hir::Node::ImplItem(hir::ImplItem {
+                kind: hir::ImplItemKind::Fn(sig, _),
+                generics,
+                ..
+            }) => (sig, generics),
+            _ => return false,
+        };
+        let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(span) else {
+            return false;
+        };
+        let impl_sugg = vec![(span.shrink_to_lo(), "impl ".to_string())];
+        // Check if trait object is safe for suggesting dynamic dispatch.
+        let is_dyn_compatible = hir_bounds.iter().all(|bound| match bound.trait_ref.path.res {
+            Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id),
+            _ => false,
+        });
+
+        let borrowed = matches!(
+            tcx.parent_hir_node(hir_id),
+            hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. })
+        );
+
+        // Suggestions for function return type.
+        if let hir::FnRetTy::Return(ty) = sig.decl.output
+            && ty.peel_refs().hir_id == hir_id
+        {
+            let pre = if !is_dyn_compatible {
+                format!("`{trait_name}` is dyn-incompatible, ")
+            } else {
+                String::new()
+            };
+            let msg = format!(
+                "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \
+                 single underlying type",
+            );
+
+            diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable);
+
+            // Suggest `Box<dyn Trait>` for return type
+            if is_dyn_compatible {
+                // If the return type is `&Trait`, we don't want
+                // the ampersand to be displayed in the `Box<dyn Trait>`
+                // suggestion.
+                let suggestion = if borrowed {
+                    vec![(ty.span, format!("Box<dyn {trait_name}>"))]
+                } else {
+                    vec![
+                        (ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
+                        (ty.span.shrink_to_hi(), ">".to_string()),
+                    ]
+                };
+
+                diag.multipart_suggestion_verbose(
+                    "alternatively, you can return an owned trait object",
+                    suggestion,
+                    Applicability::MachineApplicable,
+                );
+            }
+            return true;
+        }
+
+        // Suggestions for function parameters.
+        for ty in sig.decl.inputs {
+            if ty.peel_refs().hir_id != hir_id {
+                continue;
+            }
+            let sugg = self.add_generic_param_suggestion(generics, span, &trait_name);
+            diag.multipart_suggestion_verbose(
+                format!("use a new generic type parameter, constrained by `{trait_name}`"),
+                sugg,
+                Applicability::MachineApplicable,
+            );
+            diag.multipart_suggestion_verbose(
+                "you can also use an opaque type, but users won't be able to specify the type \
+                 parameter when calling the `fn`, having to rely exclusively on type inference",
+                impl_sugg,
+                Applicability::MachineApplicable,
+            );
+            if !is_dyn_compatible {
+                diag.note(format!(
+                    "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used"
+                ));
+            } else {
+                // No ampersand in suggestion if it's borrowed already
+                let (dyn_str, paren_dyn_str) =
+                    if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") };
+
+                let sugg = if let [_, _, ..] = hir_bounds {
+                    // There is more than one trait bound, we need surrounding parentheses.
+                    vec![
+                        (span.shrink_to_lo(), paren_dyn_str.to_string()),
+                        (span.shrink_to_hi(), ")".to_string()),
+                    ]
+                } else {
+                    vec![(span.shrink_to_lo(), dyn_str.to_string())]
+                };
+                diag.multipart_suggestion_verbose(
+                    format!(
+                        "alternatively, use a trait object to accept any type that implements \
+                         `{trait_name}`, accessing its methods at runtime using dynamic dispatch",
+                    ),
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
+            }
+            return true;
+        }
+        false
+    }
+
+    fn maybe_suggest_assoc_ty_bound(&self, hir_id: hir::HirId, diag: &mut Diag<'_>) {
+        let mut parents = self.tcx().hir_parent_iter(hir_id);
+
+        if let Some((c_hir_id, hir::Node::AssocItemConstraint(constraint))) = parents.next()
+            && let Some(obj_ty) = constraint.ty()
+            && let Some((_, hir::Node::TraitRef(trait_ref))) = parents.next()
+        {
+            if let Some((_, hir::Node::Ty(ty))) = parents.next()
+                && let hir::TyKind::TraitObject(..) = ty.kind
+            {
+                // Assoc ty bounds aren't permitted inside trait object types.
+                return;
+            }
+
+            if trait_ref
+                .path
+                .segments
+                .iter()
+                .find_map(|seg| {
+                    seg.args.filter(|args| args.constraints.iter().any(|c| c.hir_id == c_hir_id))
+                })
+                .is_none_or(|args| args.parenthesized != hir::GenericArgsParentheses::No)
+            {
+                // Only consider angle-bracketed args (where we have a `=` to replace with `:`).
+                return;
+            }
+
+            let lo = if constraint.gen_args.span_ext.is_dummy() {
+                constraint.ident.span
+            } else {
+                constraint.gen_args.span_ext
+            };
+            let hi = obj_ty.span;
+
+            if !lo.eq_ctxt(hi) {
+                return;
+            }
+
+            diag.span_suggestion_verbose(
+                lo.between(hi),
+                "you might have meant to write a bound here",
+                ": ",
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
+    fn maybe_suggest_typoed_method(
+        &self,
+        hir_id: hir::HirId,
+        trait_def_id: Option<DefId>,
+        diag: &mut Diag<'_>,
+    ) {
+        let tcx = self.tcx();
+        let Some(trait_def_id) = trait_def_id else {
+            return;
+        };
+        let hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)),
+            ..
+        }) = tcx.parent_hir_node(hir_id)
+        else {
+            return;
+        };
+        if path_ty.hir_id != hir_id {
+            return;
+        }
+        let names: Vec<_> = tcx
+            .associated_items(trait_def_id)
+            .in_definition_order()
+            .filter(|assoc| assoc.namespace() == hir::def::Namespace::ValueNS)
+            .map(|cand| cand.name())
+            .collect();
+        if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
+            diag.span_suggestion_verbose(
+                segment.ident.span,
+                format!(
+                    "you may have misspelled this associated item, causing `{}` \
+                    to be interpreted as a type rather than a trait",
+                    tcx.item_name(trait_def_id),
+                ),
+                typo,
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
 }
 
 fn replace_dummy_self_with_error<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 0cf9cb7193f..16505174464 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -859,7 +859,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)
                 }
                 // Point at the trait object that couldn't satisfy the bound.
-                ty::Dynamic(preds, _, _) => {
+                ty::Dynamic(preds, _) => {
                     for pred in preds.iter() {
                         match pred.skip_binder() {
                             ty::ExistentialPredicate::Trait(tr) => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
deleted file mode 100644
index 56998b5b53c..00000000000
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ /dev/null
@@ -1,533 +0,0 @@
-use rustc_ast::TraitObjectSyntax;
-use rustc_errors::codes::*;
-use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions};
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::DefId;
-use rustc_lint_defs::Applicability;
-use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS;
-use rustc_span::Span;
-use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
-
-use super::HirTyLowerer;
-
-impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
-    /// Prohibit or lint against *bare* trait object types depending on the edition.
-    ///
-    /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
-    /// In edition 2021 and onward we emit a hard error for them.
-    pub(super) fn prohibit_or_lint_bare_trait_object_ty(
-        &self,
-        self_ty: &hir::Ty<'_>,
-    ) -> Option<ErrorGuaranteed> {
-        let tcx = self.tcx();
-
-        let poly_trait_ref = if let hir::TyKind::TraitObject([poly_trait_ref, ..], tagged_ptr) =
-            self_ty.kind
-            && let TraitObjectSyntax::None = tagged_ptr.tag()
-        {
-            poly_trait_ref
-        } else {
-            return None;
-        };
-
-        let in_path = match tcx.parent_hir_node(self_ty.hir_id) {
-            hir::Node::Ty(hir::Ty {
-                kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)),
-                ..
-            })
-            | hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)),
-                ..
-            })
-            | hir::Node::PatExpr(hir::PatExpr {
-                kind: hir::PatExprKind::Path(hir::QPath::TypeRelative(qself, _)),
-                ..
-            }) if qself.hir_id == self_ty.hir_id => true,
-            _ => false,
-        };
-        let needs_bracket = in_path
-            && !tcx
-                .sess
-                .source_map()
-                .span_to_prev_source(self_ty.span)
-                .ok()
-                .is_some_and(|s| s.trim_end().ends_with('<'));
-
-        let is_global = poly_trait_ref.trait_ref.path.is_global();
-
-        let mut sugg = vec![(
-            self_ty.span.shrink_to_lo(),
-            format!(
-                "{}dyn {}",
-                if needs_bracket { "<" } else { "" },
-                if is_global { "(" } else { "" },
-            ),
-        )];
-
-        if is_global || needs_bracket {
-            sugg.push((
-                self_ty.span.shrink_to_hi(),
-                format!(
-                    "{}{}",
-                    if is_global { ")" } else { "" },
-                    if needs_bracket { ">" } else { "" },
-                ),
-            ));
-        }
-
-        if self_ty.span.edition().at_least_rust_2021() {
-            let mut diag = rustc_errors::struct_span_code_err!(
-                self.dcx(),
-                self_ty.span,
-                E0782,
-                "{}",
-                "expected a type, found a trait"
-            );
-            if self_ty.span.can_be_used_for_suggestions()
-                && poly_trait_ref.trait_ref.trait_def_id().is_some()
-                && !self.maybe_suggest_impl_trait(self_ty, &mut diag)
-                && !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag)
-            {
-                self.maybe_suggest_add_generic_impl_trait(self_ty, &mut diag);
-            }
-            // Check if the impl trait that we are considering is an impl of a local trait.
-            self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
-            self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
-            self.maybe_suggest_typoed_method(
-                self_ty,
-                poly_trait_ref.trait_ref.trait_def_id(),
-                &mut diag,
-            );
-            // In case there is an associated type with the same name
-            // Add the suggestion to this error
-            if let Some(mut sugg) =
-                self.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion)
-                && let Suggestions::Enabled(ref mut s1) = diag.suggestions
-                && let Suggestions::Enabled(ref mut s2) = sugg.suggestions
-            {
-                s1.append(s2);
-                sugg.cancel();
-            }
-            Some(diag.emit())
-        } else {
-            tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| {
-                lint.primary_message("trait objects without an explicit `dyn` are deprecated");
-                if self_ty.span.can_be_used_for_suggestions() {
-                    lint.multipart_suggestion_verbose(
-                        "if this is a dyn-compatible trait, use `dyn`",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-                self.maybe_suggest_blanket_trait_impl(self_ty, lint);
-            });
-            None
-        }
-    }
-
-    /// For a struct or enum with an invalid bare trait object field, suggest turning
-    /// it into a generic type bound.
-    fn maybe_suggest_add_generic_impl_trait(
-        &self,
-        self_ty: &hir::Ty<'_>,
-        diag: &mut Diag<'_>,
-    ) -> bool {
-        let tcx = self.tcx();
-
-        let parent_hir_id = tcx.parent_hir_id(self_ty.hir_id);
-        let parent_item = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
-
-        let generics = match tcx.hir_node_by_def_id(parent_item) {
-            hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Struct(_, generics, variant),
-                ..
-            }) => {
-                if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) {
-                    return false;
-                }
-                generics
-            }
-            hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics, def), .. }) => {
-                if !def
-                    .variants
-                    .iter()
-                    .flat_map(|variant| variant.data.fields().iter())
-                    .any(|field| field.hir_id == parent_hir_id)
-                {
-                    return false;
-                }
-                generics
-            }
-            _ => return false,
-        };
-
-        let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
-            return false;
-        };
-
-        let param = "TUV"
-            .chars()
-            .map(|c| c.to_string())
-            .chain((0..).map(|i| format!("P{i}")))
-            .find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s))
-            .expect("we definitely can find at least one param name to generate");
-        let mut sugg = vec![(self_ty.span, param.to_string())];
-        if let Some(insertion_span) = generics.span_for_param_suggestion() {
-            sugg.push((insertion_span, format!(", {param}: {}", rendered_ty)));
-        } else {
-            sugg.push((generics.where_clause_span, format!("<{param}: {}>", rendered_ty)));
-        }
-        diag.multipart_suggestion_verbose(
-            "you might be missing a type parameter",
-            sugg,
-            Applicability::MachineApplicable,
-        );
-        true
-    }
-    /// Make sure that we are in the condition to suggest the blanket implementation.
-    fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
-        &self,
-        self_ty: &hir::Ty<'_>,
-        diag: &mut Diag<'_, G>,
-    ) {
-        let tcx = self.tcx();
-        let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
-        if let hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }),
-            ..
-        }) = tcx.hir_node_by_def_id(parent_id)
-            && self_ty.hir_id == impl_self_ty.hir_id
-        {
-            let Some(of_trait) = of_trait else {
-                diag.span_suggestion_verbose(
-                    impl_self_ty.span.shrink_to_hi(),
-                    "you might have intended to implement this trait for a given type",
-                    format!(" for /* Type */"),
-                    Applicability::HasPlaceholders,
-                );
-                return;
-            };
-            if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) {
-                return;
-            }
-            let of_trait_span = of_trait.trait_ref.path.span;
-            // make sure that we are not calling unwrap to abort during the compilation
-            let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else {
-                return;
-            };
-
-            let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(self_ty.span)
-            else {
-                return;
-            };
-            let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &impl_trait_name);
-            diag.multipart_suggestion(
-                format!(
-                    "alternatively use a blanket implementation to implement `{of_trait_name}` for \
-                     all types that also implement `{impl_trait_name}`"
-                ),
-                sugg,
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-
-    /// Try our best to approximate when adding `dyn` would be helpful for a bare
-    /// trait object.
-    ///
-    /// Right now, this is if the type is either directly nested in another ty,
-    /// or if it's in the tail field within a struct. This approximates what the
-    /// user would've gotten on edition 2015, except for the case where we have
-    /// an *obvious* knock-on `Sized` error.
-    fn maybe_suggest_dyn_trait(
-        &self,
-        self_ty: &hir::Ty<'_>,
-        sugg: Vec<(Span, String)>,
-        diag: &mut Diag<'_>,
-    ) -> bool {
-        let tcx = self.tcx();
-
-        // Look at the direct HIR parent, since we care about the relationship between
-        // the type and the thing that directly encloses it.
-        match tcx.parent_hir_node(self_ty.hir_id) {
-            // These are all generally ok. Namely, when a trait object is nested
-            // into another expression or ty, it's either very certain that they
-            // missed the ty (e.g. `&Trait`) or it's not really possible to tell
-            // what their intention is, so let's not give confusing suggestions and
-            // just mention `dyn`. The user can make up their mind what to do here.
-            hir::Node::Ty(_)
-            | hir::Node::Expr(_)
-            | hir::Node::PatExpr(_)
-            | hir::Node::PathSegment(_)
-            | hir::Node::AssocItemConstraint(_)
-            | hir::Node::TraitRef(_)
-            | hir::Node::Item(_)
-            | hir::Node::WherePredicate(_) => {}
-
-            hir::Node::Field(field) => {
-                // Enums can't have unsized fields, fields can only have an unsized tail field.
-                if let hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Struct(_, _, variant), ..
-                }) = tcx.parent_hir_node(field.hir_id)
-                    && variant
-                        .fields()
-                        .last()
-                        .is_some_and(|tail_field| tail_field.hir_id == field.hir_id)
-                {
-                    // Ok
-                } else {
-                    return false;
-                }
-            }
-            _ => return false,
-        }
-
-        // FIXME: Only emit this suggestion if the trait is dyn-compatible.
-        diag.multipart_suggestion_verbose(
-            "you can add the `dyn` keyword if you want a trait object",
-            sugg,
-            Applicability::MachineApplicable,
-        );
-        true
-    }
-
-    fn add_generic_param_suggestion(
-        &self,
-        generics: &hir::Generics<'_>,
-        self_ty_span: Span,
-        impl_trait_name: &str,
-    ) -> Vec<(Span, String)> {
-        // check if the trait has generics, to make a correct suggestion
-        let param_name = generics.params.next_type_param_name(None);
-
-        let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() {
-            (span, format!(", {param_name}: {impl_trait_name}"))
-        } else {
-            (generics.span, format!("<{param_name}: {impl_trait_name}>"))
-        };
-        vec![(self_ty_span, param_name), add_generic_sugg]
-    }
-
-    /// Make sure that we are in the condition to suggest `impl Trait`.
-    fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
-        let tcx = self.tcx();
-        let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
-        // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>`
-        //        and suggest `Trait0<Ty = impl Trait1>`.
-        // Functions are found in three different contexts.
-        // 1. Independent functions
-        // 2. Functions inside trait blocks
-        // 3. Functions inside impl blocks
-        let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) {
-            hir::Node::Item(hir::Item {
-                kind: hir::ItemKind::Fn { sig, generics, .. }, ..
-            }) => (sig, generics),
-            hir::Node::TraitItem(hir::TraitItem {
-                kind: hir::TraitItemKind::Fn(sig, _),
-                generics,
-                ..
-            }) => (sig, generics),
-            hir::Node::ImplItem(hir::ImplItem {
-                kind: hir::ImplItemKind::Fn(sig, _),
-                generics,
-                ..
-            }) => (sig, generics),
-            _ => return false,
-        };
-        let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
-            return false;
-        };
-        let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
-        // Check if trait object is safe for suggesting dynamic dispatch.
-        let is_dyn_compatible = match self_ty.kind {
-            hir::TyKind::TraitObject(objects, ..) => {
-                objects.iter().all(|o| match o.trait_ref.path.res {
-                    Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id),
-                    _ => false,
-                })
-            }
-            _ => false,
-        };
-
-        let borrowed = matches!(
-            tcx.parent_hir_node(self_ty.hir_id),
-            hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. })
-        );
-
-        // Suggestions for function return type.
-        if let hir::FnRetTy::Return(ty) = sig.decl.output
-            && ty.peel_refs().hir_id == self_ty.hir_id
-        {
-            let pre = if !is_dyn_compatible {
-                format!("`{trait_name}` is dyn-incompatible, ")
-            } else {
-                String::new()
-            };
-            let msg = format!(
-                "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \
-                 single underlying type",
-            );
-
-            diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable);
-
-            // Suggest `Box<dyn Trait>` for return type
-            if is_dyn_compatible {
-                // If the return type is `&Trait`, we don't want
-                // the ampersand to be displayed in the `Box<dyn Trait>`
-                // suggestion.
-                let suggestion = if borrowed {
-                    vec![(ty.span, format!("Box<dyn {trait_name}>"))]
-                } else {
-                    vec![
-                        (ty.span.shrink_to_lo(), "Box<dyn ".to_string()),
-                        (ty.span.shrink_to_hi(), ">".to_string()),
-                    ]
-                };
-
-                diag.multipart_suggestion_verbose(
-                    "alternatively, you can return an owned trait object",
-                    suggestion,
-                    Applicability::MachineApplicable,
-                );
-            }
-            return true;
-        }
-
-        // Suggestions for function parameters.
-        for ty in sig.decl.inputs {
-            if ty.peel_refs().hir_id != self_ty.hir_id {
-                continue;
-            }
-            let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name);
-            diag.multipart_suggestion_verbose(
-                format!("use a new generic type parameter, constrained by `{trait_name}`"),
-                sugg,
-                Applicability::MachineApplicable,
-            );
-            diag.multipart_suggestion_verbose(
-                "you can also use an opaque type, but users won't be able to specify the type \
-                 parameter when calling the `fn`, having to rely exclusively on type inference",
-                impl_sugg,
-                Applicability::MachineApplicable,
-            );
-            if !is_dyn_compatible {
-                diag.note(format!(
-                    "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used"
-                ));
-            } else {
-                // No ampersand in suggestion if it's borrowed already
-                let (dyn_str, paren_dyn_str) =
-                    if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") };
-
-                let sugg = if let hir::TyKind::TraitObject([_, _, ..], _) = self_ty.kind {
-                    // There is more than one trait bound, we need surrounding parentheses.
-                    vec![
-                        (self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()),
-                        (self_ty.span.shrink_to_hi(), ")".to_string()),
-                    ]
-                } else {
-                    vec![(self_ty.span.shrink_to_lo(), dyn_str.to_string())]
-                };
-                diag.multipart_suggestion_verbose(
-                    format!(
-                        "alternatively, use a trait object to accept any type that implements \
-                         `{trait_name}`, accessing its methods at runtime using dynamic dispatch",
-                    ),
-                    sugg,
-                    Applicability::MachineApplicable,
-                );
-            }
-            return true;
-        }
-        false
-    }
-
-    fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) {
-        let mut parents = self.tcx().hir_parent_iter(self_ty.hir_id);
-
-        if let Some((c_hir_id, hir::Node::AssocItemConstraint(constraint))) = parents.next()
-            && let Some(obj_ty) = constraint.ty()
-            && let Some((_, hir::Node::TraitRef(trait_ref))) = parents.next()
-        {
-            if let Some((_, hir::Node::Ty(ty))) = parents.next()
-                && let hir::TyKind::TraitObject(..) = ty.kind
-            {
-                // Assoc ty bounds aren't permitted inside trait object types.
-                return;
-            }
-
-            if trait_ref
-                .path
-                .segments
-                .iter()
-                .find_map(|seg| {
-                    seg.args.filter(|args| args.constraints.iter().any(|c| c.hir_id == c_hir_id))
-                })
-                .is_none_or(|args| args.parenthesized != hir::GenericArgsParentheses::No)
-            {
-                // Only consider angle-bracketed args (where we have a `=` to replace with `:`).
-                return;
-            }
-
-            let lo = if constraint.gen_args.span_ext.is_dummy() {
-                constraint.ident.span
-            } else {
-                constraint.gen_args.span_ext
-            };
-            let hi = obj_ty.span;
-
-            if !lo.eq_ctxt(hi) {
-                return;
-            }
-
-            diag.span_suggestion_verbose(
-                lo.between(hi),
-                "you might have meant to write a bound here",
-                ": ",
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-
-    fn maybe_suggest_typoed_method(
-        &self,
-        self_ty: &hir::Ty<'_>,
-        trait_def_id: Option<DefId>,
-        diag: &mut Diag<'_>,
-    ) {
-        let tcx = self.tcx();
-        let Some(trait_def_id) = trait_def_id else {
-            return;
-        };
-        let hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)),
-            ..
-        }) = tcx.parent_hir_node(self_ty.hir_id)
-        else {
-            return;
-        };
-        if path_ty.hir_id != self_ty.hir_id {
-            return;
-        }
-        let names: Vec<_> = tcx
-            .associated_items(trait_def_id)
-            .in_definition_order()
-            .filter(|assoc| assoc.namespace() == Namespace::ValueNS)
-            .map(|cand| cand.name())
-            .collect();
-        if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) {
-            diag.span_suggestion_verbose(
-                segment.ident.span,
-                format!(
-                    "you may have misspelled this associated item, causing `{}` \
-                    to be interpreted as a type rather than a trait",
-                    tcx.item_name(trait_def_id),
-                ),
-                typo,
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-}
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 c5e079fe89a..9b198d04454 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -15,15 +15,13 @@
 
 mod bounds;
 mod cmse;
-mod dyn_compatibility;
+mod dyn_trait;
 pub mod errors;
 pub mod generics;
-mod lint;
 
 use std::assert_matches::assert_matches;
 use std::slice;
 
-use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::{
@@ -2428,19 +2426,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             ),
             hir::TyKind::TraitObject(bounds, tagged_ptr) => {
                 let lifetime = tagged_ptr.pointer();
-                let repr = tagged_ptr.tag();
-
-                if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) {
-                    // Don't continue with type analysis if the `dyn` keyword is missing
-                    // It generates confusing errors, especially if the user meant to use another
-                    // keyword like `impl`
-                    Ty::new_error(tcx, guar)
-                } else {
-                    let repr = match repr {
-                        TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
-                    };
-                    self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
-                }
+                let syntax = tagged_ptr.tag();
+                self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, syntax)
             }
             // 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
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 960ec7f66ab..be841675821 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -281,7 +281,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_args(current, data.def_id, data.args, variance);
             }
 
-            ty::Dynamic(data, r, _) => {
+            ty::Dynamic(data, r) => {
                 // The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
                 self.add_constraints_from_region(current, r, variance);