|  | //! Methods for lowering the HIR to types. There are two main cases here: | 
|  | //! | 
|  | //!  - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a | 
|  | //!    type: The entry point for this is `TyLoweringContext::lower_ty`. | 
|  | //!  - Building the type for an item: This happens through the `ty` query. | 
|  | //! | 
|  | //! This usually involves resolving names, collecting generic arguments etc. | 
|  | #![allow(unused)] | 
|  | // FIXME(next-solver): this should get removed as things get moved to rustc_type_ir from chalk_ir | 
|  | pub(crate) mod path; | 
|  |  | 
|  | use std::{ | 
|  | cell::OnceCell, | 
|  | iter, mem, | 
|  | ops::{self, Deref, Not as _}, | 
|  | }; | 
|  |  | 
|  | use base_db::Crate; | 
|  | use either::Either; | 
|  | use hir_def::hir::generics::GenericParamDataRef; | 
|  | use hir_def::item_tree::FieldsShape; | 
|  | use hir_def::{ | 
|  | AdtId, AssocItemId, CallableDefId, ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, | 
|  | GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LocalFieldId, Lookup, | 
|  | StructId, TraitId, TypeAliasId, TypeOrConstParamId, VariantId, | 
|  | expr_store::{ | 
|  | ExpressionStore, | 
|  | path::{GenericArg, Path}, | 
|  | }, | 
|  | hir::generics::{TypeOrConstParamData, WherePredicate}, | 
|  | lang_item::LangItem, | 
|  | resolver::{HasResolver, LifetimeNs, Resolver, TypeNs}, | 
|  | signatures::{FunctionSignature, TraitFlags, TypeAliasFlags}, | 
|  | type_ref::{ | 
|  | ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier, | 
|  | TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId, | 
|  | }, | 
|  | }; | 
|  | use hir_def::{ConstId, LifetimeParamId, StaticId, TypeParamId}; | 
|  | use hir_expand::name::Name; | 
|  | use intern::{Symbol, sym}; | 
|  | use la_arena::{Arena, ArenaMap, Idx}; | 
|  | use path::{PathDiagnosticCallback, PathLoweringContext, builtin}; | 
|  | use rustc_ast_ir::Mutability; | 
|  | use rustc_hash::FxHashSet; | 
|  | use rustc_pattern_analysis::Captures; | 
|  | use rustc_type_ir::{ | 
|  | AliasTyKind, ConstKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection, | 
|  | ExistentialTraitRef, FnSig, OutlivesPredicate, | 
|  | TyKind::{self}, | 
|  | TypeVisitableExt, | 
|  | inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _}, | 
|  | }; | 
|  | use rustc_type_ir::{TypeFoldable, TypeFolder, Upcast}; | 
|  | use salsa::plumbing::AsId; | 
|  | use smallvec::{SmallVec, smallvec}; | 
|  | use stdx::never; | 
|  | use triomphe::Arc; | 
|  |  | 
|  | use crate::ValueTyDefId; | 
|  | use crate::next_solver::ParamConst; | 
|  | use crate::{ | 
|  | FnAbi, ImplTraitId, Interner, ParamKind, TraitEnvironment, TyDefId, TyLoweringDiagnostic, | 
|  | TyLoweringDiagnosticKind, | 
|  | consteval_nextsolver::{intern_const_ref, path_to_const, unknown_const_as_generic}, | 
|  | db::HirDatabase, | 
|  | generics::{Generics, generics, trait_self_param_idx}, | 
|  | lower::{Diagnostics, PathDiagnosticCallbackData, create_diagnostics}, | 
|  | next_solver::{ | 
|  | AdtDef, AliasTy, Binder, BoundExistentialPredicates, BoundRegionKind, BoundTyKind, | 
|  | BoundVarKind, BoundVarKinds, Clause, Clauses, Const, DbInterner, EarlyBinder, | 
|  | EarlyParamRegion, ErrorGuaranteed, GenericArgs, ParamEnv, PolyFnSig, Predicate, Region, | 
|  | SolverDefId, TraitPredicate, TraitRef, Ty, Tys, | 
|  | abi::Safety, | 
|  | mapping::{ChalkToNextSolver, convert_ty_for_result}, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | #[derive(PartialEq, Eq, Debug, Hash)] | 
|  | pub struct ImplTraits<'db> { | 
|  | pub(crate) impl_traits: Arena<ImplTrait<'db>>, | 
|  | } | 
|  |  | 
|  | #[derive(PartialEq, Eq, Debug, Hash)] | 
|  | pub struct ImplTrait<'db> { | 
|  | pub(crate) predicates: Vec<Clause<'db>>, | 
|  | } | 
|  |  | 
|  | pub type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>; | 
|  |  | 
|  | #[derive(Debug, Default)] | 
|  | struct ImplTraitLoweringState<'db> { | 
|  | /// When turning `impl Trait` into opaque types, we have to collect the | 
|  | /// bounds at the same time to get the IDs correct (without becoming too | 
|  | /// complicated). | 
|  | mode: ImplTraitLoweringMode, | 
|  | // This is structured as a struct with fields and not as an enum because it helps with the borrow checker. | 
|  | opaque_type_data: Arena<ImplTrait<'db>>, | 
|  | param_and_variable_counter: u16, | 
|  | } | 
|  | impl<'db> ImplTraitLoweringState<'db> { | 
|  | fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState<'db> { | 
|  | Self { mode, opaque_type_data: Arena::new(), param_and_variable_counter: 0 } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Debug, Clone)] | 
|  | pub(crate) enum LifetimeElisionKind<'db> { | 
|  | /// Create a new anonymous lifetime parameter and reference it. | 
|  | /// | 
|  | /// If `report_in_path`, report an error when encountering lifetime elision in a path: | 
|  | /// ```compile_fail | 
|  | /// struct Foo<'a> { x: &'a () } | 
|  | /// async fn foo(x: Foo) {} | 
|  | /// ``` | 
|  | /// | 
|  | /// Note: the error should not trigger when the elided lifetime is in a pattern or | 
|  | /// expression-position path: | 
|  | /// ``` | 
|  | /// struct Foo<'a> { x: &'a () } | 
|  | /// async fn foo(Foo { x: _ }: Foo<'_>) {} | 
|  | /// ``` | 
|  | AnonymousCreateParameter { report_in_path: bool }, | 
|  |  | 
|  | /// Replace all anonymous lifetimes by provided lifetime. | 
|  | Elided(Region<'db>), | 
|  |  | 
|  | /// Give a hard error when either `&` or `'_` is written. Used to | 
|  | /// rule out things like `where T: Foo<'_>`. Does not imply an | 
|  | /// error on default object bounds (e.g., `Box<dyn Foo>`). | 
|  | AnonymousReportError, | 
|  |  | 
|  | /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope, | 
|  | /// otherwise give a warning that the previous behavior of introducing a new early-bound | 
|  | /// lifetime is a bug and will be removed (if `only_lint` is enabled). | 
|  | StaticIfNoLifetimeInScope { only_lint: bool }, | 
|  |  | 
|  | /// Signal we cannot find which should be the anonymous lifetime. | 
|  | ElisionFailure, | 
|  |  | 
|  | /// Infer all elided lifetimes. | 
|  | Infer, | 
|  | } | 
|  |  | 
|  | impl<'db> LifetimeElisionKind<'db> { | 
|  | #[inline] | 
|  | pub(crate) fn for_const( | 
|  | interner: DbInterner<'db>, | 
|  | const_parent: ItemContainerId, | 
|  | ) -> LifetimeElisionKind<'db> { | 
|  | match const_parent { | 
|  | ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => { | 
|  | LifetimeElisionKind::Elided(Region::new_static(interner)) | 
|  | } | 
|  | ItemContainerId::ImplId(_) => { | 
|  | LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true } | 
|  | } | 
|  | ItemContainerId::TraitId(_) => { | 
|  | LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> { | 
|  | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> { | 
|  | // FIXME: We should use the elided lifetime here, or `ElisionFailure`. | 
|  | LifetimeElisionKind::Elided(Region::error(interner)) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Debug)] | 
|  | pub(crate) struct TyLoweringContext<'db, 'a> { | 
|  | pub db: &'db dyn HirDatabase, | 
|  | interner: DbInterner<'db>, | 
|  | resolver: &'a Resolver<'db>, | 
|  | store: &'a ExpressionStore, | 
|  | def: GenericDefId, | 
|  | generics: OnceCell<Generics>, | 
|  | in_binders: DebruijnIndex, | 
|  | impl_trait_mode: ImplTraitLoweringState<'db>, | 
|  | /// Tracks types with explicit `?Sized` bounds. | 
|  | pub(crate) unsized_types: FxHashSet<Ty<'db>>, | 
|  | pub(crate) diagnostics: Vec<TyLoweringDiagnostic>, | 
|  | lifetime_elision: LifetimeElisionKind<'db>, | 
|  | /// We disallow referencing generic parameters that have an index greater than or equal to this number. | 
|  | disallow_params_after: u32, | 
|  | } | 
|  |  | 
|  | impl<'db, 'a> TyLoweringContext<'db, 'a> { | 
|  | pub(crate) fn new( | 
|  | db: &'db dyn HirDatabase, | 
|  | resolver: &'a Resolver<'db>, | 
|  | store: &'a ExpressionStore, | 
|  | def: GenericDefId, | 
|  | lifetime_elision: LifetimeElisionKind<'db>, | 
|  | ) -> Self { | 
|  | let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed); | 
|  | let in_binders = DebruijnIndex::ZERO; | 
|  | Self { | 
|  | db, | 
|  | interner: DbInterner::new_with(db, Some(resolver.krate()), None), | 
|  | resolver, | 
|  | def, | 
|  | generics: Default::default(), | 
|  | store, | 
|  | in_binders, | 
|  | impl_trait_mode, | 
|  | unsized_types: FxHashSet::default(), | 
|  | diagnostics: Vec::new(), | 
|  | lifetime_elision, | 
|  | disallow_params_after: u32::MAX, | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn set_lifetime_elision(&mut self, lifetime_elision: LifetimeElisionKind<'db>) { | 
|  | self.lifetime_elision = lifetime_elision; | 
|  | } | 
|  |  | 
|  | pub(crate) fn with_debruijn<T>( | 
|  | &mut self, | 
|  | debruijn: DebruijnIndex, | 
|  | f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T, | 
|  | ) -> T { | 
|  | let old_debruijn = mem::replace(&mut self.in_binders, debruijn); | 
|  | let result = f(self); | 
|  | self.in_binders = old_debruijn; | 
|  | result | 
|  | } | 
|  |  | 
|  | pub(crate) fn with_shifted_in<T>( | 
|  | &mut self, | 
|  | debruijn: DebruijnIndex, | 
|  | f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T, | 
|  | ) -> T { | 
|  | self.with_debruijn(self.in_binders.shifted_in(debruijn.as_u32()), f) | 
|  | } | 
|  |  | 
|  | pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self { | 
|  | Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self } | 
|  | } | 
|  |  | 
|  | pub(crate) fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self { | 
|  | self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode); | 
|  | self | 
|  | } | 
|  |  | 
|  | pub(crate) fn disallow_params_after(&mut self, after: u32) { | 
|  | self.disallow_params_after = after; | 
|  | } | 
|  |  | 
|  | pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) { | 
|  | self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind }); | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] | 
|  | pub(crate) enum ImplTraitLoweringMode { | 
|  | /// `impl Trait` gets lowered into an opaque type that doesn't unify with | 
|  | /// anything except itself. This is used in places where values flow 'out', | 
|  | /// i.e. for arguments of the function we're currently checking, and return | 
|  | /// types of functions we're calling. | 
|  | Opaque, | 
|  | /// `impl Trait` is disallowed and will be an error. | 
|  | #[default] | 
|  | Disallowed, | 
|  | } | 
|  |  | 
|  | impl<'db, 'a> TyLoweringContext<'db, 'a> { | 
|  | pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> { | 
|  | self.lower_ty_ext(type_ref).0 | 
|  | } | 
|  |  | 
|  | pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> { | 
|  | let const_ref = &self.store[const_ref.expr]; | 
|  | match const_ref { | 
|  | hir_def::hir::Expr::Path(path) => { | 
|  | path_to_const(self.db, self.resolver, path, || self.generics(), const_type) | 
|  | .unwrap_or_else(|| unknown_const(const_type)) | 
|  | } | 
|  | hir_def::hir::Expr::Literal(literal) => intern_const_ref( | 
|  | self.db, | 
|  | &match *literal { | 
|  | hir_def::hir::Literal::Float(_, _) | 
|  | | hir_def::hir::Literal::String(_) | 
|  | | hir_def::hir::Literal::ByteString(_) | 
|  | | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown, | 
|  | hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c), | 
|  | hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b), | 
|  | hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val), | 
|  | hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val), | 
|  | }, | 
|  | const_type, | 
|  | self.resolver.krate(), | 
|  | ), | 
|  | hir_def::hir::Expr::UnaryOp { expr: inner_expr, op: hir_def::hir::UnaryOp::Neg } => { | 
|  | if let hir_def::hir::Expr::Literal(literal) = &self.store[*inner_expr] { | 
|  | // Only handle negation for signed integers and floats | 
|  | match literal { | 
|  | hir_def::hir::Literal::Int(_, _) | hir_def::hir::Literal::Float(_, _) => { | 
|  | if let Some(negated_literal) = literal.clone().negate() { | 
|  | intern_const_ref( | 
|  | self.db, | 
|  | &negated_literal.into(), | 
|  | const_type, | 
|  | self.resolver.krate(), | 
|  | ) | 
|  | } else { | 
|  | unknown_const(const_type) | 
|  | } | 
|  | } | 
|  | // For unsigned integers, chars, bools, etc., negation is not meaningful | 
|  | _ => unknown_const(const_type), | 
|  | } | 
|  | } else { | 
|  | unknown_const(const_type) | 
|  | } | 
|  | } | 
|  | _ => unknown_const(const_type), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> { | 
|  | path_to_const(self.db, self.resolver, path, || self.generics(), const_type) | 
|  | .unwrap_or_else(|| unknown_const(const_type)) | 
|  | } | 
|  |  | 
|  | fn generics(&self) -> &Generics { | 
|  | self.generics.get_or_init(|| generics(self.db, self.def)) | 
|  | } | 
|  |  | 
|  | fn type_param(&mut self, id: TypeParamId, index: u32, name: Symbol) -> Ty<'db> { | 
|  | if index >= self.disallow_params_after { | 
|  | // FIXME: Report an error. | 
|  | Ty::new_error(self.interner, ErrorGuaranteed) | 
|  | } else { | 
|  | Ty::new_param(self.interner, id, index, name) | 
|  | } | 
|  | } | 
|  |  | 
|  | fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> { | 
|  | if index >= self.disallow_params_after { | 
|  | // FIXME: Report an error. | 
|  | Const::error(self.interner) | 
|  | } else { | 
|  | Const::new_param(self.interner, ParamConst { id, index }) | 
|  | } | 
|  | } | 
|  |  | 
|  | fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> { | 
|  | if index >= self.disallow_params_after { | 
|  | // FIXME: Report an error. | 
|  | Region::error(self.interner) | 
|  | } else { | 
|  | Region::new_early_param(self.interner, EarlyParamRegion { id, index }) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[tracing::instrument(skip(self), ret)] | 
|  | pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) { | 
|  | let interner = self.interner; | 
|  | let mut res = None; | 
|  | let type_ref = &self.store[type_ref_id]; | 
|  | tracing::debug!(?type_ref); | 
|  | let ty = match type_ref { | 
|  | TypeRef::Never => Ty::new(interner, TyKind::Never), | 
|  | TypeRef::Tuple(inner) => { | 
|  | let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr)); | 
|  | Ty::new_tup_from_iter(interner, inner_tys) | 
|  | } | 
|  | TypeRef::Path(path) => { | 
|  | let (ty, res_) = | 
|  | self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id)); | 
|  | res = res_; | 
|  | ty | 
|  | } | 
|  | &TypeRef::TypeParam(type_param_id) => { | 
|  | res = Some(TypeNs::GenericParam(type_param_id)); | 
|  |  | 
|  | let generics = self.generics(); | 
|  | let (idx, data) = | 
|  | generics.type_or_const_param(type_param_id.into()).expect("matching generics"); | 
|  | let type_data = match data { | 
|  | TypeOrConstParamData::TypeParamData(ty) => ty, | 
|  | _ => unreachable!(), | 
|  | }; | 
|  | self.type_param( | 
|  | type_param_id, | 
|  | idx as u32, | 
|  | type_data | 
|  | .name | 
|  | .as_ref() | 
|  | .map_or_else(|| sym::MISSING_NAME.clone(), |d| d.symbol().clone()), | 
|  | ) | 
|  | } | 
|  | &TypeRef::RawPtr(inner, mutability) => { | 
|  | let inner_ty = self.lower_ty(inner); | 
|  | Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability))) | 
|  | } | 
|  | TypeRef::Array(array) => { | 
|  | let inner_ty = self.lower_ty(array.ty); | 
|  | let const_len = self.lower_const(array.len, Ty::new_usize(interner)); | 
|  | Ty::new_array_with_const_len(interner, inner_ty, const_len) | 
|  | } | 
|  | &TypeRef::Slice(inner) => { | 
|  | let inner_ty = self.lower_ty(inner); | 
|  | Ty::new_slice(interner, inner_ty) | 
|  | } | 
|  | TypeRef::Reference(ref_) => { | 
|  | let inner_ty = self.lower_ty(ref_.ty); | 
|  | // FIXME: It should infer the eldided lifetimes instead of stubbing with error | 
|  | let lifetime = ref_ | 
|  | .lifetime | 
|  | .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr)); | 
|  | Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability)) | 
|  | } | 
|  | TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed), | 
|  | TypeRef::Fn(fn_) => { | 
|  | let substs = self.with_shifted_in( | 
|  | DebruijnIndex::from_u32(1), | 
|  | |ctx: &mut TyLoweringContext<'_, '_>| { | 
|  | Tys::new_from_iter( | 
|  | interner, | 
|  | fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)), | 
|  | ) | 
|  | }, | 
|  | ); | 
|  | Ty::new_fn_ptr( | 
|  | interner, | 
|  | Binder::dummy(FnSig { | 
|  | abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), | 
|  | safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe }, | 
|  | c_variadic: fn_.is_varargs, | 
|  | inputs_and_output: substs, | 
|  | }), | 
|  | ) | 
|  | } | 
|  | TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds), | 
|  | TypeRef::ImplTrait(bounds) => { | 
|  | match self.impl_trait_mode.mode { | 
|  | ImplTraitLoweringMode::Opaque => { | 
|  | let origin = match self.resolver.generic_def() { | 
|  | Some(GenericDefId::FunctionId(it)) => Either::Left(it), | 
|  | Some(GenericDefId::TypeAliasId(it)) => Either::Right(it), | 
|  | _ => panic!( | 
|  | "opaque impl trait lowering must be in function or type alias" | 
|  | ), | 
|  | }; | 
|  |  | 
|  | // this dance is to make sure the data is in the right | 
|  | // place even if we encounter more opaque types while | 
|  | // lowering the bounds | 
|  | let idx = self | 
|  | .impl_trait_mode | 
|  | .opaque_type_data | 
|  | .alloc(ImplTrait { predicates: Vec::default() }); | 
|  |  | 
|  | // FIXME(next-solver): this from_raw/into_raw dance isn't nice, but it's minimal | 
|  | let impl_trait_id = origin.either( | 
|  | |f| ImplTraitId::ReturnTypeImplTrait(f, Idx::from_raw(idx.into_raw())), | 
|  | |a| ImplTraitId::TypeAliasImplTrait(a, Idx::from_raw(idx.into_raw())), | 
|  | ); | 
|  | let opaque_ty_id: SolverDefId = | 
|  | self.db.intern_impl_trait_id(impl_trait_id).into(); | 
|  |  | 
|  | // We don't want to lower the bounds inside the binders | 
|  | // we're currently in, because they don't end up inside | 
|  | // those binders. E.g. when we have `impl Trait<impl | 
|  | // OtherTrait<T>>`, the `impl OtherTrait<T>` can't refer | 
|  | // to the self parameter from `impl Trait`, and the | 
|  | // bounds aren't actually stored nested within each | 
|  | // other, but separately. So if the `T` refers to a type | 
|  | // parameter of the outer function, it's just one binder | 
|  | // away instead of two. | 
|  | let actual_opaque_type_data = self | 
|  | .with_debruijn(DebruijnIndex::ZERO, |ctx| { | 
|  | ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate()) | 
|  | }); | 
|  | self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data; | 
|  |  | 
|  | let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id); | 
|  | Ty::new_alias( | 
|  | self.interner, | 
|  | AliasTyKind::Opaque, | 
|  | AliasTy::new_from_args(self.interner, opaque_ty_id, args), | 
|  | ) | 
|  | } | 
|  | ImplTraitLoweringMode::Disallowed => { | 
|  | // FIXME: report error | 
|  | Ty::new_error(self.interner, ErrorGuaranteed) | 
|  | } | 
|  | } | 
|  | } | 
|  | TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed), | 
|  | }; | 
|  | (ty, res) | 
|  | } | 
|  |  | 
|  | /// This is only for `generic_predicates_for_param`, where we can't just | 
|  | /// lower the self types of the predicates since that could lead to cycles. | 
|  | /// So we just check here if the `type_ref` resolves to a generic param, and which. | 
|  | fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option<TypeOrConstParamId> { | 
|  | let type_ref = &self.store[type_ref]; | 
|  | let path = match type_ref { | 
|  | TypeRef::Path(path) => path, | 
|  | &TypeRef::TypeParam(idx) => return Some(idx.into()), | 
|  | _ => return None, | 
|  | }; | 
|  | if path.type_anchor().is_some() { | 
|  | return None; | 
|  | } | 
|  | if path.segments().len() > 1 { | 
|  | return None; | 
|  | } | 
|  | let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) { | 
|  | Some((it, None, _)) => it, | 
|  | _ => return None, | 
|  | }; | 
|  | match resolution { | 
|  | TypeNs::GenericParam(param_id) => Some(param_id.into()), | 
|  | _ => None, | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> { | 
|  | PathDiagnosticCallback { | 
|  | data: Either::Left(PathDiagnosticCallbackData(type_ref)), | 
|  | callback: |data, this, diag| { | 
|  | let type_ref = data.as_ref().left().unwrap().0; | 
|  | this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag)) | 
|  | }, | 
|  | } | 
|  | } | 
|  |  | 
|  | #[inline] | 
|  | fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> { | 
|  | PathLoweringContext::new( | 
|  | self, | 
|  | Self::on_path_diagnostic_callback(path_id.type_ref()), | 
|  | &self.store[path_id], | 
|  | ) | 
|  | } | 
|  |  | 
|  | pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option<TypeNs>) { | 
|  | // Resolve the path (in type namespace) | 
|  | if let Some(type_ref) = path.type_anchor() { | 
|  | let (ty, res) = self.lower_ty_ext(type_ref); | 
|  | let mut ctx = self.at_path(path_id); | 
|  | return ctx.lower_ty_relative_path(ty, res, false); | 
|  | } | 
|  |  | 
|  | let mut ctx = self.at_path(path_id); | 
|  | let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() { | 
|  | Some(it) => it, | 
|  | None => return (Ty::new_error(self.interner, ErrorGuaranteed), None), | 
|  | }; | 
|  |  | 
|  | if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() { | 
|  | // trait object type without dyn | 
|  | let bound = TypeBound::Path(path_id, TraitBoundModifier::None); | 
|  | let ty = self.lower_dyn_trait(&[bound]); | 
|  | return (ty, None); | 
|  | } | 
|  |  | 
|  | ctx.lower_partly_resolved_path(resolution, false) | 
|  | } | 
|  |  | 
|  | fn lower_trait_ref_from_path( | 
|  | &mut self, | 
|  | path_id: PathId, | 
|  | explicit_self_ty: Ty<'db>, | 
|  | ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> { | 
|  | let mut ctx = self.at_path(path_id); | 
|  | let resolved = match ctx.resolve_path_in_type_ns_fully()? { | 
|  | // FIXME(trait_alias): We need to handle trait alias here. | 
|  | TypeNs::TraitId(tr) => tr, | 
|  | _ => return None, | 
|  | }; | 
|  | Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx)) | 
|  | } | 
|  |  | 
|  | fn lower_trait_ref( | 
|  | &mut self, | 
|  | trait_ref: &HirTraitRef, | 
|  | explicit_self_ty: Ty<'db>, | 
|  | ) -> Option<TraitRef<'db>> { | 
|  | self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0) | 
|  | } | 
|  |  | 
|  | pub(crate) fn lower_where_predicate<'b>( | 
|  | &'b mut self, | 
|  | where_predicate: &'b WherePredicate, | 
|  | ignore_bindings: bool, | 
|  | generics: &Generics, | 
|  | predicate_filter: PredicateFilter, | 
|  | ) -> impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'db> { | 
|  | match where_predicate { | 
|  | WherePredicate::ForLifetime { target, bound, .. } | 
|  | | WherePredicate::TypeBound { target, bound } => { | 
|  | if let PredicateFilter::SelfTrait = predicate_filter { | 
|  | let target_type = &self.store[*target]; | 
|  | let self_type = 'is_self: { | 
|  | if let TypeRef::Path(path) = target_type | 
|  | && path.is_self_type() | 
|  | { | 
|  | break 'is_self true; | 
|  | } | 
|  | if let TypeRef::TypeParam(param) = target_type | 
|  | && generics[param.local_id()].is_trait_self() | 
|  | { | 
|  | break 'is_self true; | 
|  | } | 
|  | false | 
|  | }; | 
|  | if !self_type { | 
|  | return Either::Left(Either::Left(iter::empty())); | 
|  | } | 
|  | } | 
|  | let self_ty = self.lower_ty(*target); | 
|  | Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings))) | 
|  | } | 
|  | &WherePredicate::Lifetime { bound, target } => { | 
|  | Either::Right(iter::once(Clause(Predicate::new( | 
|  | self.interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause( | 
|  | rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate( | 
|  | self.lower_lifetime(bound), | 
|  | self.lower_lifetime(target), | 
|  | )), | 
|  | )), | 
|  | )))) | 
|  | } | 
|  | } | 
|  | .into_iter() | 
|  | } | 
|  |  | 
|  | pub(crate) fn lower_type_bound<'b>( | 
|  | &'b mut self, | 
|  | bound: &'b TypeBound, | 
|  | self_ty: Ty<'db>, | 
|  | ignore_bindings: bool, | 
|  | ) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> { | 
|  | let interner = self.interner; | 
|  | let mut assoc_bounds = None; | 
|  | let mut clause = None; | 
|  | match bound { | 
|  | &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => { | 
|  | // FIXME Don't silently drop the hrtb lifetimes here | 
|  | if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) { | 
|  | // FIXME(sized-hierarchy): Remove this bound modifications once we have implemented | 
|  | // sized-hierarchy correctly. | 
|  | let meta_sized = LangItem::MetaSized | 
|  | .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); | 
|  | let pointee_sized = LangItem::PointeeSized | 
|  | .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate()); | 
|  | if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) { | 
|  | // Ignore this bound | 
|  | } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) { | 
|  | // Regard this as `?Sized` bound | 
|  | ctx.ty_ctx().unsized_types.insert(self_ty); | 
|  | } else { | 
|  | if !ignore_bindings { | 
|  | assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref); | 
|  | } | 
|  | clause = Some(Clause(Predicate::new( | 
|  | interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause( | 
|  | rustc_type_ir::ClauseKind::Trait(TraitPredicate { | 
|  | trait_ref, | 
|  | polarity: rustc_type_ir::PredicatePolarity::Positive, | 
|  | }), | 
|  | )), | 
|  | ))); | 
|  | } | 
|  | } | 
|  | } | 
|  | &TypeBound::Path(path, TraitBoundModifier::Maybe) => { | 
|  | let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate()); | 
|  | // Don't lower associated type bindings as the only possible relaxed trait bound | 
|  | // `?Sized` has no of them. | 
|  | // If we got another trait here ignore the bound completely. | 
|  | let trait_id = self | 
|  | .lower_trait_ref_from_path(path, self_ty) | 
|  | .map(|(trait_ref, _)| trait_ref.def_id.0); | 
|  | if trait_id == sized_trait { | 
|  | self.unsized_types.insert(self_ty); | 
|  | } | 
|  | } | 
|  | &TypeBound::Lifetime(l) => { | 
|  | let lifetime = self.lower_lifetime(l); | 
|  | clause = Some(Clause(Predicate::new( | 
|  | self.interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause( | 
|  | rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate( | 
|  | self_ty, lifetime, | 
|  | )), | 
|  | )), | 
|  | ))); | 
|  | } | 
|  | TypeBound::Use(_) | TypeBound::Error => {} | 
|  | } | 
|  | clause.into_iter().chain(assoc_bounds.into_iter().flatten()) | 
|  | } | 
|  |  | 
|  | fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> { | 
|  | let interner = self.interner; | 
|  | // FIXME: we should never create non-existential predicates in the first place | 
|  | // For now, use an error type so we don't run into dummy binder issues | 
|  | let self_ty = Ty::new_error(interner, ErrorGuaranteed); | 
|  | // INVARIANT: The principal trait bound, if present, must come first. Others may be in any | 
|  | // order but should be in the same order for the same set but possibly different order of | 
|  | // bounds in the input. | 
|  | // INVARIANT: If this function returns `DynTy`, there should be at least one trait bound. | 
|  | // These invariants are utilized by `TyExt::dyn_trait()` and chalk. | 
|  | let mut lifetime = None; | 
|  | let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| { | 
|  | let mut lowered_bounds: Vec< | 
|  | rustc_type_ir::Binder<DbInterner<'db>, ExistentialPredicate<DbInterner<'db>>>, | 
|  | > = Vec::new(); | 
|  | for b in bounds { | 
|  | let db = ctx.db; | 
|  | ctx.lower_type_bound(b, self_ty, false).for_each(|b| { | 
|  | if let Some(bound) = b | 
|  | .kind() | 
|  | .map_bound(|c| match c { | 
|  | rustc_type_ir::ClauseKind::Trait(t) => { | 
|  | let id = t.def_id(); | 
|  | let is_auto = | 
|  | db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); | 
|  | if is_auto { | 
|  | Some(ExistentialPredicate::AutoTrait(t.def_id())) | 
|  | } else { | 
|  | Some(ExistentialPredicate::Trait( | 
|  | ExistentialTraitRef::new_from_args( | 
|  | interner, | 
|  | t.def_id(), | 
|  | GenericArgs::new_from_iter( | 
|  | interner, | 
|  | t.trait_ref.args.iter().skip(1), | 
|  | ), | 
|  | ), | 
|  | )) | 
|  | } | 
|  | } | 
|  | rustc_type_ir::ClauseKind::Projection(p) => { | 
|  | Some(ExistentialPredicate::Projection( | 
|  | ExistentialProjection::new_from_args( | 
|  | interner, | 
|  | p.def_id(), | 
|  | GenericArgs::new_from_iter( | 
|  | interner, | 
|  | p.projection_term.args.iter().skip(1), | 
|  | ), | 
|  | p.term, | 
|  | ), | 
|  | )) | 
|  | } | 
|  | rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => { | 
|  | lifetime = Some(outlives_predicate.1); | 
|  | None | 
|  | } | 
|  | rustc_type_ir::ClauseKind::RegionOutlives(_) | 
|  | | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) | 
|  | | rustc_type_ir::ClauseKind::WellFormed(_) | 
|  | | rustc_type_ir::ClauseKind::ConstEvaluatable(_) | 
|  | | rustc_type_ir::ClauseKind::HostEffect(_) | 
|  | | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), | 
|  | }) | 
|  | .transpose() | 
|  | { | 
|  | lowered_bounds.push(bound); | 
|  | } | 
|  | }) | 
|  | } | 
|  |  | 
|  | let mut multiple_regular_traits = false; | 
|  | let mut multiple_same_projection = false; | 
|  | lowered_bounds.sort_unstable_by(|lhs, rhs| { | 
|  | use std::cmp::Ordering; | 
|  | match ((*lhs).skip_binder(), (*rhs).skip_binder()) { | 
|  | (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => { | 
|  | multiple_regular_traits = true; | 
|  | // Order doesn't matter - we error | 
|  | Ordering::Equal | 
|  | } | 
|  | ( | 
|  | ExistentialPredicate::AutoTrait(lhs_id), | 
|  | ExistentialPredicate::AutoTrait(rhs_id), | 
|  | ) => lhs_id.0.cmp(&rhs_id.0), | 
|  | (ExistentialPredicate::Trait(_), _) => Ordering::Less, | 
|  | (_, ExistentialPredicate::Trait(_)) => Ordering::Greater, | 
|  | (ExistentialPredicate::AutoTrait(_), _) => Ordering::Less, | 
|  | (_, ExistentialPredicate::AutoTrait(_)) => Ordering::Greater, | 
|  | ( | 
|  | ExistentialPredicate::Projection(lhs), | 
|  | ExistentialPredicate::Projection(rhs), | 
|  | ) => { | 
|  | let lhs_id = match lhs.def_id { | 
|  | SolverDefId::TypeAliasId(id) => id, | 
|  | _ => unreachable!(), | 
|  | }; | 
|  | let rhs_id = match rhs.def_id { | 
|  | SolverDefId::TypeAliasId(id) => id, | 
|  | _ => unreachable!(), | 
|  | }; | 
|  | // We only compare the `associated_ty_id`s. We shouldn't have | 
|  | // multiple bounds for an associated type in the correct Rust code, | 
|  | // and if we do, we error out. | 
|  | if lhs_id == rhs_id { | 
|  | multiple_same_projection = true; | 
|  | } | 
|  | lhs_id.as_id().index().cmp(&rhs_id.as_id().index()) | 
|  | } | 
|  | } | 
|  | }); | 
|  |  | 
|  | if multiple_regular_traits || multiple_same_projection { | 
|  | return None; | 
|  | } | 
|  |  | 
|  | if !lowered_bounds.first().map_or(false, |b| { | 
|  | matches!( | 
|  | b.as_ref().skip_binder(), | 
|  | ExistentialPredicate::Trait(_) | ExistentialPredicate::AutoTrait(_) | 
|  | ) | 
|  | }) { | 
|  | return None; | 
|  | } | 
|  |  | 
|  | // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the | 
|  | // bounds. We shouldn't have repeated elements besides auto traits at this point. | 
|  | lowered_bounds.dedup(); | 
|  |  | 
|  | Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds)) | 
|  | }); | 
|  |  | 
|  | if let Some(bounds) = bounds { | 
|  | let region = match lifetime { | 
|  | Some(it) => match it.kind() { | 
|  | rustc_type_ir::RegionKind::ReBound(db, var) => Region::new_bound( | 
|  | self.interner, | 
|  | db.shifted_out_to_binder(DebruijnIndex::from_u32(2)), | 
|  | var, | 
|  | ), | 
|  | _ => it, | 
|  | }, | 
|  | None => Region::new_static(self.interner), | 
|  | }; | 
|  | Ty::new_dynamic(self.interner, bounds, region) | 
|  | } else { | 
|  | // FIXME: report error | 
|  | // (additional non-auto traits, associated type rebound, or no resolved trait) | 
|  | Ty::new_error(self.interner, ErrorGuaranteed) | 
|  | } | 
|  | } | 
|  |  | 
|  | fn lower_impl_trait( | 
|  | &mut self, | 
|  | def_id: SolverDefId, | 
|  | bounds: &[TypeBound], | 
|  | krate: Crate, | 
|  | ) -> ImplTrait<'db> { | 
|  | let interner = self.interner; | 
|  | cov_mark::hit!(lower_rpit); | 
|  | let args = GenericArgs::identity_for_item(interner, def_id); | 
|  | let self_ty = Ty::new_alias( | 
|  | self.interner, | 
|  | rustc_type_ir::AliasTyKind::Opaque, | 
|  | AliasTy::new_from_args(interner, def_id, args), | 
|  | ); | 
|  | let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| { | 
|  | let mut predicates = Vec::new(); | 
|  | for b in bounds { | 
|  | predicates.extend(ctx.lower_type_bound(b, self_ty, false)); | 
|  | } | 
|  |  | 
|  | if !ctx.unsized_types.contains(&self_ty) { | 
|  | let sized_trait = LangItem::Sized.resolve_trait(self.db, krate); | 
|  | let sized_clause = sized_trait.map(|trait_id| { | 
|  | let trait_ref = TraitRef::new_from_args( | 
|  | interner, | 
|  | trait_id.into(), | 
|  | GenericArgs::new_from_iter(interner, [self_ty.into()]), | 
|  | ); | 
|  | Clause(Predicate::new( | 
|  | interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause( | 
|  | rustc_type_ir::ClauseKind::Trait(TraitPredicate { | 
|  | trait_ref, | 
|  | polarity: rustc_type_ir::PredicatePolarity::Positive, | 
|  | }), | 
|  | )), | 
|  | )) | 
|  | }); | 
|  | predicates.extend(sized_clause); | 
|  | } | 
|  | predicates.shrink_to_fit(); | 
|  | predicates | 
|  | }); | 
|  | ImplTrait { predicates } | 
|  | } | 
|  |  | 
|  | pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> { | 
|  | match self.resolver.resolve_lifetime(&self.store[lifetime]) { | 
|  | Some(resolution) => match resolution { | 
|  | LifetimeNs::Static => Region::new_static(self.interner), | 
|  | LifetimeNs::LifetimeParam(id) => { | 
|  | let idx = match self.generics().lifetime_idx(id) { | 
|  | None => return Region::error(self.interner), | 
|  | Some(idx) => idx, | 
|  | }; | 
|  | self.region_param(id, idx as u32) | 
|  | } | 
|  | }, | 
|  | None => Region::error(self.interner), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability { | 
|  | match m { | 
|  | hir_def::type_ref::Mutability::Shared => Mutability::Not, | 
|  | hir_def::type_ref::Mutability::Mut => Mutability::Mut, | 
|  | } | 
|  | } | 
|  |  | 
|  | fn unknown_const(_ty: Ty<'_>) -> Const<'_> { | 
|  | Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed)) | 
|  | } | 
|  |  | 
|  | pub(crate) fn impl_trait_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | impl_id: ImplId, | 
|  | ) -> Option<EarlyBinder<'db, TraitRef<'db>>> { | 
|  | db.impl_trait_with_diagnostics(impl_id).map(|it| it.0) | 
|  | } | 
|  |  | 
|  | pub(crate) fn impl_trait_with_diagnostics_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | impl_id: ImplId, | 
|  | ) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> { | 
|  | let impl_data = db.impl_signature(impl_id); | 
|  | let resolver = impl_id.resolver(db); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &impl_data.store, | 
|  | impl_id.into(), | 
|  | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, | 
|  | ); | 
|  | let self_ty = db.impl_self_ty(impl_id).skip_binder(); | 
|  | let target_trait = impl_data.target_trait.as_ref()?; | 
|  | let trait_ref = EarlyBinder::bind(ctx.lower_trait_ref(target_trait, self_ty)?); | 
|  | Some((trait_ref, create_diagnostics(ctx.diagnostics))) | 
|  | } | 
|  |  | 
|  | pub(crate) fn return_type_impl_traits<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: hir_def::FunctionId, | 
|  | ) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> { | 
|  | // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe | 
|  | let data = db.function_signature(def); | 
|  | let resolver = def.resolver(db); | 
|  | let mut ctx_ret = | 
|  | TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer) | 
|  | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); | 
|  | if let Some(ret_type) = data.ret_type { | 
|  | let _ret = ctx_ret.lower_ty(ret_type); | 
|  | } | 
|  | let return_type_impl_traits = | 
|  | ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data }; | 
|  | if return_type_impl_traits.impl_traits.is_empty() { | 
|  | None | 
|  | } else { | 
|  | Some(Arc::new(EarlyBinder::bind(return_type_impl_traits))) | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn type_alias_impl_traits<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: hir_def::TypeAliasId, | 
|  | ) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> { | 
|  | let data = db.type_alias_signature(def); | 
|  | let resolver = def.resolver(db); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &data.store, | 
|  | def.into(), | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ) | 
|  | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); | 
|  | if let Some(type_ref) = data.ty { | 
|  | let _ty = ctx.lower_ty(type_ref); | 
|  | } | 
|  | let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data }; | 
|  | if type_alias_impl_traits.impl_traits.is_empty() { | 
|  | None | 
|  | } else { | 
|  | Some(Arc::new(EarlyBinder::bind(type_alias_impl_traits))) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Build the declared type of an item. This depends on the namespace; e.g. for | 
|  | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 
|  | /// the constructor function `(usize) -> Foo` which lives in the values | 
|  | /// namespace. | 
|  | pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | match def { | 
|  | TyDefId::BuiltinType(it) => EarlyBinder::bind(builtin(interner, it)), | 
|  | TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt( | 
|  | interner, | 
|  | it, | 
|  | GenericArgs::identity_for_item(interner, it.into()), | 
|  | )), | 
|  | TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0, | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Build the declared type of a function. This should not need to look at the | 
|  | /// function body. | 
|  | fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | EarlyBinder::bind(Ty::new_fn_def( | 
|  | interner, | 
|  | CallableDefId::FunctionId(def).into(), | 
|  | GenericArgs::identity_for_item(interner, def.into()), | 
|  | )) | 
|  | } | 
|  |  | 
|  | /// Build the declared type of a const. | 
|  | fn type_for_const<'db>(db: &'db dyn HirDatabase, def: ConstId) -> EarlyBinder<'db, Ty<'db>> { | 
|  | let resolver = def.resolver(db); | 
|  | let data = db.const_signature(def); | 
|  | let parent = def.loc(db).container; | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &data.store, | 
|  | def.into(), | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  | ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent)); | 
|  | EarlyBinder::bind(ctx.lower_ty(data.type_ref)) | 
|  | } | 
|  |  | 
|  | /// Build the declared type of a static. | 
|  | fn type_for_static<'db>(db: &'db dyn HirDatabase, def: StaticId) -> EarlyBinder<'db, Ty<'db>> { | 
|  | let resolver = def.resolver(db); | 
|  | let module = resolver.module(); | 
|  | let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); | 
|  | let data = db.static_signature(def); | 
|  | let parent = def.loc(db).container; | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &data.store, | 
|  | def.into(), | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  | ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner))); | 
|  | EarlyBinder::bind(ctx.lower_ty(data.type_ref)) | 
|  | } | 
|  |  | 
|  | /// Build the type of a tuple struct constructor. | 
|  | fn type_for_struct_constructor<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: StructId, | 
|  | ) -> Option<EarlyBinder<'db, Ty<'db>>> { | 
|  | let struct_data = def.fields(db); | 
|  | match struct_data.shape { | 
|  | FieldsShape::Record => None, | 
|  | FieldsShape::Unit => Some(type_for_adt(db, def.into())), | 
|  | FieldsShape::Tuple => { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | Some(EarlyBinder::bind(Ty::new_fn_def( | 
|  | interner, | 
|  | CallableDefId::StructId(def).into(), | 
|  | GenericArgs::identity_for_item(interner, def.into()), | 
|  | ))) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Build the type of a tuple enum variant constructor. | 
|  | fn type_for_enum_variant_constructor<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: EnumVariantId, | 
|  | ) -> Option<EarlyBinder<'db, Ty<'db>>> { | 
|  | let struct_data = def.fields(db); | 
|  | match struct_data.shape { | 
|  | FieldsShape::Record => None, | 
|  | FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())), | 
|  | FieldsShape::Tuple => { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | Some(EarlyBinder::bind(Ty::new_fn_def( | 
|  | interner, | 
|  | CallableDefId::EnumVariantId(def).into(), | 
|  | GenericArgs::identity_for_item(interner, def.loc(db).parent.into()), | 
|  | ))) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn value_ty_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: ValueTyDefId, | 
|  | ) -> Option<EarlyBinder<'db, Ty<'db>>> { | 
|  | match def { | 
|  | ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)), | 
|  | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), | 
|  | ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())), | 
|  | ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), | 
|  | ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)), | 
|  | ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)), | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | t: TypeAliasId, | 
|  | ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { | 
|  | let type_alias_data = db.type_alias_signature(t); | 
|  | let mut diags = None; | 
|  | let resolver = t.resolver(db); | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  | let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { | 
|  | EarlyBinder::bind(Ty::new_foreign(interner, t.into())) | 
|  | } else { | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &type_alias_data.store, | 
|  | t.into(), | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ) | 
|  | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); | 
|  | let res = EarlyBinder::bind( | 
|  | type_alias_data | 
|  | .ty | 
|  | .map(|type_ref| ctx.lower_ty(type_ref)) | 
|  | .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)), | 
|  | ); | 
|  | diags = create_diagnostics(ctx.diagnostics); | 
|  | res | 
|  | }; | 
|  | (inner, diags) | 
|  | } | 
|  |  | 
|  | pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | _adt: TypeAliasId, | 
|  | ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { | 
|  | (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) | 
|  | } | 
|  |  | 
|  | pub(crate) fn impl_self_ty_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | impl_id: ImplId, | 
|  | ) -> EarlyBinder<'db, Ty<'db>> { | 
|  | db.impl_self_ty_with_diagnostics(impl_id).0 | 
|  | } | 
|  |  | 
|  | pub(crate) fn impl_self_ty_with_diagnostics_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | impl_id: ImplId, | 
|  | ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { | 
|  | let resolver = impl_id.resolver(db); | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  |  | 
|  | let impl_data = db.impl_signature(impl_id); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &impl_data.store, | 
|  | impl_id.into(), | 
|  | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }, | 
|  | ); | 
|  | let ty = ctx.lower_ty(impl_data.self_ty); | 
|  | assert!(!ty.has_escaping_bound_vars()); | 
|  | (EarlyBinder::bind(ty), create_diagnostics(ctx.diagnostics)) | 
|  | } | 
|  |  | 
|  | pub(crate) fn impl_self_ty_with_diagnostics_cycle_result( | 
|  | db: &dyn HirDatabase, | 
|  | _impl_id: ImplId, | 
|  | ) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) { | 
|  | (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) | 
|  | } | 
|  |  | 
|  | pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> { | 
|  | db.const_param_ty_with_diagnostics(def).0 | 
|  | } | 
|  |  | 
|  | // returns None if def is a type arg | 
|  | pub(crate) fn const_param_ty_with_diagnostics_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: ConstParamId, | 
|  | ) -> (Ty<'db>, Diagnostics) { | 
|  | let (parent_data, store) = db.generic_params_and_store(def.parent()); | 
|  | let data = &parent_data[def.local_id()]; | 
|  | let resolver = def.parent().resolver(db); | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &store, | 
|  | def.parent(), | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  | let ty = match data { | 
|  | TypeOrConstParamData::TypeParamData(_) => { | 
|  | never!(); | 
|  | Ty::new_error(interner, ErrorGuaranteed) | 
|  | } | 
|  | TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty), | 
|  | }; | 
|  | (ty, create_diagnostics(ctx.diagnostics)) | 
|  | } | 
|  |  | 
|  | pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | _: crate::db::HirDatabaseData, | 
|  | def: ConstParamId, | 
|  | ) -> (Ty<'db>, Diagnostics) { | 
|  | let resolver = def.parent().resolver(db); | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  | (Ty::new_error(interner, ErrorGuaranteed), None) | 
|  | } | 
|  |  | 
|  | pub(crate) fn field_types_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | variant_id: VariantId, | 
|  | ) -> Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>> { | 
|  | db.field_types_with_diagnostics(variant_id).0 | 
|  | } | 
|  |  | 
|  | /// Build the type of all specific fields of a struct or enum variant. | 
|  | pub(crate) fn field_types_with_diagnostics_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | variant_id: VariantId, | 
|  | ) -> (Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>>, Diagnostics) { | 
|  | let var_data = variant_id.fields(db); | 
|  | let fields = var_data.fields(); | 
|  | if fields.is_empty() { | 
|  | return (Arc::new(ArenaMap::default()), None); | 
|  | } | 
|  |  | 
|  | let (resolver, def): (_, GenericDefId) = match variant_id { | 
|  | VariantId::StructId(it) => (it.resolver(db), it.into()), | 
|  | VariantId::UnionId(it) => (it.resolver(db), it.into()), | 
|  | VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()), | 
|  | }; | 
|  | let mut res = ArenaMap::default(); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &var_data.store, | 
|  | def, | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  | for (field_id, field_data) in var_data.fields().iter() { | 
|  | res.insert(field_id, EarlyBinder::bind(ctx.lower_ty(field_data.type_ref))); | 
|  | } | 
|  | (Arc::new(res), create_diagnostics(ctx.diagnostics)) | 
|  | } | 
|  |  | 
|  | /// This query exists only to be used when resolving short-hand associated types | 
|  | /// like `T::Item`. | 
|  | /// | 
|  | /// See the analogous query in rustc and its comment: | 
|  | /// <https://github.com/rust-lang/rust/blob/9150f844e2624eb013ec78ca08c1d416e6644026/src/librustc_typeck/astconv.rs#L46> | 
|  | /// This is a query mostly to handle cycles somewhat gracefully; e.g. the | 
|  | /// following bounds are disallowed: `T: Foo<U::Item>, U: Foo<T::Item>`, but | 
|  | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. | 
|  | #[tracing::instrument(skip(db), ret)] | 
|  | pub(crate) fn generic_predicates_for_param_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | param_id: TypeOrConstParamId, | 
|  | assoc_name: Option<Name>, | 
|  | ) -> GenericPredicates<'db> { | 
|  | let generics = generics(db, def); | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | let resolver = def.resolver(db); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | generics.store(), | 
|  | def, | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  |  | 
|  | // we have to filter out all other predicates *first*, before attempting to lower them | 
|  | let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred { | 
|  | WherePredicate::ForLifetime { target, bound, .. } | 
|  | | WherePredicate::TypeBound { target, bound, .. } => { | 
|  | let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) }; | 
|  | if invalid_target { | 
|  | // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented | 
|  | // sized-hierarchy correctly. | 
|  | // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into | 
|  | // `ctx.unsized_types` | 
|  | let lower = || -> bool { | 
|  | match bound { | 
|  | TypeBound::Path(_, TraitBoundModifier::Maybe) => true, | 
|  | TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => { | 
|  | let TypeRef::Path(path) = &ctx.store[path.type_ref()] else { | 
|  | return false; | 
|  | }; | 
|  | let Some(pointee_sized) = | 
|  | LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate()) | 
|  | else { | 
|  | return false; | 
|  | }; | 
|  | // Lower the path directly with `Resolver` instead of PathLoweringContext` | 
|  | // to prevent diagnostics duplications. | 
|  | ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and( | 
|  | |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized), | 
|  | ) | 
|  | } | 
|  | _ => false, | 
|  | } | 
|  | }(); | 
|  | if lower { | 
|  | ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All) | 
|  | .for_each(drop); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | match bound { | 
|  | &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => { | 
|  | // Only lower the bound if the trait could possibly define the associated | 
|  | // type we're looking for. | 
|  | let path = &ctx.store[path]; | 
|  |  | 
|  | let Some(assoc_name) = &assoc_name else { return true }; | 
|  | let Some(TypeNs::TraitId(tr)) = | 
|  | resolver.resolve_path_in_type_ns_fully(db, path) | 
|  | else { | 
|  | return false; | 
|  | }; | 
|  |  | 
|  | rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| { | 
|  | tr.0.trait_items(db).items.iter().any(|(name, item)| { | 
|  | matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name | 
|  | }) | 
|  | }) | 
|  | } | 
|  | TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false, | 
|  | } | 
|  | } | 
|  | WherePredicate::Lifetime { .. } => false, | 
|  | }; | 
|  | let mut predicates = Vec::new(); | 
|  | for maybe_parent_generics in | 
|  | std::iter::successors(Some(&generics), |generics| generics.parent_generics()) | 
|  | { | 
|  | ctx.store = maybe_parent_generics.store(); | 
|  | for pred in maybe_parent_generics.where_predicates() { | 
|  | if predicate(pred, &mut ctx) { | 
|  | predicates.extend(ctx.lower_where_predicate( | 
|  | pred, | 
|  | true, | 
|  | maybe_parent_generics, | 
|  | PredicateFilter::All, | 
|  | )); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | let args = GenericArgs::identity_for_item(interner, def.into()); | 
|  | if !args.is_empty() { | 
|  | let explicitly_unsized_tys = ctx.unsized_types; | 
|  | if let Some(implicitly_sized_predicates) = | 
|  | implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver) | 
|  | { | 
|  | predicates.extend(implicitly_sized_predicates); | 
|  | }; | 
|  | } | 
|  | GenericPredicates(predicates.is_empty().not().then(|| predicates.into())) | 
|  | } | 
|  |  | 
|  | pub(crate) fn generic_predicates_for_param_cycle_result( | 
|  | _db: &dyn HirDatabase, | 
|  | _def: GenericDefId, | 
|  | _param_id: TypeOrConstParamId, | 
|  | _assoc_name: Option<Name>, | 
|  | ) -> GenericPredicates<'_> { | 
|  | GenericPredicates(None) | 
|  | } | 
|  |  | 
|  | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 
|  | pub struct GenericPredicates<'db>(Option<Arc<[Clause<'db>]>>); | 
|  |  | 
|  | impl<'db> GenericPredicates<'db> { | 
|  | pub fn instantiate( | 
|  | &self, | 
|  | interner: DbInterner<'db>, | 
|  | args: GenericArgs<'db>, | 
|  | ) -> Option<impl Iterator<Item = Clause<'db>>> { | 
|  | self.0 | 
|  | .as_ref() | 
|  | .map(|it| EarlyBinder::bind(it.iter().copied()).iter_instantiated(interner, args)) | 
|  | } | 
|  | } | 
|  |  | 
|  | impl<'db> ops::Deref for GenericPredicates<'db> { | 
|  | type Target = [Clause<'db>]; | 
|  |  | 
|  | fn deref(&self) -> &Self::Target { | 
|  | self.0.as_deref().unwrap_or(&[]) | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn trait_environment_for_body_query( | 
|  | db: &dyn HirDatabase, | 
|  | def: DefWithBodyId, | 
|  | ) -> Arc<TraitEnvironment<'_>> { | 
|  | let Some(def) = def.as_generic_def_id(db) else { | 
|  | let krate = def.module(db).krate(); | 
|  | return TraitEnvironment::empty(krate); | 
|  | }; | 
|  | db.trait_environment(def) | 
|  | } | 
|  |  | 
|  | pub(crate) fn trait_environment_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | ) -> Arc<TraitEnvironment<'db>> { | 
|  | let generics = generics(db, def); | 
|  | if generics.has_no_predicates() && generics.is_empty() { | 
|  | return TraitEnvironment::empty(def.krate(db)); | 
|  | } | 
|  |  | 
|  | let interner = DbInterner::new_with(db, Some(def.krate(db)), None); | 
|  | let resolver = def.resolver(db); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | generics.store(), | 
|  | def, | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  | let mut traits_in_scope = Vec::new(); | 
|  | let mut clauses = Vec::new(); | 
|  | for maybe_parent_generics in | 
|  | std::iter::successors(Some(&generics), |generics| generics.parent_generics()) | 
|  | { | 
|  | ctx.store = maybe_parent_generics.store(); | 
|  | for pred in maybe_parent_generics.where_predicates() { | 
|  | for pred in ctx.lower_where_predicate(pred, false, &generics, PredicateFilter::All) { | 
|  | if let rustc_type_ir::ClauseKind::Trait(tr) = pred.kind().skip_binder() { | 
|  | traits_in_scope | 
|  | .push((convert_ty_for_result(interner, tr.self_ty()), tr.def_id().0)); | 
|  | } | 
|  | clauses.push(pred); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if let Some(trait_id) = def.assoc_trait_container(db) { | 
|  | // add `Self: Trait<T1, T2, ...>` to the environment in trait | 
|  | // function default implementations (and speculative code | 
|  | // inside consts or type aliases) | 
|  | cov_mark::hit!(trait_self_implements_self); | 
|  | let trait_ref = TraitRef::identity(ctx.interner, trait_id.into()); | 
|  | let clause = Clause(Predicate::new( | 
|  | ctx.interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait( | 
|  | TraitPredicate { trait_ref, polarity: rustc_type_ir::PredicatePolarity::Positive }, | 
|  | ))), | 
|  | )); | 
|  | clauses.push(clause); | 
|  | } | 
|  |  | 
|  | let explicitly_unsized_tys = ctx.unsized_types; | 
|  |  | 
|  | let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); | 
|  | if let Some(sized_trait) = sized_trait { | 
|  | let (mut generics, mut def_id) = | 
|  | (crate::next_solver::generics::generics(db, def.into()), def); | 
|  | loop { | 
|  | let self_idx = trait_self_param_idx(db, def_id); | 
|  | for (idx, p) in generics.own_params.iter().enumerate() { | 
|  | if let Some(self_idx) = self_idx | 
|  | && p.index() as usize == self_idx | 
|  | { | 
|  | continue; | 
|  | } | 
|  | let GenericParamId::TypeParamId(param_id) = p.id else { | 
|  | continue; | 
|  | }; | 
|  | let idx = idx as u32 + generics.parent_count as u32; | 
|  | let param_ty = Ty::new_param(ctx.interner, param_id, idx, p.name.clone()); | 
|  | if explicitly_unsized_tys.contains(¶m_ty) { | 
|  | continue; | 
|  | } | 
|  | let trait_ref = TraitRef::new_from_args( | 
|  | ctx.interner, | 
|  | sized_trait.into(), | 
|  | GenericArgs::new_from_iter(ctx.interner, [param_ty.into()]), | 
|  | ); | 
|  | let clause = Clause(Predicate::new( | 
|  | ctx.interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause( | 
|  | rustc_type_ir::ClauseKind::Trait(TraitPredicate { | 
|  | trait_ref, | 
|  | polarity: rustc_type_ir::PredicatePolarity::Positive, | 
|  | }), | 
|  | )), | 
|  | )); | 
|  | clauses.push(clause); | 
|  | } | 
|  |  | 
|  | if let Some(g) = generics.parent { | 
|  | generics = crate::next_solver::generics::generics(db, g.into()); | 
|  | def_id = g; | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | let clauses = rustc_type_ir::elaborate::elaborate(ctx.interner, clauses); | 
|  | let clauses = Clauses::new_from_iter(ctx.interner, clauses); | 
|  | let env = ParamEnv { clauses }; | 
|  |  | 
|  | TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env) | 
|  | } | 
|  |  | 
|  | #[derive(Copy, Clone, Debug)] | 
|  | pub(crate) enum PredicateFilter { | 
|  | SelfTrait, | 
|  | All, | 
|  | } | 
|  |  | 
|  | /// Resolve the where clause(s) of an item with generics. | 
|  | #[tracing::instrument(skip(db))] | 
|  | pub(crate) fn generic_predicates_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | ) -> GenericPredicates<'db> { | 
|  | generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true).0 | 
|  | } | 
|  |  | 
|  | pub(crate) fn generic_predicates_without_parent_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | ) -> GenericPredicates<'db> { | 
|  | generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def).0 | 
|  | } | 
|  |  | 
|  | /// Resolve the where clause(s) of an item with generics, | 
|  | /// except the ones inherited from the parent | 
|  | pub(crate) fn generic_predicates_without_parent_with_diagnostics_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | ) -> (GenericPredicates<'db>, Diagnostics) { | 
|  | generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def) | 
|  | } | 
|  |  | 
|  | /// Resolve the where clause(s) of an item with generics, | 
|  | /// with a given filter | 
|  | #[tracing::instrument(skip(db, filter), ret)] | 
|  | pub(crate) fn generic_predicates_filtered_by<'db, F>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | predicate_filter: PredicateFilter, | 
|  | filter: F, | 
|  | ) -> (GenericPredicates<'db>, Diagnostics) | 
|  | where | 
|  | F: Fn(GenericDefId) -> bool, | 
|  | { | 
|  | let generics = generics(db, def); | 
|  | let resolver = def.resolver(db); | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | generics.store(), | 
|  | def, | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  |  | 
|  | let mut predicates = Vec::new(); | 
|  | for maybe_parent_generics in | 
|  | std::iter::successors(Some(&generics), |generics| generics.parent_generics()) | 
|  | { | 
|  | ctx.store = maybe_parent_generics.store(); | 
|  | for pred in maybe_parent_generics.where_predicates() { | 
|  | tracing::debug!(?pred); | 
|  | if filter(maybe_parent_generics.def()) { | 
|  | // We deliberately use `generics` and not `maybe_parent_generics` here. This is not a mistake! | 
|  | // If we use the parent generics | 
|  | predicates.extend(ctx.lower_where_predicate( | 
|  | pred, | 
|  | false, | 
|  | maybe_parent_generics, | 
|  | predicate_filter, | 
|  | )); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | let explicitly_unsized_tys = ctx.unsized_types; | 
|  |  | 
|  | let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); | 
|  | if let Some(sized_trait) = sized_trait { | 
|  | let (mut generics, mut def_id) = | 
|  | (crate::next_solver::generics::generics(db, def.into()), def); | 
|  | loop { | 
|  | if filter(def_id) { | 
|  | let self_idx = trait_self_param_idx(db, def_id); | 
|  | for (idx, p) in generics.own_params.iter().enumerate() { | 
|  | if let Some(self_idx) = self_idx | 
|  | && p.index() as usize == self_idx | 
|  | { | 
|  | continue; | 
|  | } | 
|  | let GenericParamId::TypeParamId(param_id) = p.id else { | 
|  | continue; | 
|  | }; | 
|  | let idx = idx as u32 + generics.parent_count as u32; | 
|  | let param_ty = Ty::new_param(interner, param_id, idx, p.name.clone()); | 
|  | if explicitly_unsized_tys.contains(¶m_ty) { | 
|  | continue; | 
|  | } | 
|  | let trait_ref = TraitRef::new_from_args( | 
|  | interner, | 
|  | sized_trait.into(), | 
|  | GenericArgs::new_from_iter(interner, [param_ty.into()]), | 
|  | ); | 
|  | let clause = Clause(Predicate::new( | 
|  | interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause( | 
|  | rustc_type_ir::ClauseKind::Trait(TraitPredicate { | 
|  | trait_ref, | 
|  | polarity: rustc_type_ir::PredicatePolarity::Positive, | 
|  | }), | 
|  | )), | 
|  | )); | 
|  | predicates.push(clause); | 
|  | } | 
|  | } | 
|  |  | 
|  | if let Some(g) = generics.parent { | 
|  | generics = crate::next_solver::generics::generics(db, g.into()); | 
|  | def_id = g; | 
|  | } else { | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // FIXME: rustc gathers more predicates by recursing through resulting trait predicates. | 
|  | // See https://github.com/rust-lang/rust/blob/76c5ed2847cdb26ef2822a3a165d710f6b772217/compiler/rustc_hir_analysis/src/collect/predicates_of.rs#L689-L715 | 
|  |  | 
|  | ( | 
|  | GenericPredicates(predicates.is_empty().not().then(|| predicates.into())), | 
|  | create_diagnostics(ctx.diagnostics), | 
|  | ) | 
|  | } | 
|  |  | 
|  | /// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound. | 
|  | /// Exception is Self of a trait def. | 
|  | fn implicitly_sized_clauses<'a, 'subst, 'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>, | 
|  | args: &'subst GenericArgs<'db>, | 
|  | resolver: &Resolver<'db>, | 
|  | ) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> { | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  | let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?; | 
|  |  | 
|  | let trait_self_idx = trait_self_param_idx(db, def); | 
|  |  | 
|  | Some( | 
|  | args.iter() | 
|  | .enumerate() | 
|  | .filter_map( | 
|  | move |(idx, generic_arg)| { | 
|  | if Some(idx) == trait_self_idx { None } else { Some(generic_arg) } | 
|  | }, | 
|  | ) | 
|  | .filter_map(|generic_arg| generic_arg.as_type()) | 
|  | .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty)) | 
|  | .map(move |self_ty| { | 
|  | let trait_ref = TraitRef::new_from_args( | 
|  | interner, | 
|  | sized_trait.into(), | 
|  | GenericArgs::new_from_iter(interner, [self_ty.into()]), | 
|  | ); | 
|  | Clause(Predicate::new( | 
|  | interner, | 
|  | Binder::dummy(rustc_type_ir::PredicateKind::Clause( | 
|  | rustc_type_ir::ClauseKind::Trait(TraitPredicate { | 
|  | trait_ref, | 
|  | polarity: rustc_type_ir::PredicatePolarity::Positive, | 
|  | }), | 
|  | )), | 
|  | )) | 
|  | }), | 
|  | ) | 
|  | } | 
|  |  | 
|  | pub(crate) fn make_binders<'db, T: rustc_type_ir::TypeVisitable<DbInterner<'db>>>( | 
|  | interner: DbInterner<'db>, | 
|  | generics: &Generics, | 
|  | value: T, | 
|  | ) -> Binder<'db, T> { | 
|  | Binder::bind_with_vars( | 
|  | value, | 
|  | BoundVarKinds::new_from_iter( | 
|  | interner, | 
|  | generics.iter_id().map(|x| match x { | 
|  | hir_def::GenericParamId::ConstParamId(_) => BoundVarKind::Const, | 
|  | hir_def::GenericParamId::TypeParamId(_) => BoundVarKind::Ty(BoundTyKind::Anon), | 
|  | hir_def::GenericParamId::LifetimeParamId(_) => { | 
|  | BoundVarKind::Region(BoundRegionKind::Anon) | 
|  | } | 
|  | }), | 
|  | ), | 
|  | ) | 
|  | } | 
|  |  | 
|  | /// Checks if the provided generic arg matches its expected kind, then lower them via | 
|  | /// provided closures. Use unknown if there was kind mismatch. | 
|  | /// | 
|  | pub(crate) fn lower_generic_arg<'a, 'db, T>( | 
|  | db: &'db dyn HirDatabase, | 
|  | kind_id: GenericParamId, | 
|  | arg: &'a GenericArg, | 
|  | this: &mut T, | 
|  | store: &ExpressionStore, | 
|  | for_type: impl FnOnce(&mut T, TypeRefId) -> Ty<'db> + 'a, | 
|  | for_const: impl FnOnce(&mut T, &ConstRef, Ty<'db>) -> Const<'db> + 'a, | 
|  | for_const_ty_path_fallback: impl FnOnce(&mut T, &Path, Ty<'db>) -> Const<'db> + 'a, | 
|  | for_lifetime: impl FnOnce(&mut T, &LifetimeRefId) -> Region<'db> + 'a, | 
|  | ) -> crate::next_solver::GenericArg<'db> { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | let kind = match kind_id { | 
|  | GenericParamId::TypeParamId(_) => ParamKind::Type, | 
|  | GenericParamId::ConstParamId(id) => { | 
|  | let ty = db.const_param_ty(id); | 
|  | ParamKind::Const(ty) | 
|  | } | 
|  | GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime, | 
|  | }; | 
|  | match (arg, kind) { | 
|  | (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, *type_ref).into(), | 
|  | (GenericArg::Const(c), ParamKind::Const(c_ty)) => { | 
|  | for_const(this, c, c_ty.to_nextsolver(interner)).into() | 
|  | } | 
|  | (GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => { | 
|  | for_lifetime(this, lifetime_ref).into() | 
|  | } | 
|  | (GenericArg::Const(_), ParamKind::Type) => Ty::new_error(interner, ErrorGuaranteed).into(), | 
|  | (GenericArg::Lifetime(_), ParamKind::Type) => { | 
|  | Ty::new_error(interner, ErrorGuaranteed).into() | 
|  | } | 
|  | (GenericArg::Type(t), ParamKind::Const(c_ty)) => match &store[*t] { | 
|  | TypeRef::Path(p) => { | 
|  | for_const_ty_path_fallback(this, p, c_ty.to_nextsolver(interner)).into() | 
|  | } | 
|  | _ => unknown_const_as_generic(c_ty.to_nextsolver(interner)), | 
|  | }, | 
|  | (GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => { | 
|  | unknown_const(c_ty.to_nextsolver(interner)).into() | 
|  | } | 
|  | (GenericArg::Type(_), ParamKind::Lifetime) => Region::error(interner).into(), | 
|  | (GenericArg::Const(_), ParamKind::Lifetime) => Region::error(interner).into(), | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 
|  | pub struct GenericDefaults<'db>( | 
|  | Option<Arc<[Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>>]>>, | 
|  | ); | 
|  |  | 
|  | impl<'db> GenericDefaults<'db> { | 
|  | #[inline] | 
|  | pub fn get(&self, idx: usize) -> Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>> { | 
|  | self.0.as_ref()?[idx] | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn generic_defaults_query( | 
|  | db: &dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | ) -> GenericDefaults<'_> { | 
|  | db.generic_defaults_ns_with_diagnostics(def).0 | 
|  | } | 
|  |  | 
|  | /// Resolve the default type params from generics. | 
|  | /// | 
|  | /// Diagnostics are only returned for this `GenericDefId` (returned defaults include parents). | 
|  | pub(crate) fn generic_defaults_with_diagnostics_query( | 
|  | db: &dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | ) -> (GenericDefaults<'_>, Diagnostics) { | 
|  | let generic_params = generics(db, def); | 
|  | if generic_params.is_empty() { | 
|  | return (GenericDefaults(None), None); | 
|  | } | 
|  | let resolver = def.resolver(db); | 
|  |  | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | generic_params.store(), | 
|  | def, | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ) | 
|  | .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed); | 
|  | let mut idx = 0; | 
|  | let mut has_any_default = false; | 
|  | let mut defaults = generic_params | 
|  | .iter_parents_with_store() | 
|  | .map(|((id, p), store)| { | 
|  | ctx.store = store; | 
|  | let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params); | 
|  | has_any_default |= has_default; | 
|  | idx += 1; | 
|  | result | 
|  | }) | 
|  | .collect::<Vec<_>>(); | 
|  | ctx.diagnostics.clear(); // Don't include diagnostics from the parent. | 
|  | defaults.extend(generic_params.iter_self().map(|(id, p)| { | 
|  | let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params); | 
|  | has_any_default |= has_default; | 
|  | idx += 1; | 
|  | result | 
|  | })); | 
|  | let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics)); | 
|  | let defaults = if has_any_default { | 
|  | GenericDefaults(Some(Arc::from_iter(defaults))) | 
|  | } else { | 
|  | GenericDefaults(None) | 
|  | }; | 
|  | return (defaults, diagnostics); | 
|  |  | 
|  | fn handle_generic_param<'db>( | 
|  | ctx: &mut TyLoweringContext<'db, '_>, | 
|  | idx: usize, | 
|  | id: GenericParamId, | 
|  | p: GenericParamDataRef<'_>, | 
|  | generic_params: &Generics, | 
|  | ) -> (Option<EarlyBinder<'db, crate::next_solver::GenericArg<'db>>>, bool) { | 
|  | // Each default can only refer to previous parameters. | 
|  | // Type variable default referring to parameter coming | 
|  | // after it is forbidden. | 
|  | ctx.disallow_params_after(idx as u32); | 
|  | match p { | 
|  | GenericParamDataRef::TypeParamData(p) => { | 
|  | let ty = p.default.map(|ty| ctx.lower_ty(ty)); | 
|  | (ty.map(|ty| EarlyBinder::bind(ty.into())), p.default.is_some()) | 
|  | } | 
|  | GenericParamDataRef::ConstParamData(p) => { | 
|  | let GenericParamId::ConstParamId(id) = id else { | 
|  | unreachable!("Unexpected lifetime or type argument") | 
|  | }; | 
|  |  | 
|  | let mut val = p.default.map(|c| { | 
|  | let param_ty = ctx.lower_ty(p.ty); | 
|  | let c = ctx.lower_const(c, param_ty); | 
|  | c.into() | 
|  | }); | 
|  | (val.map(EarlyBinder::bind), p.default.is_some()) | 
|  | } | 
|  | GenericParamDataRef::LifetimeParamData(_) => (None, false), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | pub(crate) fn generic_defaults_with_diagnostics_cycle_result( | 
|  | _db: &dyn HirDatabase, | 
|  | _def: GenericDefId, | 
|  | ) -> (GenericDefaults<'_>, Diagnostics) { | 
|  | (GenericDefaults(None), None) | 
|  | } | 
|  |  | 
|  | /// Build the signature of a callable item (function, struct or enum variant). | 
|  | pub(crate) fn callable_item_signature_query<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: CallableDefId, | 
|  | ) -> EarlyBinder<'db, PolyFnSig<'db>> { | 
|  | match def { | 
|  | CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f), | 
|  | CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s), | 
|  | CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e), | 
|  | } | 
|  | } | 
|  |  | 
|  | fn fn_sig_for_fn<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: FunctionId, | 
|  | ) -> EarlyBinder<'db, PolyFnSig<'db>> { | 
|  | let data = db.function_signature(def); | 
|  | let resolver = def.resolver(db); | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  | let mut ctx_params = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &data.store, | 
|  | def.into(), | 
|  | LifetimeElisionKind::for_fn_params(&data), | 
|  | ); | 
|  | let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr)); | 
|  |  | 
|  | let ret = match data.ret_type { | 
|  | Some(ret_type) => { | 
|  | let mut ctx_ret = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &data.store, | 
|  | def.into(), | 
|  | LifetimeElisionKind::for_fn_ret(interner), | 
|  | ) | 
|  | .with_impl_trait_mode(ImplTraitLoweringMode::Opaque); | 
|  | ctx_ret.lower_ty(ret_type) | 
|  | } | 
|  | None => Ty::new_tup(interner, &[]), | 
|  | }; | 
|  |  | 
|  | let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret))); | 
|  | // If/when we track late bound vars, we need to switch this to not be `dummy` | 
|  | EarlyBinder::bind(rustc_type_ir::Binder::dummy(FnSig { | 
|  | abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol), | 
|  | c_variadic: data.is_varargs(), | 
|  | safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe }, | 
|  | inputs_and_output, | 
|  | })) | 
|  | } | 
|  |  | 
|  | fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | let args = GenericArgs::identity_for_item(interner, adt.into()); | 
|  | let ty = Ty::new_adt(interner, adt, args); | 
|  | EarlyBinder::bind(ty) | 
|  | } | 
|  |  | 
|  | fn fn_sig_for_struct_constructor<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: StructId, | 
|  | ) -> EarlyBinder<'db, PolyFnSig<'db>> { | 
|  | let field_tys = db.field_types_ns(def.into()); | 
|  | let params = field_tys.iter().map(|(_, ty)| ty.skip_binder()); | 
|  | let ret = type_for_adt(db, def.into()).skip_binder(); | 
|  |  | 
|  | let inputs_and_output = | 
|  | Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); | 
|  | EarlyBinder::bind(Binder::dummy(FnSig { | 
|  | abi: FnAbi::RustCall, | 
|  | c_variadic: false, | 
|  | safety: Safety::Safe, | 
|  | inputs_and_output, | 
|  | })) | 
|  | } | 
|  |  | 
|  | fn fn_sig_for_enum_variant_constructor<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | def: EnumVariantId, | 
|  | ) -> EarlyBinder<'db, PolyFnSig<'db>> { | 
|  | let field_tys = db.field_types_ns(def.into()); | 
|  | let params = field_tys.iter().map(|(_, ty)| ty.skip_binder()); | 
|  | let parent = def.lookup(db).parent; | 
|  | let ret = type_for_adt(db, parent.into()).skip_binder(); | 
|  |  | 
|  | let inputs_and_output = | 
|  | Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); | 
|  | EarlyBinder::bind(Binder::dummy(FnSig { | 
|  | abi: FnAbi::RustCall, | 
|  | c_variadic: false, | 
|  | safety: Safety::Safe, | 
|  | inputs_and_output, | 
|  | })) | 
|  | } | 
|  |  | 
|  | // FIXME(next-solver): should merge this with `explicit_item_bounds` in some way | 
|  | pub(crate) fn associated_ty_item_bounds<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | type_alias: TypeAliasId, | 
|  | ) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> { | 
|  | let trait_ = match type_alias.lookup(db).container { | 
|  | ItemContainerId::TraitId(t) => t, | 
|  | _ => panic!("associated type not in trait"), | 
|  | }; | 
|  |  | 
|  | let type_alias_data = db.type_alias_signature(type_alias); | 
|  | let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); | 
|  | let interner = DbInterner::new_with(db, Some(resolver.krate()), None); | 
|  | let mut ctx = TyLoweringContext::new( | 
|  | db, | 
|  | &resolver, | 
|  | &type_alias_data.store, | 
|  | type_alias.into(), | 
|  | LifetimeElisionKind::AnonymousReportError, | 
|  | ); | 
|  | // FIXME: we should never create non-existential predicates in the first place | 
|  | // For now, use an error type so we don't run into dummy binder issues | 
|  | let self_ty = Ty::new_error(interner, ErrorGuaranteed); | 
|  |  | 
|  | let mut bounds = Vec::new(); | 
|  | for bound in &type_alias_data.bounds { | 
|  | ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| { | 
|  | if let Some(bound) = pred | 
|  | .kind() | 
|  | .map_bound(|c| match c { | 
|  | rustc_type_ir::ClauseKind::Trait(t) => { | 
|  | let id = t.def_id(); | 
|  | let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO); | 
|  | if is_auto { | 
|  | Some(ExistentialPredicate::AutoTrait(t.def_id())) | 
|  | } else { | 
|  | Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args( | 
|  | interner, | 
|  | t.def_id(), | 
|  | GenericArgs::new_from_iter( | 
|  | interner, | 
|  | t.trait_ref.args.iter().skip(1), | 
|  | ), | 
|  | ))) | 
|  | } | 
|  | } | 
|  | rustc_type_ir::ClauseKind::Projection(p) => Some( | 
|  | ExistentialPredicate::Projection(ExistentialProjection::new_from_args( | 
|  | interner, | 
|  | p.def_id(), | 
|  | GenericArgs::new_from_iter( | 
|  | interner, | 
|  | p.projection_term.args.iter().skip(1), | 
|  | ), | 
|  | p.term, | 
|  | )), | 
|  | ), | 
|  | rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => None, | 
|  | rustc_type_ir::ClauseKind::RegionOutlives(_) | 
|  | | rustc_type_ir::ClauseKind::ConstArgHasType(_, _) | 
|  | | rustc_type_ir::ClauseKind::WellFormed(_) | 
|  | | rustc_type_ir::ClauseKind::ConstEvaluatable(_) | 
|  | | rustc_type_ir::ClauseKind::HostEffect(_) | 
|  | | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(), | 
|  | }) | 
|  | .transpose() | 
|  | { | 
|  | bounds.push(bound); | 
|  | } | 
|  | }); | 
|  | } | 
|  |  | 
|  | if !ctx.unsized_types.contains(&self_ty) { | 
|  | let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()); | 
|  | let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new( | 
|  | interner, | 
|  | trait_.into(), | 
|  | [] as [crate::next_solver::GenericArg<'_>; 0], | 
|  | ))); | 
|  | bounds.push(sized_clause); | 
|  | bounds.shrink_to_fit(); | 
|  | } | 
|  |  | 
|  | EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds)) | 
|  | } | 
|  |  | 
|  | pub(crate) fn associated_type_by_name_including_super_traits<'db>( | 
|  | db: &'db dyn HirDatabase, | 
|  | trait_ref: TraitRef<'db>, | 
|  | name: &Name, | 
|  | ) -> Option<(TraitRef<'db>, TypeAliasId)> { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| { | 
|  | let trait_id = t.as_ref().skip_binder().def_id.0; | 
|  | let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?; | 
|  | Some((t.skip_binder(), assoc_type)) | 
|  | }) | 
|  | } | 
|  |  | 
|  | pub fn associated_type_shorthand_candidates( | 
|  | db: &dyn HirDatabase, | 
|  | def: GenericDefId, | 
|  | res: TypeNs, | 
|  | mut cb: impl FnMut(&Name, TypeAliasId) -> bool, | 
|  | ) -> Option<TypeAliasId> { | 
|  | let interner = DbInterner::new_with(db, None, None); | 
|  | named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| { | 
|  | cb(name, id).then_some(id) | 
|  | }) | 
|  | } | 
|  |  | 
|  | #[tracing::instrument(skip(interner, check_alias))] | 
|  | fn named_associated_type_shorthand_candidates<'db, R>( | 
|  | interner: DbInterner<'db>, | 
|  | // If the type parameter is defined in an impl and we're in a method, there | 
|  | // might be additional where clauses to consider | 
|  | def: GenericDefId, | 
|  | res: TypeNs, | 
|  | assoc_name: Option<Name>, | 
|  | mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option<R>, | 
|  | ) -> Option<R> { | 
|  | let db = interner.db; | 
|  | let mut search = |t: TraitRef<'db>| -> Option<R> { | 
|  | let trait_id = t.def_id.0; | 
|  | let mut checked_traits = FxHashSet::default(); | 
|  | let mut check_trait = |trait_ref: TraitRef<'db>| { | 
|  | let trait_id = trait_ref.def_id.0; | 
|  | let name = &db.trait_signature(trait_id).name; | 
|  | tracing::debug!(?trait_id, ?name); | 
|  | if !checked_traits.insert(trait_id) { | 
|  | return None; | 
|  | } | 
|  | let data = trait_id.trait_items(db); | 
|  |  | 
|  | tracing::debug!(?data.items); | 
|  | for (name, assoc_id) in &data.items { | 
|  | if let &AssocItemId::TypeAliasId(alias) = assoc_id | 
|  | && let Some(ty) = check_alias(name, trait_ref, alias) | 
|  | { | 
|  | return Some(ty); | 
|  | } | 
|  | } | 
|  | None | 
|  | }; | 
|  | let mut stack: SmallVec<[_; 4]> = smallvec![t]; | 
|  | while let Some(trait_ref) = stack.pop() { | 
|  | if let Some(alias) = check_trait(trait_ref) { | 
|  | return Some(alias); | 
|  | } | 
|  | for pred in generic_predicates_filtered_by( | 
|  | db, | 
|  | GenericDefId::TraitId(trait_ref.def_id.0), | 
|  | PredicateFilter::SelfTrait, | 
|  | // We are likely in the midst of lowering generic predicates of `def`. | 
|  | // So, if we allow `pred == def` we might fall into an infinite recursion. | 
|  | // Actually, we have already checked for the case `pred == def` above as we started | 
|  | // with a stack including `trait_id` | 
|  | |pred| pred != def && pred == GenericDefId::TraitId(trait_ref.def_id.0), | 
|  | ) | 
|  | .0 | 
|  | .deref() | 
|  | { | 
|  | tracing::debug!(?pred); | 
|  | let sup_trait_ref = match pred.kind().skip_binder() { | 
|  | rustc_type_ir::ClauseKind::Trait(pred) => pred.trait_ref, | 
|  | _ => continue, | 
|  | }; | 
|  | let sup_trait_ref = | 
|  | EarlyBinder::bind(sup_trait_ref).instantiate(interner, trait_ref.args); | 
|  | stack.push(sup_trait_ref); | 
|  | } | 
|  | tracing::debug!(?stack); | 
|  | } | 
|  |  | 
|  | None | 
|  | }; | 
|  |  | 
|  | match res { | 
|  | TypeNs::SelfType(impl_id) => { | 
|  | let trait_ref = db.impl_trait(impl_id)?; | 
|  |  | 
|  | // FIXME(next-solver): same method in `lower` checks for impl or not | 
|  | // Is that needed here? | 
|  |  | 
|  | // we're _in_ the impl -- the binders get added back later. Correct, | 
|  | // but it would be nice to make this more explicit | 
|  | search(trait_ref.skip_binder()) | 
|  | } | 
|  | TypeNs::GenericParam(param_id) => { | 
|  | // Handle `Self::Type` referring to own associated type in trait definitions | 
|  | // This *must* be done first to avoid cycles with | 
|  | // `generic_predicates_for_param`, but not sure that it's sufficient, | 
|  | if let GenericDefId::TraitId(trait_id) = param_id.parent() { | 
|  | let trait_name = &db.trait_signature(trait_id).name; | 
|  | tracing::debug!(?trait_name); | 
|  | let trait_generics = generics(db, trait_id.into()); | 
|  | tracing::debug!(?trait_generics); | 
|  | if trait_generics[param_id.local_id()].is_trait_self() { | 
|  | let args = crate::next_solver::GenericArgs::identity_for_item( | 
|  | interner, | 
|  | trait_id.into(), | 
|  | ); | 
|  | let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args); | 
|  | tracing::debug!(?args, ?trait_ref); | 
|  | return search(trait_ref); | 
|  | } | 
|  | } | 
|  |  | 
|  | let predicates = | 
|  | db.generic_predicates_for_param_ns(def, param_id.into(), assoc_name.clone()); | 
|  | predicates | 
|  | .iter() | 
|  | .find_map(|pred| match (*pred).kind().skip_binder() { | 
|  | rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate), | 
|  | _ => None, | 
|  | }) | 
|  | .and_then(|trait_predicate| { | 
|  | let trait_ref = trait_predicate.trait_ref; | 
|  | assert!( | 
|  | !trait_ref.has_escaping_bound_vars(), | 
|  | "FIXME unexpected higher-ranked trait bound" | 
|  | ); | 
|  | search(trait_ref) | 
|  | }) | 
|  | } | 
|  | _ => None, | 
|  | } | 
|  | } |