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 match self.kind() {
150 ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
151 ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args),
152 ty::Error(_) => {
153 ty::Binder::dummy(ty::FnSig {
155 inputs_and_output: Default::default(),
156 c_variadic: false,
157 safety: I::Safety::safe(),
158 abi: I::Abi::rust(),
159 })
160 }
161 ty::Closure(..) => panic!(
162 "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",
163 ),
164 _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self),
165 }
166 }
167
168 fn discriminant_ty(self, interner: I) -> I::Ty;
169
170 fn async_destructor_ty(self, interner: I) -> I::Ty;
171
172 fn is_known_rigid(self) -> bool {
178 match self.kind() {
179 ty::Bool
180 | ty::Char
181 | ty::Int(_)
182 | ty::Uint(_)
183 | ty::Float(_)
184 | ty::Adt(_, _)
185 | ty::Foreign(_)
186 | ty::Str
187 | ty::Array(_, _)
188 | ty::Pat(_, _)
189 | ty::Slice(_)
190 | ty::RawPtr(_, _)
191 | ty::Ref(_, _, _)
192 | ty::FnDef(_, _)
193 | ty::FnPtr(..)
194 | ty::UnsafeBinder(_)
195 | ty::Dynamic(_, _, _)
196 | ty::Closure(_, _)
197 | ty::CoroutineClosure(_, _)
198 | ty::Coroutine(_, _)
199 | ty::CoroutineWitness(..)
200 | ty::Never
201 | ty::Tuple(_) => true,
202
203 ty::Error(_)
204 | ty::Infer(_)
205 | ty::Alias(_, _)
206 | ty::Param(_)
207 | ty::Bound(_, _)
208 | ty::Placeholder(_) => false,
209 }
210 }
211}
212
213pub trait Tys<I: Interner<Tys = Self>>:
214 Copy + Debug + Hash + Eq + SliceLike<Item = I::Ty> + TypeFoldable<I> + Default
215{
216 fn inputs(self) -> I::FnInputTys;
217
218 fn output(self) -> I::Ty;
219}
220
221pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
222 fn rust() -> Self;
223
224 fn is_rust(self) -> bool;
226}
227
228pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
229 fn safe() -> Self;
230
231 fn is_safe(self) -> bool;
232
233 fn prefix_str(self) -> &'static str;
234}
235
236pub trait Region<I: Interner<Region = Self>>:
237 Copy
238 + Debug
239 + Hash
240 + Eq
241 + Into<I::GenericArg>
242 + IntoKind<Kind = ty::RegionKind<I>>
243 + Flags
244 + Relate<I>
245{
246 fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self;
247
248 fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
249
250 fn new_static(interner: I) -> Self;
251
252 fn is_bound(self) -> bool {
253 matches!(self.kind(), ty::ReBound(..))
254 }
255}
256
257pub trait Const<I: Interner<Const = Self>>:
258 Copy
259 + Debug
260 + Hash
261 + Eq
262 + Into<I::GenericArg>
263 + Into<I::Term>
264 + IntoKind<Kind = ty::ConstKind<I>>
265 + TypeSuperVisitable<I>
266 + TypeSuperFoldable<I>
267 + Relate<I>
268 + Flags
269{
270 fn new_infer(interner: I, var: ty::InferConst) -> Self;
271
272 fn new_var(interner: I, var: ty::ConstVid) -> Self;
273
274 fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self;
275
276 fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
277
278 fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
279
280 fn new_expr(interner: I, expr: I::ExprConst) -> Self;
281
282 fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
283
284 fn new_error_with_message(interner: I, msg: impl ToString) -> Self {
285 Self::new_error(interner, interner.delay_bug(msg))
286 }
287
288 fn is_ct_var(self) -> bool {
289 matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_)))
290 }
291
292 fn is_ct_error(self) -> bool {
293 matches!(self.kind(), ty::ConstKind::Error(_))
294 }
295}
296
297pub trait ValueConst<I: Interner<ValueConst = Self>>: Copy + Debug + Hash + Eq {
298 fn ty(self) -> I::Ty;
299 fn valtree(self) -> I::ValTree;
300}
301
302pub trait ExprConst<I: Interner<ExprConst = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
303 fn args(self) -> I::GenericArgs;
304}
305
306pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
307 fn count(&self) -> usize;
308}
309
310pub trait GenericArg<I: Interner<GenericArg = Self>>:
311 Copy
312 + Debug
313 + Hash
314 + Eq
315 + IntoKind<Kind = ty::GenericArgKind<I>>
316 + TypeVisitable<I>
317 + Relate<I>
318 + From<I::Ty>
319 + From<I::Region>
320 + From<I::Const>
321{
322 fn as_type(&self) -> Option<I::Ty> {
323 if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None }
324 }
325
326 fn expect_ty(&self) -> I::Ty {
327 self.as_type().expect("expected a type")
328 }
329
330 fn as_const(&self) -> Option<I::Const> {
331 if let ty::GenericArgKind::Const(c) = self.kind() { Some(c) } else { None }
332 }
333
334 fn expect_const(&self) -> I::Const {
335 self.as_const().expect("expected a const")
336 }
337
338 fn as_region(&self) -> Option<I::Region> {
339 if let ty::GenericArgKind::Lifetime(c) = self.kind() { Some(c) } else { None }
340 }
341
342 fn expect_region(&self) -> I::Region {
343 self.as_region().expect("expected a const")
344 }
345
346 fn is_non_region_infer(self) -> bool {
347 match self.kind() {
348 ty::GenericArgKind::Lifetime(_) => false,
349 ty::GenericArgKind::Type(ty) => ty.is_ty_var(),
350 ty::GenericArgKind::Const(ct) => ct.is_ct_var(),
351 }
352 }
353}
354
355pub trait Term<I: Interner<Term = Self>>:
356 Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
357{
358 fn as_type(&self) -> Option<I::Ty> {
359 if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
360 }
361
362 fn expect_ty(&self) -> I::Ty {
363 self.as_type().expect("expected a type, but found a const")
364 }
365
366 fn as_const(&self) -> Option<I::Const> {
367 if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None }
368 }
369
370 fn expect_const(&self) -> I::Const {
371 self.as_const().expect("expected a const, but found a type")
372 }
373
374 fn is_infer(self) -> bool {
375 match self.kind() {
376 ty::TermKind::Ty(ty) => ty.is_ty_var(),
377 ty::TermKind::Const(ct) => ct.is_ct_var(),
378 }
379 }
380
381 fn is_error(self) -> bool {
382 match self.kind() {
383 ty::TermKind::Ty(ty) => ty.is_ty_error(),
384 ty::TermKind::Const(ct) => ct.is_ct_error(),
385 }
386 }
387
388 fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
389 match self.kind() {
390 ty::TermKind::Ty(ty) => match ty.kind() {
391 ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
392 _ => None,
393 },
394 ty::TermKind::Const(ct) => match ct.kind() {
395 ty::ConstKind::Unevaluated(uv) => Some(uv.into()),
396 _ => None,
397 },
398 }
399 }
400}
401
402pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
403 Copy + Debug + Hash + Eq + SliceLike<Item = I::GenericArg> + Default + Relate<I>
404{
405 fn rebase_onto(
406 self,
407 interner: I,
408 source_def_id: I::DefId,
409 target: I::GenericArgs,
410 ) -> I::GenericArgs;
411
412 fn type_at(self, i: usize) -> I::Ty;
413
414 fn region_at(self, i: usize) -> I::Region;
415
416 fn const_at(self, i: usize) -> I::Const;
417
418 fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
419
420 fn extend_with_error(
421 interner: I,
422 def_id: I::DefId,
423 original_args: &[I::GenericArg],
424 ) -> I::GenericArgs;
425
426 fn split_closure_args(self) -> ty::ClosureArgsParts<I>;
427 fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<I>;
428 fn split_coroutine_args(self) -> ty::CoroutineArgsParts<I>;
429
430 fn as_closure(self) -> ty::ClosureArgs<I> {
431 ty::ClosureArgs { args: self }
432 }
433 fn as_coroutine_closure(self) -> ty::CoroutineClosureArgs<I> {
434 ty::CoroutineClosureArgs { args: self }
435 }
436 fn as_coroutine(self) -> ty::CoroutineArgs<I> {
437 ty::CoroutineArgs { args: self }
438 }
439}
440
441pub trait Predicate<I: Interner<Predicate = Self>>:
442 Copy
443 + Debug
444 + Hash
445 + Eq
446 + TypeSuperVisitable<I>
447 + TypeSuperFoldable<I>
448 + Flags
449 + UpcastFrom<I, ty::PredicateKind<I>>
450 + UpcastFrom<I, ty::Binder<I, ty::PredicateKind<I>>>
451 + UpcastFrom<I, ty::ClauseKind<I>>
452 + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
453 + UpcastFrom<I, I::Clause>
454 + UpcastFrom<I, ty::NormalizesTo<I>>
455 + UpcastFrom<I, ty::TraitRef<I>>
456 + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
457 + UpcastFrom<I, ty::TraitPredicate<I>>
458 + UpcastFrom<I, ty::OutlivesPredicate<I, I::Ty>>
459 + UpcastFrom<I, ty::OutlivesPredicate<I, I::Region>>
460 + IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
461 + Elaboratable<I>
462{
463 fn as_clause(self) -> Option<I::Clause>;
464
465 fn allow_normalization(self) -> bool;
467}
468
469pub trait Clause<I: Interner<Clause = Self>>:
470 Copy
471 + Debug
472 + Hash
473 + Eq
474 + TypeFoldable<I>
475 + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
476 + UpcastFrom<I, ty::TraitRef<I>>
477 + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
478 + UpcastFrom<I, ty::TraitPredicate<I>>
479 + UpcastFrom<I, ty::Binder<I, ty::TraitPredicate<I>>>
480 + UpcastFrom<I, ty::ProjectionPredicate<I>>
481 + UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
482 + IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
483 + Elaboratable<I>
484{
485 fn as_predicate(self) -> I::Predicate;
486
487 fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
488 self.kind()
489 .map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
490 .transpose()
491 }
492
493 fn as_host_effect_clause(self) -> Option<ty::Binder<I, ty::HostEffectPredicate<I>>> {
494 self.kind()
495 .map_bound(
496 |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None },
497 )
498 .transpose()
499 }
500
501 fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>>> {
502 self.kind()
503 .map_bound(
504 |clause| {
505 if let ty::ClauseKind::Projection(p) = clause { Some(p) } else { None }
506 },
507 )
508 .transpose()
509 }
510
511 fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
516}
517
518pub trait PlaceholderLike: Copy + Debug + Hash + Eq {
520 fn universe(self) -> ty::UniverseIndex;
521 fn var(self) -> ty::BoundVar;
522
523 fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self;
524
525 fn new(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self;
526}
527
528pub trait IntoKind {
529 type Kind;
530
531 fn kind(self) -> Self::Kind;
532}
533
534pub trait BoundVarLike<I: Interner> {
535 fn var(self) -> ty::BoundVar;
536
537 fn assert_eq(self, var: I::BoundVarKind);
538}
539
540pub trait ParamLike {
541 fn index(self) -> u32;
542}
543
544pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
545 fn def_id(self) -> I::DefId;
546
547 fn is_struct(self) -> bool;
548
549 fn struct_tail_ty(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
553
554 fn is_phantom_data(self) -> bool;
555
556 fn is_manually_drop(self) -> bool;
557
558 fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
560
561 fn sized_constraint(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
562
563 fn is_fundamental(self) -> bool;
564
565 fn destructor(self, interner: I) -> Option<AdtDestructorKind>;
566}
567
568pub trait ParamEnv<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
569 fn caller_bounds(self) -> impl SliceLike<Item = I::Clause>;
570}
571
572pub trait Features<I: Interner>: Copy {
573 fn generic_const_exprs(self) -> bool;
574
575 fn coroutine_clone(self) -> bool;
576
577 fn associated_const_equality(self) -> bool;
578}
579
580pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
581 fn is_local(self) -> bool;
582
583 fn as_local(self) -> Option<I::LocalDefId>;
584}
585
586pub trait BoundExistentialPredicates<I: Interner>:
587 Copy + Debug + Hash + Eq + Relate<I> + SliceLike<Item = ty::Binder<I, ty::ExistentialPredicate<I>>>
588{
589 fn principal_def_id(self) -> Option<I::DefId>;
590
591 fn principal(self) -> Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>;
592
593 fn auto_traits(self) -> impl IntoIterator<Item = I::DefId>;
594
595 fn projection_bounds(
596 self,
597 ) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
598}
599
600pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
601 fn dummy() -> Self;
602}
603
604pub trait SliceLike: Sized + Copy {
605 type Item: Copy;
606 type IntoIter: Iterator<Item = Self::Item>;
607
608 fn iter(self) -> Self::IntoIter;
609
610 fn as_slice(&self) -> &[Self::Item];
611
612 fn get(self, idx: usize) -> Option<Self::Item> {
613 self.as_slice().get(idx).copied()
614 }
615
616 fn len(self) -> usize {
617 self.as_slice().len()
618 }
619
620 fn is_empty(self) -> bool {
621 self.len() == 0
622 }
623
624 fn contains(self, t: &Self::Item) -> bool
625 where
626 Self::Item: PartialEq,
627 {
628 self.as_slice().contains(t)
629 }
630
631 fn to_vec(self) -> Vec<Self::Item> {
632 self.as_slice().to_vec()
633 }
634
635 fn last(self) -> Option<Self::Item> {
636 self.as_slice().last().copied()
637 }
638
639 fn split_last(&self) -> Option<(&Self::Item, &[Self::Item])> {
640 self.as_slice().split_last()
641 }
642}
643
644impl<'a, T: Copy> SliceLike for &'a [T] {
645 type Item = T;
646 type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
647
648 fn iter(self) -> Self::IntoIter {
649 self.iter().copied()
650 }
651
652 fn as_slice(&self) -> &[Self::Item] {
653 *self
654 }
655}
656
657impl<'a, T: Copy, const N: usize> SliceLike for &'a [T; N] {
658 type Item = T;
659 type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
660
661 fn iter(self) -> Self::IntoIter {
662 self.into_iter().copied()
663 }
664
665 fn as_slice(&self) -> &[Self::Item] {
666 *self
667 }
668}
669
670impl<'a, S: SliceLike> SliceLike for &'a S {
671 type Item = S::Item;
672 type IntoIter = S::IntoIter;
673
674 fn iter(self) -> Self::IntoIter {
675 (*self).iter()
676 }
677
678 fn as_slice(&self) -> &[Self::Item] {
679 (*self).as_slice()
680 }
681}