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 global: bool,
1401}
1402
1403#[derive(Debug, TypeVisitable, TypeFoldable)]
1407pub struct PrimOpProp {
1408 pub def_id: FluxLocalDefId,
1409 pub op: BinOp,
1410 pub body: Binder<Expr>,
1411}
1412
1413#[derive(Debug, TypeVisitable, TypeFoldable)]
1414pub struct PrimRel {
1415 pub body: Binder<Expr>,
1416}
1417
1418pub type TyCtor = Binder<Ty>;
1419
1420impl TyCtor {
1421 pub fn to_ty(&self) -> Ty {
1422 match &self.vars()[..] {
1423 [] => {
1424 return self.skip_binder_ref().shift_out_escaping(1);
1425 }
1426 [BoundVariableKind::Refine(sort, ..)] => {
1427 if sort.is_unit() {
1428 return self.replace_bound_reft(&Expr::unit());
1429 }
1430 if let Some(def_id) = sort.is_unit_adt() {
1431 return self.replace_bound_reft(&Expr::unit_struct(def_id));
1432 }
1433 }
1434 _ => {}
1435 }
1436 Ty::exists(self.clone())
1437 }
1438}
1439
1440#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1441pub struct Ty(Interned<TyKind>);
1442
1443impl Ty {
1444 pub fn kind(&self) -> &TyKind {
1445 &self.0
1446 }
1447
1448 pub fn trait_object_dummy_self() -> Ty {
1454 Ty::infer(TyVid::from_u32(0))
1455 }
1456
1457 pub fn dynamic(preds: impl Into<List<Binder<ExistentialPredicate>>>, region: Region) -> Ty {
1458 BaseTy::Dynamic(preds.into(), region).to_ty()
1459 }
1460
1461 pub fn strg_ref(re: Region, path: Path, ty: Ty) -> Ty {
1462 TyKind::StrgRef(re, path, ty).intern()
1463 }
1464
1465 pub fn ptr(pk: impl Into<PtrKind>, path: impl Into<Path>) -> Ty {
1466 TyKind::Ptr(pk.into(), path.into()).intern()
1467 }
1468
1469 pub fn constr(p: impl Into<Expr>, ty: Ty) -> Ty {
1470 TyKind::Constr(p.into(), ty).intern()
1471 }
1472
1473 pub fn uninit() -> Ty {
1474 TyKind::Uninit.intern()
1475 }
1476
1477 pub fn indexed(bty: BaseTy, idx: impl Into<Expr>) -> Ty {
1478 TyKind::Indexed(bty, idx.into()).intern()
1479 }
1480
1481 pub fn exists(ty: Binder<Ty>) -> Ty {
1482 TyKind::Exists(ty).intern()
1483 }
1484
1485 pub fn exists_with_constr(bty: BaseTy, pred: Expr) -> Ty {
1486 let sort = bty.sort();
1487 let ty = Ty::indexed(bty, Expr::nu());
1488 Ty::exists(Binder::bind_with_sort(Ty::constr(pred, ty), sort))
1489 }
1490
1491 pub fn discr(adt_def: AdtDef, place: Place) -> Ty {
1492 TyKind::Discr(adt_def, place).intern()
1493 }
1494
1495 pub fn unit() -> Ty {
1496 Ty::tuple(vec![])
1497 }
1498
1499 pub fn bool() -> Ty {
1500 BaseTy::Bool.to_ty()
1501 }
1502
1503 pub fn int(int_ty: IntTy) -> Ty {
1504 BaseTy::Int(int_ty).to_ty()
1505 }
1506
1507 pub fn uint(uint_ty: UintTy) -> Ty {
1508 BaseTy::Uint(uint_ty).to_ty()
1509 }
1510
1511 pub fn param(param_ty: ParamTy) -> Ty {
1512 TyKind::Param(param_ty).intern()
1513 }
1514
1515 pub fn downcast(
1516 adt: AdtDef,
1517 args: GenericArgs,
1518 ty: Ty,
1519 variant: VariantIdx,
1520 fields: List<Ty>,
1521 ) -> Ty {
1522 TyKind::Downcast(adt, args, ty, variant, fields).intern()
1523 }
1524
1525 pub fn blocked(ty: Ty) -> Ty {
1526 TyKind::Blocked(ty).intern()
1527 }
1528
1529 pub fn str() -> Ty {
1530 BaseTy::Str.to_ty()
1531 }
1532
1533 pub fn char() -> Ty {
1534 BaseTy::Char.to_ty()
1535 }
1536
1537 pub fn float(float_ty: FloatTy) -> Ty {
1538 BaseTy::Float(float_ty).to_ty()
1539 }
1540
1541 pub fn mk_ref(region: Region, ty: Ty, mutbl: Mutability) -> Ty {
1542 BaseTy::Ref(region, ty, mutbl).to_ty()
1543 }
1544
1545 pub fn mk_slice(ty: Ty) -> Ty {
1546 BaseTy::Slice(ty).to_ty()
1547 }
1548
1549 pub fn mk_box(genv: GlobalEnv, deref_ty: Ty, alloc_ty: Ty) -> QueryResult<Ty> {
1550 let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, DUMMY_SP);
1551 let adt_def = genv.adt_def(def_id)?;
1552
1553 let args = List::from_arr([GenericArg::Ty(deref_ty), GenericArg::Ty(alloc_ty)]);
1554
1555 let bty = BaseTy::adt(adt_def, args);
1556 Ok(Ty::indexed(bty, Expr::unit_struct(def_id)))
1557 }
1558
1559 pub fn mk_box_with_default_alloc(genv: GlobalEnv, deref_ty: Ty) -> QueryResult<Ty> {
1560 let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, DUMMY_SP);
1561
1562 let generics = genv.generics_of(def_id)?;
1563 let alloc_ty = genv
1564 .lower_type_of(generics.own_params[1].def_id)?
1565 .skip_binder()
1566 .refine(&Refiner::default_for_item(genv, def_id)?)?;
1567
1568 Ty::mk_box(genv, deref_ty, alloc_ty)
1569 }
1570
1571 pub fn tuple(tys: impl Into<List<Ty>>) -> Ty {
1572 BaseTy::Tuple(tys.into()).to_ty()
1573 }
1574
1575 pub fn array(ty: Ty, c: Const) -> Ty {
1576 BaseTy::Array(ty, c).to_ty()
1577 }
1578
1579 pub fn closure(
1580 did: DefId,
1581 tys: impl Into<List<Ty>>,
1582 args: &flux_rustc_bridge::ty::GenericArgs,
1583 ) -> Ty {
1584 BaseTy::Closure(did, tys.into(), args.clone()).to_ty()
1585 }
1586
1587 pub fn coroutine(did: DefId, resume_ty: Ty, upvar_tys: List<Ty>) -> Ty {
1588 BaseTy::Coroutine(did, resume_ty, upvar_tys).to_ty()
1589 }
1590
1591 pub fn never() -> Ty {
1592 BaseTy::Never.to_ty()
1593 }
1594
1595 pub fn infer(vid: TyVid) -> Ty {
1596 TyKind::Infer(vid).intern()
1597 }
1598
1599 pub fn unconstr(&self) -> (Ty, Expr) {
1600 fn go(this: &Ty, preds: &mut Vec<Expr>) -> Ty {
1601 if let TyKind::Constr(pred, ty) = this.kind() {
1602 preds.push(pred.clone());
1603 go(ty, preds)
1604 } else {
1605 this.clone()
1606 }
1607 }
1608 let mut preds = vec![];
1609 (go(self, &mut preds), Expr::and_from_iter(preds))
1610 }
1611
1612 pub fn unblocked(&self) -> Ty {
1613 match self.kind() {
1614 TyKind::Blocked(ty) => ty.clone(),
1615 _ => self.clone(),
1616 }
1617 }
1618
1619 pub fn is_integral(&self) -> bool {
1621 self.as_bty_skipping_existentials()
1622 .map(BaseTy::is_integral)
1623 .unwrap_or_default()
1624 }
1625
1626 pub fn is_bool(&self) -> bool {
1628 self.as_bty_skipping_existentials()
1629 .map(BaseTy::is_bool)
1630 .unwrap_or_default()
1631 }
1632
1633 pub fn is_char(&self) -> bool {
1635 self.as_bty_skipping_existentials()
1636 .map(BaseTy::is_char)
1637 .unwrap_or_default()
1638 }
1639
1640 pub fn is_uninit(&self) -> bool {
1641 matches!(self.kind(), TyKind::Uninit)
1642 }
1643
1644 pub fn is_box(&self) -> bool {
1645 self.as_bty_skipping_existentials()
1646 .map(BaseTy::is_box)
1647 .unwrap_or_default()
1648 }
1649
1650 pub fn is_struct(&self) -> bool {
1651 self.as_bty_skipping_existentials()
1652 .map(BaseTy::is_struct)
1653 .unwrap_or_default()
1654 }
1655
1656 pub fn is_array(&self) -> bool {
1657 self.as_bty_skipping_existentials()
1658 .map(BaseTy::is_array)
1659 .unwrap_or_default()
1660 }
1661
1662 pub fn is_slice(&self) -> bool {
1663 self.as_bty_skipping_existentials()
1664 .map(BaseTy::is_slice)
1665 .unwrap_or_default()
1666 }
1667
1668 pub fn as_bty_skipping_existentials(&self) -> Option<&BaseTy> {
1669 match self.kind() {
1670 TyKind::Indexed(bty, _) => Some(bty),
1671 TyKind::Exists(ty) => Some(ty.skip_binder_ref().as_bty_skipping_existentials()?),
1672 TyKind::Constr(_, ty) => ty.as_bty_skipping_existentials(),
1673 _ => None,
1674 }
1675 }
1676
1677 #[track_caller]
1678 pub fn expect_discr(&self) -> (&AdtDef, &Place) {
1679 if let TyKind::Discr(adt_def, place) = self.kind() {
1680 (adt_def, place)
1681 } else {
1682 tracked_span_bug!("expected discr")
1683 }
1684 }
1685
1686 #[track_caller]
1687 pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg], &Expr) {
1688 if let TyKind::Indexed(BaseTy::Adt(adt_def, args), idx) = self.kind() {
1689 (adt_def, args, idx)
1690 } else {
1691 tracked_span_bug!("expected adt `{self:?}`")
1692 }
1693 }
1694
1695 #[track_caller]
1696 pub fn expect_tuple(&self) -> &[Ty] {
1697 if let TyKind::Indexed(BaseTy::Tuple(tys), _) = self.kind() {
1698 tys
1699 } else {
1700 tracked_span_bug!("expected tuple found `{self:?}` (kind: `{:?}`)", self.kind())
1701 }
1702 }
1703
1704 pub fn simplify_type(&self) -> Option<SimplifiedType> {
1705 self.as_bty_skipping_existentials()
1706 .and_then(BaseTy::simplify_type)
1707 }
1708}
1709
1710impl<'tcx> ToRustc<'tcx> for Ty {
1711 type T = rustc_middle::ty::Ty<'tcx>;
1712
1713 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
1714 match self.kind() {
1715 TyKind::Indexed(bty, _) => bty.to_rustc(tcx),
1716 TyKind::Exists(ty) => ty.skip_binder_ref().to_rustc(tcx),
1717 TyKind::Constr(_, ty) => ty.to_rustc(tcx),
1718 TyKind::Param(pty) => pty.to_ty(tcx),
1719 TyKind::StrgRef(re, _, ty) => {
1720 rustc_middle::ty::Ty::new_ref(
1721 tcx,
1722 re.to_rustc(tcx),
1723 ty.to_rustc(tcx),
1724 Mutability::Mut,
1725 )
1726 }
1727 TyKind::Infer(vid) => rustc_middle::ty::Ty::new_var(tcx, *vid),
1728 TyKind::Uninit
1729 | TyKind::Ptr(_, _)
1730 | TyKind::Discr(..)
1731 | TyKind::Downcast(..)
1732 | TyKind::Blocked(_) => bug!("TODO: to_rustc for `{self:?}`"),
1733 }
1734 }
1735}
1736
1737#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
1738pub enum TyKind {
1739 Indexed(BaseTy, Expr),
1740 Exists(Binder<Ty>),
1741 Constr(Expr, Ty),
1742 Uninit,
1743 StrgRef(Region, Path, Ty),
1744 Ptr(PtrKind, Path),
1745 Discr(AdtDef, Place),
1754 Param(ParamTy),
1755 Downcast(AdtDef, GenericArgs, Ty, VariantIdx, List<Ty>),
1756 Blocked(Ty),
1757 Infer(TyVid),
1761}
1762
1763#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1764pub enum PtrKind {
1765 Mut(Region),
1766 Box,
1767}
1768
1769#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1770pub enum BaseTy {
1771 Int(IntTy),
1772 Uint(UintTy),
1773 Bool,
1774 Str,
1775 Char,
1776 Slice(Ty),
1777 Adt(AdtDef, GenericArgs),
1778 Float(FloatTy),
1779 RawPtr(Ty, Mutability),
1780 RawPtrMetadata(Ty),
1781 Ref(Region, Ty, Mutability),
1782 FnPtr(PolyFnSig),
1783 FnDef(DefId, GenericArgs),
1784 Tuple(List<Ty>),
1785 Alias(AliasKind, AliasTy),
1786 Array(Ty, Const),
1787 Never,
1788 Closure(DefId, List<Ty>, flux_rustc_bridge::ty::GenericArgs),
1789 Coroutine(DefId, Ty, List<Ty>),
1790 Dynamic(List<Binder<ExistentialPredicate>>, Region),
1791 Param(ParamTy),
1792 Infer(TyVid),
1793 Foreign(DefId),
1794}
1795
1796impl BaseTy {
1797 pub fn opaque(alias_ty: AliasTy) -> BaseTy {
1798 BaseTy::Alias(AliasKind::Opaque, alias_ty)
1799 }
1800
1801 pub fn projection(alias_ty: AliasTy) -> BaseTy {
1802 BaseTy::Alias(AliasKind::Projection, alias_ty)
1803 }
1804
1805 pub fn adt(adt_def: AdtDef, args: GenericArgs) -> BaseTy {
1806 BaseTy::Adt(adt_def, args)
1807 }
1808
1809 pub fn fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> BaseTy {
1810 BaseTy::FnDef(def_id, args.into())
1811 }
1812
1813 pub fn from_primitive_str(s: &str) -> Option<BaseTy> {
1814 match s {
1815 "i8" => Some(BaseTy::Int(IntTy::I8)),
1816 "i16" => Some(BaseTy::Int(IntTy::I16)),
1817 "i32" => Some(BaseTy::Int(IntTy::I32)),
1818 "i64" => Some(BaseTy::Int(IntTy::I64)),
1819 "i128" => Some(BaseTy::Int(IntTy::I128)),
1820 "u8" => Some(BaseTy::Uint(UintTy::U8)),
1821 "u16" => Some(BaseTy::Uint(UintTy::U16)),
1822 "u32" => Some(BaseTy::Uint(UintTy::U32)),
1823 "u64" => Some(BaseTy::Uint(UintTy::U64)),
1824 "u128" => Some(BaseTy::Uint(UintTy::U128)),
1825 "f16" => Some(BaseTy::Float(FloatTy::F16)),
1826 "f32" => Some(BaseTy::Float(FloatTy::F32)),
1827 "f64" => Some(BaseTy::Float(FloatTy::F64)),
1828 "f128" => Some(BaseTy::Float(FloatTy::F128)),
1829 "isize" => Some(BaseTy::Int(IntTy::Isize)),
1830 "usize" => Some(BaseTy::Uint(UintTy::Usize)),
1831 "bool" => Some(BaseTy::Bool),
1832 "char" => Some(BaseTy::Char),
1833 "str" => Some(BaseTy::Str),
1834 _ => None,
1835 }
1836 }
1837
1838 pub fn primitive_symbol(&self) -> Option<Symbol> {
1840 match self {
1841 BaseTy::Bool => Some(sym::bool),
1842 BaseTy::Char => Some(sym::char),
1843 BaseTy::Float(f) => {
1844 match f {
1845 FloatTy::F16 => Some(sym::f16),
1846 FloatTy::F32 => Some(sym::f32),
1847 FloatTy::F64 => Some(sym::f64),
1848 FloatTy::F128 => Some(sym::f128),
1849 }
1850 }
1851 BaseTy::Int(f) => {
1852 match f {
1853 IntTy::Isize => Some(sym::isize),
1854 IntTy::I8 => Some(sym::i8),
1855 IntTy::I16 => Some(sym::i16),
1856 IntTy::I32 => Some(sym::i32),
1857 IntTy::I64 => Some(sym::i64),
1858 IntTy::I128 => Some(sym::i128),
1859 }
1860 }
1861 BaseTy::Uint(f) => {
1862 match f {
1863 UintTy::Usize => Some(sym::usize),
1864 UintTy::U8 => Some(sym::u8),
1865 UintTy::U16 => Some(sym::u16),
1866 UintTy::U32 => Some(sym::u32),
1867 UintTy::U64 => Some(sym::u64),
1868 UintTy::U128 => Some(sym::u128),
1869 }
1870 }
1871 BaseTy::Str => Some(sym::str),
1872 _ => None,
1873 }
1874 }
1875
1876 pub fn is_integral(&self) -> bool {
1877 matches!(self, BaseTy::Int(_) | BaseTy::Uint(_))
1878 }
1879
1880 pub fn is_signed(&self) -> bool {
1881 matches!(self, BaseTy::Int(_))
1882 }
1883
1884 pub fn is_unsigned(&self) -> bool {
1885 matches!(self, BaseTy::Uint(_))
1886 }
1887
1888 pub fn is_float(&self) -> bool {
1889 matches!(self, BaseTy::Float(_))
1890 }
1891
1892 pub fn is_bool(&self) -> bool {
1893 matches!(self, BaseTy::Bool)
1894 }
1895
1896 fn is_struct(&self) -> bool {
1897 matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_struct())
1898 }
1899
1900 fn is_array(&self) -> bool {
1901 matches!(self, BaseTy::Array(..))
1902 }
1903
1904 fn is_slice(&self) -> bool {
1905 matches!(self, BaseTy::Slice(..))
1906 }
1907
1908 pub fn is_box(&self) -> bool {
1909 matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_box())
1910 }
1911
1912 pub fn is_char(&self) -> bool {
1913 matches!(self, BaseTy::Char)
1914 }
1915
1916 pub fn is_str(&self) -> bool {
1917 matches!(self, BaseTy::Str)
1918 }
1919
1920 pub fn invariants(
1921 &self,
1922 tcx: TyCtxt,
1923 overflow_mode: OverflowMode,
1924 ) -> impl Iterator<Item = Invariant> {
1925 let (invariants, args) = match self {
1926 BaseTy::Adt(adt_def, args) => (adt_def.invariants().skip_binder(), &args[..]),
1927 BaseTy::Uint(uint_ty) => (uint_invariants(*uint_ty, overflow_mode), &[][..]),
1928 BaseTy::Int(int_ty) => (int_invariants(*int_ty, overflow_mode), &[][..]),
1929 BaseTy::Char => (char_invariants(), &[][..]),
1930 BaseTy::Slice(_) => (slice_invariants(overflow_mode), &[][..]),
1931 _ => (&[][..], &[][..]),
1932 };
1933 invariants
1934 .iter()
1935 .map(move |inv| EarlyBinder(inv).instantiate_ref(tcx, args, &[]))
1936 }
1937
1938 pub fn to_ty(&self) -> Ty {
1939 let sort = self.sort();
1940 if sort.is_unit() {
1941 Ty::indexed(self.clone(), Expr::unit())
1942 } else {
1943 Ty::exists(Binder::bind_with_sort(
1944 Ty::indexed(self.shift_in_escaping(1), Expr::nu()),
1945 sort,
1946 ))
1947 }
1948 }
1949
1950 pub fn to_subset_ty_ctor(&self) -> SubsetTyCtor {
1951 let sort = self.sort();
1952 Binder::bind_with_sort(SubsetTy::trivial(self.clone(), Expr::nu()), sort)
1953 }
1954
1955 #[track_caller]
1956 pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg]) {
1957 if let BaseTy::Adt(adt_def, args) = self {
1958 (adt_def, args)
1959 } else {
1960 tracked_span_bug!("expected adt `{self:?}`")
1961 }
1962 }
1963
1964 pub fn is_atom(&self) -> bool {
1967 matches!(
1969 self,
1970 BaseTy::Int(_)
1971 | BaseTy::Uint(_)
1972 | BaseTy::Slice(_)
1973 | BaseTy::Bool
1974 | BaseTy::Char
1975 | BaseTy::Str
1976 | BaseTy::Adt(..)
1977 | BaseTy::Tuple(..)
1978 | BaseTy::Param(_)
1979 | BaseTy::Array(..)
1980 | BaseTy::Never
1981 | BaseTy::Closure(..)
1982 | BaseTy::Coroutine(..)
1983 | BaseTy::Alias(..)
1986 )
1987 }
1988
1989 fn simplify_type(&self) -> Option<SimplifiedType> {
1997 match self {
1998 BaseTy::Bool => Some(SimplifiedType::Bool),
1999 BaseTy::Char => Some(SimplifiedType::Char),
2000 BaseTy::Int(int_type) => Some(SimplifiedType::Int(*int_type)),
2001 BaseTy::Uint(uint_type) => Some(SimplifiedType::Uint(*uint_type)),
2002 BaseTy::Float(float_type) => Some(SimplifiedType::Float(*float_type)),
2003 BaseTy::Adt(def, _) => Some(SimplifiedType::Adt(def.did())),
2004 BaseTy::Str => Some(SimplifiedType::Str),
2005 BaseTy::Array(..) => Some(SimplifiedType::Array),
2006 BaseTy::Slice(..) => Some(SimplifiedType::Slice),
2007 BaseTy::RawPtr(_, mutbl) => Some(SimplifiedType::Ptr(*mutbl)),
2008 BaseTy::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(*mutbl)),
2009 BaseTy::FnDef(def_id, _) | BaseTy::Closure(def_id, ..) => {
2010 Some(SimplifiedType::Closure(*def_id))
2011 }
2012 BaseTy::Coroutine(def_id, ..) => Some(SimplifiedType::Coroutine(*def_id)),
2013 BaseTy::Never => Some(SimplifiedType::Never),
2014 BaseTy::Tuple(tys) => Some(SimplifiedType::Tuple(tys.len())),
2015 BaseTy::FnPtr(poly_fn_sig) => {
2016 Some(SimplifiedType::Function(poly_fn_sig.skip_binder_ref().inputs().len()))
2017 }
2018 BaseTy::Foreign(def_id) => Some(SimplifiedType::Foreign(*def_id)),
2019 BaseTy::RawPtrMetadata(_)
2020 | BaseTy::Alias(..)
2021 | BaseTy::Param(_)
2022 | BaseTy::Dynamic(..)
2023 | BaseTy::Infer(_) => None,
2024 }
2025 }
2026}
2027
2028impl<'tcx> ToRustc<'tcx> for BaseTy {
2029 type T = rustc_middle::ty::Ty<'tcx>;
2030
2031 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2032 use rustc_middle::ty;
2033 match self {
2034 BaseTy::Int(i) => ty::Ty::new_int(tcx, *i),
2035 BaseTy::Uint(i) => ty::Ty::new_uint(tcx, *i),
2036 BaseTy::Param(pty) => pty.to_ty(tcx),
2037 BaseTy::Slice(ty) => ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
2038 BaseTy::Bool => tcx.types.bool,
2039 BaseTy::Char => tcx.types.char,
2040 BaseTy::Str => tcx.types.str_,
2041 BaseTy::Adt(adt_def, args) => {
2042 let did = adt_def.did();
2043 let adt_def = tcx.adt_def(did);
2044 let args = args.to_rustc(tcx);
2045 ty::Ty::new_adt(tcx, adt_def, args)
2046 }
2047 BaseTy::FnDef(def_id, args) => {
2048 let args = args.to_rustc(tcx);
2049 ty::Ty::new_fn_def(tcx, *def_id, args)
2050 }
2051 BaseTy::Float(f) => ty::Ty::new_float(tcx, *f),
2052 BaseTy::RawPtr(ty, mutbl) => ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
2053 BaseTy::Ref(re, ty, mutbl) => {
2054 ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
2055 }
2056 BaseTy::FnPtr(poly_sig) => ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
2057 BaseTy::Tuple(tys) => {
2058 let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
2059 ty::Ty::new_tup(tcx, &ts)
2060 }
2061 BaseTy::Alias(kind, alias_ty) => {
2062 ty::Ty::new_alias(tcx, kind.to_rustc(tcx), alias_ty.to_rustc(tcx))
2063 }
2064 BaseTy::Array(ty, n) => {
2065 let ty = ty.to_rustc(tcx);
2066 let n = n.to_rustc(tcx);
2067 ty::Ty::new_array_with_const_len(tcx, ty, n)
2068 }
2069 BaseTy::Never => tcx.types.never,
2070 BaseTy::Closure(did, _, args) => ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
2071 BaseTy::Dynamic(exi_preds, re) => {
2072 let preds: Vec<_> = exi_preds
2073 .iter()
2074 .map(|pred| pred.to_rustc(tcx))
2075 .collect_vec();
2076 let preds = tcx.mk_poly_existential_predicates(&preds);
2077 ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx))
2078 }
2079 BaseTy::Coroutine(def_id, resume_ty, upvars) => {
2080 bug!("TODO: Generator {def_id:?} {resume_ty:?} {upvars:?}")
2081 }
2085 BaseTy::Infer(ty_vid) => ty::Ty::new_var(tcx, *ty_vid),
2086 BaseTy::Foreign(def_id) => ty::Ty::new_foreign(tcx, *def_id),
2087 BaseTy::RawPtrMetadata(ty) => {
2088 ty::Ty::new_ptr(
2089 tcx,
2090 ty.to_rustc(tcx),
2091 RawPtrKind::FakeForPtrMetadata.to_mutbl_lossy(),
2092 )
2093 }
2094 }
2095 }
2096}
2097
2098#[derive(
2099 Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
2100)]
2101pub struct AliasTy {
2102 pub def_id: DefId,
2103 pub args: GenericArgs,
2104 pub refine_args: RefineArgs,
2106}
2107
2108impl AliasTy {
2109 pub fn new(def_id: DefId, args: GenericArgs, refine_args: RefineArgs) -> Self {
2110 AliasTy { args, refine_args, def_id }
2111 }
2112}
2113
2114impl AliasTy {
2116 pub fn self_ty(&self) -> SubsetTyCtor {
2117 self.args[0].expect_base().clone()
2118 }
2119
2120 pub fn with_self_ty(&self, self_ty: SubsetTyCtor) -> Self {
2121 Self {
2122 def_id: self.def_id,
2123 args: [GenericArg::Base(self_ty)]
2124 .into_iter()
2125 .chain(self.args.iter().skip(1).cloned())
2126 .collect(),
2127 refine_args: self.refine_args.clone(),
2128 }
2129 }
2130}
2131
2132impl<'tcx> ToRustc<'tcx> for AliasTy {
2133 type T = rustc_middle::ty::AliasTy<'tcx>;
2134
2135 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2136 rustc_middle::ty::AliasTy::new(tcx, self.def_id, self.args.to_rustc(tcx))
2137 }
2138}
2139
2140pub type RefineArgs = List<Expr>;
2141
2142#[extension(pub trait RefineArgsExt)]
2143impl RefineArgs {
2144 fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<RefineArgs> {
2145 Self::for_item(genv, def_id, |param, index| {
2146 Ok(Expr::var(Var::EarlyParam(EarlyReftParam {
2147 index: index as u32,
2148 name: param.name(),
2149 })))
2150 })
2151 }
2152
2153 fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk: F) -> QueryResult<RefineArgs>
2154 where
2155 F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<Expr>,
2156 {
2157 let reft_generics = genv.refinement_generics_of(def_id)?;
2158 let count = reft_generics.count();
2159 let mut args = Vec::with_capacity(count);
2160 reft_generics.fill_item(genv, &mut args, &mut mk)?;
2161 Ok(List::from_vec(args))
2162 }
2163}
2164
2165pub type SubsetTyCtor = Binder<SubsetTy>;
2172
2173impl SubsetTyCtor {
2174 pub fn as_bty_skipping_binder(&self) -> &BaseTy {
2175 &self.as_ref().skip_binder().bty
2176 }
2177
2178 pub fn to_ty(&self) -> Ty {
2179 let sort = self.sort();
2180 if sort.is_unit() {
2181 self.replace_bound_reft(&Expr::unit()).to_ty()
2182 } else if let Some(def_id) = sort.is_unit_adt() {
2183 self.replace_bound_reft(&Expr::unit_struct(def_id)).to_ty()
2184 } else {
2185 Ty::exists(self.as_ref().map(SubsetTy::to_ty))
2186 }
2187 }
2188
2189 pub fn to_ty_ctor(&self) -> TyCtor {
2190 self.as_ref().map(SubsetTy::to_ty)
2191 }
2192}
2193
2194#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
2238pub struct SubsetTy {
2239 pub bty: BaseTy,
2246 pub idx: Expr,
2250 pub pred: Expr,
2252}
2253
2254impl SubsetTy {
2255 pub fn new(bty: BaseTy, idx: impl Into<Expr>, pred: impl Into<Expr>) -> Self {
2256 Self { bty, idx: idx.into(), pred: pred.into() }
2257 }
2258
2259 pub fn trivial(bty: BaseTy, idx: impl Into<Expr>) -> Self {
2260 Self::new(bty, idx, Expr::tt())
2261 }
2262
2263 pub fn strengthen(&self, pred: impl Into<Expr>) -> Self {
2264 let this = self.clone();
2265 let pred = Expr::and(this.pred, pred).simplify(&SnapshotMap::default());
2266 Self { bty: this.bty, idx: this.idx, pred }
2267 }
2268
2269 pub fn to_ty(&self) -> Ty {
2270 let bty = self.bty.clone();
2271 if self.pred.is_trivially_true() {
2272 Ty::indexed(bty, &self.idx)
2273 } else {
2274 Ty::constr(&self.pred, Ty::indexed(bty, &self.idx))
2275 }
2276 }
2277}
2278
2279impl<'tcx> ToRustc<'tcx> for SubsetTy {
2280 type T = rustc_middle::ty::Ty<'tcx>;
2281
2282 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
2283 self.bty.to_rustc(tcx)
2284 }
2285}
2286
2287#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
2288pub enum GenericArg {
2289 Ty(Ty),
2290 Base(SubsetTyCtor),
2291 Lifetime(Region),
2292 Const(Const),
2293}
2294
2295impl GenericArg {
2296 #[track_caller]
2297 pub fn expect_type(&self) -> &Ty {
2298 if let GenericArg::Ty(ty) = self {
2299 ty
2300 } else {
2301 bug!("expected `rty::GenericArg::Ty`, found `{self:?}`")
2302 }
2303 }
2304
2305 #[track_caller]
2306 pub fn expect_base(&self) -> &SubsetTyCtor {
2307 if let GenericArg::Base(ctor) = self {
2308 ctor
2309 } else {
2310 bug!("expected `rty::GenericArg::Base`, found `{self:?}`")
2311 }
2312 }
2313
2314 pub fn from_param_def(param: &GenericParamDef) -> Self {
2315 match param.kind {
2316 GenericParamDefKind::Type { .. } => {
2317 let param_ty = ParamTy { index: param.index, name: param.name };
2318 GenericArg::Ty(Ty::param(param_ty))
2319 }
2320 GenericParamDefKind::Base { .. } => {
2321 let param_ty = ParamTy { index: param.index, name: param.name };
2323 GenericArg::Base(Binder::bind_with_sort(
2324 SubsetTy::trivial(BaseTy::Param(param_ty), Expr::nu()),
2325 Sort::Param(param_ty),
2326 ))
2327 }
2328 GenericParamDefKind::Lifetime => {
2329 let region = EarlyParamRegion { index: param.index, name: param.name };
2330 GenericArg::Lifetime(Region::ReEarlyParam(region))
2331 }
2332 GenericParamDefKind::Const { .. } => {
2333 let param_const = ParamConst { index: param.index, name: param.name };
2334 let kind = ConstKind::Param(param_const);
2335 GenericArg::Const(Const { kind })
2336 }
2337 }
2338 }
2339
2340 pub fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk_kind: F) -> QueryResult<GenericArgs>
2344 where
2345 F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2346 {
2347 let defs = genv.generics_of(def_id)?;
2348 let count = defs.count();
2349 let mut args = Vec::with_capacity(count);
2350 Self::fill_item(genv, &mut args, &defs, &mut mk_kind)?;
2351 Ok(List::from_vec(args))
2352 }
2353
2354 pub fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<GenericArgs> {
2355 Self::for_item(genv, def_id, |param, _| GenericArg::from_param_def(param))
2356 }
2357
2358 fn fill_item<F>(
2359 genv: GlobalEnv,
2360 args: &mut Vec<GenericArg>,
2361 generics: &Generics,
2362 mk_kind: &mut F,
2363 ) -> QueryResult<()>
2364 where
2365 F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2366 {
2367 if let Some(def_id) = generics.parent {
2368 let parent_generics = genv.generics_of(def_id)?;
2369 Self::fill_item(genv, args, &parent_generics, mk_kind)?;
2370 }
2371 for param in &generics.own_params {
2372 let kind = mk_kind(param, args);
2373 tracked_span_assert_eq!(param.index as usize, args.len());
2374 args.push(kind);
2375 }
2376 Ok(())
2377 }
2378}
2379
2380impl From<TyOrBase> for GenericArg {
2381 fn from(v: TyOrBase) -> Self {
2382 match v {
2383 TyOrBase::Ty(ty) => GenericArg::Ty(ty),
2384 TyOrBase::Base(ctor) => GenericArg::Base(ctor),
2385 }
2386 }
2387}
2388
2389impl<'tcx> ToRustc<'tcx> for GenericArg {
2390 type T = rustc_middle::ty::GenericArg<'tcx>;
2391
2392 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2393 use rustc_middle::ty;
2394 match self {
2395 GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
2396 GenericArg::Base(ctor) => ty::GenericArg::from(ctor.skip_binder_ref().to_rustc(tcx)),
2397 GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
2398 GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
2399 }
2400 }
2401}
2402
2403pub type GenericArgs = List<GenericArg>;
2404
2405#[extension(pub trait GenericArgsExt)]
2406impl GenericArgs {
2407 #[track_caller]
2408 fn box_args(&self) -> (&Ty, &Ty) {
2409 if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
2410 (deref, alloc)
2411 } else {
2412 bug!("invalid generic arguments for box");
2413 }
2414 }
2415
2416 fn to_rustc<'tcx>(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::GenericArgsRef<'tcx> {
2418 tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
2419 }
2420
2421 fn rebase_onto(
2422 &self,
2423 tcx: &TyCtxt,
2424 source_ancestor: DefId,
2425 target_args: &GenericArgs,
2426 ) -> List<GenericArg> {
2427 let defs = tcx.generics_of(source_ancestor);
2428 target_args
2429 .iter()
2430 .chain(self.iter().skip(defs.count()))
2431 .cloned()
2432 .collect()
2433 }
2434}
2435
2436#[derive(Debug)]
2437pub enum TyOrBase {
2438 Ty(Ty),
2439 Base(SubsetTyCtor),
2440}
2441
2442impl TyOrBase {
2443 pub fn into_ty(self) -> Ty {
2444 match self {
2445 TyOrBase::Ty(ty) => ty,
2446 TyOrBase::Base(ctor) => ctor.to_ty(),
2447 }
2448 }
2449
2450 #[track_caller]
2451 pub fn expect_base(self) -> SubsetTyCtor {
2452 match self {
2453 TyOrBase::Base(ctor) => ctor,
2454 TyOrBase::Ty(_) => tracked_span_bug!("expected `TyOrBase::Base`"),
2455 }
2456 }
2457
2458 pub fn as_base(self) -> Option<SubsetTyCtor> {
2459 match self {
2460 TyOrBase::Base(ctor) => Some(ctor),
2461 TyOrBase::Ty(_) => None,
2462 }
2463 }
2464}
2465
2466#[derive(Debug, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
2467pub enum TyOrCtor {
2468 Ty(Ty),
2469 Ctor(TyCtor),
2470}
2471
2472impl TyOrCtor {
2473 #[track_caller]
2474 pub fn expect_ctor(self) -> TyCtor {
2475 match self {
2476 TyOrCtor::Ctor(ctor) => ctor,
2477 TyOrCtor::Ty(_) => tracked_span_bug!("expected `TyOrCtor::Ctor`"),
2478 }
2479 }
2480
2481 pub fn expect_subset_ty_ctor(self) -> SubsetTyCtor {
2482 self.expect_ctor().map(|ty| {
2483 if let canonicalize::CanonicalTy::Constr(constr_ty) = ty.shallow_canonicalize()
2484 && let TyKind::Indexed(bty, idx) = constr_ty.ty().kind()
2485 && idx.is_nu()
2486 {
2487 SubsetTy::new(bty.clone(), Expr::nu(), constr_ty.pred())
2488 } else {
2489 tracked_span_bug!()
2490 }
2491 })
2492 }
2493
2494 pub fn to_ty(&self) -> Ty {
2495 match self {
2496 TyOrCtor::Ctor(ctor) => ctor.to_ty(),
2497 TyOrCtor::Ty(ty) => ty.clone(),
2498 }
2499 }
2500}
2501
2502impl From<TyOrBase> for TyOrCtor {
2503 fn from(v: TyOrBase) -> Self {
2504 match v {
2505 TyOrBase::Ty(ty) => TyOrCtor::Ty(ty),
2506 TyOrBase::Base(ctor) => TyOrCtor::Ctor(ctor.to_ty_ctor()),
2507 }
2508 }
2509}
2510
2511impl CoroutineObligPredicate {
2512 pub fn to_poly_fn_sig(&self) -> PolyFnSig {
2513 let vars = vec![];
2514
2515 let resume_ty = &self.resume_ty;
2516 let env_ty = Ty::coroutine(self.def_id, resume_ty.clone(), self.upvar_tys.clone());
2517
2518 let inputs = List::from_arr([env_ty, resume_ty.clone()]);
2519 let output =
2520 Binder::bind_with_vars(FnOutput::new(self.output.clone(), vec![]), List::empty());
2521
2522 PolyFnSig::bind_with_vars(
2523 FnSig::new(Safety::Safe, rustc_abi::ExternAbi::RustCall, List::empty(), inputs, output),
2524 List::from(vars),
2525 )
2526 }
2527}
2528
2529impl RefinementGenerics {
2530 pub fn count(&self) -> usize {
2531 self.parent_count + self.own_params.len()
2532 }
2533
2534 pub fn own_count(&self) -> usize {
2535 self.own_params.len()
2536 }
2537}
2538
2539impl EarlyBinder<RefinementGenerics> {
2540 pub fn parent(&self) -> Option<DefId> {
2541 self.skip_binder_ref().parent
2542 }
2543
2544 pub fn parent_count(&self) -> usize {
2545 self.skip_binder_ref().parent_count
2546 }
2547
2548 pub fn count(&self) -> usize {
2549 self.skip_binder_ref().count()
2550 }
2551
2552 pub fn own_count(&self) -> usize {
2553 self.skip_binder_ref().own_count()
2554 }
2555
2556 pub fn own_param_at(&self, index: usize) -> EarlyBinder<RefineParam> {
2557 self.as_ref().map(|this| this.own_params[index].clone())
2558 }
2559
2560 pub fn param_at(
2561 &self,
2562 param_index: usize,
2563 genv: GlobalEnv,
2564 ) -> QueryResult<EarlyBinder<RefineParam>> {
2565 if let Some(index) = param_index.checked_sub(self.parent_count()) {
2566 Ok(self.own_param_at(index))
2567 } else {
2568 let parent = self.parent().expect("parent_count > 0 but no parent?");
2569 genv.refinement_generics_of(parent)?
2570 .param_at(param_index, genv)
2571 }
2572 }
2573
2574 pub fn iter_own_params(&self) -> impl Iterator<Item = EarlyBinder<RefineParam>> + use<'_> {
2575 self.skip_binder_ref()
2576 .own_params
2577 .iter()
2578 .cloned()
2579 .map(EarlyBinder)
2580 }
2581
2582 pub fn fill_item<F, R>(&self, genv: GlobalEnv, vec: &mut Vec<R>, mk: &mut F) -> QueryResult
2583 where
2584 F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<R>,
2585 {
2586 if let Some(def_id) = self.parent() {
2587 genv.refinement_generics_of(def_id)?
2588 .fill_item(genv, vec, mk)?;
2589 }
2590 for param in self.iter_own_params() {
2591 vec.push(mk(param, vec.len())?);
2592 }
2593 Ok(())
2594 }
2595}
2596
2597impl EarlyBinder<GenericPredicates> {
2598 pub fn predicates(&self) -> EarlyBinder<List<Clause>> {
2599 EarlyBinder(self.0.predicates.clone())
2600 }
2601}
2602
2603impl EarlyBinder<FuncSort> {
2604 pub fn instantiate_func_sort<E>(
2606 self,
2607 sort_for_param: impl FnMut(ParamTy) -> Result<Sort, E>,
2608 ) -> Result<FuncSort, E> {
2609 self.0.try_fold_with(&mut subst::GenericsSubstFolder::new(
2610 subst::GenericsSubstForSort { sort_for_param },
2611 &[],
2612 ))
2613 }
2614}
2615
2616impl VariantSig {
2617 pub fn new(
2618 adt_def: AdtDef,
2619 args: GenericArgs,
2620 fields: List<Ty>,
2621 idx: Expr,
2622 requires: List<Expr>,
2623 ) -> Self {
2624 VariantSig { adt_def, args, fields, idx, requires }
2625 }
2626
2627 pub fn fields(&self) -> &[Ty] {
2628 &self.fields
2629 }
2630
2631 pub fn ret(&self) -> Ty {
2632 let bty = BaseTy::Adt(self.adt_def.clone(), self.args.clone());
2633 let idx = self.idx.clone();
2634 Ty::indexed(bty, idx)
2635 }
2636}
2637
2638impl FnSig {
2639 pub fn new(
2640 safety: Safety,
2641 abi: rustc_abi::ExternAbi,
2642 requires: List<Expr>,
2643 inputs: List<Ty>,
2644 output: Binder<FnOutput>,
2645 ) -> Self {
2646 FnSig { safety, abi, requires, inputs, output }
2647 }
2648
2649 pub fn requires(&self) -> &[Expr] {
2650 &self.requires
2651 }
2652
2653 pub fn inputs(&self) -> &[Ty] {
2654 &self.inputs
2655 }
2656
2657 pub fn output(&self) -> Binder<FnOutput> {
2658 self.output.clone()
2659 }
2660}
2661
2662impl<'tcx> ToRustc<'tcx> for FnSig {
2663 type T = rustc_middle::ty::FnSig<'tcx>;
2664
2665 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2666 tcx.mk_fn_sig(
2667 self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
2668 self.output().as_ref().skip_binder().to_rustc(tcx),
2669 false,
2670 self.safety,
2671 self.abi,
2672 )
2673 }
2674}
2675
2676impl FnOutput {
2677 pub fn new(ret: Ty, ensures: impl Into<List<Ensures>>) -> Self {
2678 Self { ret, ensures: ensures.into() }
2679 }
2680}
2681
2682impl<'tcx> ToRustc<'tcx> for FnOutput {
2683 type T = rustc_middle::ty::Ty<'tcx>;
2684
2685 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2686 self.ret.to_rustc(tcx)
2687 }
2688}
2689
2690impl AdtDef {
2691 pub fn new(
2692 rustc: ty::AdtDef,
2693 sort_def: AdtSortDef,
2694 invariants: Vec<Invariant>,
2695 opaque: bool,
2696 ) -> Self {
2697 AdtDef(Interned::new(AdtDefData { invariants, sort_def, opaque, rustc }))
2698 }
2699
2700 pub fn did(&self) -> DefId {
2701 self.0.rustc.did()
2702 }
2703
2704 pub fn sort_def(&self) -> &AdtSortDef {
2705 &self.0.sort_def
2706 }
2707
2708 pub fn sort(&self, args: &[GenericArg]) -> Sort {
2709 self.sort_def().to_sort(args)
2710 }
2711
2712 pub fn is_box(&self) -> bool {
2713 self.0.rustc.is_box()
2714 }
2715
2716 pub fn is_enum(&self) -> bool {
2717 self.0.rustc.is_enum()
2718 }
2719
2720 pub fn is_struct(&self) -> bool {
2721 self.0.rustc.is_struct()
2722 }
2723
2724 pub fn is_union(&self) -> bool {
2725 self.0.rustc.is_union()
2726 }
2727
2728 pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
2729 self.0.rustc.variants()
2730 }
2731
2732 pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
2733 self.0.rustc.variant(idx)
2734 }
2735
2736 pub fn invariants(&self) -> EarlyBinder<&[Invariant]> {
2737 EarlyBinder(&self.0.invariants)
2738 }
2739
2740 pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
2741 self.0.rustc.discriminants()
2742 }
2743
2744 pub fn is_opaque(&self) -> bool {
2745 self.0.opaque
2746 }
2747}
2748
2749impl EarlyBinder<PolyVariant> {
2750 pub fn to_poly_fn_sig(&self, field_idx: Option<crate::FieldIdx>) -> EarlyBinder<PolyFnSig> {
2753 self.as_ref().map(|poly_variant| {
2754 poly_variant.as_ref().map(|variant| {
2755 let ret = variant.ret().shift_in_escaping(1);
2756 let output = Binder::bind_with_vars(FnOutput::new(ret, vec![]), List::empty());
2757 let inputs = match field_idx {
2758 None => variant.fields.clone(),
2759 Some(i) => List::singleton(variant.fields[i.index()].clone()),
2760 };
2761 FnSig::new(
2762 Safety::Safe,
2763 rustc_abi::ExternAbi::Rust,
2764 variant.requires.clone(),
2765 inputs,
2766 output,
2767 )
2768 })
2769 })
2770 }
2771}
2772
2773impl TyKind {
2774 fn intern(self) -> Ty {
2775 Ty(Interned::new(self))
2776 }
2777}
2778
2779fn slice_invariants(overflow_mode: OverflowMode) -> &'static [Invariant] {
2781 static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2782 [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2783 });
2784 static OVERFLOW: LazyLock<[Invariant; 2]> = LazyLock::new(|| {
2785 [
2786 Invariant {
2787 pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2788 },
2789 Invariant {
2790 pred: Binder::bind_with_sort(
2791 Expr::le(Expr::nu(), Expr::uint_max(UintTy::Usize)),
2792 Sort::Int,
2793 ),
2794 },
2795 ]
2796 });
2797 if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2798 &*OVERFLOW
2799 } else {
2800 &*DEFAULT
2801 }
2802}
2803
2804fn uint_invariants(uint_ty: UintTy, overflow_mode: OverflowMode) -> &'static [Invariant] {
2805 static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2806 [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2807 });
2808
2809 static OVERFLOW: LazyLock<UnordMap<UintTy, [Invariant; 2]>> = LazyLock::new(|| {
2810 UINT_TYS
2811 .into_iter()
2812 .map(|uint_ty| {
2813 let invariants = [
2814 Invariant {
2815 pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2816 },
2817 Invariant {
2818 pred: Binder::bind_with_sort(
2819 Expr::le(Expr::nu(), Expr::uint_max(uint_ty)),
2820 Sort::Int,
2821 ),
2822 },
2823 ];
2824 (uint_ty, invariants)
2825 })
2826 .collect()
2827 });
2828 if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2829 &OVERFLOW[&uint_ty]
2830 } else {
2831 &*DEFAULT
2832 }
2833}
2834
2835fn char_invariants() -> &'static [Invariant] {
2836 static INVARIANTS: LazyLock<[Invariant; 2]> = LazyLock::new(|| {
2837 [
2838 Invariant {
2839 pred: Binder::bind_with_sort(
2840 Expr::le(
2841 Expr::cast(Sort::Char, Sort::Int, Expr::nu()),
2842 Expr::constant((char::MAX as u32).into()),
2843 ),
2844 Sort::Int,
2845 ),
2846 },
2847 Invariant {
2848 pred: Binder::bind_with_sort(
2849 Expr::le(Expr::zero(), Expr::cast(Sort::Char, Sort::Int, Expr::nu())),
2850 Sort::Int,
2851 ),
2852 },
2853 ]
2854 });
2855 &*INVARIANTS
2856}
2857
2858fn int_invariants(int_ty: IntTy, overflow_mode: OverflowMode) -> &'static [Invariant] {
2859 static DEFAULT: [Invariant; 0] = [];
2860
2861 static OVERFLOW: LazyLock<UnordMap<IntTy, [Invariant; 2]>> = LazyLock::new(|| {
2862 INT_TYS
2863 .into_iter()
2864 .map(|int_ty| {
2865 let invariants = [
2866 Invariant {
2867 pred: Binder::bind_with_sort(
2868 Expr::ge(Expr::nu(), Expr::int_min(int_ty)),
2869 Sort::Int,
2870 ),
2871 },
2872 Invariant {
2873 pred: Binder::bind_with_sort(
2874 Expr::le(Expr::nu(), Expr::int_max(int_ty)),
2875 Sort::Int,
2876 ),
2877 },
2878 ];
2879 (int_ty, invariants)
2880 })
2881 .collect()
2882 });
2883 if matches!(overflow_mode, OverflowMode::Strict | OverflowMode::Lazy) {
2884 &OVERFLOW[&int_ty]
2885 } else {
2886 &DEFAULT
2887 }
2888}
2889
2890impl_internable!(AdtDefData, AdtSortDefData, TyKind);
2891impl_slice_internable!(
2892 Ty,
2893 GenericArg,
2894 Ensures,
2895 InferMode,
2896 Sort,
2897 SortArg,
2898 GenericParamDef,
2899 TraitRef,
2900 Binder<ExistentialPredicate>,
2901 Clause,
2902 PolyVariant,
2903 Invariant,
2904 RefineParam,
2905 FluxDefId,
2906 SortParamKind,
2907 AssocReft
2908);
2909
2910#[macro_export]
2911macro_rules! _Int {
2912 ($int_ty:pat, $idxs:pat) => {
2913 TyKind::Indexed(BaseTy::Int($int_ty), $idxs)
2914 };
2915}
2916pub use crate::_Int as Int;
2917
2918#[macro_export]
2919macro_rules! _Uint {
2920 ($uint_ty:pat, $idxs:pat) => {
2921 TyKind::Indexed(BaseTy::Uint($uint_ty), $idxs)
2922 };
2923}
2924pub use crate::_Uint as Uint;
2925
2926#[macro_export]
2927macro_rules! _Bool {
2928 ($idxs:pat) => {
2929 TyKind::Indexed(BaseTy::Bool, $idxs)
2930 };
2931}
2932pub use crate::_Bool as Bool;
2933
2934#[macro_export]
2935macro_rules! _Char {
2936 ($idxs:pat) => {
2937 TyKind::Indexed(BaseTy::Char, $idxs)
2938 };
2939}
2940pub use crate::_Char as Char;
2941
2942#[macro_export]
2943macro_rules! _Ref {
2944 ($($pats:pat),+ $(,)?) => {
2945 $crate::rty::TyKind::Indexed($crate::rty::BaseTy::Ref($($pats),+), _)
2946 };
2947}
2948pub use crate::_Ref as Ref;
2949
2950pub struct WfckResults {
2951 pub owner: FluxOwnerId,
2952 param_sorts: UnordMap<fhir::ParamId, Sort>,
2953 bin_op_sorts: ItemLocalMap<Sort>,
2954 fn_app_sorts: ItemLocalMap<List<SortArg>>,
2955 coercions: ItemLocalMap<Vec<Coercion>>,
2956 field_projs: ItemLocalMap<FieldProj>,
2957 node_sorts: ItemLocalMap<Sort>,
2958 record_ctors: ItemLocalMap<DefId>,
2959}
2960
2961#[derive(Clone, Copy, Debug)]
2962pub enum Coercion {
2963 Inject(DefId),
2964 Project(DefId),
2965}
2966
2967pub type ItemLocalMap<T> = UnordMap<fhir::ItemLocalId, T>;
2968
2969#[derive(Debug)]
2970pub struct LocalTableInContext<'a, T> {
2971 owner: FluxOwnerId,
2972 data: &'a ItemLocalMap<T>,
2973}
2974
2975pub struct LocalTableInContextMut<'a, T> {
2976 owner: FluxOwnerId,
2977 data: &'a mut ItemLocalMap<T>,
2978}
2979
2980impl WfckResults {
2981 pub fn new(owner: impl Into<FluxOwnerId>) -> Self {
2982 Self {
2983 owner: owner.into(),
2984 param_sorts: UnordMap::default(),
2985 bin_op_sorts: ItemLocalMap::default(),
2986 coercions: ItemLocalMap::default(),
2987 field_projs: ItemLocalMap::default(),
2988 node_sorts: ItemLocalMap::default(),
2989 record_ctors: ItemLocalMap::default(),
2990 fn_app_sorts: ItemLocalMap::default(),
2991 }
2992 }
2993
2994 pub fn param_sorts_mut(&mut self) -> &mut UnordMap<fhir::ParamId, Sort> {
2995 &mut self.param_sorts
2996 }
2997
2998 pub fn param_sorts(&self) -> &UnordMap<fhir::ParamId, Sort> {
2999 &self.param_sorts
3000 }
3001
3002 pub fn bin_op_sorts_mut(&mut self) -> LocalTableInContextMut<'_, Sort> {
3003 LocalTableInContextMut { owner: self.owner, data: &mut self.bin_op_sorts }
3004 }
3005
3006 pub fn fn_app_sorts_mut(&mut self) -> LocalTableInContextMut<'_, List<SortArg>> {
3007 LocalTableInContextMut { owner: self.owner, data: &mut self.fn_app_sorts }
3008 }
3009
3010 pub fn fn_app_sorts(&self) -> LocalTableInContext<'_, List<SortArg>> {
3011 LocalTableInContext { owner: self.owner, data: &self.fn_app_sorts }
3012 }
3013
3014 pub fn bin_op_sorts(&self) -> LocalTableInContext<'_, Sort> {
3015 LocalTableInContext { owner: self.owner, data: &self.bin_op_sorts }
3016 }
3017
3018 pub fn coercions_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Coercion>> {
3019 LocalTableInContextMut { owner: self.owner, data: &mut self.coercions }
3020 }
3021
3022 pub fn coercions(&self) -> LocalTableInContext<'_, Vec<Coercion>> {
3023 LocalTableInContext { owner: self.owner, data: &self.coercions }
3024 }
3025
3026 pub fn field_projs_mut(&mut self) -> LocalTableInContextMut<'_, FieldProj> {
3027 LocalTableInContextMut { owner: self.owner, data: &mut self.field_projs }
3028 }
3029
3030 pub fn field_projs(&self) -> LocalTableInContext<'_, FieldProj> {
3031 LocalTableInContext { owner: self.owner, data: &self.field_projs }
3032 }
3033
3034 pub fn node_sorts_mut(&mut self) -> LocalTableInContextMut<'_, Sort> {
3035 LocalTableInContextMut { owner: self.owner, data: &mut self.node_sorts }
3036 }
3037
3038 pub fn node_sorts(&self) -> LocalTableInContext<'_, Sort> {
3039 LocalTableInContext { owner: self.owner, data: &self.node_sorts }
3040 }
3041
3042 pub fn record_ctors_mut(&mut self) -> LocalTableInContextMut<'_, DefId> {
3043 LocalTableInContextMut { owner: self.owner, data: &mut self.record_ctors }
3044 }
3045
3046 pub fn record_ctors(&self) -> LocalTableInContext<'_, DefId> {
3047 LocalTableInContext { owner: self.owner, data: &self.record_ctors }
3048 }
3049}
3050
3051impl<T> LocalTableInContextMut<'_, T> {
3052 pub fn insert(&mut self, fhir_id: FhirId, value: T) {
3053 tracked_span_assert_eq!(self.owner, fhir_id.owner);
3054 self.data.insert(fhir_id.local_id, value);
3055 }
3056}
3057
3058impl<'a, T> LocalTableInContext<'a, T> {
3059 pub fn get(&self, fhir_id: FhirId) -> Option<&'a T> {
3060 tracked_span_assert_eq!(self.owner, fhir_id.owner);
3061 self.data.get(&fhir_id.local_id)
3062 }
3063}