1use std::fmt::Debug;
7use std::hash::Hash;
8
9use rustc_ast_ir::Mutability;
10
11use crate::elaborate::Elaboratable;
12use crate::fold::{TypeFoldable, TypeSuperFoldable};
13use crate::relate::Relate;
14use crate::solve::AdtDestructorKind;
15use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
16use crate::{self as ty, CollectAndApply, Interner, UpcastFrom};
17
18pub trait Ty<I: Interner<Ty = Self>>:
19 Copy
20 + Debug
21 + Hash
22 + Eq
23 + Into<I::GenericArg>
24 + Into<I::Term>
25 + IntoKind<Kind = ty::TyKind<I>>
26 + TypeSuperVisitable<I>
27 + TypeSuperFoldable<I>
28 + Relate<I>
29 + Flags
30{
31 fn new_unit(interner: I) -> Self;
32
33 fn new_bool(interner: I) -> Self;
34
35 fn new_u8(interner: I) -> Self;
36
37 fn new_usize(interner: I) -> Self;
38
39 fn new_infer(interner: I, var: ty::InferTy) -> Self;
40
41 fn new_var(interner: I, var: ty::TyVid) -> Self;
42
43 fn new_param(interner: I, param: I::ParamTy) -> Self;
44
45 fn new_placeholder(interner: I, param: I::PlaceholderTy) -> Self;
46
47 fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundTy) -> Self;
48
49 fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
50
51 fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
52
53 fn new_projection_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self {
54 Ty::new_alias(
55 interner,
56 ty::AliasTyKind::Projection,
57 ty::AliasTy::new_from_args(interner, def_id, args),
58 )
59 }
60
61 fn new_projection(
62 interner: I,
63 def_id: I::DefId,
64 args: impl IntoIterator<Item: Into<I::GenericArg>>,
65 ) -> Self {
66 Ty::new_alias(
67 interner,
68 ty::AliasTyKind::Projection,
69 ty::AliasTy::new(interner, def_id, args),
70 )
71 }
72
73 fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
74
75 fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self;
76
77 fn new_foreign(interner: I, def_id: I::DefId) -> Self;
78
79 fn new_dynamic(
80 interner: I,
81 preds: I::BoundExistentialPredicates,
82 region: I::Region,
83 kind: ty::DynKind,
84 ) -> Self;
85
86 fn new_coroutine(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
87
88 fn new_coroutine_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
89
90 fn new_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
91
92 fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
93
94 fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self;
95
96 fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self;
97
98 fn new_array_with_const_len(interner: I, ty: Self, len: I::Const) -> Self;
99
100 fn new_slice(interner: I, ty: Self) -> Self;
101
102 fn new_tup(interner: I, tys: &[I::Ty]) -> Self;
103
104 fn new_tup_from_iter<It, T>(interner: I, iter: It) -> T::Output
105 where
106 It: Iterator<Item = T>,
107 T: CollectAndApply<Self, Self>;
108
109 fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
110
111 fn new_fn_ptr(interner: I, sig: ty::Binder<I, ty::FnSig<I>>) -> Self;
112
113 fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self;
114
115 fn new_unsafe_binder(interner: I, ty: ty::Binder<I, I::Ty>) -> Self;
116
117 fn tuple_fields(self) -> I::Tys;
118
119 fn to_opt_closure_kind(self) -> Option<ty::ClosureKind>;
120
121 fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
122
123 fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
124
125 fn is_ty_var(self) -> bool {
126 matches!(self.kind(), ty::Infer(ty::TyVar(_)))
127 }
128
129 fn is_ty_error(self) -> bool {
130 matches!(self.kind(), ty::Error(_))
131 }
132
133 fn is_floating_point(self) -> bool {
134 matches!(self.kind(), ty::Float(_) | ty::Infer(ty::FloatVar(_)))
135 }
136
137 fn is_integral(self) -> bool {
138 matches!(self.kind(), ty::Infer(ty::IntVar(_)) | ty::Int(_) | ty::Uint(_))
139 }
140
141 fn is_fn_ptr(self) -> bool {
142 matches!(self.kind(), ty::FnPtr(..))
143 }
144
145 fn has_unsafe_fields(self) -> bool;
147
148 fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
149 self.kind().fn_sig(interner)
150 }
151
152 fn discriminant_ty(self, interner: I) -> I::Ty;
153
154 fn is_known_rigid(self) -> bool {
155 self.kind().is_known_rigid()
156 }
157
158 fn is_guaranteed_unsized_raw(self) -> bool {
159 match self.kind() {
160 ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true,
161 ty::Bool
162 | ty::Char
163 | ty::Int(_)
164 | ty::Uint(_)
165 | ty::Float(_)
166 | ty::Adt(_, _)
167 | ty::Foreign(_)
168 | ty::Array(_, _)
169 | ty::Pat(_, _)
170 | ty::RawPtr(_, _)
171 | ty::Ref(_, _, _)
172 | ty::FnDef(_, _)
173 | ty::FnPtr(_, _)
174 | ty::UnsafeBinder(_)
175 | ty::Closure(_, _)
176 | ty::CoroutineClosure(_, _)
177 | ty::Coroutine(_, _)
178 | ty::CoroutineWitness(_, _)
179 | ty::Never
180 | ty::Tuple(_)
181 | ty::Alias(_, _)
182 | ty::Param(_)
183 | ty::Bound(_, _)
184 | ty::Placeholder(_)
185 | ty::Infer(_)
186 | ty::Error(_)
187 | ty::Dynamic(_, _, ty::DynStar) => false,
188 }
189 }
190}
191
192pub trait Tys<I: Interner<Tys = Self>>:
193 Copy + Debug + Hash + Eq + SliceLike<Item = I::Ty> + TypeFoldable<I> + Default
194{
195 fn inputs(self) -> I::FnInputTys;
196
197 fn output(self) -> I::Ty;
198}
199
200pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
201 fn rust() -> Self;
202
203 fn is_rust(self) -> bool;
205}
206
207pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
208 fn safe() -> Self;
209
210 fn is_safe(self) -> bool;
211
212 fn prefix_str(self) -> &'static str;
213}
214
215pub trait Region<I: Interner<Region = Self>>:
216 Copy
217 + Debug
218 + Hash
219 + Eq
220 + Into<I::GenericArg>
221 + IntoKind<Kind = ty::RegionKind<I>>
222 + Flags
223 + Relate<I>
224{
225 fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self;
226
227 fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
228
229 fn new_static(interner: I) -> Self;
230
231 fn is_bound(self) -> bool {
232 matches!(self.kind(), ty::ReBound(..))
233 }
234}
235
236pub trait Const<I: Interner<Const = Self>>:
237 Copy
238 + Debug
239 + Hash
240 + Eq
241 + Into<I::GenericArg>
242 + Into<I::Term>
243 + IntoKind<Kind = ty::ConstKind<I>>
244 + TypeSuperVisitable<I>
245 + TypeSuperFoldable<I>
246 + Relate<I>
247 + Flags
248{
249 fn new_infer(interner: I, var: ty::InferConst) -> Self;
250
251 fn new_var(interner: I, var: ty::ConstVid) -> Self;
252
253 fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self;
254
255 fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
256
257 fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
258
259 fn new_expr(interner: I, expr: I::ExprConst) -> Self;
260
261 fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
262
263 fn new_error_with_message(interner: I, msg: impl ToString) -> Self {
264 Self::new_error(interner, interner.delay_bug(msg))
265 }
266
267 fn is_ct_var(self) -> bool {
268 matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_)))
269 }
270
271 fn is_ct_error(self) -> bool {
272 matches!(self.kind(), ty::ConstKind::Error(_))
273 }
274}
275
276pub trait ValueConst<I: Interner<ValueConst = Self>>: Copy + Debug + Hash + Eq {
277 fn ty(self) -> I::Ty;
278 fn valtree(self) -> I::ValTree;
279}
280
281pub trait ExprConst<I: Interner<ExprConst = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
282 fn args(self) -> I::GenericArgs;
283}
284
285pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
286 fn count(&self) -> usize;
287}
288
289pub trait GenericArg<I: Interner<GenericArg = Self>>:
290 Copy
291 + Debug
292 + Hash
293 + Eq
294 + IntoKind<Kind = ty::GenericArgKind<I>>
295 + TypeVisitable<I>
296 + Relate<I>
297 + From<I::Ty>
298 + From<I::Region>
299 + From<I::Const>
300 + From<I::Term>
301{
302 fn as_term(&self) -> Option<I::Term> {
303 match self.kind() {
304 ty::GenericArgKind::Lifetime(_) => None,
305 ty::GenericArgKind::Type(ty) => Some(ty.into()),
306 ty::GenericArgKind::Const(ct) => Some(ct.into()),
307 }
308 }
309
310 fn as_type(&self) -> Option<I::Ty> {
311 if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None }
312 }
313
314 fn expect_ty(&self) -> I::Ty {
315 self.as_type().expect("expected a type")
316 }
317
318 fn as_const(&self) -> Option<I::Const> {
319 if let ty::GenericArgKind::Const(c) = self.kind() { Some(c) } else { None }
320 }
321
322 fn expect_const(&self) -> I::Const {
323 self.as_const().expect("expected a const")
324 }
325
326 fn as_region(&self) -> Option<I::Region> {
327 if let ty::GenericArgKind::Lifetime(c) = self.kind() { Some(c) } else { None }
328 }
329
330 fn expect_region(&self) -> I::Region {
331 self.as_region().expect("expected a const")
332 }
333
334 fn is_non_region_infer(self) -> bool {
335 match self.kind() {
336 ty::GenericArgKind::Lifetime(_) => false,
337 ty::GenericArgKind::Type(ty) => ty.is_ty_var(),
338 ty::GenericArgKind::Const(ct) => ct.is_ct_var(),
339 }
340 }
341}
342
343pub trait Term<I: Interner<Term = Self>>:
344 Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
345{
346 fn as_type(&self) -> Option<I::Ty> {
347 if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
348 }
349
350 fn expect_ty(&self) -> I::Ty {
351 self.as_type().expect("expected a type, but found a const")
352 }
353
354 fn as_const(&self) -> Option<I::Const> {
355 if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None }
356 }
357
358 fn expect_const(&self) -> I::Const {
359 self.as_const().expect("expected a const, but found a type")
360 }
361
362 fn is_infer(self) -> bool {
363 match self.kind() {
364 ty::TermKind::Ty(ty) => ty.is_ty_var(),
365 ty::TermKind::Const(ct) => ct.is_ct_var(),
366 }
367 }
368
369 fn is_error(self) -> bool {
370 match self.kind() {
371 ty::TermKind::Ty(ty) => ty.is_ty_error(),
372 ty::TermKind::Const(ct) => ct.is_ct_error(),
373 }
374 }
375
376 fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
377 match self.kind() {
378 ty::TermKind::Ty(ty) => match ty.kind() {
379 ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
380 _ => None,
381 },
382 ty::TermKind::Const(ct) => match ct.kind() {
383 ty::ConstKind::Unevaluated(uv) => Some(uv.into()),
384 _ => None,
385 },
386 }
387 }
388}
389
390pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
391 Copy + Debug + Hash + Eq + SliceLike<Item = I::GenericArg> + Default + Relate<I>
392{
393 fn rebase_onto(
394 self,
395 interner: I,
396 source_def_id: I::DefId,
397 target: I::GenericArgs,
398 ) -> I::GenericArgs;
399
400 fn type_at(self, i: usize) -> I::Ty;
401
402 fn region_at(self, i: usize) -> I::Region;
403
404 fn const_at(self, i: usize) -> I::Const;
405
406 fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
407
408 fn extend_with_error(
409 interner: I,
410 def_id: I::DefId,
411 original_args: &[I::GenericArg],
412 ) -> I::GenericArgs;
413
414 fn split_closure_args(self) -> ty::ClosureArgsParts<I>;
415 fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<I>;
416 fn split_coroutine_args(self) -> ty::CoroutineArgsParts<I>;
417
418 fn as_closure(self) -> ty::ClosureArgs<I> {
419 ty::ClosureArgs { args: self }
420 }
421 fn as_coroutine_closure(self) -> ty::CoroutineClosureArgs<I> {
422 ty::CoroutineClosureArgs { args: self }
423 }
424 fn as_coroutine(self) -> ty::CoroutineArgs<I> {
425 ty::CoroutineArgs { args: self }
426 }
427}
428
429pub trait Predicate<I: Interner<Predicate = Self>>:
430 Copy
431 + Debug
432 + Hash
433 + Eq
434 + TypeSuperVisitable<I>
435 + TypeSuperFoldable<I>
436 + Flags
437 + UpcastFrom<I, ty::PredicateKind<I>>
438 + UpcastFrom<I, ty::Binder<I, ty::PredicateKind<I>>>
439 + UpcastFrom<I, ty::ClauseKind<I>>
440 + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
441 + UpcastFrom<I, I::Clause>
442 + UpcastFrom<I, ty::NormalizesTo<I>>
443 + UpcastFrom<I, ty::TraitRef<I>>
444 + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
445 + UpcastFrom<I, ty::TraitPredicate<I>>
446 + UpcastFrom<I, ty::OutlivesPredicate<I, I::Ty>>
447 + UpcastFrom<I, ty::OutlivesPredicate<I, I::Region>>
448 + IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
449 + Elaboratable<I>
450{
451 fn as_clause(self) -> Option<I::Clause>;
452
453 fn as_normalizes_to(self) -> Option<ty::Binder<I, ty::NormalizesTo<I>>> {
454 let kind = self.kind();
455 match kind.skip_binder() {
456 ty::PredicateKind::NormalizesTo(pred) => Some(kind.rebind(pred)),
457 _ => None,
458 }
459 }
460
461 fn allow_normalization(self) -> bool;
463}
464
465pub trait Clause<I: Interner<Clause = Self>>:
466 Copy
467 + Debug
468 + Hash
469 + Eq
470 + TypeFoldable<I>
471 + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
472 + UpcastFrom<I, ty::TraitRef<I>>
473 + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
474 + UpcastFrom<I, ty::TraitPredicate<I>>
475 + UpcastFrom<I, ty::Binder<I, ty::TraitPredicate<I>>>
476 + UpcastFrom<I, ty::ProjectionPredicate<I>>
477 + UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
478 + IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
479 + Elaboratable<I>
480{
481 fn as_predicate(self) -> I::Predicate;
482
483 fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
484 self.kind()
485 .map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
486 .transpose()
487 }
488
489 fn as_host_effect_clause(self) -> Option<ty::Binder<I, ty::HostEffectPredicate<I>>> {
490 self.kind()
491 .map_bound(
492 |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None },
493 )
494 .transpose()
495 }
496
497 fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>>> {
498 self.kind()
499 .map_bound(
500 |clause| {
501 if let ty::ClauseKind::Projection(p) = clause { Some(p) } else { None }
502 },
503 )
504 .transpose()
505 }
506
507 fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
512}
513
514pub trait PlaceholderLike: Copy + Debug + Hash + Eq {
516 fn universe(self) -> ty::UniverseIndex;
517 fn var(self) -> ty::BoundVar;
518
519 fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self;
520
521 fn new(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self;
522}
523
524pub trait IntoKind {
525 type Kind;
526
527 fn kind(self) -> Self::Kind;
528}
529
530pub trait BoundVarLike<I: Interner> {
531 fn var(self) -> ty::BoundVar;
532
533 fn assert_eq(self, var: I::BoundVarKind);
534}
535
536pub trait ParamLike {
537 fn index(self) -> u32;
538}
539
540pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
541 fn def_id(self) -> I::DefId;
542
543 fn is_struct(self) -> bool;
544
545 fn struct_tail_ty(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
549
550 fn is_phantom_data(self) -> bool;
551
552 fn is_manually_drop(self) -> bool;
553
554 fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
556
557 fn sized_constraint(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
558
559 fn is_fundamental(self) -> bool;
560
561 fn destructor(self, interner: I) -> Option<AdtDestructorKind>;
562}
563
564pub trait ParamEnv<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
565 fn caller_bounds(self) -> impl SliceLike<Item = I::Clause>;
566}
567
568pub trait Features<I: Interner>: Copy {
569 fn generic_const_exprs(self) -> bool;
570
571 fn coroutine_clone(self) -> bool;
572
573 fn associated_const_equality(self) -> bool;
574}
575
576pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
577 fn is_local(self) -> bool;
578
579 fn as_local(self) -> Option<I::LocalDefId>;
580}
581
582pub trait BoundExistentialPredicates<I: Interner>:
583 Copy + Debug + Hash + Eq + Relate<I> + SliceLike<Item = ty::Binder<I, ty::ExistentialPredicate<I>>>
584{
585 fn principal_def_id(self) -> Option<I::DefId>;
586
587 fn principal(self) -> Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>;
588
589 fn auto_traits(self) -> impl IntoIterator<Item = I::DefId>;
590
591 fn projection_bounds(
592 self,
593 ) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
594}
595
596pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
597 fn dummy() -> Self;
598}
599
600pub trait OpaqueTypeStorageEntries: Debug + Copy + Default {
601 fn needs_reevaluation(self, canonicalized: usize) -> bool;
605}
606
607pub trait SliceLike: Sized + Copy {
608 type Item: Copy;
609 type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator;
610
611 fn iter(self) -> Self::IntoIter;
612
613 fn as_slice(&self) -> &[Self::Item];
614
615 fn get(self, idx: usize) -> Option<Self::Item> {
616 self.as_slice().get(idx).copied()
617 }
618
619 fn len(self) -> usize {
620 self.as_slice().len()
621 }
622
623 fn is_empty(self) -> bool {
624 self.len() == 0
625 }
626
627 fn contains(self, t: &Self::Item) -> bool
628 where
629 Self::Item: PartialEq,
630 {
631 self.as_slice().contains(t)
632 }
633
634 fn to_vec(self) -> Vec<Self::Item> {
635 self.as_slice().to_vec()
636 }
637
638 fn last(self) -> Option<Self::Item> {
639 self.as_slice().last().copied()
640 }
641
642 fn split_last(&self) -> Option<(&Self::Item, &[Self::Item])> {
643 self.as_slice().split_last()
644 }
645}
646
647impl<'a, T: Copy> SliceLike for &'a [T] {
648 type Item = T;
649 type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
650
651 fn iter(self) -> Self::IntoIter {
652 self.iter().copied()
653 }
654
655 fn as_slice(&self) -> &[Self::Item] {
656 *self
657 }
658}
659
660impl<'a, T: Copy, const N: usize> SliceLike for &'a [T; N] {
661 type Item = T;
662 type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
663
664 fn iter(self) -> Self::IntoIter {
665 self.into_iter().copied()
666 }
667
668 fn as_slice(&self) -> &[Self::Item] {
669 *self
670 }
671}
672
673impl<'a, S: SliceLike> SliceLike for &'a S {
674 type Item = S::Item;
675 type IntoIter = S::IntoIter;
676
677 fn iter(self) -> Self::IntoIter {
678 (*self).iter()
679 }
680
681 fn as_slice(&self) -> &[Self::Item] {
682 (*self).as_slice()
683 }
684}