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