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