1#![allow(unused)]
9pub(crate) mod path;
11
12use std::{
13 cell::OnceCell,
14 iter, mem,
15 ops::{self, Deref, Not as _},
16};
17
18use base_db::Crate;
19use either::Either;
20use hir_def::{
21 AdtId, AssocItemId, CallableDefId, ConstParamId, EnumVariantId, FunctionId, GenericDefId,
22 GenericParamId, ImplId, ItemContainerId, LocalFieldId, Lookup, StructId, TraitId, TypeAliasId,
23 TypeOrConstParamId, VariantId,
24 expr_store::{
25 ExpressionStore,
26 path::{GenericArg, Path},
27 },
28 hir::generics::{TypeOrConstParamData, WherePredicate},
29 lang_item::LangItem,
30 resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
31 signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
32 type_ref::{
33 ConstRef, LifetimeRefId, LiteralConstRef, PathId, TraitBoundModifier,
34 TraitRef as HirTraitRef, TypeBound, TypeRef, TypeRefId,
35 },
36};
37use hir_expand::name::Name;
38use intern::sym;
39use la_arena::{Arena, ArenaMap, Idx};
40use path::{PathDiagnosticCallback, PathLoweringContext, builtin};
41use rustc_ast_ir::Mutability;
42use rustc_hash::FxHashSet;
43use rustc_pattern_analysis::Captures;
44use rustc_type_ir::{
45 AliasTyKind, ConstKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection,
46 ExistentialTraitRef, FnSig, OutlivesPredicate,
47 TyKind::{self},
48 TypeVisitableExt,
49 inherent::{GenericArg as _, GenericArgs as _, IntoKind as _, Region as _, SliceLike, Ty as _},
50};
51use salsa::plumbing::AsId;
52use smallvec::{SmallVec, smallvec};
53use stdx::never;
54use triomphe::Arc;
55
56use crate::{
57 FnAbi, ImplTraitId, Interner, ParamKind, TyDefId, TyLoweringDiagnostic,
58 TyLoweringDiagnosticKind,
59 consteval_nextsolver::{intern_const_ref, path_to_const, unknown_const_as_generic},
60 db::HirDatabase,
61 generics::{Generics, generics, trait_self_param_idx},
62 lower::{Diagnostics, PathDiagnosticCallbackData, create_diagnostics},
63 next_solver::{
64 AdtDef, AliasTy, Binder, BoundExistentialPredicates, BoundRegionKind, BoundTyKind,
65 BoundVarKind, BoundVarKinds, Clause, Clauses, Const, DbInterner, EarlyBinder,
66 EarlyParamRegion, ErrorGuaranteed, GenericArgs, PolyFnSig, Predicate, Region, SolverDefId,
67 TraitPredicate, TraitRef, Ty, Tys, abi::Safety, mapping::ChalkToNextSolver,
68 },
69};
70
71#[derive(PartialEq, Eq, Debug, Hash)]
72pub struct ImplTraits<'db> {
73 pub(crate) impl_traits: Arena<ImplTrait<'db>>,
74}
75
76#[derive(PartialEq, Eq, Debug, Hash)]
77pub(crate) struct ImplTrait<'db> {
78 pub(crate) predicates: Vec<Clause<'db>>,
79}
80
81pub(crate) type ImplTraitIdx<'db> = Idx<ImplTrait<'db>>;
82
83#[derive(Debug, Default)]
84struct ImplTraitLoweringState<'db> {
85 mode: ImplTraitLoweringMode,
89 opaque_type_data: Arena<ImplTrait<'db>>,
91 param_and_variable_counter: u16,
92}
93impl<'db> ImplTraitLoweringState<'db> {
94 fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState<'db> {
95 Self { mode, opaque_type_data: Arena::new(), param_and_variable_counter: 0 }
96 }
97}
98
99#[derive(Debug, Clone)]
100pub(crate) enum LifetimeElisionKind<'db> {
101 AnonymousCreateParameter { report_in_path: bool },
116
117 Elided(Region<'db>),
119
120 AnonymousReportError,
124
125 StaticIfNoLifetimeInScope { only_lint: bool },
129
130 ElisionFailure,
132
133 Infer,
135}
136
137impl<'db> LifetimeElisionKind<'db> {
138 #[inline]
139 pub(crate) fn for_const(
140 interner: DbInterner<'db>,
141 const_parent: ItemContainerId,
142 ) -> LifetimeElisionKind<'db> {
143 match const_parent {
144 ItemContainerId::ExternBlockId(_) | ItemContainerId::ModuleId(_) => {
145 LifetimeElisionKind::Elided(Region::new_static(interner))
146 }
147 ItemContainerId::ImplId(_) => {
148 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: true }
149 }
150 ItemContainerId::TraitId(_) => {
151 LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: false }
152 }
153 }
154 }
155
156 #[inline]
157 pub(crate) fn for_fn_params(data: &FunctionSignature) -> LifetimeElisionKind<'db> {
158 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: data.is_async() }
159 }
160
161 #[inline]
162 pub(crate) fn for_fn_ret(interner: DbInterner<'db>) -> LifetimeElisionKind<'db> {
163 LifetimeElisionKind::Elided(Region::error(interner))
165 }
166}
167
168#[derive(Debug)]
169pub(crate) struct TyLoweringContext<'db, 'a> {
170 pub db: &'db dyn HirDatabase,
171 interner: DbInterner<'db>,
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}
183
184impl<'db, 'a> TyLoweringContext<'db, 'a> {
185 pub(crate) fn new(
186 db: &'db dyn HirDatabase,
187 resolver: &'a Resolver<'db>,
188 store: &'a ExpressionStore,
189 def: GenericDefId,
190 lifetime_elision: LifetimeElisionKind<'db>,
191 ) -> Self {
192 let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
193 let in_binders = DebruijnIndex::ZERO;
194 Self {
195 db,
196 interner: DbInterner::new_with(db, Some(resolver.krate()), None),
197 resolver,
198 def,
199 generics: Default::default(),
200 store,
201 in_binders,
202 impl_trait_mode,
203 unsized_types: FxHashSet::default(),
204 diagnostics: Vec::new(),
205 lifetime_elision,
206 }
207 }
208
209 pub(crate) fn with_debruijn<T>(
210 &mut self,
211 debruijn: DebruijnIndex,
212 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
213 ) -> T {
214 let old_debruijn = mem::replace(&mut self.in_binders, debruijn);
215 let result = f(self);
216 self.in_binders = old_debruijn;
217 result
218 }
219
220 pub(crate) fn with_shifted_in<T>(
221 &mut self,
222 debruijn: DebruijnIndex,
223 f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> T,
224 ) -> T {
225 self.with_debruijn(self.in_binders.shifted_in(debruijn.as_u32()), f)
226 }
227
228 pub(crate) 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(crate) fn impl_trait_mode(&mut self, impl_trait_mode: ImplTraitLoweringMode) -> &mut Self {
233 self.impl_trait_mode = ImplTraitLoweringState::new(impl_trait_mode);
234 self
235 }
236
237 pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
238 self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind });
239 }
240}
241
242#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
243pub(crate) enum ImplTraitLoweringMode {
244 Opaque,
249 #[default]
251 Disallowed,
252}
253
254impl<'db, 'a> TyLoweringContext<'db, 'a> {
255 pub(crate) fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
256 self.lower_ty_ext(type_ref).0
257 }
258
259 pub(crate) fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty<'db>) -> Const<'db> {
260 let const_ref = &self.store[const_ref.expr];
261 match const_ref {
262 hir_def::hir::Expr::Path(path) => {
263 path_to_const(self.db, self.resolver, path, || self.generics(), const_type)
264 .unwrap_or_else(|| unknown_const(const_type))
265 }
266 hir_def::hir::Expr::Literal(literal) => intern_const_ref(
267 self.db,
268 &match *literal {
269 hir_def::hir::Literal::Float(_, _)
270 | hir_def::hir::Literal::String(_)
271 | hir_def::hir::Literal::ByteString(_)
272 | hir_def::hir::Literal::CString(_) => LiteralConstRef::Unknown,
273 hir_def::hir::Literal::Char(c) => LiteralConstRef::Char(c),
274 hir_def::hir::Literal::Bool(b) => LiteralConstRef::Bool(b),
275 hir_def::hir::Literal::Int(val, _) => LiteralConstRef::Int(val),
276 hir_def::hir::Literal::Uint(val, _) => LiteralConstRef::UInt(val),
277 },
278 const_type,
279 self.resolver.krate(),
280 ),
281 _ => unknown_const(const_type),
282 }
283 }
284
285 pub(crate) fn lower_path_as_const(&mut self, path: &Path, const_type: Ty<'db>) -> Const<'db> {
286 path_to_const(self.db, self.resolver, path, || self.generics(), const_type)
287 .unwrap_or_else(|| unknown_const(const_type))
288 }
289
290 fn generics(&self) -> &Generics {
291 self.generics.get_or_init(|| generics(self.db, self.def))
292 }
293
294 #[tracing::instrument(skip(self), ret)]
295 pub(crate) fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty<'db>, Option<TypeNs>) {
296 let interner = self.interner;
297 let mut res = None;
298 let type_ref = &self.store[type_ref_id];
299 tracing::debug!(?type_ref);
300 let ty = match type_ref {
301 TypeRef::Never => Ty::new(interner, TyKind::Never),
302 TypeRef::Tuple(inner) => {
303 let inner_tys = inner.iter().map(|&tr| self.lower_ty(tr));
304 Ty::new_tup_from_iter(interner, inner_tys)
305 }
306 TypeRef::Path(path) => {
307 let (ty, res_) =
308 self.lower_path(path, PathId::from_type_ref_unchecked(type_ref_id));
309 res = res_;
310 ty
311 }
312 &TypeRef::TypeParam(type_param_id) => {
313 res = Some(TypeNs::GenericParam(type_param_id));
314
315 let generics = self.generics();
316 let (idx, data) =
317 generics.type_or_const_param(type_param_id.into()).expect("matching generics");
318 let type_data = match data {
319 TypeOrConstParamData::TypeParamData(ty) => ty,
320 _ => unreachable!(),
321 };
322 Ty::new_param(
323 self.interner,
324 type_param_id,
325 idx as u32,
326 type_data
327 .name
328 .as_ref()
329 .map_or_else(|| sym::MISSING_NAME.clone(), |d| d.symbol().clone()),
330 )
331 }
332 &TypeRef::RawPtr(inner, mutability) => {
333 let inner_ty = self.lower_ty(inner);
334 Ty::new(interner, TyKind::RawPtr(inner_ty, lower_mutability(mutability)))
335 }
336 TypeRef::Array(array) => {
337 let inner_ty = self.lower_ty(array.ty);
338 let const_len = self.lower_const(&array.len, Ty::new_usize(interner));
339 Ty::new_array_with_const_len(interner, inner_ty, const_len)
340 }
341 &TypeRef::Slice(inner) => {
342 let inner_ty = self.lower_ty(inner);
343 Ty::new_slice(interner, inner_ty)
344 }
345 TypeRef::Reference(ref_) => {
346 let inner_ty = self.lower_ty(ref_.ty);
347 let lifetime = ref_
349 .lifetime
350 .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr));
351 Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability))
352 }
353 TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed),
354 TypeRef::Fn(fn_) => {
355 let substs = self.with_shifted_in(
356 DebruijnIndex::from_u32(1),
357 |ctx: &mut TyLoweringContext<'_, '_>| {
358 Tys::new_from_iter(
359 interner,
360 fn_.params.iter().map(|&(_, tr)| ctx.lower_ty(tr)),
361 )
362 },
363 );
364 Ty::new_fn_ptr(
365 interner,
366 Binder::dummy(FnSig {
367 abi: fn_.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
368 safety: if fn_.is_unsafe { Safety::Unsafe } else { Safety::Safe },
369 c_variadic: fn_.is_varargs,
370 inputs_and_output: substs,
371 }),
372 )
373 }
374 TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
375 TypeRef::ImplTrait(bounds) => {
376 match self.impl_trait_mode.mode {
377 ImplTraitLoweringMode::Opaque => {
378 let origin = match self.resolver.generic_def() {
379 Some(GenericDefId::FunctionId(it)) => Either::Left(it),
380 Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
381 _ => panic!(
382 "opaque impl trait lowering must be in function or type alias"
383 ),
384 };
385
386 let idx = self
390 .impl_trait_mode
391 .opaque_type_data
392 .alloc(ImplTrait { predicates: Vec::default() });
393
394 let impl_trait_id = origin.either(
396 |f| ImplTraitId::ReturnTypeImplTrait(f, Idx::from_raw(idx.into_raw())),
397 |a| ImplTraitId::TypeAliasImplTrait(a, Idx::from_raw(idx.into_raw())),
398 );
399 let opaque_ty_id: SolverDefId =
400 self.db.intern_impl_trait_id(impl_trait_id).into();
401
402 let actual_opaque_type_data = self
412 .with_debruijn(DebruijnIndex::ZERO, |ctx| {
413 ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate())
414 });
415 self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
416
417 let args = GenericArgs::identity_for_item(self.interner, opaque_ty_id);
418 Ty::new_alias(
419 self.interner,
420 AliasTyKind::Opaque,
421 AliasTy::new_from_args(self.interner, opaque_ty_id, args),
422 )
423 }
424 ImplTraitLoweringMode::Disallowed => {
425 Ty::new_error(self.interner, ErrorGuaranteed)
427 }
428 }
429 }
430 TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed),
431 };
432 (ty, res)
433 }
434
435 fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option<TypeOrConstParamId> {
439 let type_ref = &self.store[type_ref];
440 let path = match type_ref {
441 TypeRef::Path(path) => path,
442 &TypeRef::TypeParam(idx) => return Some(idx.into()),
443 _ => return None,
444 };
445 if path.type_anchor().is_some() {
446 return None;
447 }
448 if path.segments().len() > 1 {
449 return None;
450 }
451 let resolution = match self.resolver.resolve_path_in_type_ns(self.db, path) {
452 Some((it, None, _)) => it,
453 _ => return None,
454 };
455 match resolution {
456 TypeNs::GenericParam(param_id) => Some(param_id.into()),
457 _ => None,
458 }
459 }
460
461 #[inline]
462 fn on_path_diagnostic_callback(type_ref: TypeRefId) -> PathDiagnosticCallback<'static, 'db> {
463 PathDiagnosticCallback {
464 data: Either::Left(PathDiagnosticCallbackData(type_ref)),
465 callback: |data, this, diag| {
466 let type_ref = data.as_ref().left().unwrap().0;
467 this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag))
468 },
469 }
470 }
471
472 #[inline]
473 fn at_path(&mut self, path_id: PathId) -> PathLoweringContext<'_, 'a, 'db> {
474 PathLoweringContext::new(
475 self,
476 Self::on_path_diagnostic_callback(path_id.type_ref()),
477 &self.store[path_id],
478 )
479 }
480
481 pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty<'db>, Option<TypeNs>) {
482 if let Some(type_ref) = path.type_anchor() {
484 let (ty, res) = self.lower_ty_ext(type_ref);
485 let mut ctx = self.at_path(path_id);
486 return ctx.lower_ty_relative_path(ty, res);
487 }
488
489 let mut ctx = self.at_path(path_id);
490 let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() {
491 Some(it) => it,
492 None => return (Ty::new_error(self.interner, ErrorGuaranteed), None),
493 };
494
495 if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
496 let bound = TypeBound::Path(path_id, TraitBoundModifier::None);
498 let ty = self.lower_dyn_trait(&[bound]);
499 return (ty, None);
500 }
501
502 ctx.lower_partly_resolved_path(resolution, false)
503 }
504
505 fn lower_trait_ref_from_path(
506 &mut self,
507 path_id: PathId,
508 explicit_self_ty: Ty<'db>,
509 ) -> Option<(TraitRef<'db>, PathLoweringContext<'_, 'a, 'db>)> {
510 let mut ctx = self.at_path(path_id);
511 let resolved = match ctx.resolve_path_in_type_ns_fully()? {
512 TypeNs::TraitId(tr) => tr,
514 _ => return None,
515 };
516 Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty), ctx))
517 }
518
519 fn lower_trait_ref(
520 &mut self,
521 trait_ref: &HirTraitRef,
522 explicit_self_ty: Ty<'db>,
523 ) -> Option<TraitRef<'db>> {
524 self.lower_trait_ref_from_path(trait_ref.path, explicit_self_ty).map(|it| it.0)
525 }
526
527 pub(crate) fn lower_where_predicate<'b>(
528 &'b mut self,
529 where_predicate: &'b WherePredicate,
530 ignore_bindings: bool,
531 generics: &Generics,
532 predicate_filter: PredicateFilter,
533 ) -> impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'db> {
534 match where_predicate {
535 WherePredicate::ForLifetime { target, bound, .. }
536 | WherePredicate::TypeBound { target, bound } => {
537 if let PredicateFilter::SelfTrait = predicate_filter {
538 let target_type = &self.store[*target];
539 let self_type = 'is_self: {
540 if let TypeRef::Path(path) = target_type
541 && path.is_self_type()
542 {
543 break 'is_self true;
544 }
545 if let TypeRef::TypeParam(param) = target_type
546 && generics[param.local_id()].is_trait_self()
547 {
548 break 'is_self true;
549 }
550 false
551 };
552 if !self_type {
553 return Either::Left(Either::Left(iter::empty()));
554 }
555 }
556 let self_ty = self.lower_ty(*target);
557 Either::Left(Either::Right(self.lower_type_bound(bound, self_ty, ignore_bindings)))
558 }
559 &WherePredicate::Lifetime { bound, target } => {
560 Either::Right(iter::once(Clause(Predicate::new(
561 self.interner,
562 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
563 rustc_type_ir::ClauseKind::RegionOutlives(OutlivesPredicate(
564 self.lower_lifetime(bound),
565 self.lower_lifetime(target),
566 )),
567 )),
568 ))))
569 }
570 }
571 .into_iter()
572 }
573
574 pub(crate) fn lower_type_bound<'b>(
575 &'b mut self,
576 bound: &'b TypeBound,
577 self_ty: Ty<'db>,
578 ignore_bindings: bool,
579 ) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> {
580 let interner = self.interner;
581 let mut assoc_bounds = None;
582 let mut clause = None;
583 match bound {
584 &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
585 if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
587 let meta_sized = LangItem::MetaSized
590 .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
591 let pointee_sized = LangItem::PointeeSized
592 .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
593 if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) {
594 } else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) {
596 ctx.ty_ctx().unsized_types.insert(self_ty);
598 } else {
599 if !ignore_bindings {
600 assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref);
601 }
602 clause = Some(Clause(Predicate::new(
603 interner,
604 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
605 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
606 trait_ref,
607 polarity: rustc_type_ir::PredicatePolarity::Positive,
608 }),
609 )),
610 )));
611 }
612 }
613 }
614 &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
615 let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
616 let trait_id = self
620 .lower_trait_ref_from_path(path, self_ty)
621 .map(|(trait_ref, _)| trait_ref.def_id.0);
622 if trait_id == sized_trait {
623 self.unsized_types.insert(self_ty);
624 }
625 }
626 &TypeBound::Lifetime(l) => {
627 let lifetime = self.lower_lifetime(l);
628 clause = Some(Clause(Predicate::new(
629 self.interner,
630 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
631 rustc_type_ir::ClauseKind::TypeOutlives(OutlivesPredicate(
632 self_ty, lifetime,
633 )),
634 )),
635 )));
636 }
637 TypeBound::Use(_) | TypeBound::Error => {}
638 }
639 clause.into_iter().chain(assoc_bounds.into_iter().flatten())
640 }
641
642 fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> {
643 let interner = self.interner;
644 let self_ty = Ty::new_error(interner, ErrorGuaranteed);
647 let mut lifetime = None;
653 let bounds = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
654 let mut lowered_bounds: Vec<
655 rustc_type_ir::Binder<DbInterner<'db>, ExistentialPredicate<DbInterner<'db>>>,
656 > = Vec::new();
657 for b in bounds {
658 let db = ctx.db;
659 ctx.lower_type_bound(b, self_ty, false).for_each(|b| {
660 if let Some(bound) = b
661 .kind()
662 .map_bound(|c| match c {
663 rustc_type_ir::ClauseKind::Trait(t) => {
664 let id = t.def_id();
665 let is_auto =
666 db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
667 if is_auto {
668 Some(ExistentialPredicate::AutoTrait(t.def_id()))
669 } else {
670 Some(ExistentialPredicate::Trait(
671 ExistentialTraitRef::new_from_args(
672 interner,
673 t.def_id(),
674 GenericArgs::new_from_iter(
675 interner,
676 t.trait_ref.args.iter().skip(1),
677 ),
678 ),
679 ))
680 }
681 }
682 rustc_type_ir::ClauseKind::Projection(p) => {
683 Some(ExistentialPredicate::Projection(
684 ExistentialProjection::new_from_args(
685 interner,
686 p.def_id(),
687 GenericArgs::new_from_iter(
688 interner,
689 p.projection_term.args.iter().skip(1),
690 ),
691 p.term,
692 ),
693 ))
694 }
695 rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => {
696 lifetime = Some(outlives_predicate.1);
697 None
698 }
699 rustc_type_ir::ClauseKind::RegionOutlives(_)
700 | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
701 | rustc_type_ir::ClauseKind::WellFormed(_)
702 | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
703 | rustc_type_ir::ClauseKind::HostEffect(_)
704 | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
705 })
706 .transpose()
707 {
708 lowered_bounds.push(bound);
709 }
710 })
711 }
712
713 let mut multiple_regular_traits = false;
714 let mut multiple_same_projection = false;
715 lowered_bounds.sort_unstable_by(|lhs, rhs| {
716 use std::cmp::Ordering;
717 match ((*lhs).skip_binder(), (*rhs).skip_binder()) {
718 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => {
719 multiple_regular_traits = true;
720 Ordering::Equal
722 }
723 (
724 ExistentialPredicate::AutoTrait(lhs_id),
725 ExistentialPredicate::AutoTrait(rhs_id),
726 ) => lhs_id.0.cmp(&rhs_id.0),
727 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
728 (_, ExistentialPredicate::Trait(_)) => Ordering::Greater,
729 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Less,
730 (_, ExistentialPredicate::AutoTrait(_)) => Ordering::Greater,
731 (
732 ExistentialPredicate::Projection(lhs),
733 ExistentialPredicate::Projection(rhs),
734 ) => {
735 let lhs_id = match lhs.def_id {
736 SolverDefId::TypeAliasId(id) => id,
737 _ => unreachable!(),
738 };
739 let rhs_id = match rhs.def_id {
740 SolverDefId::TypeAliasId(id) => id,
741 _ => unreachable!(),
742 };
743 if lhs_id == rhs_id {
747 multiple_same_projection = true;
748 }
749 lhs_id.as_id().index().cmp(&rhs_id.as_id().index())
750 }
751 }
752 });
753
754 if multiple_regular_traits || multiple_same_projection {
755 return None;
756 }
757
758 if !lowered_bounds.first().map_or(false, |b| {
759 matches!(
760 b.as_ref().skip_binder(),
761 ExistentialPredicate::Trait(_) | ExistentialPredicate::AutoTrait(_)
762 )
763 }) {
764 return None;
765 }
766
767 lowered_bounds.dedup();
770
771 Some(BoundExistentialPredicates::new_from_iter(interner, lowered_bounds))
772 });
773
774 if let Some(bounds) = bounds {
775 let region = match lifetime {
776 Some(it) => match it.kind() {
777 rustc_type_ir::RegionKind::ReBound(db, var) => Region::new_bound(
778 self.interner,
779 db.shifted_out_to_binder(DebruijnIndex::from_u32(2)),
780 var,
781 ),
782 _ => it,
783 },
784 None => Region::new_static(self.interner),
785 };
786 Ty::new_dynamic(self.interner, bounds, region, rustc_type_ir::DynKind::Dyn)
787 } else {
788 Ty::new_error(self.interner, ErrorGuaranteed)
791 }
792 }
793
794 fn lower_impl_trait(
795 &mut self,
796 def_id: SolverDefId,
797 bounds: &[TypeBound],
798 krate: Crate,
799 ) -> ImplTrait<'db> {
800 let interner = self.interner;
801 cov_mark::hit!(lower_rpit);
802 let args = GenericArgs::identity_for_item(interner, def_id);
803 let self_ty = Ty::new_alias(
804 self.interner,
805 rustc_type_ir::AliasTyKind::Opaque,
806 AliasTy::new_from_args(interner, def_id, args),
807 );
808 let predicates = self.with_shifted_in(DebruijnIndex::from_u32(1), |ctx| {
809 let mut predicates = Vec::new();
810 for b in bounds {
811 predicates.extend(ctx.lower_type_bound(b, self_ty, false));
812 }
813
814 if !ctx.unsized_types.contains(&self_ty) {
815 let sized_trait = LangItem::Sized.resolve_trait(self.db, krate);
816 let sized_clause = sized_trait.map(|trait_id| {
817 let trait_ref = TraitRef::new_from_args(
818 interner,
819 trait_id.into(),
820 GenericArgs::new_from_iter(interner, [self_ty.into()]),
821 );
822 Clause(Predicate::new(
823 interner,
824 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
825 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
826 trait_ref,
827 polarity: rustc_type_ir::PredicatePolarity::Positive,
828 }),
829 )),
830 ))
831 });
832 predicates.extend(sized_clause);
833 }
834 predicates.shrink_to_fit();
835 predicates
836 });
837 ImplTrait { predicates }
838 }
839
840 pub(crate) fn lower_lifetime(&self, lifetime: LifetimeRefId) -> Region<'db> {
841 match self.resolver.resolve_lifetime(&self.store[lifetime]) {
842 Some(resolution) => match resolution {
843 LifetimeNs::Static => Region::new_static(self.interner),
844 LifetimeNs::LifetimeParam(id) => {
845 let idx = match self.generics().lifetime_idx(id) {
846 None => return Region::error(self.interner),
847 Some(idx) => idx,
848 };
849 Region::new_early_param(
850 self.interner,
851 EarlyParamRegion { index: idx as u32, id },
852 )
853 }
854 },
855 None => Region::error(self.interner),
856 }
857 }
858}
859
860pub(crate) fn lower_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
861 match m {
862 hir_def::type_ref::Mutability::Shared => Mutability::Not,
863 hir_def::type_ref::Mutability::Mut => Mutability::Mut,
864 }
865}
866
867fn unknown_const(_ty: Ty<'_>) -> Const<'_> {
868 Const::new(DbInterner::conjure(), ConstKind::Error(ErrorGuaranteed))
869}
870
871pub(crate) fn impl_trait_query<'db>(
872 db: &'db dyn HirDatabase,
873 impl_id: ImplId,
874) -> Option<EarlyBinder<'db, TraitRef<'db>>> {
875 db.impl_trait_with_diagnostics_ns(impl_id).map(|it| it.0)
876}
877
878pub(crate) fn impl_trait_with_diagnostics_query<'db>(
879 db: &'db dyn HirDatabase,
880 impl_id: ImplId,
881) -> Option<(EarlyBinder<'db, TraitRef<'db>>, Diagnostics)> {
882 let impl_data = db.impl_signature(impl_id);
883 let resolver = impl_id.resolver(db);
884 let mut ctx = TyLoweringContext::new(
885 db,
886 &resolver,
887 &impl_data.store,
888 impl_id.into(),
889 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
890 );
891 let self_ty = db.impl_self_ty_ns(impl_id).skip_binder();
892 let target_trait = impl_data.target_trait.as_ref()?;
893 let trait_ref = EarlyBinder::bind(ctx.lower_trait_ref(target_trait, self_ty)?);
894 Some((trait_ref, create_diagnostics(ctx.diagnostics)))
895}
896
897pub(crate) fn return_type_impl_traits<'db>(
898 db: &'db dyn HirDatabase,
899 def: hir_def::FunctionId,
900) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> {
901 let data = db.function_signature(def);
903 let resolver = def.resolver(db);
904 let mut ctx_ret =
905 TyLoweringContext::new(db, &resolver, &data.store, def.into(), LifetimeElisionKind::Infer)
906 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
907 if let Some(ret_type) = data.ret_type {
908 let _ret = ctx_ret.lower_ty(ret_type);
909 }
910 let return_type_impl_traits =
911 ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data };
912 if return_type_impl_traits.impl_traits.is_empty() {
913 None
914 } else {
915 Some(Arc::new(EarlyBinder::bind(return_type_impl_traits)))
916 }
917}
918
919pub(crate) fn type_alias_impl_traits<'db>(
920 db: &'db dyn HirDatabase,
921 def: hir_def::TypeAliasId,
922) -> Option<Arc<EarlyBinder<'db, ImplTraits<'db>>>> {
923 let data = db.type_alias_signature(def);
924 let resolver = def.resolver(db);
925 let mut ctx = TyLoweringContext::new(
926 db,
927 &resolver,
928 &data.store,
929 def.into(),
930 LifetimeElisionKind::AnonymousReportError,
931 )
932 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
933 if let Some(type_ref) = data.ty {
934 let _ty = ctx.lower_ty(type_ref);
935 }
936 let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data };
937 if type_alias_impl_traits.impl_traits.is_empty() {
938 None
939 } else {
940 Some(Arc::new(EarlyBinder::bind(type_alias_impl_traits)))
941 }
942}
943
944pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> {
949 let interner = DbInterner::new_with(db, None, None);
950 match def {
951 TyDefId::BuiltinType(it) => EarlyBinder::bind(builtin(interner, it)),
952 TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt(
953 interner,
954 AdtDef::new(it, interner),
955 GenericArgs::identity_for_item(interner, it.into()),
956 )),
957 TyDefId::TypeAliasId(it) => db.type_for_type_alias_with_diagnostics_ns(it).0,
958 }
959}
960
961pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>(
962 db: &'db dyn HirDatabase,
963 t: TypeAliasId,
964) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
965 let type_alias_data = db.type_alias_signature(t);
966 let mut diags = None;
967 let resolver = t.resolver(db);
968 let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
969 let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
970 EarlyBinder::bind(Ty::new_foreign(interner, t.into()))
971 } else {
972 let mut ctx = TyLoweringContext::new(
973 db,
974 &resolver,
975 &type_alias_data.store,
976 t.into(),
977 LifetimeElisionKind::AnonymousReportError,
978 )
979 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
980 let res = EarlyBinder::bind(
981 type_alias_data
982 .ty
983 .map(|type_ref| ctx.lower_ty(type_ref))
984 .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed)),
985 );
986 diags = create_diagnostics(ctx.diagnostics);
987 res
988 };
989 (inner, diags)
990}
991
992pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>(
993 db: &'db dyn HirDatabase,
994 _adt: TypeAliasId,
995) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
996 (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None)
997}
998
999pub(crate) fn impl_self_ty_query<'db>(
1000 db: &'db dyn HirDatabase,
1001 impl_id: ImplId,
1002) -> EarlyBinder<'db, Ty<'db>> {
1003 db.impl_self_ty_with_diagnostics_ns(impl_id).0
1004}
1005
1006pub(crate) fn impl_self_ty_with_diagnostics_query<'db>(
1007 db: &'db dyn HirDatabase,
1008 impl_id: ImplId,
1009) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) {
1010 let resolver = impl_id.resolver(db);
1011 let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
1012
1013 let impl_data = db.impl_signature(impl_id);
1014 let mut ctx = TyLoweringContext::new(
1015 db,
1016 &resolver,
1017 &impl_data.store,
1018 impl_id.into(),
1019 LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
1020 );
1021 let ty = ctx.lower_ty(impl_data.self_ty);
1022 assert!(!ty.has_escaping_bound_vars());
1023 (EarlyBinder::bind(ty), create_diagnostics(ctx.diagnostics))
1024}
1025
1026pub(crate) fn impl_self_ty_with_diagnostics_cycle_result(
1027 db: &dyn HirDatabase,
1028 _impl_id: ImplId,
1029) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) {
1030 (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None)
1031}
1032
1033pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> {
1034 db.const_param_ty_with_diagnostics_ns(def).0
1035}
1036
1037pub(crate) fn const_param_ty_with_diagnostics_query<'db>(
1039 db: &'db dyn HirDatabase,
1040 def: ConstParamId,
1041) -> (Ty<'db>, Diagnostics) {
1042 let (parent_data, store) = db.generic_params_and_store(def.parent());
1043 let data = &parent_data[def.local_id()];
1044 let resolver = def.parent().resolver(db);
1045 let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
1046 let mut ctx = TyLoweringContext::new(
1047 db,
1048 &resolver,
1049 &store,
1050 def.parent(),
1051 LifetimeElisionKind::AnonymousReportError,
1052 );
1053 let ty = match data {
1054 TypeOrConstParamData::TypeParamData(_) => {
1055 never!();
1056 Ty::new_error(interner, ErrorGuaranteed)
1057 }
1058 TypeOrConstParamData::ConstParamData(d) => ctx.lower_ty(d.ty),
1059 };
1060 (ty, create_diagnostics(ctx.diagnostics))
1061}
1062
1063pub(crate) fn field_types_query<'db>(
1064 db: &'db dyn HirDatabase,
1065 variant_id: VariantId,
1066) -> Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>> {
1067 db.field_types_with_diagnostics_ns(variant_id).0
1068}
1069
1070pub(crate) fn field_types_with_diagnostics_query<'db>(
1072 db: &'db dyn HirDatabase,
1073 variant_id: VariantId,
1074) -> (Arc<ArenaMap<LocalFieldId, EarlyBinder<'db, Ty<'db>>>>, Diagnostics) {
1075 let var_data = variant_id.fields(db);
1076 let fields = var_data.fields();
1077 if fields.is_empty() {
1078 return (Arc::new(ArenaMap::default()), None);
1079 }
1080
1081 let (resolver, def): (_, GenericDefId) = match variant_id {
1082 VariantId::StructId(it) => (it.resolver(db), it.into()),
1083 VariantId::UnionId(it) => (it.resolver(db), it.into()),
1084 VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
1085 };
1086 let mut res = ArenaMap::default();
1087 let mut ctx = TyLoweringContext::new(
1088 db,
1089 &resolver,
1090 &var_data.store,
1091 def,
1092 LifetimeElisionKind::AnonymousReportError,
1093 );
1094 for (field_id, field_data) in var_data.fields().iter() {
1095 res.insert(field_id, EarlyBinder::bind(ctx.lower_ty(field_data.type_ref)));
1096 }
1097 (Arc::new(res), create_diagnostics(ctx.diagnostics))
1098}
1099
1100#[tracing::instrument(skip(db), ret)]
1109pub(crate) fn generic_predicates_for_param_query<'db>(
1110 db: &'db dyn HirDatabase,
1111 def: GenericDefId,
1112 param_id: TypeOrConstParamId,
1113 assoc_name: Option<Name>,
1114) -> GenericPredicates<'db> {
1115 let generics = generics(db, def);
1116 let interner = DbInterner::new_with(db, None, None);
1117 let resolver = def.resolver(db);
1118 let mut ctx = TyLoweringContext::new(
1119 db,
1120 &resolver,
1121 generics.store(),
1122 def,
1123 LifetimeElisionKind::AnonymousReportError,
1124 );
1125
1126 let predicate = |pred: &_, ctx: &mut TyLoweringContext<'_, '_>| match pred {
1128 WherePredicate::ForLifetime { target, bound, .. }
1129 | WherePredicate::TypeBound { target, bound, .. } => {
1130 let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
1131 if invalid_target {
1132 let lower = || -> bool {
1137 match bound {
1138 TypeBound::Path(_, TraitBoundModifier::Maybe) => true,
1139 TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
1140 let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
1141 return false;
1142 };
1143 let Some(pointee_sized) =
1144 LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate())
1145 else {
1146 return false;
1147 };
1148 ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and(
1151 |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized),
1152 )
1153 }
1154 _ => false,
1155 }
1156 }();
1157 if lower {
1158 ctx.lower_where_predicate(pred, true, &generics, PredicateFilter::All)
1159 .for_each(drop);
1160 }
1161 return false;
1162 }
1163
1164 match bound {
1165 &TypeBound::ForLifetime(_, path) | &TypeBound::Path(path, _) => {
1166 let path = &ctx.store[path];
1169
1170 let Some(assoc_name) = &assoc_name else { return true };
1171 let Some(TypeNs::TraitId(tr)) =
1172 resolver.resolve_path_in_type_ns_fully(db, path)
1173 else {
1174 return false;
1175 };
1176
1177 rustc_type_ir::elaborate::supertrait_def_ids(interner, tr.into()).any(|tr| {
1178 tr.0.trait_items(db).items.iter().any(|(name, item)| {
1179 matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
1180 })
1181 })
1182 }
1183 TypeBound::Use(_) | TypeBound::Lifetime(_) | TypeBound::Error => false,
1184 }
1185 }
1186 WherePredicate::Lifetime { .. } => false,
1187 };
1188 let mut predicates = Vec::new();
1189 for maybe_parent_generics in
1190 std::iter::successors(Some(&generics), |generics| generics.parent_generics())
1191 {
1192 ctx.store = maybe_parent_generics.store();
1193 for pred in maybe_parent_generics.where_predicates() {
1194 if predicate(pred, &mut ctx) {
1195 predicates.extend(ctx.lower_where_predicate(
1196 pred,
1197 true,
1198 maybe_parent_generics,
1199 PredicateFilter::All,
1200 ));
1201 }
1202 }
1203 }
1204
1205 let args = GenericArgs::identity_for_item(interner, def.into());
1206 if !args.is_empty() {
1207 let explicitly_unsized_tys = ctx.unsized_types;
1208 if let Some(implicitly_sized_predicates) =
1209 implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver)
1210 {
1211 predicates.extend(implicitly_sized_predicates);
1212 };
1213 }
1214 GenericPredicates(predicates.is_empty().not().then(|| predicates.into()))
1215}
1216
1217pub(crate) fn generic_predicates_for_param_cycle_result(
1218 _db: &dyn HirDatabase,
1219 _def: GenericDefId,
1220 _param_id: TypeOrConstParamId,
1221 _assoc_name: Option<Name>,
1222) -> GenericPredicates<'_> {
1223 GenericPredicates(None)
1224}
1225
1226#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1227pub struct GenericPredicates<'db>(Option<Arc<[Clause<'db>]>>);
1228
1229impl<'db> ops::Deref for GenericPredicates<'db> {
1230 type Target = [Clause<'db>];
1231
1232 fn deref(&self) -> &Self::Target {
1233 self.0.as_deref().unwrap_or(&[])
1234 }
1235}
1236
1237#[derive(Copy, Clone, Debug)]
1238pub(crate) enum PredicateFilter {
1239 SelfTrait,
1240 All,
1241}
1242
1243#[tracing::instrument(skip(db))]
1245pub(crate) fn generic_predicates_query<'db>(
1246 db: &'db dyn HirDatabase,
1247 def: GenericDefId,
1248) -> GenericPredicates<'db> {
1249 generic_predicates_filtered_by(db, def, PredicateFilter::All, |_| true).0
1250}
1251
1252pub(crate) fn generic_predicates_without_parent_query<'db>(
1253 db: &'db dyn HirDatabase,
1254 def: GenericDefId,
1255) -> GenericPredicates<'db> {
1256 generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def).0
1257}
1258
1259pub(crate) fn generic_predicates_without_parent_with_diagnostics_query<'db>(
1262 db: &'db dyn HirDatabase,
1263 def: GenericDefId,
1264) -> (GenericPredicates<'db>, Diagnostics) {
1265 generic_predicates_filtered_by(db, def, PredicateFilter::All, |d| d == def)
1266}
1267
1268#[tracing::instrument(skip(db, filter), ret)]
1271pub(crate) fn generic_predicates_filtered_by<'db, F>(
1272 db: &'db dyn HirDatabase,
1273 def: GenericDefId,
1274 predicate_filter: PredicateFilter,
1275 filter: F,
1276) -> (GenericPredicates<'db>, Diagnostics)
1277where
1278 F: Fn(GenericDefId) -> bool,
1279{
1280 let generics = generics(db, def);
1281 let resolver = def.resolver(db);
1282 let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
1283 let mut ctx = TyLoweringContext::new(
1284 db,
1285 &resolver,
1286 generics.store(),
1287 def,
1288 LifetimeElisionKind::AnonymousReportError,
1289 );
1290
1291 let mut predicates = Vec::new();
1292 for maybe_parent_generics in
1293 std::iter::successors(Some(&generics), |generics| generics.parent_generics())
1294 {
1295 ctx.store = maybe_parent_generics.store();
1296 for pred in maybe_parent_generics.where_predicates() {
1297 tracing::debug!(?pred);
1298 if filter(maybe_parent_generics.def()) {
1299 predicates.extend(ctx.lower_where_predicate(
1302 pred,
1303 false,
1304 maybe_parent_generics,
1305 predicate_filter,
1306 ));
1307 }
1308 }
1309 }
1310
1311 let explicitly_unsized_tys = ctx.unsized_types;
1312
1313 let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
1314 if let Some(sized_trait) = sized_trait {
1315 let (mut generics, mut def_id) =
1316 (crate::next_solver::generics::generics(db, def.into()), def);
1317 loop {
1318 if filter(def_id) {
1319 let self_idx = trait_self_param_idx(db, def_id);
1320 for (idx, p) in generics.own_params.iter().enumerate() {
1321 if let Some(self_idx) = self_idx
1322 && p.index() as usize == self_idx
1323 {
1324 continue;
1325 }
1326 let GenericParamId::TypeParamId(param_id) = p.id else {
1327 continue;
1328 };
1329 let idx = idx as u32 + generics.parent_count as u32;
1330 let param_ty = Ty::new_param(interner, param_id, idx, p.name.clone());
1331 if explicitly_unsized_tys.contains(¶m_ty) {
1332 continue;
1333 }
1334 let trait_ref = TraitRef::new_from_args(
1335 interner,
1336 sized_trait.into(),
1337 GenericArgs::new_from_iter(interner, [param_ty.into()]),
1338 );
1339 let clause = Clause(Predicate::new(
1340 interner,
1341 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
1342 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1343 trait_ref,
1344 polarity: rustc_type_ir::PredicatePolarity::Positive,
1345 }),
1346 )),
1347 ));
1348 predicates.push(clause);
1349 }
1350 }
1351
1352 if let Some(g) = generics.parent {
1353 generics = crate::next_solver::generics::generics(db, g.into());
1354 def_id = g;
1355 } else {
1356 break;
1357 }
1358 }
1359 }
1360
1361 (
1362 GenericPredicates(predicates.is_empty().not().then(|| predicates.into())),
1363 create_diagnostics(ctx.diagnostics),
1364 )
1365}
1366
1367fn implicitly_sized_clauses<'a, 'subst, 'db>(
1370 db: &'db dyn HirDatabase,
1371 def: GenericDefId,
1372 explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>,
1373 args: &'subst GenericArgs<'db>,
1374 resolver: &Resolver<'db>,
1375) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> {
1376 let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
1377 let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?;
1378
1379 let trait_self_idx = trait_self_param_idx(db, def);
1380
1381 Some(
1382 args.iter()
1383 .enumerate()
1384 .filter_map(
1385 move |(idx, generic_arg)| {
1386 if Some(idx) == trait_self_idx { None } else { Some(generic_arg) }
1387 },
1388 )
1389 .filter_map(|generic_arg| generic_arg.as_type())
1390 .filter(move |self_ty| !explicitly_unsized_tys.contains(self_ty))
1391 .map(move |self_ty| {
1392 let trait_ref = TraitRef::new_from_args(
1393 interner,
1394 sized_trait.into(),
1395 GenericArgs::new_from_iter(interner, [self_ty.into()]),
1396 );
1397 Clause(Predicate::new(
1398 interner,
1399 Binder::dummy(rustc_type_ir::PredicateKind::Clause(
1400 rustc_type_ir::ClauseKind::Trait(TraitPredicate {
1401 trait_ref,
1402 polarity: rustc_type_ir::PredicatePolarity::Positive,
1403 }),
1404 )),
1405 ))
1406 }),
1407 )
1408}
1409
1410pub(crate) fn make_binders<'db, T: rustc_type_ir::TypeVisitable<DbInterner<'db>>>(
1411 interner: DbInterner<'db>,
1412 generics: &Generics,
1413 value: T,
1414) -> Binder<'db, T> {
1415 Binder::bind_with_vars(
1416 value,
1417 BoundVarKinds::new_from_iter(
1418 interner,
1419 generics.iter_id().map(|x| match x {
1420 hir_def::GenericParamId::ConstParamId(_) => BoundVarKind::Const,
1421 hir_def::GenericParamId::TypeParamId(_) => BoundVarKind::Ty(BoundTyKind::Anon),
1422 hir_def::GenericParamId::LifetimeParamId(_) => {
1423 BoundVarKind::Region(BoundRegionKind::Anon)
1424 }
1425 }),
1426 ),
1427 )
1428}
1429
1430pub(crate) fn lower_generic_arg<'a, 'db, T>(
1434 db: &'db dyn HirDatabase,
1435 kind_id: GenericParamId,
1436 arg: &'a GenericArg,
1437 this: &mut T,
1438 store: &ExpressionStore,
1439 for_type: impl FnOnce(&mut T, TypeRefId) -> Ty<'db> + 'a,
1440 for_const: impl FnOnce(&mut T, &ConstRef, Ty<'db>) -> Const<'db> + 'a,
1441 for_const_ty_path_fallback: impl FnOnce(&mut T, &Path, Ty<'db>) -> Const<'db> + 'a,
1442 for_lifetime: impl FnOnce(&mut T, &LifetimeRefId) -> Region<'db> + 'a,
1443) -> crate::next_solver::GenericArg<'db> {
1444 let interner = DbInterner::new_with(db, None, None);
1445 let kind = match kind_id {
1446 GenericParamId::TypeParamId(_) => ParamKind::Type,
1447 GenericParamId::ConstParamId(id) => {
1448 let ty = db.const_param_ty(id);
1449 ParamKind::Const(ty)
1450 }
1451 GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
1452 };
1453 match (arg, kind) {
1454 (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, *type_ref).into(),
1455 (GenericArg::Const(c), ParamKind::Const(c_ty)) => {
1456 for_const(this, c, c_ty.to_nextsolver(interner)).into()
1457 }
1458 (GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
1459 for_lifetime(this, lifetime_ref).into()
1460 }
1461 (GenericArg::Const(_), ParamKind::Type) => Ty::new_error(interner, ErrorGuaranteed).into(),
1462 (GenericArg::Lifetime(_), ParamKind::Type) => {
1463 Ty::new_error(interner, ErrorGuaranteed).into()
1464 }
1465 (GenericArg::Type(t), ParamKind::Const(c_ty)) => match &store[*t] {
1466 TypeRef::Path(p) => {
1467 for_const_ty_path_fallback(this, p, c_ty.to_nextsolver(interner)).into()
1468 }
1469 _ => unknown_const_as_generic(c_ty.to_nextsolver(interner)),
1470 },
1471 (GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => {
1472 unknown_const(c_ty.to_nextsolver(interner)).into()
1473 }
1474 (GenericArg::Type(_), ParamKind::Lifetime) => Region::error(interner).into(),
1475 (GenericArg::Const(_), ParamKind::Lifetime) => Region::error(interner).into(),
1476 }
1477}
1478
1479pub(crate) fn callable_item_signature_query<'db>(
1481 db: &'db dyn HirDatabase,
1482 def: CallableDefId,
1483) -> EarlyBinder<'db, PolyFnSig<'db>> {
1484 match def {
1485 CallableDefId::FunctionId(f) => fn_sig_for_fn(db, f),
1486 CallableDefId::StructId(s) => fn_sig_for_struct_constructor(db, s),
1487 CallableDefId::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
1488 }
1489}
1490
1491fn fn_sig_for_fn<'db>(
1492 db: &'db dyn HirDatabase,
1493 def: FunctionId,
1494) -> EarlyBinder<'db, PolyFnSig<'db>> {
1495 let data = db.function_signature(def);
1496 let resolver = def.resolver(db);
1497 let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
1498 let mut ctx_params = TyLoweringContext::new(
1499 db,
1500 &resolver,
1501 &data.store,
1502 def.into(),
1503 LifetimeElisionKind::for_fn_params(&data),
1504 );
1505 let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
1506
1507 let ret = match data.ret_type {
1508 Some(ret_type) => {
1509 let mut ctx_ret = TyLoweringContext::new(
1510 db,
1511 &resolver,
1512 &data.store,
1513 def.into(),
1514 LifetimeElisionKind::for_fn_ret(interner),
1515 )
1516 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
1517 ctx_ret.lower_ty(ret_type)
1518 }
1519 None => Ty::new_tup(interner, &[]),
1520 };
1521
1522 let inputs_and_output = Tys::new_from_iter(interner, params.chain(Some(ret)));
1523 EarlyBinder::bind(rustc_type_ir::Binder::dummy(FnSig {
1525 abi: data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
1526 c_variadic: data.is_varargs(),
1527 safety: if data.is_unsafe() { Safety::Unsafe } else { Safety::Safe },
1528 inputs_and_output,
1529 }))
1530}
1531
1532fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> {
1533 let interner = DbInterner::new_with(db, None, None);
1534 let args = GenericArgs::identity_for_item(interner, adt.into());
1535 let ty = Ty::new_adt(interner, AdtDef::new(adt, interner), args);
1536 EarlyBinder::bind(ty)
1537}
1538
1539fn fn_sig_for_struct_constructor<'db>(
1540 db: &'db dyn HirDatabase,
1541 def: StructId,
1542) -> EarlyBinder<'db, PolyFnSig<'db>> {
1543 let field_tys = db.field_types_ns(def.into());
1544 let params = field_tys.iter().map(|(_, ty)| ty.skip_binder());
1545 let ret = type_for_adt(db, def.into()).skip_binder();
1546
1547 let inputs_and_output =
1548 Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret)));
1549 EarlyBinder::bind(Binder::dummy(FnSig {
1550 abi: FnAbi::RustCall,
1551 c_variadic: false,
1552 safety: Safety::Safe,
1553 inputs_and_output,
1554 }))
1555}
1556
1557fn fn_sig_for_enum_variant_constructor<'db>(
1558 db: &'db dyn HirDatabase,
1559 def: EnumVariantId,
1560) -> EarlyBinder<'db, PolyFnSig<'db>> {
1561 let field_tys = db.field_types_ns(def.into());
1562 let params = field_tys.iter().map(|(_, ty)| ty.skip_binder());
1563 let parent = def.lookup(db).parent;
1564 let ret = type_for_adt(db, parent.into()).skip_binder();
1565
1566 let inputs_and_output =
1567 Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret)));
1568 EarlyBinder::bind(Binder::dummy(FnSig {
1569 abi: FnAbi::RustCall,
1570 c_variadic: false,
1571 safety: Safety::Safe,
1572 inputs_and_output,
1573 }))
1574}
1575
1576pub(crate) fn associated_ty_item_bounds<'db>(
1578 db: &'db dyn HirDatabase,
1579 type_alias: TypeAliasId,
1580) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
1581 let trait_ = match type_alias.lookup(db).container {
1582 ItemContainerId::TraitId(t) => t,
1583 _ => panic!("associated type not in trait"),
1584 };
1585
1586 let type_alias_data = db.type_alias_signature(type_alias);
1587 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
1588 let interner = DbInterner::new_with(db, Some(resolver.krate()), None);
1589 let mut ctx = TyLoweringContext::new(
1590 db,
1591 &resolver,
1592 &type_alias_data.store,
1593 type_alias.into(),
1594 LifetimeElisionKind::AnonymousReportError,
1595 );
1596 let self_ty = Ty::new_error(interner, ErrorGuaranteed);
1599
1600 let mut bounds = Vec::new();
1601 for bound in &type_alias_data.bounds {
1602 ctx.lower_type_bound(bound, self_ty, false).for_each(|pred| {
1603 if let Some(bound) = pred
1604 .kind()
1605 .map_bound(|c| match c {
1606 rustc_type_ir::ClauseKind::Trait(t) => {
1607 let id = t.def_id();
1608 let is_auto = db.trait_signature(id.0).flags.contains(TraitFlags::AUTO);
1609 if is_auto {
1610 Some(ExistentialPredicate::AutoTrait(t.def_id()))
1611 } else {
1612 Some(ExistentialPredicate::Trait(ExistentialTraitRef::new_from_args(
1613 interner,
1614 t.def_id(),
1615 GenericArgs::new_from_iter(
1616 interner,
1617 t.trait_ref.args.iter().skip(1),
1618 ),
1619 )))
1620 }
1621 }
1622 rustc_type_ir::ClauseKind::Projection(p) => Some(
1623 ExistentialPredicate::Projection(ExistentialProjection::new_from_args(
1624 interner,
1625 p.def_id(),
1626 GenericArgs::new_from_iter(
1627 interner,
1628 p.projection_term.args.iter().skip(1),
1629 ),
1630 p.term,
1631 )),
1632 ),
1633 rustc_type_ir::ClauseKind::TypeOutlives(outlives_predicate) => None,
1634 rustc_type_ir::ClauseKind::RegionOutlives(_)
1635 | rustc_type_ir::ClauseKind::ConstArgHasType(_, _)
1636 | rustc_type_ir::ClauseKind::WellFormed(_)
1637 | rustc_type_ir::ClauseKind::ConstEvaluatable(_)
1638 | rustc_type_ir::ClauseKind::HostEffect(_)
1639 | rustc_type_ir::ClauseKind::UnstableFeature(_) => unreachable!(),
1640 })
1641 .transpose()
1642 {
1643 bounds.push(bound);
1644 }
1645 });
1646 }
1647
1648 if !ctx.unsized_types.contains(&self_ty) {
1649 let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
1650 let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new(
1651 interner,
1652 trait_.into(),
1653 [] as [crate::next_solver::GenericArg<'_>; 0],
1654 )));
1655 bounds.push(sized_clause);
1656 bounds.shrink_to_fit();
1657 }
1658
1659 EarlyBinder::bind(BoundExistentialPredicates::new_from_iter(interner, bounds))
1660}
1661
1662pub(crate) fn associated_type_by_name_including_super_traits<'db>(
1663 db: &'db dyn HirDatabase,
1664 trait_ref: TraitRef<'db>,
1665 name: &Name,
1666) -> Option<(TraitRef<'db>, TypeAliasId)> {
1667 let interner = DbInterner::new_with(db, None, None);
1668 rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| {
1669 let trait_id = t.as_ref().skip_binder().def_id.0;
1670 let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?;
1671 Some((t.skip_binder(), assoc_type))
1672 })
1673}
1674
1675pub fn associated_type_shorthand_candidates(
1676 db: &dyn HirDatabase,
1677 def: GenericDefId,
1678 res: TypeNs,
1679 mut cb: impl FnMut(&Name, TypeAliasId) -> bool,
1680) -> Option<TypeAliasId> {
1681 let interner = DbInterner::new_with(db, None, None);
1682 named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| {
1683 cb(name, id).then_some(id)
1684 })
1685}
1686
1687#[tracing::instrument(skip(interner, check_alias))]
1688fn named_associated_type_shorthand_candidates<'db, R>(
1689 interner: DbInterner<'db>,
1690 def: GenericDefId,
1693 res: TypeNs,
1694 assoc_name: Option<Name>,
1695 mut check_alias: impl FnMut(&Name, TraitRef<'db>, TypeAliasId) -> Option<R>,
1696) -> Option<R> {
1697 let db = interner.db;
1698 let mut search = |t: TraitRef<'db>| -> Option<R> {
1699 let trait_id = t.def_id.0;
1700 let mut checked_traits = FxHashSet::default();
1701 let mut check_trait = |trait_id: TraitId| {
1702 let name = &db.trait_signature(trait_id).name;
1703 tracing::debug!(?trait_id, ?name);
1704 if !checked_traits.insert(trait_id) {
1705 return None;
1706 }
1707 let data = trait_id.trait_items(db);
1708
1709 tracing::debug!(?data.items);
1710 for (name, assoc_id) in &data.items {
1711 if let &AssocItemId::TypeAliasId(alias) = assoc_id
1712 && let Some(ty) = check_alias(name, t, alias)
1713 {
1714 return Some(ty);
1715 }
1716 }
1717 None
1718 };
1719 let mut stack: SmallVec<[_; 4]> = smallvec![trait_id];
1720 while let Some(trait_def_id) = stack.pop() {
1721 if let Some(alias) = check_trait(trait_def_id) {
1722 return Some(alias);
1723 }
1724 for pred in generic_predicates_filtered_by(
1725 db,
1726 GenericDefId::TraitId(trait_def_id),
1727 PredicateFilter::SelfTrait,
1728 |pred| pred != def && pred == GenericDefId::TraitId(trait_def_id),
1733 )
1734 .0
1735 .deref()
1736 {
1737 tracing::debug!(?pred);
1738 let trait_id = match pred.kind().skip_binder() {
1739 rustc_type_ir::ClauseKind::Trait(pred) => pred.def_id(),
1740 _ => continue,
1741 };
1742 stack.push(trait_id.0);
1743 }
1744 tracing::debug!(?stack);
1745 }
1746
1747 None
1748 };
1749
1750 match res {
1751 TypeNs::SelfType(impl_id) => {
1752 let trait_ref = db.impl_trait_ns(impl_id)?;
1753
1754 search(trait_ref.skip_binder())
1760 }
1761 TypeNs::GenericParam(param_id) => {
1762 if let GenericDefId::TraitId(trait_id) = param_id.parent() {
1766 let trait_name = &db.trait_signature(trait_id).name;
1767 tracing::debug!(?trait_name);
1768 let trait_generics = generics(db, trait_id.into());
1769 tracing::debug!(?trait_generics);
1770 if trait_generics[param_id.local_id()].is_trait_self() {
1771 let args = crate::next_solver::GenericArgs::identity_for_item(
1772 interner,
1773 trait_id.into(),
1774 );
1775 let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
1776 tracing::debug!(?args, ?trait_ref);
1777 return search(trait_ref);
1778 }
1779 }
1780
1781 let predicates =
1782 db.generic_predicates_for_param_ns(def, param_id.into(), assoc_name.clone());
1783 predicates
1784 .iter()
1785 .find_map(|pred| match (*pred).kind().skip_binder() {
1786 rustc_type_ir::ClauseKind::Trait(trait_predicate) => Some(trait_predicate),
1787 _ => None,
1788 })
1789 .and_then(|trait_predicate| {
1790 let trait_ref = trait_predicate.trait_ref;
1791 assert!(
1792 !trait_ref.has_escaping_bound_vars(),
1793 "FIXME unexpected higher-ranked trait bound"
1794 );
1795 search(trait_ref)
1796 })
1797 }
1798 _ => None,
1799 }
1800}