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