1pub(crate) mod diagnostics;
9pub(crate) mod path;
10
11use std::{cell::OnceCell, iter, mem, ops::Deref, sync::OnceLock};
12
13use either::Either;
14use hir_def::{
15 AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, EnumId, EnumVariantId,
16 ExpressionStoreOwnerId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
17 ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TraitId,
18 TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId,
19 builtin_type::BuiltinType,
20 expr_store::{ExpressionStore, path::Path},
21 hir::{
22 ExprId, PatId,
23 generics::{
24 GenericParamDataRef, GenericParams, LocalTypeOrConstParamId, TypeOrConstParamData,
25 TypeParamProvenance, WherePredicate,
26 },
27 },
28 item_tree::FieldsShape,
29 lang_item::LangItems,
30 resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
31 signatures::{
32 ConstSignature, FunctionSignature, ImplSignature, StaticSignature, StructSignature,
33 TraitFlags, TraitSignature, TypeAliasFlags, TypeAliasSignature,
34 },
35 type_ref::{
36 ConstRef, FnType, LifetimeRef, LifetimeRefId, PathId, TraitBoundModifier,
37 TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
38 },
39};
40use hir_expand::name::Name;
41use la_arena::{Arena, ArenaMap, Idx};
42use path::{PathDiagnosticCallback, PathLoweringContext};
43use rustc_abi::ExternAbi;
44use rustc_ast_ir::Mutability;
45use rustc_hash::FxHashSet;
46use rustc_type_ir::{
47 AliasTyKind, BoundRegion, BoundRegionKind, BoundTyKind, BoundVar, BoundVariableKind,
48 DebruijnIndex, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
49 Interner, OutlivesPredicate, TermKind, TyKind, TypeFoldable, TypeVisitableExt, Upcast,
50 UpcastFrom, elaborate,
51 inherent::{Clause as _, GenericArgs as _, IntoKind as _, Region as _, Ty as _},
52};
53use salsa::SalsaValue;
54use smallvec::SmallVec;
55use stdx::{impl_from, never};
56use thin_vec::ThinVec;
57use tracing::debug;
58
59pub use hir_def::LoweringMode;
60pub(crate) use hir_def::TrackedStructToken;
61
62use crate::{
63 ImplTraitId, Span, TyLoweringDiagnostic,
64 consteval::{create_anon_const, path_to_const},
65 db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId},
66 generics::{Generics, SingleGenerics, generics},
67 infer::unify::InferenceTable,
68 next_solver::{
69 AliasTy, Binder, BoundExistentialPredicates, BoundVarKinds, Clause, ClauseKind, Clauses,
70 Const, ConstKind, DbInterner, DefaultAny, EarlyBinder, EarlyParamRegion, ErrorGuaranteed,
71 FnSigKind, FxIndexMap, GenericArg, GenericArgs, ParamConst, ParamEnv, PatList, Pattern,
72 PolyFnSig, Predicate, Region, StoredClauses, StoredConst, StoredEarlyBinder,
73 StoredGenericArg, StoredGenericArgs, StoredPolyFnSig, StoredTraitRef, StoredTy,
74 TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety, mk_param,
75 util::BottomUpFolder,
76 },
77};
78
79pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId);
80
81#[derive(PartialEq, Eq, Debug, Hash, SalsaValue)]
82pub struct WithDefinedOpaques<T> {
83 value: T,
84 impl_traits: Option<Box<Arena<ImplTrait>>>,
85}
86
87#[derive(PartialEq, Eq, Debug, Hash)]
88pub struct ImplTrait {
89 pub(crate) predicates: StoredEarlyBinder<StoredClauses>,
90 pub(crate) assoc_ty_bounds_start: u32,
91}
92
93pub type ImplTraitIdx = Idx<ImplTrait>;
94
95#[derive(Debug, Default)]
96struct ImplTraitLoweringState {
97 mode: ImplTraitLoweringMode,
101 opaque_type_data: Arena<ImplTrait>,
103}
104
105impl ImplTraitLoweringState {
106 fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState {
107 Self { mode, opaque_type_data: Arena::new() }
108 }
109}
110
111#[derive(Debug, Clone, Copy)]
112pub enum LifetimeElisionKind<'db> {
113 AnonymousCreateParameter { report_in_path: bool },
128
129 Elided(Region<'db>),
131
132 AnonymousReportError,
136
137 StaticIfNoLifetimeInScope { only_lint: bool },
141
142 ElisionFailure,
144
145 Infer,
147}
148
149impl<'db> LifetimeElisionKind<'db> {
150 #[inline]
151 pub(crate) fn for_const(
152 interner: DbInterner<'db>,
153 const_parent: ItemContainerId,
154 ) -> LifetimeElisionKind<'db> {
155 match const_parent {
156 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
157 LifetimeElisionKind::Elided(Region::new_static(interner))
158 }
159 ItemContainerId::ImplId(_) => {
160 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true }
161 }
162 ItemContainerId::TraitId(_) => {
163 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false }
164 }
165 }
166 }
167
168 #[inline]
169 pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> {
170 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() }
171 }
172
173 #[inline]
174 pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> {
175 LifetimeElisionKind::Elided(Region::error(interner))
177 }
178}
179
180#[derive(Clone, Copy, PartialEq, Debug)]
181pub(crate) enum GenericPredicateSource {
182 SelfOnly,
183 AssocTyBound,
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq)]
187pub(crate) enum ForbidParamsAfterReason {
188 LoweringParamDefault,
191 AnonConst,
194 ConstParamTy,
196}
197
198pub trait TyLoweringInferVarsCtx<'db> {
199 fn next_ty_var(&mut self, span: Span) -> Ty<'db>;
200 fn next_const_var(&mut self, span: Span) -> Const<'db>;
201 fn next_region_var(&mut self, span: Span) -> Region<'db>;
202
203 #[expect(private_interfaces)]
204 fn as_table(&mut self) -> Option<&mut InferenceTable<'db>> {
205 None
206 }
207}
208
209pub struct TyLoweringContext<'db, 'a> {
210 pub db: &'db dyn HirDatabase,
211 pub(crate) interner: DbInterner<'db>,
212 types: &'db crate::next_solver::DefaultAny<'db>,
213 lang_items: &'db LangItems,
214 resolver: &'a Resolver<'db>,
215 store: &'db ExpressionStore,
216 def: ExpressionStoreOwnerId,
217 generic_def: GenericDefId,
218 generics: &'a OnceCell<Generics<'db>>,
219 in_binders: DebruijnIndex,
220 impl_trait_mode: ImplTraitLoweringState,
221 interning_mode: LoweringMode,
222 pub(crate) unsized_types: FxHashSet<Ty<'db>>,
224 pub(crate) diagnostics: ThinVec<TyLoweringDiagnostic>,
225 lifetime_elision: LifetimeElisionKind<'db>,
226 forbid_params_after: Option<u32>,
227 forbid_params_after_reason: ForbidParamsAfterReason,
228 pub(crate) defined_anon_consts: ThinVec<AnonConstId<'db>>,
229 infer_vars: Option<&'a mut dyn TyLoweringInferVarsCtx<'db>>,
230 is_lowering_impl_trait_bounds: bool,
231 bound_vars: Vec<(Vec<Name>, BoundVarKinds<'db>)>,
232 lifetime_lowering_mode: LifetimeLoweringMode,
233}
234
235impl<'db, 'a> TyLoweringContext<'db, 'a> {
236 pub fn new(
237 db: &'db dyn HirDatabase,
238 resolver: &'a Resolver<'db>,
239 store: &'db ExpressionStore,
240 def: ExpressionStoreOwnerId,
241 generic_def: GenericDefId,
242 generics: &'a OnceCell<Generics<'db>>,
243 lifetime_elision: LifetimeElisionKind<'db>,
244 lifetime_lowering_mode: LifetimeLoweringMode,
245 ) -> Self {
246 let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
247 let in_binders = DebruijnIndex::ZERO;
248 let interner = DbInterner::new_with(db, resolver.krate());
249 let bound_vars =
250 vec![(Vec::new(), TyLoweringContext::bound_vars(db, interner, generic_def, generics))];
251 Self {
252 db,
253 interner,
255 types: crate::next_solver::default_types(db),
256 lang_items: interner.lang_items(),
257 resolver,
258 def,
259 generic_def,
260 generics,
261 store,
262 in_binders,
263 impl_trait_mode,
264 interning_mode: LoweringMode::Analysis,
265 unsized_types: FxHashSet::default(),
266 diagnostics: ThinVec::new(),
267 lifetime_elision,
268 forbid_params_after: None,
269 forbid_params_after_reason: ForbidParamsAfterReason::AnonConst,
270 defined_anon_consts: ThinVec::new(),
271 infer_vars: None,
272 is_lowering_impl_trait_bounds: false,
273 bound_vars,
274 lifetime_lowering_mode,
275 }
276 }
277
278 pub(crate) fn set_lifetime_elision(&mut self, lifetime_elision: LifetimeElisionKind<'db>) {
279 self.lifetime_elision = lifetime_elision;
280 }
281
282 pub(crate) fn set_owner(&mut self, owner: &'a SingleGenerics<'db>) {
283 self.store = owner.store();
284 self.def = ExpressionStoreOwnerId::Signature(owner.def());
285 }
286
287 pub(crate) fn with_interning_mode(mut self, interning_mode: LoweringMode) -> Self {
288 self.interning_mode = interning_mode;
289 self
290 }
291
292 pub(crate) fn with_debruijn<T>(
293 &mut self,
294 debruijn: DebruijnIndex,
295 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
296 ) -> T {
297 let old_debruijn = mem::replace(&mut self.in_binders, debruijn);
298 let result = f(self);
299 self.in_binders = old_debruijn;
300 result
301 }
302
303 pub(crate) fn with_shifted_in<T>(
304 &mut self,
305 binder: &[Name],
306 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
307 ) -> (T, BoundVarKinds<'db>) {
308 self.push_bound_vars(binder);
309 let res = self.with_debruijn(self.in_binders.shifted_in(1), f);
310 let bound_vars = self.pop_bound_vars();
311 (res, bound_vars)
312 }
313
314 pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
315 Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self }
316 }
317
318 pub(crate) fn forbid_params_after(&mut self, index: u32, reason: ForbidParamsAfterReason) {
319 self.forbid_params_after = Some(index);
320 self.forbid_params_after_reason = reason;
321 }
322
323 pub fn with_infer_vars_behavior(
324 mut self,
325 behavior: Option<&'a mut dyn TyLoweringInferVarsCtx<'db>>,
326 ) -> Self {
327 self.infer_vars = behavior;
328 self
329 }
330
331 pub(crate) fn push_diagnostic(&mut self, diagnostic: TyLoweringDiagnostic) {
332 self.diagnostics.push(diagnostic);
333 }
334
335 fn push_infer_vars_not_allowed(&mut self, span: Span) {
336 if !span.is_dummy() {
337 self.push_diagnostic(TyLoweringDiagnostic::InferVarsNotAllowed { source: span });
338 }
339 }
340
341 #[track_caller]
342 pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> {
343 self.infer_vars.as_mut().unwrap().as_table().unwrap()
344 }
345
346 fn next_ty_var(&mut self, span: Span) -> Ty<'db> {
347 match &mut self.infer_vars {
348 Some(infer_vars) => infer_vars.next_ty_var(span),
349 None => {
350 self.push_infer_vars_not_allowed(span);
351 self.types.types.error
352 }
353 }
354 }
355
356 fn next_const_var(&mut self, span: Span) -> Const<'db> {
357 match &mut self.infer_vars {
358 Some(infer_vars) => infer_vars.next_const_var(span),
359 None => {
360 self.push_infer_vars_not_allowed(span);
361 self.types.consts.error
362 }
363 }
364 }
365
366 fn next_region_var(&mut self, span: Span) -> Region<'db> {
367 match &mut self.infer_vars {
368 Some(infer_vars) => infer_vars.next_region_var(span),
369 None => {
370 self.push_infer_vars_not_allowed(span);
371 self.types.regions.error
372 }
373 }
374 }
375
376 fn push_bound_vars(&mut self, binder: &[Name]) {
377 let bound_vars = BoundVarKinds::new_from_iter(
378 self.interner,
379 binder.iter().map(|_| {
380 BoundVariableKind::Region(BoundRegionKind::Named(self.generic_def.into()))
381 }),
382 );
383 self.bound_vars.push((binder.to_vec(), bound_vars));
384 }
385
386 fn pop_bound_vars(&mut self) -> BoundVarKinds<'db> {
387 self.bound_vars.pop().unwrap().1
388 }
389
390 fn peek_bound_vars(&self) -> BoundVarKinds<'db> {
391 self.bound_vars.last().unwrap().1
392 }
393
394 fn bound_vars(
395 db: &'db dyn HirDatabase,
396 interner: DbInterner<'db>,
397 def: GenericDefId,
398 generic: &'a OnceCell<Generics<'db>>,
399 ) -> BoundVarKinds<'db> {
400 let def_id = def.into();
401
402 let generics = generic.get_or_init(|| generics(db, def));
403 let args = generics.iter_self_late_bound().map(|(_, data)| match data {
404 GenericParamDataRef::TypeParamData(..) => {
405 BoundVariableKind::Ty(BoundTyKind::Param(def_id))
406 }
407 GenericParamDataRef::ConstParamData(..) => BoundVariableKind::Const,
408 GenericParamDataRef::LifetimeParamData(..) => {
409 BoundVariableKind::Region(BoundRegionKind::Named(def_id))
410 }
411 });
412
413 BoundVarKinds::new_from_iter(interner, args)
414 }
415
416 fn take_defined_opaques(&mut self) -> Option<Box<Arena<ImplTrait>>> {
417 if self.impl_trait_mode.opaque_type_data.is_empty() {
418 None
419 } else {
420 self.impl_trait_mode.opaque_type_data.shrink_to_fit();
421 Some(Box::new(mem::take(&mut self.impl_trait_mode.opaque_type_data)))
422 }
423 }
424}
425
426#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
427pub(crate) enum ImplTraitLoweringMode {
428 Opaque,
433 #[default]
435 Disallowed,
436}
437
438#[derive(Clone, Debug, PartialEq, Eq)]
439pub enum LifetimeLoweringMode {
440 Bound,
443 LateParam,
446}
447
448impl<'db, 'a> TyLoweringContext<'db, 'a> {
449 pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
450 self.lower_ty_ext(type_ref).0
451 }
452
453 pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> {
454 self.lower_expr_as_const(const_ref.expr, const_type)
455 }
456
457 pub(crate) fn lower_expr_as_const(
458 &mut self,
459 expr_id: ExprId,
460 const_type: Ty<'db>,
461 ) -> Const<'db> {
462 #[expect(clippy::manual_map, reason = "a `map()` here generates a borrowck error")]
463 let create_var = match &mut self.infer_vars {
464 Some(infer_vars) => Some(
465 (&mut |span| infer_vars.next_const_var(span)) as &mut dyn FnMut(Span) -> Const<'db>,
466 ),
467 None => None,
468 };
469 let konst = create_anon_const(
470 self.interner,
471 self.def,
472 self.store,
473 expr_id,
474 self.resolver,
475 const_type,
476 &|| self.generics.get_or_init(|| generics(self.db, self.generic_def)),
477 create_var,
478 self.interning_mode,
479 self.forbid_params_after,
480 );
481
482 if let Ok(konst) = konst
483 && let ConstKind::Unevaluated(konst) = konst.kind()
484 && let GeneralConstId::AnonConstId(konst) = konst.def.0
485 {
486 self.defined_anon_consts.push(konst);
487 }
488
489 konst.unwrap_or({
490 self.types.consts.error
492 })
493 }
494
495 pub(crate) fn lower_path_as_const(&mut self, path: &Path, _const_type: Ty<'db>) -> Const<'db> {
496 path_to_const(self.db, self.resolver, &|| self.generics(), self.forbid_params_after, path)
497 .unwrap_or({
498 self.types.consts.error
500 })
501 }
502
503 fn generics(&self) -> &Generics<'db> {
504 self.generics.get_or_init(|| generics(self.db, self.generic_def))
505 }
506
507 fn param_index_is_disallowed(&self, index: u32) -> bool {
508 self.forbid_params_after.is_some_and(|disallow_params_after| index >= disallow_params_after)
509 }
510
511 fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> {
512 if self.param_index_is_disallowed(index) {
513 self.types.types.error
515 } else {
516 Ty::new_param(self.interner, id, index)
517 }
518 }
519
520 fn region_param(
521 &mut self,
522 id: LifetimeParamId,
523 index: u32,
524 is_late_bound: bool,
525 ) -> Region<'db> {
526 if self.param_index_is_disallowed(index) {
527 self.types.regions.error
529 } else {
530 if is_late_bound {
531 self.hrtb_region_param(
532 index,
533 DebruijnIndex::from_usize(self.in_binders.as_usize()),
534 id.parent,
535 )
536 } else {
537 Region::new_early_param(self.interner, EarlyParamRegion { id, index })
538 }
539 }
540 }
541
542 fn hrtb_region_param(
543 &self,
544 index: u32,
545 debruijn: DebruijnIndex,
546 parent: GenericDefId,
547 ) -> Region<'db> {
548 if self.param_index_is_disallowed(index) {
549 self.types.regions.error
551 } else {
552 if self.lifetime_lowering_mode == LifetimeLoweringMode::Bound {
553 Region::new_bound(
554 self.interner,
555 debruijn,
556 BoundRegion {
557 var: BoundVar::from_u32(index),
558 kind: BoundRegionKind::Named(parent.into()),
559 },
560 )
561 } else {
562 let solver_def_id = parent.into();
563 Region::new_late_param(
564 self.interner,
565 solver_def_id,
566 BoundRegion {
567 var: BoundVar::from_u32(index),
568 kind: BoundRegionKind::Named(solver_def_id),
569 },
570 )
571 }
572 }
573 }
574
575 #[tracing::instrument(skip(self), ret)]
576 pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) {
577 let interner = self.interner;
578 let mut res = None;
579 let type_ref = &self.store[type_ref_id];
580 tracing::debug!(?type_ref);
581 let ty = match type_ref {
582 TypeRef::Never => self.types.types.never,
583 TypeRef::Tuple(inner) => {
584 let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr));
585 Ty::new_tup_from_iter(interner, inner_tys)
586 }
587 TypeRef::Path(path) => {
588 let (ty, res_) =
589 self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id));
590 res = res_;
591 ty
592 }
593 &TypeRef::TypeParam(type_param_id) => {
594 res = Some(TypeNs::GenericParam(type_param_id));
595
596 let generics = self.generics();
597 let idx = generics.type_or_const_param_idx(type_param_id.into());
598 self.type_param(type_param_id, idx)
599 }
600 &TypeRef::RawPtr(inner, mutability) => {
601 let inner_ty = self.lower_ty(inner);
602 Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability)))
603 }
604 TypeRef::Array(array) => {
605 let inner_ty = self.lower_ty(array.ty);
606 let const_len = self.lower_const(array.len, self.types.types.usize);
607 Ty::new_array_with_const_len(interner, inner_ty, const_len)
608 }
609 &TypeRef::Slice(inner) => {
610 let inner_ty = self.lower_ty(inner);
611 Ty::new_slice(interner, inner_ty)
612 }
613 TypeRef::Reference(ref_) => {
614 let inner_ty = self.lower_ty(ref_.ty);
615 let lifetime =
617 ref_.lifetime.map_or(self.types.regions.error, |lr| self.lower_lifetime(lr));
618 Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability))
619 }
620 TypeRef::Placeholder => self.next_ty_var(type_ref_id.into()),
621 TypeRef::Fn(fn_) => self.lower_fn_ptr(fn_),
622 TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
623 TypeRef::ImplTrait(bounds) => {
624 match self.impl_trait_mode.mode {
625 ImplTraitLoweringMode::Opaque => {
626 let origin = match self.resolver.generic_def() {
627 Some(GenericDefId::FunctionId(it)) => Either::Left(it),
628 Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
629 _ => panic!(
630 "opaque impl trait lowering must be in function or type alias"
631 ),
632 };
633
634 let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait {
638 predicates: StoredEarlyBinder::bind(Clauses::empty(interner).store()),
639 assoc_ty_bounds_start: 0,
640 });
641
642 let impl_trait_id = origin.either(
643 |f| ImplTraitId::ReturnTypeImplTrait(f, idx),
644 |a| ImplTraitId::TypeAliasImplTrait(a, idx),
645 );
646 let opaque_ty_id = InternedOpaqueTyId::new(self.db, impl_trait_id);
647
648 let actual_opaque_type_data = self
658 .with_debruijn(DebruijnIndex::ZERO, |ctx| {
659 ctx.lower_impl_trait(opaque_ty_id, bounds)
660 });
661 self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
662
663 let mut late_bound_index = 0;
664 let args = GenericArgs::for_item(
665 self.interner,
666 opaque_ty_id.into(),
667 |index, param_id, lt_param, _| {
668 if let Some(lt) = lt_param
669 && lt.is_late_bound()
670 && !self.is_lowering_impl_trait_bounds
671 {
672 let GenericParamId::LifetimeParamId(id) = param_id else {
673 unreachable!()
674 };
675 let bound_region_kind =
676 BoundRegionKind::Named(id.parent.into());
677 let region = match self.lifetime_lowering_mode {
678 LifetimeLoweringMode::Bound => Region::new_bound(
679 interner,
680 self.in_binders,
681 BoundRegion {
682 var: BoundVar::from_u32(late_bound_index),
683 kind: bound_region_kind,
684 },
685 ),
686 LifetimeLoweringMode::LateParam => Region::new_late_param(
687 interner,
688 self.generic_def.into(),
689 BoundRegion {
690 var: BoundVar::from_u32(late_bound_index),
691 kind: bound_region_kind,
692 },
693 ),
694 };
695 late_bound_index += 1;
696 return region.into();
697 }
698
699 mk_param(interner, index - late_bound_index, param_id)
700 },
701 );
702 Ty::new_alias(
703 self.interner,
704 AliasTy::new_from_args(
705 self.interner,
706 AliasTyKind::Opaque { def_id: opaque_ty_id.into() },
707 args,
708 ),
709 )
710 }
711 ImplTraitLoweringMode::Disallowed => {
712 self.types.types.error
714 }
715 }
716 }
717 &TypeRef::PatternType(ty, pat) => {
718 let ty = self.lower_ty(ty);
719 let Some(pat) = self.lower_pattern_type(pat, ty) else {
720 return (self.types.types.error, res);
721 };
722 Ty::new_pat(self.interner, ty, pat)
723 }
724 TypeRef::Error => self.types.types.error,
725 };
726 (ty, res)
727 }
728
729 fn lower_pattern_type(&mut self, pat: PatId, ty: Ty<'db>) -> Option<Pattern<'db>> {
730 let pat_kind = match self.store[pat] {
731 hir_def::hir::Pat::Range { start: Some(start), end: Some(end), range_type: _ } => {
732 rustc_type_ir::PatternKind::Range {
733 start: self.lower_expr_as_const(start, ty),
734 end: self.lower_expr_as_const(end, ty),
735 }
736 }
737 hir_def::hir::Pat::NotNull => rustc_type_ir::PatternKind::NotNull,
738 hir_def::hir::Pat::Or(ref pats) => rustc_type_ir::PatternKind::Or(
739 PatList::new_from_iter(
740 self.interner,
741 pats.iter().map(|&pat| self.lower_pattern_type(pat, ty).ok_or(())),
742 )
743 .ok()?,
744 ),
745 hir_def::hir::Pat::Missing => return None,
746 _ => {
747 never!("pattern type can only be Range, NotNull or Or");
748 return None;
749 }
750 };
751 Some(Pattern::new(self.interner, pat_kind))
752 }
753
754 fn lower_fn_ptr(&mut self, fn_: &FnType) -> Ty<'db> {
755 let interner = self.interner;
756 let (params, ret_ty) = fn_.split_params_and_ret();
757 let old_lifetime_elision = self.lifetime_elision;
758 let mut args = Vec::with_capacity(fn_.params.len());
759 let binder = fn_.binder.as_ref().map(|b| b.as_ref()).unwrap_or_default();
760 let (_, binder) = self.with_shifted_in(binder, |ctx: &mut TyLoweringContext<'_, '_>| {
761 ctx.lifetime_elision =
762 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
763 args.extend(params.iter().map(|&(_, tr)| ctx.lower_ty(tr)));
764 ctx.lifetime_elision = LifetimeElisionKind::for_fn_ret(interner);
765 args.push(ctx.lower_ty(ret_ty));
766 });
767 self.lifetime_elision = old_lifetime_elision;
768
769 Ty::new_fn_ptr(
770 interner,
771 Binder::bind_with_vars(
772 FnSig {
773 fn_sig_kind: FnSigKind::new(
774 fn_.abi,
775 if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
776 fn_.is_varargs,
777 ),
779 inputs_and_output: Tys::new_from_slice(&args),
780 },
781 binder,
782 ),
783 )
784 }
785
786 fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option<TypeOrConstParamId> {
790 let type_ref = &self.store[type_ref];
791 let path = match type_ref {
792 TypeRef::Path(path) => path,
793 &TypeRef::TypeParam(idx) => return Some(idx.into()),
794 _ => return None,
795 };
796 if path.type_anchor().is_some() {
797 return None;
798 }
799 if path.segments().len() > 1 {
800 return None;
801 }
802 let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) {
803 Some((it, None, _)) => it,
804 _ => return None,
805 };
806 match resolution {
807 TypeNs::GenericParam(param_id) => Some(param_id.into()),
808 _ => None,
809 }
810 }
811
812 #[inline]
813 fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> {
814 PathDiagnosticCallback {
815 data: Either::Left(PathDiagnosticCallbackData(type_ref)),
816 callback: |data, this, diag| {
817 let type_ref = data.as_ref().left().unwrap().0;
818 this.push_diagnostic(TyLoweringDiagnostic::PathDiagnostic {
819 source: type_ref,
820 diag,
821 })
822 },
823 }
824 }
825
826 #[inline]
827 fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> {
828 PathLoweringContext::new(
829 self,
830 Self::on_path_diagnostic_callback(path_id.type_ref()),
831 &self.store[path_id],
832 )
833 }
834
835 pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option<TypeNs>) {
836 if let Some(type_ref) = path.type_anchor() {
838 let (ty, res) = self.lower_ty_ext(type_ref);
839 let mut ctx = self.at_path(path_id);
840 return ctx.lower_ty_relative_path(ty, res, false, path_id.type_ref().into());
841 }
842
843 let mut ctx = self.at_path(path_id);
844 let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() {
845 Some(it) => it,
846 None => return (self.types.types.error, None),
847 };
848
849 if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
850 let bound = TypeBound::Path(path_id, TraitBoundModifier::None);
852 let ty = self.lower_dyn_trait(&[bound]);
853 return (ty, None);
854 }
855
856 ctx.lower_partly_resolved_path(resolution, false, path_id.type_ref().into())
857 }
858
859 fn lower_trait_ref_from_path(
860 &mut self,
861 path_id: PathId,
862 explicit_self_ty: Ty<'db>,
863 ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> {
864 let mut ctx = self.at_path(path_id);
865 let resolved = match ctx.resolve_path_in_type_ns_fully()? {
866 TypeNs::TraitId(tr) => tr,
868 _ => return None,
869 };
870 Some((
871 ctx.lower_trait_ref_from_resolved_path(
872 resolved,
873 explicit_self_ty,
874 false,
875 path_id.type_ref().into(),
876 ),
877 ctx,
878 ))
879 }
880
881 fn lower_trait_ref(
882 &mut self,
883 trait_ref: &HirTraitRef,
884 explicit_self_ty: Ty<'db>,
885 ) -> Option<TraitRef<'db>> {
886 self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
887 }
888
889 pub(crate) fn lower_where_predicate<'b>(
890 &'b mut self,
891 where_predicate: &'b WherePredicate,
892 ignore_bindings: bool,
893 ) -> impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'db> {
894 let lower_type_outlives = |ctx: &mut TyLoweringContext<'db, '_>,
895 target: &TypeRefId,
896 bound| {
897 let self_ty = ctx.lower_ty(*target);
898 let clause = ctx.lower_type_bound(bound, self_ty, ignore_bindings).collect::<Vec<_>>();
899 Either::Left(clause.into_iter())
900 };
901
902 match where_predicate {
903 WherePredicate::TypeBound { lifetimes, target, bound } => match lifetimes {
904 Some(lifetimes) => {
905 self.with_shifted_in(lifetimes, |ctx| lower_type_outlives(ctx, target, bound)).0
906 }
907 None => lower_type_outlives(self, target, bound),
908 },
909 &WherePredicate::Lifetime { bound, target } => Either::Right(iter::once((
910 Clause(Predicate::new(
911 self.interner,
912 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
913 rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate(
914 self.lower_lifetime(bound),
915 self.lower_lifetime(target),
916 )),
917 )),
918 )),
919 GenericPredicateSource::SelfOnly,
920 ))),
921 }
922 .into_iter()
923 }
924
925 pub(crate) fn lower_type_bound<'b>(
926 &'b mut self,
927 bound: &'b TypeBound,
928 self_ty: Ty<'db>,
929 ignore_bindings: bool,
930 ) -> impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'db> {
931 let interner = self.interner;
932 let meta_sized = self.lang_items.MetaSized;
933 let pointee_sized = self.lang_items.PointeeSized;
934
935 let mut assoc_bounds = None;
936 let mut clause = None;
937
938 let mut lower_path_bound = |ctx: &mut TyLoweringContext<'db, '_>, path| {
939 let binder = ctx.peek_bound_vars();
940
941 if let Some((trait_ref, mut ctx)) = ctx.lower_trait_ref_from_path(path, self_ty) {
942 if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) {
945 } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) {
947 ctx.ty_ctx().unsized_types.insert(self_ty);
949 } else {
950 if !ignore_bindings {
951 assoc_bounds = ctx
952 .assoc_type_bindings_from_type_bound(trait_ref, path.type_ref().into())
953 .map(|iter| iter.collect::<Vec<_>>());
954 }
955 clause = Some(Clause(Predicate::new(
956 interner,
957 Binder::bind_with_vars(
958 rustc_type_ir::PredicateKind::Clause(rustc_type_ir::ClauseKind::Trait(
959 TraitPredicate {
960 trait_ref,
961 polarity: rustc_type_ir::PredicatePolarity::Positive,
962 },
963 )),
964 binder,
965 ),
966 )));
967 }
968 }
969 };
970
971 match bound {
972 &TypeBound::ForLifetime(ref binder, path) => {
973 self.with_shifted_in(binder, |ctx| lower_path_bound(ctx, path)).0
974 }
975 &TypeBound::Path(path, TraitBoundModifier::None) => lower_path_bound(self, path),
976 &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
977 let sized_trait = self.lang_items.Sized;
978 let trait_id = self
982 .lower_trait_ref_from_path(path, self_ty)
983 .map(|(trait_ref, _)| trait_ref.def_id.0);
984 if trait_id == sized_trait {
985 self.unsized_types.insert(self_ty);
986 }
987 }
988 &TypeBound::Lifetime(l) => {
989 let lifetime = self.lower_lifetime(l);
990 let binder = self.peek_bound_vars();
991 clause = Some(Clause(Predicate::new(
992 self.interner,
993 Binder::bind_with_vars(
994 rustc_type_ir::PredicateKind::Clause(
995 rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate(
996 self_ty, lifetime,
997 )),
998 ),
999 binder,
1000 ),
1001 )));
1002 }
1003 TypeBound::Use(_) | TypeBound::Error => {}
1004 }
1005 clause
1006 .into_iter()
1007 .map(|pred| (pred, GenericPredicateSource::SelfOnly))
1008 .chain(assoc_bounds.into_iter().flatten())
1009 }
1010
1011 fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> {
1012 let interner = self.interner;
1013 let dummy_self_ty = self.types.types.dyn_trait_dummy_self;
1014 let mut region = None;
1015 let bounds = 'bounds: {
1021 let mut principal = None;
1022 let mut auto_traits = SmallVec::<[_; 3]>::new();
1023 let mut projections = Vec::new();
1024 let mut had_error = false;
1025
1026 for b in bounds {
1027 let db = self.db;
1028 match b {
1029 TypeBound::Path(_, TraitBoundModifier::None) => {
1030 self.with_shifted_in(&[], |ctx| {
1032 ctx.lower_type_bound(b, dummy_self_ty, false)
1033 })
1034 .0
1035 }
1036 _ => self.lower_type_bound(b, dummy_self_ty, false),
1037 }
1038 .for_each(|(b, _)| {
1039 match b.kind().skip_binder() {
1040 rustc_type_ir::ClauseKind::Trait(t) => {
1041 let id = t.def_id();
1042 let is_auto =
1043 TraitSignature::of(db, id.0).flags.contains(TraitFlags::AUTO);
1044 if is_auto {
1045 auto_traits.push(t.def_id().0);
1046 } else {
1047 if principal.is_some() {
1048 had_error = true;
1050 }
1051 principal = Some(b.kind().rebind(t.trait_ref));
1052 }
1053 }
1054 rustc_type_ir::ClauseKind::Projection(p) => {
1055 projections.push(b.kind().rebind(p));
1056 }
1057 rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => {
1058 if region.is_some() {
1059 had_error = true;
1061 }
1062 region = Some(outlives_predicate.1);
1063 }
1064 rustc_type_ir::ClauseKind::RegionOutlives(_)
1065 | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
1066 | rustc_type_ir::ClauseKind::WellFormed(_)
1067 | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
1068 | rustc_type_ir::ClauseKind::HostEffect(_)
1069 | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
1070 }
1071 })
1072 }
1073
1074 if had_error {
1075 break 'bounds None;
1076 }
1077
1078 if principal.is_none() && auto_traits.is_empty() {
1079 break 'bounds None;
1081 }
1082
1083 auto_traits.sort_unstable();
1085 auto_traits.dedup();
1087
1088 let mut projection_bounds = FxIndexMap::default();
1098 for proj in projections {
1099 let key = (
1100 proj.skip_binder().def_id().0,
1101 interner.anonymize_bound_vars(
1102 proj.map_bound(|proj| proj.projection_term.trait_ref(interner)),
1103 ),
1104 );
1105 if let Some(old_proj) = projection_bounds.insert(key, proj)
1106 && interner.anonymize_bound_vars(proj)
1107 != interner.anonymize_bound_vars(old_proj)
1108 {
1109 }
1111 }
1112
1113 let mut ordered_associated_types = vec![];
1120
1121 if let Some(principal_trait) = principal {
1122 for clause in elaborate::elaborate(
1125 interner,
1126 [Clause::upcast_from(
1127 TraitRef::identity(interner, principal_trait.def_id()),
1128 interner,
1129 )],
1130 )
1131 .filter_only_self()
1132 {
1133 let clause = clause.instantiate_supertrait(interner, principal_trait);
1134 debug!("observing object predicate `{clause:?}`");
1135
1136 let bound_predicate = clause.kind();
1137 match bound_predicate.skip_binder() {
1138 ClauseKind::Trait(pred) => {
1139 let trait_ref = interner
1141 .anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
1142 ordered_associated_types.extend(
1143 pred.trait_ref
1144 .def_id
1145 .0
1146 .trait_items(self.db)
1147 .associated_types()
1148 .map(|item| (item.into(), trait_ref)),
1149 );
1150 }
1151 ClauseKind::Projection(pred) => {
1152 let pred = bound_predicate.rebind(pred);
1153 let references_self = match pred.skip_binder().term.kind() {
1156 TermKind::Ty(ty) => {
1157 ty.walk().any(|arg| arg == dummy_self_ty.into())
1158 }
1159 TermKind::Const(_) => false,
1161 };
1162
1163 if !references_self {
1181 let key = (
1182 pred.skip_binder().def_id().0,
1183 interner.anonymize_bound_vars(pred.map_bound(|proj| {
1184 proj.projection_term.trait_ref(interner)
1185 })),
1186 );
1187 if !projection_bounds.contains_key(&key) {
1188 projection_bounds.insert(key, pred);
1189 }
1190 }
1191 }
1192 _ => (),
1193 }
1194 }
1195 }
1196
1197 let mut projection_bounds: Vec<_> = ordered_associated_types
1204 .into_iter()
1205 .filter_map(|key| projection_bounds.get(&key).copied())
1206 .collect();
1207
1208 projection_bounds.sort_unstable_by_key(|proj| proj.skip_binder().def_id().0);
1209
1210 let principal = principal.map(|principal| {
1211 principal.map_bound(|principal| {
1212 let args: Vec<_> = principal
1214 .args
1215 .iter()
1216 .skip(1)
1218 .map(|arg| {
1219 if arg.walk().any(|arg| arg == dummy_self_ty.into()) {
1220 self.types.types.error.into()
1222 } else {
1223 arg
1224 }
1225 })
1226 .collect();
1227
1228 ExistentialPredicate::Trait(ExistentialTraitRef::new(
1229 interner,
1230 principal.def_id,
1231 args,
1232 ))
1233 })
1234 });
1235
1236 let projections = projection_bounds.into_iter().map(|proj| {
1237 proj.map_bound(|mut proj| {
1238 let references_self = proj.projection_term.args.iter().skip(1).any(|arg| {
1241 if arg.walk().any(|arg| arg == dummy_self_ty.into()) {
1242 return true;
1243 }
1244 false
1245 });
1246 if references_self {
1247 proj.projection_term = replace_dummy_self_with_error(
1248 interner,
1249 self.types,
1250 proj.projection_term,
1251 );
1252 }
1253
1254 ExistentialPredicate::Projection(ExistentialProjection::erase_self_ty(
1255 interner, proj,
1256 ))
1257 })
1258 });
1259
1260 let auto_traits = auto_traits.into_iter().map(|auto_trait| {
1261 Binder::dummy(ExistentialPredicate::AutoTrait(auto_trait.into()))
1262 });
1263
1264 Some(BoundExistentialPredicates::new_from_iter(
1266 interner,
1267 principal.into_iter().chain(projections).chain(auto_traits),
1268 ))
1269 };
1270
1271 if let Some(bounds) = bounds {
1272 let region = match region {
1273 Some(it) => it,
1274 None => Region::new_static(self.interner),
1275 };
1276 Ty::new_dynamic(self.interner, bounds, region)
1277 } else {
1278 self.types.types.error
1281 }
1282 }
1283
1284 fn lower_impl_trait(
1285 &mut self,
1286 def_id: InternedOpaqueTyId<'db>,
1287 bounds: &[TypeBound],
1288 ) -> ImplTrait {
1289 let interner = self.interner;
1290 cov_mark::hit!(lower_rpit);
1291 let args = GenericArgs::identity_for_item(interner, def_id.into());
1292 let self_ty = Ty::new_alias(
1293 self.interner,
1294 AliasTy::new_from_args(interner, rustc_type_ir::Opaque { def_id: def_id.into() }, args),
1295 );
1296 let prev_is_lowering_impl_trait_bounds =
1297 mem::replace(&mut self.is_lowering_impl_trait_bounds, true);
1298
1299 let mut predicates = Vec::new();
1300 let mut assoc_ty_bounds = Vec::new();
1301 for b in bounds {
1302 for (pred, source) in self.lower_type_bound(b, self_ty, false) {
1303 match source {
1304 GenericPredicateSource::SelfOnly => predicates.push(pred),
1305 GenericPredicateSource::AssocTyBound => assoc_ty_bounds.push(pred),
1306 }
1307 }
1308 }
1309
1310 if !self.unsized_types.contains(&self_ty) {
1311 let sized_trait = self.lang_items.Sized;
1312 let sized_clause = sized_trait.map(|trait_id| {
1313 let trait_ref = TraitRef::new_from_args(
1314 interner,
1315 trait_id.into(),
1316 GenericArgs::new_from_slice(&[self_ty.into()]),
1317 );
1318 Clause(Predicate::new(
1319 interner,
1320 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
1321 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1322 trait_ref,
1323 polarity: rustc_type_ir::PredicatePolarity::Positive,
1324 }),
1325 )),
1326 ))
1327 });
1328 predicates.extend(sized_clause);
1329 }
1330
1331 let assoc_ty_bounds_start = predicates.len() as u32;
1332 predicates.extend(assoc_ty_bounds);
1333
1334 self.is_lowering_impl_trait_bounds = prev_is_lowering_impl_trait_bounds;
1335 ImplTrait {
1336 predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&predicates).store()),
1337 assoc_ty_bounds_start,
1338 }
1339 }
1340
1341 pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> {
1342 if let Some(region) = self.find_and_lower_hrtb_lifetime(lifetime) {
1343 return region;
1344 };
1345
1346 match self.resolver.resolve_lifetime(&self.store[lifetime]) {
1347 Some(resolution) => match resolution {
1348 LifetimeNs::Static => Region::new_static(self.interner),
1349 LifetimeNs::LifetimeParam(id) => {
1350 let (idx, is_late_bound) =
1351 self.generics().lifetime_param_idx(id, self.is_lowering_impl_trait_bounds);
1352 self.region_param(id, idx, is_late_bound)
1353 }
1354 },
1355 None => Region::error(self.interner),
1356 }
1357 }
1358
1359 fn find_and_lower_hrtb_lifetime(&mut self, lifetime: LifetimeRefId) -> Option<Region<'db>> {
1360 if let LifetimeRef::Named(lt_name) = &self.store[lifetime] {
1361 self.bound_vars.iter().rev().enumerate().find_map(|(debruijn, (binder, _))| {
1362 binder.iter().enumerate().find_map(|(index, l)| {
1363 (l == lt_name).then(|| {
1364 self.hrtb_region_param(
1365 index as u32,
1366 DebruijnIndex::from_usize(debruijn),
1367 self.generic_def,
1368 )
1369 })
1370 })
1371 })
1372 } else {
1373 None
1374 }
1375 }
1376}
1377
1378#[derive(Clone, PartialEq, Eq, SalsaValue)]
1379pub struct TyLoweringResult<'db, T> {
1380 pub value: T,
1381 info: Option<Box<TyLoweringResultInfo<'db>>>,
1382}
1383
1384#[derive(Clone, PartialEq, Eq, SalsaValue)]
1385struct TyLoweringResultInfo<'db> {
1386 diagnostics: ThinVec<TyLoweringDiagnostic>,
1387 anon_consts: ThinVec<AnonConstId<'db>>,
1388}
1389
1390impl<T: std::fmt::Debug> std::fmt::Debug for TyLoweringResult<'_, T> {
1391 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1392 let mut debug = f.debug_struct("TyLoweringResult");
1393 debug.field("value", &self.value);
1394 let diagnostics = self.diagnostics();
1395 if !diagnostics.is_empty() {
1396 debug.field("diagnostics", &diagnostics);
1397 }
1398 let defined_anon_consts = self.defined_anon_consts();
1399 if !defined_anon_consts.is_empty() {
1400 debug.field("defined_anon_consts", &defined_anon_consts);
1401 }
1402 debug.finish()
1403 }
1404}
1405
1406impl<'db, T> TyLoweringResult<'db, T> {
1407 fn new(
1408 value: T,
1409 mut diagnostics: ThinVec<TyLoweringDiagnostic>,
1410 mut defined_anon_consts: ThinVec<AnonConstId<'db>>,
1411 ) -> Self {
1412 let info = if diagnostics.is_empty() && defined_anon_consts.is_empty() {
1413 None
1414 } else {
1415 diagnostics.shrink_to_fit();
1416 defined_anon_consts.shrink_to_fit();
1417 Some(Box::new(TyLoweringResultInfo { diagnostics, anon_consts: defined_anon_consts }))
1418 };
1419 Self { value, info }
1420 }
1421
1422 fn from_ctx(value: T, ctx: TyLoweringContext<'db, '_>) -> Self {
1423 Self::new(value, ctx.diagnostics, ctx.defined_anon_consts)
1424 }
1425
1426 fn empty(value: T) -> Self {
1427 Self { value, info: None }
1428 }
1429
1430 #[inline]
1431 pub fn diagnostics(&self) -> &[TyLoweringDiagnostic] {
1432 match &self.info {
1433 Some(info) => &info.diagnostics,
1434 None => &[],
1435 }
1436 }
1437
1438 #[inline]
1439 pub fn defined_anon_consts(&self) -> &[AnonConstId<'db>] {
1440 match &self.info {
1441 Some(info) => &info.anon_consts,
1442 None => &[],
1443 }
1444 }
1445}
1446
1447fn replace_dummy_self_with_error<'db, T: TypeFoldable<DbInterner<'db>>>(
1448 interner: DbInterner<'db>,
1449 types: &DefaultAny<'db>,
1450 t: T,
1451) -> T {
1452 t.fold_with(&mut BottomUpFolder {
1453 interner,
1454 ty_op: |ty| {
1455 if ty == types.types.dyn_trait_dummy_self { types.types.error } else { ty }
1456 },
1457 lt_op: |lt| lt,
1458 ct_op: |ct| ct,
1459 })
1460}
1461
1462pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
1463 match m {
1464 hir_def::type_ref::Mutability::Shared => Mutability::Not,
1465 hir_def::type_ref::Mutability::Mut => Mutability::Mut,
1466 }
1467}
1468
1469pub(crate) fn impl_trait_query<'db>(
1470 db: &'db dyn HirDatabase,
1471 impl_id: ImplId,
1472) -> Option<EarlyBinder<'db, TraitRef<'db>>> {
1473 impl_trait_with_diagnostics(db, impl_id)
1474 .as_ref()
1475 .map(|it| it.value.get(DbInterner::new_no_crate(db)))
1476}
1477
1478#[salsa::tracked(returns(ref), cycle_result = impl_trait_with_diagnostics_cycle_result)]
1479pub(crate) fn impl_trait_with_diagnostics<'db>(
1480 db: &'db dyn HirDatabase,
1481 impl_id: ImplId,
1482) -> Option<TyLoweringResult<'db, StoredEarlyBinder<StoredTraitRef>>> {
1483 let impl_data = ImplSignature::of(db, impl_id);
1484 let resolver = impl_id.resolver(db);
1485 let generics = OnceCell::new();
1486 let mut ctx = TyLoweringContext::new(
1487 db,
1488 &resolver,
1489 &impl_data.store,
1490 ExpressionStoreOwnerId::Signature(impl_id.into()),
1491 impl_id.into(),
1492 &generics,
1493 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
1494 LifetimeLoweringMode::Bound,
1495 );
1496 let self_ty = db.impl_self_ty(impl_id).skip_binder();
1497 let target_trait = impl_data.target_trait.as_ref()?;
1498 let trait_ref = ctx.lower_trait_ref(target_trait, self_ty)?;
1499 Some(TyLoweringResult::from_ctx(StoredEarlyBinder::bind(StoredTraitRef::new(trait_ref)), ctx))
1500}
1501
1502pub(crate) fn impl_trait_with_diagnostics_cycle_result<'db>(
1503 _db: &'db dyn HirDatabase,
1504 _: salsa::Id,
1505 _impl_id: ImplId,
1506) -> Option<TyLoweringResult<'db, StoredEarlyBinder<StoredTraitRef>>> {
1507 None
1508}
1509
1510impl ImplTraitId {
1511 #[inline]
1512 fn data(self, db: &dyn HirDatabase) -> &ImplTrait {
1513 let (impl_traits, idx) = match self {
1514 ImplTraitId::ReturnTypeImplTrait(owner, idx) => {
1515 (ImplTrait::return_type_impl_traits(db, owner), idx)
1516 }
1517 ImplTraitId::TypeAliasImplTrait(owner, idx) => {
1518 (ImplTrait::type_alias_impl_traits(db, owner), idx)
1519 }
1520 };
1521 &impl_traits[idx]
1522 }
1523
1524 #[inline]
1525 pub fn predicates<'db>(self, db: &'db dyn HirDatabase) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1526 self.data(db).predicates.get().map_bound(|it| it.as_slice())
1527 }
1528
1529 #[inline]
1530 pub fn self_predicates<'db>(
1531 self,
1532 db: &'db dyn HirDatabase,
1533 ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1534 let data = self.data(db);
1535 data.predicates.get().map_bound(|it| &it.as_slice()[..data.assoc_ty_bounds_start as usize])
1536 }
1537}
1538
1539impl InternedOpaqueTyId<'_> {
1540 #[inline]
1541 pub fn predicates<'db>(self, db: &'db dyn HirDatabase) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1542 self.loc(db).predicates(db)
1543 }
1544
1545 #[inline]
1546 pub fn self_predicates<'db>(
1547 self,
1548 db: &'db dyn HirDatabase,
1549 ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1550 self.loc(db).self_predicates(db)
1551 }
1552}
1553
1554impl ImplTrait {
1555 #[inline]
1556 pub(crate) fn return_type_impl_traits(
1557 db: &dyn HirDatabase,
1558 def: FunctionId,
1559 ) -> &Arena<ImplTrait> {
1560 fn_sig_for_fn(db, def).value.impl_traits.as_deref().unwrap_or(const { &Arena::new() })
1561 }
1562
1563 #[inline]
1564 pub(crate) fn type_alias_impl_traits(
1565 db: &dyn HirDatabase,
1566 def: TypeAliasId,
1567 ) -> &Arena<ImplTrait> {
1568 type_for_type_alias_with_diagnostics(db, def)
1569 .value
1570 .impl_traits
1571 .as_deref()
1572 .unwrap_or(const { &Arena::new() })
1573 }
1574}
1575
1576#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1577pub enum TyDefId {
1578 BuiltinType(BuiltinType),
1579 AdtId(AdtId),
1580 TypeAliasId(TypeAliasId),
1581}
1582impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
1583
1584#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
1585pub enum ValueTyDefId {
1586 FunctionId(FunctionId),
1587 StructId(StructId),
1588 UnionId(UnionId),
1589 EnumVariantId(EnumVariantId),
1590 ConstId(ConstId),
1591 StaticId(StaticId),
1592}
1593impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
1594
1595impl ValueTyDefId {
1596 pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> GenericDefId {
1597 match self {
1598 Self::FunctionId(id) => id.into(),
1599 Self::StructId(id) => id.into(),
1600 Self::UnionId(id) => id.into(),
1601 Self::EnumVariantId(var) => var.lookup(db).parent.into(),
1602 Self::ConstId(id) => id.into(),
1603 Self::StaticId(id) => id.into(),
1604 }
1605 }
1606}
1607
1608pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> {
1613 let interner = DbInterner::new_no_crate(db);
1614 match def {
1615 TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)),
1616 TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt(
1617 interner,
1618 it,
1619 GenericArgs::identity_for_item(interner, it.into()),
1620 )),
1621 TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).value.value.get(),
1622 }
1623}
1624
1625fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> {
1628 let interner = DbInterner::new_no_crate(db);
1629 EarlyBinder::bind(Ty::new_fn_def(
1630 interner,
1631 CallableDefId::FunctionId(def).into(),
1632 GenericArgs::identity_for_item(interner, def.into()),
1633 ))
1634}
1635
1636pub(crate) fn type_for_const<'db>(
1637 db: &'db dyn HirDatabase,
1638 def: ConstId,
1639) -> EarlyBinder<'db, Ty<'db>> {
1640 type_for_const_with_diagnostics(db, def).value.get()
1641}
1642
1643#[salsa::tracked(returns(ref))]
1645pub(crate) fn type_for_const_with_diagnostics<'db>(
1646 db: &'db dyn HirDatabase,
1647 def: ConstId,
1648) -> TyLoweringResult<'db, StoredEarlyBinder<StoredTy>> {
1649 let resolver = def.resolver(db);
1650 let data = ConstSignature::of(db, def);
1651 let parent = def.loc(db).container;
1652 let generics = OnceCell::new();
1653 let mut ctx = TyLoweringContext::new(
1654 db,
1655 &resolver,
1656 &data.store,
1657 ExpressionStoreOwnerId::Signature(def.into()),
1658 def.into(),
1659 &generics,
1660 LifetimeElisionKind::AnonymousReportError,
1661 LifetimeLoweringMode::Bound,
1662 );
1663 ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent));
1664 let result = StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store());
1665 TyLoweringResult::from_ctx(result, ctx)
1666}
1667
1668pub(crate) fn type_for_static<'db>(
1669 db: &'db dyn HirDatabase,
1670 def: StaticId,
1671) -> EarlyBinder<'db, Ty<'db>> {
1672 type_for_static_with_diagnostics(db, def).value.get()
1673}
1674
1675#[salsa::tracked(returns(ref))]
1677pub(crate) fn type_for_static_with_diagnostics<'db>(
1678 db: &'db dyn HirDatabase,
1679 def: StaticId,
1680) -> TyLoweringResult<'db, StoredEarlyBinder<StoredTy>> {
1681 let resolver = def.resolver(db);
1682 let data = StaticSignature::of(db, def);
1683 let generics = OnceCell::new();
1684 let mut ctx = TyLoweringContext::new(
1685 db,
1686 &resolver,
1687 &data.store,
1688 ExpressionStoreOwnerId::Signature(def.into()),
1689 def.into(),
1690 &generics,
1691 LifetimeElisionKind::AnonymousReportError,
1692 LifetimeLoweringMode::Bound,
1693 );
1694 ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner)));
1695 let result = StoredEarlyBinder::bind(ctx.lower_ty(data.type_ref).store());
1696 TyLoweringResult::from_ctx(result, ctx)
1697}
1698
1699fn type_for_struct_constructor<'db>(
1701 db: &'db dyn HirDatabase,
1702 def: StructId,
1703) -> Option<EarlyBinder<'db, Ty<'db>>> {
1704 let struct_data = StructSignature::of(db, def);
1705 match struct_data.shape {
1706 FieldsShape::Record => None,
1707 FieldsShape::Unit => Some(type_for_adt(db, def.into())),
1708 FieldsShape::Tuple => {
1709 let interner = DbInterner::new_no_crate(db);
1710 let def = CallableDefId::StructId(def);
1711 Some(EarlyBinder::bind(Ty::new_fn_def(
1712 interner,
1713 def.into(),
1714 GenericArgs::identity_for_item(interner, def.into()),
1715 )))
1716 }
1717 }
1718}
1719
1720fn type_for_enum_variant_constructor<'db>(
1722 db: &'db dyn HirDatabase,
1723 def: EnumVariantId,
1724) -> Option<EarlyBinder<'db, Ty<'db>>> {
1725 let struct_data = def.fields(db);
1726 match struct_data.shape {
1727 FieldsShape::Record => None,
1728 FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())),
1729 FieldsShape::Tuple => {
1730 let interner = DbInterner::new_no_crate(db);
1731 let def = CallableDefId::EnumVariantId(def);
1732 Some(EarlyBinder::bind(Ty::new_fn_def(
1733 interner,
1734 def.into(),
1735 GenericArgs::identity_for_item(interner, def.into()),
1736 )))
1737 }
1738 }
1739}
1740
1741pub(crate) fn value_ty<'db>(
1742 db: &'db dyn HirDatabase,
1743 def: ValueTyDefId,
1744) -> Option<EarlyBinder<'db, Ty<'db>>> {
1745 match def {
1746 ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
1747 ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
1748 ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
1749 ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
1750 ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
1751 ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
1752 }
1753}
1754
1755#[salsa::tracked(returns(ref), cycle_result = type_for_type_alias_with_diagnostics_cycle_result)]
1756pub(crate) fn type_for_type_alias_with_diagnostics<'db>(
1757 db: &'db dyn HirDatabase,
1758 t: TypeAliasId,
1759) -> TyLoweringResult<'db, WithDefinedOpaques<StoredEarlyBinder<StoredTy>>> {
1760 let type_alias_data = TypeAliasSignature::of(db, t);
1761 let interner = DbInterner::new_no_crate(db);
1762 if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
1763 TyLoweringResult::empty(WithDefinedOpaques {
1764 value: StoredEarlyBinder::bind(Ty::new_foreign(interner, t.into()).store()),
1765 impl_traits: None,
1766 })
1767 } else {
1768 let resolver = t.resolver(db);
1769 let generics = OnceCell::new();
1770 let mut ctx = TyLoweringContext::new(
1771 db,
1772 &resolver,
1773 &type_alias_data.store,
1774 ExpressionStoreOwnerId::Signature(t.into()),
1775 t.into(),
1776 &generics,
1777 LifetimeElisionKind::AnonymousReportError,
1778 LifetimeLoweringMode::Bound,
1779 )
1780 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
1781 let res = StoredEarlyBinder::bind(
1782 type_alias_data
1783 .ty
1784 .map(|type_ref| ctx.lower_ty(type_ref))
1785 .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
1786 .store(),
1787 );
1788 TyLoweringResult::from_ctx(
1789 WithDefinedOpaques { value: res, impl_traits: ctx.take_defined_opaques() },
1790 ctx,
1791 )
1792 }
1793}
1794
1795pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>(
1796 db: &'db dyn HirDatabase,
1797 _: salsa::Id,
1798 _adt: TypeAliasId,
1799) -> TyLoweringResult<'db, WithDefinedOpaques<StoredEarlyBinder<StoredTy>>> {
1800 TyLoweringResult::empty(WithDefinedOpaques {
1801 value: StoredEarlyBinder::bind(
1802 Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(),
1803 ),
1804 impl_traits: None,
1805 })
1806}
1807
1808pub(crate) fn impl_self_ty_query<'db>(
1809 db: &'db dyn HirDatabase,
1810 impl_id: ImplId,
1811) -> EarlyBinder<'db, Ty<'db>> {
1812 impl_self_ty_with_diagnostics(db, impl_id).value.get()
1813}
1814
1815#[salsa::tracked(returns(ref), cycle_result = impl_self_ty_with_diagnostics_cycle_result)]
1816pub(crate) fn impl_self_ty_with_diagnostics<'db>(
1817 db: &'db dyn HirDatabase,
1818 impl_id: ImplId,
1819) -> TyLoweringResult<'db, StoredEarlyBinder<StoredTy>> {
1820 let resolver = impl_id.resolver(db);
1821 let generics = OnceCell::new();
1822 let impl_data = ImplSignature::of(db, impl_id);
1823 let mut ctx = TyLoweringContext::new(
1824 db,
1825 &resolver,
1826 &impl_data.store,
1827 ExpressionStoreOwnerId::Signature(impl_id.into()),
1828 impl_id.into(),
1829 &generics,
1830 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
1831 LifetimeLoweringMode::Bound,
1832 );
1833 let ty = ctx.lower_ty(impl_data.self_ty);
1834 assert!(!ty.has_escaping_bound_vars());
1835 TyLoweringResult::from_ctx(StoredEarlyBinder::bind(ty.store()), ctx)
1836}
1837
1838pub(crate) fn impl_self_ty_with_diagnostics_cycle_result<'db>(
1839 db: &'db dyn HirDatabase,
1840 _: salsa::Id,
1841 _impl_id: ImplId,
1842) -> TyLoweringResult<'db, StoredEarlyBinder<StoredTy>> {
1843 TyLoweringResult::empty(StoredEarlyBinder::bind(
1844 Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed).store(),
1845 ))
1846}
1847
1848pub(crate) fn const_param_ty<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> {
1849 let param_types = const_param_types(db, def.parent());
1850 match param_types.get(def.local_id()) {
1851 Some(ty) => ty.as_ref(),
1852 None => Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed),
1853 }
1854}
1855
1856#[derive(Default, PartialEq, Eq, SalsaValue)]
1860pub struct ConstParamTypes {
1861 map: ArenaMap<LocalTypeOrConstParamId, StoredTy>,
1862}
1863
1864impl Deref for ConstParamTypes {
1865 type Target = ArenaMap<LocalTypeOrConstParamId, StoredTy>;
1866
1867 fn deref(&self) -> &Self::Target {
1868 &self.map
1869 }
1870}
1871
1872pub(crate) fn const_param_types(db: &dyn HirDatabase, def: GenericDefId) -> &ConstParamTypes {
1873 &const_param_types_with_diagnostics(db, def).value
1874}
1875
1876#[salsa::tracked(returns(ref), cycle_result = const_param_types_with_diagnostics_cycle_result)]
1877pub(crate) fn const_param_types_with_diagnostics<'db>(
1878 db: &'db dyn HirDatabase,
1879 def: GenericDefId,
1880) -> TyLoweringResult<'db, ConstParamTypes> {
1881 let mut result = ArenaMap::new();
1882 let (data, store) = GenericParams::with_store(db, def);
1883 let resolver = def.resolver(db);
1884 let generics = OnceCell::new();
1885 let mut ctx = TyLoweringContext::new(
1886 db,
1887 &resolver,
1888 store,
1889 ExpressionStoreOwnerId::Signature(def),
1890 def,
1891 &generics,
1892 LifetimeElisionKind::AnonymousReportError,
1893 LifetimeLoweringMode::Bound,
1894 );
1895 ctx.forbid_params_after(0, ForbidParamsAfterReason::ConstParamTy);
1896 for (local_id, param_data) in data.iter_type_or_consts() {
1897 if let TypeOrConstParamData::ConstParamData(param_data) = param_data {
1898 result.insert(local_id, ctx.lower_ty(param_data.ty).store());
1899 }
1900 }
1901 result.shrink_to_fit();
1902 TyLoweringResult::from_ctx(ConstParamTypes { map: result }, ctx)
1903}
1904
1905fn const_param_types_with_diagnostics_cycle_result<'db>(
1906 _db: &'db dyn HirDatabase,
1907 _: salsa::Id,
1908 _def: GenericDefId,
1909) -> TyLoweringResult<'db, ConstParamTypes> {
1910 TyLoweringResult::empty(ConstParamTypes::default())
1911}
1912
1913#[derive(Default, PartialEq, Eq, SalsaValue)]
1917pub struct FieldTypes {
1918 map: ArenaMap<LocalFieldId, FieldType>,
1919}
1920
1921impl Deref for FieldTypes {
1922 type Target = ArenaMap<LocalFieldId, FieldType>;
1923
1924 fn deref(&self) -> &Self::Target {
1925 &self.map
1926 }
1927}
1928
1929pub(crate) fn field_types_query(db: &dyn HirDatabase, variant_id: VariantId) -> &FieldTypes {
1930 &field_types_with_diagnostics(db, variant_id).value
1931}
1932
1933#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1934pub struct FieldType {
1935 ty: StoredEarlyBinder<StoredTy>,
1936 default: Option<StoredEarlyBinder<StoredConst>>,
1937}
1938
1939impl FieldType {
1940 #[inline]
1941 pub fn ty<'db>(&self) -> EarlyBinder<'db, Ty<'db>> {
1942 self.ty.get()
1943 }
1944
1945 #[inline]
1946 pub fn default<'db>(&self) -> Option<EarlyBinder<'db, Const<'db>>> {
1947 self.default.as_ref().map(|default| default.get_with(|it| it.as_ref()))
1948 }
1949}
1950
1951#[salsa::tracked(returns(ref))]
1953pub(crate) fn field_types_with_diagnostics<'db>(
1954 db: &'db dyn HirDatabase,
1955 variant_id: VariantId,
1956) -> TyLoweringResult<'db, FieldTypes> {
1957 let var_data = variant_id.fields(db);
1958 let fields = var_data.fields();
1959 if fields.is_empty() {
1960 return TyLoweringResult::empty(FieldTypes::default());
1961 }
1962
1963 let (resolver, generic_def): (_, GenericDefId) = match variant_id {
1964 VariantId::StructId(it) => (it.resolver(db), it.into()),
1965 VariantId::UnionId(it) => (it.resolver(db), it.into()),
1966 VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
1967 };
1968 let generics = OnceCell::new();
1969 let mut res = ArenaMap::default();
1970 let mut ctx = TyLoweringContext::new(
1971 db,
1972 &resolver,
1973 &var_data.store,
1974 ExpressionStoreOwnerId::VariantFields(variant_id),
1975 generic_def,
1976 &generics,
1977 LifetimeElisionKind::AnonymousReportError,
1978 LifetimeLoweringMode::Bound,
1979 );
1980 for (field_id, field_data) in var_data.fields().iter() {
1981 let ty = ctx.lower_ty(field_data.type_ref);
1982 let default = field_data.default_value.map(|default| ctx.lower_const(default, ty));
1983 res.insert(
1984 field_id,
1985 FieldType {
1986 ty: StoredEarlyBinder::bind(ty.store()),
1987 default: default.map(|default| StoredEarlyBinder::bind(default.store())),
1988 },
1989 );
1990 }
1991 TyLoweringResult::from_ctx(FieldTypes { map: res }, ctx)
1992}
1993
1994#[derive(Debug, PartialEq, Eq, Default)]
1995pub(crate) struct SupertraitsInfo {
1996 pub(crate) all_supertraits: Box<[TraitId]>,
1998 pub(crate) direct_supertraits: Box<[TraitId]>,
1999 pub(crate) defined_assoc_types: Box<[(Name, TypeAliasId)]>,
2000}
2001
2002impl SupertraitsInfo {
2003 #[inline]
2004 pub(crate) fn query(db: &dyn HirDatabase, trait_: TraitId) -> &Self {
2005 return supertraits_info(db, trait_);
2006
2007 #[salsa::tracked(returns(ref), cycle_result = supertraits_info_cycle)]
2008 fn supertraits_info(db: &dyn HirDatabase, trait_: TraitId) -> SupertraitsInfo {
2009 let mut all_supertraits = FxHashSet::default();
2010 let mut direct_supertraits = FxHashSet::default();
2011 let mut defined_assoc_types = FxHashSet::default();
2012
2013 all_supertraits.insert(trait_);
2014 defined_assoc_types.extend(trait_.trait_items(db).items.iter().filter_map(
2015 |(name, id)| match *id {
2016 AssocItemId::TypeAliasId(id) => Some((name.clone(), id)),
2017 _ => None,
2018 },
2019 ));
2020
2021 let resolver = trait_.resolver(db);
2022 let signature = TraitSignature::of(db, trait_);
2023 for pred in signature.generic_params.where_predicates() {
2024 let WherePredicate::TypeBound { lifetimes: _, target, bound } = pred else {
2025 continue;
2026 };
2027 let (TypeBound::Path(bounded_trait, TraitBoundModifier::None)
2028 | TypeBound::ForLifetime(_, bounded_trait)) = *bound
2029 else {
2030 continue;
2031 };
2032 let target = &signature.store[*target];
2033 match target {
2034 TypeRef::TypeParam(param)
2035 if param.local_id() == GenericParams::SELF_PARAM_ID_IN_SELF => {}
2036 TypeRef::Path(path) if path.is_self_type() => {}
2037 _ => continue,
2038 }
2039 let Some(TypeNs::TraitId(bounded_trait)) =
2040 resolver.resolve_path_in_type_ns_fully(db, &signature.store[bounded_trait])
2041 else {
2042 continue;
2043 };
2044 let SupertraitsInfo {
2045 all_supertraits: bounded_trait_all_supertraits,
2046 direct_supertraits: _,
2047 defined_assoc_types: bounded_traits_defined_assoc_types,
2048 } = SupertraitsInfo::query(db, bounded_trait);
2049 all_supertraits.extend(bounded_trait_all_supertraits);
2050 direct_supertraits.insert(bounded_trait);
2051 defined_assoc_types.extend(bounded_traits_defined_assoc_types.iter().cloned());
2052 }
2053
2054 SupertraitsInfo {
2055 all_supertraits: Box::from_iter(all_supertraits),
2056 direct_supertraits: Box::from_iter(direct_supertraits),
2057 defined_assoc_types: Box::from_iter(defined_assoc_types),
2058 }
2059 }
2060
2061 fn supertraits_info_cycle(
2062 _db: &dyn HirDatabase,
2063 _: salsa::Id,
2064 _trait_: TraitId,
2065 ) -> SupertraitsInfo {
2066 SupertraitsInfo::default()
2067 }
2068 }
2069}
2070
2071#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2072enum AssocTypeShorthandResolution {
2073 Resolved(StoredEarlyBinder<(TypeAliasId, StoredGenericArgs)>),
2074 Ambiguous {
2075 sub_trait_resolution: Option<StoredEarlyBinder<(TypeAliasId, StoredGenericArgs)>>,
2079 },
2080 NotFound,
2081 Cycle,
2082}
2083
2084#[tracing::instrument(skip(db), ret)]
2098#[salsa::tracked(returns(ref), cycle_result = resolve_type_param_assoc_type_shorthand_cycle_result)]
2099fn resolve_type_param_assoc_type_shorthand(
2100 db: &dyn HirDatabase,
2101 def: GenericDefId,
2102 param: TypeParamId,
2103 assoc_name: Name,
2104) -> AssocTypeShorthandResolution {
2105 let generics = generics(db, def);
2106 let store = generics.store();
2107 let generics = &OnceCell::from(generics);
2108 let resolver = def.resolver(db);
2109 let mut ctx = TyLoweringContext::new(
2110 db,
2111 &resolver,
2112 store,
2113 ExpressionStoreOwnerId::Signature(def),
2114 def,
2115 generics,
2116 LifetimeElisionKind::AnonymousReportError,
2117 LifetimeLoweringMode::Bound,
2118 );
2119 let interner = ctx.interner;
2120 let generics = generics.get().unwrap();
2121 let param_ty = Ty::new_param(interner, param, generics.type_or_const_param_idx(param.into()));
2122
2123 let mut this_trait_resolution = None;
2124 if let GenericDefId::TraitId(containing_trait) = param.parent()
2125 && param.local_id() == GenericParams::SELF_PARAM_ID_IN_SELF
2126 {
2127 if let Some(assoc_type) =
2129 containing_trait.trait_items(db).associated_type_by_name(&assoc_name)
2130 {
2131 let args = GenericArgs::identity_for_item(interner, containing_trait.into());
2132 this_trait_resolution = Some(StoredEarlyBinder::bind((assoc_type, args.store())));
2133 }
2134 }
2135
2136 let mut supertraits_resolution = None;
2137 for maybe_parent_generics in generics.iter_owners().rev() {
2138 ctx.set_owner(maybe_parent_generics);
2139 for pred in maybe_parent_generics.where_predicates() {
2140 let WherePredicate::TypeBound { lifetimes: _, target, bound } = pred else {
2141 continue;
2142 };
2143 let (TypeBound::Path(bounded_trait_path, TraitBoundModifier::None)
2144 | TypeBound::ForLifetime(_, bounded_trait_path)) = *bound
2145 else {
2146 continue;
2147 };
2148 let Some(target) = ctx.lower_ty_only_param(*target) else { continue };
2149 if target != param.into() {
2150 continue;
2151 }
2152 let Some(TypeNs::TraitId(bounded_trait)) =
2153 resolver.resolve_path_in_type_ns_fully(db, &ctx.store[bounded_trait_path])
2154 else {
2155 continue;
2156 };
2157 if !SupertraitsInfo::query(db, bounded_trait)
2158 .defined_assoc_types
2159 .iter()
2160 .any(|(name, _)| *name == assoc_name)
2161 {
2162 continue;
2163 }
2164
2165 let Some((bounded_trait_ref, _)) =
2166 ctx.lower_trait_ref_from_path(bounded_trait_path, param_ty)
2167 else {
2168 continue;
2169 };
2170 let lookup_on_bounded_trait = resolve_type_param_assoc_type_shorthand(
2173 db,
2174 bounded_trait.into(),
2175 TypeParamId::trait_self(bounded_trait),
2176 assoc_name.clone(),
2177 );
2178 let assoc_type_and_args = match &lookup_on_bounded_trait {
2179 AssocTypeShorthandResolution::Resolved(trait_ref) => trait_ref,
2180 AssocTypeShorthandResolution::Ambiguous {
2181 sub_trait_resolution: Some(trait_ref),
2182 } => trait_ref,
2183 AssocTypeShorthandResolution::Ambiguous { sub_trait_resolution: None } => {
2184 return AssocTypeShorthandResolution::Ambiguous {
2185 sub_trait_resolution: this_trait_resolution,
2186 };
2187 }
2188 AssocTypeShorthandResolution::NotFound => {
2189 never!("we checked that the trait defines this assoc type");
2190 continue;
2191 }
2192 AssocTypeShorthandResolution::Cycle => return AssocTypeShorthandResolution::Cycle,
2193 };
2194 let (assoc_type, args) = assoc_type_and_args
2195 .get_with(|(assoc_type, args)| (*assoc_type, args.as_ref()))
2196 .skip_binder();
2197 let args = EarlyBinder::bind(args)
2198 .instantiate(interner, bounded_trait_ref.args)
2199 .skip_norm_wip();
2200 let current_result = StoredEarlyBinder::bind((assoc_type, args.store()));
2201 if let Some(this_trait_resolution) = &this_trait_resolution {
2202 if *this_trait_resolution == current_result {
2203 continue;
2204 } else {
2205 return AssocTypeShorthandResolution::Ambiguous {
2206 sub_trait_resolution: Some(this_trait_resolution.clone()),
2207 };
2208 }
2209 } else if let Some(prev_resolution) = &supertraits_resolution {
2210 if let AssocTypeShorthandResolution::Ambiguous {
2211 sub_trait_resolution: Some(prev_resolution),
2212 }
2213 | AssocTypeShorthandResolution::Resolved(prev_resolution) = prev_resolution
2214 && *prev_resolution == current_result
2215 {
2216 continue;
2217 } else {
2218 return AssocTypeShorthandResolution::Ambiguous { sub_trait_resolution: None };
2219 }
2220 } else {
2221 supertraits_resolution = Some(match lookup_on_bounded_trait {
2222 AssocTypeShorthandResolution::Resolved(_) => {
2223 AssocTypeShorthandResolution::Resolved(current_result)
2224 }
2225 AssocTypeShorthandResolution::Ambiguous { .. } => {
2226 AssocTypeShorthandResolution::Ambiguous {
2227 sub_trait_resolution: Some(current_result),
2228 }
2229 }
2230 AssocTypeShorthandResolution::NotFound
2231 | AssocTypeShorthandResolution::Cycle => unreachable!(),
2232 });
2233 }
2234 }
2235 }
2236
2237 supertraits_resolution
2238 .or_else(|| this_trait_resolution.map(AssocTypeShorthandResolution::Resolved))
2239 .unwrap_or(AssocTypeShorthandResolution::NotFound)
2240}
2241
2242fn resolve_type_param_assoc_type_shorthand_cycle_result(
2243 _db: &dyn HirDatabase,
2244 _: salsa::Id,
2245 _def: GenericDefId,
2246 _param: TypeParamId,
2247 _assoc_name: Name,
2248) -> AssocTypeShorthandResolution {
2249 AssocTypeShorthandResolution::Cycle
2250}
2251
2252#[inline]
2253pub(crate) fn type_alias_bounds<'db>(
2254 db: &'db dyn HirDatabase,
2255 type_alias: TypeAliasId,
2256) -> EarlyBinder<'db, &'db [Clause<'db>]> {
2257 type_alias_bounds_with_diagnostics(db, type_alias)
2258 .value
2259 .predicates
2260 .get()
2261 .map_bound(|it| it.as_slice())
2262}
2263
2264#[inline]
2265pub(crate) fn type_alias_self_bounds<'db>(
2266 db: &'db dyn HirDatabase,
2267 type_alias: TypeAliasId,
2268) -> EarlyBinder<'db, &'db [Clause<'db>]> {
2269 let TypeAliasBounds { predicates, assoc_ty_bounds_start } =
2270 &type_alias_bounds_with_diagnostics(db, type_alias).value;
2271 predicates.get().map_bound(|it| &it.as_slice()[..*assoc_ty_bounds_start as usize])
2272}
2273
2274#[derive(PartialEq, Eq, Debug, Hash, SalsaValue)]
2275pub struct TypeAliasBounds<T> {
2276 predicates: T,
2277 assoc_ty_bounds_start: u32,
2278}
2279
2280#[salsa::tracked(returns(ref))]
2281pub(crate) fn type_alias_bounds_with_diagnostics<'db>(
2282 db: &'db dyn HirDatabase,
2283 type_alias: TypeAliasId,
2284) -> TyLoweringResult<'db, TypeAliasBounds<StoredEarlyBinder<StoredClauses>>> {
2285 let type_alias_data = TypeAliasSignature::of(db, type_alias);
2286 let resolver = type_alias.resolver(db);
2287 let generics = OnceCell::new();
2288 let mut ctx = TyLoweringContext::new(
2289 db,
2290 &resolver,
2291 &type_alias_data.store,
2292 ExpressionStoreOwnerId::Signature(type_alias.into()),
2293 type_alias.into(),
2294 &generics,
2295 LifetimeElisionKind::AnonymousReportError,
2296 LifetimeLoweringMode::Bound,
2297 );
2298 let interner = ctx.interner;
2299
2300 let item_args = GenericArgs::identity_for_item(interner, type_alias.into());
2301 let interner_ty = Ty::new_projection_from_args(interner, type_alias.into(), item_args);
2302
2303 let mut bounds = Vec::new();
2304 let mut assoc_ty_bounds = Vec::new();
2305 for bound in &type_alias_data.bounds {
2306 ctx.lower_type_bound(bound, interner_ty, false).for_each(|(pred, source)| match source {
2307 GenericPredicateSource::SelfOnly => {
2308 bounds.push(pred);
2309 }
2310 GenericPredicateSource::AssocTyBound => {
2311 assoc_ty_bounds.push(pred);
2312 }
2313 });
2314 }
2315
2316 if !ctx.unsized_types.contains(&interner_ty) {
2317 let sized_trait = ctx.lang_items.Sized;
2318 if let Some(sized_trait) = sized_trait {
2319 let trait_ref = TraitRef::new_from_args(
2320 interner,
2321 sized_trait.into(),
2322 GenericArgs::new_from_slice(&[interner_ty.into()]),
2323 );
2324 bounds.push(trait_ref.upcast(interner));
2325 };
2326 }
2327
2328 let assoc_ty_bounds_start = bounds.len() as u32;
2329 bounds.extend(assoc_ty_bounds);
2330
2331 TyLoweringResult::from_ctx(
2332 TypeAliasBounds {
2333 predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&bounds).store()),
2334 assoc_ty_bounds_start,
2335 },
2336 ctx,
2337 )
2338}
2339
2340#[derive(Debug, Clone, PartialEq, Eq, Hash, SalsaValue)]
2341pub struct GenericPredicates {
2342 predicates: StoredEarlyBinder<StoredClauses>,
2352 has_trait_implied_predicate: bool,
2354 parent_explicit_self_predicates_start: u32,
2355 own_predicates_start: u32,
2356 own_assoc_ty_bounds_start: u32,
2357}
2358
2359#[salsa::tracked]
2360impl<'db> GenericPredicates {
2361 #[salsa::tracked(returns(ref), cycle_result=generic_predicates_cycle_result)]
2365 pub fn query_with_diagnostics(
2366 db: &'db dyn HirDatabase,
2367 def: GenericDefId,
2368 ) -> TyLoweringResult<'db, GenericPredicates> {
2369 generic_predicates(db, def)
2370 }
2371}
2372
2373fn generic_predicates_cycle_result<'db>(
2375 db: &'db dyn HirDatabase,
2376 _: salsa::Id,
2377 _def: GenericDefId,
2378) -> TyLoweringResult<'db, GenericPredicates> {
2379 TyLoweringResult::empty(GenericPredicates::from_explicit_own_predicates(
2380 StoredEarlyBinder::bind(Clauses::empty(DbInterner::new_no_crate(db)).store()),
2381 ))
2382}
2383
2384impl GenericPredicates {
2385 #[inline]
2386 pub fn empty() -> &'static GenericPredicates {
2387 static EMPTY: OnceLock<GenericPredicates> = OnceLock::new();
2388 EMPTY.get_or_init(|| GenericPredicates {
2389 predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&[]).store()),
2390 has_trait_implied_predicate: false,
2391 parent_explicit_self_predicates_start: 0,
2392 own_predicates_start: 0,
2393 own_assoc_ty_bounds_start: 0,
2394 })
2395 }
2396
2397 #[inline]
2398 pub(crate) fn from_explicit_own_predicates(
2399 predicates: StoredEarlyBinder<StoredClauses>,
2400 ) -> Self {
2401 let len = predicates.get().skip_binder().len() as u32;
2402 Self {
2403 predicates,
2404 has_trait_implied_predicate: false,
2405 parent_explicit_self_predicates_start: 0,
2406 own_predicates_start: 0,
2407 own_assoc_ty_bounds_start: len,
2408 }
2409 }
2410
2411 #[inline]
2412 pub fn query(db: &dyn HirDatabase, def: GenericDefId) -> &GenericPredicates {
2413 &Self::query_with_diagnostics(db, def).value
2414 }
2415
2416 #[inline]
2417 pub fn query_all<'db>(
2418 db: &'db dyn HirDatabase,
2419 def: GenericDefId,
2420 ) -> EarlyBinder<'db, impl Iterator<Item = Clause<'db>>> {
2421 Self::query(db, def).all_predicates()
2422 }
2423
2424 #[inline]
2425 pub fn query_own_explicit<'db>(
2426 db: &'db dyn HirDatabase,
2427 def: GenericDefId,
2428 ) -> EarlyBinder<'db, impl Iterator<Item = Clause<'db>>> {
2429 Self::query(db, def).own_explicit_predicates()
2430 }
2431
2432 #[inline]
2433 pub fn query_explicit<'db>(
2434 db: &'db dyn HirDatabase,
2435 def: GenericDefId,
2436 ) -> EarlyBinder<'db, impl Iterator<Item = Clause<'db>>> {
2437 Self::query(db, def).explicit_predicates()
2438 }
2439
2440 #[inline]
2441 pub fn all_predicates(&self) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
2442 self.predicates.get().map_bound(|it| it.as_slice().iter().copied())
2443 }
2444
2445 #[inline]
2446 pub fn own_explicit_predicates(&self) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
2447 self.predicates
2448 .get()
2449 .map_bound(|it| it.as_slice()[self.own_predicates_start as usize..].iter().copied())
2450 }
2451
2452 #[inline]
2453 pub fn explicit_predicates(&self) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
2454 self.predicates.get().map_bound(|it| {
2455 it.as_slice()[usize::from(self.has_trait_implied_predicate)..].iter().copied()
2456 })
2457 }
2458
2459 #[inline]
2460 pub fn explicit_non_assoc_types_predicates(
2461 &self,
2462 ) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
2463 self.predicates.get().map_bound(|it| {
2464 it.as_slice()[self.parent_explicit_self_predicates_start as usize
2465 ..self.own_assoc_ty_bounds_start as usize]
2466 .iter()
2467 .copied()
2468 })
2469 }
2470
2471 #[inline]
2472 pub fn explicit_assoc_types_predicates(
2473 &self,
2474 ) -> EarlyBinder<'_, impl Iterator<Item = Clause<'_>>> {
2475 self.predicates.get().map_bound(|predicates| {
2476 let predicates = predicates.as_slice();
2477 predicates[usize::from(self.has_trait_implied_predicate)
2478 ..self.parent_explicit_self_predicates_start as usize]
2479 .iter()
2480 .copied()
2481 .chain(predicates[self.own_assoc_ty_bounds_start as usize..].iter().copied())
2482 })
2483 }
2484}
2485
2486pub(crate) fn param_env_from_predicates<'db>(
2487 interner: DbInterner<'db>,
2488 predicates: &'db GenericPredicates,
2489) -> ParamEnv<'db> {
2490 let clauses = rustc_type_ir::elaborate::elaborate(
2491 interner,
2492 predicates.all_predicates().iter_identity().map(Unnormalized::skip_norm_wip),
2493 );
2494 let clauses = Clauses::new_from_iter(interner, clauses);
2495
2496 ParamEnv { clauses }
2498}
2499
2500pub(crate) fn trait_environment<'db>(db: &'db dyn HirDatabase, def: GenericDefId) -> ParamEnv<'db> {
2501 return ParamEnv { clauses: trait_environment_query(db, def).as_ref() };
2502
2503 #[salsa::tracked(returns(ref))]
2504 pub(crate) fn trait_environment_query(
2505 db: &dyn HirDatabase,
2506 def: GenericDefId,
2507 ) -> StoredClauses {
2508 let module = def.module(db);
2509 let interner = DbInterner::new_with(db, module.krate(db));
2510 let predicates = GenericPredicates::query(db, def);
2511 param_env_from_predicates(interner, predicates).clauses.store()
2512 }
2513}
2514
2515#[tracing::instrument(skip(db), ret)]
2518fn generic_predicates<'db>(
2519 db: &'db dyn HirDatabase,
2520 def: GenericDefId,
2521) -> TyLoweringResult<'db, GenericPredicates> {
2522 let generics = generics(db, def);
2523 let store = generics.store();
2524 let generics = &OnceCell::from(generics);
2525 let resolver = def.resolver(db);
2526 let interner = DbInterner::new_no_crate(db);
2527 let mut ctx = TyLoweringContext::new(
2528 db,
2529 &resolver,
2530 store,
2531 ExpressionStoreOwnerId::Signature(def),
2532 def,
2533 generics,
2534 LifetimeElisionKind::AnonymousReportError,
2535 LifetimeLoweringMode::Bound,
2536 );
2537 let generics = generics.get().unwrap();
2538 let sized_trait = ctx.lang_items.Sized;
2539
2540 let mut own_predicates = Vec::new();
2543 let mut parent_predicates = Vec::new();
2544 let mut own_assoc_ty_bounds = Vec::new();
2545 let mut parent_assoc_ty_bounds = Vec::new();
2546 let own_implicit_trait_predicate = implicit_trait_predicate(interner, def);
2547 let parent_implicit_trait_predicate = if let Some(parent) = generics.parent() {
2548 implicit_trait_predicate(interner, parent.def())
2549 } else {
2550 None
2551 };
2552 for maybe_parent_generics in generics.iter_owners() {
2553 ctx.diagnostics.clear();
2555
2556 ctx.set_owner(maybe_parent_generics);
2557 for pred in maybe_parent_generics.where_predicates() {
2558 tracing::debug!(?pred);
2559 for (pred, source) in ctx.lower_where_predicate(pred, false) {
2560 match source {
2561 GenericPredicateSource::SelfOnly => {
2562 if maybe_parent_generics.def() == def {
2563 own_predicates.push(pred);
2564 } else {
2565 parent_predicates.push(pred);
2566 }
2567 }
2568 GenericPredicateSource::AssocTyBound => {
2569 if maybe_parent_generics.def() == def {
2570 own_assoc_ty_bounds.push(pred);
2571 } else {
2572 parent_assoc_ty_bounds.push(pred);
2573 }
2574 }
2575 }
2576 }
2577 }
2578
2579 if maybe_parent_generics.def() == def {
2580 push_const_arg_has_type_predicates(db, &mut own_predicates, maybe_parent_generics);
2581 } else {
2582 push_const_arg_has_type_predicates(db, &mut parent_predicates, maybe_parent_generics);
2583 }
2584
2585 if let Some(sized_trait) = sized_trait {
2586 let mut add_sized_clause = |param_idx, param_id, param_data| {
2587 let (
2588 GenericParamId::TypeParamId(param_id),
2589 GenericParamDataRef::TypeParamData(param_data),
2590 ) = (param_id, param_data)
2591 else {
2592 return;
2593 };
2594
2595 if param_data.provenance == TypeParamProvenance::TraitSelf {
2596 return;
2597 }
2598
2599 let param_ty = Ty::new_param(interner, param_id, param_idx);
2600 if ctx.unsized_types.contains(¶m_ty) {
2601 return;
2602 }
2603 let trait_ref = TraitRef::new_from_args(
2604 interner,
2605 sized_trait.into(),
2606 GenericArgs::new_from_slice(&[param_ty.into()]),
2607 );
2608 let clause = Clause(Predicate::new(
2609 interner,
2610 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
2611 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
2612 trait_ref,
2613 polarity: rustc_type_ir::PredicatePolarity::Positive,
2614 }),
2615 )),
2616 ));
2617 if maybe_parent_generics.def() == def {
2618 own_predicates.push(clause);
2619 } else {
2620 parent_predicates.push(clause);
2621 }
2622 };
2623 maybe_parent_generics.iter_with_idx().for_each(|(param_idx, param_id, param_data)| {
2624 add_sized_clause(param_idx, param_id, param_data);
2625 });
2626 }
2627
2628 }
2633
2634 let diagnostics = mem::take(&mut ctx.diagnostics);
2635 let defined_anon_consts = mem::take(&mut ctx.defined_anon_consts);
2636
2637 let predicates = parent_implicit_trait_predicate
2638 .iter()
2639 .chain(own_implicit_trait_predicate.iter())
2640 .chain(parent_assoc_ty_bounds.iter())
2641 .chain(parent_predicates.iter())
2642 .chain(own_predicates.iter())
2643 .chain(own_assoc_ty_bounds.iter())
2644 .copied()
2645 .collect::<Vec<_>>();
2646 let has_trait_implied_predicate =
2647 parent_implicit_trait_predicate.is_some() || own_implicit_trait_predicate.is_some();
2648 let parent_explicit_self_predicates_start =
2649 has_trait_implied_predicate as u32 + parent_assoc_ty_bounds.len() as u32;
2650 let own_predicates_start =
2651 parent_explicit_self_predicates_start + parent_predicates.len() as u32;
2652 let own_assoc_ty_bounds_start = own_predicates_start + own_predicates.len() as u32;
2653
2654 let predicates = GenericPredicates {
2655 has_trait_implied_predicate,
2656 parent_explicit_self_predicates_start,
2657 own_predicates_start,
2658 own_assoc_ty_bounds_start,
2659 predicates: StoredEarlyBinder::bind(Clauses::new_from_slice(&predicates).store()),
2660 };
2661 return TyLoweringResult::new(predicates, diagnostics, defined_anon_consts);
2662
2663 fn implicit_trait_predicate<'db>(
2664 interner: DbInterner<'db>,
2665 def: GenericDefId,
2666 ) -> Option<Clause<'db>> {
2667 if let GenericDefId::TraitId(def_id) = def {
2680 Some(TraitRef::identity(interner, def_id.into()).upcast(interner))
2681 } else {
2682 None
2683 }
2684 }
2685}
2686
2687fn push_const_arg_has_type_predicates<'db>(
2688 db: &'db dyn HirDatabase,
2689 predicates: &mut Vec<Clause<'db>>,
2690 single_generics: &SingleGenerics<'db>,
2691) {
2692 let interner = DbInterner::new_no_crate(db);
2693 for (param_index, param_id, _) in single_generics.iter_with_idx() {
2694 let GenericParamId::ConstParamId(param_id) = param_id else { continue };
2695 predicates.push(Clause(
2696 ClauseKind::ConstArgHasType(
2697 Const::new_param(interner, ParamConst { id: param_id, index: param_index }),
2698 db.const_param_ty(param_id),
2699 )
2700 .upcast(interner),
2701 ));
2702 }
2703}
2704
2705#[derive(Debug, Clone, PartialEq, Eq, Hash, SalsaValue)]
2706pub struct GenericDefaults(ThinVec<Option<StoredEarlyBinder<StoredGenericArg>>>);
2707
2708impl GenericDefaults {
2709 #[inline]
2710 pub fn as_ref(&self) -> GenericDefaultsRef<'_> {
2711 GenericDefaultsRef(&self.0)
2712 }
2713}
2714
2715#[derive(Debug, Clone, Copy)]
2716pub struct GenericDefaultsRef<'db>(&'db [Option<StoredEarlyBinder<StoredGenericArg>>]);
2717
2718impl<'db> GenericDefaultsRef<'db> {
2719 #[inline]
2720 pub fn get(self, idx: usize) -> Option<EarlyBinder<'db, GenericArg<'db>>> {
2721 Some(self.0.get(idx)?.as_ref()?.get())
2722 }
2723}
2724
2725pub(crate) fn generic_defaults(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaultsRef<'_> {
2726 generic_defaults_with_diagnostics(db, def).value.as_ref()
2727}
2728
2729#[salsa::tracked(returns(ref), cycle_result = generic_defaults_with_diagnostics_cycle_result)]
2733pub(crate) fn generic_defaults_with_diagnostics<'db>(
2734 db: &'db dyn HirDatabase,
2735 def: GenericDefId,
2736) -> TyLoweringResult<'db, GenericDefaults> {
2737 let generics = generics(db, def);
2738 if generics.has_no_params() {
2739 return TyLoweringResult::empty(GenericDefaults(ThinVec::new()));
2740 }
2741 let resolver = def.resolver(db);
2742
2743 let store_for_self = generics.store();
2744 let generics = &OnceCell::from(generics);
2745 let mut ctx = TyLoweringContext::new(
2746 db,
2747 &resolver,
2748 store_for_self,
2749 ExpressionStoreOwnerId::Signature(def),
2750 def,
2751 generics,
2752 LifetimeElisionKind::AnonymousReportError,
2753 LifetimeLoweringMode::Bound,
2754 )
2755 .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
2756 let generics = generics.get().unwrap();
2757 let mut defaults = ThinVec::new();
2758 if let Some(parent) = generics.parent() {
2759 ctx.set_owner(parent);
2760 defaults.extend(
2761 parent.iter_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
2762 );
2763 }
2764 ctx.diagnostics.clear(); ctx.defined_anon_consts.clear();
2766 ctx.set_owner(generics.owner());
2767 defaults.extend(
2768 generics.iter_self_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
2769 );
2770 defaults.shrink_to_fit();
2771 return TyLoweringResult::from_ctx(GenericDefaults(defaults), ctx);
2772
2773 fn handle_generic_param<'db>(
2774 ctx: &mut TyLoweringContext<'db, '_>,
2775 idx: u32,
2776 p: GenericParamDataRef<'_>,
2777 ) -> Option<StoredEarlyBinder<StoredGenericArg>> {
2778 ctx.forbid_params_after(idx, ForbidParamsAfterReason::LoweringParamDefault);
2779 match p {
2780 GenericParamDataRef::TypeParamData(p) => {
2781 let ty = p.default.map(|ty| ctx.lower_ty(ty));
2782 ty.map(|ty| StoredEarlyBinder::bind(GenericArg::from(ty).store()))
2783 }
2784 GenericParamDataRef::ConstParamData(p) => {
2785 let val = p.default.map(|c| {
2786 let param_ty = ctx.lower_ty(p.ty);
2787 let c = ctx.lower_const(c, param_ty);
2788 GenericArg::from(c).store()
2789 });
2790 val.map(StoredEarlyBinder::bind)
2791 }
2792 GenericParamDataRef::LifetimeParamData(_) => None,
2793 }
2794 }
2795}
2796
2797fn generic_defaults_with_diagnostics_cycle_result<'db>(
2798 _db: &'db dyn HirDatabase,
2799 _: salsa::Id,
2800 _def: GenericDefId,
2801) -> TyLoweringResult<'db, GenericDefaults> {
2802 TyLoweringResult::empty(GenericDefaults(ThinVec::new()))
2803}
2804
2805pub(crate) fn callable_item_signature<'db>(
2807 db: &'db dyn HirDatabase,
2808 def: CallableDefId,
2809) -> EarlyBinder<'db, PolyFnSig<'db>> {
2810 match def {
2811 CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f).value.value.get(),
2812 CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s).get(),
2813 CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e).get(),
2814 }
2815}
2816
2817#[salsa::tracked(returns(ref))]
2818pub(crate) fn fn_sig_for_fn<'db>(
2819 db: &'db dyn HirDatabase,
2820 def: FunctionId,
2821) -> TyLoweringResult<'db, WithDefinedOpaques<StoredEarlyBinder<StoredPolyFnSig>>> {
2822 let data = FunctionSignature::of(db, def);
2823 let resolver = def.resolver(db);
2824 let interner = DbInterner::new_no_crate(db);
2825 let generics = OnceCell::new();
2826 let mut ctx_params = TyLoweringContext::new(
2827 db,
2828 &resolver,
2829 &data.store,
2830 ExpressionStoreOwnerId::Signature(def.into()),
2831 def.into(),
2832 &generics,
2833 LifetimeElisionKind::for_fn_params(data),
2834 LifetimeLoweringMode::Bound,
2835 );
2836 let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
2837
2838 let mut ctx_ret = TyLoweringContext::new(
2839 db,
2840 &resolver,
2841 &data.store,
2842 ExpressionStoreOwnerId::Signature(def.into()),
2843 def.into(),
2844 &generics,
2845 LifetimeElisionKind::for_fn_ret(interner),
2846 LifetimeLoweringMode::Bound,
2847 )
2848 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
2849 let ret = match data.ret_type {
2850 Some(ret_type) => ctx_ret.lower_ty(ret_type),
2851 None => Ty::new_unit(interner),
2852 };
2853 let impl_traits = ctx_ret.take_defined_opaques();
2854
2855 let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret)));
2856 ctx_params.diagnostics.extend(ctx_ret.diagnostics);
2857 ctx_params.defined_anon_consts.extend(ctx_ret.defined_anon_consts);
2858
2859 let binder = TyLoweringContext::bound_vars(db, interner, def.into(), &generics);
2860 let result = StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::bind_with_vars(
2861 FnSig {
2862 inputs_and_output,
2863 fn_sig_kind: FnSigKind::new(
2864 data.abi,
2865 if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
2866 data.is_varargs(),
2867 ),
2868 },
2869 binder,
2870 )));
2871 TyLoweringResult::from_ctx(WithDefinedOpaques { value: result, impl_traits }, ctx_params)
2872}
2873
2874fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> {
2875 let interner = DbInterner::new_no_crate(db);
2876 let args = GenericArgs::identity_for_item(interner, adt.into());
2877 let ty = Ty::new_adt(interner, adt, args);
2878 EarlyBinder::bind(ty)
2879}
2880
2881fn ctor_signature(
2882 db: &dyn HirDatabase,
2883 variant: VariantId,
2884 adt: AdtId,
2885) -> StoredEarlyBinder<StoredPolyFnSig> {
2886 let field_tys = db.field_types(variant);
2887 let params = field_tys.iter().map(|(_, field)| field.ty().skip_binder());
2888 let ret = type_for_adt(db, adt).skip_binder();
2889
2890 let inputs_and_output =
2891 Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret)));
2892 StoredEarlyBinder::bind(StoredPolyFnSig::new(Binder::dummy(FnSig {
2893 fn_sig_kind: FnSigKind::new(ExternAbi::Rust, Safety::Safe, false),
2894 inputs_and_output,
2895 })))
2896}
2897
2898#[salsa::tracked(returns(ref))]
2899fn fn_sig_for_struct_constructor(
2900 db: &dyn HirDatabase,
2901 def: StructId,
2902) -> StoredEarlyBinder<StoredPolyFnSig> {
2903 ctor_signature(db, def.into(), def.into())
2904}
2905
2906#[salsa::tracked(returns(ref))]
2907fn fn_sig_for_enum_variant_constructor(
2908 db: &dyn HirDatabase,
2909 def: EnumVariantId,
2910) -> StoredEarlyBinder<StoredPolyFnSig> {
2911 ctor_signature(db, def.into(), def.lookup(db).parent.into())
2912}
2913
2914pub(crate) fn associated_ty_item_bounds<'db>(
2916 db: &'db dyn HirDatabase,
2917 type_alias: TypeAliasId,
2918) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
2919 let type_alias_data = TypeAliasSignature::of(db, type_alias);
2920 let resolver = type_alias.resolver(db);
2921 let interner = DbInterner::new_no_crate(db);
2922 let generics = OnceCell::new();
2923 let mut ctx = TyLoweringContext::new(
2924 db,
2925 &resolver,
2926 &type_alias_data.store,
2927 ExpressionStoreOwnerId::Signature(type_alias.into()),
2928 type_alias.into(),
2929 &generics,
2930 LifetimeElisionKind::AnonymousReportError,
2931 LifetimeLoweringMode::Bound,
2932 );
2933 let self_ty = Ty::new_error(interner, ErrorGuaranteed);
2936
2937 let mut bounds = Vec::new();
2938 for bound in &type_alias_data.bounds {
2939 ctx.lower_type_bound(bound, self_ty, false).for_each(|(pred, _)| {
2940 if let Some(bound) = pred
2941 .kind()
2942 .map_bound(|c| match c {
2943 rustc_type_ir::ClauseKind::Trait(t) => {
2944 let id = t.def_id();
2945 let is_auto = TraitSignature::of(db, id.0).flags.contains(TraitFlags::AUTO);
2946 if is_auto {
2947 Some(ExistentialPredicate::AutoTrait(t.def_id()))
2948 } else {
2949 Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args(
2950 interner,
2951 t.def_id(),
2952 GenericArgs::new_from_slice(&t.trait_ref.args[1..]),
2953 )))
2954 }
2955 }
2956 rustc_type_ir::ClauseKind::Projection(p) => Some(
2957 ExistentialPredicate::Projection(ExistentialProjection::new_from_args(
2958 interner,
2959 p.def_id(),
2960 GenericArgs::new_from_slice(&p.projection_term.args[1..]),
2961 p.term,
2962 )),
2963 ),
2964 rustc_type_ir::ClauseKind::TypeOutlives(_) => None,
2965 rustc_type_ir::ClauseKind::RegionOutlives(_)
2966 | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
2967 | rustc_type_ir::ClauseKind::WellFormed(_)
2968 | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
2969 | rustc_type_ir::ClauseKind::HostEffect(_)
2970 | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
2971 })
2972 .transpose()
2973 {
2974 bounds.push(bound);
2975 }
2976 });
2977 }
2978
2979 if !ctx.unsized_types.contains(&self_ty)
2980 && let Some(sized_trait) = ctx.lang_items.Sized
2981 {
2982 let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new(
2983 interner,
2984 sized_trait.into(),
2985 [] as [GenericArg<'_>; 0],
2986 )));
2987 bounds.push(sized_clause);
2988 }
2989
2990 EarlyBinder::bind(BoundExistentialPredicates::new_from_slice(&bounds))
2991}
2992
2993pub(crate) fn associated_type_by_name_including_super_traits_allow_ambiguity<'db>(
2994 db: &'db dyn HirDatabase,
2995 trait_ref: TraitRef<'db>,
2996 name: Name,
2997) -> Option<(TypeAliasId, GenericArgs<'db>)> {
2998 let (AssocTypeShorthandResolution::Resolved(assoc_type)
2999 | AssocTypeShorthandResolution::Ambiguous { sub_trait_resolution: Some(assoc_type) }) =
3000 resolve_type_param_assoc_type_shorthand(
3001 db,
3002 trait_ref.def_id.0.into(),
3003 TypeParamId::trait_self(trait_ref.def_id.0),
3004 name.clone(),
3005 )
3006 else {
3007 return None;
3008 };
3009 let (assoc_type, trait_args) = assoc_type
3010 .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref()))
3011 .skip_binder();
3012 let interner = DbInterner::new_no_crate(db);
3013 Some((
3014 assoc_type,
3015 EarlyBinder::bind(trait_args).instantiate(interner, trait_ref.args).skip_norm_wip(),
3016 ))
3017}