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