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