1pub(crate) mod diagnostics;
9pub(crate) mod path;
10
11use std::{cell::OnceCell, iter, mem};
12
13use arrayvec::ArrayVec;
14use either::Either;
15use hir_def::{
16 AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
17 FunctionId, GeneralConstId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId,
18 LifetimeParamId, LocalFieldId, Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId,
19 TypeParamId, UnionId, VariantId,
20 builtin_type::BuiltinType,
21 expr_store::{ExpressionStore, HygieneId, path::Path},
22 hir::generics::{
23 GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
24 },
25 item_tree::FieldsShape,
26 lang_item::LangItems,
27 resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
28 signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
29 type_ref::{
30 ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier,
31 TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
32 },
33};
34use hir_expand::name::Name;
35use la_arena::{Arena, ArenaMap, Idx};
36use path::{PathDiagnosticCallback, PathLoweringContext};
37use rustc_ast_ir::Mutability;
38use rustc_hash::FxHashSet;
39use rustc_pattern_analysis::Captures;
40use rustc_type_ir::{
41 AliasTyKind, BoundVarIndexKind, ConstKind, DebruijnIndex, ExistentialPredicate,
42 ExistentialProjection, ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind,
43 TyKind::{self},
44 TypeFoldable, TypeVisitableExt, Upcast, UpcastFrom, elaborate,
45 inherent::{
46 Clause as _, GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike,
47 Ty as _,
48 },
49};
50use smallvec::{SmallVec, smallvec};
51use stdx::{impl_from, never};
52use tracing::debug;
53use triomphe::{Arc, ThinArc};
54
55use crate::{
56 FnAbi, ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
57 consteval::intern_const_ref,
58 db::{HirDatabase, InternedOpaqueTyId},
59 generics::{Generics, generics, trait_self_param_idx},
60 next_solver::{
61 AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const,
62 DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FxIndexMap, GenericArg,
63 GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, SolverDefId,
64 TraitPredicate, TraitRef, Ty, Tys, UnevaluatedConst, abi::Safety, util::BottomUpFolder,
65 },
66};
67
68pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId);
69
70#[derive(PartialEq, Eq, Debug, Hash)]
71pub struct ImplTraits<'db> {
72 pub(crate) impl_traits: Arena<ImplTrait<'db>>,
73}
74
75#[derive(PartialEq, Eq, Debug, Hash)]
76pub struct ImplTrait<'db> {
77 pub(crate) predicates: Box<[Clause<'db>]>,
78}
79
80pub type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>;
81
82#[derive(Debug, Default)]
83struct ImplTraitLoweringState<'db> {
84 mode: ImplTraitLoweringMode,
88 opaque_type_data: Arena<ImplTrait<'db>>,
90}
91
92impl<'db> ImplTraitLoweringState<'db> {
93 fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState<'db> {
94 Self { mode, opaque_type_data: Arena::new() }
95 }
96}
97
98#[derive(Debug, Clone)]
99pub enum LifetimeElisionKind<'db> {
100 AnonymousCreateParameter { report_in_path: bool },
115
116 Elided(Region<'db>),
118
119 AnonymousReportError,
123
124 StaticIfNoLifetimeInScope { only_lint: bool },
128
129 ElisionFailure,
131
132 Infer,
134}
135
136impl<'db> LifetimeElisionKind<'db> {
137 #[inline]
138 pub(crate) fn for_const(
139 interner: DbInterner<'db>,
140 const_parent: ItemContainerId,
141 ) -> LifetimeElisionKind<'db> {
142 match const_parent {
143 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
144 LifetimeElisionKind::Elided(Region::new_static(interner))
145 }
146 ItemContainerId::ImplId(_) => {
147 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true }
148 }
149 ItemContainerId::TraitId(_) => {
150 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false }
151 }
152 }
153 }
154
155 #[inline]
156 pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> {
157 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() }
158 }
159
160 #[inline]
161 pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> {
162 LifetimeElisionKind::Elided(Region::error(interner))
164 }
165}
166
167#[derive(Debug)]
168pub struct TyLoweringContext<'db, 'a> {
169 pub db: &'db dyn HirDatabase,
170 interner: DbInterner<'db>,
171 lang_items: &'db LangItems,
172 resolver: &'a Resolver<'db>,
173 store: &'a ExpressionStore,
174 def: GenericDefId,
175 generics: OnceCell<Generics>,
176 in_binders: DebruijnIndex,
177 impl_trait_mode: ImplTraitLoweringState<'db>,
178 pub(crate) unsized_types: FxHashSet<Ty<'db>>,
180 pub(crate) diagnostics: Vec<TyLoweringDiagnostic>,
181 lifetime_elision: LifetimeElisionKind<'db>,
182 lowering_param_default: Option<u32>,
185}
186
187impl<'db, 'a> TyLoweringContext<'db, 'a> {
188 pub fn new(
189 db: &'db dyn HirDatabase,
190 resolver: &'a Resolver<'db>,
191 store: &'a ExpressionStore,
192 def: GenericDefId,
193 lifetime_elision: LifetimeElisionKind<'db>,
194 ) -> Self {
195 let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
196 let in_binders = DebruijnIndex::ZERO;
197 let interner = DbInterner::new_with(db, resolver.krate());
198 Self {
199 db,
200 interner,
202 lang_items: interner.lang_items(),
203 resolver,
204 def,
205 generics: Default::default(),
206 store,
207 in_binders,
208 impl_trait_mode,
209 unsized_types: FxHashSet::default(),
210 diagnostics: Vec::new(),
211 lifetime_elision,
212 lowering_param_default: None,
213 }
214 }
215
216 pub(crate) fn set_lifetime_elision(&mut self, lifetime_elision: LifetimeElisionKind<'db>) {
217 self.lifetime_elision = lifetime_elision;
218 }
219
220 pub(crate) fn with_debruijn<T>(
221 &mut self,
222 debruijn: DebruijnIndex,
223 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
224 ) -> T {
225 let old_debruijn = mem::replace(&mut self.in_binders, debruijn);
226 let result = f(self);
227 self.in_binders = old_debruijn;
228 result
229 }
230
231 pub(crate) fn with_shifted_in<T>(
232 &mut self,
233 debruijn: DebruijnIndex,
234 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
235 ) -> T {
236 self.with_debruijn(self.in_binders.shifted_in(debruijn.as_u32()), f)
237 }
238
239 pub(crate) fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
240 Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self }
241 }
242
243 pub(crate) fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self {
244 self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode);
245 self
246 }
247
248 pub(crate) fn lowering_param_default(&mut self, index: u32) {
249 self.lowering_param_default = Some(index);
250 }
251
252 pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
253 self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind });
254 }
255}
256
257#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
258pub(crate) enum ImplTraitLoweringMode {
259 Opaque,
264 #[default]
266 Disallowed,
267}
268
269impl<'db, 'a> TyLoweringContext<'db, 'a> {
270 pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
271 self.lower_ty_ext(type_ref).0
272 }
273
274 pub(crate) fn lower_const(&mut self, const_ref: ConstRef, const_type: Ty<'db>) -> Const<'db> {
275 let const_ref = &self.store[const_ref.expr];
276 match const_ref {
277 hir_def::hir::Expr::Path(path) => {
278 self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
279 }
280 hir_def::hir::Expr::Literal(literal) => intern_const_ref(
281 self.db,
282 &match *literal {
283 hir_def::hir::Literal::Float(_, _)
284 | hir_def::hir::Literal::String(_)
285 | hir_def::hir::Literal::ByteString(_)
286 | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown,
287 hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c),
288 hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b),
289 hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val),
290 hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val),
291 },
292 const_type,
293 self.resolver.krate(),
294 ),
295 hir_def::hir::Expr::UnaryOp { expr: inner_expr, op: hir_def::hir::UnaryOp::Neg } => {
296 if let hir_def::hir::Expr::Literal(literal) = &self.store[*inner_expr] {
297 match literal {
299 hir_def::hir::Literal::Int(_, _) | hir_def::hir::Literal::Float(_, _) => {
300 if let Some(negated_literal) = literal.clone().negate() {
301 intern_const_ref(
302 self.db,
303 &negated_literal.into(),
304 const_type,
305 self.resolver.krate(),
306 )
307 } else {
308 unknown_const(const_type)
309 }
310 }
311 _ => unknown_const(const_type),
313 }
314 } else {
315 unknown_const(const_type)
316 }
317 }
318 _ => unknown_const(const_type),
319 }
320 }
321
322 pub(crate) fn path_to_const(&mut self, path: &Path) -> Option<Const<'db>> {
323 match self.resolver.resolve_path_in_value_ns_fully(self.db, path, HygieneId::ROOT) {
324 Some(ValueNs::GenericParam(p)) => {
325 let args = self.generics();
326 match args.type_or_const_param_idx(p.into()) {
327 Some(idx) => Some(self.const_param(p, idx as u32)),
328 None => {
329 never!(
330 "Generic list doesn't contain this param: {:?}, {:?}, {:?}",
331 args,
332 path,
333 p
334 );
335 None
336 }
337 }
338 }
339 Some(ValueNs::ConstId(c)) => {
340 let args = GenericArgs::new_from_iter(self.interner, []);
341 Some(Const::new(
342 self.interner,
343 rustc_type_ir::ConstKind::Unevaluated(UnevaluatedConst::new(
344 GeneralConstId::ConstId(c).into(),
345 args,
346 )),
347 ))
348 }
349 _ => None,
350 }
351 }
352
353 pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> {
354 self.path_to_const(path).unwrap_or_else(|| unknown_const(const_type))
355 }
356
357 fn generics(&self) -> &Generics {
358 self.generics.get_or_init(|| generics(self.db, self.def))
359 }
360
361 fn param_index_is_disallowed(&self, index: u32) -> bool {
362 self.lowering_param_default
363 .is_some_and(|disallow_params_after| index >= disallow_params_after)
364 }
365
366 fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> {
367 if self.param_index_is_disallowed(index) {
368 Ty::new_error(self.interner, ErrorGuaranteed)
370 } else {
371 Ty::new_param(self.interner, id, index)
372 }
373 }
374
375 fn const_param(&mut self, id: ConstParamId, index: u32) -> Const<'db> {
376 if self.param_index_is_disallowed(index) {
377 Const::error(self.interner)
379 } else {
380 Const::new_param(self.interner, ParamConst { id, index })
381 }
382 }
383
384 fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> {
385 if self.param_index_is_disallowed(index) {
386 Region::error(self.interner)
388 } else {
389 Region::new_early_param(self.interner, EarlyParamRegion { id, index })
390 }
391 }
392
393 #[tracing::instrument(skip(self), ret)]
394 pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) {
395 let interner = self.interner;
396 let mut res = None;
397 let type_ref = &self.store[type_ref_id];
398 tracing::debug!(?type_ref);
399 let ty = match type_ref {
400 TypeRef::Never => Ty::new(interner, TyKind::Never),
401 TypeRef::Tuple(inner) => {
402 let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr));
403 Ty::new_tup_from_iter(interner, inner_tys)
404 }
405 TypeRef::Path(path) => {
406 let (ty, res_) =
407 self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id));
408 res = res_;
409 ty
410 }
411 &TypeRef::TypeParam(type_param_id) => {
412 res = Some(TypeNs::GenericParam(type_param_id));
413
414 let generics = self.generics();
415 let (idx, _data) =
416 generics.type_or_const_param(type_param_id.into()).expect("matching generics");
417 self.type_param(type_param_id, idx as u32)
418 }
419 &TypeRef::RawPtr(inner, mutability) => {
420 let inner_ty = self.lower_ty(inner);
421 Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability)))
422 }
423 TypeRef::Array(array) => {
424 let inner_ty = self.lower_ty(array.ty);
425 let const_len = self.lower_const(array.len, Ty::new_usize(interner));
426 Ty::new_array_with_const_len(interner, inner_ty, const_len)
427 }
428 &TypeRef::Slice(inner) => {
429 let inner_ty = self.lower_ty(inner);
430 Ty::new_slice(interner, inner_ty)
431 }
432 TypeRef::Reference(ref_) => {
433 let inner_ty = self.lower_ty(ref_.ty);
434 let lifetime = ref_
436 .lifetime
437 .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr));
438 Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability))
439 }
440 TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed),
441 TypeRef::Fn(fn_) => {
442 let substs = self.with_shifted_in(
443 DebruijnIndex::from_u32(1),
444 |ctx: &mut TyLoweringContext<'_, '_>| {
445 Tys::new_from_iter(
446 interner,
447 fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)),
448 )
449 },
450 );
451 Ty::new_fn_ptr(
452 interner,
453 Binder::dummy(FnSig {
454 abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
455 safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
456 c_variadic: fn_.is_varargs,
457 inputs_and_output: substs,
458 }),
459 )
460 }
461 TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
462 TypeRef::ImplTrait(bounds) => {
463 match self.impl_trait_mode.mode {
464 ImplTraitLoweringMode::Opaque => {
465 let origin = match self.resolver.generic_def() {
466 Some(GenericDefId::FunctionId(it)) => Either::Left(it),
467 Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
468 _ => panic!(
469 "opaque impl trait lowering must be in function or type alias"
470 ),
471 };
472
473 let idx = self
477 .impl_trait_mode
478 .opaque_type_data
479 .alloc(ImplTrait { predicates: Box::default() });
480
481 let impl_trait_id = origin.either(
482 |f| ImplTraitId::ReturnTypeImplTrait(f, idx),
483 |a| ImplTraitId::TypeAliasImplTrait(a, idx),
484 );
485 let opaque_ty_id: SolverDefId =
486 self.db.intern_impl_trait_id(impl_trait_id).into();
487
488 let actual_opaque_type_data = self
498 .with_debruijn(DebruijnIndex::ZERO, |ctx| {
499 ctx.lower_impl_trait(opaque_ty_id, bounds)
500 });
501 self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
502
503 let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id);
504 Ty::new_alias(
505 self.interner,
506 AliasTyKind::Opaque,
507 AliasTy::new_from_args(self.interner, opaque_ty_id, args),
508 )
509 }
510 ImplTraitLoweringMode::Disallowed => {
511 Ty::new_error(self.interner, ErrorGuaranteed)
513 }
514 }
515 }
516 TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed),
517 };
518 (ty, res)
519 }
520
521 fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option<TypeOrConstParamId> {
525 let type_ref = &self.store[type_ref];
526 let path = match type_ref {
527 TypeRef::Path(path) => path,
528 &TypeRef::TypeParam(idx) => return Some(idx.into()),
529 _ => return None,
530 };
531 if path.type_anchor().is_some() {
532 return None;
533 }
534 if path.segments().len() > 1 {
535 return None;
536 }
537 let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) {
538 Some((it, None, _)) => it,
539 _ => return None,
540 };
541 match resolution {
542 TypeNs::GenericParam(param_id) => Some(param_id.into()),
543 _ => None,
544 }
545 }
546
547 #[inline]
548 fn on_path_diagnostic_callback<'b>(type_ref: TypeRefId) -> PathDiagnosticCallback<'b, 'db> {
549 PathDiagnosticCallback {
550 data: Either::Left(PathDiagnosticCallbackData(type_ref)),
551 callback: |data, this, diag| {
552 let type_ref = data.as_ref().left().unwrap().0;
553 this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag))
554 },
555 }
556 }
557
558 #[inline]
559 fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> {
560 PathLoweringContext::new(
561 self,
562 Self::on_path_diagnostic_callback(path_id.type_ref()),
563 &self.store[path_id],
564 )
565 }
566
567 pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option<TypeNs>) {
568 if let Some(type_ref) = path.type_anchor() {
570 let (ty, res) = self.lower_ty_ext(type_ref);
571 let mut ctx = self.at_path(path_id);
572 return ctx.lower_ty_relative_path(ty, res, false);
573 }
574
575 let mut ctx = self.at_path(path_id);
576 let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() {
577 Some(it) => it,
578 None => return (Ty::new_error(self.interner, ErrorGuaranteed), None),
579 };
580
581 if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
582 let bound = TypeBound::Path(path_id, TraitBoundModifier::None);
584 let ty = self.lower_dyn_trait(&[bound]);
585 return (ty, None);
586 }
587
588 ctx.lower_partly_resolved_path(resolution, false)
589 }
590
591 fn lower_trait_ref_from_path(
592 &mut self,
593 path_id: PathId,
594 explicit_self_ty: Ty<'db>,
595 ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> {
596 let mut ctx = self.at_path(path_id);
597 let resolved = match ctx.resolve_path_in_type_ns_fully()? {
598 TypeNs::TraitId(tr) => tr,
600 _ => return None,
601 };
602 Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx))
603 }
604
605 fn lower_trait_ref(
606 &mut self,
607 trait_ref: &HirTraitRef,
608 explicit_self_ty: Ty<'db>,
609 ) -> Option<TraitRef<'db>> {
610 self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
611 }
612
613 pub(crate) fn lower_where_predicate<'b>(
614 &'b mut self,
615 where_predicate: &'b WherePredicate,
616 ignore_bindings: bool,
617 generics: &Generics,
618 predicate_filter: PredicateFilter,
619 ) -> impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'db> {
620 match where_predicate {
621 WherePredicate::ForLifetime { target, bound, .. }
622 | WherePredicate::TypeBound { target, bound } => {
623 if let PredicateFilter::SelfTrait = predicate_filter {
624 let target_type = &self.store[*target];
625 let self_type = 'is_self: {
626 if let TypeRef::Path(path) = target_type
627 && path.is_self_type()
628 {
629 break 'is_self true;
630 }
631 if let TypeRef::TypeParam(param) = target_type
632 && generics[param.local_id()].is_trait_self()
633 {
634 break 'is_self true;
635 }
636 false
637 };
638 if !self_type {
639 return Either::Left(Either::Left(iter::empty()));
640 }
641 }
642 let self_ty = self.lower_ty(*target);
643 Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings)))
644 }
645 &WherePredicate::Lifetime { bound, target } => {
646 Either::Right(iter::once(Clause(Predicate::new(
647 self.interner,
648 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
649 rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate(
650 self.lower_lifetime(bound),
651 self.lower_lifetime(target),
652 )),
653 )),
654 ))))
655 }
656 }
657 .into_iter()
658 }
659
660 pub(crate) fn lower_type_bound<'b>(
661 &'b mut self,
662 bound: &'b TypeBound,
663 self_ty: Ty<'db>,
664 ignore_bindings: bool,
665 ) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> {
666 let interner = self.interner;
667 let meta_sized = self.lang_items.MetaSized;
668 let pointee_sized = self.lang_items.PointeeSized;
669 let mut assoc_bounds = None;
670 let mut clause = None;
671 match bound {
672 &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
673 if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
675 if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) {
678 } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) {
680 ctx.ty_ctx().unsized_types.insert(self_ty);
682 } else {
683 if !ignore_bindings {
684 assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref);
685 }
686 clause = Some(Clause(Predicate::new(
687 interner,
688 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
689 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
690 trait_ref,
691 polarity: rustc_type_ir::PredicatePolarity::Positive,
692 }),
693 )),
694 )));
695 }
696 }
697 }
698 &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
699 let sized_trait = self.lang_items.Sized;
700 let trait_id = self
704 .lower_trait_ref_from_path(path, self_ty)
705 .map(|(trait_ref, _)| trait_ref.def_id.0);
706 if trait_id == sized_trait {
707 self.unsized_types.insert(self_ty);
708 }
709 }
710 &TypeBound::Lifetime(l) => {
711 let lifetime = self.lower_lifetime(l);
712 clause = Some(Clause(Predicate::new(
713 self.interner,
714 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
715 rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate(
716 self_ty, lifetime,
717 )),
718 )),
719 )));
720 }
721 TypeBound::Use(_) | TypeBound::Error => {}
722 }
723 clause.into_iter().chain(assoc_bounds.into_iter().flatten())
724 }
725
726 fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> {
727 let interner = self.interner;
728 let dummy_self_ty = dyn_trait_dummy_self(interner);
729 let mut region = None;
730 let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
736 let mut principal = None;
737 let mut auto_traits = SmallVec::<[_; 3]>::new();
738 let mut projections = Vec::new();
739 let mut had_error = false;
740
741 for b in bounds {
742 let db = ctx.db;
743 ctx.lower_type_bound(b, dummy_self_ty, false).for_each(|b| {
744 match b.kind().skip_binder() {
745 rustc_type_ir::ClauseKind::Trait(t) => {
746 let id = t.def_id();
747 let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
748 if is_auto {
749 auto_traits.push(t.def_id().0);
750 } else {
751 if principal.is_some() {
752 had_error = true;
754 }
755 principal = Some(b.kind().rebind(t.trait_ref));
756 }
757 }
758 rustc_type_ir::ClauseKind::Projection(p) => {
759 projections.push(b.kind().rebind(p));
760 }
761 rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => {
762 if region.is_some() {
763 had_error = true;
765 }
766 region = Some(outlives_predicate.1);
767 }
768 rustc_type_ir::ClauseKind::RegionOutlives(_)
769 | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
770 | rustc_type_ir::ClauseKind::WellFormed(_)
771 | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
772 | rustc_type_ir::ClauseKind::HostEffect(_)
773 | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
774 }
775 })
776 }
777
778 if had_error {
779 return None;
780 }
781
782 if principal.is_none() && auto_traits.is_empty() {
783 return None;
785 }
786
787 auto_traits.sort_unstable();
789 auto_traits.dedup();
791
792 let mut projection_bounds = FxIndexMap::default();
802 for proj in projections {
803 let key = (
804 proj.skip_binder().def_id().expect_type_alias(),
805 interner.anonymize_bound_vars(
806 proj.map_bound(|proj| proj.projection_term.trait_ref(interner)),
807 ),
808 );
809 if let Some(old_proj) = projection_bounds.insert(key, proj)
810 && interner.anonymize_bound_vars(proj)
811 != interner.anonymize_bound_vars(old_proj)
812 {
813 }
815 }
816
817 let mut ordered_associated_types = vec![];
824
825 if let Some(principal_trait) = principal {
826 for clause in elaborate::elaborate(
827 interner,
828 [Clause::upcast_from(
829 TraitRef::identity(interner, principal_trait.def_id()),
830 interner,
831 )],
832 )
833 .filter_only_self()
834 {
835 let clause = clause.instantiate_supertrait(interner, principal_trait);
836 debug!("observing object predicate `{clause:?}`");
837
838 let bound_predicate = clause.kind();
839 match bound_predicate.skip_binder() {
840 ClauseKind::Trait(pred) => {
841 let trait_ref = interner
843 .anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
844 ordered_associated_types.extend(
845 pred.trait_ref
846 .def_id
847 .0
848 .trait_items(self.db)
849 .associated_types()
850 .map(|item| (item, trait_ref)),
851 );
852 }
853 ClauseKind::Projection(pred) => {
854 let pred = bound_predicate.rebind(pred);
855 let references_self = match pred.skip_binder().term.kind() {
858 TermKind::Ty(ty) => {
859 ty.walk().any(|arg| arg == dummy_self_ty.into())
860 }
861 TermKind::Const(_) => false,
863 };
864
865 if !references_self {
883 let key = (
884 pred.skip_binder().projection_term.def_id.expect_type_alias(),
885 interner.anonymize_bound_vars(pred.map_bound(|proj| {
886 proj.projection_term.trait_ref(interner)
887 })),
888 );
889 if !projection_bounds.contains_key(&key) {
890 projection_bounds.insert(key, pred);
891 }
892 }
893 }
894 _ => (),
895 }
896 }
897 }
898
899 let mut projection_bounds: Vec<_> = ordered_associated_types
906 .into_iter()
907 .filter_map(|key| projection_bounds.get(&key).copied())
908 .collect();
909
910 projection_bounds.sort_unstable_by_key(|proj| proj.skip_binder().def_id());
911
912 let principal = principal.map(|principal| {
913 principal.map_bound(|principal| {
914 let args: Vec<_> = principal
916 .args
917 .iter()
918 .skip(1)
920 .map(|arg| {
921 if arg.walk().any(|arg| arg == dummy_self_ty.into()) {
922 Ty::new_error(interner, ErrorGuaranteed).into()
924 } else {
925 arg
926 }
927 })
928 .collect();
929
930 ExistentialPredicate::Trait(ExistentialTraitRef::new(
931 interner,
932 principal.def_id,
933 args,
934 ))
935 })
936 });
937
938 let projections = projection_bounds.into_iter().map(|proj| {
939 proj.map_bound(|mut proj| {
940 let references_self = proj.projection_term.args.iter().skip(1).any(|arg| {
943 if arg.walk().any(|arg| arg == dummy_self_ty.into()) {
944 return true;
945 }
946 false
947 });
948 if references_self {
949 proj.projection_term =
950 replace_dummy_self_with_error(interner, proj.projection_term);
951 }
952
953 ExistentialPredicate::Projection(ExistentialProjection::erase_self_ty(
954 interner, proj,
955 ))
956 })
957 });
958
959 let auto_traits = auto_traits.into_iter().map(|auto_trait| {
960 Binder::dummy(ExistentialPredicate::AutoTrait(auto_trait.into()))
961 });
962
963 Some(BoundExistentialPredicates::new_from_iter(
965 interner,
966 principal.into_iter().chain(projections).chain(auto_traits),
967 ))
968 });
969
970 if let Some(bounds) = bounds {
971 let region = match region {
972 Some(it) => match it.kind() {
973 rustc_type_ir::RegionKind::ReBound(BoundVarIndexKind::Bound(db), var) => {
974 Region::new_bound(
975 self.interner,
976 db.shifted_out_to_binder(DebruijnIndex::from_u32(2)),
977 var,
978 )
979 }
980 _ => it,
981 },
982 None => Region::new_static(self.interner),
983 };
984 Ty::new_dynamic(self.interner, bounds, region)
985 } else {
986 Ty::new_error(self.interner, ErrorGuaranteed)
989 }
990 }
991
992 fn lower_impl_trait(&mut self, def_id: SolverDefId, bounds: &[TypeBound]) -> ImplTrait<'db> {
993 let interner = self.interner;
994 cov_mark::hit!(lower_rpit);
995 let args = GenericArgs::identity_for_item(interner, def_id);
996 let self_ty = Ty::new_alias(
997 self.interner,
998 rustc_type_ir::AliasTyKind::Opaque,
999 AliasTy::new_from_args(interner, def_id, args),
1000 );
1001 let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
1002 let mut predicates = Vec::new();
1003 for b in bounds {
1004 predicates.extend(ctx.lower_type_bound(b, self_ty, false));
1005 }
1006
1007 if !ctx.unsized_types.contains(&self_ty) {
1008 let sized_trait = self.lang_items.Sized;
1009 let sized_clause = sized_trait.map(|trait_id| {
1010 let trait_ref = TraitRef::new_from_args(
1011 interner,
1012 trait_id.into(),
1013 GenericArgs::new_from_iter(interner, [self_ty.into()]),
1014 );
1015 Clause(Predicate::new(
1016 interner,
1017 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
1018 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1019 trait_ref,
1020 polarity: rustc_type_ir::PredicatePolarity::Positive,
1021 }),
1022 )),
1023 ))
1024 });
1025 predicates.extend(sized_clause);
1026 }
1027 predicates.into_boxed_slice()
1028 });
1029 ImplTrait { predicates }
1030 }
1031
1032 pub(crate) fn lower_lifetime(&mut self, lifetime: LifetimeRefId) -> Region<'db> {
1033 match self.resolver.resolve_lifetime(&self.store[lifetime]) {
1034 Some(resolution) => match resolution {
1035 LifetimeNs::Static => Region::new_static(self.interner),
1036 LifetimeNs::LifetimeParam(id) => {
1037 let idx = match self.generics().lifetime_idx(id) {
1038 None => return Region::error(self.interner),
1039 Some(idx) => idx,
1040 };
1041 self.region_param(id, idx as u32)
1042 }
1043 },
1044 None => Region::error(self.interner),
1045 }
1046 }
1047}
1048
1049fn dyn_trait_dummy_self(interner: DbInterner<'_>) -> Ty<'_> {
1050 Ty::new_fresh(interner, 0)
1052}
1053
1054fn replace_dummy_self_with_error<'db, T: TypeFoldable<DbInterner<'db>>>(
1055 interner: DbInterner<'db>,
1056 t: T,
1057) -> T {
1058 let dyn_trait_dummy_self = dyn_trait_dummy_self(interner);
1059 t.fold_with(&mut BottomUpFolder {
1060 interner,
1061 ty_op: |ty| {
1062 if ty == dyn_trait_dummy_self { Ty::new_error(interner, ErrorGuaranteed) } else { ty }
1063 },
1064 lt_op: |lt| lt,
1065 ct_op: |ct| ct,
1066 })
1067}
1068
1069pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
1070 match m {
1071 hir_def::type_ref::Mutability::Shared => Mutability::Not,
1072 hir_def::type_ref::Mutability::Mut => Mutability::Mut,
1073 }
1074}
1075
1076fn unknown_const(_ty: Ty<'_>) -> Const<'_> {
1077 Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed))
1078}
1079
1080pub(crate) type Diagnostics = Option<ThinArc<(), TyLoweringDiagnostic>>;
1081
1082pub(crate) fn create_diagnostics(diagnostics: Vec<TyLoweringDiagnostic>) -> Diagnostics {
1083 (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter()))
1084}
1085
1086pub(crate) fn impl_trait_query<'db>(
1087 db: &'db dyn HirDatabase,
1088 impl_id: ImplId,
1089) -> Option<EarlyBinder<'db, TraitRef<'db>>> {
1090 db.impl_trait_with_diagnostics(impl_id).map(|it| it.0)
1091}
1092
1093pub(crate) fn impl_trait_with_diagnostics_query<'db>(
1094 db: &'db dyn HirDatabase,
1095 impl_id: ImplId,
1096) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> {
1097 let impl_data = db.impl_signature(impl_id);
1098 let resolver = impl_id.resolver(db);
1099 let mut ctx = TyLoweringContext::new(
1100 db,
1101 &resolver,
1102 &impl_data.store,
1103 impl_id.into(),
1104 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
1105 );
1106 let self_ty = db.impl_self_ty(impl_id).skip_binder();
1107 let target_trait = impl_data.target_trait.as_ref()?;
1108 let trait_ref = EarlyBinder::bind(ctx.lower_trait_ref(target_trait, self_ty)?);
1109 Some((trait_ref, create_diagnostics(ctx.diagnostics)))
1110}
1111
1112impl<'db> ImplTraitId<'db> {
1113 #[inline]
1114 pub fn predicates(self, db: &'db dyn HirDatabase) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1115 let (impl_traits, idx) = match self {
1116 ImplTraitId::ReturnTypeImplTrait(owner, idx) => {
1117 (ImplTraits::return_type_impl_traits(db, owner), idx)
1118 }
1119 ImplTraitId::TypeAliasImplTrait(owner, idx) => {
1120 (ImplTraits::type_alias_impl_traits(db, owner), idx)
1121 }
1122 };
1123 impl_traits
1124 .as_deref()
1125 .expect("owner should have opaque type")
1126 .as_ref()
1127 .map_bound(|it| &*it.impl_traits[idx].predicates)
1128 }
1129}
1130
1131impl InternedOpaqueTyId {
1132 #[inline]
1133 pub fn predicates<'db>(self, db: &'db dyn HirDatabase) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1134 self.loc(db).predicates(db)
1135 }
1136}
1137
1138#[salsa::tracked]
1139impl<'db> ImplTraits<'db> {
1140 #[salsa::tracked(returns(ref), unsafe(non_update_return_type))]
1141 pub(crate) fn return_type_impl_traits(
1142 db: &'db dyn HirDatabase,
1143 def: hir_def::FunctionId,
1144 ) -> Option<Box<EarlyBinder<'db, ImplTraits<'db>>>> {
1145 let data = db.function_signature(def);
1147 let resolver = def.resolver(db);
1148 let mut ctx_ret = TyLoweringContext::new(
1149 db,
1150 &resolver,
1151 &data.store,
1152 def.into(),
1153 LifetimeElisionKind::Infer,
1154 )
1155 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
1156 if let Some(ret_type) = data.ret_type {
1157 let _ret = ctx_ret.lower_ty(ret_type);
1158 }
1159 let mut return_type_impl_traits =
1160 ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data };
1161 if return_type_impl_traits.impl_traits.is_empty() {
1162 None
1163 } else {
1164 return_type_impl_traits.impl_traits.shrink_to_fit();
1165 Some(Box::new(EarlyBinder::bind(return_type_impl_traits)))
1166 }
1167 }
1168
1169 #[salsa::tracked(returns(ref), unsafe(non_update_return_type))]
1170 pub(crate) fn type_alias_impl_traits(
1171 db: &'db dyn HirDatabase,
1172 def: hir_def::TypeAliasId,
1173 ) -> Option<Box<EarlyBinder<'db, ImplTraits<'db>>>> {
1174 let data = db.type_alias_signature(def);
1175 let resolver = def.resolver(db);
1176 let mut ctx = TyLoweringContext::new(
1177 db,
1178 &resolver,
1179 &data.store,
1180 def.into(),
1181 LifetimeElisionKind::AnonymousReportError,
1182 )
1183 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
1184 if let Some(type_ref) = data.ty {
1185 let _ty = ctx.lower_ty(type_ref);
1186 }
1187 let mut type_alias_impl_traits =
1188 ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data };
1189 if type_alias_impl_traits.impl_traits.is_empty() {
1190 None
1191 } else {
1192 type_alias_impl_traits.impl_traits.shrink_to_fit();
1193 Some(Box::new(EarlyBinder::bind(type_alias_impl_traits)))
1194 }
1195 }
1196}
1197
1198#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1199pub enum TyDefId {
1200 BuiltinType(BuiltinType),
1201 AdtId(AdtId),
1202 TypeAliasId(TypeAliasId),
1203}
1204impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
1205
1206#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
1207pub enum ValueTyDefId {
1208 FunctionId(FunctionId),
1209 StructId(StructId),
1210 UnionId(UnionId),
1211 EnumVariantId(EnumVariantId),
1212 ConstId(ConstId),
1213 StaticId(StaticId),
1214}
1215impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
1216
1217impl ValueTyDefId {
1218 pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> GenericDefId {
1219 match self {
1220 Self::FunctionId(id) => id.into(),
1221 Self::StructId(id) => id.into(),
1222 Self::UnionId(id) => id.into(),
1223 Self::EnumVariantId(var) => var.lookup(db).parent.into(),
1224 Self::ConstId(id) => id.into(),
1225 Self::StaticId(id) => id.into(),
1226 }
1227 }
1228}
1229
1230pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> {
1235 let interner = DbInterner::new_no_crate(db);
1236 match def {
1237 TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)),
1238 TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt(
1239 interner,
1240 it,
1241 GenericArgs::identity_for_item(interner, it.into()),
1242 )),
1243 TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
1244 }
1245}
1246
1247fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> {
1250 let interner = DbInterner::new_no_crate(db);
1251 EarlyBinder::bind(Ty::new_fn_def(
1252 interner,
1253 CallableDefId::FunctionId(def).into(),
1254 GenericArgs::identity_for_item(interner, def.into()),
1255 ))
1256}
1257
1258fn type_for_const<'db>(db: &'db dyn HirDatabase, def: ConstId) -> EarlyBinder<'db, Ty<'db>> {
1260 let resolver = def.resolver(db);
1261 let data = db.const_signature(def);
1262 let parent = def.loc(db).container;
1263 let mut ctx = TyLoweringContext::new(
1264 db,
1265 &resolver,
1266 &data.store,
1267 def.into(),
1268 LifetimeElisionKind::AnonymousReportError,
1269 );
1270 ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent));
1271 EarlyBinder::bind(ctx.lower_ty(data.type_ref))
1272}
1273
1274fn type_for_static<'db>(db: &'db dyn HirDatabase, def: StaticId) -> EarlyBinder<'db, Ty<'db>> {
1276 let resolver = def.resolver(db);
1277 let data = db.static_signature(def);
1278 let mut ctx = TyLoweringContext::new(
1279 db,
1280 &resolver,
1281 &data.store,
1282 def.into(),
1283 LifetimeElisionKind::AnonymousReportError,
1284 );
1285 ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner)));
1286 EarlyBinder::bind(ctx.lower_ty(data.type_ref))
1287}
1288
1289fn type_for_struct_constructor<'db>(
1291 db: &'db dyn HirDatabase,
1292 def: StructId,
1293) -> Option<EarlyBinder<'db, Ty<'db>>> {
1294 let struct_data = def.fields(db);
1295 match struct_data.shape {
1296 FieldsShape::Record => None,
1297 FieldsShape::Unit => Some(type_for_adt(db, def.into())),
1298 FieldsShape::Tuple => {
1299 let interner = DbInterner::new_no_crate(db);
1300 Some(EarlyBinder::bind(Ty::new_fn_def(
1301 interner,
1302 CallableDefId::StructId(def).into(),
1303 GenericArgs::identity_for_item(interner, def.into()),
1304 )))
1305 }
1306 }
1307}
1308
1309fn type_for_enum_variant_constructor<'db>(
1311 db: &'db dyn HirDatabase,
1312 def: EnumVariantId,
1313) -> Option<EarlyBinder<'db, Ty<'db>>> {
1314 let struct_data = def.fields(db);
1315 match struct_data.shape {
1316 FieldsShape::Record => None,
1317 FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())),
1318 FieldsShape::Tuple => {
1319 let interner = DbInterner::new_no_crate(db);
1320 Some(EarlyBinder::bind(Ty::new_fn_def(
1321 interner,
1322 CallableDefId::EnumVariantId(def).into(),
1323 GenericArgs::identity_for_item(interner, def.loc(db).parent.into()),
1324 )))
1325 }
1326 }
1327}
1328
1329pub(crate) fn value_ty_query<'db>(
1330 db: &'db dyn HirDatabase,
1331 def: ValueTyDefId,
1332) -> Option<EarlyBinder<'db, Ty<'db>>> {
1333 match def {
1334 ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
1335 ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
1336 ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
1337 ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
1338 ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
1339 ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
1340 }
1341}
1342
1343pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>(
1344 db: &'db dyn HirDatabase,
1345 t: TypeAliasId,
1346) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
1347 let type_alias_data = db.type_alias_signature(t);
1348 let mut diags = None;
1349 let resolver = t.resolver(db);
1350 let interner = DbInterner::new_no_crate(db);
1351 let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
1352 EarlyBinder::bind(Ty::new_foreign(interner, t.into()))
1353 } else {
1354 let mut ctx = TyLoweringContext::new(
1355 db,
1356 &resolver,
1357 &type_alias_data.store,
1358 t.into(),
1359 LifetimeElisionKind::AnonymousReportError,
1360 )
1361 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
1362 let res = EarlyBinder::bind(
1363 type_alias_data
1364 .ty
1365 .map(|type_ref| ctx.lower_ty(type_ref))
1366 .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)),
1367 );
1368 diags = create_diagnostics(ctx.diagnostics);
1369 res
1370 };
1371 (inner, diags)
1372}
1373
1374pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>(
1375 db: &'db dyn HirDatabase,
1376 _adt: TypeAliasId,
1377) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
1378 (EarlyBinder::bind(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed)), None)
1379}
1380
1381pub(crate) fn impl_self_ty_query<'db>(
1382 db: &'db dyn HirDatabase,
1383 impl_id: ImplId,
1384) -> EarlyBinder<'db, Ty<'db>> {
1385 db.impl_self_ty_with_diagnostics(impl_id).0
1386}
1387
1388pub(crate) fn impl_self_ty_with_diagnostics_query<'db>(
1389 db: &'db dyn HirDatabase,
1390 impl_id: ImplId,
1391) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
1392 let resolver = impl_id.resolver(db);
1393
1394 let impl_data = db.impl_signature(impl_id);
1395 let mut ctx = TyLoweringContext::new(
1396 db,
1397 &resolver,
1398 &impl_data.store,
1399 impl_id.into(),
1400 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
1401 );
1402 let ty = ctx.lower_ty(impl_data.self_ty);
1403 assert!(!ty.has_escaping_bound_vars());
1404 (EarlyBinder::bind(ty), create_diagnostics(ctx.diagnostics))
1405}
1406
1407pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
1408 db: &dyn HirDatabase,
1409 _impl_id: ImplId,
1410) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) {
1411 (EarlyBinder::bind(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed)), None)
1412}
1413
1414pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> {
1415 db.const_param_ty_with_diagnostics(def).0
1416}
1417
1418pub(crate) fn const_param_ty_with_diagnostics_query<'db>(
1420 db: &'db dyn HirDatabase,
1421 def: ConstParamId,
1422) -> (Ty<'db>, Diagnostics) {
1423 let (parent_data, store) = db.generic_params_and_store(def.parent());
1424 let data = &parent_data[def.local_id()];
1425 let resolver = def.parent().resolver(db);
1426 let interner = DbInterner::new_no_crate(db);
1427 let mut ctx = TyLoweringContext::new(
1428 db,
1429 &resolver,
1430 &store,
1431 def.parent(),
1432 LifetimeElisionKind::AnonymousReportError,
1433 );
1434 let ty = match data {
1435 TypeOrConstParamData::TypeParamData(_) => {
1436 never!();
1437 Ty::new_error(interner, ErrorGuaranteed)
1438 }
1439 TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
1440 };
1441 (ty, create_diagnostics(ctx.diagnostics))
1442}
1443
1444pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>(
1445 db: &'db dyn HirDatabase,
1446 _: crate::db::HirDatabaseData,
1447 _def: ConstParamId,
1448) -> (Ty<'db>, Diagnostics) {
1449 let interner = DbInterner::new_no_crate(db);
1450 (Ty::new_error(interner, ErrorGuaranteed), None)
1451}
1452
1453pub(crate) fn field_types_query<'db>(
1454 db: &'db dyn HirDatabase,
1455 variant_id: VariantId,
1456) -> Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>> {
1457 db.field_types_with_diagnostics(variant_id).0
1458}
1459
1460pub(crate) fn field_types_with_diagnostics_query<'db>(
1462 db: &'db dyn HirDatabase,
1463 variant_id: VariantId,
1464) -> (Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>>, Diagnostics) {
1465 let var_data = variant_id.fields(db);
1466 let fields = var_data.fields();
1467 if fields.is_empty() {
1468 return (Arc::new(ArenaMap::default()), None);
1469 }
1470
1471 let (resolver, def): (_, GenericDefId) = match variant_id {
1472 VariantId::StructId(it) => (it.resolver(db), it.into()),
1473 VariantId::UnionId(it) => (it.resolver(db), it.into()),
1474 VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
1475 };
1476 let mut res = ArenaMap::default();
1477 let mut ctx = TyLoweringContext::new(
1478 db,
1479 &resolver,
1480 &var_data.store,
1481 def,
1482 LifetimeElisionKind::AnonymousReportError,
1483 );
1484 for (field_id, field_data) in var_data.fields().iter() {
1485 res.insert(field_id, EarlyBinder::bind(ctx.lower_ty(field_data.type_ref)));
1486 }
1487 (Arc::new(res), create_diagnostics(ctx.diagnostics))
1488}
1489
1490#[tracing::instrument(skip(db), ret)]
1499#[salsa::tracked(returns(ref), unsafe(non_update_return_type), cycle_result = generic_predicates_for_param_cycle_result)]
1500pub(crate) fn generic_predicates_for_param<'db>(
1501 db: &'db dyn HirDatabase,
1502 def: GenericDefId,
1503 param_id: TypeOrConstParamId,
1504 assoc_name: Option<Name>,
1505) -> EarlyBinder<'db, Box<[Clause<'db>]>> {
1506 let generics = generics(db, def);
1507 let interner = DbInterner::new_no_crate(db);
1508 let resolver = def.resolver(db);
1509 let mut ctx = TyLoweringContext::new(
1510 db,
1511 &resolver,
1512 generics.store(),
1513 def,
1514 LifetimeElisionKind::AnonymousReportError,
1515 );
1516
1517 let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred {
1519 WherePredicate::ForLifetime { target, bound, .. }
1520 | WherePredicate::TypeBound { target, bound, .. } => {
1521 let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
1522 if invalid_target {
1523 let lower = || -> bool {
1528 match bound {
1529 TypeBound::Path(_, TraitBoundModifier::Maybe) => true,
1530 TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
1531 let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
1532 return false;
1533 };
1534 let Some(pointee_sized) = ctx.lang_items.PointeeSized else {
1535 return false;
1536 };
1537 ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and(
1540 |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized),
1541 )
1542 }
1543 _ => false,
1544 }
1545 }();
1546 if lower {
1547 ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All)
1548 .for_each(drop);
1549 }
1550 return false;
1551 }
1552
1553 match bound {
1554 &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => {
1555 let path = &ctx.store[path];
1558
1559 let Some(assoc_name) = &assoc_name else { return true };
1560 let Some(TypeNs::TraitId(tr)) =
1561 resolver.resolve_path_in_type_ns_fully(db, path)
1562 else {
1563 return false;
1564 };
1565
1566 rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| {
1567 tr.0.trait_items(db).items.iter().any(|(name, item)| {
1568 matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
1569 })
1570 })
1571 }
1572 TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false,
1573 }
1574 }
1575 WherePredicate::Lifetime { .. } => false,
1576 };
1577 let mut predicates = Vec::new();
1578 for maybe_parent_generics in
1579 std::iter::successors(Some(&generics), |generics| generics.parent_generics())
1580 {
1581 ctx.store = maybe_parent_generics.store();
1582 for pred in maybe_parent_generics.where_predicates() {
1583 if predicate(pred, &mut ctx) {
1584 predicates.extend(ctx.lower_where_predicate(
1585 pred,
1586 true,
1587 maybe_parent_generics,
1588 PredicateFilter::All,
1589 ));
1590 }
1591 }
1592 }
1593
1594 let args = GenericArgs::identity_for_item(interner, def.into());
1595 if !args.is_empty() {
1596 let explicitly_unsized_tys = ctx.unsized_types;
1597 if let Some(implicitly_sized_predicates) = implicitly_sized_clauses(
1598 db,
1599 ctx.lang_items,
1600 param_id.parent,
1601 &explicitly_unsized_tys,
1602 &args,
1603 ) {
1604 predicates.extend(implicitly_sized_predicates);
1605 };
1606 }
1607 EarlyBinder::bind(predicates.into_boxed_slice())
1608}
1609
1610pub(crate) fn generic_predicates_for_param_cycle_result<'db>(
1611 _db: &'db dyn HirDatabase,
1612 _def: GenericDefId,
1613 _param_id: TypeOrConstParamId,
1614 _assoc_name: Option<Name>,
1615) -> EarlyBinder<'db, Box<[Clause<'db>]>> {
1616 EarlyBinder::bind(Box::new([]))
1617}
1618
1619#[inline]
1620pub(crate) fn type_alias_bounds<'db>(
1621 db: &'db dyn HirDatabase,
1622 type_alias: TypeAliasId,
1623) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1624 type_alias_bounds_with_diagnostics(db, type_alias).0.as_ref().map_bound(|it| &**it)
1625}
1626
1627#[salsa::tracked(returns(ref), unsafe(non_update_return_type))]
1628pub fn type_alias_bounds_with_diagnostics<'db>(
1629 db: &'db dyn HirDatabase,
1630 type_alias: TypeAliasId,
1631) -> (EarlyBinder<'db, Box<[Clause<'db>]>>, Diagnostics) {
1632 let type_alias_data = db.type_alias_signature(type_alias);
1633 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
1634 let mut ctx = TyLoweringContext::new(
1635 db,
1636 &resolver,
1637 &type_alias_data.store,
1638 type_alias.into(),
1639 LifetimeElisionKind::AnonymousReportError,
1640 );
1641 let interner = ctx.interner;
1642 let def_id = type_alias.into();
1643
1644 let item_args = GenericArgs::identity_for_item(interner, def_id);
1645 let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args);
1646
1647 let mut bounds = Vec::new();
1648 for bound in &type_alias_data.bounds {
1649 ctx.lower_type_bound(bound, interner_ty, false).for_each(|pred| {
1650 bounds.push(pred);
1651 });
1652 }
1653
1654 if !ctx.unsized_types.contains(&interner_ty) {
1655 let sized_trait = ctx.lang_items.Sized;
1656 if let Some(sized_trait) = sized_trait {
1657 let trait_ref = TraitRef::new_from_args(
1658 interner,
1659 sized_trait.into(),
1660 GenericArgs::new_from_iter(interner, [interner_ty.into()]),
1661 );
1662 bounds.push(trait_ref.upcast(interner));
1663 };
1664 }
1665
1666 (EarlyBinder::bind(bounds.into_boxed_slice()), create_diagnostics(ctx.diagnostics))
1667}
1668
1669#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1670pub struct GenericPredicates<'db> {
1671 predicates: EarlyBinder<'db, Box<[Clause<'db>]>>,
1675 own_predicates_start: u32,
1676 is_trait: bool,
1677 parent_is_trait: bool,
1678}
1679
1680#[salsa::tracked]
1681impl<'db> GenericPredicates<'db> {
1682 #[salsa::tracked(returns(ref), unsafe(non_update_return_type))]
1686 pub fn query_with_diagnostics(
1687 db: &'db dyn HirDatabase,
1688 def: GenericDefId,
1689 ) -> (GenericPredicates<'db>, Diagnostics) {
1690 generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true)
1691 }
1692}
1693
1694impl<'db> GenericPredicates<'db> {
1695 #[inline]
1696 pub fn query(db: &'db dyn HirDatabase, def: GenericDefId) -> &'db GenericPredicates<'db> {
1697 &Self::query_with_diagnostics(db, def).0
1698 }
1699
1700 #[inline]
1701 pub fn query_all(
1702 db: &'db dyn HirDatabase,
1703 def: GenericDefId,
1704 ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1705 Self::query(db, def).all_predicates()
1706 }
1707
1708 #[inline]
1709 pub fn query_own(
1710 db: &'db dyn HirDatabase,
1711 def: GenericDefId,
1712 ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1713 Self::query(db, def).own_predicates()
1714 }
1715
1716 #[inline]
1717 pub fn query_explicit(
1718 db: &'db dyn HirDatabase,
1719 def: GenericDefId,
1720 ) -> EarlyBinder<'db, &'db [Clause<'db>]> {
1721 Self::query(db, def).explicit_predicates()
1722 }
1723
1724 #[inline]
1725 pub fn all_predicates(&self) -> EarlyBinder<'db, &[Clause<'db>]> {
1726 self.predicates.as_ref().map_bound(|it| &**it)
1727 }
1728
1729 #[inline]
1730 pub fn own_predicates(&self) -> EarlyBinder<'db, &[Clause<'db>]> {
1731 self.predicates.as_ref().map_bound(|it| &it[self.own_predicates_start as usize..])
1732 }
1733
1734 #[inline]
1736 pub fn explicit_predicates(&self) -> EarlyBinder<'db, &[Clause<'db>]> {
1737 self.predicates.as_ref().map_bound(|it| {
1738 &it[usize::from(self.parent_is_trait)..it.len() - usize::from(self.is_trait)]
1739 })
1740 }
1741}
1742
1743pub(crate) fn trait_environment_for_body_query(
1744 db: &dyn HirDatabase,
1745 def: DefWithBodyId,
1746) -> ParamEnv<'_> {
1747 let Some(def) = def.as_generic_def_id(db) else {
1748 return ParamEnv::empty();
1749 };
1750 db.trait_environment(def)
1751}
1752
1753pub(crate) fn trait_environment_query<'db>(
1754 db: &'db dyn HirDatabase,
1755 def: GenericDefId,
1756) -> ParamEnv<'db> {
1757 let module = def.module(db);
1758 let interner = DbInterner::new_with(db, module.krate(db));
1759 let predicates = GenericPredicates::query_all(db, def);
1760 let clauses = rustc_type_ir::elaborate::elaborate(interner, predicates.iter_identity_copied());
1761 let clauses = Clauses::new_from_iter(interner, clauses);
1762
1763 ParamEnv { clauses }
1765}
1766
1767#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1768pub(crate) enum PredicateFilter {
1769 SelfTrait,
1770 All,
1771}
1772
1773#[tracing::instrument(skip(db, filter), ret)]
1776pub(crate) fn generic_predicates_filtered_by<'db, F>(
1777 db: &'db dyn HirDatabase,
1778 def: GenericDefId,
1779 predicate_filter: PredicateFilter,
1780 filter: F,
1781) -> (GenericPredicates<'db>, Diagnostics)
1782where
1783 F: Fn(GenericDefId) -> bool,
1784{
1785 let generics = generics(db, def);
1786 let resolver = def.resolver(db);
1787 let interner = DbInterner::new_no_crate(db);
1788 let mut ctx = TyLoweringContext::new(
1789 db,
1790 &resolver,
1791 generics.store(),
1792 def,
1793 LifetimeElisionKind::AnonymousReportError,
1794 );
1795 let sized_trait = ctx.lang_items.Sized;
1796
1797 let mut predicates = Vec::new();
1798 let all_generics =
1799 std::iter::successors(Some(&generics), |generics| generics.parent_generics())
1800 .collect::<ArrayVec<_, 2>>();
1801 let mut is_trait = false;
1802 let mut parent_is_trait = false;
1803 if all_generics.len() > 1 {
1804 add_implicit_trait_predicate(
1805 interner,
1806 all_generics.last().unwrap().def(),
1807 predicate_filter,
1808 &mut predicates,
1809 &mut parent_is_trait,
1810 );
1811 }
1812 let mut own_predicates_start = 0;
1815 for &maybe_parent_generics in all_generics.iter().rev() {
1816 let current_def_predicates_start = predicates.len();
1817 ctx.diagnostics.clear();
1819
1820 if filter(maybe_parent_generics.def()) {
1821 ctx.store = maybe_parent_generics.store();
1822 for pred in maybe_parent_generics.where_predicates() {
1823 tracing::debug!(?pred);
1824 predicates.extend(ctx.lower_where_predicate(
1825 pred,
1826 false,
1827 maybe_parent_generics,
1828 predicate_filter,
1829 ));
1830 }
1831
1832 push_const_arg_has_type_predicates(db, &mut predicates, maybe_parent_generics);
1833
1834 if let Some(sized_trait) = sized_trait {
1835 let mut add_sized_clause = |param_idx, param_id, param_data| {
1836 let (
1837 GenericParamId::TypeParamId(param_id),
1838 GenericParamDataRef::TypeParamData(param_data),
1839 ) = (param_id, param_data)
1840 else {
1841 return;
1842 };
1843
1844 if param_data.provenance == TypeParamProvenance::TraitSelf {
1845 return;
1846 }
1847
1848 let param_ty = Ty::new_param(interner, param_id, param_idx);
1849 if ctx.unsized_types.contains(¶m_ty) {
1850 return;
1851 }
1852 let trait_ref = TraitRef::new_from_args(
1853 interner,
1854 sized_trait.into(),
1855 GenericArgs::new_from_iter(interner, [param_ty.into()]),
1856 );
1857 let clause = Clause(Predicate::new(
1858 interner,
1859 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
1860 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1861 trait_ref,
1862 polarity: rustc_type_ir::PredicatePolarity::Positive,
1863 }),
1864 )),
1865 ));
1866 predicates.push(clause);
1867 };
1868 let parent_params_len = maybe_parent_generics.len_parent();
1869 maybe_parent_generics.iter_self().enumerate().for_each(
1870 |(param_idx, (param_id, param_data))| {
1871 add_sized_clause(
1872 (param_idx + parent_params_len) as u32,
1873 param_id,
1874 param_data,
1875 );
1876 },
1877 );
1878 }
1879
1880 }
1885
1886 if maybe_parent_generics.def() == def {
1887 own_predicates_start = current_def_predicates_start as u32;
1888 }
1889 }
1890
1891 add_implicit_trait_predicate(interner, def, predicate_filter, &mut predicates, &mut is_trait);
1892
1893 let diagnostics = create_diagnostics(ctx.diagnostics);
1894 let predicates = GenericPredicates {
1895 own_predicates_start,
1896 is_trait,
1897 parent_is_trait,
1898 predicates: EarlyBinder::bind(predicates.into_boxed_slice()),
1899 };
1900 return (predicates, diagnostics);
1901
1902 fn add_implicit_trait_predicate<'db>(
1903 interner: DbInterner<'db>,
1904 def: GenericDefId,
1905 predicate_filter: PredicateFilter,
1906 predicates: &mut Vec<Clause<'db>>,
1907 set_is_trait: &mut bool,
1908 ) {
1909 if let GenericDefId::TraitId(def_id) = def
1922 && predicate_filter == PredicateFilter::All
1923 {
1924 *set_is_trait = true;
1925 predicates.push(TraitRef::identity(interner, def_id.into()).upcast(interner));
1926 }
1927 }
1928}
1929
1930fn push_const_arg_has_type_predicates<'db>(
1931 db: &'db dyn HirDatabase,
1932 predicates: &mut Vec<Clause<'db>>,
1933 generics: &Generics,
1934) {
1935 let interner = DbInterner::new_no_crate(db);
1936 let const_params_offset = generics.len_parent() + generics.len_lifetimes_self();
1937 for (param_index, (param_idx, param_data)) in generics.iter_self_type_or_consts().enumerate() {
1938 if !matches!(param_data, TypeOrConstParamData::ConstParamData(_)) {
1939 continue;
1940 }
1941
1942 let param_id = ConstParamId::from_unchecked(TypeOrConstParamId {
1943 parent: generics.def(),
1944 local_id: param_idx,
1945 });
1946 predicates.push(Clause(
1947 ClauseKind::ConstArgHasType(
1948 Const::new_param(
1949 interner,
1950 ParamConst { id: param_id, index: (param_index + const_params_offset) as u32 },
1951 ),
1952 db.const_param_ty_ns(param_id),
1953 )
1954 .upcast(interner),
1955 ));
1956 }
1957}
1958
1959fn implicitly_sized_clauses<'a, 'subst, 'db>(
1962 db: &'db dyn HirDatabase,
1963 lang_items: &LangItems,
1964 def: GenericDefId,
1965 explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>,
1966 args: &'subst GenericArgs<'db>,
1967) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> {
1968 let interner = DbInterner::new_no_crate(db);
1969 let sized_trait = lang_items.Sized?;
1970
1971 let trait_self_idx = trait_self_param_idx(db, def);
1972
1973 Some(
1974 args.iter()
1975 .enumerate()
1976 .filter_map(
1977 move |(idx, generic_arg)| {
1978 if Some(idx) == trait_self_idx { None } else { Some(generic_arg) }
1979 },
1980 )
1981 .filter_map(|generic_arg| generic_arg.as_type())
1982 .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty))
1983 .map(move |self_ty| {
1984 let trait_ref = TraitRef::new_from_args(
1985 interner,
1986 sized_trait.into(),
1987 GenericArgs::new_from_iter(interner, [self_ty.into()]),
1988 );
1989 Clause(Predicate::new(
1990 interner,
1991 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
1992 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1993 trait_ref,
1994 polarity: rustc_type_ir::PredicatePolarity::Positive,
1995 }),
1996 )),
1997 ))
1998 }),
1999 )
2000}
2001
2002#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2003pub struct GenericDefaults<'db>(Option<Arc<[Option<EarlyBinder<'db, GenericArg<'db>>>]>>);
2004
2005impl<'db> GenericDefaults<'db> {
2006 #[inline]
2007 pub fn get(&self, idx: usize) -> Option<EarlyBinder<'db, GenericArg<'db>>> {
2008 self.0.as_ref()?[idx]
2009 }
2010}
2011
2012pub(crate) fn generic_defaults_query(
2013 db: &dyn HirDatabase,
2014 def: GenericDefId,
2015) -> GenericDefaults<'_> {
2016 db.generic_defaults_with_diagnostics(def).0
2017}
2018
2019pub(crate) fn generic_defaults_with_diagnostics_query(
2023 db: &dyn HirDatabase,
2024 def: GenericDefId,
2025) -> (GenericDefaults<'_>, Diagnostics) {
2026 let generic_params = generics(db, def);
2027 if generic_params.is_empty() {
2028 return (GenericDefaults(None), None);
2029 }
2030 let resolver = def.resolver(db);
2031
2032 let mut ctx = TyLoweringContext::new(
2033 db,
2034 &resolver,
2035 generic_params.store(),
2036 def,
2037 LifetimeElisionKind::AnonymousReportError,
2038 )
2039 .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
2040 let mut idx = 0;
2041 let mut has_any_default = false;
2042 let mut defaults = generic_params
2043 .iter_parents_with_store()
2044 .map(|((_id, p), store)| {
2045 ctx.store = store;
2046 let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
2047 has_any_default |= has_default;
2048 idx += 1;
2049 result
2050 })
2051 .collect::<Vec<_>>();
2052 ctx.diagnostics.clear(); defaults.extend(generic_params.iter_self().map(|(_id, p)| {
2054 let (result, has_default) = handle_generic_param(&mut ctx, idx, p);
2055 has_any_default |= has_default;
2056 idx += 1;
2057 result
2058 }));
2059 let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
2060 let defaults = if has_any_default {
2061 GenericDefaults(Some(Arc::from_iter(defaults)))
2062 } else {
2063 GenericDefaults(None)
2064 };
2065 return (defaults, diagnostics);
2066
2067 fn handle_generic_param<'db>(
2068 ctx: &mut TyLoweringContext<'db, '_>,
2069 idx: usize,
2070 p: GenericParamDataRef<'_>,
2071 ) -> (Option<EarlyBinder<'db, GenericArg<'db>>>, bool) {
2072 ctx.lowering_param_default(idx as u32);
2073 match p {
2074 GenericParamDataRef::TypeParamData(p) => {
2075 let ty = p.default.map(|ty| ctx.lower_ty(ty));
2076 (ty.map(|ty| EarlyBinder::bind(ty.into())), p.default.is_some())
2077 }
2078 GenericParamDataRef::ConstParamData(p) => {
2079 let val = p.default.map(|c| {
2080 let param_ty = ctx.lower_ty(p.ty);
2081 let c = ctx.lower_const(c, param_ty);
2082 c.into()
2083 });
2084 (val.map(EarlyBinder::bind), p.default.is_some())
2085 }
2086 GenericParamDataRef::LifetimeParamData(_) => (None, false),
2087 }
2088 }
2089}
2090
2091pub(crate) fn generic_defaults_with_diagnostics_cycle_result(
2092 _db: &dyn HirDatabase,
2093 _def: GenericDefId,
2094) -> (GenericDefaults<'_>, Diagnostics) {
2095 (GenericDefaults(None), None)
2096}
2097
2098pub(crate) fn callable_item_signature_query<'db>(
2100 db: &'db dyn HirDatabase,
2101 def: CallableDefId,
2102) -> EarlyBinder<'db, PolyFnSig<'db>> {
2103 match def {
2104 CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
2105 CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
2106 CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
2107 }
2108}
2109
2110fn fn_sig_for_fn<'db>(
2111 db: &'db dyn HirDatabase,
2112 def: FunctionId,
2113) -> EarlyBinder<'db, PolyFnSig<'db>> {
2114 let data = db.function_signature(def);
2115 let resolver = def.resolver(db);
2116 let interner = DbInterner::new_no_crate(db);
2117 let mut ctx_params = TyLoweringContext::new(
2118 db,
2119 &resolver,
2120 &data.store,
2121 def.into(),
2122 LifetimeElisionKind::for_fn_params(&data),
2123 );
2124 let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
2125
2126 let ret = match data.ret_type {
2127 Some(ret_type) => {
2128 let mut ctx_ret = TyLoweringContext::new(
2129 db,
2130 &resolver,
2131 &data.store,
2132 def.into(),
2133 LifetimeElisionKind::for_fn_ret(interner),
2134 )
2135 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
2136 ctx_ret.lower_ty(ret_type)
2137 }
2138 None => Ty::new_tup(interner, &[]),
2139 };
2140
2141 let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret)));
2142 EarlyBinder::bind(rustc_type_ir::Binder::dummy(FnSig {
2144 abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
2145 c_variadic: data.is_varargs(),
2146 safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
2147 inputs_and_output,
2148 }))
2149}
2150
2151fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> {
2152 let interner = DbInterner::new_no_crate(db);
2153 let args = GenericArgs::identity_for_item(interner, adt.into());
2154 let ty = Ty::new_adt(interner, adt, args);
2155 EarlyBinder::bind(ty)
2156}
2157
2158fn fn_sig_for_struct_constructor<'db>(
2159 db: &'db dyn HirDatabase,
2160 def: StructId,
2161) -> EarlyBinder<'db, PolyFnSig<'db>> {
2162 let field_tys = db.field_types(def.into());
2163 let params = field_tys.iter().map(|(_, ty)| ty.skip_binder());
2164 let ret = type_for_adt(db, def.into()).skip_binder();
2165
2166 let inputs_and_output =
2167 Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret)));
2168 EarlyBinder::bind(Binder::dummy(FnSig {
2169 abi: FnAbi::RustCall,
2170 c_variadic: false,
2171 safety: Safety::Safe,
2172 inputs_and_output,
2173 }))
2174}
2175
2176fn fn_sig_for_enum_variant_constructor<'db>(
2177 db: &'db dyn HirDatabase,
2178 def: EnumVariantId,
2179) -> EarlyBinder<'db, PolyFnSig<'db>> {
2180 let field_tys = db.field_types(def.into());
2181 let params = field_tys.iter().map(|(_, ty)| ty.skip_binder());
2182 let parent = def.lookup(db).parent;
2183 let ret = type_for_adt(db, parent.into()).skip_binder();
2184
2185 let inputs_and_output =
2186 Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret)));
2187 EarlyBinder::bind(Binder::dummy(FnSig {
2188 abi: FnAbi::RustCall,
2189 c_variadic: false,
2190 safety: Safety::Safe,
2191 inputs_and_output,
2192 }))
2193}
2194
2195pub(crate) fn associated_ty_item_bounds<'db>(
2197 db: &'db dyn HirDatabase,
2198 type_alias: TypeAliasId,
2199) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
2200 let type_alias_data = db.type_alias_signature(type_alias);
2201 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
2202 let interner = DbInterner::new_no_crate(db);
2203 let mut ctx = TyLoweringContext::new(
2204 db,
2205 &resolver,
2206 &type_alias_data.store,
2207 type_alias.into(),
2208 LifetimeElisionKind::AnonymousReportError,
2209 );
2210 let self_ty = Ty::new_error(interner, ErrorGuaranteed);
2213
2214 let mut bounds = Vec::new();
2215 for bound in &type_alias_data.bounds {
2216 ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| {
2217 if let Some(bound) = pred
2218 .kind()
2219 .map_bound(|c| match c {
2220 rustc_type_ir::ClauseKind::Trait(t) => {
2221 let id = t.def_id();
2222 let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
2223 if is_auto {
2224 Some(ExistentialPredicate::AutoTrait(t.def_id()))
2225 } else {
2226 Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args(
2227 interner,
2228 t.def_id(),
2229 GenericArgs::new_from_iter(
2230 interner,
2231 t.trait_ref.args.iter().skip(1),
2232 ),
2233 )))
2234 }
2235 }
2236 rustc_type_ir::ClauseKind::Projection(p) => Some(
2237 ExistentialPredicate::Projection(ExistentialProjection::new_from_args(
2238 interner,
2239 p.def_id(),
2240 GenericArgs::new_from_iter(
2241 interner,
2242 p.projection_term.args.iter().skip(1),
2243 ),
2244 p.term,
2245 )),
2246 ),
2247 rustc_type_ir::ClauseKind::TypeOutlives(_) => None,
2248 rustc_type_ir::ClauseKind::RegionOutlives(_)
2249 | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
2250 | rustc_type_ir::ClauseKind::WellFormed(_)
2251 | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
2252 | rustc_type_ir::ClauseKind::HostEffect(_)
2253 | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
2254 })
2255 .transpose()
2256 {
2257 bounds.push(bound);
2258 }
2259 });
2260 }
2261
2262 if !ctx.unsized_types.contains(&self_ty)
2263 && let Some(sized_trait) = ctx.lang_items.Sized
2264 {
2265 let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new(
2266 interner,
2267 sized_trait.into(),
2268 [] as [GenericArg<'_>; 0],
2269 )));
2270 bounds.push(sized_clause);
2271 }
2272
2273 EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds))
2274}
2275
2276pub(crate) fn associated_type_by_name_including_super_traits<'db>(
2277 db: &'db dyn HirDatabase,
2278 trait_ref: TraitRef<'db>,
2279 name: &Name,
2280) -> Option<(TraitRef<'db>, TypeAliasId)> {
2281 let module = trait_ref.def_id.0.module(db);
2282 let interner = DbInterner::new_with(db, module.krate(db));
2283 rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| {
2284 let trait_id = t.as_ref().skip_binder().def_id.0;
2285 let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?;
2286 Some((t.skip_binder(), assoc_type))
2287 })
2288}
2289
2290pub fn associated_type_shorthand_candidates(
2291 db: &dyn HirDatabase,
2292 def: GenericDefId,
2293 res: TypeNs,
2294 mut cb: impl FnMut(&Name, TypeAliasId) -> bool,
2295) -> Option<TypeAliasId> {
2296 let interner = DbInterner::new_no_crate(db);
2297 named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| {
2298 cb(name, id).then_some(id)
2299 })
2300}
2301
2302#[tracing::instrument(skip(interner, check_alias))]
2303fn named_associated_type_shorthand_candidates<'db, R>(
2304 interner: DbInterner<'db>,
2305 def: GenericDefId,
2308 res: TypeNs,
2309 assoc_name: Option<Name>,
2310 mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option<R>,
2311) -> Option<R> {
2312 let db = interner.db;
2313 let mut search = |t: TraitRef<'db>| -> Option<R> {
2314 let mut checked_traits = FxHashSet::default();
2315 let mut check_trait = |trait_ref: TraitRef<'db>| {
2316 let trait_id = trait_ref.def_id.0;
2317 let name = &db.trait_signature(trait_id).name;
2318 tracing::debug!(?trait_id, ?name);
2319 if !checked_traits.insert(trait_id) {
2320 return None;
2321 }
2322 let data = trait_id.trait_items(db);
2323
2324 tracing::debug!(?data.items);
2325 for (name, assoc_id) in &data.items {
2326 if let &AssocItemId::TypeAliasId(alias) = assoc_id
2327 && let Some(ty) = check_alias(name, trait_ref, alias)
2328 {
2329 return Some(ty);
2330 }
2331 }
2332 None
2333 };
2334 let mut stack: SmallVec<[_; 4]> = smallvec![t];
2335 while let Some(trait_ref) = stack.pop() {
2336 if let Some(alias) = check_trait(trait_ref) {
2337 return Some(alias);
2338 }
2339 for pred in generic_predicates_filtered_by(
2340 db,
2341 GenericDefId::TraitId(trait_ref.def_id.0),
2342 PredicateFilter::SelfTrait,
2343 |pred| pred != def && pred == GenericDefId::TraitId(trait_ref.def_id.0),
2348 )
2349 .0
2350 .predicates
2351 .instantiate_identity()
2352 {
2353 tracing::debug!(?pred);
2354 let sup_trait_ref = match pred.kind().skip_binder() {
2355 rustc_type_ir::ClauseKind::Trait(pred) => pred.trait_ref,
2356 _ => continue,
2357 };
2358 let sup_trait_ref =
2359 EarlyBinder::bind(sup_trait_ref).instantiate(interner, trait_ref.args);
2360 stack.push(sup_trait_ref);
2361 }
2362 tracing::debug!(?stack);
2363 }
2364
2365 None
2366 };
2367
2368 match res {
2369 TypeNs::SelfType(impl_id) => {
2370 let trait_ref = db.impl_trait(impl_id)?;
2371
2372 search(trait_ref.skip_binder())
2378 }
2379 TypeNs::GenericParam(param_id) => {
2380 if let GenericDefId::TraitId(trait_id) = param_id.parent() {
2384 let trait_name = &db.trait_signature(trait_id).name;
2385 tracing::debug!(?trait_name);
2386 let trait_generics = generics(db, trait_id.into());
2387 tracing::debug!(?trait_generics);
2388 if trait_generics[param_id.local_id()].is_trait_self() {
2389 let args = GenericArgs::identity_for_item(interner, trait_id.into());
2390 let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
2391 tracing::debug!(?args, ?trait_ref);
2392 return search(trait_ref);
2393 }
2394 }
2395
2396 let predicates =
2397 generic_predicates_for_param(db, def, param_id.into(), assoc_name.clone());
2398 predicates
2399 .as_ref()
2400 .iter_identity_copied()
2401 .find_map(|pred| match pred.kind().skip_binder() {
2402 rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate),
2403 _ => None,
2404 })
2405 .and_then(|trait_predicate| {
2406 let trait_ref = trait_predicate.trait_ref;
2407 assert!(
2408 !trait_ref.has_escaping_bound_vars(),
2409 "FIXME unexpected higher-ranked trait bound"
2410 );
2411 search(trait_ref)
2412 })
2413 }
2414 _ => None,
2415 }
2416}