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