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 SortInfer::*;
19pub use binder::{Binder, BoundReftKind, BoundVariableKind, BoundVariableKinds, EarlyBinder};
20pub use expr::{
21 AggregateKind, AliasReft, BinOp, BoundReft, Constant, Ctor, ESpan, EVid, EarlyReftParam, Expr,
22 ExprKind, FieldProj, HoleKind, KVar, KVid, Lambda, Loc, Name, Path, Real, UnOp, Var,
23};
24pub use flux_arc_interner::List;
25use flux_arc_interner::{Interned, impl_internable, impl_slice_internable};
26use flux_common::{bug, tracked_span_assert_eq, tracked_span_bug};
27use flux_macros::{TypeFoldable, TypeVisitable};
28pub use flux_rustc_bridge::ty::{
29 AliasKind, BoundRegion, BoundRegionKind, BoundVar, Const, ConstKind, ConstVid, DebruijnIndex,
30 EarlyParamRegion, LateParamRegion, LateParamRegionKind,
31 Region::{self, *},
32 RegionVid,
33};
34use flux_rustc_bridge::{
35 ToRustc,
36 mir::{Place, RawPtrKind},
37 ty::{self, GenericArgsExt as _, VariantDef},
38};
39use itertools::Itertools;
40pub use normalize::{NormalizeInfo, NormalizedDefns, local_deps};
41use refining::{Refine as _, Refiner};
42use rustc_abi;
43pub use rustc_abi::{FIRST_VARIANT, VariantIdx};
44use rustc_data_structures::{fx::FxIndexMap, snapshot_map::SnapshotMap, unord::UnordMap};
45use rustc_hir::{LangItem, Safety, def_id::DefId};
46use rustc_index::{IndexSlice, IndexVec, newtype_index};
47use rustc_macros::{Decodable, Encodable, TyDecodable, TyEncodable, extension};
48use rustc_middle::ty::TyCtxt;
49pub use rustc_middle::{
50 mir::Mutability,
51 ty::{AdtFlags, ClosureKind, FloatTy, IntTy, ParamConst, ParamTy, ScalarInt, UintTy},
52};
53use rustc_span::{Symbol, sym, symbol::kw};
54use rustc_type_ir::Upcast as _;
55pub use rustc_type_ir::{INNERMOST, TyVid};
56
57use self::fold::TypeFoldable;
58pub use crate::fhir::InferMode;
59use crate::{
60 LocalDefId,
61 def_id::{FluxDefId, FluxLocalDefId},
62 fhir::{self, FhirId, FluxOwnerId},
63 global_env::GlobalEnv,
64 pretty::{Pretty, PrettyCx},
65 queries::QueryResult,
66 rty::subst::SortSubst,
67};
68
69#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
71pub struct AdtSortDef(Interned<AdtSortDefData>);
72
73#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
74pub struct AdtSortVariant {
75 field_names: Vec<Symbol>,
77 sorts: List<Sort>,
82}
83
84impl AdtSortVariant {
85 pub fn new(fields: Vec<(Symbol, Sort)>) -> Self {
86 let (field_names, sorts) = fields.into_iter().unzip();
87 AdtSortVariant { field_names, sorts: List::from_vec(sorts) }
88 }
89
90 pub fn fields(&self) -> usize {
91 self.sorts.len()
92 }
93
94 pub fn field_names(&self) -> &Vec<Symbol> {
95 &self.field_names
96 }
97
98 pub fn sort_by_field_name(&self, args: &[Sort]) -> FxIndexMap<Symbol, Sort> {
99 std::iter::zip(&self.field_names, &self.sorts.fold_with(&mut SortSubst::new(args)))
100 .map(|(name, sort)| (*name, sort.clone()))
101 .collect()
102 }
103
104 pub fn field_by_name(
105 &self,
106 def_id: DefId,
107 args: &[Sort],
108 name: Symbol,
109 ) -> Option<(FieldProj, Sort)> {
110 let idx = self.field_names.iter().position(|it| name == *it)?;
111 let proj = FieldProj::Adt { def_id, field: idx as u32 };
112 let sort = self.sorts[idx].fold_with(&mut SortSubst::new(args));
113 Some((proj, sort))
114 }
115
116 pub fn field_sorts(&self, args: &[Sort]) -> List<Sort> {
117 self.sorts.fold_with(&mut SortSubst::new(args))
118 }
119
120 pub fn projections(&self, def_id: DefId) -> impl Iterator<Item = FieldProj> {
121 (0..self.fields()).map(move |i| FieldProj::Adt { def_id, field: i as u32 })
122 }
123}
124
125#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
126struct AdtSortDefData {
127 def_id: DefId,
129 params: Vec<ParamTy>,
136 variants: IndexVec<VariantIdx, AdtSortVariant>,
140 is_reflected: bool,
141 is_struct: bool,
142}
143
144impl AdtSortDef {
145 pub fn new(
146 def_id: DefId,
147 params: Vec<ParamTy>,
148 variants: IndexVec<VariantIdx, AdtSortVariant>,
149 is_reflected: bool,
150 is_struct: bool,
151 ) -> Self {
152 Self(Interned::new(AdtSortDefData { def_id, params, variants, is_reflected, is_struct }))
153 }
154
155 pub fn did(&self) -> DefId {
156 self.0.def_id
157 }
158
159 pub fn variant(&self, idx: VariantIdx) -> &AdtSortVariant {
160 &self.0.variants[idx]
161 }
162
163 pub fn variants(&self) -> &IndexSlice<VariantIdx, AdtSortVariant> {
164 &self.0.variants
165 }
166
167 pub fn opt_struct_variant(&self) -> Option<&AdtSortVariant> {
168 if self.is_struct() { Some(self.struct_variant()) } else { None }
169 }
170
171 #[track_caller]
172 pub fn struct_variant(&self) -> &AdtSortVariant {
173 tracked_span_assert_eq!(self.0.is_struct, true);
174 &self.0.variants[FIRST_VARIANT]
175 }
176
177 pub fn is_reflected(&self) -> bool {
178 self.0.is_reflected
179 }
180
181 pub fn is_struct(&self) -> bool {
182 self.0.is_struct
183 }
184
185 pub fn to_sort(&self, args: &[GenericArg]) -> Sort {
186 let sorts = self
187 .filter_generic_args(args)
188 .map(|arg| arg.expect_base().sort())
189 .collect();
190
191 Sort::App(SortCtor::Adt(self.clone()), sorts)
192 }
193
194 pub fn filter_generic_args<'a, A>(&'a self, args: &'a [A]) -> impl Iterator<Item = &'a A> + 'a {
197 self.0.params.iter().map(|p| &args[p.index as usize])
198 }
199
200 pub fn identity_args(&self) -> List<Sort> {
201 (0..self.0.params.len())
202 .map(|i| Sort::Var(ParamSort::from(i)))
203 .collect()
204 }
205
206 pub fn param_count(&self) -> usize {
208 self.0.params.len()
209 }
210}
211
212#[derive(Debug, Clone, Default, Encodable, Decodable)]
213pub struct Generics {
214 pub parent: Option<DefId>,
215 pub parent_count: usize,
216 pub own_params: List<GenericParamDef>,
217 pub has_self: bool,
218}
219
220impl Generics {
221 pub fn count(&self) -> usize {
222 self.parent_count + self.own_params.len()
223 }
224
225 pub fn own_default_count(&self) -> usize {
226 self.own_params
227 .iter()
228 .filter(|param| {
229 match param.kind {
230 GenericParamDefKind::Type { has_default }
231 | GenericParamDefKind::Const { has_default }
232 | GenericParamDefKind::Base { has_default } => has_default,
233 GenericParamDefKind::Lifetime => false,
234 }
235 })
236 .count()
237 }
238
239 pub fn param_at(&self, param_index: usize, genv: GlobalEnv) -> QueryResult<GenericParamDef> {
240 if let Some(index) = param_index.checked_sub(self.parent_count) {
241 Ok(self.own_params[index].clone())
242 } else {
243 let parent = self.parent.expect("parent_count > 0 but no parent?");
244 genv.generics_of(parent)?.param_at(param_index, genv)
245 }
246 }
247
248 pub fn const_params(&self, genv: GlobalEnv) -> QueryResult<Vec<(ParamConst, Sort)>> {
249 let mut res = vec![];
251 for i in 0..self.count() {
252 let param = self.param_at(i, genv)?;
253 if let GenericParamDefKind::Const { .. } = param.kind
254 && let Some(sort) = genv.sort_of_generic_param(param.def_id)?
255 {
256 let param_const = ParamConst { name: param.name, index: param.index };
257 res.push((param_const, sort));
258 }
259 }
260 Ok(res)
261 }
262}
263
264#[derive(Debug, Clone, TyEncodable, TyDecodable)]
265pub struct RefinementGenerics {
266 pub parent: Option<DefId>,
267 pub parent_count: usize,
268 pub own_params: List<RefineParam>,
269}
270
271#[derive(
272 PartialEq, Eq, Debug, Clone, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
273)]
274pub struct RefineParam {
275 pub sort: Sort,
276 pub name: Symbol,
277 pub mode: InferMode,
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
281pub struct GenericParamDef {
282 pub kind: GenericParamDefKind,
283 pub def_id: DefId,
284 pub index: u32,
285 pub name: Symbol,
286}
287
288#[derive(Copy, Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
289pub enum GenericParamDefKind {
290 Type { has_default: bool },
291 Base { has_default: bool },
292 Lifetime,
293 Const { has_default: bool },
294}
295
296pub const SELF_PARAM_TY: ParamTy = ParamTy { index: 0, name: kw::SelfUpper };
297
298#[derive(Debug, Clone, TyEncodable, TyDecodable)]
299pub struct GenericPredicates {
300 pub parent: Option<DefId>,
301 pub predicates: List<Clause>,
302}
303
304#[derive(
305 Debug, PartialEq, Eq, Hash, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
306)]
307pub struct Clause {
308 kind: Binder<ClauseKind>,
309}
310
311impl Clause {
312 pub fn new(vars: impl Into<List<BoundVariableKind>>, kind: ClauseKind) -> Self {
313 Clause { kind: Binder::bind_with_vars(kind, vars.into()) }
314 }
315
316 pub fn kind(&self) -> Binder<ClauseKind> {
317 self.kind.clone()
318 }
319
320 fn as_trait_clause(&self) -> Option<Binder<TraitPredicate>> {
321 let clause = self.kind();
322 if let ClauseKind::Trait(trait_clause) = clause.skip_binder_ref() {
323 Some(clause.rebind(trait_clause.clone()))
324 } else {
325 None
326 }
327 }
328
329 pub fn as_projection_clause(&self) -> Option<Binder<ProjectionPredicate>> {
330 let clause = self.kind();
331 if let ClauseKind::Projection(proj_clause) = clause.skip_binder_ref() {
332 Some(clause.rebind(proj_clause.clone()))
333 } else {
334 None
335 }
336 }
337
338 pub fn kind_skipping_binder(&self) -> ClauseKind {
341 self.kind.clone().skip_binder()
342 }
343
344 pub fn split_off_fn_trait_clauses(
348 genv: GlobalEnv,
349 clauses: &Clauses,
350 ) -> (Vec<Clause>, Vec<Binder<FnTraitPredicate>>) {
351 let mut fn_trait_clauses = vec![];
352 let mut fn_trait_output_clauses = vec![];
353 let mut rest = vec![];
354 for clause in clauses {
355 if let Some(trait_clause) = clause.as_trait_clause()
356 && let Some(kind) = genv.tcx().fn_trait_kind_from_def_id(trait_clause.def_id())
357 {
358 fn_trait_clauses.push((kind, trait_clause));
359 } else if let Some(proj_clause) = clause.as_projection_clause()
360 && genv.is_fn_output(proj_clause.projection_def_id())
361 {
362 fn_trait_output_clauses.push(proj_clause);
363 } else {
364 rest.push(clause.clone());
365 }
366 }
367 let fn_trait_clauses = fn_trait_clauses
368 .into_iter()
369 .map(|(kind, fn_trait_clause)| {
370 let mut candidates = vec![];
371 for fn_trait_output_clause in &fn_trait_output_clauses {
372 if fn_trait_output_clause.self_ty() == fn_trait_clause.self_ty() {
373 candidates.push(fn_trait_output_clause.clone());
374 }
375 }
376 tracked_span_assert_eq!(candidates.len(), 1);
377 let proj_pred = candidates.pop().unwrap().skip_binder();
378 fn_trait_clause.map(|fn_trait_clause| {
379 FnTraitPredicate {
380 kind,
381 self_ty: fn_trait_clause.self_ty().to_ty(),
382 tupled_args: fn_trait_clause.trait_ref.args[1].expect_base().to_ty(),
383 output: proj_pred.term.to_ty(),
384 }
385 })
386 })
387 .collect_vec();
388 (rest, fn_trait_clauses)
389 }
390}
391
392impl<'tcx> ToRustc<'tcx> for Clause {
393 type T = rustc_middle::ty::Clause<'tcx>;
394
395 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
396 self.kind.to_rustc(tcx).upcast(tcx)
397 }
398}
399
400impl From<Binder<ClauseKind>> for Clause {
401 fn from(kind: Binder<ClauseKind>) -> Self {
402 Clause { kind }
403 }
404}
405
406pub type Clauses = List<Clause>;
407
408#[derive(
409 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
410)]
411pub enum ClauseKind {
412 Trait(TraitPredicate),
413 Projection(ProjectionPredicate),
414 RegionOutlives(RegionOutlivesPredicate),
415 TypeOutlives(TypeOutlivesPredicate),
416 ConstArgHasType(Const, Ty),
417}
418
419impl<'tcx> ToRustc<'tcx> for ClauseKind {
420 type T = rustc_middle::ty::ClauseKind<'tcx>;
421
422 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
423 match self {
424 ClauseKind::Trait(trait_predicate) => {
425 rustc_middle::ty::ClauseKind::Trait(trait_predicate.to_rustc(tcx))
426 }
427 ClauseKind::Projection(projection_predicate) => {
428 rustc_middle::ty::ClauseKind::Projection(projection_predicate.to_rustc(tcx))
429 }
430 ClauseKind::RegionOutlives(outlives_predicate) => {
431 rustc_middle::ty::ClauseKind::RegionOutlives(outlives_predicate.to_rustc(tcx))
432 }
433 ClauseKind::TypeOutlives(outlives_predicate) => {
434 rustc_middle::ty::ClauseKind::TypeOutlives(outlives_predicate.to_rustc(tcx))
435 }
436 ClauseKind::ConstArgHasType(constant, ty) => {
437 rustc_middle::ty::ClauseKind::ConstArgHasType(
438 constant.to_rustc(tcx),
439 ty.to_rustc(tcx),
440 )
441 }
442 }
443 }
444}
445
446#[derive(Eq, PartialEq, Hash, Clone, Debug, TyEncodable, TyDecodable)]
447pub struct OutlivesPredicate<T>(pub T, pub Region);
448
449pub type TypeOutlivesPredicate = OutlivesPredicate<Ty>;
450pub type RegionOutlivesPredicate = OutlivesPredicate<Region>;
451
452impl<'tcx, V: ToRustc<'tcx>> ToRustc<'tcx> for OutlivesPredicate<V> {
453 type T = rustc_middle::ty::OutlivesPredicate<'tcx, V::T>;
454
455 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
456 rustc_middle::ty::OutlivesPredicate(self.0.to_rustc(tcx), self.1.to_rustc(tcx))
457 }
458}
459
460#[derive(
461 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
462)]
463pub struct TraitPredicate {
464 pub trait_ref: TraitRef,
465}
466
467impl TraitPredicate {
468 fn self_ty(&self) -> SubsetTyCtor {
469 self.trait_ref.self_ty()
470 }
471}
472
473impl<'tcx> ToRustc<'tcx> for TraitPredicate {
474 type T = rustc_middle::ty::TraitPredicate<'tcx>;
475
476 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
477 rustc_middle::ty::TraitPredicate {
478 polarity: rustc_middle::ty::PredicatePolarity::Positive,
479 trait_ref: self.trait_ref.to_rustc(tcx),
480 }
481 }
482}
483
484pub type PolyTraitPredicate = Binder<TraitPredicate>;
485
486impl PolyTraitPredicate {
487 fn def_id(&self) -> DefId {
488 self.skip_binder_ref().trait_ref.def_id
489 }
490
491 fn self_ty(&self) -> Binder<SubsetTyCtor> {
492 self.clone().map(|predicate| predicate.self_ty())
493 }
494}
495
496#[derive(
497 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
498)]
499pub struct TraitRef {
500 pub def_id: DefId,
501 pub args: GenericArgs,
502}
503
504impl TraitRef {
505 pub fn self_ty(&self) -> SubsetTyCtor {
506 self.args[0].expect_base().clone()
507 }
508}
509
510impl<'tcx> ToRustc<'tcx> for TraitRef {
511 type T = rustc_middle::ty::TraitRef<'tcx>;
512
513 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
514 rustc_middle::ty::TraitRef::new(tcx, self.def_id, self.args.to_rustc(tcx))
515 }
516}
517
518pub type PolyTraitRef = Binder<TraitRef>;
519
520impl PolyTraitRef {
521 pub fn def_id(&self) -> DefId {
522 self.as_ref().skip_binder().def_id
523 }
524}
525
526#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
527pub enum ExistentialPredicate {
528 Trait(ExistentialTraitRef),
529 Projection(ExistentialProjection),
530 AutoTrait(DefId),
531}
532
533pub type PolyExistentialPredicate = Binder<ExistentialPredicate>;
534
535impl ExistentialPredicate {
536 pub fn stable_cmp(&self, tcx: TyCtxt, other: &Self) -> Ordering {
538 match (self, other) {
539 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
540 (ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
541 tcx.def_path_hash(a.def_id)
542 .cmp(&tcx.def_path_hash(b.def_id))
543 }
544 (ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b)) => {
545 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
546 }
547 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
548 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
549 Ordering::Greater
550 }
551 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
552 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
553 }
554 }
555}
556
557impl<'tcx> ToRustc<'tcx> for ExistentialPredicate {
558 type T = rustc_middle::ty::ExistentialPredicate<'tcx>;
559
560 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
561 match self {
562 ExistentialPredicate::Trait(trait_ref) => {
563 let trait_ref = rustc_middle::ty::ExistentialTraitRef::new_from_args(
564 tcx,
565 trait_ref.def_id,
566 trait_ref.args.to_rustc(tcx),
567 );
568 rustc_middle::ty::ExistentialPredicate::Trait(trait_ref)
569 }
570 ExistentialPredicate::Projection(projection) => {
571 rustc_middle::ty::ExistentialPredicate::Projection(
572 rustc_middle::ty::ExistentialProjection::new_from_args(
573 tcx,
574 projection.def_id,
575 projection.args.to_rustc(tcx),
576 projection.term.skip_binder_ref().to_rustc(tcx).into(),
577 ),
578 )
579 }
580 ExistentialPredicate::AutoTrait(def_id) => {
581 rustc_middle::ty::ExistentialPredicate::AutoTrait(*def_id)
582 }
583 }
584 }
585}
586
587#[derive(
588 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
589)]
590pub struct ExistentialTraitRef {
591 pub def_id: DefId,
592 pub args: GenericArgs,
593}
594
595pub type PolyExistentialTraitRef = Binder<ExistentialTraitRef>;
596
597impl PolyExistentialTraitRef {
598 pub fn def_id(&self) -> DefId {
599 self.as_ref().skip_binder().def_id
600 }
601}
602
603#[derive(
604 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
605)]
606pub struct ExistentialProjection {
607 pub def_id: DefId,
608 pub args: GenericArgs,
609 pub term: SubsetTyCtor,
610}
611
612#[derive(
613 PartialEq, Eq, Hash, Debug, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
614)]
615pub struct ProjectionPredicate {
616 pub projection_ty: AliasTy,
617 pub term: SubsetTyCtor,
618}
619
620impl Pretty for ProjectionPredicate {
621 fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622 write!(
623 f,
624 "ProjectionPredicate << projection_ty = {:?}, term = {:?} >>",
625 self.projection_ty, self.term
626 )
627 }
628}
629
630impl ProjectionPredicate {
631 pub fn self_ty(&self) -> SubsetTyCtor {
632 self.projection_ty.self_ty().clone()
633 }
634}
635
636impl<'tcx> ToRustc<'tcx> for ProjectionPredicate {
637 type T = rustc_middle::ty::ProjectionPredicate<'tcx>;
638
639 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
640 rustc_middle::ty::ProjectionPredicate {
641 projection_term: rustc_middle::ty::AliasTerm::new_from_args(
642 tcx,
643 self.projection_ty.def_id,
644 self.projection_ty.args.to_rustc(tcx),
645 ),
646 term: self.term.as_bty_skipping_binder().to_rustc(tcx).into(),
647 }
648 }
649}
650
651pub type PolyProjectionPredicate = Binder<ProjectionPredicate>;
652
653impl PolyProjectionPredicate {
654 pub fn projection_def_id(&self) -> DefId {
655 self.skip_binder_ref().projection_ty.def_id
656 }
657
658 pub fn self_ty(&self) -> Binder<SubsetTyCtor> {
659 self.clone().map(|predicate| predicate.self_ty())
660 }
661}
662
663#[derive(
664 Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
665)]
666pub struct FnTraitPredicate {
667 pub self_ty: Ty,
668 pub tupled_args: Ty,
669 pub output: Ty,
670 pub kind: ClosureKind,
671}
672
673impl Pretty for FnTraitPredicate {
674 fn fmt(&self, _cx: &PrettyCx, f: &mut fmt::Formatter<'_>) -> fmt::Result {
675 write!(
676 f,
677 "self = {:?}, args = {:?}, output = {:?}, kind = {}",
678 self.self_ty, self.tupled_args, self.output, self.kind
679 )
680 }
681}
682
683impl FnTraitPredicate {
684 pub fn fndef_sig(&self) -> FnSig {
685 let inputs = self.tupled_args.expect_tuple().iter().cloned().collect();
686 let ret = self.output.clone().shift_in_escaping(1);
687 let output = Binder::bind_with_vars(FnOutput::new(ret, vec![]), List::empty());
688 FnSig::new(Safety::Safe, rustc_abi::ExternAbi::Rust, List::empty(), inputs, output)
689 }
690}
691
692pub fn to_closure_sig(
693 tcx: TyCtxt,
694 closure_id: LocalDefId,
695 tys: &[Ty],
696 args: &flux_rustc_bridge::ty::GenericArgs,
697 poly_sig: &PolyFnSig,
698) -> PolyFnSig {
699 let closure_args = args.as_closure();
700 let kind_ty = closure_args.kind_ty().to_rustc(tcx);
701 let Some(kind) = kind_ty.to_opt_closure_kind() else {
702 bug!("to_closure_sig: expected closure kind, found {kind_ty:?}");
703 };
704
705 let mut vars = poly_sig.vars().clone().to_vec();
706 let fn_sig = poly_sig.clone().skip_binder();
707 let closure_ty = Ty::closure(closure_id.into(), tys, args);
708 let env_ty = match kind {
709 ClosureKind::Fn => {
710 vars.push(BoundVariableKind::Region(BoundRegionKind::ClosureEnv));
711 let br = BoundRegion {
712 var: BoundVar::from_usize(vars.len() - 1),
713 kind: BoundRegionKind::ClosureEnv,
714 };
715 Ty::mk_ref(ReBound(INNERMOST, br), closure_ty, Mutability::Not)
716 }
717 ClosureKind::FnMut => {
718 vars.push(BoundVariableKind::Region(BoundRegionKind::ClosureEnv));
719 let br = BoundRegion {
720 var: BoundVar::from_usize(vars.len() - 1),
721 kind: BoundRegionKind::ClosureEnv,
722 };
723 Ty::mk_ref(ReBound(INNERMOST, br), closure_ty, Mutability::Mut)
724 }
725 ClosureKind::FnOnce => closure_ty,
726 };
727
728 let inputs = std::iter::once(env_ty)
729 .chain(fn_sig.inputs().iter().cloned())
730 .collect::<Vec<_>>();
731 let output = fn_sig.output().clone();
732
733 let fn_sig = crate::rty::FnSig::new(
734 fn_sig.safety,
735 fn_sig.abi,
736 fn_sig.requires.clone(), inputs.into(),
738 output,
739 );
740
741 PolyFnSig::bind_with_vars(fn_sig, List::from(vars))
742}
743
744#[derive(
745 Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
746)]
747pub struct CoroutineObligPredicate {
748 pub def_id: DefId,
749 pub resume_ty: Ty,
750 pub upvar_tys: List<Ty>,
751 pub output: Ty,
752}
753
754#[derive(Clone, Encodable, Decodable)]
755pub struct AssocRefinements {
756 pub items: List<FluxDefId>,
757}
758
759impl Default for AssocRefinements {
760 fn default() -> Self {
761 Self { items: List::empty() }
762 }
763}
764
765impl AssocRefinements {
766 pub fn find(&self, name: Symbol) -> Option<FluxDefId> {
767 self.items.iter().find(|it| it.name() == name).copied()
768 }
769}
770
771#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
772pub enum SortCtor {
773 Set,
774 Map,
775 Adt(AdtSortDef),
776 User { name: Symbol },
777}
778
779newtype_index! {
780 #[debug_format = "?{}s"]
787 #[encodable]
788 pub struct ParamSort {}
789}
790
791newtype_index! {
792 #[debug_format = "?{}s"]
794 #[encodable]
795 pub struct SortVid {}
796}
797
798impl ena::unify::UnifyKey for SortVid {
799 type Value = Option<Sort>;
800
801 #[inline]
802 fn index(&self) -> u32 {
803 self.as_u32()
804 }
805
806 #[inline]
807 fn from_index(u: u32) -> Self {
808 SortVid::from_u32(u)
809 }
810
811 fn tag() -> &'static str {
812 "SortVid"
813 }
814}
815
816impl ena::unify::EqUnifyValue for Sort {}
817
818newtype_index! {
819 #[debug_format = "?{}n"]
821 #[encodable]
822 pub struct NumVid {}
823}
824
825#[derive(Debug, Clone, Copy, PartialEq, Eq)]
826pub enum NumVarValue {
827 Real,
828 Int,
829 BitVec(BvSize),
830}
831
832impl NumVarValue {
833 pub fn to_sort(self) -> Sort {
834 match self {
835 NumVarValue::Real => Sort::Real,
836 NumVarValue::Int => Sort::Int,
837 NumVarValue::BitVec(size) => Sort::BitVec(size),
838 }
839 }
840}
841
842impl ena::unify::UnifyKey for NumVid {
843 type Value = Option<NumVarValue>;
844
845 #[inline]
846 fn index(&self) -> u32 {
847 self.as_u32()
848 }
849
850 #[inline]
851 fn from_index(u: u32) -> Self {
852 NumVid::from_u32(u)
853 }
854
855 fn tag() -> &'static str {
856 "NumVid"
857 }
858}
859
860impl ena::unify::EqUnifyValue for NumVarValue {}
861
862#[derive(PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
864pub enum SortInfer {
865 SortVar(SortVid),
867 NumVar(NumVid),
869}
870
871newtype_index! {
872 #[debug_format = "?{}size"]
874 #[encodable]
875 pub struct BvSizeVid {}
876}
877
878impl ena::unify::UnifyKey for BvSizeVid {
879 type Value = Option<BvSize>;
880
881 #[inline]
882 fn index(&self) -> u32 {
883 self.as_u32()
884 }
885
886 #[inline]
887 fn from_index(u: u32) -> Self {
888 BvSizeVid::from_u32(u)
889 }
890
891 fn tag() -> &'static str {
892 "BvSizeVid"
893 }
894}
895
896impl ena::unify::EqUnifyValue for BvSize {}
897
898#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
899pub enum Sort {
900 Int,
901 Bool,
902 Real,
903 BitVec(BvSize),
904 Str,
905 Char,
906 Loc,
907 Param(ParamTy),
908 Tuple(List<Sort>),
909 Alias(AliasKind, AliasTy),
910 Func(PolyFuncSort),
911 App(SortCtor, List<Sort>),
912 Var(ParamSort),
913 Infer(SortInfer),
914 Err,
915}
916
917impl Sort {
918 pub fn tuple(sorts: impl Into<List<Sort>>) -> Self {
919 Sort::Tuple(sorts.into())
920 }
921
922 pub fn app(ctor: SortCtor, sorts: List<Sort>) -> Self {
923 Sort::App(ctor, sorts)
924 }
925
926 pub fn unit() -> Self {
927 Self::tuple(vec![])
928 }
929
930 #[track_caller]
931 pub fn expect_func(&self) -> &PolyFuncSort {
932 if let Sort::Func(sort) = self { sort } else { bug!("expected `Sort::Func`") }
933 }
934
935 pub fn is_loc(&self) -> bool {
936 matches!(self, Sort::Loc)
937 }
938
939 pub fn is_unit(&self) -> bool {
940 matches!(self, Sort::Tuple(sorts) if sorts.is_empty())
941 }
942
943 pub fn is_unit_adt(&self) -> Option<DefId> {
944 if let Sort::App(SortCtor::Adt(sort_def), _) = self
945 && let Some(variant) = sort_def.opt_struct_variant()
946 && variant.fields() == 0
947 {
948 Some(sort_def.did())
949 } else {
950 None
951 }
952 }
953
954 pub fn is_pred(&self) -> bool {
956 matches!(self, Sort::Func(fsort) if fsort.skip_binders().output().is_bool())
957 }
958
959 #[must_use]
963 pub fn is_bool(&self) -> bool {
964 matches!(self, Self::Bool)
965 }
966
967 pub fn is_numeric(&self) -> bool {
968 matches!(self, Self::Int | Self::Real)
969 }
970
971 pub fn walk(&self, mut f: impl FnMut(&Sort, &[FieldProj])) {
972 fn go(sort: &Sort, f: &mut impl FnMut(&Sort, &[FieldProj]), proj: &mut Vec<FieldProj>) {
973 match sort {
974 Sort::Tuple(flds) => {
975 for (i, sort) in flds.iter().enumerate() {
976 proj.push(FieldProj::Tuple { arity: flds.len(), field: i as u32 });
977 go(sort, f, proj);
978 proj.pop();
979 }
980 }
981 Sort::App(SortCtor::Adt(sort_def), args) if sort_def.is_struct() => {
982 let field_sorts = sort_def.struct_variant().field_sorts(args);
983 for (i, sort) in field_sorts.iter().enumerate() {
984 proj.push(FieldProj::Adt { def_id: sort_def.did(), field: i as u32 });
985 go(sort, f, proj);
986 proj.pop();
987 }
988 }
989 _ => {
990 f(sort, proj);
991 }
992 }
993 }
994 go(self, &mut f, &mut vec![]);
995 }
996}
997
998#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1002pub enum BvSize {
1003 Fixed(u32),
1005 Param(ParamSort),
1007 Infer(BvSizeVid),
1010}
1011
1012impl rustc_errors::IntoDiagArg for Sort {
1013 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1014 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1015 }
1016}
1017
1018impl rustc_errors::IntoDiagArg for FuncSort {
1019 fn into_diag_arg(self, _path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
1020 rustc_errors::DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
1021 }
1022}
1023
1024#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1025pub struct FuncSort {
1026 pub inputs_and_output: List<Sort>,
1027}
1028
1029impl FuncSort {
1030 pub fn new(mut inputs: Vec<Sort>, output: Sort) -> Self {
1031 inputs.push(output);
1032 FuncSort { inputs_and_output: List::from_vec(inputs) }
1033 }
1034
1035 pub fn inputs(&self) -> &[Sort] {
1036 &self.inputs_and_output[0..self.inputs_and_output.len() - 1]
1037 }
1038
1039 pub fn output(&self) -> &Sort {
1040 &self.inputs_and_output[self.inputs_and_output.len() - 1]
1041 }
1042
1043 pub fn to_poly(&self) -> PolyFuncSort {
1044 PolyFuncSort::new(List::empty(), self.clone())
1045 }
1046}
1047
1048#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
1050pub enum SortParamKind {
1051 Sort,
1052 BvSize,
1053}
1054
1055#[derive(Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
1065pub struct PolyFuncSort {
1066 params: List<SortParamKind>,
1068 fsort: FuncSort,
1069}
1070
1071impl PolyFuncSort {
1072 pub fn new(params: List<SortParamKind>, fsort: FuncSort) -> Self {
1073 PolyFuncSort { params, fsort }
1074 }
1075
1076 pub fn skip_binders(&self) -> FuncSort {
1077 self.fsort.clone()
1078 }
1079
1080 pub fn instantiate_identity(&self) -> FuncSort {
1081 self.fsort.clone()
1082 }
1083
1084 pub fn expect_mono(&self) -> FuncSort {
1085 assert!(self.params.is_empty());
1086 self.fsort.clone()
1087 }
1088
1089 pub fn params(&self) -> impl ExactSizeIterator<Item = SortParamKind> + '_ {
1090 self.params.iter().copied()
1091 }
1092
1093 pub fn instantiate(&self, args: &[SortArg]) -> FuncSort {
1094 self.fsort.fold_with(&mut SortSubst::new(args))
1095 }
1096}
1097
1098#[derive(
1101 Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
1102)]
1103pub enum SortArg {
1104 Sort(Sort),
1105 BvSize(BvSize),
1106}
1107
1108#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1109pub enum ConstantInfo {
1110 Uninterpreted,
1112 Interpreted(Expr, Sort),
1114}
1115
1116#[derive(Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1117pub struct AdtDef(Interned<AdtDefData>);
1118
1119#[derive(Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1120pub struct AdtDefData {
1121 invariants: Vec<Invariant>,
1122 sort_def: AdtSortDef,
1123 opaque: bool,
1124 rustc: ty::AdtDef,
1125}
1126
1127#[derive(Clone, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1130pub enum Opaqueness<T> {
1131 Opaque,
1132 Transparent(T),
1133}
1134
1135pub static INT_TYS: [IntTy; 6] =
1136 [IntTy::Isize, IntTy::I8, IntTy::I16, IntTy::I32, IntTy::I64, IntTy::I128];
1137pub static UINT_TYS: [UintTy; 6] =
1138 [UintTy::Usize, UintTy::U8, UintTy::U16, UintTy::U32, UintTy::U64, UintTy::U128];
1139
1140#[derive(
1141 Debug, Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable,
1142)]
1143pub struct Invariant {
1144 pred: Binder<Expr>,
1147}
1148
1149impl Invariant {
1150 pub fn new(pred: Binder<Expr>) -> Self {
1151 Self { pred }
1152 }
1153
1154 pub fn apply(&self, idx: &Expr) -> Expr {
1155 self.pred.replace_bound_reft(idx)
1162 }
1163}
1164
1165pub type PolyVariants = List<Binder<VariantSig>>;
1166pub type PolyVariant = Binder<VariantSig>;
1167
1168#[derive(Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1169pub struct VariantSig {
1170 pub adt_def: AdtDef,
1171 pub args: GenericArgs,
1172 pub fields: List<Ty>,
1173 pub idx: Expr,
1174 pub requires: List<Expr>,
1175}
1176
1177pub type PolyFnSig = Binder<FnSig>;
1178
1179#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
1180pub struct FnSig {
1181 pub safety: Safety,
1182 pub abi: rustc_abi::ExternAbi,
1183 pub requires: List<Expr>,
1184 pub inputs: List<Ty>,
1185 pub output: Binder<FnOutput>,
1186}
1187
1188#[derive(
1189 Debug, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
1190)]
1191pub struct FnOutput {
1192 pub ret: Ty,
1193 pub ensures: List<Ensures>,
1194}
1195
1196#[derive(Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
1197pub enum Ensures {
1198 Type(Path, Ty),
1199 Pred(Expr),
1200}
1201
1202#[derive(Debug, TypeVisitable, TypeFoldable)]
1203pub struct Qualifier {
1204 pub def_id: FluxLocalDefId,
1205 pub body: Binder<Expr>,
1206 pub global: bool,
1207}
1208
1209pub type TyCtor = Binder<Ty>;
1210
1211impl TyCtor {
1212 pub fn to_ty(&self) -> Ty {
1213 match &self.vars()[..] {
1214 [] => {
1215 return self.skip_binder_ref().shift_out_escaping(1);
1216 }
1217 [BoundVariableKind::Refine(sort, ..)] => {
1218 if sort.is_unit() {
1219 return self.replace_bound_reft(&Expr::unit());
1220 }
1221 if let Some(def_id) = sort.is_unit_adt() {
1222 return self.replace_bound_reft(&Expr::unit_struct(def_id));
1223 }
1224 }
1225 _ => {}
1226 }
1227 Ty::exists(self.clone())
1228 }
1229}
1230
1231#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1232pub struct Ty(Interned<TyKind>);
1233
1234impl Ty {
1235 pub fn kind(&self) -> &TyKind {
1236 &self.0
1237 }
1238
1239 pub fn trait_object_dummy_self() -> Ty {
1245 Ty::infer(TyVid::from_u32(0))
1246 }
1247
1248 pub fn dynamic(preds: impl Into<List<Binder<ExistentialPredicate>>>, region: Region) -> Ty {
1249 BaseTy::Dynamic(preds.into(), region).to_ty()
1250 }
1251
1252 pub fn strg_ref(re: Region, path: Path, ty: Ty) -> Ty {
1253 TyKind::StrgRef(re, path, ty).intern()
1254 }
1255
1256 pub fn ptr(pk: impl Into<PtrKind>, path: impl Into<Path>) -> Ty {
1257 TyKind::Ptr(pk.into(), path.into()).intern()
1258 }
1259
1260 pub fn constr(p: impl Into<Expr>, ty: Ty) -> Ty {
1261 TyKind::Constr(p.into(), ty).intern()
1262 }
1263
1264 pub fn uninit() -> Ty {
1265 TyKind::Uninit.intern()
1266 }
1267
1268 pub fn indexed(bty: BaseTy, idx: impl Into<Expr>) -> Ty {
1269 TyKind::Indexed(bty, idx.into()).intern()
1270 }
1271
1272 pub fn exists(ty: Binder<Ty>) -> Ty {
1273 TyKind::Exists(ty).intern()
1274 }
1275
1276 pub fn exists_with_constr(bty: BaseTy, pred: Expr) -> Ty {
1277 let sort = bty.sort();
1278 let ty = Ty::indexed(bty, Expr::nu());
1279 Ty::exists(Binder::bind_with_sort(Ty::constr(pred, ty), sort))
1280 }
1281
1282 pub fn discr(adt_def: AdtDef, place: Place) -> Ty {
1283 TyKind::Discr(adt_def, place).intern()
1284 }
1285
1286 pub fn unit() -> Ty {
1287 Ty::tuple(vec![])
1288 }
1289
1290 pub fn bool() -> Ty {
1291 BaseTy::Bool.to_ty()
1292 }
1293
1294 pub fn int(int_ty: IntTy) -> Ty {
1295 BaseTy::Int(int_ty).to_ty()
1296 }
1297
1298 pub fn uint(uint_ty: UintTy) -> Ty {
1299 BaseTy::Uint(uint_ty).to_ty()
1300 }
1301
1302 pub fn param(param_ty: ParamTy) -> Ty {
1303 TyKind::Param(param_ty).intern()
1304 }
1305
1306 pub fn downcast(
1307 adt: AdtDef,
1308 args: GenericArgs,
1309 ty: Ty,
1310 variant: VariantIdx,
1311 fields: List<Ty>,
1312 ) -> Ty {
1313 TyKind::Downcast(adt, args, ty, variant, fields).intern()
1314 }
1315
1316 pub fn blocked(ty: Ty) -> Ty {
1317 TyKind::Blocked(ty).intern()
1318 }
1319
1320 pub fn str() -> Ty {
1321 BaseTy::Str.to_ty()
1322 }
1323
1324 pub fn char() -> Ty {
1325 BaseTy::Char.to_ty()
1326 }
1327
1328 pub fn float(float_ty: FloatTy) -> Ty {
1329 BaseTy::Float(float_ty).to_ty()
1330 }
1331
1332 pub fn mk_ref(region: Region, ty: Ty, mutbl: Mutability) -> Ty {
1333 BaseTy::Ref(region, ty, mutbl).to_ty()
1334 }
1335
1336 pub fn mk_slice(ty: Ty) -> Ty {
1337 BaseTy::Slice(ty).to_ty()
1338 }
1339
1340 pub fn mk_box(genv: GlobalEnv, deref_ty: Ty, alloc_ty: Ty) -> QueryResult<Ty> {
1341 let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, None);
1342 let adt_def = genv.adt_def(def_id)?;
1343
1344 let args = List::from_arr([GenericArg::Ty(deref_ty), GenericArg::Ty(alloc_ty)]);
1345
1346 let bty = BaseTy::adt(adt_def, args);
1347 Ok(Ty::indexed(bty, Expr::unit_struct(def_id)))
1348 }
1349
1350 pub fn mk_box_with_default_alloc(genv: GlobalEnv, deref_ty: Ty) -> QueryResult<Ty> {
1351 let def_id = genv.tcx().require_lang_item(LangItem::OwnedBox, None);
1352
1353 let generics = genv.generics_of(def_id)?;
1354 let alloc_ty = genv
1355 .lower_type_of(generics.own_params[1].def_id)?
1356 .skip_binder()
1357 .refine(&Refiner::default_for_item(genv, def_id)?)?;
1358
1359 Ty::mk_box(genv, deref_ty, alloc_ty)
1360 }
1361
1362 pub fn tuple(tys: impl Into<List<Ty>>) -> Ty {
1363 BaseTy::Tuple(tys.into()).to_ty()
1364 }
1365
1366 pub fn array(ty: Ty, c: Const) -> Ty {
1367 BaseTy::Array(ty, c).to_ty()
1368 }
1369
1370 pub fn closure(
1371 did: DefId,
1372 tys: impl Into<List<Ty>>,
1373 args: &flux_rustc_bridge::ty::GenericArgs,
1374 ) -> Ty {
1375 BaseTy::Closure(did, tys.into(), args.clone()).to_ty()
1376 }
1377
1378 pub fn coroutine(did: DefId, resume_ty: Ty, upvar_tys: List<Ty>) -> Ty {
1379 BaseTy::Coroutine(did, resume_ty, upvar_tys).to_ty()
1380 }
1381
1382 pub fn never() -> Ty {
1383 BaseTy::Never.to_ty()
1384 }
1385
1386 pub fn infer(vid: TyVid) -> Ty {
1387 TyKind::Infer(vid).intern()
1388 }
1389
1390 pub fn unconstr(&self) -> (Ty, Expr) {
1391 fn go(this: &Ty, preds: &mut Vec<Expr>) -> Ty {
1392 if let TyKind::Constr(pred, ty) = this.kind() {
1393 preds.push(pred.clone());
1394 go(ty, preds)
1395 } else {
1396 this.clone()
1397 }
1398 }
1399 let mut preds = vec![];
1400 (go(self, &mut preds), Expr::and_from_iter(preds))
1401 }
1402
1403 pub fn unblocked(&self) -> Ty {
1404 match self.kind() {
1405 TyKind::Blocked(ty) => ty.clone(),
1406 _ => self.clone(),
1407 }
1408 }
1409
1410 pub fn is_integral(&self) -> bool {
1412 self.as_bty_skipping_existentials()
1413 .map(BaseTy::is_integral)
1414 .unwrap_or_default()
1415 }
1416
1417 pub fn is_bool(&self) -> bool {
1419 self.as_bty_skipping_existentials()
1420 .map(BaseTy::is_bool)
1421 .unwrap_or_default()
1422 }
1423
1424 pub fn is_char(&self) -> bool {
1426 self.as_bty_skipping_existentials()
1427 .map(BaseTy::is_char)
1428 .unwrap_or_default()
1429 }
1430
1431 pub fn is_uninit(&self) -> bool {
1432 matches!(self.kind(), TyKind::Uninit)
1433 }
1434
1435 pub fn is_box(&self) -> bool {
1436 self.as_bty_skipping_existentials()
1437 .map(BaseTy::is_box)
1438 .unwrap_or_default()
1439 }
1440
1441 pub fn is_struct(&self) -> bool {
1442 self.as_bty_skipping_existentials()
1443 .map(BaseTy::is_struct)
1444 .unwrap_or_default()
1445 }
1446
1447 pub fn is_array(&self) -> bool {
1448 self.as_bty_skipping_existentials()
1449 .map(BaseTy::is_array)
1450 .unwrap_or_default()
1451 }
1452
1453 pub fn is_slice(&self) -> bool {
1454 self.as_bty_skipping_existentials()
1455 .map(BaseTy::is_slice)
1456 .unwrap_or_default()
1457 }
1458
1459 pub fn as_bty_skipping_existentials(&self) -> Option<&BaseTy> {
1460 match self.kind() {
1461 TyKind::Indexed(bty, _) => Some(bty),
1462 TyKind::Exists(ty) => Some(ty.skip_binder_ref().as_bty_skipping_existentials()?),
1463 TyKind::Constr(_, ty) => ty.as_bty_skipping_existentials(),
1464 _ => None,
1465 }
1466 }
1467
1468 #[track_caller]
1469 pub fn expect_discr(&self) -> (&AdtDef, &Place) {
1470 if let TyKind::Discr(adt_def, place) = self.kind() {
1471 (adt_def, place)
1472 } else {
1473 tracked_span_bug!("expected discr")
1474 }
1475 }
1476
1477 #[track_caller]
1478 pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg], &Expr) {
1479 if let TyKind::Indexed(BaseTy::Adt(adt_def, args), idx) = self.kind() {
1480 (adt_def, args, idx)
1481 } else {
1482 tracked_span_bug!("expected adt `{self:?}`")
1483 }
1484 }
1485
1486 #[track_caller]
1487 pub fn expect_tuple(&self) -> &[Ty] {
1488 if let TyKind::Indexed(BaseTy::Tuple(tys), _) = self.kind() {
1489 tys
1490 } else {
1491 tracked_span_bug!("expected tuple found `{self:?}` (kind: `{:?}`)", self.kind())
1492 }
1493 }
1494}
1495
1496impl<'tcx> ToRustc<'tcx> for Ty {
1497 type T = rustc_middle::ty::Ty<'tcx>;
1498
1499 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
1500 match self.kind() {
1501 TyKind::Indexed(bty, _) => bty.to_rustc(tcx),
1502 TyKind::Exists(ty) => ty.skip_binder_ref().to_rustc(tcx),
1503 TyKind::Constr(_, ty) => ty.to_rustc(tcx),
1504 TyKind::Param(pty) => pty.to_ty(tcx),
1505 TyKind::StrgRef(re, _, ty) => {
1506 rustc_middle::ty::Ty::new_ref(
1507 tcx,
1508 re.to_rustc(tcx),
1509 ty.to_rustc(tcx),
1510 Mutability::Mut,
1511 )
1512 }
1513 TyKind::Infer(vid) => rustc_middle::ty::Ty::new_var(tcx, *vid),
1514 TyKind::Uninit
1515 | TyKind::Ptr(_, _)
1516 | TyKind::Discr(_, _)
1517 | TyKind::Downcast(_, _, _, _, _)
1518 | TyKind::Blocked(_) => bug!("TODO: to_rustc for `{self:?}`"),
1519 }
1520 }
1521}
1522
1523#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug)]
1524pub enum TyKind {
1525 Indexed(BaseTy, Expr),
1526 Exists(Binder<Ty>),
1527 Constr(Expr, Ty),
1528 Uninit,
1529 StrgRef(Region, Path, Ty),
1530 Ptr(PtrKind, Path),
1531 Discr(AdtDef, Place),
1540 Param(ParamTy),
1541 Downcast(AdtDef, GenericArgs, Ty, VariantIdx, List<Ty>),
1542 Blocked(Ty),
1543 Infer(TyVid),
1547}
1548
1549#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1550pub enum PtrKind {
1551 Mut(Region),
1552 Box,
1553}
1554
1555#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
1556pub enum BaseTy {
1557 Int(IntTy),
1558 Uint(UintTy),
1559 Bool,
1560 Str,
1561 Char,
1562 Slice(Ty),
1563 Adt(AdtDef, GenericArgs),
1564 Float(FloatTy),
1565 RawPtr(Ty, Mutability),
1566 RawPtrMetadata(Ty),
1567 Ref(Region, Ty, Mutability),
1568 FnPtr(PolyFnSig),
1569 FnDef(DefId, GenericArgs),
1570 Tuple(List<Ty>),
1571 Alias(AliasKind, AliasTy),
1572 Array(Ty, Const),
1573 Never,
1574 Closure(DefId, List<Ty>, flux_rustc_bridge::ty::GenericArgs),
1575 Coroutine(DefId, Ty, List<Ty>),
1576 Dynamic(List<Binder<ExistentialPredicate>>, Region),
1577 Param(ParamTy),
1578 Infer(TyVid),
1579 Foreign(DefId),
1580}
1581
1582impl BaseTy {
1583 pub fn opaque(alias_ty: AliasTy) -> BaseTy {
1584 BaseTy::Alias(AliasKind::Opaque, alias_ty)
1585 }
1586
1587 pub fn projection(alias_ty: AliasTy) -> BaseTy {
1588 BaseTy::Alias(AliasKind::Projection, alias_ty)
1589 }
1590
1591 pub fn adt(adt_def: AdtDef, args: GenericArgs) -> BaseTy {
1592 BaseTy::Adt(adt_def, args)
1593 }
1594
1595 pub fn fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> BaseTy {
1596 BaseTy::FnDef(def_id, args.into())
1597 }
1598
1599 pub fn from_primitive_str(s: &str) -> Option<BaseTy> {
1600 match s {
1601 "i8" => Some(BaseTy::Int(IntTy::I8)),
1602 "i16" => Some(BaseTy::Int(IntTy::I16)),
1603 "i32" => Some(BaseTy::Int(IntTy::I32)),
1604 "i64" => Some(BaseTy::Int(IntTy::I64)),
1605 "i128" => Some(BaseTy::Int(IntTy::I128)),
1606 "u8" => Some(BaseTy::Uint(UintTy::U8)),
1607 "u16" => Some(BaseTy::Uint(UintTy::U16)),
1608 "u32" => Some(BaseTy::Uint(UintTy::U32)),
1609 "u64" => Some(BaseTy::Uint(UintTy::U64)),
1610 "u128" => Some(BaseTy::Uint(UintTy::U128)),
1611 "f16" => Some(BaseTy::Float(FloatTy::F16)),
1612 "f32" => Some(BaseTy::Float(FloatTy::F32)),
1613 "f64" => Some(BaseTy::Float(FloatTy::F64)),
1614 "f128" => Some(BaseTy::Float(FloatTy::F128)),
1615 "isize" => Some(BaseTy::Int(IntTy::Isize)),
1616 "usize" => Some(BaseTy::Uint(UintTy::Usize)),
1617 "bool" => Some(BaseTy::Bool),
1618 "char" => Some(BaseTy::Char),
1619 "str" => Some(BaseTy::Str),
1620 _ => None,
1621 }
1622 }
1623
1624 pub fn primitive_symbol(&self) -> Option<Symbol> {
1626 match self {
1627 BaseTy::Bool => Some(sym::bool),
1628 BaseTy::Char => Some(sym::char),
1629 BaseTy::Float(f) => {
1630 match f {
1631 FloatTy::F16 => Some(sym::f16),
1632 FloatTy::F32 => Some(sym::f32),
1633 FloatTy::F64 => Some(sym::f64),
1634 FloatTy::F128 => Some(sym::f128),
1635 }
1636 }
1637 BaseTy::Int(f) => {
1638 match f {
1639 IntTy::Isize => Some(sym::isize),
1640 IntTy::I8 => Some(sym::i8),
1641 IntTy::I16 => Some(sym::i16),
1642 IntTy::I32 => Some(sym::i32),
1643 IntTy::I64 => Some(sym::i64),
1644 IntTy::I128 => Some(sym::i128),
1645 }
1646 }
1647 BaseTy::Uint(f) => {
1648 match f {
1649 UintTy::Usize => Some(sym::usize),
1650 UintTy::U8 => Some(sym::u8),
1651 UintTy::U16 => Some(sym::u16),
1652 UintTy::U32 => Some(sym::u32),
1653 UintTy::U64 => Some(sym::u64),
1654 UintTy::U128 => Some(sym::u128),
1655 }
1656 }
1657 BaseTy::Str => Some(sym::str),
1658 _ => None,
1659 }
1660 }
1661
1662 pub fn is_integral(&self) -> bool {
1663 matches!(self, BaseTy::Int(_) | BaseTy::Uint(_))
1664 }
1665
1666 pub fn is_numeric(&self) -> bool {
1667 matches!(self, BaseTy::Int(_) | BaseTy::Uint(_) | BaseTy::Float(_))
1668 }
1669
1670 pub fn is_signed(&self) -> bool {
1671 matches!(self, BaseTy::Int(_))
1672 }
1673
1674 pub fn is_unsigned(&self) -> bool {
1675 matches!(self, BaseTy::Uint(_))
1676 }
1677
1678 pub fn is_float(&self) -> bool {
1679 matches!(self, BaseTy::Float(_))
1680 }
1681
1682 pub fn is_bool(&self) -> bool {
1683 matches!(self, BaseTy::Bool)
1684 }
1685
1686 fn is_struct(&self) -> bool {
1687 matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_struct())
1688 }
1689
1690 fn is_array(&self) -> bool {
1691 matches!(self, BaseTy::Array(..))
1692 }
1693
1694 fn is_slice(&self) -> bool {
1695 matches!(self, BaseTy::Slice(..))
1696 }
1697
1698 pub fn is_box(&self) -> bool {
1699 matches!(self, BaseTy::Adt(adt_def, _) if adt_def.is_box())
1700 }
1701
1702 pub fn is_char(&self) -> bool {
1703 matches!(self, BaseTy::Char)
1704 }
1705
1706 pub fn is_str(&self) -> bool {
1707 matches!(self, BaseTy::Str)
1708 }
1709
1710 pub fn unpack_box(&self) -> Option<(&Ty, &Ty)> {
1711 if let BaseTy::Adt(adt_def, args) = self
1712 && adt_def.is_box()
1713 {
1714 Some(args.box_args())
1715 } else {
1716 None
1717 }
1718 }
1719
1720 pub fn invariants(
1721 &self,
1722 tcx: TyCtxt,
1723 overflow_checking: bool,
1724 ) -> impl Iterator<Item = Invariant> {
1725 let (invariants, args) = match self {
1726 BaseTy::Adt(adt_def, args) => (adt_def.invariants().skip_binder(), &args[..]),
1727 BaseTy::Uint(uint_ty) => (uint_invariants(*uint_ty, overflow_checking), &[][..]),
1728 BaseTy::Int(int_ty) => (int_invariants(*int_ty, overflow_checking), &[][..]),
1729 BaseTy::Slice(_) => (slice_invariants(overflow_checking), &[][..]),
1730 _ => (&[][..], &[][..]),
1731 };
1732 invariants
1733 .iter()
1734 .map(move |inv| EarlyBinder(inv).instantiate_ref(tcx, args, &[]))
1735 }
1736
1737 pub fn to_ty(&self) -> Ty {
1738 let sort = self.sort();
1739 if sort.is_unit() {
1740 Ty::indexed(self.clone(), Expr::unit())
1741 } else {
1742 Ty::exists(Binder::bind_with_sort(Ty::indexed(self.clone(), Expr::nu()), sort))
1743 }
1744 }
1745
1746 pub fn to_subset_ty_ctor(&self) -> SubsetTyCtor {
1747 let sort = self.sort();
1748 Binder::bind_with_sort(SubsetTy::trivial(self.clone(), Expr::nu()), sort)
1749 }
1750
1751 #[track_caller]
1752 pub fn expect_adt(&self) -> (&AdtDef, &[GenericArg]) {
1753 if let BaseTy::Adt(adt_def, args) = self {
1754 (adt_def, args)
1755 } else {
1756 tracked_span_bug!("expected adt `{self:?}`")
1757 }
1758 }
1759
1760 pub fn is_atom(&self) -> bool {
1763 matches!(
1765 self,
1766 BaseTy::Int(_)
1767 | BaseTy::Uint(_)
1768 | BaseTy::Slice(_)
1769 | BaseTy::Bool
1770 | BaseTy::Char
1771 | BaseTy::Str
1772 | BaseTy::Adt(..)
1773 | BaseTy::Tuple(..)
1774 | BaseTy::Param(_)
1775 | BaseTy::Array(..)
1776 | BaseTy::Never
1777 | BaseTy::Closure(..)
1778 | BaseTy::Coroutine(..)
1779 | BaseTy::Alias(..)
1782 )
1783 }
1784}
1785
1786impl<'tcx> ToRustc<'tcx> for BaseTy {
1787 type T = rustc_middle::ty::Ty<'tcx>;
1788
1789 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
1790 use rustc_middle::ty;
1791 match self {
1792 BaseTy::Int(i) => ty::Ty::new_int(tcx, *i),
1793 BaseTy::Uint(i) => ty::Ty::new_uint(tcx, *i),
1794 BaseTy::Param(pty) => pty.to_ty(tcx),
1795 BaseTy::Slice(ty) => ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
1796 BaseTy::Bool => tcx.types.bool,
1797 BaseTy::Char => tcx.types.char,
1798 BaseTy::Str => tcx.types.str_,
1799 BaseTy::Adt(adt_def, args) => {
1800 let did = adt_def.did();
1801 let adt_def = tcx.adt_def(did);
1802 let args = args.to_rustc(tcx);
1803 ty::Ty::new_adt(tcx, adt_def, args)
1804 }
1805 BaseTy::FnDef(def_id, args) => {
1806 let args = args.to_rustc(tcx);
1807 ty::Ty::new_fn_def(tcx, *def_id, args)
1808 }
1809 BaseTy::Float(f) => ty::Ty::new_float(tcx, *f),
1810 BaseTy::RawPtr(ty, mutbl) => ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
1811 BaseTy::Ref(re, ty, mutbl) => {
1812 ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
1813 }
1814 BaseTy::FnPtr(poly_sig) => ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
1815 BaseTy::Tuple(tys) => {
1816 let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
1817 ty::Ty::new_tup(tcx, &ts)
1818 }
1819 BaseTy::Alias(kind, alias_ty) => {
1820 ty::Ty::new_alias(tcx, kind.to_rustc(tcx), alias_ty.to_rustc(tcx))
1821 }
1822 BaseTy::Array(ty, n) => {
1823 let ty = ty.to_rustc(tcx);
1824 let n = n.to_rustc(tcx);
1825 ty::Ty::new_array_with_const_len(tcx, ty, n)
1826 }
1827 BaseTy::Never => tcx.types.never,
1828 BaseTy::Closure(did, _, args) => ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
1829 BaseTy::Dynamic(exi_preds, re) => {
1830 let preds: Vec<_> = exi_preds
1831 .iter()
1832 .map(|pred| pred.to_rustc(tcx))
1833 .collect_vec();
1834 let preds = tcx.mk_poly_existential_predicates(&preds);
1835 ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx), rustc_middle::ty::DynKind::Dyn)
1836 }
1837 BaseTy::Coroutine(def_id, resume_ty, upvars) => {
1838 bug!("TODO: Generator {def_id:?} {resume_ty:?} {upvars:?}")
1839 }
1843 BaseTy::Infer(ty_vid) => ty::Ty::new_var(tcx, *ty_vid),
1844 BaseTy::Foreign(def_id) => ty::Ty::new_foreign(tcx, *def_id),
1845 BaseTy::RawPtrMetadata(ty) => {
1846 ty::Ty::new_ptr(
1847 tcx,
1848 ty.to_rustc(tcx),
1849 RawPtrKind::FakeForPtrMetadata.to_mutbl_lossy(),
1850 )
1851 }
1852 }
1853 }
1854}
1855
1856#[derive(
1857 Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable,
1858)]
1859pub struct AliasTy {
1860 pub def_id: DefId,
1861 pub args: GenericArgs,
1862 pub refine_args: RefineArgs,
1864}
1865
1866impl AliasTy {
1867 pub fn new(def_id: DefId, args: GenericArgs, refine_args: RefineArgs) -> Self {
1868 AliasTy { args, refine_args, def_id }
1869 }
1870}
1871
1872impl AliasTy {
1874 pub fn self_ty(&self) -> SubsetTyCtor {
1875 self.args[0].expect_base().clone()
1876 }
1877
1878 pub fn with_self_ty(&self, self_ty: SubsetTyCtor) -> Self {
1879 Self {
1880 def_id: self.def_id,
1881 args: [GenericArg::Base(self_ty)]
1882 .into_iter()
1883 .chain(self.args.iter().skip(1).cloned())
1884 .collect(),
1885 refine_args: self.refine_args.clone(),
1886 }
1887 }
1888}
1889
1890impl<'tcx> ToRustc<'tcx> for AliasTy {
1891 type T = rustc_middle::ty::AliasTy<'tcx>;
1892
1893 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
1894 rustc_middle::ty::AliasTy::new(tcx, self.def_id, self.args.to_rustc(tcx))
1895 }
1896}
1897
1898pub type RefineArgs = List<Expr>;
1899
1900#[extension(pub trait RefineArgsExt)]
1901impl RefineArgs {
1902 fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<RefineArgs> {
1903 Self::for_item(genv, def_id, |param, index| {
1904 Ok(Expr::var(Var::EarlyParam(EarlyReftParam {
1905 index: index as u32,
1906 name: param.name(),
1907 })))
1908 })
1909 }
1910
1911 fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk: F) -> QueryResult<RefineArgs>
1912 where
1913 F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<Expr>,
1914 {
1915 let reft_generics = genv.refinement_generics_of(def_id)?;
1916 let count = reft_generics.count();
1917 let mut args = Vec::with_capacity(count);
1918 reft_generics.fill_item(genv, &mut args, &mut mk)?;
1919 Ok(List::from_vec(args))
1920 }
1921}
1922
1923pub type SubsetTyCtor = Binder<SubsetTy>;
1930
1931impl SubsetTyCtor {
1932 pub fn as_bty_skipping_binder(&self) -> &BaseTy {
1933 &self.as_ref().skip_binder().bty
1934 }
1935
1936 pub fn to_ty(&self) -> Ty {
1937 let sort = self.sort();
1938 if sort.is_unit() {
1939 self.replace_bound_reft(&Expr::unit()).to_ty()
1940 } else if let Some(def_id) = sort.is_unit_adt() {
1941 self.replace_bound_reft(&Expr::unit_struct(def_id)).to_ty()
1942 } else {
1943 Ty::exists(self.as_ref().map(SubsetTy::to_ty))
1944 }
1945 }
1946
1947 pub fn to_ty_ctor(&self) -> TyCtor {
1948 self.as_ref().map(SubsetTy::to_ty)
1949 }
1950}
1951
1952#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
1996pub struct SubsetTy {
1997 pub bty: BaseTy,
2004 pub idx: Expr,
2008 pub pred: Expr,
2010}
2011
2012impl SubsetTy {
2013 pub fn new(bty: BaseTy, idx: impl Into<Expr>, pred: impl Into<Expr>) -> Self {
2014 Self { bty, idx: idx.into(), pred: pred.into() }
2015 }
2016
2017 pub fn trivial(bty: BaseTy, idx: impl Into<Expr>) -> Self {
2018 Self::new(bty, idx, Expr::tt())
2019 }
2020
2021 pub fn strengthen(&self, pred: impl Into<Expr>) -> Self {
2022 let this = self.clone();
2023 let pred = Expr::and(this.pred, pred).simplify(&SnapshotMap::default());
2024 Self { bty: this.bty, idx: this.idx, pred }
2025 }
2026
2027 pub fn to_ty(&self) -> Ty {
2028 let bty = self.bty.clone();
2029 if self.pred.is_trivially_true() {
2030 Ty::indexed(bty, &self.idx)
2031 } else {
2032 Ty::constr(&self.pred, Ty::indexed(bty, &self.idx))
2033 }
2034 }
2035}
2036
2037impl<'tcx> ToRustc<'tcx> for SubsetTy {
2038 type T = rustc_middle::ty::Ty<'tcx>;
2039
2040 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
2041 self.bty.to_rustc(tcx)
2042 }
2043}
2044
2045#[derive(PartialEq, Clone, Eq, Hash, TyEncodable, TyDecodable)]
2046pub enum GenericArg {
2047 Ty(Ty),
2048 Base(SubsetTyCtor),
2049 Lifetime(Region),
2050 Const(Const),
2051}
2052
2053impl GenericArg {
2054 #[track_caller]
2055 pub fn expect_type(&self) -> &Ty {
2056 if let GenericArg::Ty(ty) = self {
2057 ty
2058 } else {
2059 bug!("expected `rty::GenericArg::Ty`, found `{self:?}`")
2060 }
2061 }
2062
2063 #[track_caller]
2064 pub fn expect_base(&self) -> &SubsetTyCtor {
2065 if let GenericArg::Base(ctor) = self {
2066 ctor
2067 } else {
2068 bug!("expected `rty::GenericArg::Base`, found `{self:?}`")
2069 }
2070 }
2071
2072 pub fn from_param_def(param: &GenericParamDef) -> Self {
2073 match param.kind {
2074 GenericParamDefKind::Type { .. } => {
2075 let param_ty = ParamTy { index: param.index, name: param.name };
2076 GenericArg::Ty(Ty::param(param_ty))
2077 }
2078 GenericParamDefKind::Base { .. } => {
2079 let param_ty = ParamTy { index: param.index, name: param.name };
2081 GenericArg::Base(Binder::bind_with_sort(
2082 SubsetTy::trivial(BaseTy::Param(param_ty), Expr::nu()),
2083 Sort::Param(param_ty),
2084 ))
2085 }
2086 GenericParamDefKind::Lifetime => {
2087 let region = EarlyParamRegion { index: param.index, name: param.name };
2088 GenericArg::Lifetime(Region::ReEarlyParam(region))
2089 }
2090 GenericParamDefKind::Const { .. } => {
2091 let param_const = ParamConst { index: param.index, name: param.name };
2092 let kind = ConstKind::Param(param_const);
2093 GenericArg::Const(Const { kind })
2094 }
2095 }
2096 }
2097
2098 pub fn for_item<F>(genv: GlobalEnv, def_id: DefId, mut mk_kind: F) -> QueryResult<GenericArgs>
2102 where
2103 F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2104 {
2105 let defs = genv.generics_of(def_id)?;
2106 let count = defs.count();
2107 let mut args = Vec::with_capacity(count);
2108 Self::fill_item(genv, &mut args, &defs, &mut mk_kind)?;
2109 Ok(List::from_vec(args))
2110 }
2111
2112 pub fn identity_for_item(genv: GlobalEnv, def_id: DefId) -> QueryResult<GenericArgs> {
2113 Self::for_item(genv, def_id, |param, _| GenericArg::from_param_def(param))
2114 }
2115
2116 fn fill_item<F>(
2117 genv: GlobalEnv,
2118 args: &mut Vec<GenericArg>,
2119 generics: &Generics,
2120 mk_kind: &mut F,
2121 ) -> QueryResult<()>
2122 where
2123 F: FnMut(&GenericParamDef, &[GenericArg]) -> GenericArg,
2124 {
2125 if let Some(def_id) = generics.parent {
2126 let parent_generics = genv.generics_of(def_id)?;
2127 Self::fill_item(genv, args, &parent_generics, mk_kind)?;
2128 }
2129 for param in &generics.own_params {
2130 let kind = mk_kind(param, args);
2131 tracked_span_assert_eq!(param.index as usize, args.len());
2132 args.push(kind);
2133 }
2134 Ok(())
2135 }
2136}
2137
2138impl From<TyOrBase> for GenericArg {
2139 fn from(v: TyOrBase) -> Self {
2140 match v {
2141 TyOrBase::Ty(ty) => GenericArg::Ty(ty),
2142 TyOrBase::Base(ctor) => GenericArg::Base(ctor),
2143 }
2144 }
2145}
2146
2147impl<'tcx> ToRustc<'tcx> for GenericArg {
2148 type T = rustc_middle::ty::GenericArg<'tcx>;
2149
2150 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2151 use rustc_middle::ty;
2152 match self {
2153 GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
2154 GenericArg::Base(ctor) => ty::GenericArg::from(ctor.skip_binder_ref().to_rustc(tcx)),
2155 GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
2156 GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
2157 }
2158 }
2159}
2160
2161pub type GenericArgs = List<GenericArg>;
2162
2163#[extension(pub trait GenericArgsExt)]
2164impl GenericArgs {
2165 #[track_caller]
2166 fn box_args(&self) -> (&Ty, &Ty) {
2167 if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
2168 (deref, alloc)
2169 } else {
2170 bug!("invalid generic arguments for box");
2171 }
2172 }
2173
2174 fn to_rustc<'tcx>(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::GenericArgsRef<'tcx> {
2176 tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
2177 }
2178
2179 fn rebase_onto(
2180 &self,
2181 tcx: &TyCtxt,
2182 source_ancestor: DefId,
2183 target_args: &GenericArgs,
2184 ) -> List<GenericArg> {
2185 let defs = tcx.generics_of(source_ancestor);
2186 target_args
2187 .iter()
2188 .chain(self.iter().skip(defs.count()))
2189 .cloned()
2190 .collect()
2191 }
2192}
2193
2194#[derive(Debug)]
2195pub enum TyOrBase {
2196 Ty(Ty),
2197 Base(SubsetTyCtor),
2198}
2199
2200impl TyOrBase {
2201 pub fn into_ty(self) -> Ty {
2202 match self {
2203 TyOrBase::Ty(ty) => ty,
2204 TyOrBase::Base(ctor) => ctor.to_ty(),
2205 }
2206 }
2207
2208 #[track_caller]
2209 pub fn expect_base(self) -> SubsetTyCtor {
2210 match self {
2211 TyOrBase::Base(ctor) => ctor,
2212 TyOrBase::Ty(_) => tracked_span_bug!("expected `TyOrBase::Base`"),
2213 }
2214 }
2215
2216 pub fn as_base(self) -> Option<SubsetTyCtor> {
2217 match self {
2218 TyOrBase::Base(ctor) => Some(ctor),
2219 TyOrBase::Ty(_) => None,
2220 }
2221 }
2222}
2223
2224#[derive(Debug, Clone, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
2225pub enum TyOrCtor {
2226 Ty(Ty),
2227 Ctor(TyCtor),
2228}
2229
2230impl TyOrCtor {
2231 #[track_caller]
2232 pub fn expect_ctor(self) -> TyCtor {
2233 match self {
2234 TyOrCtor::Ctor(ctor) => ctor,
2235 TyOrCtor::Ty(_) => tracked_span_bug!("expected `TyOrCtor::Ctor`"),
2236 }
2237 }
2238
2239 pub fn expect_subset_ty_ctor(self) -> SubsetTyCtor {
2240 self.expect_ctor().map(|ty| {
2241 if let canonicalize::CanonicalTy::Constr(constr_ty) = ty.shallow_canonicalize()
2242 && let TyKind::Indexed(bty, idx) = constr_ty.ty().kind()
2243 && idx.is_nu()
2244 {
2245 SubsetTy::new(bty.clone(), Expr::nu(), constr_ty.pred())
2246 } else {
2247 tracked_span_bug!()
2248 }
2249 })
2250 }
2251
2252 pub fn to_ty(&self) -> Ty {
2253 match self {
2254 TyOrCtor::Ctor(ctor) => ctor.to_ty(),
2255 TyOrCtor::Ty(ty) => ty.clone(),
2256 }
2257 }
2258}
2259
2260impl From<TyOrBase> for TyOrCtor {
2261 fn from(v: TyOrBase) -> Self {
2262 match v {
2263 TyOrBase::Ty(ty) => TyOrCtor::Ty(ty),
2264 TyOrBase::Base(ctor) => TyOrCtor::Ctor(ctor.to_ty_ctor()),
2265 }
2266 }
2267}
2268
2269impl CoroutineObligPredicate {
2270 pub fn to_poly_fn_sig(&self) -> PolyFnSig {
2271 let vars = vec![];
2272
2273 let resume_ty = &self.resume_ty;
2274 let env_ty = Ty::coroutine(self.def_id, resume_ty.clone(), self.upvar_tys.clone());
2275
2276 let inputs = List::from_arr([env_ty, resume_ty.clone()]);
2277 let output =
2278 Binder::bind_with_vars(FnOutput::new(self.output.clone(), vec![]), List::empty());
2279
2280 PolyFnSig::bind_with_vars(
2281 FnSig::new(Safety::Safe, rustc_abi::ExternAbi::RustCall, List::empty(), inputs, output),
2282 List::from(vars),
2283 )
2284 }
2285}
2286
2287impl RefinementGenerics {
2288 pub fn count(&self) -> usize {
2289 self.parent_count + self.own_params.len()
2290 }
2291
2292 pub fn own_count(&self) -> usize {
2293 self.own_params.len()
2294 }
2295
2296 }
2310
2311impl EarlyBinder<RefinementGenerics> {
2312 pub fn parent(&self) -> Option<DefId> {
2313 self.skip_binder_ref().parent
2314 }
2315
2316 pub fn parent_count(&self) -> usize {
2317 self.skip_binder_ref().parent_count
2318 }
2319
2320 pub fn count(&self) -> usize {
2321 self.skip_binder_ref().count()
2322 }
2323
2324 pub fn own_count(&self) -> usize {
2325 self.skip_binder_ref().own_count()
2326 }
2327
2328 pub fn own_param_at(&self, index: usize) -> EarlyBinder<RefineParam> {
2329 self.as_ref().map(|this| this.own_params[index].clone())
2330 }
2331
2332 pub fn param_at(
2333 &self,
2334 param_index: usize,
2335 genv: GlobalEnv,
2336 ) -> QueryResult<EarlyBinder<RefineParam>> {
2337 if let Some(index) = param_index.checked_sub(self.parent_count()) {
2338 Ok(self.own_param_at(index))
2339 } else {
2340 let parent = self.parent().expect("parent_count > 0 but no parent?");
2341 genv.refinement_generics_of(parent)?
2342 .param_at(param_index, genv)
2343 }
2344 }
2345
2346 pub fn iter_own_params(&self) -> impl Iterator<Item = EarlyBinder<RefineParam>> + use<'_> {
2347 self.skip_binder_ref()
2348 .own_params
2349 .iter()
2350 .cloned()
2351 .map(EarlyBinder)
2352 }
2353
2354 pub fn fill_item<F, R>(&self, genv: GlobalEnv, vec: &mut Vec<R>, mk: &mut F) -> QueryResult
2355 where
2356 F: FnMut(EarlyBinder<RefineParam>, usize) -> QueryResult<R>,
2357 {
2358 if let Some(def_id) = self.parent() {
2359 genv.refinement_generics_of(def_id)?
2360 .fill_item(genv, vec, mk)?;
2361 }
2362 for param in self.iter_own_params() {
2363 vec.push(mk(param, vec.len())?);
2364 }
2365 Ok(())
2366 }
2367}
2368
2369impl EarlyBinder<GenericPredicates> {
2370 pub fn predicates(&self) -> EarlyBinder<List<Clause>> {
2371 EarlyBinder(self.0.predicates.clone())
2372 }
2373}
2374
2375impl EarlyBinder<FuncSort> {
2376 pub fn instantiate_func_sort<E>(
2378 self,
2379 sort_for_param: impl FnMut(ParamTy) -> Result<Sort, E>,
2380 ) -> Result<FuncSort, E> {
2381 self.0.try_fold_with(&mut subst::GenericsSubstFolder::new(
2382 subst::GenericsSubstForSort { sort_for_param },
2383 &[],
2384 ))
2385 }
2386}
2387
2388impl VariantSig {
2389 pub fn new(
2390 adt_def: AdtDef,
2391 args: GenericArgs,
2392 fields: List<Ty>,
2393 idx: Expr,
2394 requires: List<Expr>,
2395 ) -> Self {
2396 VariantSig { adt_def, args, fields, idx, requires }
2397 }
2398
2399 pub fn fields(&self) -> &[Ty] {
2400 &self.fields
2401 }
2402
2403 pub fn ret(&self) -> Ty {
2404 let bty = BaseTy::Adt(self.adt_def.clone(), self.args.clone());
2405 let idx = self.idx.clone();
2406 Ty::indexed(bty, idx)
2407 }
2408}
2409
2410impl FnSig {
2411 pub fn new(
2412 safety: Safety,
2413 abi: rustc_abi::ExternAbi,
2414 requires: List<Expr>,
2415 inputs: List<Ty>,
2416 output: Binder<FnOutput>,
2417 ) -> Self {
2418 FnSig { safety, abi, requires, inputs, output }
2419 }
2420
2421 pub fn requires(&self) -> &[Expr] {
2422 &self.requires
2423 }
2424
2425 pub fn inputs(&self) -> &[Ty] {
2426 &self.inputs
2427 }
2428
2429 pub fn output(&self) -> Binder<FnOutput> {
2430 self.output.clone()
2431 }
2432}
2433
2434impl<'tcx> ToRustc<'tcx> for FnSig {
2435 type T = rustc_middle::ty::FnSig<'tcx>;
2436
2437 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2438 tcx.mk_fn_sig(
2439 self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
2440 self.output().as_ref().skip_binder().to_rustc(tcx),
2441 false,
2442 self.safety,
2443 self.abi,
2444 )
2445 }
2446}
2447
2448impl FnOutput {
2449 pub fn new(ret: Ty, ensures: impl Into<List<Ensures>>) -> Self {
2450 Self { ret, ensures: ensures.into() }
2451 }
2452}
2453
2454impl<'tcx> ToRustc<'tcx> for FnOutput {
2455 type T = rustc_middle::ty::Ty<'tcx>;
2456
2457 fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
2458 self.ret.to_rustc(tcx)
2459 }
2460}
2461
2462impl AdtDef {
2463 pub fn new(
2464 rustc: ty::AdtDef,
2465 sort_def: AdtSortDef,
2466 invariants: Vec<Invariant>,
2467 opaque: bool,
2468 ) -> Self {
2469 AdtDef(Interned::new(AdtDefData { invariants, sort_def, opaque, rustc }))
2470 }
2471
2472 pub fn did(&self) -> DefId {
2473 self.0.rustc.did()
2474 }
2475
2476 pub fn sort_def(&self) -> &AdtSortDef {
2477 &self.0.sort_def
2478 }
2479
2480 pub fn sort(&self, args: &[GenericArg]) -> Sort {
2481 self.sort_def().to_sort(args)
2482 }
2483
2484 pub fn is_box(&self) -> bool {
2485 self.0.rustc.is_box()
2486 }
2487
2488 pub fn is_enum(&self) -> bool {
2489 self.0.rustc.is_enum()
2490 }
2491
2492 pub fn is_struct(&self) -> bool {
2493 self.0.rustc.is_struct()
2494 }
2495
2496 pub fn is_union(&self) -> bool {
2497 self.0.rustc.is_union()
2498 }
2499
2500 pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
2501 self.0.rustc.variants()
2502 }
2503
2504 pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
2505 self.0.rustc.variant(idx)
2506 }
2507
2508 pub fn invariants(&self) -> EarlyBinder<&[Invariant]> {
2509 EarlyBinder(&self.0.invariants)
2510 }
2511
2512 pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
2513 self.0.rustc.discriminants()
2514 }
2515
2516 pub fn is_opaque(&self) -> bool {
2517 self.0.opaque
2518 }
2519}
2520
2521impl<T> Opaqueness<T> {
2522 pub fn map<S>(self, f: impl FnOnce(T) -> S) -> Opaqueness<S> {
2523 match self {
2524 Opaqueness::Opaque => Opaqueness::Opaque,
2525 Opaqueness::Transparent(value) => Opaqueness::Transparent(f(value)),
2526 }
2527 }
2528
2529 pub fn as_ref(&self) -> Opaqueness<&T> {
2530 match self {
2531 Opaqueness::Opaque => Opaqueness::Opaque,
2532 Opaqueness::Transparent(value) => Opaqueness::Transparent(value),
2533 }
2534 }
2535
2536 pub fn as_deref(&self) -> Opaqueness<&T::Target>
2537 where
2538 T: std::ops::Deref,
2539 {
2540 match self {
2541 Opaqueness::Opaque => Opaqueness::Opaque,
2542 Opaqueness::Transparent(value) => Opaqueness::Transparent(value.deref()),
2543 }
2544 }
2545
2546 pub fn ok_or_else<E>(self, err: impl FnOnce() -> E) -> Result<T, E> {
2547 match self {
2548 Opaqueness::Transparent(v) => Ok(v),
2549 Opaqueness::Opaque => Err(err()),
2550 }
2551 }
2552
2553 #[track_caller]
2554 pub fn expect(self, msg: &str) -> T {
2555 match self {
2556 Opaqueness::Transparent(val) => val,
2557 Opaqueness::Opaque => bug!("{}", msg),
2558 }
2559 }
2560}
2561
2562impl<T, E> Opaqueness<Result<T, E>> {
2563 pub fn transpose(self) -> Result<Opaqueness<T>, E> {
2564 match self {
2565 Opaqueness::Transparent(Ok(x)) => Ok(Opaqueness::Transparent(x)),
2566 Opaqueness::Transparent(Err(e)) => Err(e),
2567 Opaqueness::Opaque => Ok(Opaqueness::Opaque),
2568 }
2569 }
2570}
2571
2572impl EarlyBinder<PolyVariant> {
2573 pub fn to_poly_fn_sig(&self, field_idx: Option<crate::FieldIdx>) -> EarlyBinder<PolyFnSig> {
2576 self.as_ref().map(|poly_variant| {
2577 poly_variant.as_ref().map(|variant| {
2578 let ret = variant.ret().shift_in_escaping(1);
2579 let output = Binder::bind_with_vars(FnOutput::new(ret, vec![]), List::empty());
2580 let inputs = match field_idx {
2581 None => variant.fields.clone(),
2582 Some(i) => List::singleton(variant.fields[i.index()].clone()),
2583 };
2584 FnSig::new(
2585 Safety::Safe,
2586 rustc_abi::ExternAbi::Rust,
2587 variant.requires.clone(),
2588 inputs,
2589 output,
2590 )
2591 })
2592 })
2593 }
2594}
2595
2596impl TyKind {
2597 fn intern(self) -> Ty {
2598 Ty(Interned::new(self))
2599 }
2600}
2601
2602fn slice_invariants(overflow_checking: bool) -> &'static [Invariant] {
2604 static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2605 [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2606 });
2607 static OVERFLOW: LazyLock<[Invariant; 2]> = LazyLock::new(|| {
2608 [
2609 Invariant {
2610 pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2611 },
2612 Invariant {
2613 pred: Binder::bind_with_sort(
2614 Expr::le(Expr::nu(), Expr::uint_max(UintTy::Usize)),
2615 Sort::Int,
2616 ),
2617 },
2618 ]
2619 });
2620 if overflow_checking { &*OVERFLOW } else { &*DEFAULT }
2621}
2622
2623fn uint_invariants(uint_ty: UintTy, overflow_checking: bool) -> &'static [Invariant] {
2624 static DEFAULT: LazyLock<[Invariant; 1]> = LazyLock::new(|| {
2625 [Invariant { pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int) }]
2626 });
2627
2628 static OVERFLOW: LazyLock<UnordMap<UintTy, [Invariant; 2]>> = LazyLock::new(|| {
2629 UINT_TYS
2630 .into_iter()
2631 .map(|uint_ty| {
2632 let invariants = [
2633 Invariant {
2634 pred: Binder::bind_with_sort(Expr::ge(Expr::nu(), Expr::zero()), Sort::Int),
2635 },
2636 Invariant {
2637 pred: Binder::bind_with_sort(
2638 Expr::le(Expr::nu(), Expr::uint_max(uint_ty)),
2639 Sort::Int,
2640 ),
2641 },
2642 ];
2643 (uint_ty, invariants)
2644 })
2645 .collect()
2646 });
2647 if overflow_checking { &OVERFLOW[&uint_ty] } else { &*DEFAULT }
2648}
2649
2650fn int_invariants(int_ty: IntTy, overflow_checking: bool) -> &'static [Invariant] {
2651 static DEFAULT: [Invariant; 0] = [];
2652
2653 static OVERFLOW: LazyLock<UnordMap<IntTy, [Invariant; 2]>> = LazyLock::new(|| {
2654 INT_TYS
2655 .into_iter()
2656 .map(|int_ty| {
2657 let invariants = [
2658 Invariant {
2659 pred: Binder::bind_with_sort(
2660 Expr::ge(Expr::nu(), Expr::int_min(int_ty)),
2661 Sort::Int,
2662 ),
2663 },
2664 Invariant {
2665 pred: Binder::bind_with_sort(
2666 Expr::le(Expr::nu(), Expr::int_max(int_ty)),
2667 Sort::Int,
2668 ),
2669 },
2670 ];
2671 (int_ty, invariants)
2672 })
2673 .collect()
2674 });
2675 if overflow_checking { &OVERFLOW[&int_ty] } else { &DEFAULT }
2676}
2677
2678impl_internable!(AdtDefData, AdtSortDefData, TyKind);
2679impl_slice_internable!(
2680 Ty,
2681 GenericArg,
2682 Ensures,
2683 InferMode,
2684 Sort,
2685 GenericParamDef,
2686 TraitRef,
2687 Binder<ExistentialPredicate>,
2688 Clause,
2689 PolyVariant,
2690 Invariant,
2691 RefineParam,
2692 FluxDefId,
2693 SortParamKind,
2694);
2695
2696#[macro_export]
2697macro_rules! _Int {
2698 ($int_ty:pat, $idxs:pat) => {
2699 TyKind::Indexed(BaseTy::Int($int_ty), $idxs)
2700 };
2701}
2702pub use crate::_Int as Int;
2703
2704#[macro_export]
2705macro_rules! _Uint {
2706 ($uint_ty:pat, $idxs:pat) => {
2707 TyKind::Indexed(BaseTy::Uint($uint_ty), $idxs)
2708 };
2709}
2710pub use crate::_Uint as Uint;
2711
2712#[macro_export]
2713macro_rules! _Bool {
2714 ($idxs:pat) => {
2715 TyKind::Indexed(BaseTy::Bool, $idxs)
2716 };
2717}
2718pub use crate::_Bool as Bool;
2719
2720#[macro_export]
2721macro_rules! _Ref {
2722 ($($pats:pat),+ $(,)?) => {
2723 $crate::rty::TyKind::Indexed($crate::rty::BaseTy::Ref($($pats),+), _)
2724 };
2725}
2726pub use crate::_Ref as Ref;
2727
2728pub struct WfckResults {
2729 pub owner: FluxOwnerId,
2730 bin_op_sorts: ItemLocalMap<Sort>,
2731 coercions: ItemLocalMap<Vec<Coercion>>,
2732 field_projs: ItemLocalMap<FieldProj>,
2733 node_sorts: ItemLocalMap<Sort>,
2734 record_ctors: ItemLocalMap<DefId>,
2735}
2736
2737#[derive(Clone, Copy, Debug)]
2738pub enum Coercion {
2739 Inject(DefId),
2740 Project(DefId),
2741}
2742
2743pub type ItemLocalMap<T> = UnordMap<fhir::ItemLocalId, T>;
2744
2745#[derive(Debug)]
2746pub struct LocalTableInContext<'a, T> {
2747 owner: FluxOwnerId,
2748 data: &'a ItemLocalMap<T>,
2749}
2750
2751pub struct LocalTableInContextMut<'a, T> {
2752 owner: FluxOwnerId,
2753 data: &'a mut ItemLocalMap<T>,
2754}
2755
2756impl WfckResults {
2757 pub fn new(owner: impl Into<FluxOwnerId>) -> Self {
2758 Self {
2759 owner: owner.into(),
2760 bin_op_sorts: ItemLocalMap::default(),
2761 coercions: ItemLocalMap::default(),
2762 field_projs: ItemLocalMap::default(),
2763 node_sorts: ItemLocalMap::default(),
2764 record_ctors: ItemLocalMap::default(),
2765 }
2766 }
2767
2768 pub fn bin_op_sorts_mut(&mut self) -> LocalTableInContextMut<Sort> {
2769 LocalTableInContextMut { owner: self.owner, data: &mut self.bin_op_sorts }
2770 }
2771
2772 pub fn bin_op_sorts(&self) -> LocalTableInContext<Sort> {
2773 LocalTableInContext { owner: self.owner, data: &self.bin_op_sorts }
2774 }
2775
2776 pub fn coercions_mut(&mut self) -> LocalTableInContextMut<Vec<Coercion>> {
2777 LocalTableInContextMut { owner: self.owner, data: &mut self.coercions }
2778 }
2779
2780 pub fn coercions(&self) -> LocalTableInContext<Vec<Coercion>> {
2781 LocalTableInContext { owner: self.owner, data: &self.coercions }
2782 }
2783
2784 pub fn field_projs_mut(&mut self) -> LocalTableInContextMut<FieldProj> {
2785 LocalTableInContextMut { owner: self.owner, data: &mut self.field_projs }
2786 }
2787
2788 pub fn field_projs(&self) -> LocalTableInContext<FieldProj> {
2789 LocalTableInContext { owner: self.owner, data: &self.field_projs }
2790 }
2791
2792 pub fn node_sorts_mut(&mut self) -> LocalTableInContextMut<Sort> {
2793 LocalTableInContextMut { owner: self.owner, data: &mut self.node_sorts }
2794 }
2795
2796 pub fn node_sorts(&self) -> LocalTableInContext<Sort> {
2797 LocalTableInContext { owner: self.owner, data: &self.node_sorts }
2798 }
2799
2800 pub fn record_ctors_mut(&mut self) -> LocalTableInContextMut<DefId> {
2801 LocalTableInContextMut { owner: self.owner, data: &mut self.record_ctors }
2802 }
2803
2804 pub fn record_ctors(&self) -> LocalTableInContext<DefId> {
2805 LocalTableInContext { owner: self.owner, data: &self.record_ctors }
2806 }
2807}
2808
2809impl<T> LocalTableInContextMut<'_, T> {
2810 pub fn insert(&mut self, fhir_id: FhirId, value: T) {
2811 tracked_span_assert_eq!(self.owner, fhir_id.owner);
2812 self.data.insert(fhir_id.local_id, value);
2813 }
2814}
2815
2816impl<'a, T> LocalTableInContext<'a, T> {
2817 pub fn get(&self, fhir_id: FhirId) -> Option<&'a T> {
2818 tracked_span_assert_eq!(self.owner, fhir_id.owner);
2819 self.data.get(&fhir_id.local_id)
2820 }
2821}