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