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