1mod binder;
8pub mod canonicalize;
9mod expr;
10pub mod fold;
11pub mod normalize;
12mod pretty;
13pub mod refining;
14pub mod region_matching;
15pub mod subst;
16use std::{borrow::Cow, cmp::Ordering, fmt, hash::Hash, sync::LazyLock};
17
18pub use binder::{Binder, BoundReftKind, BoundVariableKind, BoundVariableKinds, EarlyBinder};
19use bitflags::bitflags;
20pub use expr::{
21 AggregateKind, AliasReft, BinOp, BoundReft, Constant, Ctor, ESpan, EVid, EarlyReftParam, Expr,
22 ExprKind, FieldProj, HoleKind, InternalFuncKind, KVar, KVid, Lambda, Loc, Name, Path, Real,
23 SpecFuncKind, UnOp, Var,
24};
25pub use flux_arc_interner::List;
26use flux_arc_interner::{Interned, impl_internable, impl_slice_internable};
27use flux_common::{bug, tracked_span_assert_eq, tracked_span_bug};
28use flux_config::OverflowMode;
29use flux_macros::{TypeFoldable, TypeVisitable};
30pub use flux_rustc_bridge::ty::{
31 AliasKind, BoundRegion, BoundRegionKind, BoundVar, Const, ConstKind, ConstVid, DebruijnIndex,
32 EarlyParamRegion, LateParamRegion, LateParamRegionKind,
33 Region::{self, *},
34 RegionVid,
35};
36use flux_rustc_bridge::{
37 ToRustc,
38 mir::{Place, RawPtrKind},
39 ty::{self, GenericArgsExt as _, VariantDef},
40};
41use itertools::Itertools;
42pub use normalize::{NormalizeInfo, NormalizedDefns, local_deps};
43use refining::{Refine as _, Refiner};
44use rustc_abi;
45pub use rustc_abi::{FIRST_VARIANT, VariantIdx};
46use rustc_data_structures::{fx::FxIndexMap, snapshot_map::SnapshotMap, unord::UnordMap};
47use rustc_hir::{LangItem, Safety, def_id::DefId};
48use rustc_index::{IndexSlice, IndexVec, newtype_index};
49use rustc_macros::{Decodable, Encodable, TyDecodable, TyEncodable, extension};
50use rustc_middle::ty::{TyCtxt, fast_reject::SimplifiedType};
51pub use rustc_middle::{
52 mir::Mutability,
53 ty::{AdtFlags, ClosureKind, FloatTy, IntTy, ParamConst, ParamTy, ScalarInt, UintTy},
54};
55use rustc_span::{DUMMY_SP, Span, Symbol, sym, symbol::kw};
56use rustc_type_ir::Upcast as _;
57pub use rustc_type_ir::{INNERMOST, TyVid};
58
59use self::fold::TypeFoldable;
60pub use crate::fhir::InferMode;
61use crate::{
62 LocalDefId,
63 def_id::{FluxDefId, FluxLocalDefId},
64 fhir::{self, FhirId, FluxOwnerId},
65 global_env::GlobalEnv,
66 pretty::{Pretty, PrettyCx},
67 queries::{QueryErr, QueryResult},
68 rty::subst::SortSubst,
69};
70
71#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
73pub struct AdtSortDef(Interned<AdtSortDefData>);
74
75#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
76pub struct AdtSortVariant {
77 field_names: Vec<Symbol>,
79 sorts: List<Sort>,
84}
85
86impl AdtSortVariant {
87 pub fn new(fields: Vec<(Symbol, Sort)>) -> Self {
88 let (field_names, sorts) = fields.into_iter().unzip();
89 AdtSortVariant { field_names, sorts: List::from_vec(sorts) }
90 }
91
92 pub fn fields(&self) -> usize {
93 self.sorts.len()
94 }
95
96 pub fn field_names(&self) -> &Vec<Symbol> {
97 &self.field_names
98 }
99
100 pub fn sort_by_field_name(&self, args: &[Sort]) -> FxIndexMap<Symbol, Sort> {
101 std::iter::zip(&self.field_names, &self.sorts.fold_with(&mut SortSubst::new(args)))
102 .map(|(name, sort)| (*name, sort.clone()))
103 .collect()
104 }
105
106 pub fn field_by_name(
107 &self,
108 def_id: DefId,
109 args: &[Sort],
110 name: Symbol,
111 ) -> Option<(FieldProj, Sort)> {
112 let idx = self.field_names.iter().position(|it| name == *it)?;
113 let proj = FieldProj::Adt { def_id, field: idx as u32 };
114 let sort = self.sorts[idx].fold_with(&mut SortSubst::new(args));
115 Some((proj, sort))
116 }
117
118 pub fn field_sorts(&self, args: &[Sort]) -> List<Sort> {
119 self.sorts.fold_with(&mut SortSubst::new(args))
120 }
121
122 pub fn field_sorts_instantiate_identity(&self) -> List<Sort> {
123 self.sorts.clone()
124 }
125
126 pub fn projections(&self, def_id: DefId) -> impl Iterator<Item = FieldProj> {
127 (0..self.fields()).map(move |i| FieldProj::Adt { def_id, field: i as u32 })
128 }
129}
130
131#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
132struct AdtSortDefData {
133 def_id: DefId,
135 params: Vec<ParamTy>,
142 variants: IndexVec<VariantIdx, AdtSortVariant>,
146 is_reflected: bool,
147 is_struct: bool,
148}
149
150impl AdtSortDef {
151 pub fn new(
152 def_id: DefId,
153 params: Vec<ParamTy>,
154 variants: IndexVec<VariantIdx, AdtSortVariant>,
155 is_reflected: bool,
156 is_struct: bool,
157 ) -> Self {
158 Self(Interned::new(AdtSortDefData { def_id, params, variants, is_reflected, is_struct }))
159 }
160
161 pub fn did(&self) -> DefId {
162 self.0.def_id
163 }
164
165 pub fn variant(&self, idx: VariantIdx) -> &AdtSortVariant {
166 &self.0.variants[idx]
167 }
168
169 pub fn variants(&self) -> &IndexSlice<VariantIdx, AdtSortVariant> {
170 &self.0.variants
171 }
172
173 pub fn opt_struct_variant(&self) -> Option<&AdtSortVariant> {
174 if self.is_struct() { Some(self.struct_variant()) } else { None }
175 }
176
177 #[track_caller]
178 pub fn struct_variant(&self) -> &AdtSortVariant {
179 tracked_span_assert_eq!(self.0.is_struct, true);
180 &self.0.variants[FIRST_VARIANT]
181 }
182
183 pub fn is_reflected(&self) -> bool {
184 self.0.is_reflected
185 }
186
187 pub fn is_struct(&self) -> bool {
188 self.0.is_struct
189 }
190
191 pub fn to_sort(&self, args: &[GenericArg]) -> Sort {
192 let sorts = self
193 .filter_generic_args(args)
194 .map(|arg| arg.expect_base().sort())
195 .collect();
196
197 Sort::App(SortCtor::Adt(self.clone()), sorts)
198 }
199
200 pub fn filter_generic_args<'a, A>(&'a self, args: &'a [A]) -> impl Iterator<Item = &'a A> + 'a {
203 self.0.params.iter().map(|p| &args[p.index as usize])
204 }
205
206 pub fn identity_args(&self) -> List<Sort> {
207 (0..self.0.params.len())
208 .map(|i| Sort::Var(ParamSort::from(i)))
209 .collect()
210 }
211
212 pub fn param_count(&self) -> usize {
214 self.0.params.len()
215 }
216}
217
218#[derive(Debug, Clone, Default, Encodable, Decodable)]
219pub struct Generics {
220 pub parent: Option<DefId>,
221 pub parent_count: usize,
222 pub own_params: List<GenericParamDef>,
223 pub has_self: bool,
224}
225
226impl Generics {
227 pub fn count(&self) -> usize {
228 self.parent_count + self.own_params.len()
229 }
230
231 pub fn own_default_count(&self) -> usize {
232 self.own_params
233 .iter()
234 .filter(|param| {
235 match param.kind {
236 GenericParamDefKind::Type { has_default }
237 | GenericParamDefKind::Const { has_default }
238 | GenericParamDefKind::Base { has_default } => has_default,
239 GenericParamDefKind::Lifetime => false,
240 }
241 })
242 .count()
243 }
244
245 pub fn param_at(&self, param_index: usize, genv: GlobalEnv) -> QueryResult<GenericParamDef> {
246 if let Some(index) = param_index.checked_sub(self.parent_count) {
247 Ok(self.own_params[index].clone())
248 } else {
249 let parent = self.parent.expect("parent_count > 0 but no parent?");
250 genv.generics_of(parent)?.param_at(param_index, genv)
251 }
252 }
253
254 pub fn const_params(&self, genv: GlobalEnv) -> QueryResult<Vec<(ParamConst, Sort)>> {
255 let mut res = vec![];
256 for i in 0..self.count() {
257 let param = self.param_at(i, genv)?;
258 if let GenericParamDefKind::Const { .. } = param.kind
259 && let Some(sort) = genv.sort_of_def_id(param.def_id)?
260 {
261 let param_const = ParamConst { name: param.name, index: param.index };
262 res.push((param_const, sort));
263 }
264 }
265 Ok(res)
266 }
267}
268
269#[derive(Debug, Clone, TyEncodable, TyDecodable)]
270pub struct RefinementGenerics {
271 pub parent: Option<DefId>,
272 pub parent_count: usize,
273 pub own_params: List<RefineParam>,
274}
275
276#[derive(
277 PartialEq, Eq, Debug, Clone, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
278)]
279pub struct RefineParam {
280 pub sort: Sort,
281 pub name: Symbol,
282 pub mode: InferMode,
283}
284
285#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
286pub struct GenericParamDef {
287 pub kind: GenericParamDefKind,
288 pub def_id: DefId,
289 pub index: u32,
290 pub name: Symbol,
291}
292
293#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
294pub enum GenericParamDefKind {
295 Type { has_default: bool },
296 Base { has_default: bool },
297 Lifetime,
298 Const { has_default: bool },
299}
300
301pub const SELF_PARAM_TY: ParamTy = ParamTy { index: 0, name: kw::SelfUpper };
302
303#[derive(Debug, Clone, TyEncodable, TyDecodable)]
304pub struct GenericPredicates {
305 pub parent: Option<DefId>,
306 pub predicates: List<Clause>,
307}
308
309#[derive(
310 Debug, PartialEq, Eq, Hash, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
311)]
312pub struct Clause {
313 kind: Binder<ClauseKind>,
314}
315
316impl Clause {
317 pub fn new(vars: impl Into<List<BoundVariableKind>>, kind: ClauseKind) -> Self {
318 Clause { kind: Binder::bind_with_vars(kind, vars.into()) }
319 }
320
321 pub fn kind(&self) -> Binder<ClauseKind> {
322 self.kind.clone()
323 }
324
325 fn as_trait_clause(&self) -> Option<Binder<TraitPredicate>> {
326 let clause = self.kind();
327 if let ClauseKind::Trait(trait_clause) = clause.skip_binder_ref() {
328 Some(clause.rebind(trait_clause.clone()))
329 } else {
330 None
331 }
332 }
333
334 pub fn as_projection_clause(&self) -> Option<Binder<ProjectionPredicate>> {
335 let clause = self.kind();
336 if let ClauseKind::Projection(proj_clause) = clause.skip_binder_ref() {
337 Some(clause.rebind(proj_clause.clone()))
338 } else {
339 None
340 }
341 }
342
343 pub fn kind_skipping_binder(&self) -> ClauseKind {
346 self.kind.clone().skip_binder()
347 }
348
349 pub fn split_off_fn_trait_clauses(
353 genv: GlobalEnv,
354 clauses: &Clauses,
355 ) -> (Vec<Clause>, Vec<Binder<FnTraitPredicate>>) {
356 let mut fn_trait_clauses = vec![];
357 let mut fn_trait_output_clauses = vec![];
358 let mut rest = vec![];
359 for clause in clauses {
360 if let Some(trait_clause) = clause.as_trait_clause()
361 && let Some(kind) = genv.tcx().fn_trait_kind_from_def_id(trait_clause.def_id())
362 {
363 fn_trait_clauses.push((kind, trait_clause));
364 } else if let Some(proj_clause) = clause.as_projection_clause()
365 && genv.is_fn_output(proj_clause.projection_def_id())
366 {
367 fn_trait_output_clauses.push(proj_clause);
368 } else {
369 rest.push(clause.clone());
370 }
371 }
372 let fn_trait_clauses = fn_trait_clauses
373 .into_iter()
374 .map(|(kind, fn_trait_clause)| {
375 let mut candidates = vec![];
376 for fn_trait_output_clause in &fn_trait_output_clauses {
377 if fn_trait_output_clause.self_ty() == fn_trait_clause.self_ty() {
378 candidates.push(fn_trait_output_clause.clone());
379 }
380 }
381 tracked_span_assert_eq!(candidates.len(), 1);
382 let proj_pred = candidates.pop().unwrap().skip_binder();
383 fn_trait_clause.map(|fn_trait_clause| {
384 FnTraitPredicate {
385 kind,
386 self_ty: fn_trait_clause.self_ty().to_ty(),
387 tupled_args: fn_trait_clause.trait_ref.args[1].expect_base().to_ty(),
388 output: proj_pred.term.to_ty(),
389 }
390 })
391 })
392 .collect_vec();
393 (rest, fn_trait_clauses)
394 }
395}
396
397impl<'tcx> ToRustc<'tcx> for Clause {
398 type T = rustc_middle::ty::Clause<'tcx>;
399
400 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
401 self.kind.to_rustc(tcx).upcast(tcx)
402 }
403}
404
405impl From<Binder<ClauseKind>> for Clause {
406 fn from(kind: Binder<ClauseKind>) -> Self {
407 Clause { kind }
408 }
409}
410
411pub type Clauses = List<Clause>;
412
413#[derive(
414 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
415)]
416pub enum ClauseKind {
417 Trait(TraitPredicate),
418 Projection(ProjectionPredicate),
419 RegionOutlives(RegionOutlivesPredicate),
420 TypeOutlives(TypeOutlivesPredicate),
421 ConstArgHasType(Const, Ty),
422}
423
424impl<'tcx> ToRustc<'tcx> for ClauseKind {
425 type T = rustc_middle::ty::ClauseKind<'tcx>;
426
427 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
428 match self {
429 ClauseKind::Trait(trait_predicate) => {
430 rustc_middle::ty::ClauseKind::Trait(trait_predicate.to_rustc(tcx))
431 }
432 ClauseKind::Projection(projection_predicate) => {
433 rustc_middle::ty::ClauseKind::Projection(projection_predicate.to_rustc(tcx))
434 }
435 ClauseKind::RegionOutlives(outlives_predicate) => {
436 rustc_middle::ty::ClauseKind::RegionOutlives(outlives_predicate.to_rustc(tcx))
437 }
438 ClauseKind::TypeOutlives(outlives_predicate) => {
439 rustc_middle::ty::ClauseKind::TypeOutlives(outlives_predicate.to_rustc(tcx))
440 }
441 ClauseKind::ConstArgHasType(constant, ty) => {
442 rustc_middle::ty::ClauseKind::ConstArgHasType(
443 constant.to_rustc(tcx),
444 ty.to_rustc(tcx),
445 )
446 }
447 }
448 }
449}
450
451#[derive(Eq, PartialEq, Hash, Clone, Debug, TyEncodable, TyDecodable)]
452pub struct OutlivesPredicate<T>(pub T, pub Region);
453
454pub type TypeOutlivesPredicate = OutlivesPredicate<Ty>;
455pub type RegionOutlivesPredicate = OutlivesPredicate<Region>;
456
457impl<'tcx, V: ToRustc<'tcx>> ToRustc<'tcx> for OutlivesPredicate<V> {
458 type T = rustc_middle::ty::OutlivesPredicate<'tcx, V::T>;
459
460 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
461 rustc_middle::ty::OutlivesPredicate(self.0.to_rustc(tcx), self.1.to_rustc(tcx))
462 }
463}
464
465#[derive(
466 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
467)]
468pub struct TraitPredicate {
469 pub trait_ref: TraitRef,
470}
471
472impl TraitPredicate {
473 fn self_ty(&self) -> SubsetTyCtor {
474 self.trait_ref.self_ty()
475 }
476}
477
478impl<'tcx> ToRustc<'tcx> for TraitPredicate {
479 type T = rustc_middle::ty::TraitPredicate<'tcx>;
480
481 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
482 rustc_middle::ty::TraitPredicate {
483 polarity: rustc_middle::ty::PredicatePolarity::Positive,
484 trait_ref: self.trait_ref.to_rustc(tcx),
485 }
486 }
487}
488
489pub type PolyTraitPredicate = Binder<TraitPredicate>;
490
491impl PolyTraitPredicate {
492 fn def_id(&self) -> DefId {
493 self.skip_binder_ref().trait_ref.def_id
494 }
495
496 fn self_ty(&self) -> Binder<SubsetTyCtor> {
497 self.clone().map(|predicate| predicate.self_ty())
498 }
499}
500
501#[derive(
502 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
503)]
504pub struct TraitRef {
505 pub def_id: DefId,
506 pub args: GenericArgs,
507}
508
509impl TraitRef {
510 pub fn self_ty(&self) -> SubsetTyCtor {
511 self.args[0].expect_base().clone()
512 }
513}
514
515impl<'tcx> ToRustc<'tcx> for TraitRef {
516 type T = rustc_middle::ty::TraitRef<'tcx>;
517
518 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
519 rustc_middle::ty::TraitRef::new(tcx, self.def_id, self.args.to_rustc(tcx))
520 }
521}
522
523pub type PolyTraitRef = Binder<TraitRef>;
524
525impl PolyTraitRef {
526 pub fn def_id(&self) -> DefId {
527 self.as_ref().skip_binder().def_id
528 }
529}
530
531#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
532pub enum ExistentialPredicate {
533 Trait(ExistentialTraitRef),
534 Projection(ExistentialProjection),
535 AutoTrait(DefId),
536}
537
538pub type PolyExistentialPredicate = Binder<ExistentialPredicate>;
539
540impl ExistentialPredicate {
541 pub fn stable_cmp(&self, tcx: TyCtxt, other: &Self) -> Ordering {
543 match (self, other) {
544 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
545 (ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
546 tcx.def_path_hash(a.def_id)
547 .cmp(&tcx.def_path_hash(b.def_id))
548 }
549 (ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b)) => {
550 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
551 }
552 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
553 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
554 Ordering::Greater
555 }
556 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
557 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
558 }
559 }
560}
561
562impl<'tcx> ToRustc<'tcx> for ExistentialPredicate {
563 type T = rustc_middle::ty::ExistentialPredicate<'tcx>;
564
565 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
566 match self {
567 ExistentialPredicate::Trait(trait_ref) => {
568 let trait_ref = rustc_middle::ty::ExistentialTraitRef::new_from_args(
569 tcx,
570 trait_ref.def_id,
571 trait_ref.args.to_rustc(tcx),
572 );
573 rustc_middle::ty::ExistentialPredicate::Trait(trait_ref)
574 }
575 ExistentialPredicate::Projection(projection) => {
576 rustc_middle::ty::ExistentialPredicate::Projection(
577 rustc_middle::ty::ExistentialProjection::new_from_args(
578 tcx,
579 projection.def_id,
580 projection.args.to_rustc(tcx),
581 projection.term.skip_binder_ref().to_rustc(tcx).into(),
582 ),
583 )
584 }
585 ExistentialPredicate::AutoTrait(def_id) => {
586 rustc_middle::ty::ExistentialPredicate::AutoTrait(*def_id)
587 }
588 }
589 }
590}
591
592#[derive(
593 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
594)]
595pub struct ExistentialTraitRef {
596 pub def_id: DefId,
597 pub args: GenericArgs,
598}
599
600pub type PolyExistentialTraitRef = Binder<ExistentialTraitRef>;
601
602impl PolyExistentialTraitRef {
603 pub fn def_id(&self) -> DefId {
604 self.as_ref().skip_binder().def_id
605 }
606}
607
608#[derive(
609 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
610)]
611pub struct ExistentialProjection {
612 pub def_id: DefId,
613 pub args: GenericArgs,
614 pub term: SubsetTyCtor,
615}
616
617#[derive(
618 PartialEq, Eq, Hash, Debug, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
619)]
620pub struct ProjectionPredicate {
621 pub projection_ty: AliasTy,
622 pub term: SubsetTyCtor,
623}
624
625impl Pretty for ProjectionPredicate {
626 fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627 write!(
628 f,
629 "ProjectionPredicate << projection_ty = {:?}, term = {:?} >>",
630 self.projection_ty, self.term
631 )
632 }
633}
634
635impl ProjectionPredicate {
636 pub fn self_ty(&self) -> SubsetTyCtor {
637 self.projection_ty.self_ty().clone()
638 }
639}
640
641impl<'tcx> ToRustc<'tcx> for ProjectionPredicate {
642 type T = rustc_middle::ty::ProjectionPredicate<'tcx>;
643
644 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
645 rustc_middle::ty::ProjectionPredicate {
646 projection_term: rustc_middle::ty::AliasTerm::new_from_args(
647 tcx,
648 self.projection_ty.def_id,
649 self.projection_ty.args.to_rustc(tcx),
650 ),
651 term: self.term.as_bty_skipping_binder().to_rustc(tcx).into(),
652 }
653 }
654}
655
656pub type PolyProjectionPredicate = Binder<ProjectionPredicate>;
657
658impl PolyProjectionPredicate {
659 pub fn projection_def_id(&self) -> DefId {
660 self.skip_binder_ref().projection_ty.def_id
661 }
662
663 pub fn self_ty(&self) -> Binder<SubsetTyCtor> {
664 self.clone().map(|predicate| predicate.self_ty())
665 }
666}
667
668#[derive(
669 Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
670)]
671pub struct FnTraitPredicate {
672 pub self_ty: Ty,
673 pub tupled_args: Ty,
674 pub output: Ty,
675 pub kind: ClosureKind,
676}
677
678impl Pretty for FnTraitPredicate {
679 fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
680 write!(
681 f,
682 "self = {:?}, args = {:?}, output = {:?}, kind = {}",
683 self.self_ty, self.tupled_args, self.output, self.kind
684 )
685 }
686}
687
688impl FnTraitPredicate {
689 pub fn fndef_sig(&self) -> FnSig {
690 let inputs = self.tupled_args.expect_tuple().iter().cloned().collect();
691 let ret = self.output.clone().shift_in_escaping(1);
692 let output = Binder::bind_with_vars(FnOutput::new(ret, vec![]), List::empty());
693 FnSig::new(Safety::Safe, rustc_abi::ExternAbi::Rust, List::empty(), inputs, output)
694 }
695}
696
697pub fn to_closure_sig(
698 tcx: TyCtxt,
699 closure_id: LocalDefId,
700 tys: &[Ty],
701 args: &flux_rustc_bridge::ty::GenericArgs,
702 poly_sig: &PolyFnSig,
703) -> PolyFnSig {
704 let closure_args = args.as_closure();
705 let kind_ty = closure_args.kind_ty().to_rustc(tcx);
706 let Some(kind) = kind_ty.to_opt_closure_kind() else {
707 bug!("to_closure_sig: expected closure kind, found {kind_ty:?}");
708 };
709
710 let mut vars = poly_sig.vars().clone().to_vec();
711 let fn_sig = poly_sig.clone().skip_binder();
712 let closure_ty = Ty::closure(closure_id.into(), tys, args);
713 let env_ty = match kind {
714 ClosureKind::Fn => {
715 vars.push(BoundVariableKind::Region(BoundRegionKind::ClosureEnv));
716 let br = BoundRegion {
717 var: BoundVar::from_usize(vars.len() - 1),
718 kind: BoundRegionKind::ClosureEnv,
719 };
720 Ty::mk_ref(ReBound(INNERMOST, br), closure_ty, Mutability::Not)
721 }
722 ClosureKind::FnMut => {
723 vars.push(BoundVariableKind::Region(BoundRegionKind::ClosureEnv));
724 let br = BoundRegion {
725 var: BoundVar::from_usize(vars.len() - 1),
726 kind: BoundRegionKind::ClosureEnv,
727 };
728 Ty::mk_ref(ReBound(INNERMOST, br), closure_ty, Mutability::Mut)
729 }
730 ClosureKind::FnOnce => closure_ty,
731 };
732
733 let inputs = std::iter::once(env_ty)
734 .chain(fn_sig.inputs().iter().cloned())
735 .collect::<Vec<_>>();
736 let output = fn_sig.output().clone();
737
738 let fn_sig = crate::rty::FnSig::new(
739 fn_sig.safety,
740 fn_sig.abi,
741 fn_sig.requires.clone(), inputs.into(),
743 output,
744 );
745
746 PolyFnSig::bind_with_vars(fn_sig, List::from(vars))
747}
748
749#[derive(
750 Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
751)]
752pub struct CoroutineObligPredicate {
753 pub def_id: DefId,
754 pub resume_ty: Ty,
755 pub upvar_tys: List<Ty>,
756 pub output: Ty,
757}
758
759#[derive(Copy, Clone, Encodable, Decodable, Hash, PartialEq, Eq)]
760pub struct AssocReft {
761 pub def_id: FluxDefId,
762 pub final_: bool,
764 pub span: Span,
765}
766
767impl AssocReft {
768 pub fn new(def_id: FluxDefId, final_: bool, span: Span) -> Self {
769 Self { def_id, final_, span }
770 }
771
772 pub fn name(&self) -> Symbol {
773 self.def_id.name()
774 }
775
776 pub fn def_id(&self) -> FluxDefId {
777 self.def_id
778 }
779}
780
781#[derive(Clone, Encodable, Decodable)]
782pub struct AssocRefinements {
783 pub items: List<AssocReft>,
784}
785
786impl Default for AssocRefinements {
787 fn default() -> Self {
788 Self { items: List::empty() }
789 }
790}
791
792impl AssocRefinements {
793 pub fn get(&self, assoc_id: FluxDefId) -> AssocReft {
794 *self
795 .items
796 .into_iter()
797 .find(|it| it.def_id == assoc_id)
798 .unwrap_or_else(|| bug!("caller should guarantee existence of associated refinement"))
799 }
800
801 pub fn find(&self, name: Symbol) -> Option<AssocReft> {
802 Some(*self.items.into_iter().find(|it| it.name() == name)?)
803 }
804}
805
806#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
807pub enum SortCtor {
808 Set,
809 Map,
810 Adt(AdtSortDef),
811 User(FluxDefId),
812}
813
814newtype_index! {
815 #[debug_format = "?{}s"]
822 #[encodable]
823 pub struct ParamSort {}
824}
825
826newtype_index! {
827 #[debug_format = "?{}s"]
829 #[encodable]
830 pub struct SortVid {}
831}
832
833impl ena::unify::UnifyKey for SortVid {
834 type Value = SortVarVal;
835
836 #[inline]
837 fn index(&self) -> u32 {
838 self.as_u32()
839 }
840
841 #[inline]
842 fn from_index(u: u32) -> Self {
843 SortVid::from_u32(u)
844 }
845
846 fn tag() -> &'static str {
847 "SortVid"
848 }
849}
850
851bitflags! {
852 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
858 pub struct SortCstr: u16 {
859 const BOT = 0b0000000000;
861 const MUL = 0b0000000001;
863 const DIV = 0b0000000010;
865 const MOD = 0b0000000100;
867 const ADD = 0b0000001000;
869 const SUB = 0b0000010000;
871 const BIT_OR = 0b0000100000;
873 const BIT_AND = 0b0001000000;
875 const BIT_SHL = 0b0010000000;
877 const BIT_SHR = 0b0100000000;
879 const BIT_XOR = 0b1000000000;
881
882 const NUMERIC = Self::ADD.bits() | Self::SUB.bits() | Self::MUL.bits() | Self::DIV.bits();
884 const INT = Self::DIV.bits()
886 | Self::MUL.bits()
887 | Self::MOD.bits()
888 | Self::ADD.bits()
889 | Self::SUB.bits();
890 const REAL = Self::ADD.bits() | Self::SUB.bits() | Self::MUL.bits() | Self::DIV.bits();
892 const BITVEC = Self::DIV.bits()
894 | Self::MUL.bits()
895 | Self::MOD.bits()
896 | Self::ADD.bits()
897 | Self::SUB.bits()
898 | Self::BIT_OR.bits()
899 | Self::BIT_AND.bits()
900 | Self::BIT_SHL.bits()
901 | Self::BIT_SHR.bits()
902 | Self::BIT_XOR.bits();
903 const SET = Self::SUB.bits() | Self::BIT_OR.bits() | Self::BIT_AND.bits();
905 }
906}
907
908impl SortCstr {
909 pub fn from_bin_op(op: fhir::BinOp) -> Self {
911 match op {
912 fhir::BinOp::Add => Self::ADD,
913 fhir::BinOp::Sub => Self::SUB,
914 fhir::BinOp::Mul => Self::MUL,
915 fhir::BinOp::Div => Self::DIV,
916 fhir::BinOp::Mod => Self::MOD,
917 fhir::BinOp::BitAnd => Self::BIT_AND,
918 fhir::BinOp::BitOr => Self::BIT_OR,
919 fhir::BinOp::BitXor => Self::BIT_XOR,
920 fhir::BinOp::BitShl => Self::BIT_SHL,
921 fhir::BinOp::BitShr => Self::BIT_SHR,
922 _ => bug!("{op:?} not supported as a constraint"),
923 }
924 }
925
926 fn satisfy(self, sort: &Sort) -> bool {
928 match sort {
929 Sort::Int => SortCstr::INT.contains(self),
930 Sort::Real => SortCstr::REAL.contains(self),
931 Sort::BitVec(_) => SortCstr::BITVEC.contains(self),
932 Sort::App(SortCtor::Set, _) => SortCstr::SET.contains(self),
933 _ => self == SortCstr::BOT,
934 }
935 }
936}
937
938#[derive(Debug, Clone, PartialEq, Eq)]
940pub enum SortVarVal {
941 Unsolved(SortCstr),
943 Solved(Sort),
945}
946
947impl Default for SortVarVal {
948 fn default() -> Self {
949 SortVarVal::Unsolved(SortCstr::BOT)
950 }
951}
952
953impl SortVarVal {
954 pub fn solved_or(&self, sort: &Sort) -> Sort {
955 match self {
956 SortVarVal::Unsolved(_) => sort.clone(),
957 SortVarVal::Solved(sort) => sort.clone(),
958 }
959 }
960
961 pub fn map_solved(&self, f: impl FnOnce(&Sort) -> Sort) -> SortVarVal {
962 match self {
963 SortVarVal::Unsolved(cstr) => SortVarVal::Unsolved(*cstr),
964 SortVarVal::Solved(sort) => SortVarVal::Solved(f(sort)),
965 }
966 }
967}
968
969impl ena::unify::UnifyValue for SortVarVal {
970 type Error = ();
971
972 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> {
973 match (value1, value2) {
974 (SortVarVal::Solved(s1), SortVarVal::Solved(s2)) if s1 == s2 => {
975 Ok(SortVarVal::Solved(s1.clone()))
976 }
977 (SortVarVal::Unsolved(a), SortVarVal::Unsolved(b)) => Ok(SortVarVal::Unsolved(*a | *b)),
978 (SortVarVal::Unsolved(v), SortVarVal::Solved(sort))
979 | (SortVarVal::Solved(sort), SortVarVal::Unsolved(v))
980 if v.satisfy(sort) =>
981 {
982 Ok(SortVarVal::Solved(sort.clone()))
983 }
984 _ => Err(()),
985 }
986 }
987}
988
989newtype_index! {
990 #[debug_format = "?{}size"]
992 #[encodable]
993 pub struct BvSizeVid {}
994}
995
996impl ena::unify::UnifyKey for BvSizeVid {
997 type Value = Option<BvSize>;
998
999 #[inline]
1000 fn index(&self) -> u32 {
1001 self.as_u32()
1002 }
1003
1004 #[inline]
1005 fn from_index(u: u32) -> Self {
1006 BvSizeVid::from_u32(u)
1007 }
1008
1009 fn tag() -> &'static str {
1010 "BvSizeVid"
1011 }
1012}
1013
1014impl ena::unify::EqUnifyValue for BvSize {}
1015
1016#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1017pub enum Sort {
1018 Int,
1019 Bool,
1020 Real,
1021 BitVec(BvSize),
1022 Str,
1023 Char,
1024 Loc,
1025 Param(ParamTy),
1026 Tuple(List<Sort>),
1027 Alias(AliasKind, AliasTy),
1028 Func(PolyFuncSort),
1029 App(SortCtor, List<Sort>),
1030 Var(ParamSort),
1031 Infer(SortVid),
1032 Err,
1033}
1034
1035pub enum CastKind {
1036 Identity,
1038 BoolToInt,
1040 IntoUnit,
1042 Uninterpreted,
1044}
1045
1046impl Sort {
1047 pub fn tuple(sorts: impl Into<List<Sort>>) -> Self {
1048 Sort::Tuple(sorts.into())
1049 }
1050
1051 pub fn app(ctor: SortCtor, sorts: List<Sort>) -> Self {
1052 Sort::App(ctor, sorts)
1053 }
1054
1055 pub fn unit() -> Self {
1056 Self::tuple(vec![])
1057 }
1058
1059 #[track_caller]
1060 pub fn expect_func(&self) -> &PolyFuncSort {
1061 if let Sort::Func(sort) = self { sort } else { bug!("expected `Sort::Func`") }
1062 }
1063
1064 pub fn is_loc(&self) -> bool {
1065 matches!(self, Sort::Loc)
1066 }
1067
1068 pub fn is_unit(&self) -> bool {
1069 matches!(self, Sort::Tuple(sorts) if sorts.is_empty())
1070 }
1071
1072 pub fn is_unit_adt(&self) -> Option<DefId> {
1073 if let Sort::App(SortCtor::Adt(sort_def), _) = self
1074 && let Some(variant) = sort_def.opt_struct_variant()
1075 && variant.fields() == 0
1076 {
1077 Some(sort_def.did())
1078 } else {
1079 None
1080 }
1081 }
1082
1083 pub fn is_pred(&self) -> bool {
1085 matches!(self, Sort::Func(fsort) if fsort.skip_binders().output().is_bool())
1086 }
1087
1088 #[must_use]
1092 pub fn is_bool(&self) -> bool {
1093 matches!(self, Self::Bool)
1094 }
1095
1096 pub fn cast_kind(self: &Sort, to: &Sort) -> CastKind {
1097 if self == to
1098 || (matches!(self, Sort::Char | Sort::Int) && matches!(to, Sort::Char | Sort::Int))
1099 {
1100 CastKind::Identity
1101 } else if matches!(self, Sort::Bool) && matches!(to, Sort::Int) {
1102 CastKind::BoolToInt
1103 } else if to.is_unit() {
1104 CastKind::IntoUnit
1105 } else {
1106 CastKind::Uninterpreted
1107 }
1108 }
1109
1110 pub fn walk(&self, mut f: impl FnMut(&Sort, &[FieldProj])) {
1111 fn go(sort: &Sort, f: &mut impl FnMut(&Sort, &[FieldProj]), proj: &mut Vec<FieldProj>) {
1112 match sort {
1113 Sort::Tuple(flds) => {
1114 for (i, sort) in flds.iter().enumerate() {
1115 proj.push(FieldProj::Tuple { arity: flds.len(), field: i as u32 });
1116 go(sort, f, proj);
1117 proj.pop();
1118 }
1119 }
1120 Sort::App(SortCtor::Adt(sort_def), args) if sort_def.is_struct() => {
1121 let field_sorts = sort_def.struct_variant().field_sorts(args);
1122 for (i, sort) in field_sorts.iter().enumerate() {
1123 proj.push(FieldProj::Adt { def_id: sort_def.did(), field: i as u32 });
1124 go(sort, f, proj);
1125 proj.pop();
1126 }
1127 }
1128 _ => {
1129 f(sort, proj);
1130 }
1131 }
1132 }
1133 go(self, &mut f, &mut vec![]);
1134 }
1135}
1136
1137#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1141pub enum BvSize {
1142 Fixed(u32),
1144 Param(ParamSort),
1146 Infer(BvSizeVid),
1149}
1150
1151impl rustc_errors::IntoDiagArg for Sort {
1152 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1153 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1154 }
1155}
1156
1157impl rustc_errors::IntoDiagArg for FuncSort {
1158 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1159 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1160 }
1161}
1162
1163#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1164pub struct FuncSort {
1165 pub inputs_and_output: List<Sort>,
1166}
1167
1168impl FuncSort {
1169 pub fn new(mut inputs: Vec<Sort>, output: Sort) -> Self {
1170 inputs.push(output);
1171 FuncSort { inputs_and_output: List::from_vec(inputs) }
1172 }
1173
1174 pub fn inputs(&self) -> &[Sort] {
1175 &self.inputs_and_output[0..self.inputs_and_output.len() - 1]
1176 }
1177
1178 pub fn output(&self) -> &Sort {
1179 &self.inputs_and_output[self.inputs_and_output.len() - 1]
1180 }
1181
1182 pub fn to_poly(&self) -> PolyFuncSort {
1183 PolyFuncSort::new(List::empty(), self.clone())
1184 }
1185}
1186
1187#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
1189pub enum SortParamKind {
1190 Sort,
1191 BvSize,
1192}
1193
1194#[derive(Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
1204pub struct PolyFuncSort {
1205 params: List<SortParamKind>,
1207 fsort: FuncSort,
1208}
1209
1210impl PolyFuncSort {
1211 pub fn new(params: List<SortParamKind>, fsort: FuncSort) -> Self {
1212 PolyFuncSort { params, fsort }
1213 }
1214
1215 pub fn skip_binders(&self) -> FuncSort {
1216 self.fsort.clone()
1217 }
1218
1219 pub fn instantiate_identity(&self) -> FuncSort {
1220 self.fsort.clone()
1221 }
1222
1223 pub fn expect_mono(&self) -> FuncSort {
1224 assert!(self.params.is_empty());
1225 self.fsort.clone()
1226 }
1227
1228 pub fn params(&self) -> impl ExactSizeIterator<Item = SortParamKind> + '_ {
1229 self.params.iter().copied()
1230 }
1231
1232 pub fn instantiate(&self, args: &[SortArg]) -> FuncSort {
1233 self.fsort.fold_with(&mut SortSubst::new(args))
1234 }
1235}
1236
1237#[derive(
1240 Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
1241)]
1242pub enum SortArg {
1243 Sort(Sort),
1244 BvSize(BvSize),
1245}
1246
1247#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1248pub enum ConstantInfo {
1249 Uninterpreted,
1251 Interpreted(Expr, Sort),
1253}
1254
1255#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1256pub struct AdtDef(Interned<AdtDefData>);
1257
1258#[derive(Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1259pub struct AdtDefData {
1260 invariants: Vec<Invariant>,
1261 sort_def: AdtSortDef,
1262 opaque: bool,
1263 rustc: ty::AdtDef,
1264}
1265
1266#[derive(Clone, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1269pub enum Opaqueness<T> {
1270 Opaque,
1271 Transparent(T),
1272}
1273
1274impl<T> Opaqueness<T> {
1275 pub fn map<S>(self, f: impl FnOnce(T) -> S) -> Opaqueness<S> {
1276 match self {
1277 Opaqueness::Opaque => Opaqueness::Opaque,
1278 Opaqueness::Transparent(value) => Opaqueness::Transparent(f(value)),
1279 }
1280 }
1281
1282 pub fn as_ref(&self) -> Opaqueness<&T> {
1283 match self {
1284 Opaqueness::Opaque => Opaqueness::Opaque,
1285 Opaqueness::Transparent(value) => Opaqueness::Transparent(value),
1286 }
1287 }
1288
1289 pub fn as_deref(&self) -> Opaqueness<&T::Target>
1290 where
1291 T: std::ops::Deref,
1292 {
1293 match self {
1294 Opaqueness::Opaque => Opaqueness::Opaque,
1295 Opaqueness::Transparent(value) => Opaqueness::Transparent(value.deref()),
1296 }
1297 }
1298
1299 pub fn ok_or_else<E>(self, err: impl FnOnce() -> E) -> Result<T, E> {
1300 match self {
1301 Opaqueness::Transparent(v) => Ok(v),
1302 Opaqueness::Opaque => Err(err()),
1303 }
1304 }
1305
1306 #[track_caller]
1307 pub fn expect(self, msg: &str) -> T {
1308 match self {
1309 Opaqueness::Transparent(val) => val,
1310 Opaqueness::Opaque => bug!("{}", msg),
1311 }
1312 }
1313
1314 pub fn ok_or_query_err(self, struct_id: DefId) -> Result<T, QueryErr> {
1315 self.ok_or_else(|| QueryErr::OpaqueStruct { struct_id })
1316 }
1317}
1318
1319impl<T, E> Opaqueness<Result<T, E>> {
1320 pub fn transpose(self) -> Result<Opaqueness<T>, E> {
1321 match self {
1322 Opaqueness::Transparent(Ok(x)) => Ok(Opaqueness::Transparent(x)),
1323 Opaqueness::Transparent(Err(e)) => Err(e),
1324 Opaqueness::Opaque => Ok(Opaqueness::Opaque),
1325 }
1326 }
1327}
1328
1329pub static INT_TYS: [IntTy; 6] =
1330 [IntTy::Isize, IntTy::I8, IntTy::I16, IntTy::I32, IntTy::I64, IntTy::I128];
1331pub static UINT_TYS: [UintTy; 6] =
1332 [UintTy::Usize, UintTy::U8, UintTy::U16, UintTy::U32, UintTy::U64, UintTy::U128];
1333
1334#[derive(
1335 Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable,
1336)]
1337pub struct Invariant {
1338 pred: Binder<Expr>,
1341}
1342
1343impl Invariant {
1344 pub fn new(pred: Binder<Expr>) -> Self {
1345 Self { pred }
1346 }
1347
1348 pub fn apply(&self, idx: &Expr) -> Expr {
1349 self.pred.replace_bound_reft(idx)
1356 }
1357}
1358
1359pub type PolyVariants = List<Binder<VariantSig>>;
1360pub type PolyVariant = Binder<VariantSig>;
1361
1362#[derive(Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1363pub struct VariantSig {
1364 pub adt_def: AdtDef,
1365 pub args: GenericArgs,
1366 pub fields: List<Ty>,
1367 pub idx: Expr,
1368 pub requires: List<Expr>,
1369}
1370
1371pub type PolyFnSig = Binder<FnSig>;
1372
1373#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1374pub struct FnSig {
1375 pub safety: Safety,
1376 pub abi: rustc_abi::ExternAbi,
1377 pub requires: List<Expr>,
1378 pub inputs: List<Ty>,
1379 pub output: Binder<FnOutput>,
1380}
1381
1382#[derive(
1383 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
1384)]
1385pub struct FnOutput {
1386 pub ret: Ty,
1387 pub ensures: List<Ensures>,
1388}
1389
1390#[derive(Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1391pub enum Ensures {
1392 Type(Path, Ty),
1393 Pred(Expr),
1394}
1395
1396#[derive(Debug, TypeVisitable, TypeFoldable)]
1397pub struct Qualifier {
1398 pub def_id: FluxLocalDefId,
1399 pub body: Binder<Expr>,
1400 pub kind: QualifierKind,
1401}
1402
1403#[derive(Debug, TypeFoldable, TypeVisitable, Copy, Clone)]
1404pub enum QualifierKind {
1405 Global,
1406 Local,
1407 Hint,
1408}
1409
1410#[derive(Debug, TypeVisitable, TypeFoldable)]
1414pub struct PrimOpProp {
1415 pub def_id: FluxLocalDefId,
1416 pub op: BinOp,
1417 pub body: Binder<Expr>,
1418}
1419
1420#[derive(Debug, TypeVisitable, TypeFoldable)]
1421pub struct PrimRel {
1422 pub body: Binder<Expr>,
1423}
1424
1425pub type TyCtor = Binder<Ty>;
1426
1427impl TyCtor {
1428 pub fn to_ty(&self) -> Ty {
1429 match &self.vars()[..] {
1430 [] => {
1431 return self.skip_binder_ref().shift_out_escaping(1);
1432 }
1433 [BoundVariableKind::Refine(sort, ..)] => {
1434 if sort.is_unit() {
1435 return self.replace_bound_reft(&Expr::unit());
1436 }
1437 if let Some(def_id) = sort.is_unit_adt() {
1438 return self.replace_bound_reft(&Expr::unit_struct(def_id));
1439 }
1440 }
1441 _ => {}
1442 }
1443 Ty::exists(self.clone())
1444 }
1445}
1446
1447#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1448pub struct Ty(Interned<TyKind>);
1449
1450impl Ty {
1451 pub fn kind(&self) -> &TyKind {
1452 &self.0
1453 }
1454
1455 pub fn trait_object_dummy_self() -> Ty {
1461 Ty::infer(TyVid::from_u32(0))
1462 }
1463
1464 pub fn dynamic(preds: impl Into<List<Binder<ExistentialPredicate>>>, region: Region) -> Ty {
1465 BaseTy::Dynamic(preds.into(), region).to_ty()
1466 }
1467
1468 pub fn strg_ref(re: Region, path: Path, ty: Ty) -> Ty {
1469 TyKind::StrgRef(re, path, ty).intern()
1470 }
1471
1472 pub fn ptr(pk: impl Into<PtrKind>, path: impl Into<Path>) -> Ty {
1473 TyKind::Ptr(pk.into(), path.into()).intern()
1474 }
1475
1476 pub fn constr(p: impl Into<Expr>, ty: Ty) -> Ty {
1477 TyKind::Constr(p.into(), ty).intern()
1478 }
1479
1480 pub fn uninit() -> Ty {
1481 TyKind::Uninit.intern()
1482 }
1483
1484 pub fn indexed(bty: BaseTy, idx: impl Into<Expr>) -> Ty {
1485 TyKind::Indexed(bty, idx.into()).intern()
1486 }
1487
1488 pub fn exists(ty: Binder<Ty>) -> Ty {
1489 TyKind::Exists(ty).intern()
1490 }
1491
1492 pub fn exists_with_constr(bty: BaseTy, pred: Expr) -> Ty {
1493 let sort = bty.sort();
1494 let ty = Ty::indexed(bty, Expr::nu());
1495 Ty::exists(Binder::bind_with_sort(Ty::constr(pred, ty), sort))
1496 }
1497
1498 pub fn discr(adt_def: AdtDef, place: Place) -> Ty {
1499 TyKind::Discr(adt_def, place).intern()
1500 }
1501
1502 pub fn unit() -> Ty {
1503 Ty::tuple(vec![])
1504 }
1505
1506 pub fn bool() -> Ty {
1507 BaseTy::Bool.to_ty()
1508 }
1509
1510 pub fn int(int_ty: IntTy) -> Ty {
1511 BaseTy::Int(int_ty).to_ty()
1512 }
1513
1514 pub fn uint(uint_ty: UintTy) -> Ty {
1515 BaseTy::Uint(uint_ty).to_ty()
1516 }
1517
1518 pub fn param(param_ty: ParamTy) -> Ty {
1519 TyKind::Param(param_ty).intern()
1520 }
1521
1522 pub fn downcast(
1523 adt: AdtDef,
1524 args: GenericArgs,
1525 ty: Ty,
1526 variant: VariantIdx,
1527 fields: List<Ty>,
1528 ) -> Ty {
1529 TyKind::Downcast(adt, args, ty, variant, fields).intern()
1530 }
1531
1532 pub fn blocked(ty: Ty) -> Ty {
1533 TyKind::Blocked(ty).intern()
1534 }
1535
1536 pub fn str() -> Ty {
1537 BaseTy::Str.to_ty()
1538 }
1539
1540 pub fn char() -> Ty {
1541 BaseTy::Char.to_ty()
1542 }
1543
1544 pub fn float(float_ty: FloatTy) -> Ty {
1545 BaseTy::Float(float_ty).to_ty()
1546 }
1547
1548 pub fn mk_ref(region: Region, ty: Ty, mutbl: Mutability) -> Ty {
1549 BaseTy::Ref(region, ty, mutbl).to_ty()
1550 }
1551
1552 pub fn mk_slice(ty: Ty) -> Ty {
1553 BaseTy::Slice(ty).to_ty()
1554 }
1555
1556 pub fn mk_box(genv: GlobalEnv, deref_ty: Ty, alloc_ty: Ty) -> QueryResult<Ty> {
1557 let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, DUMMY_SP);
1558 let adt_def = genv.adt_def(def_id)?;
1559
1560 let args = List::from_arr([GenericArg::Ty(deref_ty), GenericArg::Ty(alloc_ty)]);
1561
1562 let bty = BaseTy::adt(adt_def, args);
1563 Ok(Ty::indexed(bty, Expr::unit_struct(def_id)))
1564 }
1565
1566 pub fn mk_box_with_default_alloc(genv: GlobalEnv, deref_ty: Ty) -> QueryResult<Ty> {
1567 let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, DUMMY_SP);
1568
1569 let generics = genv.generics_of(def_id)?;
1570 let alloc_ty = genv
1571 .lower_type_of(generics.own_params[1].def_id)?
1572 .skip_binder()
1573 .refine(&Refiner::default_for_item(genv, def_id)?)?;
1574
1575 Ty::mk_box(genv, deref_ty, alloc_ty)
1576 }
1577
1578 pub fn tuple(tys: impl Into<List<Ty>>) -> Ty {
1579 BaseTy::Tuple(tys.into()).to_ty()
1580 }
1581
1582 pub fn array(ty: Ty, c: Const) -> Ty {
1583 BaseTy::Array(ty, c).to_ty()
1584 }
1585
1586 pub fn closure(
1587 did: DefId,
1588 tys: impl Into<List<Ty>>,
1589 args: &flux_rustc_bridge::ty::GenericArgs,
1590 ) -> Ty {
1591 BaseTy::Closure(did, tys.into(), args.clone()).to_ty()
1592 }
1593
1594 pub fn coroutine(did: DefId, resume_ty: Ty, upvar_tys: List<Ty>) -> Ty {
1595 BaseTy::Coroutine(did, resume_ty, upvar_tys).to_ty()
1596 }
1597
1598 pub fn never() -> Ty {
1599 BaseTy::Never.to_ty()
1600 }
1601
1602 pub fn infer(vid: TyVid) -> Ty {
1603 TyKind::Infer(vid).intern()
1604 }
1605
1606 pub fn unconstr(&self) -> (Ty, Expr) {
1607 fn go(this: &Ty, preds: &mut Vec<Expr>) -> Ty {
1608 if let TyKind::Constr(pred, ty) = this.kind() {
1609 preds.push(pred.clone());
1610 go(ty, preds)
1611 } else {
1612 this.clone()
1613 }
1614 }
1615 let mut preds = vec![];
1616 (go(self, &mut preds), Expr::and_from_iter(preds))
1617 }
1618
1619 pub fn unblocked(&self) -> Ty {
1620 match self.kind() {
1621 TyKind::Blocked(ty) => ty.clone(),
1622 _ => self.clone(),
1623 }
1624 }
1625
1626 pub fn is_integral(&self) -> bool {
1628 self.as_bty_skipping_existentials()
1629 .map(BaseTy::is_integral)
1630 .unwrap_or_default()
1631 }
1632
1633 pub fn is_bool(&self) -> bool {
1635 self.as_bty_skipping_existentials()
1636 .map(BaseTy::is_bool)
1637 .unwrap_or_default()
1638 }
1639
1640 pub fn is_char(&self) -> bool {
1642 self.as_bty_skipping_existentials()
1643 .map(BaseTy::is_char)
1644 .unwrap_or_default()
1645 }
1646
1647 pub fn is_uninit(&self) -> bool {
1648 matches!(self.kind(), TyKind::Uninit)
1649 }
1650
1651 pub fn is_box(&self) -> bool {
1652 self.as_bty_skipping_existentials()
1653 .map(BaseTy::is_box)
1654 .unwrap_or_default()
1655 }
1656
1657 pub fn is_struct(&self) -> bool {
1658 self.as_bty_skipping_existentials()
1659 .map(BaseTy::is_struct)
1660 .unwrap_or_default()
1661 }
1662
1663 pub fn is_array(&self) -> bool {
1664 self.as_bty_skipping_existentials()
1665 .map(BaseTy::is_array)
1666 .unwrap_or_default()
1667 }
1668
1669 pub fn is_slice(&self) -> bool {
1670 self.as_bty_skipping_existentials()
1671 .map(BaseTy::is_slice)
1672 .unwrap_or_default()
1673 }
1674
1675 pub fn as_bty_skipping_existentials(&self) -> Option<&BaseTy> {
1676 match self.kind() {
1677 TyKind::Indexed(bty, _) => Some(bty),
1678 TyKind::Exists(ty) => Some(ty.skip_binder_ref().as_bty_skipping_existentials()?),
1679 TyKind::Constr(_, ty) => ty.as_bty_skipping_existentials(),
1680 _ => None,
1681 }
1682 }
1683
1684 #[track_caller]
1685 pub fn expect_discr(&self) -> (&AdtDef, &Place) {
1686 if let TyKind::Discr(adt_def, place) = self.kind() {
1687 (adt_def, place)
1688 } else {
1689 tracked_span_bug!("expected discr")
1690 }
1691 }
1692
1693 #[track_caller]
1694 pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg], &Expr) {
1695 if let TyKind::Indexed(BaseTy::Adt(adt_def, args), idx) = self.kind() {
1696 (adt_def, args, idx)
1697 } else {
1698 tracked_span_bug!("expected adt `{self:?}`")
1699 }
1700 }
1701
1702 #[track_caller]
1703 pub fn expect_tuple(&self) -> &[Ty] {
1704 if let TyKind::Indexed(BaseTy::Tuple(tys), _) = self.kind() {
1705 tys
1706 } else {
1707 tracked_span_bug!("expected tuple found `{self:?}` (kind: `{:?}`)", self.kind())
1708 }
1709 }
1710
1711 pub fn simplify_type(&self) -> Option<SimplifiedType> {
1712 self.as_bty_skipping_existentials()
1713 .and_then(BaseTy::simplify_type)
1714 }
1715}
1716
1717impl<'tcx> ToRustc<'tcx> for Ty {
1718 type T = rustc_middle::ty::Ty<'tcx>;
1719
1720 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
1721 match self.kind() {
1722 TyKind::Indexed(bty, _) => bty.to_rustc(tcx),
1723 TyKind::Exists(ty) => ty.skip_binder_ref().to_rustc(tcx),
1724 TyKind::Constr(_, ty) => ty.to_rustc(tcx),
1725 TyKind::Param(pty) => pty.to_ty(tcx),
1726 TyKind::StrgRef(re, _, ty) => {
1727 rustc_middle::ty::Ty::new_ref(
1728 tcx,
1729 re.to_rustc(tcx),
1730 ty.to_rustc(tcx),
1731 Mutability::Mut,
1732 )
1733 }
1734 TyKind::Infer(vid) => rustc_middle::ty::Ty::new_var(tcx, *vid),
1735 TyKind::Uninit
1736 | TyKind::Ptr(_, _)
1737 | TyKind::Discr(..)
1738 | TyKind::Downcast(..)
1739 | TyKind::Blocked(_) => bug!("TODO: to_rustc for `{self:?}`"),
1740 }
1741 }
1742}
1743
1744#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
1745pub enum TyKind {
1746 Indexed(BaseTy, Expr),
1747 Exists(Binder<Ty>),
1748 Constr(Expr, Ty),
1749 Uninit,
1750 StrgRef(Region, Path, Ty),
1751 Ptr(PtrKind, Path),
1752 Discr(AdtDef, Place),
1761 Param(ParamTy),
1762 Downcast(AdtDef, GenericArgs, Ty, VariantIdx, List<Ty>),
1763 Blocked(Ty),
1764 Infer(TyVid),
1768}
1769
1770#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1771pub enum PtrKind {
1772 Mut(Region),
1773 Box,
1774}
1775
1776#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1777pub enum BaseTy {
1778 Int(IntTy),
1779 Uint(UintTy),
1780 Bool,
1781 Str,
1782 Char,
1783 Slice(Ty),
1784 Adt(AdtDef, GenericArgs),
1785 Float(FloatTy),
1786 RawPtr(Ty, Mutability),
1787 RawPtrMetadata(Ty),
1788 Ref(Region, Ty, Mutability),
1789 FnPtr(PolyFnSig),
1790 FnDef(DefId, GenericArgs),
1791 Tuple(List<Ty>),
1792 Alias(AliasKind, AliasTy),
1793 Array(Ty, Const),
1794 Never,
1795 Closure(DefId, List<Ty>, flux_rustc_bridge::ty::GenericArgs),
1796 Coroutine(DefId, Ty, List<Ty>),
1797 Dynamic(List<Binder<ExistentialPredicate>>, Region),
1798 Param(ParamTy),
1799 Infer(TyVid),
1800 Foreign(DefId),
1801}
1802
1803impl BaseTy {
1804 pub fn opaque(alias_ty: AliasTy) -> BaseTy {
1805 BaseTy::Alias(AliasKind::Opaque, alias_ty)
1806 }
1807
1808 pub fn projection(alias_ty: AliasTy) -> BaseTy {
1809 BaseTy::Alias(AliasKind::Projection, alias_ty)
1810 }
1811
1812 pub fn adt(adt_def: AdtDef, args: GenericArgs) -> BaseTy {
1813 BaseTy::Adt(adt_def, args)
1814 }
1815
1816 pub fn fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> BaseTy {
1817 BaseTy::FnDef(def_id, args.into())
1818 }
1819
1820 pub fn from_primitive_str(s: &str) -> Option<BaseTy> {
1821 match s {
1822 "i8" => Some(BaseTy::Int(IntTy::I8)),
1823 "i16" => Some(BaseTy::Int(IntTy::I16)),
1824 "i32" => Some(BaseTy::Int(IntTy::I32)),
1825 "i64" => Some(BaseTy::Int(IntTy::I64)),
1826 "i128" => Some(BaseTy::Int(IntTy::I128)),
1827 "u8" => Some(BaseTy::Uint(UintTy::U8)),
1828 "u16" => Some(BaseTy::Uint(UintTy::U16)),
1829 "u32" => Some(BaseTy::Uint(UintTy::U32)),
1830 "u64" => Some(BaseTy::Uint(UintTy::U64)),
1831 "u128" => Some(BaseTy::Uint(UintTy::U128)),
1832 "f16" => Some(BaseTy::Float(FloatTy::F16)),
1833 "f32" => Some(BaseTy::Float(FloatTy::F32)),
1834 "f64" => Some(BaseTy::Float(FloatTy::F64)),
1835 "f128" => Some(BaseTy::Float(FloatTy::F128)),
1836 "isize" => Some(BaseTy::Int(IntTy::Isize)),
1837 "usize" => Some(BaseTy::Uint(UintTy::Usize)),
1838 "bool" => Some(BaseTy::Bool),
1839 "char" => Some(BaseTy::Char),
1840 "str" => Some(BaseTy::Str),
1841 _ => None,
1842 }
1843 }
1844
1845 pub fn primitive_symbol(&self) -> Option<Symbol> {
1847 match self {
1848 BaseTy::Bool => Some(sym::bool),
1849 BaseTy::Char => Some(sym::char),
1850 BaseTy::Float(f) => {
1851 match f {
1852 FloatTy::F16 => Some(sym::f16),
1853 FloatTy::F32 => Some(sym::f32),
1854 FloatTy::F64 => Some(sym::f64),
1855 FloatTy::F128 => Some(sym::f128),
1856 }
1857 }
1858 BaseTy::Int(f) => {
1859 match f {
1860 IntTy::Isize => Some(sym::isize),
1861 IntTy::I8 => Some(sym::i8),
1862 IntTy::I16 => Some(sym::i16),
1863 IntTy::I32 => Some(sym::i32),
1864 IntTy::I64 => Some(sym::i64),
1865 IntTy::I128 => Some(sym::i128),
1866 }
1867 }
1868 BaseTy::Uint(f) => {
1869 match f {
1870 UintTy::Usize => Some(sym::usize),
1871 UintTy::U8 => Some(sym::u8),
1872 UintTy::U16 => Some(sym::u16),
1873 UintTy::U32 => Some(sym::u32),
1874 UintTy::U64 => Some(sym::u64),
1875 UintTy::U128 => Some(sym::u128),
1876 }
1877 }
1878 BaseTy::Str => Some(sym::str),
1879 _ => None,
1880 }
1881 }
1882
1883 pub fn is_integral(&self) -> bool {
1884 matches!(self, BaseTy::Int(_) | BaseTy::Uint(_))
1885 }
1886
1887 pub fn is_signed(&self) -> bool {
1888 matches!(self, BaseTy::Int(_))
1889 }
1890
1891 pub fn is_unsigned(&self) -> bool {
1892 matches!(self, BaseTy::Uint(_))
1893 }
1894
1895 pub fn is_float(&self) -> bool {
1896 matches!(self, BaseTy::Float(_))
1897 }
1898
1899 pub fn is_bool(&self) -> bool {
1900 matches!(self, BaseTy::Bool)
1901 }
1902
1903 fn is_struct(&self) -> bool {
1904 matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_struct())
1905 }
1906
1907 fn is_array(&self) -> bool {
1908 matches!(self, BaseTy::Array(..))
1909 }
1910
1911 fn is_slice(&self) -> bool {
1912 matches!(self, BaseTy::Slice(..))
1913 }
1914
1915 pub fn is_box(&self) -> bool {
1916 matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_box())
1917 }
1918
1919 pub fn is_char(&self) -> bool {
1920 matches!(self, BaseTy::Char)
1921 }
1922
1923 pub fn is_str(&self) -> bool {
1924 matches!(self, BaseTy::Str)
1925 }
1926
1927 pub fn invariants(
1928 &self,
1929 tcx: TyCtxt,
1930 overflow_mode: OverflowMode,
1931 ) -> impl Iterator<Item = Invariant> {
1932 let (invariants, args) = match self {
1933 BaseTy::Adt(adt_def, args) => (adt_def.invariants().skip_binder(), &args[..]),
1934 BaseTy::Uint(uint_ty) => (uint_invariants(*uint_ty, overflow_mode), &[][..]),
1935 BaseTy::Int(int_ty) => (int_invariants(*int_ty, overflow_mode), &[][..]),
1936 BaseTy::Char => (char_invariants(), &[][..]),
1937 BaseTy::Slice(_) => (slice_invariants(overflow_mode), &[][..]),
1938 _ => (&[][..], &[][..]),
1939 };
1940 invariants
1941 .iter()
1942 .map(move |inv| EarlyBinder(inv).instantiate_ref(tcx, args, &[]))
1943 }
1944
1945 pub fn to_ty(&self) -> Ty {
1946 let sort = self.sort();
1947 if sort.is_unit() {
1948 Ty::indexed(self.clone(), Expr::unit())
1949 } else {
1950 Ty::exists(Binder::bind_with_sort(
1951 Ty::indexed(self.shift_in_escaping(1), Expr::nu()),
1952 sort,
1953 ))
1954 }
1955 }
1956
1957 pub fn to_subset_ty_ctor(&self) -> SubsetTyCtor {
1958 let sort = self.sort();
1959 Binder::bind_with_sort(SubsetTy::trivial(self.clone(), Expr::nu()), sort)
1960 }
1961
1962 #[track_caller]
1963 pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg]) {
1964 if let BaseTy::Adt(adt_def, args) = self {
1965 (adt_def, args)
1966 } else {
1967 tracked_span_bug!("expected adt `{self:?}`")
1968 }
1969 }
1970
1971 pub fn is_atom(&self) -> bool {
1974 matches!(
1976 self,
1977 BaseTy::Int(_)
1978 | BaseTy::Uint(_)
1979 | BaseTy::Slice(_)
1980 | BaseTy::Bool
1981 | BaseTy::Char
1982 | BaseTy::Str
1983 | BaseTy::Adt(..)
1984 | BaseTy::Tuple(..)
1985 | BaseTy::Param(_)
1986 | BaseTy::Array(..)
1987 | BaseTy::Never
1988 | BaseTy::Closure(..)
1989 | BaseTy::Coroutine(..)
1990 | BaseTy::Alias(..)
1993 )
1994 }
1995
1996 fn simplify_type(&self) -> Option<SimplifiedType> {
2004 match self {
2005 BaseTy::Bool => Some(SimplifiedType::Bool),
2006 BaseTy::Char => Some(SimplifiedType::Char),
2007 BaseTy::Int(int_type) => Some(SimplifiedType::Int(*int_type)),
2008 BaseTy::Uint(uint_type) => Some(SimplifiedType::Uint(*uint_type)),
2009 BaseTy::Float(float_type) => Some(SimplifiedType::Float(*float_type)),
2010 BaseTy::Adt(def, _) => Some(SimplifiedType::Adt(def.did())),
2011 BaseTy::Str => Some(SimplifiedType::Str),
2012 BaseTy::Array(..) => Some(SimplifiedType::Array),
2013 BaseTy::Slice(..) => Some(SimplifiedType::Slice),
2014 BaseTy::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(*mutbl)),
2015 BaseTy::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(*mutbl)),
2016 BaseTy::FnDef(def_id, _) | BaseTy::Closure(def_id, ..) => {
2017 Some(SimplifiedType::Closure(*def_id))
2018 }
2019 BaseTy::Coroutine(def_id, ..) => Some(SimplifiedType::Coroutine(*def_id)),
2020 BaseTy::Never => Some(SimplifiedType::Never),
2021 BaseTy::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
2022 BaseTy::FnPtr(poly_fn_sig) => {
2023 Some(SimplifiedType::Function(poly_fn_sig.skip_binder_ref().inputs().len()))
2024 }
2025 BaseTy::Foreign(def_id) => Some(SimplifiedType::Foreign(*def_id)),
2026 BaseTy::RawPtrMetadata(_)
2027 | BaseTy::Alias(..)
2028 | BaseTy::Param(_)
2029 | BaseTy::Dynamic(..)
2030 | BaseTy::Infer(_) => None,
2031 }
2032 }
2033}
2034
2035impl<'tcx> ToRustc<'tcx> for BaseTy {
2036 type T = rustc_middle::ty::Ty<'tcx>;
2037
2038 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2039 use rustc_middle::ty;
2040 match self {
2041 BaseTy::Int(i) => ty::Ty::new_int(tcx, *i),
2042 BaseTy::Uint(i) => ty::Ty::new_uint(tcx, *i),
2043 BaseTy::Param(pty) => pty.to_ty(tcx),
2044 BaseTy::Slice(ty) => ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
2045 BaseTy::Bool => tcx.types.bool,
2046 BaseTy::Char => tcx.types.char,
2047 BaseTy::Str => tcx.types.str_,
2048 BaseTy::Adt(adt_def, args) => {
2049 let did = adt_def.did();
2050 let adt_def = tcx.adt_def(did);
2051 let args = args.to_rustc(tcx);
2052 ty::Ty::new_adt(tcx, adt_def, args)
2053 }
2054 BaseTy::FnDef(def_id, args) => {
2055 let args = args.to_rustc(tcx);
2056 ty::Ty::new_fn_def(tcx, *def_id, args)
2057 }
2058 BaseTy::Float(f) => ty::Ty::new_float(tcx, *f),
2059 BaseTy::RawPtr(ty, mutbl) => ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
2060 BaseTy::Ref(re, ty, mutbl) => {
2061 ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
2062 }
2063 BaseTy::FnPtr(poly_sig) => ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
2064 BaseTy::Tuple(tys) => {
2065 let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
2066 ty::Ty::new_tup(tcx, &ts)
2067 }
2068 BaseTy::Alias(kind, alias_ty) => {
2069 ty::Ty::new_alias(tcx, kind.to_rustc(tcx), alias_ty.to_rustc(tcx))
2070 }
2071 BaseTy::Array(ty, n) => {
2072 let ty = ty.to_rustc(tcx);
2073 let n = n.to_rustc(tcx);
2074 ty::Ty::new_array_with_const_len(tcx, ty, n)
2075 }
2076 BaseTy::Never => tcx.types.never,
2077 BaseTy::Closure(did, _, args) => ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
2078 BaseTy::Dynamic(exi_preds, re) => {
2079 let preds: Vec<_> = exi_preds
2080 .iter()
2081 .map(|pred| pred.to_rustc(tcx))
2082 .collect_vec();
2083 let preds = tcx.mk_poly_existential_predicates(&preds);
2084 ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx))
2085 }
2086 BaseTy::Coroutine(def_id, resume_ty, upvars) => {
2087 bug!("TODO: Generator {def_id:?} {resume_ty:?} {upvars:?}")
2088 }
2092 BaseTy::Infer(ty_vid) => ty::Ty::new_var(tcx, *ty_vid),
2093 BaseTy::Foreign(def_id) => ty::Ty::new_foreign(tcx, *def_id),
2094 BaseTy::RawPtrMetadata(ty) => {
2095 ty::Ty::new_ptr(
2096 tcx,
2097 ty.to_rustc(tcx),
2098 RawPtrKind::FakeForPtrMetadata.to_mutbl_lossy(),
2099 )
2100 }
2101 }
2102 }
2103}
2104
2105#[derive(
2106 Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
2107)]
2108pub struct AliasTy {
2109 pub def_id: DefId,
2110 pub args: GenericArgs,
2111 pub refine_args: RefineArgs,
2113}
2114
2115impl AliasTy {
2116 pub fn new(def_id: DefId, args: GenericArgs, refine_args: RefineArgs) -> Self {
2117 AliasTy { args, refine_args, def_id }
2118 }
2119}
2120
2121impl AliasTy {
2123 pub fn self_ty(&self) -> SubsetTyCtor {
2124 self.args[0].expect_base().clone()
2125 }
2126
2127 pub fn with_self_ty(&self, self_ty: SubsetTyCtor) -> Self {
2128 Self {
2129 def_id: self.def_id,
2130 args: [GenericArg::Base(self_ty)]
2131 .into_iter()
2132 .chain(self.args.iter().skip(1).cloned())
2133 .collect(),
2134 refine_args: self.refine_args.clone(),
2135 }
2136 }
2137}
2138
2139impl<'tcx> ToRustc<'tcx> for AliasTy {
2140 type T = rustc_middle::ty::AliasTy<'tcx>;
2141
2142 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2143 rustc_middle::ty::AliasTy::new(tcx, self.def_id, self.args.to_rustc(tcx))
2144 }
2145}
2146
2147pub type RefineArgs = List<Expr>;
2148
2149#[extension(pub trait RefineArgsExt)]
2150impl RefineArgs {
2151 fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<RefineArgs> {
2152 Self::for_item(genv, def_id, |param, index| {
2153 Ok(Expr::var(Var::EarlyParam(EarlyReftParam {
2154 index: index as u32,
2155 name: param.name(),
2156 })))
2157 })
2158 }
2159
2160 fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk: F) -> QueryResult<RefineArgs>
2161 where
2162 F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<Expr>,
2163 {
2164 let reft_generics = genv.refinement_generics_of(def_id)?;
2165 let count = reft_generics.count();
2166 let mut args = Vec::with_capacity(count);
2167 reft_generics.fill_item(genv, &mut args, &mut mk)?;
2168 Ok(List::from_vec(args))
2169 }
2170}
2171
2172pub type SubsetTyCtor = Binder<SubsetTy>;
2179
2180impl SubsetTyCtor {
2181 pub fn as_bty_skipping_binder(&self) -> &BaseTy {
2182 &self.as_ref().skip_binder().bty
2183 }
2184
2185 pub fn to_ty(&self) -> Ty {
2186 let sort = self.sort();
2187 if sort.is_unit() {
2188 self.replace_bound_reft(&Expr::unit()).to_ty()
2189 } else if let Some(def_id) = sort.is_unit_adt() {
2190 self.replace_bound_reft(&Expr::unit_struct(def_id)).to_ty()
2191 } else {
2192 Ty::exists(self.as_ref().map(SubsetTy::to_ty))
2193 }
2194 }
2195
2196 pub fn to_ty_ctor(&self) -> TyCtor {
2197 self.as_ref().map(SubsetTy::to_ty)
2198 }
2199}
2200
2201#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
2245pub struct SubsetTy {
2246 pub bty: BaseTy,
2253 pub idx: Expr,
2257 pub pred: Expr,
2259}
2260
2261impl SubsetTy {
2262 pub fn new(bty: BaseTy, idx: impl Into<Expr>, pred: impl Into<Expr>) -> Self {
2263 Self { bty, idx: idx.into(), pred: pred.into() }
2264 }
2265
2266 pub fn trivial(bty: BaseTy, idx: impl Into<Expr>) -> Self {
2267 Self::new(bty, idx, Expr::tt())
2268 }
2269
2270 pub fn strengthen(&self, pred: impl Into<Expr>) -> Self {
2271 let this = self.clone();
2272 let pred = Expr::and(this.pred, pred).simplify(&SnapshotMap::default());
2273 Self { bty: this.bty, idx: this.idx, pred }
2274 }
2275
2276 pub fn to_ty(&self) -> Ty {
2277 let bty = self.bty.clone();
2278 if self.pred.is_trivially_true() {
2279 Ty::indexed(bty, &self.idx)
2280 } else {
2281 Ty::constr(&self.pred, Ty::indexed(bty, &self.idx))
2282 }
2283 }
2284}
2285
2286impl<'tcx> ToRustc<'tcx> for SubsetTy {
2287 type T = rustc_middle::ty::Ty<'tcx>;
2288
2289 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
2290 self.bty.to_rustc(tcx)
2291 }
2292}
2293
2294#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
2295pub enum GenericArg {
2296 Ty(Ty),
2297 Base(SubsetTyCtor),
2298 Lifetime(Region),
2299 Const(Const),
2300}
2301
2302impl GenericArg {
2303 #[track_caller]
2304 pub fn expect_type(&self) -> &Ty {
2305 if let GenericArg::Ty(ty) = self {
2306 ty
2307 } else {
2308 bug!("expected `rty::GenericArg::Ty`, found `{self:?}`")
2309 }
2310 }
2311
2312 #[track_caller]
2313 pub fn expect_base(&self) -> &SubsetTyCtor {
2314 if let GenericArg::Base(ctor) = self {
2315 ctor
2316 } else {
2317 bug!("expected `rty::GenericArg::Base`, found `{self:?}`")
2318 }
2319 }
2320
2321 pub fn from_param_def(param: &GenericParamDef) -> Self {
2322 match param.kind {
2323 GenericParamDefKind::Type { .. } => {
2324 let param_ty = ParamTy { index: param.index, name: param.name };
2325 GenericArg::Ty(Ty::param(param_ty))
2326 }
2327 GenericParamDefKind::Base { .. } => {
2328 let param_ty = ParamTy { index: param.index, name: param.name };
2330 GenericArg::Base(Binder::bind_with_sort(
2331 SubsetTy::trivial(BaseTy::Param(param_ty), Expr::nu()),
2332 Sort::Param(param_ty),
2333 ))
2334 }
2335 GenericParamDefKind::Lifetime => {
2336 let region = EarlyParamRegion { index: param.index, name: param.name };
2337 GenericArg::Lifetime(Region::ReEarlyParam(region))
2338 }
2339 GenericParamDefKind::Const { .. } => {
2340 let param_const = ParamConst { index: param.index, name: param.name };
2341 let kind = ConstKind::Param(param_const);
2342 GenericArg::Const(Const { kind })
2343 }
2344 }
2345 }
2346
2347 pub fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk_kind: F) -> QueryResult<GenericArgs>
2351 where
2352 F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2353 {
2354 let defs = genv.generics_of(def_id)?;
2355 let count = defs.count();
2356 let mut args = Vec::with_capacity(count);
2357 Self::fill_item(genv, &mut args, &defs, &mut mk_kind)?;
2358 Ok(List::from_vec(args))
2359 }
2360
2361 pub fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<GenericArgs> {
2362 Self::for_item(genv, def_id, |param, _| GenericArg::from_param_def(param))
2363 }
2364
2365 fn fill_item<F>(
2366 genv: GlobalEnv,
2367 args: &mut Vec<GenericArg>,
2368 generics: &Generics,
2369 mk_kind: &mut F,
2370 ) -> QueryResult<()>
2371 where
2372 F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2373 {
2374 if let Some(def_id) = generics.parent {
2375 let parent_generics = genv.generics_of(def_id)?;
2376 Self::fill_item(genv, args, &parent_generics, mk_kind)?;
2377 }
2378 for param in &generics.own_params {
2379 let kind = mk_kind(param, args);
2380 tracked_span_assert_eq!(param.index as usize, args.len());
2381 args.push(kind);
2382 }
2383 Ok(())
2384 }
2385}
2386
2387impl From<TyOrBase> for GenericArg {
2388 fn from(v: TyOrBase) -> Self {
2389 match v {
2390 TyOrBase::Ty(ty) => GenericArg::Ty(ty),
2391 TyOrBase::Base(ctor) => GenericArg::Base(ctor),
2392 }
2393 }
2394}
2395
2396impl<'tcx> ToRustc<'tcx> for GenericArg {
2397 type T = rustc_middle::ty::GenericArg<'tcx>;
2398
2399 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2400 use rustc_middle::ty;
2401 match self {
2402 GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
2403 GenericArg::Base(ctor) => ty::GenericArg::from(ctor.skip_binder_ref().to_rustc(tcx)),
2404 GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
2405 GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
2406 }
2407 }
2408}
2409
2410pub type GenericArgs = List<GenericArg>;
2411
2412#[extension(pub trait GenericArgsExt)]
2413impl GenericArgs {
2414 #[track_caller]
2415 fn box_args(&self) -> (&Ty, &Ty) {
2416 if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
2417 (deref, alloc)
2418 } else {
2419 bug!("invalid generic arguments for box");
2420 }
2421 }
2422
2423 fn to_rustc<'tcx>(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::GenericArgsRef<'tcx> {
2425 tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
2426 }
2427
2428 fn rebase_onto(
2429 &self,
2430 tcx: &TyCtxt,
2431 source_ancestor: DefId,
2432 target_args: &GenericArgs,
2433 ) -> List<GenericArg> {
2434 let defs = tcx.generics_of(source_ancestor);
2435 target_args
2436 .iter()
2437 .chain(self.iter().skip(defs.count()))
2438 .cloned()
2439 .collect()
2440 }
2441}
2442
2443#[derive(Debug)]
2444pub enum TyOrBase {
2445 Ty(Ty),
2446 Base(SubsetTyCtor),
2447}
2448
2449impl TyOrBase {
2450 pub fn into_ty(self) -> Ty {
2451 match self {
2452 TyOrBase::Ty(ty) => ty,
2453 TyOrBase::Base(ctor) => ctor.to_ty(),
2454 }
2455 }
2456
2457 #[track_caller]
2458 pub fn expect_base(self) -> SubsetTyCtor {
2459 match self {
2460 TyOrBase::Base(ctor) => ctor,
2461 TyOrBase::Ty(_) => tracked_span_bug!("expected `TyOrBase::Base`"),
2462 }
2463 }
2464
2465 pub fn as_base(self) -> Option<SubsetTyCtor> {
2466 match self {
2467 TyOrBase::Base(ctor) => Some(ctor),
2468 TyOrBase::Ty(_) => None,
2469 }
2470 }
2471}
2472
2473#[derive(Debug, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
2474pub enum TyOrCtor {
2475 Ty(Ty),
2476 Ctor(TyCtor),
2477}
2478
2479impl TyOrCtor {
2480 #[track_caller]
2481 pub fn expect_ctor(self) -> TyCtor {
2482 match self {
2483 TyOrCtor::Ctor(ctor) => ctor,
2484 TyOrCtor::Ty(_) => tracked_span_bug!("expected `TyOrCtor::Ctor`"),
2485 }
2486 }
2487
2488 pub fn expect_subset_ty_ctor(self) -> SubsetTyCtor {
2489 self.expect_ctor().map(|ty| {
2490 if let canonicalize::CanonicalTy::Constr(constr_ty) = ty.shallow_canonicalize()
2491 && let TyKind::Indexed(bty, idx) = constr_ty.ty().kind()
2492 && idx.is_nu()
2493 {
2494 SubsetTy::new(bty.clone(), Expr::nu(), constr_ty.pred())
2495 } else {
2496 tracked_span_bug!()
2497 }
2498 })
2499 }
2500
2501 pub fn to_ty(&self) -> Ty {
2502 match self {
2503 TyOrCtor::Ctor(ctor) => ctor.to_ty(),
2504 TyOrCtor::Ty(ty) => ty.clone(),
2505 }
2506 }
2507}
2508
2509impl From<TyOrBase> for TyOrCtor {
2510 fn from(v: TyOrBase) -> Self {
2511 match v {
2512 TyOrBase::Ty(ty) => TyOrCtor::Ty(ty),
2513 TyOrBase::Base(ctor) => TyOrCtor::Ctor(ctor.to_ty_ctor()),
2514 }
2515 }
2516}
2517
2518impl CoroutineObligPredicate {
2519 pub fn to_poly_fn_sig(&self) -> PolyFnSig {
2520 let vars = vec![];
2521
2522 let resume_ty = &self.resume_ty;
2523 let env_ty = Ty::coroutine(self.def_id, resume_ty.clone(), self.upvar_tys.clone());
2524
2525 let inputs = List::from_arr([env_ty, resume_ty.clone()]);
2526 let output =
2527 Binder::bind_with_vars(FnOutput::new(self.output.clone(), vec![]), List::empty());
2528
2529 PolyFnSig::bind_with_vars(
2530 FnSig::new(Safety::Safe, rustc_abi::ExternAbi::RustCall, List::empty(), inputs, output),
2531 List::from(vars),
2532 )
2533 }
2534}
2535
2536impl RefinementGenerics {
2537 pub fn count(&self) -> usize {
2538 self.parent_count + self.own_params.len()
2539 }
2540
2541 pub fn own_count(&self) -> usize {
2542 self.own_params.len()
2543 }
2544}
2545
2546impl EarlyBinder<RefinementGenerics> {
2547 pub fn parent(&self) -> Option<DefId> {
2548 self.skip_binder_ref().parent
2549 }
2550
2551 pub fn parent_count(&self) -> usize {
2552 self.skip_binder_ref().parent_count
2553 }
2554
2555 pub fn count(&self) -> usize {
2556 self.skip_binder_ref().count()
2557 }
2558
2559 pub fn own_count(&self) -> usize {
2560 self.skip_binder_ref().own_count()
2561 }
2562
2563 pub fn own_param_at(&self, index: usize) -> EarlyBinder<RefineParam> {
2564 self.as_ref().map(|this| this.own_params[index].clone())
2565 }
2566
2567 pub fn param_at(
2568 &self,
2569 param_index: usize,
2570 genv: GlobalEnv,
2571 ) -> QueryResult<EarlyBinder<RefineParam>> {
2572 if let Some(index) = param_index.checked_sub(self.parent_count()) {
2573 Ok(self.own_param_at(index))
2574 } else {
2575 let parent = self.parent().expect("parent_count > 0 but no parent?");
2576 genv.refinement_generics_of(parent)?
2577 .param_at(param_index, genv)
2578 }
2579 }
2580
2581 pub fn iter_own_params(&self) -> impl Iterator<Item = EarlyBinder<RefineParam>> + use<'_> {
2582 self.skip_binder_ref()
2583 .own_params
2584 .iter()
2585 .cloned()
2586 .map(EarlyBinder)
2587 }
2588
2589 pub fn fill_item<F, R>(&self, genv: GlobalEnv, vec: &mut Vec<R>, mk: &mut F) -> QueryResult
2590 where
2591 F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<R>,
2592 {
2593 if let Some(def_id) = self.parent() {
2594 genv.refinement_generics_of(def_id)?
2595 .fill_item(genv, vec, mk)?;
2596 }
2597 for param in self.iter_own_params() {
2598 vec.push(mk(param, vec.len())?);
2599 }
2600 Ok(())
2601 }
2602}
2603
2604impl EarlyBinder<GenericPredicates> {
2605 pub fn predicates(&self) -> EarlyBinder<List<Clause>> {
2606 EarlyBinder(self.0.predicates.clone())
2607 }
2608}
2609
2610impl EarlyBinder<FuncSort> {
2611 pub fn instantiate_func_sort<E>(
2613 self,
2614 sort_for_param: impl FnMut(ParamTy) -> Result<Sort, E>,
2615 ) -> Result<FuncSort, E> {
2616 self.0.try_fold_with(&mut subst::GenericsSubstFolder::new(
2617 subst::GenericsSubstForSort { sort_for_param },
2618 &[],
2619 ))
2620 }
2621}
2622
2623impl VariantSig {
2624 pub fn new(
2625 adt_def: AdtDef,
2626 args: GenericArgs,
2627 fields: List<Ty>,
2628 idx: Expr,
2629 requires: List<Expr>,
2630 ) -> Self {
2631 VariantSig { adt_def, args, fields, idx, requires }
2632 }
2633
2634 pub fn fields(&self) -> &[Ty] {
2635 &self.fields
2636 }
2637
2638 pub fn ret(&self) -> Ty {
2639 let bty = BaseTy::Adt(self.adt_def.clone(), self.args.clone());
2640 let idx = self.idx.clone();
2641 Ty::indexed(bty, idx)
2642 }
2643}
2644
2645impl FnSig {
2646 pub fn new(
2647 safety: Safety,
2648 abi: rustc_abi::ExternAbi,
2649 requires: List<Expr>,
2650 inputs: List<Ty>,
2651 output: Binder<FnOutput>,
2652 ) -> Self {
2653 FnSig { safety, abi, requires, inputs, output }
2654 }
2655
2656 pub fn requires(&self) -> &[Expr] {
2657 &self.requires
2658 }
2659
2660 pub fn inputs(&self) -> &[Ty] {
2661 &self.inputs
2662 }
2663
2664 pub fn output(&self) -> Binder<FnOutput> {
2665 self.output.clone()
2666 }
2667}
2668
2669impl<'tcx> ToRustc<'tcx> for FnSig {
2670 type T = rustc_middle::ty::FnSig<'tcx>;
2671
2672 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2673 tcx.mk_fn_sig(
2674 self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
2675 self.output().as_ref().skip_binder().to_rustc(tcx),
2676 false,
2677 self.safety,
2678 self.abi,
2679 )
2680 }
2681}
2682
2683impl FnOutput {
2684 pub fn new(ret: Ty, ensures: impl Into<List<Ensures>>) -> Self {
2685 Self { ret, ensures: ensures.into() }
2686 }
2687}
2688
2689impl<'tcx> ToRustc<'tcx> for FnOutput {
2690 type T = rustc_middle::ty::Ty<'tcx>;
2691
2692 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2693 self.ret.to_rustc(tcx)
2694 }
2695}
2696
2697impl AdtDef {
2698 pub fn new(
2699 rustc: ty::AdtDef,
2700 sort_def: AdtSortDef,
2701 invariants: Vec<Invariant>,
2702 opaque: bool,
2703 ) -> Self {
2704 AdtDef(Interned::new(AdtDefData { invariants, sort_def, opaque, rustc }))
2705 }
2706
2707 pub fn did(&self) -> DefId {
2708 self.0.rustc.did()
2709 }
2710
2711 pub fn sort_def(&self) -> &AdtSortDef {
2712 &self.0.sort_def
2713 }
2714
2715 pub fn sort(&self, args: &[GenericArg]) -> Sort {
2716 self.sort_def().to_sort(args)
2717 }
2718
2719 pub fn is_box(&self) -> bool {
2720 self.0.rustc.is_box()
2721 }
2722
2723 pub fn is_enum(&self) -> bool {
2724 self.0.rustc.is_enum()
2725 }
2726
2727 pub fn is_struct(&self) -> bool {
2728 self.0.rustc.is_struct()
2729 }
2730
2731 pub fn is_union(&self) -> bool {
2732 self.0.rustc.is_union()
2733 }
2734
2735 pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
2736 self.0.rustc.variants()
2737 }
2738
2739 pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
2740 self.0.rustc.variant(idx)
2741 }
2742
2743 pub fn invariants(&self) -> EarlyBinder<&[Invariant]> {
2744 EarlyBinder(&self.0.invariants)
2745 }
2746
2747 pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
2748 self.0.rustc.discriminants()
2749 }
2750
2751 pub fn is_opaque(&self) -> bool {
2752 self.0.opaque
2753 }
2754}
2755
2756impl EarlyBinder<PolyVariant> {
2757 pub fn to_poly_fn_sig(&self, field_idx: Option<crate::FieldIdx>) -> EarlyBinder<PolyFnSig> {
2760 self.as_ref().map(|poly_variant| {
2761 poly_variant.as_ref().map(|variant| {
2762 let ret = variant.ret().shift_in_escaping(1);
2763 let output = Binder::bind_with_vars(FnOutput::new(ret, vec![]), List::empty());
2764 let inputs = match field_idx {
2765 None => variant.fields.clone(),
2766 Some(i) => List::singleton(variant.fields[i.index()].clone()),
2767 };
2768 FnSig::new(
2769 Safety::Safe,
2770 rustc_abi::ExternAbi::Rust,
2771 variant.requires.clone(),
2772 inputs,
2773 output,
2774 )
2775 })
2776 })
2777 }
2778}
2779
2780impl TyKind {
2781 fn intern(self) -> Ty {
2782 Ty(Interned::new(self))
2783 }
2784}
2785
2786fn slice_invariants(overflow_mode: OverflowMode) -> &'static [Invariant] {
2788 static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2789 [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2790 });
2791 static OVERFLOW: LazyLock<[Invariant; 2]> = LazyLock::new(|| {
2792 [
2793 Invariant {
2794 pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2795 },
2796 Invariant {
2797 pred: Binder::bind_with_sort(
2798 Expr::le(Expr::nu(), Expr::uint_max(UintTy::Usize)),
2799 Sort::Int,
2800 ),
2801 },
2802 ]
2803 });
2804 if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2805 &*OVERFLOW
2806 } else {
2807 &*DEFAULT
2808 }
2809}
2810
2811fn uint_invariants(uint_ty: UintTy, overflow_mode: OverflowMode) -> &'static [Invariant] {
2812 static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2813 [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2814 });
2815
2816 static OVERFLOW: LazyLock<UnordMap<UintTy, [Invariant; 2]>> = LazyLock::new(|| {
2817 UINT_TYS
2818 .into_iter()
2819 .map(|uint_ty| {
2820 let invariants = [
2821 Invariant {
2822 pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2823 },
2824 Invariant {
2825 pred: Binder::bind_with_sort(
2826 Expr::le(Expr::nu(), Expr::uint_max(uint_ty)),
2827 Sort::Int,
2828 ),
2829 },
2830 ];
2831 (uint_ty, invariants)
2832 })
2833 .collect()
2834 });
2835 if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2836 &OVERFLOW[&uint_ty]
2837 } else {
2838 &*DEFAULT
2839 }
2840}
2841
2842fn char_invariants() -> &'static [Invariant] {
2843 static INVARIANTS: LazyLock<[Invariant; 2]> = LazyLock::new(|| {
2844 [
2845 Invariant {
2846 pred: Binder::bind_with_sort(
2847 Expr::le(
2848 Expr::cast(Sort::Char, Sort::Int, Expr::nu()),
2849 Expr::constant((char::MAX as u32).into()),
2850 ),
2851 Sort::Int,
2852 ),
2853 },
2854 Invariant {
2855 pred: Binder::bind_with_sort(
2856 Expr::le(Expr::zero(), Expr::cast(Sort::Char, Sort::Int, Expr::nu())),
2857 Sort::Int,
2858 ),
2859 },
2860 ]
2861 });
2862 &*INVARIANTS
2863}
2864
2865fn int_invariants(int_ty: IntTy, overflow_mode: OverflowMode) -> &'static [Invariant] {
2866 static DEFAULT: [Invariant; 0] = [];
2867
2868 static OVERFLOW: LazyLock<UnordMap<IntTy, [Invariant; 2]>> = LazyLock::new(|| {
2869 INT_TYS
2870 .into_iter()
2871 .map(|int_ty| {
2872 let invariants = [
2873 Invariant {
2874 pred: Binder::bind_with_sort(
2875 Expr::ge(Expr::nu(), Expr::int_min(int_ty)),
2876 Sort::Int,
2877 ),
2878 },
2879 Invariant {
2880 pred: Binder::bind_with_sort(
2881 Expr::le(Expr::nu(), Expr::int_max(int_ty)),
2882 Sort::Int,
2883 ),
2884 },
2885 ];
2886 (int_ty, invariants)
2887 })
2888 .collect()
2889 });
2890 if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2891 &OVERFLOW[&int_ty]
2892 } else {
2893 &DEFAULT
2894 }
2895}
2896
2897impl_internable!(AdtDefData, AdtSortDefData, TyKind);
2898impl_slice_internable!(
2899 Ty,
2900 GenericArg,
2901 Ensures,
2902 InferMode,
2903 Sort,
2904 SortArg,
2905 GenericParamDef,
2906 TraitRef,
2907 Binder<ExistentialPredicate>,
2908 Clause,
2909 PolyVariant,
2910 Invariant,
2911 RefineParam,
2912 FluxDefId,
2913 SortParamKind,
2914 AssocReft
2915);
2916
2917#[macro_export]
2918macro_rules! _Int {
2919 ($int_ty:pat, $idxs:pat) => {
2920 TyKind::Indexed(BaseTy::Int($int_ty), $idxs)
2921 };
2922}
2923pub use crate::_Int as Int;
2924
2925#[macro_export]
2926macro_rules! _Uint {
2927 ($uint_ty:pat, $idxs:pat) => {
2928 TyKind::Indexed(BaseTy::Uint($uint_ty), $idxs)
2929 };
2930}
2931pub use crate::_Uint as Uint;
2932
2933#[macro_export]
2934macro_rules! _Bool {
2935 ($idxs:pat) => {
2936 TyKind::Indexed(BaseTy::Bool, $idxs)
2937 };
2938}
2939pub use crate::_Bool as Bool;
2940
2941#[macro_export]
2942macro_rules! _Char {
2943 ($idxs:pat) => {
2944 TyKind::Indexed(BaseTy::Char, $idxs)
2945 };
2946}
2947pub use crate::_Char as Char;
2948
2949#[macro_export]
2950macro_rules! _Ref {
2951 ($($pats:pat),+ $(,)?) => {
2952 $crate::rty::TyKind::Indexed($crate::rty::BaseTy::Ref($($pats),+), _)
2953 };
2954}
2955pub use crate::_Ref as Ref;
2956
2957pub struct WfckResults {
2958 pub owner: FluxOwnerId,
2959 param_sorts: UnordMap<fhir::ParamId, Sort>,
2960 bin_op_sorts: ItemLocalMap<Sort>,
2961 fn_app_sorts: ItemLocalMap<List<SortArg>>,
2962 coercions: ItemLocalMap<Vec<Coercion>>,
2963 field_projs: ItemLocalMap<FieldProj>,
2964 node_sorts: ItemLocalMap<Sort>,
2965 record_ctors: ItemLocalMap<DefId>,
2966}
2967
2968#[derive(Clone, Copy, Debug)]
2969pub enum Coercion {
2970 Inject(DefId),
2971 Project(DefId),
2972}
2973
2974pub type ItemLocalMap<T> = UnordMap<fhir::ItemLocalId, T>;
2975
2976#[derive(Debug)]
2977pub struct LocalTableInContext<'a, T> {
2978 owner: FluxOwnerId,
2979 data: &'a ItemLocalMap<T>,
2980}
2981
2982pub struct LocalTableInContextMut<'a, T> {
2983 owner: FluxOwnerId,
2984 data: &'a mut ItemLocalMap<T>,
2985}
2986
2987impl WfckResults {
2988 pub fn new(owner: impl Into<FluxOwnerId>) -> Self {
2989 Self {
2990 owner: owner.into(),
2991 param_sorts: UnordMap::default(),
2992 bin_op_sorts: ItemLocalMap::default(),
2993 coercions: ItemLocalMap::default(),
2994 field_projs: ItemLocalMap::default(),
2995 node_sorts: ItemLocalMap::default(),
2996 record_ctors: ItemLocalMap::default(),
2997 fn_app_sorts: ItemLocalMap::default(),
2998 }
2999 }
3000
3001 pub fn param_sorts_mut(&mut self) -> &mut UnordMap<fhir::ParamId, Sort> {
3002 &mut self.param_sorts
3003 }
3004
3005 pub fn param_sorts(&self) -> &UnordMap<fhir::ParamId, Sort> {
3006 &self.param_sorts
3007 }
3008
3009 pub fn bin_op_sorts_mut(&mut self) -> LocalTableInContextMut<'_, Sort> {
3010 LocalTableInContextMut { owner: self.owner, data: &mut self.bin_op_sorts }
3011 }
3012
3013 pub fn fn_app_sorts_mut(&mut self) -> LocalTableInContextMut<'_, List<SortArg>> {
3014 LocalTableInContextMut { owner: self.owner, data: &mut self.fn_app_sorts }
3015 }
3016
3017 pub fn fn_app_sorts(&self) -> LocalTableInContext<'_, List<SortArg>> {
3018 LocalTableInContext { owner: self.owner, data: &self.fn_app_sorts }
3019 }
3020
3021 pub fn bin_op_sorts(&self) -> LocalTableInContext<'_, Sort> {
3022 LocalTableInContext { owner: self.owner, data: &self.bin_op_sorts }
3023 }
3024
3025 pub fn coercions_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Coercion>> {
3026 LocalTableInContextMut { owner: self.owner, data: &mut self.coercions }
3027 }
3028
3029 pub fn coercions(&self) -> LocalTableInContext<'_, Vec<Coercion>> {
3030 LocalTableInContext { owner: self.owner, data: &self.coercions }
3031 }
3032
3033 pub fn field_projs_mut(&mut self) -> LocalTableInContextMut<'_, FieldProj> {
3034 LocalTableInContextMut { owner: self.owner, data: &mut self.field_projs }
3035 }
3036
3037 pub fn field_projs(&self) -> LocalTableInContext<'_, FieldProj> {
3038 LocalTableInContext { owner: self.owner, data: &self.field_projs }
3039 }
3040
3041 pub fn node_sorts_mut(&mut self) -> LocalTableInContextMut<'_, Sort> {
3042 LocalTableInContextMut { owner: self.owner, data: &mut self.node_sorts }
3043 }
3044
3045 pub fn node_sorts(&self) -> LocalTableInContext<'_, Sort> {
3046 LocalTableInContext { owner: self.owner, data: &self.node_sorts }
3047 }
3048
3049 pub fn record_ctors_mut(&mut self) -> LocalTableInContextMut<'_, DefId> {
3050 LocalTableInContextMut { owner: self.owner, data: &mut self.record_ctors }
3051 }
3052
3053 pub fn record_ctors(&self) -> LocalTableInContext<'_, DefId> {
3054 LocalTableInContext { owner: self.owner, data: &self.record_ctors }
3055 }
3056}
3057
3058impl<T> LocalTableInContextMut<'_, T> {
3059 pub fn insert(&mut self, fhir_id: FhirId, value: T) {
3060 tracked_span_assert_eq!(self.owner, fhir_id.owner);
3061 self.data.insert(fhir_id.local_id, value);
3062 }
3063}
3064
3065impl<'a, T> LocalTableInContext<'a, T> {
3066 pub fn get(&self, fhir_id: FhirId) -> Option<&'a T> {
3067 tracked_span_assert_eq!(self.owner, fhir_id.owner);
3068 self.data.get(&fhir_id.local_id)
3069 }
3070}