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