about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs406
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs408
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs10
7 files changed, 454 insertions, 411 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 89677141f38..a6ee7215617 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -386,11 +386,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                                 .type_of(param.def_id)
                                 .no_bound_vars()
                                 .expect("ct params cannot have early bound vars");
-                            tcx.mk_const(
-                                ty::ConstKind::Bound(
-                                    ty::INNERMOST,
-                                    ty::BoundVar::from_usize(num_bound_vars),
-                                ),
+                            ty::Const::new_bound(
+                                tcx,
+                                ty::INNERMOST,
+                                ty::BoundVar::from_usize(num_bound_vars),
                                 ty,
                             )
                             .into()
@@ -529,13 +528,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                         let reported = err.emit();
                         term = match def_kind {
                             hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
-                            hir::def::DefKind::AssocConst => tcx
-                                .const_error(
-                                    tcx.type_of(assoc_item_def_id)
-                                        .subst(tcx, projection_ty.skip_binder().substs),
-                                    reported,
-                                )
-                                .into(),
+                            hir::def::DefKind::AssocConst => ty::Const::new_error(
+                                tcx,
+                                reported,
+                                tcx.type_of(assoc_item_def_id)
+                                    .subst(tcx, projection_ty.skip_binder().substs),
+                            )
+                            .into(),
                             _ => unreachable!(),
                         };
                     }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 1d5e4ac55f8..a6503e032c7 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -6,14 +6,13 @@ mod bounds;
 mod errors;
 pub mod generics;
 mod lint;
+mod object_safety;
 
 use crate::astconv::errors::prohibit_assoc_ty_binding;
 use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
 use crate::bounds::Bounds;
 use crate::collect::HirPlaceholderCollector;
-use crate::errors::{
-    AmbiguousLifetimeBound, TraitObjectDeclaredWithNoTraits, TypeofReservedKeywordUsed,
-};
+use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed};
 use crate::middle::resolve_bound_vars as rbv;
 use crate::require_c_abi_if_c_variadic;
 use rustc_ast::TraitObjectSyntax;
@@ -31,24 +30,17 @@ use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc_middle::ty::DynKind;
 use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi;
-use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 use rustc_trait_selection::traits::wf::object_region_bounds;
-use rustc_trait_selection::traits::{
-    self, astconv_object_safety_violations, NormalizeExt, ObligationCtxt,
-};
+use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt};
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 
-use smallvec::{smallvec, SmallVec};
-use std::collections::BTreeSet;
 use std::fmt::Display;
 use std::slice;
 
@@ -482,7 +474,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             self.astconv.ct_infer(ty, Some(param), inf.span).into()
                         } else {
                             self.inferred_params.push(inf.span);
-                            tcx.const_error_misc(ty).into()
+                            ty::Const::new_misc_error(tcx, ty).into()
                         }
                     }
                     _ => unreachable!(),
@@ -537,7 +529,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             .no_bound_vars()
                             .expect("const parameter types cannot be generic");
                         if let Err(guar) = ty.error_reported() {
-                            return tcx.const_error(ty, guar).into();
+                            return ty::Const::new_error(tcx, guar, ty).into();
                         }
                         if !infer_args && has_default {
                             tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
@@ -546,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 self.astconv.ct_infer(ty, Some(param), self.span).into()
                             } else {
                                 // We've already errored above about the mismatch.
-                                tcx.const_error_misc(ty).into()
+                                ty::Const::new_misc_error(tcx, ty).into()
                             }
                         }
                     }
@@ -926,380 +918,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         }
     }
 
-    fn conv_object_ty_poly_trait_ref(
-        &self,
-        span: Span,
-        hir_trait_bounds: &[hir::PolyTraitRef<'_>],
-        lifetime: &hir::Lifetime,
-        borrowed: bool,
-        representation: DynKind,
-    ) -> Ty<'tcx> {
-        let tcx = self.tcx();
-
-        let mut bounds = Bounds::default();
-        let mut potential_assoc_types = Vec::new();
-        let dummy_self = self.tcx().types.trait_object_dummy_self;
-        for trait_bound in hir_trait_bounds.iter().rev() {
-            if let GenericArgCountResult {
-                correct:
-                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
-                ..
-            } = self.instantiate_poly_trait_ref(
-                &trait_bound.trait_ref,
-                trait_bound.span,
-                ty::BoundConstness::NotConst,
-                ty::ImplPolarity::Positive,
-                dummy_self,
-                &mut bounds,
-                false,
-                // FIXME: This should be `true`, but we don't really handle
-                // associated type bounds or type aliases in objects in a way
-                // that makes this meaningful, I think.
-                OnlySelfBounds(false),
-            ) {
-                potential_assoc_types.extend(cur_potential_assoc_types);
-            }
-        }
-
-        let mut trait_bounds = vec![];
-        let mut projection_bounds = vec![];
-        for (pred, span) in bounds.clauses() {
-            let bound_pred = pred.kind();
-            match bound_pred.skip_binder() {
-                ty::ClauseKind::Trait(trait_pred) => {
-                    assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
-                    trait_bounds.push((
-                        bound_pred.rebind(trait_pred.trait_ref),
-                        span,
-                        trait_pred.constness,
-                    ));
-                }
-                ty::ClauseKind::Projection(proj) => {
-                    projection_bounds.push((bound_pred.rebind(proj), span));
-                }
-                ty::ClauseKind::TypeOutlives(_) => {
-                    // Do nothing, we deal with regions separately
-                }
-                ty::ClauseKind::RegionOutlives(_)
-                | ty::ClauseKind::ConstArgHasType(..)
-                | ty::ClauseKind::WellFormed(_)
-                | ty::ClauseKind::ConstEvaluatable(_) => {
-                    bug!()
-                }
-            }
-        }
-
-        // Expand trait aliases recursively and check that only one regular (non-auto) trait
-        // is used and no 'maybe' bounds are used.
-        let expanded_traits =
-            traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b)));
-
-        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
-            .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
-            .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
-        if regular_traits.len() > 1 {
-            let first_trait = &regular_traits[0];
-            let additional_trait = &regular_traits[1];
-            let mut err = struct_span_err!(
-                tcx.sess,
-                additional_trait.bottom().1,
-                E0225,
-                "only auto traits can be used as additional traits in a trait object"
-            );
-            additional_trait.label_with_exp_info(
-                &mut err,
-                "additional non-auto trait",
-                "additional use",
-            );
-            first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
-            err.help(format!(
-                "consider creating a new trait with all of these as supertraits and using that \
-                 trait here instead: `trait NewTrait: {} {{}}`",
-                regular_traits
-                    .iter()
-                    .map(|t| t.trait_ref().print_only_trait_path().to_string())
-                    .collect::<Vec<_>>()
-                    .join(" + "),
-            ));
-            err.note(
-                "auto-traits like `Send` and `Sync` are traits that have special properties; \
-                 for more information on them, visit \
-                 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
-            );
-            err.emit();
-        }
-
-        if regular_traits.is_empty() && auto_traits.is_empty() {
-            let trait_alias_span = trait_bounds
-                .iter()
-                .map(|&(trait_ref, _, _)| trait_ref.def_id())
-                .find(|&trait_ref| tcx.is_trait_alias(trait_ref))
-                .map(|trait_ref| tcx.def_span(trait_ref));
-            let reported =
-                tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
-            return tcx.ty_error(reported);
-        }
-
-        // Check that there are no gross object safety violations;
-        // most importantly, that the supertraits don't contain `Self`,
-        // to avoid ICEs.
-        for item in &regular_traits {
-            let object_safety_violations =
-                astconv_object_safety_violations(tcx, item.trait_ref().def_id());
-            if !object_safety_violations.is_empty() {
-                let reported = report_object_safety_error(
-                    tcx,
-                    span,
-                    item.trait_ref().def_id(),
-                    &object_safety_violations,
-                )
-                .emit();
-                return tcx.ty_error(reported);
-            }
-        }
-
-        // Use a `BTreeSet` to keep output in a more consistent order.
-        let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
-
-        let regular_traits_refs_spans = trait_bounds
-            .into_iter()
-            .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
-
-        for (base_trait_ref, span, constness) in regular_traits_refs_spans {
-            assert_eq!(constness, ty::BoundConstness::NotConst);
-            let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
-            for pred in traits::elaborate(tcx, [base_pred]) {
-                debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
-
-                let bound_predicate = pred.kind();
-                match bound_predicate.skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
-                        let pred = bound_predicate.rebind(pred);
-                        associated_types.entry(span).or_default().extend(
-                            tcx.associated_items(pred.def_id())
-                                .in_definition_order()
-                                .filter(|item| item.kind == ty::AssocKind::Type)
-                                .filter(|item| item.opt_rpitit_info.is_none())
-                                .map(|item| item.def_id),
-                        );
-                    }
-                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
-                        let pred = bound_predicate.rebind(pred);
-                        // A `Self` within the original bound will be substituted with a
-                        // `trait_object_dummy_self`, so check for that.
-                        let references_self = match pred.skip_binder().term.unpack() {
-                            ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
-                            ty::TermKind::Const(c) => {
-                                c.ty().walk().any(|arg| arg == dummy_self.into())
-                            }
-                        };
-
-                        // If the projection output contains `Self`, force the user to
-                        // elaborate it explicitly to avoid a lot of complexity.
-                        //
-                        // The "classically useful" case is the following:
-                        // ```
-                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
-                        //         type MyOutput;
-                        //     }
-                        // ```
-                        //
-                        // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
-                        // but actually supporting that would "expand" to an infinitely-long type
-                        // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
-                        //
-                        // Instead, we force the user to write
-                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
-                        // the discussion in #56288 for alternatives.
-                        if !references_self {
-                            // Include projections defined on supertraits.
-                            projection_bounds.push((pred, span));
-                        }
-                    }
-                    _ => (),
-                }
-            }
-        }
-
-        // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where <Self as Trait>::Assoc = Foo`.
-        // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
-        // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
-        // corresponding `Projection` clause
-        for (projection_bound, _) in &projection_bounds {
-            for def_ids in associated_types.values_mut() {
-                def_ids.remove(&projection_bound.projection_def_id());
-            }
-        }
-
-        self.complain_about_missing_associated_types(
-            associated_types,
-            potential_assoc_types,
-            hir_trait_bounds,
-        );
-
-        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
-        // `dyn Trait + Send`.
-        // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
-        // the bounds
-        let mut duplicates = FxHashSet::default();
-        auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id()));
-        debug!("regular_traits: {:?}", regular_traits);
-        debug!("auto_traits: {:?}", auto_traits);
-
-        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
-        let existential_trait_refs = regular_traits.iter().map(|i| {
-            i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| {
-                assert_eq!(trait_ref.self_ty(), dummy_self);
-
-                // Verify that `dummy_self` did not leak inside default type parameters. This
-                // could not be done at path creation, since we need to see through trait aliases.
-                let mut missing_type_params = vec![];
-                let mut references_self = false;
-                let generics = tcx.generics_of(trait_ref.def_id);
-                let substs: Vec<_> = trait_ref
-                    .substs
-                    .iter()
-                    .enumerate()
-                    .skip(1) // Remove `Self` for `ExistentialPredicate`.
-                    .map(|(index, arg)| {
-                        if arg == dummy_self.into() {
-                            let param = &generics.params[index];
-                            missing_type_params.push(param.name);
-                            return tcx.ty_error_misc().into();
-                        } else if arg.walk().any(|arg| arg == dummy_self.into()) {
-                            references_self = true;
-                            return tcx.ty_error_misc().into();
-                        }
-                        arg
-                    })
-                    .collect();
-                let substs = tcx.mk_substs(&substs);
-
-                let span = i.bottom().1;
-                let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
-                    hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
-                        && hir_bound.span.contains(span)
-                });
-                self.complain_about_missing_type_params(
-                    missing_type_params,
-                    trait_ref.def_id,
-                    span,
-                    empty_generic_args,
-                );
-
-                if references_self {
-                    let def_id = i.bottom().0.def_id();
-                    let mut err = struct_span_err!(
-                        tcx.sess,
-                        i.bottom().1,
-                        E0038,
-                        "the {} `{}` cannot be made into an object",
-                        tcx.def_descr(def_id),
-                        tcx.item_name(def_id),
-                    );
-                    err.note(
-                        rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
-                            .error_msg(),
-                    );
-                    err.emit();
-                }
-
-                ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
-            })
-        });
-
-        let existential_projections = projection_bounds
-            .iter()
-            // We filter out traits that don't have `Self` as their self type above,
-            // we need to do the same for projections.
-            .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
-            .map(|(bound, _)| {
-                bound.map_bound(|mut b| {
-                    assert_eq!(b.projection_ty.self_ty(), dummy_self);
-
-                    // Like for trait refs, verify that `dummy_self` did not leak inside default type
-                    // parameters.
-                    let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
-                        if arg.walk().any(|arg| arg == dummy_self.into()) {
-                            return true;
-                        }
-                        false
-                    });
-                    if references_self {
-                        let guar = tcx.sess.delay_span_bug(
-                            span,
-                            "trait object projection bounds reference `Self`",
-                        );
-                        let substs: Vec<_> = b
-                            .projection_ty
-                            .substs
-                            .iter()
-                            .map(|arg| {
-                                if arg.walk().any(|arg| arg == dummy_self.into()) {
-                                    return tcx.ty_error(guar).into();
-                                }
-                                arg
-                            })
-                            .collect();
-                        b.projection_ty.substs = tcx.mk_substs(&substs);
-                    }
-
-                    ty::ExistentialProjection::erase_self_ty(tcx, b)
-                })
-            });
-
-        let regular_trait_predicates = existential_trait_refs
-            .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
-        let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
-            ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
-        });
-        // N.b. principal, projections, auto traits
-        // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
-        let mut v = regular_trait_predicates
-            .chain(
-                existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)),
-            )
-            .chain(auto_trait_predicates)
-            .collect::<SmallVec<[_; 8]>>();
-        v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
-        v.dedup();
-        let existential_predicates = tcx.mk_poly_existential_predicates(&v);
-
-        // Use explicitly-specified region bound.
-        let region_bound = if !lifetime.is_elided() {
-            self.ast_region_to_region(lifetime, None)
-        } else {
-            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
-                if tcx.named_bound_var(lifetime.hir_id).is_some() {
-                    self.ast_region_to_region(lifetime, None)
-                } else {
-                    self.re_infer(None, span).unwrap_or_else(|| {
-                        let mut err = struct_span_err!(
-                            tcx.sess,
-                            span,
-                            E0228,
-                            "the lifetime bound for this object type cannot be deduced \
-                             from context; please supply an explicit bound"
-                        );
-                        let e = if borrowed {
-                            // We will have already emitted an error E0106 complaining about a
-                            // missing named lifetime in `&dyn Trait`, so we elide this one.
-                            err.delay_as_bug()
-                        } else {
-                            err.emit()
-                        };
-                        ty::Region::new_error(tcx, e)
-                    })
-                }
-            })
-        };
-        debug!("region_bound: {:?}", region_bound);
-
-        let ty = tcx.mk_dynamic(existential_predicates, region_bound, representation);
-        debug!("trait_object_type: {:?}", ty);
-        ty
-    }
-
     fn report_ambiguous_associated_type(
         &self,
         span: Span,
@@ -1970,7 +1588,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     assert!(!ct.ty().has_escaping_bound_vars());
 
                     match ct.kind() {
-                        ty::ConstKind::Bound(_, bv) => self.tcx.mk_const(
+                        ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder(
+                            self.tcx,
                             ty::PlaceholderConst { universe: self.universe, bound: bv },
                             ct.ty(),
                         ),
@@ -2801,7 +2420,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     TraitObjectSyntax::DynStar => ty::DynStar,
                 };
 
-                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr)
+                self.conv_object_ty_poly_trait_ref(
+                    ast_ty.span,
+                    ast_ty.hir_id,
+                    bounds,
+                    lifetime,
+                    borrowed,
+                    repr,
+                )
             }
             hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
                 debug!(?maybe_qself, ?path);
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
new file mode 100644
index 00000000000..918724e0477
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -0,0 +1,408 @@
+use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
+use crate::bounds::Bounds;
+use crate::errors::TraitObjectDeclaredWithNoTraits;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
+use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{DynKind, ToPredicate};
+use rustc_span::Span;
+use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
+use rustc_trait_selection::traits::{self, astconv_object_safety_violations};
+
+use smallvec::{smallvec, SmallVec};
+use std::collections::BTreeSet;
+
+use super::AstConv;
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+    pub(super) fn conv_object_ty_poly_trait_ref(
+        &self,
+        span: Span,
+        hir_id: hir::HirId,
+        hir_trait_bounds: &[hir::PolyTraitRef<'_>],
+        lifetime: &hir::Lifetime,
+        borrowed: bool,
+        representation: DynKind,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+
+        let mut bounds = Bounds::default();
+        let mut potential_assoc_types = Vec::new();
+        let dummy_self = self.tcx().types.trait_object_dummy_self;
+        for trait_bound in hir_trait_bounds.iter().rev() {
+            if let GenericArgCountResult {
+                correct:
+                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
+                ..
+            } = self.instantiate_poly_trait_ref(
+                &trait_bound.trait_ref,
+                trait_bound.span,
+                ty::BoundConstness::NotConst,
+                ty::ImplPolarity::Positive,
+                dummy_self,
+                &mut bounds,
+                false,
+                // FIXME: This should be `true`, but we don't really handle
+                // associated type bounds or type aliases in objects in a way
+                // that makes this meaningful, I think.
+                OnlySelfBounds(false),
+            ) {
+                potential_assoc_types.extend(cur_potential_assoc_types);
+            }
+        }
+
+        let mut trait_bounds = vec![];
+        let mut projection_bounds = vec![];
+        for (pred, span) in bounds.clauses() {
+            let bound_pred = pred.kind();
+            match bound_pred.skip_binder() {
+                ty::ClauseKind::Trait(trait_pred) => {
+                    assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
+                    trait_bounds.push((
+                        bound_pred.rebind(trait_pred.trait_ref),
+                        span,
+                        trait_pred.constness,
+                    ));
+                }
+                ty::ClauseKind::Projection(proj) => {
+                    projection_bounds.push((bound_pred.rebind(proj), span));
+                }
+                ty::ClauseKind::TypeOutlives(_) => {
+                    // Do nothing, we deal with regions separately
+                }
+                ty::ClauseKind::RegionOutlives(_)
+                | ty::ClauseKind::ConstArgHasType(..)
+                | ty::ClauseKind::WellFormed(_)
+                | ty::ClauseKind::ConstEvaluatable(_) => {
+                    bug!()
+                }
+            }
+        }
+
+        // Expand trait aliases recursively and check that only one regular (non-auto) trait
+        // is used and no 'maybe' bounds are used.
+        let expanded_traits =
+            traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b)));
+
+        let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits
+            .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self)
+            .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
+        if regular_traits.len() > 1 {
+            let first_trait = &regular_traits[0];
+            let additional_trait = &regular_traits[1];
+            let mut err = struct_span_err!(
+                tcx.sess,
+                additional_trait.bottom().1,
+                E0225,
+                "only auto traits can be used as additional traits in a trait object"
+            );
+            additional_trait.label_with_exp_info(
+                &mut err,
+                "additional non-auto trait",
+                "additional use",
+            );
+            first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
+            err.help(format!(
+                "consider creating a new trait with all of these as supertraits and using that \
+             trait here instead: `trait NewTrait: {} {{}}`",
+                regular_traits
+                    .iter()
+                    .map(|t| t.trait_ref().print_only_trait_path().to_string())
+                    .collect::<Vec<_>>()
+                    .join(" + "),
+            ));
+            err.note(
+                "auto-traits like `Send` and `Sync` are traits that have special properties; \
+             for more information on them, visit \
+             <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
+            );
+            err.emit();
+        }
+
+        if regular_traits.is_empty() && auto_traits.is_empty() {
+            let trait_alias_span = trait_bounds
+                .iter()
+                .map(|&(trait_ref, _, _)| trait_ref.def_id())
+                .find(|&trait_ref| tcx.is_trait_alias(trait_ref))
+                .map(|trait_ref| tcx.def_span(trait_ref));
+            let reported =
+                tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
+            return tcx.ty_error(reported);
+        }
+
+        // Check that there are no gross object safety violations;
+        // most importantly, that the supertraits don't contain `Self`,
+        // to avoid ICEs.
+        for item in &regular_traits {
+            let object_safety_violations =
+                astconv_object_safety_violations(tcx, item.trait_ref().def_id());
+            if !object_safety_violations.is_empty() {
+                let reported = report_object_safety_error(
+                    tcx,
+                    span,
+                    item.trait_ref().def_id(),
+                    &object_safety_violations,
+                )
+                .emit();
+                return tcx.ty_error(reported);
+            }
+        }
+
+        // Use a `BTreeSet` to keep output in a more consistent order.
+        let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default();
+
+        let regular_traits_refs_spans = trait_bounds
+            .into_iter()
+            .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
+
+        for (base_trait_ref, span, constness) in regular_traits_refs_spans {
+            assert_eq!(constness, ty::BoundConstness::NotConst);
+            let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx);
+            for pred in traits::elaborate(tcx, [base_pred]) {
+                debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred);
+
+                let bound_predicate = pred.kind();
+                match bound_predicate.skip_binder() {
+                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+                        let pred = bound_predicate.rebind(pred);
+                        associated_types.entry(span).or_default().extend(
+                            tcx.associated_items(pred.def_id())
+                                .in_definition_order()
+                                .filter(|item| item.kind == ty::AssocKind::Type)
+                                .filter(|item| item.opt_rpitit_info.is_none())
+                                .map(|item| item.def_id),
+                        );
+                    }
+                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
+                        let pred = bound_predicate.rebind(pred);
+                        // A `Self` within the original bound will be substituted with a
+                        // `trait_object_dummy_self`, so check for that.
+                        let references_self = match pred.skip_binder().term.unpack() {
+                            ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()),
+                            ty::TermKind::Const(c) => {
+                                c.ty().walk().any(|arg| arg == dummy_self.into())
+                            }
+                        };
+
+                        // If the projection output contains `Self`, force the user to
+                        // elaborate it explicitly to avoid a lot of complexity.
+                        //
+                        // The "classically useful" case is the following:
+                        // ```
+                        //     trait MyTrait: FnMut() -> <Self as MyTrait>::MyOutput {
+                        //         type MyOutput;
+                        //     }
+                        // ```
+                        //
+                        // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
+                        // but actually supporting that would "expand" to an infinitely-long type
+                        // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
+                        //
+                        // Instead, we force the user to write
+                        // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
+                        // the discussion in #56288 for alternatives.
+                        if !references_self {
+                            // Include projections defined on supertraits.
+                            projection_bounds.push((pred, span));
+                        }
+                    }
+                    _ => (),
+                }
+            }
+        }
+
+        // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where <Self as Trait>::Assoc = Foo`.
+        // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
+        // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
+        // corresponding `Projection` clause
+        for def_ids in associated_types.values_mut() {
+            for (projection_bound, span) in &projection_bounds {
+                let def_id = projection_bound.projection_def_id();
+                def_ids.remove(&def_id);
+                if tcx.generics_require_sized_self(def_id) {
+                    tcx.emit_spanned_lint(
+                        UNUSED_ASSOCIATED_TYPE_BOUNDS,
+                        hir_id,
+                        *span,
+                        crate::errors::UnusedAssociatedTypeBounds { span: *span },
+                    );
+                }
+            }
+            // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
+            // type in the `dyn Trait`.
+            def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id));
+        }
+
+        self.complain_about_missing_associated_types(
+            associated_types,
+            potential_assoc_types,
+            hir_trait_bounds,
+        );
+
+        // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
+        // `dyn Trait + Send`.
+        // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering
+        // the bounds
+        let mut duplicates = FxHashSet::default();
+        auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id()));
+        debug!("regular_traits: {:?}", regular_traits);
+        debug!("auto_traits: {:?}", auto_traits);
+
+        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
+        let existential_trait_refs = regular_traits.iter().map(|i| {
+            i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| {
+                assert_eq!(trait_ref.self_ty(), dummy_self);
+
+                // Verify that `dummy_self` did not leak inside default type parameters. This
+                // could not be done at path creation, since we need to see through trait aliases.
+                let mut missing_type_params = vec![];
+                let mut references_self = false;
+                let generics = tcx.generics_of(trait_ref.def_id);
+                let substs: Vec<_> = trait_ref
+                    .substs
+                    .iter()
+                    .enumerate()
+                    .skip(1) // Remove `Self` for `ExistentialPredicate`.
+                    .map(|(index, arg)| {
+                        if arg == dummy_self.into() {
+                            let param = &generics.params[index];
+                            missing_type_params.push(param.name);
+                            return tcx.ty_error_misc().into();
+                        } else if arg.walk().any(|arg| arg == dummy_self.into()) {
+                            references_self = true;
+                            return tcx.ty_error_misc().into();
+                        }
+                        arg
+                    })
+                    .collect();
+                let substs = tcx.mk_substs(&substs);
+
+                let span = i.bottom().1;
+                let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
+                    hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
+                        && hir_bound.span.contains(span)
+                });
+                self.complain_about_missing_type_params(
+                    missing_type_params,
+                    trait_ref.def_id,
+                    span,
+                    empty_generic_args,
+                );
+
+                if references_self {
+                    let def_id = i.bottom().0.def_id();
+                    let mut err = struct_span_err!(
+                        tcx.sess,
+                        i.bottom().1,
+                        E0038,
+                        "the {} `{}` cannot be made into an object",
+                        tcx.def_descr(def_id),
+                        tcx.item_name(def_id),
+                    );
+                    err.note(
+                        rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![])
+                            .error_msg(),
+                    );
+                    err.emit();
+                }
+
+                ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs }
+            })
+        });
+
+        let existential_projections = projection_bounds
+            .iter()
+            // We filter out traits that don't have `Self` as their self type above,
+            // we need to do the same for projections.
+            .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
+            .map(|(bound, _)| {
+                bound.map_bound(|mut b| {
+                    assert_eq!(b.projection_ty.self_ty(), dummy_self);
+
+                    // Like for trait refs, verify that `dummy_self` did not leak inside default type
+                    // parameters.
+                    let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
+                        if arg.walk().any(|arg| arg == dummy_self.into()) {
+                            return true;
+                        }
+                        false
+                    });
+                    if references_self {
+                        let guar = tcx.sess.delay_span_bug(
+                            span,
+                            "trait object projection bounds reference `Self`",
+                        );
+                        let substs: Vec<_> = b
+                            .projection_ty
+                            .substs
+                            .iter()
+                            .map(|arg| {
+                                if arg.walk().any(|arg| arg == dummy_self.into()) {
+                                    return tcx.ty_error(guar).into();
+                                }
+                                arg
+                            })
+                            .collect();
+                        b.projection_ty.substs = tcx.mk_substs(&substs);
+                    }
+
+                    ty::ExistentialProjection::erase_self_ty(tcx, b)
+                })
+            });
+
+        let regular_trait_predicates = existential_trait_refs
+            .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
+        let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
+            ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
+        });
+        // N.b. principal, projections, auto traits
+        // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
+        let mut v = regular_trait_predicates
+            .chain(
+                existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)),
+            )
+            .chain(auto_trait_predicates)
+            .collect::<SmallVec<[_; 8]>>();
+        v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
+        v.dedup();
+        let existential_predicates = tcx.mk_poly_existential_predicates(&v);
+
+        // Use explicitly-specified region bound.
+        let region_bound = if !lifetime.is_elided() {
+            self.ast_region_to_region(lifetime, None)
+        } else {
+            self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
+                if tcx.named_bound_var(lifetime.hir_id).is_some() {
+                    self.ast_region_to_region(lifetime, None)
+                } else {
+                    self.re_infer(None, span).unwrap_or_else(|| {
+                        let mut err = struct_span_err!(
+                            tcx.sess,
+                            span,
+                            E0228,
+                            "the lifetime bound for this object type cannot be deduced \
+                         from context; please supply an explicit bound"
+                        );
+                        let e = if borrowed {
+                            // We will have already emitted an error E0106 complaining about a
+                            // missing named lifetime in `&dyn Trait`, so we elide this one.
+                            err.delay_as_bug()
+                        } else {
+                            err.emit()
+                        };
+                        ty::Region::new_error(tcx, e)
+                    })
+                }
+            })
+        };
+        debug!("region_bound: {:?}", region_bound);
+
+        let ty = tcx.mk_dynamic(existential_predicates, region_bound, representation);
+        debug!("trait_object_type: {:?}", ty);
+        ty
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 3f5164e093d..0fa65eff616 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2047,11 +2047,10 @@ pub(super) fn check_type_bounds<'tcx>(
             GenericParamDefKind::Const { .. } => {
                 let bound_var = ty::BoundVariableKind::Const;
                 bound_vars.push(bound_var);
-                tcx.mk_const(
-                    ty::ConstKind::Bound(
-                        ty::INNERMOST,
-                        ty::BoundVar::from_usize(bound_vars.len() - 1),
-                    ),
+                ty::Const::new_bound(
+                    tcx,
+                    ty::INNERMOST,
+                    ty::BoundVar::from_usize(bound_vars.len() - 1),
                     tcx.type_of(param.def_id)
                         .no_bound_vars()
                         .expect("const parameter types cannot be generic"),
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index d7ac9e7ce73..0339e79a278 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -390,7 +390,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
             // left alone.
             r => bug!("unexpected region: {r:?}"),
         });
-        self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
+        ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant")
     }
 
     fn projected_ty_from_poly_trait_ref(
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 1d00dc2a11d..df2c24a6001 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -243,9 +243,12 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                 let name = param.name.ident().name;
                 let param_const = ty::ParamConst::new(index, name);
 
-                let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity();
+                let ct_ty = tcx
+                    .type_of(param.def_id.to_def_id())
+                    .no_bound_vars()
+                    .expect("const parameters cannot be generic");
 
-                let ct = tcx.mk_const(param_const, ct_ty);
+                let ct = ty::Const::new_param(tcx, param_const, ct_ty);
 
                 predicates.insert((
                     ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index cb840592edd..205e26d0eda 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -5,7 +5,7 @@ use rustc_errors::{
     error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
     MultiSpan,
 };
-use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
@@ -900,3 +900,11 @@ pub(crate) enum LateBoundInApit {
         param_span: Span,
     },
 }
+
+#[derive(LintDiagnostic)]
+#[diag(hir_analysis_unused_associated_type_bounds)]
+#[note]
+pub struct UnusedAssociatedTypeBounds {
+    #[suggestion(code = "")]
+    pub span: Span,
+}