1pub(crate) mod diagnostics;
9pub(crate) mod path;
10
11use std::{
12 cell::OnceCell,
13 iter, mem,
14 ops::{self, Not as _},
15};
16
17use base_db::Crate;
18use chalk_ir::{
19 Mutability, Safety, TypeOutlives,
20 cast::Cast,
21 fold::{Shift, TypeFoldable},
22 interner::HasInterner,
23};
24
25use either::Either;
26use hir_def::{
27 AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
28 FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LocalFieldId,
29 Lookup, StaticId, StructId, TypeAliasId, TypeOrConstParamId, UnionId, VariantId,
30 builtin_type::BuiltinType,
31 expr_store::{ExpressionStore, path::Path},
32 hir::generics::{GenericParamDataRef, TypeOrConstParamData, WherePredicate},
33 item_tree::FieldsShape,
34 lang_item::LangItem,
35 resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
36 signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
37 type_ref::{
38 ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier,
39 TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
40 },
41};
42use hir_expand::name::Name;
43use la_arena::{Arena, ArenaMap};
44use rustc_hash::FxHashSet;
45use stdx::{impl_from, never};
46use triomphe::{Arc, ThinArc};
47
48use crate::{
49 AliasTy, Binders, BoundVar, CallableSig, Const, DebruijnIndex, DomainGoal, DynTy, FnAbi,
50 FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
51 LifetimeData, LifetimeOutlives, PolyFnSig, QuantifiedWhereClause, QuantifiedWhereClauses,
52 Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
53 all_super_traits,
54 consteval::{intern_const_ref, path_to_const, unknown_const, unknown_const_as_generic},
55 db::HirDatabase,
56 error_lifetime,
57 generics::{Generics, generics, trait_self_param_idx},
58 lower::{
59 diagnostics::*,
60 path::{PathDiagnosticCallback, PathLoweringContext},
61 },
62 make_binders,
63 mapping::{ToChalk, from_chalk_trait_id, lt_to_placeholder_idx},
64 static_lifetime, to_chalk_trait_id, to_placeholder_idx,
65 utils::all_super_trait_refs,
66 variable_kinds_from_iter,
67};
68
69#[derive(Debug, Default)]
70struct ImplTraitLoweringState {
71 mode: ImplTraitLoweringMode,
75 opaque_type_data: Arena<ImplTrait>,
77}
78impl ImplTraitLoweringState {
79 fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState {
80 Self { mode, opaque_type_data: Arena::new() }
81 }
82}
83
84pub(crate) struct PathDiagnosticCallbackData(pub(crate) TypeRefId);
85
86#[derive(Debug, Clone)]
87pub enum LifetimeElisionKind {
88 AnonymousCreateParameter { report_in_path: bool },
103
104 Elided(Lifetime),
106
107 AnonymousReportError,
111
112 StaticIfNoLifetimeInScope { only_lint: bool },
116
117 ElisionFailure,
119
120 Infer,
122}
123
124impl LifetimeElisionKind {
125 #[inline]
126 pub(crate) fn for_const(const_parent: ItemContainerId) -> LifetimeElisionKind {
127 match const_parent {
128 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
129 LifetimeElisionKind::Elided(static_lifetime())
130 }
131 ItemContainerId::ImplId(_) => {
132 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true }
133 }
134 ItemContainerId::TraitId(_) => {
135 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false }
136 }
137 }
138 }
139
140 #[inline]
141 pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind {
142 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() }
143 }
144
145 #[inline]
146 pub(crate) fn for_fn_ret() -> LifetimeElisionKind {
147 LifetimeElisionKind::Elided(error_lifetime())
149 }
150}
151
152#[derive(Debug)]
153pub struct TyLoweringContext<'db> {
154 pub db: &'db dyn HirDatabase,
155 resolver: &'db Resolver<'db>,
156 store: &'db ExpressionStore,
157 def: GenericDefId,
158 generics: OnceCell<Generics>,
159 in_binders: DebruijnIndex,
160 pub type_param_mode: ParamLoweringMode,
165 impl_trait_mode: ImplTraitLoweringState,
166 pub(crate) unsized_types: FxHashSet<Ty>,
168 pub(crate) diagnostics: Vec<TyLoweringDiagnostic>,
169 lifetime_elision: LifetimeElisionKind,
170}
171
172impl<'db> TyLoweringContext<'db> {
173 pub fn new(
174 db: &'db dyn HirDatabase,
175 resolver: &'db Resolver<'db>,
176 store: &'db ExpressionStore,
177 def: GenericDefId,
178 lifetime_elision: LifetimeElisionKind,
179 ) -> Self {
180 let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
181 let type_param_mode = ParamLoweringMode::Placeholder;
182 let in_binders = DebruijnIndex::INNERMOST;
183 Self {
184 db,
185 resolver,
186 def,
187 generics: Default::default(),
188 store,
189 in_binders,
190 impl_trait_mode,
191 type_param_mode,
192 unsized_types: FxHashSet::default(),
193 diagnostics: Vec::new(),
194 lifetime_elision,
195 }
196 }
197
198 pub fn with_debruijn<T>(
199 &mut self,
200 debruijn: DebruijnIndex,
201 f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
202 ) -> T {
203 let old_debruijn = mem::replace(&mut self.in_binders, debruijn);
204 let result = f(self);
205 self.in_binders = old_debruijn;
206 result
207 }
208
209 pub fn with_shifted_in<T>(
210 &mut self,
211 debruijn: DebruijnIndex,
212 f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
213 ) -> T {
214 self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f)
215 }
216
217 fn with_lifetime_elision<T>(
218 &mut self,
219 lifetime_elision: LifetimeElisionKind,
220 f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
221 ) -> T {
222 let old_lifetime_elision = mem::replace(&mut self.lifetime_elision, lifetime_elision);
223 let result = f(self);
224 self.lifetime_elision = old_lifetime_elision;
225 result
226 }
227
228 pub fn with_impl_trait_mode(self, impl_trait_mode: ImplTraitLoweringMode) -> Self {
229 Self { impl_trait_mode: ImplTraitLoweringState::new(impl_trait_mode), ..self }
230 }
231
232 pub fn with_type_param_mode(self, type_param_mode: ParamLoweringMode) -> Self {
233 Self { type_param_mode, ..self }
234 }
235
236 pub fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self {
237 self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode);
238 self
239 }
240
241 pub fn type_param_mode(&mut self, type_param_mode: ParamLoweringMode) -> &mut Self {
242 self.type_param_mode = type_param_mode;
243 self
244 }
245
246 pub fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
247 self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind });
248 }
249}
250
251#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
252pub enum ImplTraitLoweringMode {
253 Opaque,
258 #[default]
260 Disallowed,
261}
262
263#[derive(Copy, Clone, Debug, PartialEq, Eq)]
264pub enum ParamLoweringMode {
265 Placeholder,
266 Variable,
267}
268
269impl<'a> TyLoweringContext<'a> {
270 pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty {
271 self.lower_ty_ext(type_ref).0
272 }
273
274 pub fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const {
275 let const_ref = &self.store[const_ref.expr];
276 match const_ref {
277 hir_def::hir::Expr::Path(path) => path_to_const(
278 self.db,
279 self.resolver,
280 path,
281 self.type_param_mode,
282 || self.generics(),
283 self.in_binders,
284 const_type.clone(),
285 )
286 .unwrap_or_else(|| unknown_const(const_type)),
287 hir_def::hir::Expr::Literal(literal) => intern_const_ref(
288 self.db,
289 &match *literal {
290 hir_def::hir::Literal::Float(_, _)
291 | hir_def::hir::Literal::String(_)
292 | hir_def::hir::Literal::ByteString(_)
293 | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown,
294 hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c),
295 hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b),
296 hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val),
297 hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val),
298 },
299 const_type,
300 self.resolver.krate(),
301 ),
302 _ => unknown_const(const_type),
303 }
304 }
305
306 pub fn lower_path_as_const(&mut self, path: &Path, const_type: Ty) -> Const {
307 path_to_const(
308 self.db,
309 self.resolver,
310 path,
311 self.type_param_mode,
312 || self.generics(),
313 self.in_binders,
314 const_type.clone(),
315 )
316 .unwrap_or_else(|| unknown_const(const_type))
317 }
318
319 fn generics(&self) -> &Generics {
320 self.generics.get_or_init(|| generics(self.db, self.def))
321 }
322
323 pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) {
324 let mut res = None;
325 let type_ref = &self.store[type_ref_id];
326 let ty = match type_ref {
327 TypeRef::Never => TyKind::Never.intern(Interner),
328 TypeRef::Tuple(inner) => {
329 let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr));
330 TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
331 .intern(Interner)
332 }
333 TypeRef::Path(path) => {
334 let (ty, res_) =
335 self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id));
336 res = res_;
337 ty
338 }
339 &TypeRef::TypeParam(type_param_id) => {
340 res = Some(TypeNs::GenericParam(type_param_id));
341 match self.type_param_mode {
342 ParamLoweringMode::Placeholder => {
343 let generics = self.generics();
344 let idx = generics.type_or_const_param_idx(type_param_id.into()).unwrap();
345 TyKind::Placeholder(to_placeholder_idx(
346 self.db,
347 type_param_id.into(),
348 idx as u32,
349 ))
350 }
351 ParamLoweringMode::Variable => {
352 let idx =
353 self.generics().type_or_const_param_idx(type_param_id.into()).unwrap();
354 TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
355 }
356 }
357 .intern(Interner)
358 }
359 &TypeRef::RawPtr(inner, mutability) => {
360 let inner_ty = self.lower_ty(inner);
361 TyKind::Raw(lower_to_chalk_mutability(mutability), inner_ty).intern(Interner)
362 }
363 TypeRef::Array(array) => {
364 let inner_ty = self.lower_ty(array.ty);
365 let const_len = self.lower_const(&array.len, TyBuilder::usize());
366 TyKind::Array(inner_ty, const_len).intern(Interner)
367 }
368 &TypeRef::Slice(inner) => {
369 let inner_ty = self.lower_ty(inner);
370 TyKind::Slice(inner_ty).intern(Interner)
371 }
372 TypeRef::Reference(ref_) => {
373 let inner_ty = self.lower_ty(ref_.ty);
374 let lifetime = ref_
376 .lifetime
377 .as_ref()
378 .map_or_else(error_lifetime, |&lr| self.lower_lifetime(lr));
379 TyKind::Ref(lower_to_chalk_mutability(ref_.mutability), lifetime, inner_ty)
380 .intern(Interner)
381 }
382 TypeRef::Placeholder => TyKind::Error.intern(Interner),
383 TypeRef::Fn(fn_) => {
384 let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
385 let (params, ret) = fn_.split_params_and_ret();
386 let mut subst = Vec::with_capacity(fn_.params.len());
387 ctx.with_lifetime_elision(
388 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false },
389 |ctx| {
390 subst.extend(params.iter().map(|&(_, tr)| ctx.lower_ty(tr)));
391 },
392 );
393 ctx.with_lifetime_elision(LifetimeElisionKind::for_fn_ret(), |ctx| {
394 subst.push(ctx.lower_ty(ret));
395 });
396 Substitution::from_iter(Interner, subst)
397 });
398 TyKind::Function(FnPointer {
399 num_binders: 0, sig: FnSig {
401 abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
402 safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
403 variadic: fn_.is_varargs,
404 },
405 substitution: FnSubst(substs),
406 })
407 .intern(Interner)
408 }
409 TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
410 TypeRef::ImplTrait(bounds) => {
411 match self.impl_trait_mode.mode {
412 ImplTraitLoweringMode::Opaque => {
413 let origin = match self.def {
414 GenericDefId::FunctionId(it) => Either::Left(it),
415 GenericDefId::TypeAliasId(it) => Either::Right(it),
416 _ => panic!(
417 "opaque impl trait lowering must be in function or type alias"
418 ),
419 };
420
421 let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait {
425 bounds: crate::make_single_type_binders(Vec::default()),
426 });
427 let actual_opaque_type_data = self
437 .with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
438 ctx.lower_impl_trait(bounds, self.resolver.krate())
439 });
440 self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
441
442 let impl_trait_id = origin.either(
443 |f| ImplTraitId::ReturnTypeImplTrait(f, idx),
444 |a| ImplTraitId::TypeAliasImplTrait(a, idx),
445 );
446 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
447 let generics = generics(self.db, origin.either(|f| f.into(), |a| a.into()));
448 let parameters = generics.bound_vars_subst(self.db, self.in_binders);
449 TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner)
450 }
451 ImplTraitLoweringMode::Disallowed => {
452 TyKind::Error.intern(Interner)
454 }
455 }
456 }
457 TypeRef::Error => TyKind::Error.intern(Interner),
458 };
459 (ty, res)
460 }
461
462 fn lower_ty_only_param(&mut self, type_ref_id: TypeRefId) -> Option<TypeOrConstParamId> {
466 let type_ref = &self.store[type_ref_id];
467 let path = match type_ref {
468 TypeRef::Path(path) => path,
469 &TypeRef::TypeParam(idx) => return Some(idx.into()),
470 _ => return None,
471 };
472 if path.type_anchor().is_some() {
473 return None;
474 }
475 if path.segments().len() > 1 {
476 return None;
477 }
478 let mut ctx = self.at_path(PathId::from_type_ref_unchecked(type_ref_id));
479 let resolution = match ctx.resolve_path_in_type_ns() {
480 Some((it, None)) => it,
481 _ => return None,
482 };
483 match resolution {
484 TypeNs::GenericParam(param_id) => Some(param_id.into()),
485 _ => None,
486 }
487 }
488
489 #[inline]
490 fn on_path_diagnostic_callback(type_ref: TypeRefId) -> PathDiagnosticCallback<'static> {
491 PathDiagnosticCallback {
492 data: Either::Left(PathDiagnosticCallbackData(type_ref)),
493 callback: |data, this, diag| {
494 let type_ref = data.as_ref().left().unwrap().0;
495 this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag))
496 },
497 }
498 }
499
500 #[inline]
501 fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a> {
502 PathLoweringContext::new(
503 self,
504 Self::on_path_diagnostic_callback(path_id.type_ref()),
505 &self.store[path_id],
506 )
507 }
508
509 pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty, Option<TypeNs>) {
510 if let Some(type_ref) = path.type_anchor() {
512 let (ty, res) = self.lower_ty_ext(type_ref);
513 let mut ctx = self.at_path(path_id);
514 return ctx.lower_ty_relative_path(ty, res, false);
515 }
516
517 let mut ctx = self.at_path(path_id);
518 let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() {
519 Some(it) => it,
520 None => return (TyKind::Error.intern(Interner), None),
521 };
522
523 if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
524 let bound = TypeBound::Path(path_id, TraitBoundModifier::None);
526 let ty = self.lower_dyn_trait(&[bound]);
527 return (ty, None);
528 }
529
530 ctx.lower_partly_resolved_path(resolution, false)
531 }
532
533 fn lower_trait_ref_from_path(
534 &mut self,
535 path_id: PathId,
536 explicit_self_ty: Ty,
537 ) -> Option<(TraitRef, PathLoweringContext<'_, 'a>)> {
538 let mut ctx = self.at_path(path_id);
539 let resolved = match ctx.resolve_path_in_type_ns_fully()? {
540 TypeNs::TraitId(tr) => tr,
542 _ => return None,
543 };
544 Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx))
545 }
546
547 fn lower_trait_ref(
548 &mut self,
549 trait_ref: &HirTraitRef,
550 explicit_self_ty: Ty,
551 ) -> Option<TraitRef> {
552 self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
553 }
554
555 pub(crate) fn lower_where_predicate<'b>(
559 &'b mut self,
560 where_predicate: &'b WherePredicate,
561 ignore_bindings: bool,
562 ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
563 match where_predicate {
564 WherePredicate::ForLifetime { target, bound, .. }
565 | WherePredicate::TypeBound { target, bound } => {
566 let self_ty = self.lower_ty(*target);
567 Either::Left(self.lower_type_bound(bound, self_ty, ignore_bindings))
568 }
569 &WherePredicate::Lifetime { bound, target } => Either::Right(iter::once(
570 crate::wrap_empty_binders(WhereClause::LifetimeOutlives(LifetimeOutlives {
571 a: self.lower_lifetime(bound),
572 b: self.lower_lifetime(target),
573 })),
574 )),
575 }
576 .into_iter()
577 }
578
579 pub(crate) fn lower_type_bound<'b>(
580 &'b mut self,
581 bound: &'b TypeBound,
582 self_ty: Ty,
583 ignore_bindings: bool,
584 ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
585 let mut assoc_bounds = None;
586 let mut clause = None;
587 match bound {
588 &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
589 if let Some((trait_ref, mut ctx)) =
591 self.lower_trait_ref_from_path(path, self_ty.clone())
592 {
593 let meta_sized = LangItem::MetaSized
596 .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
597 let pointee_sized = LangItem::PointeeSized
598 .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
599 let destruct = LangItem::Destruct
600 .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
601 let hir_trait_id = trait_ref.hir_trait_id();
602 if meta_sized.is_some_and(|it| it == hir_trait_id)
603 || destruct.is_some_and(|it| it == hir_trait_id)
604 {
605 } else if pointee_sized.is_some_and(|it| it == hir_trait_id) {
607 ctx.ty_ctx().unsized_types.insert(self_ty);
609 } else {
610 if !ignore_bindings {
611 assoc_bounds =
612 ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
613 }
614 clause =
615 Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
616 }
617 }
618 }
619 &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
620 let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
621 let trait_id = self
625 .lower_trait_ref_from_path(path, self_ty.clone())
626 .map(|(trait_ref, _)| trait_ref.hir_trait_id());
627 if trait_id == sized_trait {
628 self.unsized_types.insert(self_ty);
629 }
630 }
631 &TypeBound::Lifetime(l) => {
632 let lifetime = self.lower_lifetime(l);
633 clause = Some(crate::wrap_empty_binders(WhereClause::TypeOutlives(TypeOutlives {
634 ty: self_ty,
635 lifetime,
636 })));
637 }
638 TypeBound::Use(_) | TypeBound::Error => {}
639 }
640 clause.into_iter().chain(assoc_bounds.into_iter().flatten())
641 }
642
643 fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty {
644 let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
645 let mut lifetime = None;
651 let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
652 let mut lowered_bounds = Vec::new();
653 for b in bounds {
654 ctx.lower_type_bound(b, self_ty.clone(), false).for_each(|b| {
655 let filter = match b.skip_binders() {
656 WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true,
657 WhereClause::LifetimeOutlives(_) => false,
658 WhereClause::TypeOutlives(t) => {
659 lifetime = Some(t.lifetime.clone());
660 false
661 }
662 };
663 if filter {
664 lowered_bounds.push(b);
665 }
666 });
667 }
668
669 let mut multiple_regular_traits = false;
670 let mut multiple_same_projection = false;
671 lowered_bounds.sort_unstable_by(|lhs, rhs| {
672 use std::cmp::Ordering;
673 match (lhs.skip_binders(), rhs.skip_binders()) {
674 (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => {
675 let lhs_id = lhs.trait_id;
676 let lhs_is_auto = ctx
677 .db
678 .trait_signature(from_chalk_trait_id(lhs_id))
679 .flags
680 .contains(TraitFlags::AUTO);
681 let rhs_id = rhs.trait_id;
682 let rhs_is_auto = ctx
683 .db
684 .trait_signature(from_chalk_trait_id(rhs_id))
685 .flags
686 .contains(TraitFlags::AUTO);
687
688 if !lhs_is_auto && !rhs_is_auto {
689 multiple_regular_traits = true;
690 }
691 (lhs_is_auto, lhs_id).cmp(&(rhs_is_auto, rhs_id))
694 }
695 (WhereClause::Implemented(_), _) => Ordering::Less,
696 (_, WhereClause::Implemented(_)) => Ordering::Greater,
697 (WhereClause::AliasEq(lhs), WhereClause::AliasEq(rhs)) => {
698 match (&lhs.alias, &rhs.alias) {
699 (AliasTy::Projection(lhs_proj), AliasTy::Projection(rhs_proj)) => {
700 if lhs_proj.associated_ty_id == rhs_proj.associated_ty_id {
704 multiple_same_projection = true;
705 }
706 lhs_proj.associated_ty_id.cmp(&rhs_proj.associated_ty_id)
707 }
708 _ => unreachable!(),
710 }
711 }
712 _ => unreachable!(),
714 }
715 });
716
717 if multiple_regular_traits || multiple_same_projection {
718 return None;
719 }
720
721 lowered_bounds.first().and_then(|b| b.trait_id())?;
722
723 lowered_bounds.dedup();
726
727 Some(QuantifiedWhereClauses::from_iter(Interner, lowered_bounds))
728 });
729
730 if let Some(bounds) = bounds {
731 let bounds = crate::make_single_type_binders(bounds);
732 TyKind::Dyn(DynTy {
733 bounds,
734 lifetime: match lifetime {
735 Some(it) => match it.bound_var(Interner) {
736 Some(bound_var) => bound_var
737 .shifted_out_to(DebruijnIndex::new(2))
738 .map(|bound_var| LifetimeData::BoundVar(bound_var).intern(Interner))
739 .unwrap_or(it),
740 None => it,
741 },
742 None => error_lifetime(),
743 },
744 })
745 .intern(Interner)
746 } else {
747 TyKind::Error.intern(Interner)
750 }
751 }
752
753 fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: Crate) -> ImplTrait {
754 cov_mark::hit!(lower_rpit);
755 let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
756 let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
757 let mut predicates = Vec::new();
758 for b in bounds {
759 predicates.extend(ctx.lower_type_bound(b, self_ty.clone(), false));
760 }
761
762 if !ctx.unsized_types.contains(&self_ty) {
763 let sized_trait =
764 LangItem::Sized.resolve_trait(ctx.db, krate).map(to_chalk_trait_id);
765 let sized_clause = sized_trait.map(|trait_id| {
766 let clause = WhereClause::Implemented(TraitRef {
767 trait_id,
768 substitution: Substitution::from1(Interner, self_ty.clone()),
769 });
770 crate::wrap_empty_binders(clause)
771 });
772 predicates.extend(sized_clause);
773 }
774 predicates.shrink_to_fit();
775 predicates
776 });
777 ImplTrait { bounds: crate::make_single_type_binders(predicates) }
778 }
779
780 pub fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Lifetime {
781 match self.resolver.resolve_lifetime(&self.store[lifetime]) {
782 Some(resolution) => match resolution {
783 LifetimeNs::Static => static_lifetime(),
784 LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
785 ParamLoweringMode::Placeholder => {
786 let generics = self.generics();
787 let idx = generics.lifetime_idx(id).unwrap();
788 LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id, idx as u32))
789 }
790 ParamLoweringMode::Variable => {
791 let idx = match self.generics().lifetime_idx(id) {
792 None => return error_lifetime(),
793 Some(idx) => idx,
794 };
795
796 LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
797 }
798 }
799 .intern(Interner),
800 },
801 None => error_lifetime(),
802 }
803 }
804}
805
806pub(crate) fn callable_item_signature_query(db: &dyn HirDatabase, def: CallableDefId) -> PolyFnSig {
808 match def {
809 CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
810 CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
811 CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
812 }
813}
814
815fn named_associated_type_shorthand_candidates<R>(
816 db: &dyn HirDatabase,
817 def: GenericDefId,
820 res: TypeNs,
821 assoc_name: Option<Name>,
822 mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
826) -> Option<R> {
827 let mut search = |t| {
828 all_super_trait_refs(db, t, |t| {
829 let data = t.hir_trait_id().trait_items(db);
830
831 for (name, assoc_id) in &data.items {
832 if let AssocItemId::TypeAliasId(alias) = assoc_id
833 && let Some(result) = cb(name, &t, *alias)
834 {
835 return Some(result);
836 }
837 }
838 None
839 })
840 };
841
842 match res {
843 TypeNs::SelfType(impl_id) => {
844 let trait_ref = db.impl_trait(impl_id)?.into_value_and_skipped_binders().0;
847
848 let impl_id_as_generic_def: GenericDefId = impl_id.into();
849 if impl_id_as_generic_def != def {
850 let subst = TyBuilder::subst_for_def(db, impl_id, None)
851 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
852 .build();
853 let trait_ref = subst.apply(trait_ref, Interner);
854 search(trait_ref)
855 } else {
856 search(trait_ref)
857 }
858 }
859 TypeNs::GenericParam(param_id) => {
860 let predicates = db.generic_predicates_for_param(def, param_id.into(), assoc_name);
861 let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {
862 WhereClause::Implemented(tr) => search(
864 tr.clone()
865 .shifted_out_to(Interner, DebruijnIndex::ONE)
866 .expect("FIXME unexpected higher-ranked trait bound"),
867 ),
868 _ => None,
869 });
870 if res.is_some() {
871 return res;
872 }
873 if let GenericDefId::TraitId(trait_id) = param_id.parent() {
875 let trait_generics = generics(db, trait_id.into());
876 if trait_generics[param_id.local_id()].is_trait_self() {
877 let trait_ref = TyBuilder::trait_ref(db, trait_id)
878 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
879 .build();
880 return search(trait_ref);
881 }
882 }
883 None
884 }
885 _ => None,
886 }
887}
888
889pub(crate) type Diagnostics = Option<ThinArc<(), TyLoweringDiagnostic>>;
890
891pub(crate) fn create_diagnostics(diagnostics: Vec<TyLoweringDiagnostic>) -> Diagnostics {
892 (!diagnostics.is_empty()).then(|| ThinArc::from_header_and_iter((), diagnostics.into_iter()))
893}
894
895pub(crate) fn field_types_query(
896 db: &dyn HirDatabase,
897 variant_id: VariantId,
898) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> {
899 db.field_types_with_diagnostics(variant_id).0
900}
901
902pub(crate) fn field_types_with_diagnostics_query(
904 db: &dyn HirDatabase,
905 variant_id: VariantId,
906) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) {
907 let var_data = variant_id.fields(db);
908 let fields = var_data.fields();
909 if fields.is_empty() {
910 return (Arc::new(ArenaMap::default()), None);
911 }
912
913 let (resolver, def): (_, GenericDefId) = match variant_id {
914 VariantId::StructId(it) => (it.resolver(db), it.into()),
915 VariantId::UnionId(it) => (it.resolver(db), it.into()),
916 VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
917 };
918 let generics = generics(db, def);
919 let mut res = ArenaMap::default();
920 let mut ctx = TyLoweringContext::new(
921 db,
922 &resolver,
923 &var_data.store,
924 def,
925 LifetimeElisionKind::AnonymousReportError,
926 )
927 .with_type_param_mode(ParamLoweringMode::Variable);
928 for (field_id, field_data) in fields.iter() {
929 res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
930 }
931 (Arc::new(res), create_diagnostics(ctx.diagnostics))
932}
933
934pub(crate) fn generic_predicates_for_param_query(
943 db: &dyn HirDatabase,
944 def: GenericDefId,
945 param_id: TypeOrConstParamId,
946 assoc_name: Option<Name>,
947) -> GenericPredicates {
948 let generics = generics(db, def);
949 if generics.has_no_predicates() && generics.is_empty() {
950 return GenericPredicates(None);
951 }
952
953 let resolver = def.resolver(db);
954 let mut ctx = TyLoweringContext::new(
955 db,
956 &resolver,
957 generics.store(),
958 def,
959 LifetimeElisionKind::AnonymousReportError,
960 )
961 .with_type_param_mode(ParamLoweringMode::Variable);
962
963 let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_>| match pred {
965 WherePredicate::ForLifetime { target, bound, .. }
966 | WherePredicate::TypeBound { target, bound, .. } => {
967 let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
968 if invalid_target {
969 let lower = || -> bool {
974 match bound {
975 TypeBound::Path(_, TraitBoundModifier::Maybe) => true,
976 TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
977 let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
978 return false;
979 };
980 let Some(pointee_sized) =
981 LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate())
982 else {
983 return false;
984 };
985 ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and(
988 |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized),
989 )
990 }
991 _ => false,
992 }
993 }();
994 if lower {
995 ctx.lower_where_predicate(pred, true).for_each(drop);
996 }
997 return false;
998 }
999
1000 match bound {
1001 &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => {
1002 let path = &ctx.store[path];
1005
1006 let Some(assoc_name) = &assoc_name else { return true };
1007 let Some(TypeNs::TraitId(tr)) =
1008 resolver.resolve_path_in_type_ns_fully(db, path)
1009 else {
1010 return false;
1011 };
1012
1013 all_super_traits(db, tr).iter().any(|tr| {
1014 tr.trait_items(db).items.iter().any(|(name, item)| {
1015 matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
1016 })
1017 })
1018 }
1019 TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false,
1020 }
1021 }
1022 WherePredicate::Lifetime { .. } => false,
1023 };
1024 let mut predicates = Vec::new();
1025 for maybe_parent_generics in
1026 std::iter::successors(Some(&generics), |generics| generics.parent_generics())
1027 {
1028 ctx.store = maybe_parent_generics.store();
1029 for pred in maybe_parent_generics.where_predicates() {
1030 if predicate(pred, &mut ctx) {
1031 predicates.extend(
1032 ctx.lower_where_predicate(pred, true).map(|p| make_binders(db, &generics, p)),
1033 );
1034 }
1035 }
1036 }
1037
1038 let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
1039 if !subst.is_empty(Interner) {
1040 let explicitly_unsized_tys = ctx.unsized_types;
1041 if let Some(implicitly_sized_predicates) = implicitly_sized_clauses(
1042 db,
1043 param_id.parent,
1044 &explicitly_unsized_tys,
1045 &subst,
1046 &resolver,
1047 ) {
1048 predicates.extend(
1049 implicitly_sized_predicates
1050 .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))),
1051 );
1052 };
1053 }
1054 GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
1055}
1056
1057pub(crate) fn generic_predicates_for_param_cycle_result(
1058 _db: &dyn HirDatabase,
1059 _def: GenericDefId,
1060 _param_id: TypeOrConstParamId,
1061 _assoc_name: Option<Name>,
1062) -> GenericPredicates {
1063 GenericPredicates(None)
1064}
1065
1066pub(crate) fn trait_environment_for_body_query(
1067 db: &dyn HirDatabase,
1068 def: DefWithBodyId,
1069) -> Arc<TraitEnvironment> {
1070 let Some(def) = def.as_generic_def_id(db) else {
1071 let krate = def.module(db).krate();
1072 return TraitEnvironment::empty(krate);
1073 };
1074 db.trait_environment(def)
1075}
1076
1077pub(crate) fn trait_environment_query(
1078 db: &dyn HirDatabase,
1079 def: GenericDefId,
1080) -> Arc<TraitEnvironment> {
1081 let generics = generics(db, def);
1082 if generics.has_no_predicates() && generics.is_empty() {
1083 return TraitEnvironment::empty(def.krate(db));
1084 }
1085
1086 let resolver = def.resolver(db);
1087 let mut ctx = TyLoweringContext::new(
1088 db,
1089 &resolver,
1090 generics.store(),
1091 def,
1092 LifetimeElisionKind::AnonymousReportError,
1093 )
1094 .with_type_param_mode(ParamLoweringMode::Placeholder);
1095 let mut traits_in_scope = Vec::new();
1096 let mut clauses = Vec::new();
1097 for maybe_parent_generics in
1098 std::iter::successors(Some(&generics), |generics| generics.parent_generics())
1099 {
1100 ctx.store = maybe_parent_generics.store();
1101 for pred in maybe_parent_generics.where_predicates() {
1102 for pred in ctx.lower_where_predicate(pred, false) {
1103 if let WhereClause::Implemented(tr) = pred.skip_binders() {
1104 traits_in_scope
1105 .push((tr.self_type_parameter(Interner).clone(), tr.hir_trait_id()));
1106 }
1107 let program_clause: Binders<DomainGoal> =
1108 pred.map(|pred| pred.into_from_env_goal(Interner).cast(Interner));
1109 clauses.push(program_clause);
1110 }
1111 }
1112 }
1113
1114 if let Some(trait_id) = def.assoc_trait_container(db) {
1115 cov_mark::hit!(trait_self_implements_self);
1119 let substs = TyBuilder::placeholder_subst(db, trait_id);
1120 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
1121 let pred = WhereClause::Implemented(trait_ref);
1122 clauses.push(Binders::empty(
1123 Interner,
1124 pred.cast::<DomainGoal>(Interner).into_from_env_goal(Interner),
1125 ));
1126 }
1127
1128 let subst = generics.placeholder_subst(db);
1129 if !subst.is_empty(Interner) {
1130 let explicitly_unsized_tys = ctx.unsized_types;
1131 if let Some(implicitly_sized_clauses) =
1132 implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
1133 {
1134 clauses.extend(implicitly_sized_clauses.map(|pred| {
1135 Binders::empty(
1136 Interner,
1137 pred.into_from_env_goal(Interner).cast::<DomainGoal>(Interner),
1138 )
1139 }));
1140 };
1141 }
1142
1143 let clauses = chalk_ir::ProgramClauses::from_iter(
1144 Interner,
1145 clauses.into_iter().map(|g| {
1146 chalk_ir::ProgramClause::new(
1147 Interner,
1148 chalk_ir::ProgramClauseData(g.map(|g| chalk_ir::ProgramClauseImplication {
1149 consequence: g,
1150 conditions: chalk_ir::Goals::empty(Interner),
1151 constraints: chalk_ir::Constraints::empty(Interner),
1152 priority: chalk_ir::ClausePriority::High,
1153 })),
1154 )
1155 }),
1156 );
1157 let env = chalk_ir::Environment { clauses };
1158
1159 TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env)
1160}
1161
1162#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1163pub struct GenericPredicates(Option<Arc<[Binders<QuantifiedWhereClause>]>>);
1164
1165impl ops::Deref for GenericPredicates {
1166 type Target = [Binders<crate::QuantifiedWhereClause>];
1167
1168 fn deref(&self) -> &Self::Target {
1169 self.0.as_deref().unwrap_or(&[])
1170 }
1171}
1172
1173pub(crate) fn generic_predicates_query(
1175 db: &dyn HirDatabase,
1176 def: GenericDefId,
1177) -> GenericPredicates {
1178 generic_predicates_filtered_by(db, def, |_, _| true).0
1179}
1180
1181fn generic_predicates_filtered_by<F>(
1184 db: &dyn HirDatabase,
1185 def: GenericDefId,
1186 filter: F,
1187) -> (GenericPredicates, Diagnostics)
1188where
1189 F: Fn(&WherePredicate, GenericDefId) -> bool,
1190{
1191 let generics = generics(db, def);
1192 if generics.has_no_predicates() && generics.is_empty() {
1193 return (GenericPredicates(None), None);
1194 }
1195
1196 let resolver = def.resolver(db);
1197 let mut ctx = TyLoweringContext::new(
1198 db,
1199 &resolver,
1200 generics.store(),
1201 def,
1202 LifetimeElisionKind::AnonymousReportError,
1203 )
1204 .with_type_param_mode(ParamLoweringMode::Variable);
1205
1206 let mut predicates = Vec::new();
1207 for maybe_parent_generics in
1208 std::iter::successors(Some(&generics), |generics| generics.parent_generics())
1209 {
1210 ctx.store = maybe_parent_generics.store();
1211 for pred in maybe_parent_generics.where_predicates() {
1212 if filter(pred, maybe_parent_generics.def()) {
1213 predicates.extend(
1216 ctx.lower_where_predicate(pred, false).map(|p| make_binders(db, &generics, p)),
1217 );
1218 }
1219 }
1220 }
1221
1222 if !generics.is_empty() {
1223 let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
1224 let explicitly_unsized_tys = ctx.unsized_types;
1225 if let Some(implicitly_sized_predicates) =
1226 implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
1227 {
1228 predicates.extend(
1229 implicitly_sized_predicates
1230 .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))),
1231 );
1232 };
1233 }
1234
1235 (
1236 GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
1237 create_diagnostics(ctx.diagnostics),
1238 )
1239}
1240
1241fn implicitly_sized_clauses<'db, 'a, 'subst: 'a>(
1244 db: &'db dyn HirDatabase,
1245 def: GenericDefId,
1246 explicitly_unsized_tys: &'a FxHashSet<Ty>,
1247 substitution: &'subst Substitution,
1248 resolver: &Resolver<'db>,
1249) -> Option<impl Iterator<Item = WhereClause>> {
1250 let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?;
1251
1252 let trait_self_idx = trait_self_param_idx(db, def);
1253
1254 Some(
1255 substitution
1256 .iter(Interner)
1257 .enumerate()
1258 .filter_map(
1259 move |(idx, generic_arg)| {
1260 if Some(idx) == trait_self_idx { None } else { Some(generic_arg) }
1261 },
1262 )
1263 .filter_map(|generic_arg| generic_arg.ty(Interner))
1264 .filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty))
1265 .map(move |self_ty| {
1266 WhereClause::Implemented(TraitRef {
1267 trait_id: sized_trait,
1268 substitution: Substitution::from1(Interner, self_ty.clone()),
1269 })
1270 }),
1271 )
1272}
1273
1274#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1275pub struct GenericDefaults(Option<Arc<[Binders<crate::GenericArg>]>>);
1276
1277impl ops::Deref for GenericDefaults {
1278 type Target = [Binders<crate::GenericArg>];
1279
1280 fn deref(&self) -> &Self::Target {
1281 self.0.as_deref().unwrap_or(&[])
1282 }
1283}
1284
1285pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) -> GenericDefaults {
1286 db.generic_defaults_with_diagnostics(def).0
1287}
1288
1289pub(crate) fn generic_defaults_with_diagnostics_query(
1293 db: &dyn HirDatabase,
1294 def: GenericDefId,
1295) -> (GenericDefaults, Diagnostics) {
1296 let generic_params = generics(db, def);
1297 if generic_params.is_empty() {
1298 return (GenericDefaults(None), None);
1299 }
1300 let resolver = def.resolver(db);
1301
1302 let mut ctx = TyLoweringContext::new(
1303 db,
1304 &resolver,
1305 generic_params.store(),
1306 def,
1307 LifetimeElisionKind::AnonymousReportError,
1308 )
1309 .with_impl_trait_mode(ImplTraitLoweringMode::Disallowed)
1310 .with_type_param_mode(ParamLoweringMode::Variable);
1311 let mut idx = 0;
1312 let mut has_any_default = false;
1313 let mut defaults = generic_params
1314 .iter_parents_with_store()
1315 .map(|((id, p), store)| {
1316 ctx.store = store;
1317 let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
1318 has_any_default |= has_default;
1319 idx += 1;
1320 result
1321 })
1322 .collect::<Vec<_>>();
1323 ctx.diagnostics.clear(); defaults.extend(generic_params.iter_self().map(|(id, p)| {
1325 let (result, has_default) = handle_generic_param(&mut ctx, idx, id, p, &generic_params);
1326 has_any_default |= has_default;
1327 idx += 1;
1328 result
1329 }));
1330 let diagnostics = create_diagnostics(mem::take(&mut ctx.diagnostics));
1331 let defaults = if has_any_default {
1332 GenericDefaults(Some(Arc::from_iter(defaults)))
1333 } else {
1334 GenericDefaults(None)
1335 };
1336 return (defaults, diagnostics);
1337
1338 fn handle_generic_param(
1339 ctx: &mut TyLoweringContext<'_>,
1340 idx: usize,
1341 id: GenericParamId,
1342 p: GenericParamDataRef<'_>,
1343 generic_params: &Generics,
1344 ) -> (Binders<crate::GenericArg>, bool) {
1345 let binders = variable_kinds_from_iter(ctx.db, generic_params.iter_id().take(idx));
1346 match p {
1347 GenericParamDataRef::TypeParamData(p) => {
1348 let ty = p.default.as_ref().map_or_else(
1349 || TyKind::Error.intern(Interner),
1350 |ty| {
1351 fallback_bound_vars(ctx.lower_ty(*ty), idx)
1355 },
1356 );
1357 (Binders::new(binders, ty.cast(Interner)), p.default.is_some())
1358 }
1359 GenericParamDataRef::ConstParamData(p) => {
1360 let GenericParamId::ConstParamId(id) = id else {
1361 unreachable!("Unexpected lifetime or type argument")
1362 };
1363
1364 let mut val = p.default.as_ref().map_or_else(
1365 || unknown_const_as_generic(ctx.db.const_param_ty(id)),
1366 |c| {
1367 let param_ty = ctx.lower_ty(p.ty);
1368 let c = ctx.lower_const(c, param_ty);
1369 c.cast(Interner)
1370 },
1371 );
1372 val = fallback_bound_vars(val, idx);
1374 (Binders::new(binders, val), p.default.is_some())
1375 }
1376 GenericParamDataRef::LifetimeParamData(_) => {
1377 (Binders::new(binders, error_lifetime().cast(Interner)), false)
1378 }
1379 }
1380 }
1381}
1382
1383pub(crate) fn generic_defaults_with_diagnostics_cycle_result(
1384 _db: &dyn HirDatabase,
1385 _def: GenericDefId,
1386) -> (GenericDefaults, Diagnostics) {
1387 (GenericDefaults(None), None)
1388}
1389
1390fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1391 let data = db.function_signature(def);
1392 let resolver = def.resolver(db);
1393 let mut ctx_params = TyLoweringContext::new(
1394 db,
1395 &resolver,
1396 &data.store,
1397 def.into(),
1398 LifetimeElisionKind::for_fn_params(&data),
1399 )
1400 .with_type_param_mode(ParamLoweringMode::Variable);
1401 let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
1402
1403 let ret = match data.ret_type {
1404 Some(ret_type) => {
1405 let mut ctx_ret = TyLoweringContext::new(
1406 db,
1407 &resolver,
1408 &data.store,
1409 def.into(),
1410 LifetimeElisionKind::for_fn_ret(),
1411 )
1412 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1413 .with_type_param_mode(ParamLoweringMode::Variable);
1414 ctx_ret.lower_ty(ret_type)
1415 }
1416 None => TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
1417 };
1418 let generics = generics(db, def.into());
1419 let sig = CallableSig::from_params_and_return(
1420 params,
1421 ret,
1422 data.is_varargs(),
1423 if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
1424 data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
1425 );
1426 make_binders(db, &generics, sig)
1427}
1428
1429fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
1432 let generics = generics(db, def.into());
1433 let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
1434 make_binders(
1435 db,
1436 &generics,
1437 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(Interner),
1438 )
1439}
1440
1441fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
1443 let data = db.const_signature(def);
1444 let generics = generics(db, def.into());
1445 let resolver = def.resolver(db);
1446 let parent = def.loc(db).container;
1447 let mut ctx = TyLoweringContext::new(
1448 db,
1449 &resolver,
1450 &data.store,
1451 def.into(),
1452 LifetimeElisionKind::for_const(parent),
1453 )
1454 .with_type_param_mode(ParamLoweringMode::Variable);
1455
1456 make_binders(db, &generics, ctx.lower_ty(data.type_ref))
1457}
1458
1459fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> {
1461 let data = db.static_signature(def);
1462 let resolver = def.resolver(db);
1463 let mut ctx = TyLoweringContext::new(
1464 db,
1465 &resolver,
1466 &data.store,
1467 def.into(),
1468 LifetimeElisionKind::Elided(static_lifetime()),
1469 );
1470
1471 Binders::empty(Interner, ctx.lower_ty(data.type_ref))
1472}
1473
1474fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig {
1475 let field_tys = db.field_types(def.into());
1476 let params = field_tys.iter().map(|(_, ty)| ty.skip_binders().clone());
1477 let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
1478 Binders::new(
1479 binders,
1480 CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall),
1481 )
1482}
1483
1484fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Binders<Ty>> {
1486 let struct_data = def.fields(db);
1487 match struct_data.shape {
1488 FieldsShape::Record => None,
1489 FieldsShape::Unit => Some(type_for_adt(db, def.into())),
1490 FieldsShape::Tuple => {
1491 let generics = generics(db, AdtId::from(def).into());
1492 let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
1493 Some(make_binders(
1494 db,
1495 &generics,
1496 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(Interner),
1497 ))
1498 }
1499 }
1500}
1501
1502fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -> PolyFnSig {
1503 let field_tys = db.field_types(def.into());
1504 let params = field_tys.iter().map(|(_, ty)| ty.skip_binders().clone());
1505 let parent = def.lookup(db).parent;
1506 let (ret, binders) = type_for_adt(db, parent.into()).into_value_and_skipped_binders();
1507 Binders::new(
1508 binders,
1509 CallableSig::from_params_and_return(params, ret, false, Safety::Safe, FnAbi::RustCall),
1510 )
1511}
1512
1513fn type_for_enum_variant_constructor(
1515 db: &dyn HirDatabase,
1516 def: EnumVariantId,
1517) -> Option<Binders<Ty>> {
1518 let e = def.lookup(db).parent;
1519 match def.fields(db).shape {
1520 FieldsShape::Record => None,
1521 FieldsShape::Unit => Some(type_for_adt(db, e.into())),
1522 FieldsShape::Tuple => {
1523 let generics = generics(db, e.into());
1524 let substs = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
1525 Some(make_binders(
1526 db,
1527 &generics,
1528 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs)
1529 .intern(Interner),
1530 ))
1531 }
1532 }
1533}
1534
1535#[salsa_macros::tracked(cycle_result = type_for_adt_cycle_result)]
1536fn type_for_adt_tracked(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1537 type_for_adt(db, adt)
1538}
1539
1540fn type_for_adt_cycle_result(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1541 let generics = generics(db, adt.into());
1542 make_binders(db, &generics, TyKind::Error.intern(Interner))
1543}
1544
1545fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1546 let generics = generics(db, adt.into());
1547 let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
1548 let ty = TyKind::Adt(crate::AdtId(adt), subst).intern(Interner);
1549 make_binders(db, &generics, ty)
1550}
1551
1552pub(crate) fn type_for_type_alias_with_diagnostics_query(
1553 db: &dyn HirDatabase,
1554 t: TypeAliasId,
1555) -> (Binders<Ty>, Diagnostics) {
1556 let generics = generics(db, t.into());
1557 let type_alias_data = db.type_alias_signature(t);
1558 let mut diags = None;
1559 let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
1560 TyKind::Foreign(crate::to_foreign_def_id(t)).intern(Interner)
1561 } else {
1562 let resolver = t.resolver(db);
1563 let alias = db.type_alias_signature(t);
1564 let mut ctx = TyLoweringContext::new(
1565 db,
1566 &resolver,
1567 &alias.store,
1568 t.into(),
1569 LifetimeElisionKind::AnonymousReportError,
1570 )
1571 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1572 .with_type_param_mode(ParamLoweringMode::Variable);
1573 let res = alias
1574 .ty
1575 .map(|type_ref| ctx.lower_ty(type_ref))
1576 .unwrap_or_else(|| TyKind::Error.intern(Interner));
1577 diags = create_diagnostics(ctx.diagnostics);
1578 res
1579 };
1580
1581 (make_binders(db, &generics, inner), diags)
1582}
1583
1584pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result(
1585 db: &dyn HirDatabase,
1586 adt: TypeAliasId,
1587) -> (Binders<Ty>, Diagnostics) {
1588 let generics = generics(db, adt.into());
1589 (make_binders(db, &generics, TyKind::Error.intern(Interner)), None)
1590}
1591
1592#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1593pub enum TyDefId {
1594 BuiltinType(BuiltinType),
1595 AdtId(AdtId),
1596 TypeAliasId(TypeAliasId),
1597}
1598impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
1599
1600#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
1601pub enum ValueTyDefId {
1602 FunctionId(FunctionId),
1603 StructId(StructId),
1604 UnionId(UnionId),
1605 EnumVariantId(EnumVariantId),
1606 ConstId(ConstId),
1607 StaticId(StaticId),
1608}
1609impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
1610
1611impl ValueTyDefId {
1612 pub(crate) fn to_generic_def_id(self, db: &dyn HirDatabase) -> GenericDefId {
1613 match self {
1614 Self::FunctionId(id) => id.into(),
1615 Self::StructId(id) => id.into(),
1616 Self::UnionId(id) => id.into(),
1617 Self::EnumVariantId(var) => var.lookup(db).parent.into(),
1618 Self::ConstId(id) => id.into(),
1619 Self::StaticId(id) => id.into(),
1620 }
1621 }
1622}
1623
1624pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> {
1629 match def {
1630 TyDefId::BuiltinType(it) => Binders::empty(Interner, TyBuilder::builtin(it)),
1631 TyDefId::AdtId(it) => type_for_adt_tracked(db, it),
1632 TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics(it).0,
1633 }
1634}
1635
1636pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Option<Binders<Ty>> {
1637 match def {
1638 ValueTyDefId::FunctionId(it) => Some(type_for_fn(db, it)),
1639 ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
1640 ValueTyDefId::UnionId(it) => Some(type_for_adt(db, it.into())),
1641 ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
1642 ValueTyDefId::ConstId(it) => Some(type_for_const(db, it)),
1643 ValueTyDefId::StaticId(it) => Some(type_for_static(db, it)),
1644 }
1645}
1646
1647pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binders<Ty> {
1648 db.impl_self_ty_with_diagnostics(impl_id).0
1649}
1650
1651pub(crate) fn impl_self_ty_with_diagnostics_query(
1652 db: &dyn HirDatabase,
1653 impl_id: ImplId,
1654) -> (Binders<Ty>, Diagnostics) {
1655 let impl_data = db.impl_signature(impl_id);
1656 let resolver = impl_id.resolver(db);
1657 let generics = generics(db, impl_id.into());
1658 let mut ctx = TyLoweringContext::new(
1659 db,
1660 &resolver,
1661 &impl_data.store,
1662 impl_id.into(),
1663 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
1664 )
1665 .with_type_param_mode(ParamLoweringMode::Variable);
1666 (
1667 make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty)),
1668 create_diagnostics(ctx.diagnostics),
1669 )
1670}
1671
1672pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
1673 db: &dyn HirDatabase,
1674 impl_id: ImplId,
1675) -> (Binders<Ty>, Diagnostics) {
1676 let generics = generics(db, impl_id.into());
1677 (make_binders(db, &generics, TyKind::Error.intern(Interner)), None)
1678}
1679
1680pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
1681 db.const_param_ty_with_diagnostics(def).0
1682}
1683
1684pub(crate) fn const_param_ty_with_diagnostics_query(
1686 db: &dyn HirDatabase,
1687 def: ConstParamId,
1688) -> (Ty, Diagnostics) {
1689 let (parent_data, store) = db.generic_params_and_store(def.parent());
1690 let data = &parent_data[def.local_id()];
1691 let resolver = def.parent().resolver(db);
1692 let mut ctx = TyLoweringContext::new(
1693 db,
1694 &resolver,
1695 &store,
1696 def.parent(),
1697 LifetimeElisionKind::AnonymousReportError,
1698 );
1699 let ty = match data {
1700 TypeOrConstParamData::TypeParamData(_) => {
1701 never!();
1702 Ty::new(Interner, TyKind::Error)
1703 }
1704 TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
1705 };
1706 (ty, create_diagnostics(ctx.diagnostics))
1707}
1708
1709pub(crate) fn const_param_ty_with_diagnostics_cycle_result(
1710 _: &dyn HirDatabase,
1711 _: crate::db::HirDatabaseData,
1712 _: ConstParamId,
1713) -> (Ty, Diagnostics) {
1714 (TyKind::Error.intern(Interner), None)
1715}
1716
1717pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
1718 db.impl_trait_with_diagnostics(impl_id).map(|it| it.0)
1719}
1720
1721pub(crate) fn impl_trait_with_diagnostics_query(
1722 db: &dyn HirDatabase,
1723 impl_id: ImplId,
1724) -> Option<(Binders<TraitRef>, Diagnostics)> {
1725 let impl_data = db.impl_signature(impl_id);
1726 let resolver = impl_id.resolver(db);
1727 let mut ctx = TyLoweringContext::new(
1728 db,
1729 &resolver,
1730 &impl_data.store,
1731 impl_id.into(),
1732 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
1733 )
1734 .with_type_param_mode(ParamLoweringMode::Variable);
1735 let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
1736 let target_trait = impl_data.target_trait.as_ref()?;
1737 let trait_ref = Binders::new(binders, ctx.lower_trait_ref(target_trait, self_ty)?);
1738 Some((trait_ref, create_diagnostics(ctx.diagnostics)))
1739}
1740
1741pub(crate) fn return_type_impl_traits(
1742 db: &dyn HirDatabase,
1743 def: hir_def::FunctionId,
1744) -> Option<Arc<Binders<ImplTraits>>> {
1745 let data = db.function_signature(def);
1747 let resolver = def.resolver(db);
1748 let mut ctx_ret =
1749 TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer)
1750 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1751 .with_type_param_mode(ParamLoweringMode::Variable);
1752 if let Some(ret_type) = data.ret_type {
1753 let _ret = ctx_ret.lower_ty(ret_type);
1754 }
1755 let generics = generics(db, def.into());
1756 let return_type_impl_traits =
1757 ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data };
1758 if return_type_impl_traits.impl_traits.is_empty() {
1759 None
1760 } else {
1761 Some(Arc::new(make_binders(db, &generics, return_type_impl_traits)))
1762 }
1763}
1764
1765pub(crate) fn type_alias_impl_traits(
1766 db: &dyn HirDatabase,
1767 def: hir_def::TypeAliasId,
1768) -> Option<Arc<Binders<ImplTraits>>> {
1769 let data = db.type_alias_signature(def);
1770 let resolver = def.resolver(db);
1771 let mut ctx = TyLoweringContext::new(
1772 db,
1773 &resolver,
1774 &data.store,
1775 def.into(),
1776 LifetimeElisionKind::AnonymousReportError,
1777 )
1778 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1779 .with_type_param_mode(ParamLoweringMode::Variable);
1780 if let Some(type_ref) = data.ty {
1781 let _ty = ctx.lower_ty(type_ref);
1782 }
1783 let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data };
1784 if type_alias_impl_traits.impl_traits.is_empty() {
1785 None
1786 } else {
1787 let generics = generics(db, def.into());
1788 Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits)))
1789 }
1790}
1791
1792pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
1793 match m {
1794 hir_def::type_ref::Mutability::Shared => Mutability::Not,
1795 hir_def::type_ref::Mutability::Mut => Mutability::Mut,
1796 }
1797}
1798
1799fn fallback_bound_vars<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
1803 s: T,
1804 param_index: usize,
1805) -> T {
1806 let is_allowed = |index| (0..param_index).contains(&index);
1807
1808 crate::fold_free_vars(
1809 s,
1810 |bound, binders| {
1811 if bound.index_if_innermost().is_none_or(is_allowed) {
1812 bound.shifted_in_from(binders).to_ty(Interner)
1813 } else {
1814 TyKind::Error.intern(Interner)
1815 }
1816 },
1817 |ty, bound, binders| {
1818 if bound.index_if_innermost().is_none_or(is_allowed) {
1819 bound.shifted_in_from(binders).to_const(Interner, ty)
1820 } else {
1821 unknown_const(ty)
1822 }
1823 },
1824 )
1825}