1pub mod struct_compat;
12use std::{borrow::Borrow, iter};
13
14use flux_common::{
15 bug,
16 dbg::{self, SpanTrace},
17 iter::IterExt,
18 result::ResultExt as _,
19 span_bug,
20};
21use flux_middle::{
22 THEORY_FUNCS,
23 def_id::{FluxDefId, MaybeExternId},
24 fhir::{self, FhirId, FluxOwnerId, QPathExpr},
25 global_env::GlobalEnv,
26 queries::{QueryErr, QueryResult},
27 query_bug,
28 rty::{
29 self, AssocReft, BoundReftKind, ESpan, Expr, INNERMOST, InternalFuncKind, List,
30 RefineArgsExt, WfckResults,
31 fold::TypeFoldable,
32 refining::{self, Refine, Refiner},
33 },
34};
35use flux_rustc_bridge::{
36 ToRustc,
37 lowering::{Lower, UnsupportedErr},
38};
39use itertools::Itertools;
40use rustc_data_structures::{
41 fx::{FxHashMap, FxIndexMap},
42 unord::UnordMap,
43};
44use rustc_errors::Diagnostic;
45use rustc_hash::FxHashSet;
46use rustc_hir::{self as hir, BodyId, OwnerId, Safety, def::DefKind, def_id::DefId};
47use rustc_index::IndexVec;
48use rustc_middle::{
49 middle::resolve_bound_vars::ResolvedArg,
50 ty::{self, AssocItem, AssocTag, BoundVar, TyCtxt},
51};
52use rustc_span::{
53 DUMMY_SP, ErrorGuaranteed, Span, Symbol,
54 symbol::{Ident, kw},
55};
56use rustc_trait_selection::traits;
57use rustc_type_ir::DebruijnIndex;
58
59#[repr(transparent)]
62pub struct ConvCtxt<P>(P);
63
64pub(crate) struct AfterSortck<'a, 'genv, 'tcx> {
65 genv: GlobalEnv<'genv, 'tcx>,
66 wfckresults: &'a WfckResults,
67 next_sort_index: u32,
68 next_type_index: u32,
69 next_region_index: u32,
70 next_const_index: u32,
71}
72
73pub trait ConvPhase<'genv, 'tcx>: Sized {
77 const EXPAND_TYPE_ALIASES: bool;
79
80 const HAS_ELABORATED_INFORMATION: bool;
83
84 type Results: WfckResultsProvider;
85
86 fn genv(&self) -> GlobalEnv<'genv, 'tcx>;
87
88 fn owner(&self) -> FluxOwnerId;
89
90 fn next_sort_vid(&mut self) -> rty::SortVid;
91
92 fn next_type_vid(&mut self) -> rty::TyVid;
93
94 fn next_region_vid(&mut self) -> rty::RegionVid;
95
96 fn next_const_vid(&mut self) -> rty::ConstVid;
97
98 fn results(&self) -> &Self::Results;
99
100 fn insert_node_sort(&mut self, fhir_id: FhirId, sort: rty::Sort);
106
107 fn insert_path_args(&mut self, fhir_id: FhirId, args: rty::GenericArgs);
110
111 fn insert_alias_reft_sort(&mut self, fhir_id: FhirId, fsort: rty::FuncSort);
114
115 fn into_conv_ctxt(self) -> ConvCtxt<Self> {
116 ConvCtxt(self)
117 }
118
119 fn as_conv_ctxt(&mut self) -> &mut ConvCtxt<Self> {
120 unsafe { std::mem::transmute(self) }
122 }
123}
124
125pub trait WfckResultsProvider: Sized {
128 fn bin_op_sort(&self, fhir_id: FhirId) -> rty::Sort;
129
130 fn coercions_for(&self, fhir_id: FhirId) -> &[rty::Coercion];
131
132 fn field_proj(&self, fhir_id: FhirId) -> rty::FieldProj;
133
134 fn record_ctor(&self, fhir_id: FhirId) -> DefId;
135
136 fn param_sort(&self, param_id: fhir::ParamId) -> rty::Sort;
137
138 fn node_sort(&self, fhir_id: FhirId) -> rty::Sort;
139
140 fn node_sort_args(&self, fhir_id: FhirId) -> List<rty::SortArg>;
141}
142
143impl<'genv, 'tcx> ConvPhase<'genv, 'tcx> for AfterSortck<'_, 'genv, 'tcx> {
144 const EXPAND_TYPE_ALIASES: bool = true;
145 const HAS_ELABORATED_INFORMATION: bool = true;
146
147 type Results = WfckResults;
148
149 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
150 self.genv
151 }
152
153 fn owner(&self) -> FluxOwnerId {
154 self.wfckresults.owner
155 }
156
157 fn next_sort_vid(&mut self) -> rty::SortVid {
158 self.next_sort_index = self.next_sort_index.checked_add(1).unwrap();
159 rty::SortVid::from_u32(self.next_sort_index - 1)
160 }
161
162 fn next_type_vid(&mut self) -> rty::TyVid {
163 self.next_type_index = self.next_type_index.checked_add(1).unwrap();
164 rty::TyVid::from_u32(self.next_type_index - 1)
165 }
166
167 fn next_region_vid(&mut self) -> rty::RegionVid {
168 self.next_region_index = self.next_region_index.checked_add(1).unwrap();
169 rty::RegionVid::from_u32(self.next_region_index - 1)
170 }
171
172 fn next_const_vid(&mut self) -> rty::ConstVid {
173 self.next_const_index = self.next_const_index.checked_add(1).unwrap();
174 rty::ConstVid::from_u32(self.next_const_index - 1)
175 }
176
177 fn results(&self) -> &Self::Results {
178 self.wfckresults
179 }
180
181 fn insert_node_sort(&mut self, _: FhirId, _: rty::Sort) {}
182
183 fn insert_path_args(&mut self, _: FhirId, _: rty::GenericArgs) {}
184
185 fn insert_alias_reft_sort(&mut self, _: FhirId, _: rty::FuncSort) {}
186}
187
188impl WfckResultsProvider for WfckResults {
189 fn bin_op_sort(&self, fhir_id: FhirId) -> rty::Sort {
190 self.bin_op_sorts()
191 .get(fhir_id)
192 .cloned()
193 .unwrap_or_else(|| bug!("binary operation without elaborated sort `{fhir_id:?}`"))
194 }
195
196 fn coercions_for(&self, fhir_id: FhirId) -> &[rty::Coercion] {
197 self.coercions().get(fhir_id).map_or(&[][..], Vec::as_slice)
198 }
199
200 fn field_proj(&self, fhir_id: FhirId) -> rty::FieldProj {
201 *self
202 .field_projs()
203 .get(fhir_id)
204 .unwrap_or_else(|| bug!("field projection without elaboration `{fhir_id:?}`"))
205 }
206
207 fn record_ctor(&self, fhir_id: FhirId) -> DefId {
208 *self
209 .record_ctors()
210 .get(fhir_id)
211 .unwrap_or_else(|| bug!("unelaborated record constructor `{fhir_id:?}`"))
212 }
213
214 fn param_sort(&self, param_id: fhir::ParamId) -> rty::Sort {
215 self.param_sorts()
216 .get(¶m_id)
217 .unwrap_or_else(|| bug!("unresolved sort for param `{param_id:?}`"))
218 .clone()
219 }
220
221 fn node_sort(&self, fhir_id: FhirId) -> rty::Sort {
222 self.node_sorts()
223 .get(fhir_id)
224 .unwrap_or_else(|| bug!("node without elaborated sort for `{fhir_id:?}`"))
225 .clone()
226 }
227
228 fn node_sort_args(&self, fhir_id: FhirId) -> List<rty::SortArg> {
229 self.fn_app_sorts()
230 .get(fhir_id)
231 .unwrap_or_else(|| bug!("fn-app node without elaborated sort_args for `{fhir_id:?}`"))
232 .clone()
233 }
234}
235
236#[derive(Debug)]
237pub(crate) struct Env {
238 layers: Vec<Layer>,
239 early_params: FxIndexMap<fhir::ParamId, Symbol>,
240}
241
242#[derive(Debug, Clone)]
243struct Layer {
244 map: FxIndexMap<fhir::ParamId, ParamEntry>,
245 kind: LayerKind,
246}
247
248#[derive(Debug, Clone, Copy)]
253enum LayerKind {
254 List {
255 bound_regions: u32,
259 },
260 Coalesce(DefId),
261}
262
263#[derive(Debug, Clone)]
264struct ParamEntry {
265 name: Symbol,
266 sort: rty::Sort,
267 mode: rty::InferMode,
268}
269
270#[derive(Debug)]
271struct LookupResult<'a> {
272 kind: LookupResultKind<'a>,
273 var_span: Span,
275}
276
277#[derive(Debug)]
278enum LookupResultKind<'a> {
279 Bound {
280 debruijn: DebruijnIndex,
281 entry: &'a ParamEntry,
282 kind: LayerKind,
283 index: u32,
285 },
286 EarlyParam {
287 name: Symbol,
288 index: u32,
290 },
291}
292
293pub(crate) fn conv_adt_sort_def(
294 genv: GlobalEnv,
295 def_id: MaybeExternId,
296 kind: &fhir::RefinementKind,
297) -> QueryResult<rty::AdtSortDef> {
298 let wfckresults = &WfckResults::new(def_id.map(|def_id| OwnerId { def_id }));
299 let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
300 match kind {
301 fhir::RefinementKind::Refined(refined_by) => {
302 let params = refined_by
303 .sort_params
304 .iter()
305 .map(|def_id| def_id_to_param_ty(genv, *def_id))
306 .collect();
307 let fields = refined_by
308 .fields
309 .iter()
310 .map(|(name, sort)| -> QueryResult<_> { Ok((*name, cx.conv_sort(sort)?)) })
311 .try_collect_vec()?;
312 let variants = IndexVec::from([rty::AdtSortVariant::new(fields)]);
313 let def_id = def_id.resolved_id();
314 Ok(rty::AdtSortDef::new(def_id, params, variants, false, true))
315 }
316 fhir::RefinementKind::Reflected => {
317 let enum_def_id = def_id.resolved_id();
318 let mut variants = IndexVec::new();
319 for variant in genv.tcx().adt_def(enum_def_id).variants() {
320 if let Some(field) = variant.fields.iter().next() {
321 let span = genv.tcx().def_span(field.did);
322 let err = genv
323 .sess()
324 .emit_err(errors::FieldsOnReflectedEnumVariant::new(span));
325 Err(err)?;
326 }
327 variants.push(rty::AdtSortVariant::new(vec![]));
328 }
329 Ok(rty::AdtSortDef::new(enum_def_id, vec![], variants, true, false))
330 }
331 }
332}
333
334pub(crate) fn conv_generics(
335 genv: GlobalEnv,
336 generics: &fhir::Generics,
337 def_id: MaybeExternId,
338 is_trait: bool,
339) -> rty::Generics {
340 let opt_self = is_trait.then(|| {
341 let kind = rty::GenericParamDefKind::Base { has_default: false };
342 rty::GenericParamDef { index: 0, name: kw::SelfUpper, def_id: def_id.resolved_id(), kind }
343 });
344 let rust_generics = genv.tcx().generics_of(def_id.resolved_id());
345 let params = {
346 opt_self
347 .into_iter()
348 .chain(rust_generics.own_params.iter().flat_map(|rust_param| {
349 let param = generics
351 .params
352 .iter()
353 .find(|param| param.def_id.resolved_id() == rust_param.def_id)?;
354 Some(rty::GenericParamDef {
355 kind: conv_generic_param_kind(¶m.kind),
356 def_id: param.def_id.resolved_id(),
357 index: rust_param.index,
358 name: rust_param.name,
359 })
360 }))
361 .collect_vec()
362 };
363
364 let rust_generics = genv.tcx().generics_of(def_id.resolved_id());
365 rty::Generics {
366 own_params: List::from_vec(params),
367 parent: rust_generics.parent,
368 parent_count: rust_generics.parent_count,
369 has_self: rust_generics.has_self,
370 }
371}
372
373pub(crate) fn conv_refinement_generics(
374 params: &[fhir::RefineParam],
375 wfckresults: &WfckResults,
376) -> QueryResult<List<rty::RefineParam>> {
377 params
378 .iter()
379 .map(|param| {
380 let sort = wfckresults.param_sort(param.id);
381 let mode = rty::InferMode::from_param_kind(param.kind);
382 Ok(rty::RefineParam { sort, name: param.name, mode })
383 })
384 .try_collect()
385}
386
387fn conv_generic_param_kind(kind: &fhir::GenericParamKind) -> rty::GenericParamDefKind {
388 match kind {
389 fhir::GenericParamKind::Type { default } => {
390 rty::GenericParamDefKind::Base { has_default: default.is_some() }
391 }
392 fhir::GenericParamKind::Lifetime => rty::GenericParamDefKind::Lifetime,
393 fhir::GenericParamKind::Const { .. } => {
394 rty::GenericParamDefKind::Const { has_default: false }
395 }
396 }
397}
398
399pub(crate) fn conv_default_type_parameter(
400 genv: GlobalEnv,
401 def_id: MaybeExternId,
402 ty: &fhir::Ty,
403 wfckresults: &WfckResults,
404) -> QueryResult<rty::TyOrBase> {
405 let mut env = Env::new(&[]);
406 let idx = genv.def_id_to_param_index(def_id.resolved_id());
407 let owner = ty_param_owner(genv, def_id.resolved_id());
408 let param = genv.generics_of(owner)?.param_at(idx as usize, genv)?;
409 let mut cx = AfterSortck::new(genv, wfckresults).into_conv_ctxt();
410 let rty_ty = cx.conv_ty(&mut env, ty, None)?;
411 cx.try_to_ty_or_base(param.kind, ty.span, &rty_ty)
412}
413
414impl<'a, 'genv, 'tcx> AfterSortck<'a, 'genv, 'tcx> {
415 pub(crate) fn new(genv: GlobalEnv<'genv, 'tcx>, wfckresults: &'a WfckResults) -> Self {
416 Self {
417 genv,
418 wfckresults,
419 next_sort_index: 1,
422 next_type_index: 1,
423 next_region_index: 0,
424 next_const_index: 0,
425 }
426 }
427}
428
429impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
431 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
432 self.0.genv()
433 }
434
435 fn tcx(&self) -> TyCtxt<'tcx> {
436 self.0.genv().tcx()
437 }
438
439 fn owner(&self) -> FluxOwnerId {
440 self.0.owner()
441 }
442
443 fn results(&self) -> &P::Results {
444 self.0.results()
445 }
446
447 fn next_sort_vid(&mut self) -> rty::SortVid {
448 self.0.next_sort_vid()
449 }
450
451 fn next_type_vid(&mut self) -> rty::TyVid {
452 self.0.next_type_vid()
453 }
454
455 fn next_region_vid(&mut self) -> rty::RegionVid {
456 self.0.next_region_vid()
457 }
458
459 fn next_const_vid(&mut self) -> rty::ConstVid {
460 self.0.next_const_vid()
461 }
462}
463
464fn variant_idx(tcx: TyCtxt, variant_def_id: DefId) -> rty::VariantIdx {
465 let enum_def_id = tcx.parent(variant_def_id);
466 tcx.adt_def(enum_def_id)
467 .variant_index_with_id(variant_def_id)
468}
469
470impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
472 pub(crate) fn conv_qualifier(
473 &mut self,
474 qualifier: &fhir::Qualifier,
475 ) -> QueryResult<rty::Qualifier> {
476 let mut env = Env::new(&[]);
477 env.push_layer(Layer::list(self.results(), 0, qualifier.args));
478 let body = self.conv_expr(&mut env, &qualifier.expr)?;
479 let body = rty::Binder::bind_with_vars(body, env.pop_layer().into_bound_vars(self.genv())?);
480 Ok(rty::Qualifier { def_id: qualifier.def_id, body, kind: qualifier.kind })
481 }
482
483 pub(crate) fn conv_defn(
484 &mut self,
485 func: &fhir::SpecFunc,
486 ) -> QueryResult<Option<rty::Binder<rty::Expr>>> {
487 if let Some(body) = &func.body {
488 let mut env = Env::new(&[]);
489 env.push_layer(Layer::list(self.results(), 0, func.args));
490 let expr = self.conv_expr(&mut env, body)?;
491 let body =
492 rty::Binder::bind_with_vars(expr, env.pop_layer().into_bound_vars(self.genv())?);
493 Ok(Some(body))
494 } else {
495 Ok(None)
496 }
497 }
498
499 pub(crate) fn conv_primop_prop(
500 &mut self,
501 primop_prop: &fhir::PrimOpProp,
502 ) -> QueryResult<rty::PrimOpProp> {
503 let mut env = Env::new(&[]);
504 env.push_layer(Layer::list(self.results(), 0, primop_prop.args));
505 let body = self.conv_expr(&mut env, &primop_prop.body)?;
506 let body = rty::Binder::bind_with_vars(body, env.pop_layer().into_bound_vars(self.genv())?);
507 let op = match primop_prop.op {
508 fhir::BinOp::BitAnd => rty::BinOp::BitAnd(rty::Sort::Int),
509 fhir::BinOp::BitOr => rty::BinOp::BitOr(rty::Sort::Int),
510 fhir::BinOp::BitXor => rty::BinOp::BitXor(rty::Sort::Int),
511 fhir::BinOp::BitShl => rty::BinOp::BitShl(rty::Sort::Int),
512 fhir::BinOp::BitShr => rty::BinOp::BitShr(rty::Sort::Int),
513 _ => {
514 span_bug!(
515 primop_prop.span,
516 "unexpected binary operator in primitive property: {:?}",
517 primop_prop.op
518 )
519 }
520 };
521 Ok(rty::PrimOpProp { def_id: primop_prop.def_id, op, body })
522 }
523}
524
525impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
527 pub(crate) fn conv_constant_expr(&mut self, expr: &fhir::Expr) -> QueryResult<rty::Expr> {
528 let mut env = Env::new(&[]);
529 self.conv_expr(&mut env, expr)
530 }
531
532 pub(crate) fn conv_enum_variants(
533 &mut self,
534 enum_id: MaybeExternId,
535 enum_def: &fhir::EnumDef,
536 ) -> QueryResult<Vec<rty::PolyVariant>> {
537 let reflected = enum_def.refinement.is_reflected();
538 enum_def
539 .variants
540 .iter()
541 .map(|variant| self.conv_enum_variant(enum_id, variant, reflected))
542 .try_collect_vec()
543 }
544
545 fn conv_enum_variant(
546 &mut self,
547 enum_id: MaybeExternId,
548 variant: &fhir::VariantDef,
549 reflected: bool,
550 ) -> QueryResult<rty::PolyVariant> {
551 let mut env = Env::new(&[]);
552 env.push_layer(Layer::list(self.results(), 0, variant.params));
553
554 let fields = variant
556 .fields
557 .iter()
558 .map(|field| self.conv_ty(&mut env, &field.ty, None))
559 .try_collect()?;
560
561 let adt_def = self.genv().adt_def(enum_id)?;
562 let idxs = if reflected {
563 let enum_def_id = enum_id.resolved_id();
564 let idx = variant_idx(self.tcx(), variant.def_id.to_def_id());
565 rty::Expr::ctor_enum(enum_def_id, idx)
566 } else {
567 self.conv_expr(&mut env, &variant.ret.idx)?
568 };
569 let variant = rty::VariantSig::new(
570 adt_def,
571 rty::GenericArg::identity_for_item(self.genv(), enum_id.resolved_id())?,
572 fields,
573 idxs,
574 List::empty(),
575 );
576
577 Ok(rty::Binder::bind_with_vars(variant, env.pop_layer().into_bound_vars(self.genv())?))
578 }
579
580 pub(crate) fn conv_struct_variant(
581 &mut self,
582 struct_id: MaybeExternId,
583 struct_def: &fhir::StructDef,
584 ) -> QueryResult<rty::Opaqueness<rty::PolyVariant>> {
585 let mut env = Env::new(&[]);
586 env.push_layer(Layer::list(self.results(), 0, struct_def.params));
587
588 if let fhir::StructKind::Transparent { fields } = &struct_def.kind {
589 let adt_def = self.genv().adt_def(struct_id)?;
590
591 let fields = fields
592 .iter()
593 .map(|field_def| self.conv_ty(&mut env, &field_def.ty, None))
594 .try_collect()?;
595
596 let vars = env.pop_layer().into_bound_vars(self.genv())?;
597 let idx = rty::Expr::ctor_struct(
598 struct_id.resolved_id(),
599 (0..vars.len())
600 .map(|idx| {
601 rty::Expr::bvar(
602 INNERMOST,
603 BoundVar::from_usize(idx),
604 rty::BoundReftKind::Anon,
605 )
606 })
607 .collect(),
608 );
609
610 let requires = adt_def
611 .invariants()
612 .iter_identity()
613 .map(|inv| inv.apply(&idx))
614 .collect();
615
616 let variant = rty::VariantSig::new(
617 adt_def,
618 rty::GenericArg::identity_for_item(self.genv(), struct_id.resolved_id())?,
619 fields,
620 idx,
621 requires,
622 );
623 let variant = rty::Binder::bind_with_vars(variant, vars);
624 Ok(rty::Opaqueness::Transparent(variant))
625 } else {
626 Ok(rty::Opaqueness::Opaque)
627 }
628 }
629
630 pub(crate) fn conv_type_alias(
631 &mut self,
632 ty_alias_id: MaybeExternId,
633 ty_alias: &fhir::TyAlias,
634 ) -> QueryResult<rty::TyCtor> {
635 let generics = self
636 .genv()
637 .fhir_get_generics(ty_alias_id.local_id())?
638 .unwrap();
639
640 let mut env = Env::new(generics.refinement_params);
641
642 if let Some(index) = &ty_alias.index {
643 env.push_layer(Layer::list(self.results(), 0, std::slice::from_ref(index)));
644 let ty = self.conv_ty(&mut env, &ty_alias.ty, None)?;
645
646 Ok(rty::Binder::bind_with_vars(ty, env.pop_layer().into_bound_vars(self.genv())?))
647 } else {
648 let ctor = self
649 .conv_ty(&mut env, &ty_alias.ty, None)?
650 .shallow_canonicalize()
651 .as_ty_or_base()
652 .as_base()
653 .ok_or_else(|| self.emit(errors::InvalidBaseInstance::new(ty_alias.span)))?;
654 Ok(ctor.to_ty_ctor())
655 }
656 }
657
658 pub(crate) fn conv_fn_sig(
659 &mut self,
660 fn_id: MaybeExternId,
661 fn_sig: &fhir::FnSig,
662 ) -> QueryResult<rty::PolyFnSig> {
663 let decl = &fn_sig.decl;
664 let header = fn_sig.header;
665
666 let late_bound_regions =
667 refining::refine_bound_variables(&self.genv().lower_late_bound_vars(fn_id.local_id())?);
668
669 let generics = self.genv().fhir_get_generics(fn_id.local_id())?.unwrap();
670 let mut env = Env::new(generics.refinement_params);
671 env.push_layer(Layer::list(self.results(), late_bound_regions.len() as u32, &[]));
672
673 let body_id = self.tcx().hir_node_by_def_id(fn_id.local_id()).body_id();
674 let no_panic = self.genv().no_panic(fn_id);
675
676 let fn_sig =
677 self.conv_fn_decl(&mut env, header.safety(), header.abi, decl, body_id, no_panic)?;
678
679 let vars = late_bound_regions
680 .iter()
681 .chain(env.pop_layer().into_bound_vars(self.genv())?.iter())
682 .cloned()
683 .collect();
684
685 Ok(rty::PolyFnSig::bind_with_vars(fn_sig, vars))
686 }
687
688 pub(crate) fn conv_generic_predicates(
689 &mut self,
690 def_id: MaybeExternId,
691 generics: &fhir::Generics,
692 ) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
693 let env = &mut Env::new(generics.refinement_params);
694
695 let predicates = if let Some(fhir_predicates) = generics.predicates {
696 let mut clauses = vec![];
697 for pred in fhir_predicates {
698 let span = pred.bounded_ty.span;
699 let bounded_ty = self.conv_ty(env, &pred.bounded_ty, None)?;
700 for clause in self.conv_generic_bounds(env, span, bounded_ty, pred.bounds)? {
701 clauses.push(clause);
702 }
703 }
704 self.match_clauses(def_id, &clauses)?
705 } else {
706 self.genv()
707 .lower_predicates_of(def_id)?
708 .refine(&Refiner::default_for_item(self.genv(), def_id.resolved_id())?)?
709 };
710 Ok(rty::EarlyBinder(predicates))
711 }
712
713 fn match_clauses(
714 &self,
715 def_id: MaybeExternId,
716 refined_clauses: &[rty::Clause],
717 ) -> QueryResult<rty::GenericPredicates> {
718 let tcx = self.genv().tcx();
719 let predicates = tcx.predicates_of(def_id);
720 let unrefined_clauses = predicates.predicates;
721
722 let mut map = UnordMap::default();
725 for (j, clause) in refined_clauses.iter().enumerate() {
726 let clause = clause.to_rustc(tcx);
727 let Some((i, _)) = unrefined_clauses.iter().find_position(|it| it.0 == clause) else {
728 self.emit_fail_to_match_predicates(def_id)?;
729 };
730 if map.insert(i, j).is_some() {
731 self.emit_fail_to_match_predicates(def_id)?;
732 }
733 }
734
735 let refiner = Refiner::default_for_item(self.genv(), def_id.resolved_id())?;
738 let mut clauses = vec![];
739 for (i, (clause, span)) in unrefined_clauses.iter().enumerate() {
740 let clause = if let Some(j) = map.get(&i) {
741 refined_clauses[*j].clone()
742 } else {
743 clause
744 .lower(tcx)
745 .map_err(|reason| {
746 let err = UnsupportedErr::new(reason).with_span(*span);
747 QueryErr::unsupported(def_id.resolved_id(), err)
748 })?
749 .refine(&refiner)?
750 };
751 clauses.push(clause);
752 }
753
754 Ok(rty::GenericPredicates {
755 parent: predicates.parent,
756 predicates: List::from_vec(clauses),
757 })
758 }
759
760 fn emit_fail_to_match_predicates(&self, def_id: MaybeExternId) -> Result<!, ErrorGuaranteed> {
761 let span = self.tcx().def_span(def_id.resolved_id());
762 Err(self.emit(errors::FailToMatchPredicates { span }))
763 }
764
765 pub(crate) fn conv_opaque_ty(
766 &mut self,
767 opaque_ty: &fhir::OpaqueTy,
768 ) -> QueryResult<rty::Clauses> {
769 let def_id = opaque_ty.def_id;
770 let parent = self.tcx().local_parent(def_id.local_id());
771 let refparams = &self
772 .genv()
773 .fhir_get_generics(parent)?
774 .unwrap()
775 .refinement_params;
776
777 let env = &mut Env::new(refparams);
778
779 let args = rty::GenericArg::identity_for_item(self.genv(), def_id.resolved_id())?;
780 let alias_ty = rty::AliasTy::new(def_id.resolved_id(), args, env.to_early_param_args());
781 let self_ty = rty::BaseTy::opaque(alias_ty).to_ty();
782 Ok(self
784 .conv_generic_bounds(env, DUMMY_SP, self_ty, opaque_ty.bounds)?
785 .into_iter()
786 .collect())
787 }
788
789 pub(crate) fn conv_assoc_reft_body(
790 &mut self,
791 params: &[fhir::RefineParam],
792 body: &fhir::Expr,
793 output: &fhir::Sort,
794 ) -> QueryResult<rty::Lambda> {
795 let mut env = Env::new(&[]);
796 env.push_layer(Layer::list(self.results(), 0, params));
797 let expr = self.conv_expr(&mut env, body)?;
798 let output = self.conv_sort(output)?;
799 let inputs = env.pop_layer().into_bound_vars(self.genv())?;
800 Ok(rty::Lambda::bind_with_vars(expr, inputs, output))
801 }
802}
803
804impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
806 pub(crate) fn conv_sort(&mut self, sort: &fhir::Sort) -> QueryResult<rty::Sort> {
807 let sort = match sort {
808 fhir::Sort::Path(path) => self.conv_sort_path(path)?,
809 fhir::Sort::BitVec(size) => rty::Sort::BitVec(rty::BvSize::Fixed(*size)),
810 fhir::Sort::Loc => rty::Sort::Loc,
811 fhir::Sort::Func(fsort) => rty::Sort::Func(self.conv_poly_func_sort(fsort)?),
812 fhir::Sort::SortOf(bty) => {
813 let rty::TyOrCtor::Ctor(ty_ctor) = self.conv_bty(&mut Env::empty(), bty, None)?
814 else {
815 return Err(self.emit(errors::RefinedUnrefinableType::new(bty.span)))?;
817 };
818 ty_ctor.sort()
819 }
820 fhir::Sort::Tuple(sorts) => {
821 let sorts = sorts.iter().map(|s| self.conv_sort(s)).try_collect_vec()?;
822 rty::Sort::Tuple(rty::List::from_vec(sorts))
823 }
824 fhir::Sort::Infer => rty::Sort::Infer(self.next_sort_vid()),
825 fhir::Sort::Err(_) => rty::Sort::Err,
826 };
827 Ok(sort)
828 }
829
830 fn conv_poly_func_sort(&mut self, sort: &fhir::PolyFuncSort) -> QueryResult<rty::PolyFuncSort> {
831 let params = iter::repeat_n(rty::SortParamKind::Sort, sort.params).collect();
832 Ok(rty::PolyFuncSort::new(params, self.conv_func_sort(&sort.fsort)?))
833 }
834
835 fn conv_func_sort(&mut self, fsort: &fhir::FuncSort) -> QueryResult<rty::FuncSort> {
836 let inputs = fsort
837 .inputs()
838 .iter()
839 .map(|sort| self.conv_sort(sort))
840 .try_collect()?;
841 Ok(rty::FuncSort::new(inputs, self.conv_sort(fsort.output())?))
842 }
843
844 fn conv_sort_path(&mut self, path: &fhir::SortPath) -> QueryResult<rty::Sort> {
845 let ctor = match path.res {
846 fhir::SortRes::PrimSort(fhir::PrimSort::Int) => {
847 self.check_prim_sort_generics(path, fhir::PrimSort::Int)?;
848 return Ok(rty::Sort::Int);
849 }
850 fhir::SortRes::PrimSort(fhir::PrimSort::Bool) => {
851 self.check_prim_sort_generics(path, fhir::PrimSort::Bool)?;
852 return Ok(rty::Sort::Bool);
853 }
854 fhir::SortRes::PrimSort(fhir::PrimSort::Real) => {
855 self.check_prim_sort_generics(path, fhir::PrimSort::Real)?;
856 return Ok(rty::Sort::Real);
857 }
858 fhir::SortRes::PrimSort(fhir::PrimSort::Char) => {
859 self.check_prim_sort_generics(path, fhir::PrimSort::Char)?;
860 return Ok(rty::Sort::Char);
861 }
862 fhir::SortRes::PrimSort(fhir::PrimSort::Str) => {
863 self.check_prim_sort_generics(path, fhir::PrimSort::Str)?;
864 return Ok(rty::Sort::Str);
865 }
866 fhir::SortRes::PrimSort(fhir::PrimSort::RawPtr) => {
867 self.check_prim_sort_generics(path, fhir::PrimSort::RawPtr)?;
868 return Ok(rty::Sort::RawPtr);
869 }
870 fhir::SortRes::SortParam(n) => return Ok(rty::Sort::Var(rty::ParamSort::from(n))),
871 fhir::SortRes::TyParam(def_id) => {
872 if !path.args.is_empty() {
873 let err = errors::GenericsOnSortTyParam::new(
874 path.segments.last().unwrap().span,
875 path.args.len(),
876 );
877 Err(self.emit(err))?;
878 }
879 return Ok(rty::Sort::Param(def_id_to_param_ty(self.genv(), def_id)));
880 }
881 fhir::SortRes::SelfParam { .. } => {
882 if !path.args.is_empty() {
883 let err = errors::GenericsOnSelf::new(
884 path.segments.last().unwrap().span,
885 path.args.len(),
886 );
887 Err(self.emit(err))?;
888 }
889 return Ok(rty::Sort::Param(rty::SELF_PARAM_TY));
890 }
891 fhir::SortRes::SelfAlias { alias_to } => {
892 if !path.args.is_empty() {
893 let err = errors::GenericsOnSelf::new(
894 path.segments.last().unwrap().span,
895 path.args.len(),
896 );
897 Err(self.emit(err))?;
898 }
899 return Ok(self
900 .genv()
901 .sort_of_self_ty_alias(alias_to)?
902 .unwrap_or(rty::Sort::Err));
903 }
904 fhir::SortRes::SelfParamAssoc { trait_id, ident } => {
905 let res = fhir::Res::SelfTyParam { trait_: trait_id };
906 let assoc_segment =
907 fhir::PathSegment { args: &[], constraints: &[], ident, res: fhir::Res::Err };
908 let mut env = Env::empty();
909 let alias_ty = self.conv_type_relative_type_path(&mut env, res, &assoc_segment)?;
910 return Ok(rty::Sort::Alias(rty::AliasKind::Projection, alias_ty));
911 }
912 fhir::SortRes::PrimSort(fhir::PrimSort::Set) => {
913 self.check_prim_sort_generics(path, fhir::PrimSort::Set)?;
914 rty::SortCtor::Set
915 }
916 fhir::SortRes::PrimSort(fhir::PrimSort::Map) => {
917 self.check_prim_sort_generics(path, fhir::PrimSort::Map)?;
918 rty::SortCtor::Map
919 }
920 fhir::SortRes::User(def_id) => {
921 self.check_user_defined_sort_param_count(path, def_id)?;
922 rty::SortCtor::User(def_id)
923 }
924 fhir::SortRes::Adt(def_id) => {
925 let sort_def = self.genv().adt_sort_def_of(def_id)?;
926 if path.args.len() != sort_def.param_count() {
927 let err = errors::IncorrectGenericsOnSort::new(
928 self.genv(),
929 def_id,
930 path.segments.last().unwrap().span,
931 path.args.len(),
932 sort_def.param_count(),
933 );
934 Err(self.emit(err))?;
935 }
936 rty::SortCtor::Adt(sort_def)
937 }
938 };
939 let args = path.args.iter().map(|t| self.conv_sort(t)).try_collect()?;
940
941 Ok(rty::Sort::app(ctor, args))
942 }
943
944 fn check_user_defined_sort_param_count(
945 &mut self,
946 path: &fhir::SortPath<'_>,
947 def_id: FluxDefId,
948 ) -> QueryResult {
949 let expected_param_count = self.genv().sort_decl_param_count(def_id);
950 if path.args.len() != expected_param_count {
951 let err = errors::IncorrectGenericsOnUserDefinedOpaqueSort::new(
952 path.segments.last().unwrap().span,
953 def_id.name(),
954 expected_param_count,
955 path.args.len(),
956 );
957 Err(self.emit(err))?;
958 }
959 Ok(())
960 }
961
962 fn check_prim_sort_generics(
963 &mut self,
964 path: &fhir::SortPath<'_>,
965 prim_sort: fhir::PrimSort,
966 ) -> QueryResult {
967 if path.args.len() != prim_sort.generics() {
968 let err = errors::GenericsOnPrimitiveSort::new(
969 path.segments.last().unwrap().span,
970 prim_sort.name_str(),
971 path.args.len(),
972 prim_sort.generics(),
973 );
974 Err(self.emit(err))?;
975 }
976 Ok(())
977 }
978}
979
980impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
982 fn conv_fn_decl(
983 &mut self,
984 env: &mut Env,
985 safety: Safety,
986 abi: rustc_abi::ExternAbi,
987 decl: &fhir::FnDecl,
988 body_id: Option<BodyId>,
989 no_panic: bool,
990 ) -> QueryResult<rty::FnSig> {
991 let mut requires = vec![];
992 for req in decl.requires {
993 requires.push(self.conv_requires(env, req)?);
994 }
995
996 let mut inputs = vec![];
997 let params =
998 if let Some(body_id) = body_id { self.tcx().hir_body(body_id).params } else { &[] };
999 for (i, ty) in decl.inputs.iter().enumerate() {
1000 let name = if let Some(param) = params.get(i)
1001 && let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind
1002 {
1003 Some(ident.name)
1004 } else {
1005 None
1006 };
1007 inputs.push(self.conv_ty(env, ty, name)?);
1008 }
1009
1010 let output = self.conv_fn_output(env, &decl.output)?;
1011
1012 Ok(rty::FnSig::new(
1013 safety,
1014 abi,
1015 requires.into(),
1016 inputs.into(),
1017 output,
1018 if no_panic { Expr::tt() } else { Expr::ff() },
1019 decl.lifted,
1020 ))
1021 }
1022
1023 fn conv_requires(
1024 &mut self,
1025 env: &mut Env,
1026 requires: &fhir::Requires,
1027 ) -> QueryResult<rty::Expr> {
1028 if requires.params.is_empty() {
1029 self.conv_expr(env, &requires.pred)
1030 } else {
1031 env.push_layer(Layer::list(self.results(), 0, requires.params));
1032 let pred = self.conv_expr(env, &requires.pred)?;
1033 let sorts = env.pop_layer().into_bound_vars(self.genv())?;
1034 Ok(rty::Expr::forall(rty::Binder::bind_with_vars(pred, sorts)))
1035 }
1036 }
1037
1038 fn conv_ensures(
1039 &mut self,
1040 env: &mut Env,
1041 ensures: &fhir::Ensures,
1042 ) -> QueryResult<rty::Ensures> {
1043 match ensures {
1044 fhir::Ensures::Type(loc, ty) => {
1045 Ok(rty::Ensures::Type(
1046 self.conv_loc(env, *loc)?,
1047 self.conv_ty(env, ty, loc.name())?,
1048 ))
1049 }
1050 fhir::Ensures::Pred(pred) => Ok(rty::Ensures::Pred(self.conv_expr(env, pred)?)),
1051 }
1052 }
1053
1054 fn conv_fn_output(
1055 &mut self,
1056 env: &mut Env,
1057 output: &fhir::FnOutput,
1058 ) -> QueryResult<rty::Binder<rty::FnOutput>> {
1059 env.push_layer(Layer::list(self.results(), 0, output.params));
1060
1061 let ret = self.conv_ty(env, &output.ret, None)?;
1062
1063 let ensures: List<rty::Ensures> = output
1064 .ensures
1065 .iter()
1066 .map(|ens| self.conv_ensures(env, ens))
1067 .try_collect()?;
1068 let output = rty::FnOutput::new(ret, ensures);
1069
1070 let vars = env.pop_layer().into_bound_vars(self.genv())?;
1071 Ok(rty::Binder::bind_with_vars(output, vars))
1072 }
1073
1074 fn conv_generic_bounds(
1075 &mut self,
1076 env: &mut Env,
1077 bounded_ty_span: Span,
1078 bounded_ty: rty::Ty,
1079 bounds: fhir::GenericBounds,
1080 ) -> QueryResult<Vec<rty::Clause>> {
1081 let mut clauses = vec![];
1082 for bound in bounds {
1083 match bound {
1084 fhir::GenericBound::Trait(poly_trait_ref) => {
1085 match poly_trait_ref.modifiers {
1086 fhir::TraitBoundModifier::None => {
1087 self.conv_poly_trait_ref(
1088 env,
1089 bounded_ty_span,
1090 &bounded_ty,
1091 poly_trait_ref,
1092 &mut clauses,
1093 )?;
1094 }
1095 fhir::TraitBoundModifier::Maybe => {
1096 }
1100 }
1101 }
1102 fhir::GenericBound::Outlives(lft) => {
1103 let re = self.conv_lifetime(env, *lft, bounded_ty_span);
1104 clauses.push(rty::Clause::new(
1105 List::empty(),
1106 rty::ClauseKind::TypeOutlives(rty::OutlivesPredicate(
1107 bounded_ty.clone(),
1108 re,
1109 )),
1110 ));
1111 }
1112 }
1113 }
1114 Ok(clauses)
1115 }
1116
1117 fn conv_poly_trait_ref(
1119 &mut self,
1120 env: &mut Env,
1121 span: Span,
1122 bounded_ty: &rty::Ty,
1123 poly_trait_ref: &fhir::PolyTraitRef,
1124 clauses: &mut Vec<rty::Clause>,
1125 ) -> QueryResult {
1126 let generic_params = &poly_trait_ref.bound_generic_params;
1127 let layer =
1128 Layer::list(self.results(), generic_params.len() as u32, poly_trait_ref.refine_params);
1129 env.push_layer(layer);
1130
1131 let trait_id = poly_trait_ref.trait_def_id();
1132 let generics = self.genv().generics_of(trait_id)?;
1133 let trait_segment = poly_trait_ref.trait_ref.last_segment();
1134
1135 let self_param = generics.param_at(0, self.genv())?;
1136 let mut args = vec![
1137 self.try_to_ty_or_base(self_param.kind, span, bounded_ty)?
1138 .into(),
1139 ];
1140 self.conv_generic_args_into(env, trait_id, trait_segment, &mut args)?;
1141
1142 let vars = env.top_layer().to_bound_vars(self.genv())?;
1143 let poly_trait_ref = rty::Binder::bind_with_vars(
1144 rty::TraitRef { def_id: trait_id, args: args.into() },
1145 vars,
1146 );
1147
1148 clauses.push(
1149 poly_trait_ref
1150 .clone()
1151 .map(|trait_ref| {
1152 rty::ClauseKind::Trait(rty::TraitPredicate { trait_ref: trait_ref.clone() })
1153 })
1154 .into(),
1155 );
1156
1157 for cstr in trait_segment.constraints {
1158 self.conv_assoc_item_constraint(env, &poly_trait_ref, cstr, clauses)?;
1159 }
1160
1161 env.pop_layer();
1162
1163 Ok(())
1164 }
1165
1166 fn conv_assoc_item_constraint(
1167 &mut self,
1168 env: &mut Env,
1169 poly_trait_ref: &rty::PolyTraitRef,
1170 constraint: &fhir::AssocItemConstraint,
1171 clauses: &mut Vec<rty::Clause>,
1172 ) -> QueryResult {
1173 let tcx = self.tcx();
1174
1175 let candidate = self.probe_single_bound_for_assoc_item(
1176 || traits::supertraits(tcx, poly_trait_ref.to_rustc(tcx)),
1177 constraint.ident,
1178 AssocTag::Type,
1179 )?;
1180 let assoc_item_id = AssocTag::Type
1181 .trait_defines_item_named(self.genv(), candidate.def_id(), constraint.ident)?
1182 .unwrap()
1183 .def_id;
1184
1185 let fhir::AssocItemConstraintKind::Equality { term } = &constraint.kind;
1186 let span = term.span;
1187 let term = self.conv_ty(env, term, None)?;
1188 let term = self.ty_to_subset_ty_ctor(span, &term)?;
1189
1190 let clause = poly_trait_ref
1191 .clone()
1192 .map(|trait_ref| {
1193 let args = trait_ref.args;
1195 let refine_args = List::empty();
1196 let projection_ty = rty::AliasTy { def_id: assoc_item_id, args, refine_args };
1197
1198 rty::ClauseKind::Projection(rty::ProjectionPredicate { projection_ty, term })
1199 })
1200 .into();
1201
1202 clauses.push(clause);
1203 Ok(())
1204 }
1205
1206 fn suffix_symbol<S: ToString>(sym: Symbol, suffix: S) -> Symbol {
1207 let str = format!("{}_{}", sym, suffix.to_string());
1208 Symbol::intern(&str)
1209 }
1210
1211 fn conv_ty(
1212 &mut self,
1213 env: &mut Env,
1214 ty: &fhir::Ty,
1215 name: Option<Symbol>,
1216 ) -> QueryResult<rty::Ty> {
1217 match &ty.kind {
1218 fhir::TyKind::BaseTy(bty) => Ok(self.conv_bty(env, bty, name)?.to_ty()),
1219 fhir::TyKind::Indexed(bty, idx) => {
1220 let fhir_id = bty.fhir_id;
1221 let rty::TyOrCtor::Ctor(ty_ctor) = self.conv_bty(env, bty, None)? else {
1222 return Err(self.emit(errors::RefinedUnrefinableType::new(bty.span)))?;
1223 };
1224 let idx = self.conv_expr(env, idx)?;
1225 self.0.insert_node_sort(fhir_id, ty_ctor.sort());
1226 Ok(ty_ctor.replace_bound_reft(&idx))
1227 }
1228 fhir::TyKind::Exists(params, ty) => {
1229 let layer = Layer::list(self.results(), 0, params);
1230 env.push_layer(layer);
1231 let ty = self.conv_ty(env, ty, name)?;
1232 let sorts = env.pop_layer().into_bound_vars(self.genv())?;
1233 if sorts.is_empty() {
1234 Ok(ty.shift_out_escaping(1))
1235 } else {
1236 Ok(rty::Ty::exists(rty::Binder::bind_with_vars(ty, sorts)))
1237 }
1238 }
1239 fhir::TyKind::StrgRef(lft, loc, ty) => {
1240 let re = self.conv_lifetime(env, *lft, ty.span);
1241 let name = loc.name();
1242 let loc = self.conv_loc(env, **loc)?;
1243 let ty = self.conv_ty(env, ty, name)?;
1244 Ok(rty::Ty::strg_ref(re, loc, ty))
1245 }
1246 fhir::TyKind::Ref(lft, fhir::MutTy { ty, mutbl }) => {
1247 let region = self.conv_lifetime(env, *lft, ty.span);
1248 Ok(rty::Ty::mk_ref(region, self.conv_ty(env, ty, name)?, *mutbl))
1249 }
1250 fhir::TyKind::BareFn(bare_fn) => {
1251 let mut env = Env::empty();
1252 env.push_layer(Layer::list(
1253 self.results(),
1254 bare_fn.generic_params.len() as u32,
1255 &[],
1256 ));
1257 let fn_sig = self.conv_fn_decl(
1258 &mut env,
1259 bare_fn.safety,
1260 bare_fn.abi,
1261 bare_fn.decl,
1262 None,
1263 false,
1264 )?;
1265 let vars = bare_fn
1266 .generic_params
1267 .iter()
1268 .map(|param| self.param_as_bound_var(param))
1269 .try_collect()?;
1270 let poly_fn_sig = rty::Binder::bind_with_vars(fn_sig, vars);
1271 Ok(rty::BaseTy::FnPtr(poly_fn_sig).to_ty())
1272 }
1273 fhir::TyKind::Tuple(tys) => {
1274 let tys: List<rty::Ty> = tys
1275 .iter()
1276 .enumerate()
1277 .map(|(i, ty)| {
1278 self.conv_ty(env, ty, name.map(|sym| Self::suffix_symbol(sym, i)))
1279 })
1280 .try_collect()?;
1281 Ok(rty::Ty::tuple(tys))
1282 }
1283 fhir::TyKind::Array(ty, len) => {
1284 let name = name.map(|sym| Self::suffix_symbol(sym, "elem"));
1285 Ok(rty::Ty::array(self.conv_ty(env, ty, name)?, self.conv_const_arg(*len)))
1286 }
1287 fhir::TyKind::Never => Ok(rty::Ty::never()),
1288 fhir::TyKind::Constr(pred, ty) => {
1289 let pred = self.conv_expr(env, pred)?;
1290 Ok(rty::Ty::constr(pred, self.conv_ty(env, ty, name)?))
1291 }
1292 fhir::TyKind::OpaqueDef(opaque_ty) => self.conv_opaque_def(env, opaque_ty, ty.span),
1293 fhir::TyKind::TraitObject(trait_bounds, lft, syn) => {
1294 if matches!(syn, rustc_ast::TraitObjectSyntax::Dyn) {
1295 self.conv_trait_object(env, trait_bounds, *lft, ty.span)
1296 } else {
1297 span_bug!(ty.span, "dyn* traits not supported yet")
1298 }
1299 }
1300 fhir::TyKind::Infer => Ok(rty::Ty::infer(self.next_type_vid())),
1301 fhir::TyKind::Err(err) => Err(QueryErr::Emitted(*err)),
1302 }
1303 }
1304
1305 fn conv_opaque_def(
1307 &mut self,
1308 env: &mut Env,
1309 opaque_ty: &fhir::OpaqueTy,
1310 span: Span,
1311 ) -> QueryResult<rty::Ty> {
1312 let def_id = opaque_ty.def_id;
1313
1314 if P::HAS_ELABORATED_INFORMATION {
1315 let lifetimes = self.tcx().opaque_captured_lifetimes(def_id.local_id());
1316
1317 let generics = self.tcx().generics_of(opaque_ty.def_id);
1318
1319 let offset = generics.parent_count;
1320
1321 let args = rty::GenericArg::for_item(self.genv(), def_id.resolved_id(), |param, _| {
1322 if let Some(i) = (param.index as usize).checked_sub(offset) {
1323 let (lifetime, _) = lifetimes[i];
1324 rty::GenericArg::Lifetime(self.conv_resolved_lifetime(env, lifetime, span))
1325 } else {
1326 rty::GenericArg::from_param_def(param)
1327 }
1328 })?;
1329 let reft_args = rty::RefineArgs::identity_for_item(self.genv(), def_id.resolved_id())?;
1330 let alias_ty = rty::AliasTy::new(def_id.resolved_id(), args, reft_args);
1331 Ok(rty::BaseTy::opaque(alias_ty).to_ty())
1332 } else {
1333 self.conv_opaque_ty(opaque_ty)?;
1337
1338 let alias_ty = rty::AliasTy::new(def_id.resolved_id(), List::empty(), List::empty());
1341 Ok(rty::BaseTy::opaque(alias_ty).to_ty())
1342 }
1343 }
1344
1345 fn conv_trait_object(
1346 &mut self,
1347 env: &mut Env,
1348 trait_bounds: &[fhir::PolyTraitRef],
1349 lifetime: fhir::Lifetime,
1350 span: Span,
1351 ) -> QueryResult<rty::Ty> {
1352 let mut bounds = vec![];
1359 let dummy_self = rty::Ty::trait_object_dummy_self();
1360 for trait_bound in trait_bounds.iter().rev() {
1361 self.conv_poly_trait_ref(env, trait_bound.span, &dummy_self, trait_bound, &mut bounds)?;
1362 }
1363
1364 let mut trait_bounds = vec![];
1366 let mut projection_bounds = vec![];
1367 for pred in bounds {
1368 let bound_pred = pred.kind();
1369 let vars = bound_pred.vars().clone();
1370 match bound_pred.skip_binder() {
1371 rty::ClauseKind::Trait(trait_pred) => {
1372 trait_bounds.push(rty::Binder::bind_with_vars(trait_pred.trait_ref, vars));
1373 }
1374 rty::ClauseKind::Projection(proj) => {
1375 projection_bounds.push(rty::Binder::bind_with_vars(proj, vars));
1376 }
1377 rty::ClauseKind::RegionOutlives(_) => {}
1378 rty::ClauseKind::TypeOutlives(_) => {}
1379 rty::ClauseKind::ConstArgHasType(..) => {
1380 bug!("did not expect {pred:?} clause in object bounds");
1381 }
1382 }
1383 }
1384
1385 let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = trait_bounds
1387 .into_iter()
1388 .partition(|trait_ref| self.tcx().trait_is_auto(trait_ref.def_id()));
1389
1390 {
1392 let mut duplicates = FxHashSet::default();
1393 auto_traits.retain(|trait_ref| duplicates.insert(trait_ref.def_id()));
1394 }
1395
1396 let regular_trait_predicates = regular_traits.into_iter().map(|poly_trait_ref| {
1397 poly_trait_ref.map(|trait_ref| {
1398 let args = trait_ref.args.iter().skip(1).cloned().collect();
1400 rty::ExistentialPredicate::Trait(rty::ExistentialTraitRef {
1401 def_id: trait_ref.def_id,
1402 args,
1403 })
1404 })
1405 });
1406
1407 let auto_trait_predicates = auto_traits.into_iter().map(|trait_def| {
1408 rty::Binder::dummy(rty::ExistentialPredicate::AutoTrait(trait_def.def_id()))
1409 });
1410
1411 let existential_projections = projection_bounds.into_iter().map(|bound| {
1412 bound.map(|proj| {
1413 let args = proj.projection_ty.args.iter().skip(1).cloned().collect();
1415 rty::ExistentialPredicate::Projection(rty::ExistentialProjection {
1416 def_id: proj.projection_ty.def_id,
1417 args,
1418 term: proj.term.clone(),
1419 })
1420 })
1421 });
1422
1423 let existential_predicates = {
1424 let mut v = regular_trait_predicates
1425 .chain(existential_projections)
1426 .chain(auto_trait_predicates)
1427 .collect_vec();
1428 v.sort_by(|a, b| {
1429 a.as_ref()
1430 .skip_binder()
1431 .stable_cmp(self.tcx(), b.as_ref().skip_binder())
1432 });
1433 List::from_vec(v)
1434 };
1435
1436 let region = self.conv_lifetime(env, lifetime, span);
1437 Ok(rty::Ty::dynamic(existential_predicates, region))
1438 }
1439
1440 pub(crate) fn conv_bty(
1441 &mut self,
1442 env: &mut Env,
1443 bty: &fhir::BaseTy,
1444 name: Option<Symbol>,
1445 ) -> QueryResult<rty::TyOrCtor> {
1446 match &bty.kind {
1447 fhir::BaseTyKind::Path(fhir::QPath::Resolved(qself, path)) => {
1448 self.conv_qpath(env, *qself, path, name)
1449 }
1450 fhir::BaseTyKind::Path(fhir::QPath::TypeRelative(qself, segment)) => {
1451 let qself_res =
1452 if let Some(path) = qself.as_path() { path.res } else { fhir::Res::Err };
1453 let alias_ty = self
1454 .conv_type_relative_type_path(env, qself_res, segment)?
1455 .shift_in_escaping(1);
1456 let bty = rty::BaseTy::Alias(rty::AliasKind::Projection, alias_ty);
1457 let sort = bty.sort();
1458 let ty = rty::Ty::indexed(bty, rty::Expr::nu());
1459 Ok(rty::TyOrCtor::Ctor(rty::Binder::bind_with_sort(ty, sort)))
1460 }
1461 fhir::BaseTyKind::Slice(ty) => {
1462 let name = name.map(|sym| Self::suffix_symbol(sym, "elem"));
1463 let bty = rty::BaseTy::Slice(self.conv_ty(env, ty, name)?).shift_in_escaping(1);
1464 let sort = bty.sort();
1465 let ty = rty::Ty::indexed(bty, rty::Expr::nu());
1466 Ok(rty::TyOrCtor::Ctor(rty::Binder::bind_with_sort(ty, sort)))
1467 }
1468 fhir::BaseTyKind::RawPtr(ty, mutability) => {
1469 let name = name.map(|sym| Self::suffix_symbol(sym, "size"));
1470 let bty = rty::BaseTy::RawPtr(self.conv_ty(env, ty, name)?, *mutability)
1471 .shift_in_escaping(1);
1472 let sort = bty.sort();
1473 let ty = rty::Ty::indexed(bty, rty::Expr::nu());
1474 Ok(rty::TyOrCtor::Ctor(rty::Binder::bind_with_sort(ty, sort)))
1475 }
1476 fhir::BaseTyKind::Err(err) => Err(QueryErr::Emitted(*err)),
1477 }
1478 }
1479
1480 fn conv_type_relative_path<Tag: AssocItemTag>(
1481 &mut self,
1482 tag: Tag,
1483 qself_res: fhir::Res,
1484 assoc_ident: Ident,
1485 ) -> QueryResult<(Tag::AssocItem<'tcx>, rty::TraitRef)> {
1486 let tcx = self.tcx();
1487
1488 let bound = match qself_res {
1489 fhir::Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true } => {
1490 let trait_ref = tcx.impl_trait_ref(impl_def_id);
1491
1492 self.probe_single_bound_for_assoc_item(
1493 || {
1494 traits::supertraits(
1495 tcx,
1496 ty::Binder::dummy(trait_ref.instantiate_identity()),
1497 )
1498 },
1499 assoc_ident,
1500 tag,
1501 )?
1502 }
1503 fhir::Res::Def(DefKind::TyParam, param_id)
1504 | fhir::Res::SelfTyParam { trait_: param_id } => {
1505 let item_def_id = self.owner().resolved_id().unwrap();
1506 let predicates = type_param_predicates(tcx, item_def_id, param_id);
1507 self.probe_single_bound_for_assoc_item(
1508 || {
1509 tag.transitive_bounds_that_define_assoc_item(
1510 self.genv(),
1511 predicates.map(|pred| pred.map_bound(|t| t.trait_ref)),
1512 assoc_ident,
1513 )
1514 },
1515 assoc_ident,
1516 tag,
1517 )?
1518 }
1519 _ => self.report_assoc_item_not_found(assoc_ident.span, tag)?,
1520 };
1521
1522 let Some(trait_ref) = bound.no_bound_vars() else {
1523 Err(self.emit(
1531 query_bug!("associated path with uninferred generic parameters")
1532 .at(assoc_ident.span),
1533 ))?
1534 };
1535
1536 let trait_ref = trait_ref
1537 .lower(tcx)
1538 .map_err(|err| QueryErr::unsupported(trait_ref.def_id, err.into_err()))?
1539 .refine(&self.refiner()?)?;
1540 let assoc_item = tag
1541 .trait_defines_item_named(self.genv(), trait_ref.def_id, assoc_ident)?
1542 .unwrap();
1543
1544 Ok((assoc_item, trait_ref))
1545 }
1546
1547 fn conv_type_relative_type_path(
1548 &mut self,
1549 env: &mut Env,
1550 qself_res: fhir::Res,
1551 assoc_segment: &fhir::PathSegment,
1552 ) -> QueryResult<rty::AliasTy> {
1553 let (assoc_item, trait_ref) =
1554 self.conv_type_relative_path(AssocTag::Type, qself_res, assoc_segment.ident)?;
1555
1556 let assoc_id = assoc_item.def_id;
1557 let mut args = trait_ref.args.to_vec();
1558 self.conv_generic_args_into(env, assoc_id, assoc_segment, &mut args)?;
1559
1560 let args = List::from_vec(args);
1561 let refine_args = List::empty();
1562 let alias_ty = rty::AliasTy { args, refine_args, def_id: assoc_id };
1563 Ok(alias_ty)
1564 }
1565
1566 fn conv_type_relative_const_path(
1567 &mut self,
1568 fhir_expr: &fhir::Expr,
1569 qself: &rty::Ty,
1570 assoc: Ident,
1571 ) -> QueryResult<rty::Expr> {
1572 let tcx = self.genv().tcx();
1573
1574 let mut candidates = vec![];
1575 if let Some(simplified_type) = qself.simplify_type() {
1576 candidates = tcx
1577 .incoherent_impls(simplified_type)
1578 .iter()
1579 .filter_map(|impl_id| {
1580 tcx.associated_items(impl_id).find_by_ident_and_kind(
1581 tcx,
1582 assoc,
1583 AssocTag::Const,
1584 *impl_id,
1585 )
1586 })
1587 .collect_vec();
1588 }
1589 let (expr, sort) = match &candidates[..] {
1590 [candidate] => self.conv_const(fhir_expr.span, candidate.def_id)?,
1591 [] => self.report_assoc_item_not_found(fhir_expr.span, AssocTag::Const)?,
1592 _ => self.report_ambiguous_assoc_item(fhir_expr.span, AssocTag::Const, assoc)?,
1593 };
1594 self.0.insert_node_sort(fhir_expr.fhir_id, sort);
1595 Ok(expr)
1596 }
1597
1598 fn refiner(&self) -> QueryResult<Refiner<'genv, 'tcx>> {
1600 match self.owner() {
1601 FluxOwnerId::Rust(owner_id) => {
1602 Refiner::default_for_item(self.genv(), owner_id.resolved_id())
1603 }
1604 FluxOwnerId::Flux(_) => Err(query_bug!("cannot refine types insicde flux item")),
1605 }
1606 }
1607
1608 fn probe_single_bound_for_assoc_item<I, Tag: AssocItemTag>(
1609 &self,
1610 all_candidates: impl FnOnce() -> I,
1611 assoc_name: Ident,
1612 tag: Tag,
1613 ) -> QueryResult<ty::PolyTraitRef<'tcx>>
1614 where
1615 I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
1616 {
1617 let mut matching_candidates = vec![];
1618 for candidate in all_candidates() {
1619 if tag
1620 .trait_defines_item_named(self.genv(), candidate.def_id(), assoc_name)?
1621 .is_some()
1622 {
1623 matching_candidates.push(candidate);
1624 }
1625 }
1626
1627 let Some(bound) = matching_candidates.pop() else {
1628 self.report_assoc_item_not_found(assoc_name.span, tag)?;
1629 };
1630
1631 if !matching_candidates.is_empty() {
1632 self.report_ambiguous_assoc_item(assoc_name.span, tag, assoc_name)?;
1633 }
1634
1635 Ok(bound)
1636 }
1637
1638 fn conv_lifetime(&mut self, env: &Env, lft: fhir::Lifetime, span: Span) -> rty::Region {
1639 let res = match lft {
1640 fhir::Lifetime::Hole(_) => return rty::Region::ReVar(self.next_region_vid()),
1641 fhir::Lifetime::Resolved(res) => res,
1642 };
1643 self.conv_resolved_lifetime(env, res, span)
1644 }
1645
1646 fn conv_resolved_lifetime(&mut self, env: &Env, res: ResolvedArg, span: Span) -> rty::Region {
1647 let tcx = self.tcx();
1648 let lifetime_name = |def_id| tcx.item_name(def_id);
1649 match res {
1650 ResolvedArg::StaticLifetime => rty::ReStatic,
1651 ResolvedArg::EarlyBound(def_id) => {
1652 let index = self.genv().def_id_to_param_index(def_id.to_def_id());
1653 let name = lifetime_name(def_id.to_def_id());
1654 rty::ReEarlyParam(rty::EarlyParamRegion { index, name })
1655 }
1656 ResolvedArg::LateBound(_, index, def_id) => {
1657 let Some(depth) = env.depth().checked_sub(1) else {
1658 span_bug!(span, "late-bound variable at depth 0")
1659 };
1660 let kind = rty::BoundRegionKind::Named(def_id.to_def_id());
1661 let var = BoundVar::from_u32(index);
1662 let bound_region = rty::BoundRegion { var, kind };
1663 rty::ReBound(rty::DebruijnIndex::from_usize(depth), bound_region)
1664 }
1665 ResolvedArg::Free(scope, id) => {
1666 let kind = rty::LateParamRegionKind::Named(id.to_def_id());
1667 rty::ReLateParam(rty::LateParamRegion { scope: scope.to_def_id(), kind })
1668 }
1669 ResolvedArg::Error(_) => bug!("lifetime resolved to an error"),
1670 }
1671 }
1672
1673 fn conv_const_arg(&mut self, cst: fhir::ConstArg) -> rty::Const {
1674 match cst.kind {
1675 fhir::ConstArgKind::Lit(lit) => rty::Const::from_usize(self.tcx(), lit),
1676 fhir::ConstArgKind::Param(def_id) => {
1677 rty::Const {
1678 kind: rty::ConstKind::Param(def_id_to_param_const(self.genv(), def_id)),
1679 }
1680 }
1681 fhir::ConstArgKind::Infer => {
1682 rty::Const {
1683 kind: rty::ConstKind::Infer(ty::InferConst::Var(self.next_const_vid())),
1684 }
1685 }
1686 }
1687 }
1688
1689 fn conv_qpath(
1690 &mut self,
1691 env: &mut Env,
1692 qself: Option<&fhir::Ty>,
1693 path: &fhir::Path,
1694 name: Option<Symbol>,
1695 ) -> QueryResult<rty::TyOrCtor> {
1696 let bty = match path.res {
1697 fhir::Res::PrimTy(prim_ty) => {
1698 self.check_prim_ty_generics(path, prim_ty)?;
1699 prim_ty_to_bty(prim_ty)
1700 }
1701 fhir::Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, did) => {
1702 let adt_def = self.genv().adt_def(did)?;
1703 let args = self.conv_generic_args(env, did, path.last_segment())?;
1704 rty::BaseTy::adt(adt_def, args)
1705 }
1706 fhir::Res::Def(DefKind::TyParam, def_id) => {
1707 let owner_id = ty_param_owner(self.genv(), def_id);
1708 let param_ty = def_id_to_param_ty(self.genv(), def_id);
1709 self.check_ty_param_generics(path, param_ty)?;
1710 let param = self
1711 .genv()
1712 .generics_of(owner_id)?
1713 .param_at(param_ty.index as usize, self.genv())?;
1714 match param.kind {
1715 rty::GenericParamDefKind::Type { .. } => {
1716 return Ok(rty::TyOrCtor::Ty(rty::Ty::param(param_ty)));
1717 }
1718 rty::GenericParamDefKind::Base { .. } => rty::BaseTy::Param(param_ty),
1719 _ => return Err(query_bug!("unexpected param kind")),
1720 }
1721 }
1722 fhir::Res::SelfTyParam { trait_ } => {
1723 self.check_self_ty_generics(path)?;
1724 let param = &self.genv().generics_of(trait_)?.own_params[0];
1725 match param.kind {
1726 rty::GenericParamDefKind::Type { .. } => {
1727 return Ok(rty::TyOrCtor::Ty(rty::Ty::param(rty::SELF_PARAM_TY)));
1728 }
1729 rty::GenericParamDefKind::Base { .. } => rty::BaseTy::Param(rty::SELF_PARAM_TY),
1730 _ => return Err(query_bug!("unexpected param kind")),
1731 }
1732 }
1733 fhir::Res::SelfTyAlias { alias_to, .. } => {
1734 self.check_self_ty_generics(path)?;
1735 if P::EXPAND_TYPE_ALIASES {
1736 return Ok(self.genv().type_of(alias_to)?.instantiate_identity());
1737 } else {
1738 rty::BaseTy::Alias(
1739 rty::AliasKind::Free,
1740 rty::AliasTy {
1741 def_id: alias_to,
1742 args: List::empty(),
1743 refine_args: List::empty(),
1744 },
1745 )
1746 }
1747 }
1748 fhir::Res::Def(DefKind::AssocTy, assoc_id) => {
1749 let trait_id = self.tcx().trait_of_assoc(assoc_id).unwrap();
1750
1751 let [.., trait_segment, assoc_segment] = path.segments else {
1752 span_bug!(path.span, "expected at least two segments");
1753 };
1754
1755 let Some(qself) = qself else {
1756 self.report_ambiguous_assoc_item(
1757 path.span,
1758 AssocTag::Type,
1759 assoc_segment.ident,
1760 )?
1761 };
1762
1763 let trait_generics = self.genv().generics_of(trait_id)?;
1764 let qself =
1765 self.conv_ty_to_generic_arg(env, &trait_generics.own_params[0], qself)?;
1766 let mut args = vec![qself];
1767 self.conv_generic_args_into(env, trait_id, trait_segment, &mut args)?;
1768 self.conv_generic_args_into(env, assoc_id, assoc_segment, &mut args)?;
1769 let args = List::from_vec(args);
1770
1771 let refine_args = List::empty();
1772 let alias_ty = rty::AliasTy { args, refine_args, def_id: assoc_id };
1773 rty::BaseTy::Alias(rty::AliasKind::Projection, alias_ty)
1774 }
1775 fhir::Res::Def(DefKind::TyAlias, def_id) => {
1776 self.check_refinement_generics(path, def_id)?;
1777 let args = self.conv_generic_args(env, def_id, path.last_segment())?;
1778 self.0.insert_path_args(path.fhir_id, args.clone());
1779 let refine_args = path
1780 .refine
1781 .iter()
1782 .map(|expr| self.conv_expr(env, expr))
1783 .try_collect_vec()?;
1784
1785 if P::EXPAND_TYPE_ALIASES {
1786 let tcx = self.tcx();
1787 return Ok(self
1788 .genv()
1789 .type_of(def_id)?
1790 .instantiate(tcx, &args, &refine_args));
1791 } else {
1792 rty::BaseTy::Alias(
1793 rty::AliasKind::Free,
1794 rty::AliasTy { def_id, args, refine_args: List::from(refine_args) },
1795 )
1796 }
1797 }
1798 fhir::Res::Def(DefKind::ForeignTy, def_id) => {
1799 self.check_foreign_ty_generics(path)?;
1800 rty::BaseTy::Foreign(def_id)
1801 }
1802 fhir::Res::Def(kind, def_id) => self.report_expected_type(path.span, kind, def_id)?,
1803 fhir::Res::Param(..) | fhir::Res::GlobalFunc(..) | fhir::Res::Err => {
1804 span_bug!(path.span, "unexpected resolution in conv_ty_ctor: {:?}", path.res)
1805 }
1806 };
1807 let sort = bty.sort();
1808 let bty = bty.shift_in_escaping(1);
1809 let kind = match name {
1810 Some(name) => BoundReftKind::Named(name),
1811 None => BoundReftKind::Anon,
1812 };
1813 let var = rty::BoundVariableKind::Refine(sort, rty::InferMode::EVar, kind);
1814 let ctor = rty::Binder::bind_with_vars(
1815 rty::Ty::indexed(bty, rty::Expr::nu()),
1816 List::singleton(var),
1817 );
1818 Ok(rty::TyOrCtor::Ctor(ctor))
1819 }
1820
1821 fn param_as_bound_var(
1822 &mut self,
1823 param: &fhir::GenericParam,
1824 ) -> QueryResult<rty::BoundVariableKind> {
1825 let def_id = param.def_id.resolved_id();
1826 match param.kind {
1827 fhir::GenericParamKind::Lifetime => {
1828 Ok(rty::BoundVariableKind::Region(rty::BoundRegionKind::Named(def_id)))
1829 }
1830 fhir::GenericParamKind::Const { .. } | fhir::GenericParamKind::Type { .. } => {
1831 Err(query_bug!(def_id, "unsupported param kind `{:?}`", param.kind))
1832 }
1833 }
1834 }
1835
1836 fn conv_generic_args(
1837 &mut self,
1838 env: &mut Env,
1839 def_id: DefId,
1840 segment: &fhir::PathSegment,
1841 ) -> QueryResult<List<rty::GenericArg>> {
1842 let mut into = vec![];
1843 self.conv_generic_args_into(env, def_id, segment, &mut into)?;
1844 Ok(List::from(into))
1845 }
1846
1847 fn conv_generic_args_into(
1848 &mut self,
1849 env: &mut Env,
1850 def_id: DefId,
1851 segment: &fhir::PathSegment,
1852 into: &mut Vec<rty::GenericArg>,
1853 ) -> QueryResult {
1854 let generics = self.genv().generics_of(def_id)?;
1855
1856 self.check_generic_arg_count(&generics, def_id, segment)?;
1857
1858 let len = into.len();
1859 for (idx, arg) in segment.args.iter().enumerate() {
1860 let param = generics.param_at(idx + len, self.genv())?;
1861 let arg = match arg {
1862 fhir::GenericArg::Lifetime(lft) => {
1863 rty::GenericArg::Lifetime(self.conv_lifetime(env, *lft, segment.ident.span))
1864 }
1865 fhir::GenericArg::Type(ty) => self.conv_ty_to_generic_arg(env, ¶m, ty)?,
1866 fhir::GenericArg::Const(cst) => rty::GenericArg::Const(self.conv_const_arg(*cst)),
1867 fhir::GenericArg::Infer => {
1868 self.conv_generic_arg_hole(env, param, segment.ident.span)?
1869 }
1870 };
1871 into.push(arg);
1872 }
1873 self.fill_generic_args_defaults(def_id, into)
1874 }
1875
1876 fn conv_generic_arg_hole(
1877 &mut self,
1878 env: &mut Env,
1879 param: rty::GenericParamDef,
1880 span: Span,
1881 ) -> QueryResult<rty::GenericArg> {
1882 match param.kind {
1883 rty::GenericParamDefKind::Type { .. } | rty::GenericParamDefKind::Base { .. } => {
1884 let ty = fhir::Ty { kind: fhir::TyKind::Infer, span };
1885 Ok(self.conv_ty_to_generic_arg(env, ¶m, &ty)?)
1886 }
1887 rty::GenericParamDefKind::Const { .. } => {
1888 let cst = fhir::ConstArg { kind: fhir::ConstArgKind::Infer, span };
1889 Ok(rty::GenericArg::Const(self.conv_const_arg(cst)))
1890 }
1891 rty::GenericParamDefKind::Lifetime => {
1892 let re = rty::Region::ReVar(self.next_region_vid());
1893 Ok(rty::GenericArg::Lifetime(re))
1894 }
1895 }
1896 }
1897
1898 fn check_generic_arg_count(
1899 &mut self,
1900 generics: &rty::Generics,
1901 def_id: DefId,
1902 segment: &fhir::PathSegment,
1903 ) -> QueryResult {
1904 let found = segment.args.len();
1905 let mut param_count = generics.own_params.len();
1906
1907 if let DefKind::Trait = self.genv().def_kind(def_id) {
1909 param_count -= 1;
1910 }
1911
1912 let min = param_count - generics.own_default_count();
1913 let max = param_count;
1914 if min == max && found != min {
1915 Err(self.emit(errors::GenericArgCountMismatch::new(
1916 self.genv(),
1917 def_id,
1918 segment,
1919 min,
1920 )))?;
1921 }
1922 if found < min {
1923 Err(self.emit(errors::TooFewGenericArgs::new(self.genv(), def_id, segment, min)))?;
1924 }
1925 if found > max {
1926 Err(self.emit(errors::TooManyGenericArgs::new(self.genv(), def_id, segment, min)))?;
1927 }
1928 Ok(())
1929 }
1930
1931 fn fill_generic_args_defaults(
1932 &mut self,
1933 def_id: DefId,
1934 into: &mut Vec<rty::GenericArg>,
1935 ) -> QueryResult {
1936 let generics = self.genv().generics_of(def_id)?;
1937 for param in generics.own_params.iter().skip(into.len()) {
1938 debug_assert!(matches!(
1939 param.kind,
1940 rty::GenericParamDefKind::Type { has_default: true }
1941 | rty::GenericParamDefKind::Base { has_default: true }
1942 ));
1943 let span = self.tcx().def_span(param.def_id);
1944 let ty = self
1947 .genv()
1948 .type_of(param.def_id)?
1949 .instantiate(self.tcx(), into, &[])
1950 .to_ty();
1951 into.push(self.try_to_ty_or_base(param.kind, span, &ty)?.into());
1952 }
1953 Ok(())
1954 }
1955
1956 fn conv_ty_to_generic_arg(
1957 &mut self,
1958 env: &mut Env,
1959 param: &rty::GenericParamDef,
1960 ty: &fhir::Ty,
1961 ) -> QueryResult<rty::GenericArg> {
1962 let rty_ty = self.conv_ty(env, ty, None)?;
1963 Ok(self.try_to_ty_or_base(param.kind, ty.span, &rty_ty)?.into())
1964 }
1965
1966 fn try_to_ty_or_base(
1967 &mut self,
1968 kind: rty::GenericParamDefKind,
1969 span: Span,
1970 ty: &rty::Ty,
1971 ) -> QueryResult<rty::TyOrBase> {
1972 match kind {
1973 rty::GenericParamDefKind::Type { .. } => Ok(rty::TyOrBase::Ty(ty.clone())),
1974 rty::GenericParamDefKind::Base { .. } => {
1975 Ok(rty::TyOrBase::Base(self.ty_to_subset_ty_ctor(span, ty)?))
1976 }
1977 _ => span_bug!(span, "unexpected param kind `{kind:?}`"),
1978 }
1979 }
1980
1981 fn ty_to_subset_ty_ctor(&mut self, span: Span, ty: &rty::Ty) -> QueryResult<rty::SubsetTyCtor> {
1982 let ctor = if let rty::TyKind::Infer(vid) = ty.kind() {
1983 let sort_vid =
1985 if vid.as_u32() == 0 { rty::SortVid::from_u32(0) } else { self.next_sort_vid() };
1986 rty::SubsetTyCtor::bind_with_sort(
1987 rty::SubsetTy::trivial(rty::BaseTy::Infer(*vid), rty::Expr::nu()),
1988 rty::Sort::Infer(sort_vid),
1989 )
1990 } else {
1991 ty.shallow_canonicalize()
1992 .as_ty_or_base()
1993 .as_base()
1994 .ok_or_else(|| self.emit(errors::InvalidBaseInstance::new(span)))?
1995 };
1996 Ok(ctor)
1997 }
1998
1999 #[track_caller]
2000 fn emit(&self, err: impl Diagnostic<'genv>) -> ErrorGuaranteed {
2001 self.genv().sess().emit_err(err)
2002 }
2003
2004 fn report_assoc_item_not_found<Tag: AssocItemTag>(
2005 &self,
2006 span: Span,
2007 assoc_tag: Tag,
2008 ) -> Result<!, ErrorGuaranteed> {
2009 Err(self.emit(errors::AssocItemNotFound { span, tag: assoc_tag.descr() }))?
2010 }
2011
2012 fn report_ambiguous_assoc_item<Tag: AssocItemTag>(
2013 &self,
2014 span: Span,
2015 assoc_tag: Tag,
2016 assoc_name: Ident,
2017 ) -> Result<!, ErrorGuaranteed> {
2018 Err(self.emit(errors::AmbiguousAssocItem {
2019 span,
2020 name: assoc_name,
2021 tag: assoc_tag.descr(),
2022 }))?
2023 }
2024
2025 #[track_caller]
2026 fn report_expected_type(
2027 &self,
2028 span: Span,
2029 kind: DefKind,
2030 def_id: DefId,
2031 ) -> Result<!, ErrorGuaranteed> {
2032 Err(self.emit(errors::ExpectedType {
2033 span,
2034 def_descr: self.tcx().def_kind_descr(kind, def_id),
2035 name: self.tcx().def_path_str(def_id),
2036 }))?
2037 }
2038}
2039
2040impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
2042 fn check_refinement_generics(&mut self, path: &fhir::Path, def_id: DefId) -> QueryResult {
2043 let generics = self.genv().refinement_generics_of(def_id)?;
2044 if generics.count() != path.refine.len() {
2045 let err = errors::RefineArgMismatch {
2046 span: path.span,
2047 expected: generics.count(),
2048 found: path.refine.len(),
2049 kind: self.tcx().def_descr(def_id),
2050 };
2051 Err(self.emit(err))?;
2052 }
2053 Ok(())
2054 }
2055
2056 fn check_prim_ty_generics(
2057 &mut self,
2058 path: &fhir::Path<'_>,
2059 prim_ty: rustc_hir::PrimTy,
2060 ) -> QueryResult {
2061 if !path.last_segment().args.is_empty() {
2062 let err = errors::GenericsOnPrimTy { span: path.span, name: prim_ty.name_str() };
2063 Err(self.emit(err))?;
2064 }
2065 Ok(())
2066 }
2067
2068 fn check_ty_param_generics(
2069 &mut self,
2070 path: &fhir::Path<'_>,
2071 param_ty: rty::ParamTy,
2072 ) -> QueryResult {
2073 if !path.last_segment().args.is_empty() {
2074 let err = errors::GenericsOnTyParam { span: path.span, name: param_ty.name };
2075 Err(self.emit(err))?;
2076 }
2077 Ok(())
2078 }
2079
2080 fn check_self_ty_generics(&mut self, path: &fhir::Path<'_>) -> QueryResult {
2081 if !path.last_segment().args.is_empty() {
2082 let err = errors::GenericsOnSelfTy { span: path.span };
2083 Err(self.emit(err))?;
2084 }
2085 Ok(())
2086 }
2087
2088 fn check_foreign_ty_generics(&mut self, path: &fhir::Path<'_>) -> QueryResult {
2089 if !path.last_segment().args.is_empty() {
2090 let err = errors::GenericsOnForeignTy { span: path.span };
2091 Err(self.emit(err))?;
2092 }
2093 Ok(())
2094 }
2095}
2096
2097fn prim_ty_to_bty(prim_ty: rustc_hir::PrimTy) -> rty::BaseTy {
2098 match prim_ty {
2099 rustc_hir::PrimTy::Int(int_ty) => rty::BaseTy::Int(int_ty),
2100 rustc_hir::PrimTy::Uint(uint_ty) => rty::BaseTy::Uint(uint_ty),
2101 rustc_hir::PrimTy::Float(float_ty) => rty::BaseTy::Float(float_ty),
2102 rustc_hir::PrimTy::Str => rty::BaseTy::Str,
2103 rustc_hir::PrimTy::Bool => rty::BaseTy::Bool,
2104 rustc_hir::PrimTy::Char => rty::BaseTy::Char,
2105 }
2106}
2107
2108impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
2110 fn conv_lit(&self, lit: fhir::Lit, fhir_id: FhirId, span: Span) -> QueryResult<rty::Constant> {
2111 match lit {
2112 fhir::Lit::Int(n, kind) => {
2113 match kind {
2114 Some(fhir::NumLitKind::Int) => Ok(rty::Constant::from(n)),
2115 Some(fhir::NumLitKind::Real) => Ok(rty::Constant::Real(rty::Real(n))),
2116 None => {
2117 let sort = self.results().node_sort(fhir_id);
2118 if let rty::Sort::BitVec(bvsize) = sort {
2119 if let rty::BvSize::Fixed(size) = bvsize
2120 && (n == 0 || n.ilog2() < size)
2121 {
2122 Ok(rty::Constant::BitVec(n, size))
2123 } else {
2124 Err(self.emit(errors::InvalidBitVectorConstant::new(span, sort)))?
2125 }
2126 } else {
2127 Ok(rty::Constant::from(n))
2128 }
2129 }
2130 }
2131 }
2132 fhir::Lit::Bool(b) => Ok(rty::Constant::from(b)),
2133 fhir::Lit::Str(s) => Ok(rty::Constant::from(s)),
2134 fhir::Lit::Char(c) => Ok(rty::Constant::from(c)),
2135 }
2136 }
2137
2138 fn conv_expr(&mut self, env: &mut Env, expr: &fhir::Expr) -> QueryResult<rty::Expr> {
2139 let fhir_id = expr.fhir_id;
2140 let espan = ESpan::new(expr.span);
2141 let expr = match expr.kind {
2142 fhir::ExprKind::Var(QPathExpr::Resolved(path, _)) => self.conv_path_expr(env, path)?,
2143 fhir::ExprKind::Var(QPathExpr::TypeRelative(qself, assoc)) => {
2144 let qself = self.conv_ty(env, qself, None)?;
2145 self.conv_type_relative_const_path(expr, &qself, assoc)?
2146 }
2147 fhir::ExprKind::Literal(lit) => {
2148 rty::Expr::constant(self.conv_lit(lit, fhir_id, expr.span)?).at(espan)
2149 }
2150 fhir::ExprKind::BinaryOp(op, e1, e2) => {
2151 rty::Expr::binary_op(
2152 self.conv_bin_op(op, expr.fhir_id),
2153 self.conv_expr(env, e1)?,
2154 self.conv_expr(env, e2)?,
2155 )
2156 .at(espan)
2157 }
2158 fhir::ExprKind::UnaryOp(op, e) => {
2159 rty::Expr::unary_op(conv_un_op(op), self.conv_expr(env, e)?).at(espan)
2160 }
2161
2162 fhir::ExprKind::PrimApp(op, e1, e2) => {
2163 rty::Expr::prim_val(
2164 self.conv_primop_val(op),
2165 self.conv_expr(env, e1)?,
2166 self.conv_expr(env, e2)?,
2167 )
2168 .at(espan)
2169 }
2170 fhir::ExprKind::App(func, args) => {
2171 let sort_args = self.results().node_sort_args(fhir_id);
2172 rty::Expr::app(self.conv_func(env, &func)?, sort_args, self.conv_exprs(env, args)?)
2173 .at(espan)
2174 }
2175 fhir::ExprKind::Alias(alias, args) => {
2176 let args = args
2177 .iter()
2178 .map(|arg| self.conv_expr(env, arg))
2179 .try_collect()?;
2180 let alias = self.conv_alias_reft(env, expr.fhir_id, &alias)?;
2181 rty::Expr::alias(alias, args).at(espan)
2182 }
2183 fhir::ExprKind::IfThenElse(p, e1, e2) => {
2184 rty::Expr::ite(
2185 self.conv_expr(env, p)?,
2186 self.conv_expr(env, e1)?,
2187 self.conv_expr(env, e2)?,
2188 )
2189 .at(espan)
2190 }
2191 fhir::ExprKind::Dot(base, _) => {
2192 let proj = self.results().field_proj(fhir_id);
2193 rty::Expr::field_proj(self.conv_expr(env, base)?, proj)
2194 }
2195 fhir::ExprKind::Abs(params, body) => {
2196 env.push_layer(Layer::list(self.results(), 0, params));
2197 let pred = self.conv_expr(env, body)?;
2198 let vars = env.pop_layer().into_bound_vars(self.genv())?;
2199 let output = self.results().node_sort(body.fhir_id);
2200 let lam = rty::Lambda::bind_with_vars(pred, vars, output);
2201 rty::Expr::abs(lam)
2202 }
2203 fhir::ExprKind::Block(decls, body) => {
2204 for decl in decls {
2205 env.push_layer(Layer::list(self.results(), 0, &[decl.param]));
2206 }
2207 let mut body = self.conv_expr(env, body)?;
2208 for decl in decls.iter().rev() {
2209 let vars = env.pop_layer().into_bound_vars(self.genv())?;
2210 let init = self.conv_expr(env, &decl.init)?;
2211 body = rty::Expr::let_(init, rty::Binder::bind_with_vars(body, vars));
2212 }
2213 body
2214 }
2215 fhir::ExprKind::BoundedQuant(kind, param, rng, body) => {
2216 env.push_layer(Layer::list(self.results(), 0, &[param]));
2217 let pred = self.conv_expr(env, body)?;
2218 let vars = env.pop_layer().into_bound_vars(self.genv())?;
2219 let body = rty::Binder::bind_with_vars(pred, vars);
2220 rty::Expr::bounded_quant(kind, rng, body)
2221 }
2222 fhir::ExprKind::Record(flds) => {
2223 let def_id = self.results().record_ctor(expr.fhir_id);
2224 let flds = flds
2225 .iter()
2226 .map(|expr| self.conv_expr(env, expr))
2227 .try_collect()?;
2228 rty::Expr::ctor_struct(def_id, flds)
2229 }
2230 fhir::ExprKind::SetLiteral(elems) => {
2231 let elems = elems
2232 .iter()
2233 .map(|expr| self.conv_expr(env, expr))
2234 .try_collect()?;
2235 rty::Expr::set(elems)
2236 }
2237 fhir::ExprKind::Constructor(path, exprs, spread) => {
2238 let def_id = if let Some(path) = path {
2239 match path.res {
2240 fhir::Res::Def(DefKind::Enum | DefKind::Struct, def_id) => def_id,
2241 _ => span_bug!(path.span, "unexpected path in constructor"),
2242 }
2243 } else {
2244 self.results().record_ctor(expr.fhir_id)
2245 };
2246 let assns = self.conv_constructor_exprs(def_id, env, exprs, &spread)?;
2247 rty::Expr::ctor_struct(def_id, assns)
2248 }
2249 fhir::ExprKind::Tuple(exprs) => {
2250 let exprs = exprs
2251 .iter()
2252 .map(|expr| self.conv_expr(env, expr))
2253 .try_collect()?;
2254 rty::Expr::tuple(exprs)
2255 }
2256 fhir::ExprKind::Err(err) => Err(QueryErr::Emitted(err))?,
2257 };
2258 Ok(self.add_coercions(expr, fhir_id))
2259 }
2260
2261 fn conv_loc(&mut self, env: &mut Env, loc: fhir::PathExpr) -> QueryResult<rty::Path> {
2262 Ok(self
2263 .conv_path_expr(env, loc)?
2264 .to_path()
2265 .unwrap_or_else(|| span_bug!(loc.span, "expected path, found `{loc:?}`")))
2266 }
2267
2268 fn conv_path_expr(&mut self, env: &mut Env, path: fhir::PathExpr) -> QueryResult<rty::Expr> {
2269 let genv = self.genv();
2270 let tcx = self.genv().tcx();
2271 let espan = ESpan::new(path.span);
2272 let (expr, sort) = match path.res {
2273 fhir::Res::Param(_, id) => (env.lookup(&path).to_expr(), self.results().param_sort(id)),
2274 fhir::Res::Def(DefKind::Const, def_id) => {
2275 self.hyperlink(path.span, tcx.def_ident_span(def_id));
2276 let (expr, sort) = self.conv_const(path.span, def_id)?;
2277 (expr.at(espan), sort)
2278 }
2279 fhir::Res::Def(DefKind::Ctor(..), ctor_id) => {
2280 let Some(sort) = genv.sort_of_def_id(ctor_id).emit(&genv)? else {
2281 span_bug!(path.span, "unexpected variant {ctor_id:?}")
2282 };
2283
2284 let variant_id = self.tcx().parent(ctor_id);
2285 let enum_id = self.tcx().parent(variant_id);
2286 self.hyperlink(path.span, tcx.def_ident_span(variant_id));
2287 let idx = variant_idx(self.tcx(), variant_id);
2288 (rty::Expr::ctor_enum(enum_id, idx), sort)
2289 }
2290 fhir::Res::Def(DefKind::ConstParam, def_id) => {
2291 self.hyperlink(path.span, tcx.def_ident_span(def_id));
2292 let sort = rty::Sort::Int;
2294 (rty::Expr::const_generic(def_id_to_param_const(genv, def_id)).at(espan), sort)
2295 }
2296 _ => {
2297 Err(self.emit(errors::InvalidRes { span: path.span, res_descr: path.res.descr() }))?
2298 }
2299 };
2300 self.0.insert_node_sort(path.fhir_id, sort);
2301 Ok(expr)
2302 }
2303
2304 fn conv_const(&self, span: Span, def_id: DefId) -> QueryResult<(rty::Expr, rty::Sort)> {
2305 match self.genv().constant_info(def_id)? {
2306 rty::ConstantInfo::Uninterpreted => {
2307 Err(self.emit(errors::ConstantAnnotationNeeded::new(span)))?
2308 }
2309 rty::ConstantInfo::Interpreted(_, sort) => {
2310 Ok((rty::Expr::const_def_id(def_id).at(ESpan::new(span)), sort))
2311 }
2312 }
2313 }
2314
2315 fn conv_constructor_exprs(
2316 &mut self,
2317 struct_def_id: DefId,
2318 env: &mut Env,
2319 exprs: &[fhir::FieldExpr],
2320 spread: &Option<&fhir::Spread>,
2321 ) -> QueryResult<List<rty::Expr>> {
2322 let spread = spread
2323 .map(|spread| self.conv_expr(env, &spread.expr))
2324 .transpose()?;
2325 let mut field_exprs_by_name: FxHashMap<Symbol, rty::Expr> = exprs
2326 .iter()
2327 .map(|field_expr| -> QueryResult<_> {
2328 Ok((field_expr.ident.name, self.conv_expr(env, &field_expr.expr)?))
2329 })
2330 .try_collect()?;
2331
2332 if !P::HAS_ELABORATED_INFORMATION {
2333 return Ok(List::default());
2334 };
2335
2336 let adt_def = self.genv().adt_sort_def_of(struct_def_id)?;
2337 let struct_variant = adt_def.struct_variant();
2338 let mut assns = Vec::new();
2339 for (idx, field_name) in struct_variant.field_names().iter().enumerate() {
2340 if let Some(expr) = field_exprs_by_name.remove(field_name) {
2341 assns.push(expr);
2342 } else if let Some(spread) = &spread {
2343 let proj = rty::FieldProj::Adt { def_id: struct_def_id, field: idx as u32 };
2344 assns.push(rty::Expr::field_proj(spread, proj));
2345 }
2346 }
2347 Ok(List::from_vec(assns))
2348 }
2349
2350 fn conv_exprs(&mut self, env: &mut Env, exprs: &[fhir::Expr]) -> QueryResult<List<rty::Expr>> {
2351 exprs.iter().map(|e| self.conv_expr(env, e)).collect()
2352 }
2353
2354 fn conv_primop_val(&self, op: fhir::BinOp) -> rty::BinOp {
2355 match op {
2356 fhir::BinOp::BitAnd => rty::BinOp::BitAnd(rty::Sort::Int),
2357 fhir::BinOp::BitOr => rty::BinOp::BitOr(rty::Sort::Int),
2358 fhir::BinOp::BitXor => rty::BinOp::BitXor(rty::Sort::Int),
2359 fhir::BinOp::BitShl => rty::BinOp::BitShl(rty::Sort::Int),
2360 fhir::BinOp::BitShr => rty::BinOp::BitShr(rty::Sort::Int),
2361 _ => bug!("unsupported primop {op:?}"),
2362 }
2363 }
2364
2365 fn conv_bin_op(&self, op: fhir::BinOp, fhir_id: FhirId) -> rty::BinOp {
2366 match op {
2367 fhir::BinOp::Iff => rty::BinOp::Iff,
2368 fhir::BinOp::Imp => rty::BinOp::Imp,
2369 fhir::BinOp::Or => rty::BinOp::Or,
2370 fhir::BinOp::And => rty::BinOp::And,
2371 fhir::BinOp::Eq => rty::BinOp::Eq,
2372 fhir::BinOp::Ne => rty::BinOp::Ne,
2373 fhir::BinOp::Gt => rty::BinOp::Gt(self.results().bin_op_sort(fhir_id)),
2374 fhir::BinOp::Ge => rty::BinOp::Ge(self.results().bin_op_sort(fhir_id)),
2375 fhir::BinOp::Lt => rty::BinOp::Lt(self.results().bin_op_sort(fhir_id)),
2376 fhir::BinOp::Le => rty::BinOp::Le(self.results().bin_op_sort(fhir_id)),
2377 fhir::BinOp::Add => rty::BinOp::Add(self.results().bin_op_sort(fhir_id)),
2378 fhir::BinOp::Sub => rty::BinOp::Sub(self.results().bin_op_sort(fhir_id)),
2379 fhir::BinOp::Mul => rty::BinOp::Mul(self.results().bin_op_sort(fhir_id)),
2380 fhir::BinOp::Mod => rty::BinOp::Mod(self.results().bin_op_sort(fhir_id)),
2381 fhir::BinOp::Div => rty::BinOp::Div(self.results().bin_op_sort(fhir_id)),
2382 fhir::BinOp::BitAnd => rty::BinOp::BitAnd(self.results().bin_op_sort(fhir_id)),
2383 fhir::BinOp::BitOr => rty::BinOp::BitOr(self.results().bin_op_sort(fhir_id)),
2384 fhir::BinOp::BitXor => rty::BinOp::BitXor(self.results().bin_op_sort(fhir_id)),
2385 fhir::BinOp::BitShl => rty::BinOp::BitShl(self.results().bin_op_sort(fhir_id)),
2386 fhir::BinOp::BitShr => rty::BinOp::BitShr(self.results().bin_op_sort(fhir_id)),
2387 }
2388 }
2389
2390 fn add_coercions(&self, mut expr: rty::Expr, fhir_id: FhirId) -> rty::Expr {
2391 let span = expr.span();
2392 for coercion in self.results().coercions_for(fhir_id) {
2393 expr = match *coercion {
2394 rty::Coercion::Inject(def_id) => {
2395 rty::Expr::ctor_struct(def_id, List::singleton(expr)).at_opt(span)
2396 }
2397 rty::Coercion::Project(def_id) => {
2398 rty::Expr::field_proj(expr, rty::FieldProj::Adt { def_id, field: 0 })
2399 .at_opt(span)
2400 }
2401 };
2402 }
2403 expr
2404 }
2405
2406 fn hyperlink(&self, span: Span, dst_span: Option<Span>) {
2407 if P::HAS_ELABORATED_INFORMATION
2408 && let Some(dst_span) = dst_span
2409 {
2410 dbg::hyperlink!(self.genv().tcx(), span, dst_span);
2411 }
2412 }
2413
2414 fn conv_func(&mut self, env: &Env, func: &fhir::PathExpr) -> QueryResult<rty::Expr> {
2415 let genv = self.genv();
2416 let span = func.span;
2417 let (expr, sort) = match func.res {
2418 fhir::Res::Param(_, id) => {
2419 let sort = self.results().param_sort(id);
2420 (env.lookup(func).to_expr(), sort)
2421 }
2422 fhir::Res::GlobalFunc(fhir::SpecFuncKind::Def(did)) => {
2423 self.hyperlink(span, Some(genv.func_span(did)));
2424 let sort = rty::Sort::Func(genv.func_sort(did));
2425 (rty::Expr::global_func(rty::SpecFuncKind::Def(did)), sort)
2426 }
2427 fhir::Res::GlobalFunc(fhir::SpecFuncKind::Thy(itf)) => {
2428 let sort = THEORY_FUNCS.get(&itf).unwrap().sort.clone();
2429 (rty::Expr::global_func(rty::SpecFuncKind::Thy(itf)), rty::Sort::Func(sort))
2430 }
2431 fhir::Res::GlobalFunc(fhir::SpecFuncKind::PtrSize) => {
2432 let fsort = rty::PolyFuncSort::new(
2433 List::empty(),
2434 rty::FuncSort::new(vec![rty::Sort::RawPtr], rty::Sort::Int),
2435 );
2436 (rty::Expr::internal_func(rty::InternalFuncKind::PtrSize), rty::Sort::Func(fsort))
2437 }
2438 fhir::Res::GlobalFunc(fhir::SpecFuncKind::Cast) => {
2439 let fsort = rty::PolyFuncSort::new(
2440 List::from_arr([rty::SortParamKind::Sort, rty::SortParamKind::Sort]),
2441 rty::FuncSort::new(
2442 vec![rty::Sort::Var(rty::ParamSort::from(0_usize))],
2443 rty::Sort::Var(rty::ParamSort::from(1_usize)),
2444 ),
2445 );
2446 (rty::Expr::internal_func(InternalFuncKind::Cast), rty::Sort::Func(fsort))
2447 }
2448 _ => {
2449 return Err(
2450 self.emit(errors::InvalidRes { span: func.span, res_descr: func.res.descr() })
2451 )?;
2452 }
2453 };
2454 self.0.insert_node_sort(func.fhir_id, sort);
2455 Ok(self.add_coercions(expr, func.fhir_id))
2456 }
2457
2458 fn conv_alias_reft(
2459 &mut self,
2460 env: &mut Env,
2461 fhir_id: FhirId,
2462 alias: &fhir::AliasReft,
2463 ) -> QueryResult<rty::AliasReft> {
2464 let alias_reft = match alias {
2465 fhir::AliasReft::Qualified { qself, trait_, name } => {
2466 let fhir::Res::Def(DefKind::Trait, trait_id) = trait_.res else {
2467 span_bug!(trait_.span, "expected trait")
2468 };
2469 let trait_segment = trait_.last_segment();
2470
2471 let generics = self.genv().generics_of(trait_id)?;
2472 let self_ty =
2473 self.conv_ty_to_generic_arg(env, &generics.param_at(0, self.genv())?, qself)?;
2474 let mut generic_args = vec![self_ty];
2475 self.conv_generic_args_into(env, trait_id, trait_segment, &mut generic_args)?;
2476
2477 let Some(assoc_reft) = self.genv().assoc_refinements_of(trait_id)?.find(name.name)
2478 else {
2479 return Err(self.emit(errors::InvalidAssocReft::new(
2480 trait_.span,
2481 name.name,
2482 format!("{:?}", trait_),
2483 )))?;
2484 };
2485
2486 let assoc_id = assoc_reft.def_id;
2487
2488 dbg::hyperlink!(self.genv().tcx(), name.span, assoc_reft.span);
2489
2490 rty::AliasReft { assoc_id, args: List::from_vec(generic_args) }
2491 }
2492 fhir::AliasReft::TypeRelative { qself, name } => {
2493 let qself_res =
2494 if let Some(path) = qself.as_path() { path.res } else { fhir::Res::Err };
2495 let (assoc_reft, trait_ref) =
2496 self.conv_type_relative_path(AssocReftTag, qself_res, *name)?;
2497 rty::AliasReft { assoc_id: assoc_reft.def_id, args: trait_ref.args }
2498 }
2499 };
2500 let fsort = alias_reft.fsort(self.genv())?;
2501 self.0.insert_alias_reft_sort(fhir_id, fsort);
2502 Ok(alias_reft)
2503 }
2504
2505 pub(crate) fn conv_invariants(
2506 &mut self,
2507 adt_id: MaybeExternId,
2508 params: &[fhir::RefineParam],
2509 invariants: &[fhir::Expr],
2510 ) -> QueryResult<Vec<rty::Invariant>> {
2511 let mut env = Env::new(&[]);
2512 env.push_layer(Layer::coalesce(self.results(), adt_id.resolved_id(), params));
2513 invariants
2514 .iter()
2515 .map(|invariant| self.conv_invariant(&mut env, invariant))
2516 .collect()
2517 }
2518
2519 fn conv_invariant(
2520 &mut self,
2521 env: &mut Env,
2522 invariant: &fhir::Expr,
2523 ) -> QueryResult<rty::Invariant> {
2524 Ok(rty::Invariant::new(rty::Binder::bind_with_vars(
2525 self.conv_expr(env, invariant)?,
2526 env.top_layer().to_bound_vars(self.genv())?,
2527 )))
2528 }
2529}
2530
2531impl Env {
2532 fn new(early_params: &[fhir::RefineParam]) -> Self {
2533 let early_params = early_params
2534 .iter()
2535 .map(|param| (param.id, param.name))
2536 .collect();
2537 Self { layers: vec![], early_params }
2538 }
2539
2540 pub(crate) fn empty() -> Self {
2541 Self { layers: vec![], early_params: Default::default() }
2542 }
2543
2544 fn depth(&self) -> usize {
2545 self.layers.len()
2546 }
2547
2548 fn push_layer(&mut self, layer: Layer) {
2549 self.layers.push(layer);
2550 }
2551
2552 fn pop_layer(&mut self) -> Layer {
2553 self.layers.pop().expect("bottom of layer stack")
2554 }
2555
2556 fn top_layer(&self) -> &Layer {
2557 self.layers.last().expect("bottom of layer stack")
2558 }
2559
2560 fn lookup(&self, var: &fhir::PathExpr) -> LookupResult<'_> {
2561 let (_, id) = var.res.expect_param();
2562 for (i, layer) in self.layers.iter().rev().enumerate() {
2563 if let Some((idx, entry)) = layer.get(id) {
2564 let debruijn = DebruijnIndex::from_usize(i);
2565 let kind = LookupResultKind::Bound {
2566 debruijn,
2567 entry,
2568 index: idx as u32,
2569 kind: layer.kind,
2570 };
2571 return LookupResult { var_span: var.span, kind };
2572 }
2573 }
2574 if let Some((idx, _, name)) = self.early_params.get_full(&id) {
2575 LookupResult {
2576 var_span: var.span,
2577 kind: LookupResultKind::EarlyParam { index: idx as u32, name: *name },
2578 }
2579 } else {
2580 span_bug!(var.span, "no entry found for key: `{:?}`", id);
2581 }
2582 }
2583
2584 fn to_early_param_args(&self) -> List<rty::Expr> {
2585 self.early_params
2586 .iter()
2587 .enumerate()
2588 .map(|(idx, (_, name))| rty::Expr::early_param(idx as u32, *name))
2589 .collect()
2590 }
2591}
2592
2593impl Layer {
2594 fn new<R: WfckResultsProvider>(
2595 results: &R,
2596 params: &[fhir::RefineParam],
2597 kind: LayerKind,
2598 ) -> Self {
2599 let map = params
2600 .iter()
2601 .map(|param| {
2602 let sort = results.param_sort(param.id);
2603 let infer_mode = rty::InferMode::from_param_kind(param.kind);
2604 let entry = ParamEntry::new(sort, infer_mode, param.name);
2605 (param.id, entry)
2606 })
2607 .collect();
2608 Self { map, kind }
2609 }
2610
2611 fn list<R: WfckResultsProvider>(
2612 results: &R,
2613 bound_regions: u32,
2614 params: &[fhir::RefineParam],
2615 ) -> Self {
2616 Self::new(results, params, LayerKind::List { bound_regions })
2617 }
2618
2619 fn coalesce<R: WfckResultsProvider>(
2620 results: &R,
2621 def_id: DefId,
2622 params: &[fhir::RefineParam],
2623 ) -> Self {
2624 Self::new(results, params, LayerKind::Coalesce(def_id))
2625 }
2626
2627 fn get(&self, name: impl Borrow<fhir::ParamId>) -> Option<(usize, &ParamEntry)> {
2628 let (idx, _, entry) = self.map.get_full(name.borrow())?;
2629 Some((idx, entry))
2630 }
2631
2632 fn into_bound_vars(self, genv: GlobalEnv) -> QueryResult<List<rty::BoundVariableKind>> {
2633 match self.kind {
2634 LayerKind::List { .. } => {
2635 Ok(self
2636 .into_iter()
2637 .map(|entry| {
2638 let kind = rty::BoundReftKind::Named(entry.name);
2639 rty::BoundVariableKind::Refine(entry.sort, entry.mode, kind)
2640 })
2641 .collect())
2642 }
2643 LayerKind::Coalesce(def_id) => {
2644 let sort_def = genv.adt_sort_def_of(def_id)?;
2645 let args = sort_def.identity_args();
2646 let ctor = rty::SortCtor::Adt(sort_def);
2647 Ok(List::singleton(rty::BoundVariableKind::Refine(
2648 rty::Sort::App(ctor, args),
2649 rty::InferMode::EVar,
2650 rty::BoundReftKind::Anon,
2651 )))
2652 }
2653 }
2654 }
2655
2656 fn to_bound_vars(&self, genv: GlobalEnv) -> QueryResult<List<rty::BoundVariableKind>> {
2657 self.clone().into_bound_vars(genv)
2658 }
2659
2660 fn into_iter(self) -> impl Iterator<Item = ParamEntry> {
2661 self.map.into_values()
2662 }
2663}
2664
2665impl ParamEntry {
2666 fn new(sort: rty::Sort, mode: fhir::InferMode, name: Symbol) -> Self {
2667 ParamEntry { name, sort, mode }
2668 }
2669}
2670
2671impl LookupResult<'_> {
2672 fn to_expr(&self) -> rty::Expr {
2673 let espan = ESpan::new(self.var_span);
2674 match &self.kind {
2675 LookupResultKind::Bound { debruijn, entry: ParamEntry { name, .. }, kind, index } => {
2676 match *kind {
2677 LayerKind::List { bound_regions } => {
2678 rty::Expr::bvar(
2679 *debruijn,
2680 BoundVar::from_u32(bound_regions + *index),
2681 rty::BoundReftKind::Named(*name),
2682 )
2683 .at(espan)
2684 }
2685 LayerKind::Coalesce(def_id) => {
2686 let var =
2687 rty::Expr::bvar(*debruijn, BoundVar::ZERO, rty::BoundReftKind::Anon)
2688 .at(espan);
2689 rty::Expr::field_proj(var, rty::FieldProj::Adt { def_id, field: *index })
2690 .at(espan)
2691 }
2692 }
2693 }
2694 &LookupResultKind::EarlyParam { index, name, .. } => {
2695 rty::Expr::early_param(index, name).at(espan)
2696 }
2697 }
2698 }
2699}
2700
2701pub fn conv_func_decl(genv: GlobalEnv, func: &fhir::SpecFunc) -> QueryResult<rty::PolyFuncSort> {
2702 let wfckresults = WfckResults::new(FluxOwnerId::Flux(func.def_id));
2703 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
2704 let inputs_and_output = func
2705 .args
2706 .iter()
2707 .map(|p| &p.sort)
2708 .chain(iter::once(&func.sort))
2709 .map(|sort| cx.conv_sort(sort))
2710 .try_collect()?;
2711 let params = iter::repeat_n(rty::SortParamKind::Sort, func.params).collect();
2712 Ok(rty::PolyFuncSort::new(params, rty::FuncSort { inputs_and_output }))
2713}
2714
2715fn conv_un_op(op: fhir::UnOp) -> rty::UnOp {
2716 match op {
2717 fhir::UnOp::Not => rty::UnOp::Not,
2718 fhir::UnOp::Neg => rty::UnOp::Neg,
2719 }
2720}
2721
2722fn def_id_to_param_ty(genv: GlobalEnv, def_id: DefId) -> rty::ParamTy {
2723 rty::ParamTy { index: genv.def_id_to_param_index(def_id), name: ty_param_name(genv, def_id) }
2724}
2725
2726fn def_id_to_param_const(genv: GlobalEnv, def_id: DefId) -> rty::ParamConst {
2727 rty::ParamConst { index: genv.def_id_to_param_index(def_id), name: ty_param_name(genv, def_id) }
2728}
2729
2730fn ty_param_owner(genv: GlobalEnv, def_id: DefId) -> DefId {
2731 let def_kind = genv.def_kind(def_id);
2732 match def_kind {
2733 DefKind::Trait | DefKind::TraitAlias => def_id,
2734 DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
2735 genv.tcx().parent(def_id)
2736 }
2737 _ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind),
2738 }
2739}
2740
2741fn ty_param_name(genv: GlobalEnv, def_id: DefId) -> Symbol {
2742 let def_kind = genv.tcx().def_kind(def_id);
2743 match def_kind {
2744 DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper,
2745 DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
2746 genv.tcx().item_name(def_id)
2747 }
2748 _ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind),
2749 }
2750}
2751
2752trait AssocItemTag: Copy {
2755 type AssocItem<'tcx>;
2756
2757 fn descr(self) -> &'static str;
2758
2759 fn trait_defines_item_named<'tcx>(
2760 self,
2761 genv: GlobalEnv<'_, 'tcx>,
2762 trait_def_id: DefId,
2763 assoc_name: Ident,
2764 ) -> QueryResult<Option<Self::AssocItem<'tcx>>>;
2765
2766 fn transitive_bounds_that_define_assoc_item<'tcx>(
2767 self,
2768 genv: GlobalEnv<'_, 'tcx>,
2769 trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
2770 assoc_name: Ident,
2771 ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>>;
2772}
2773
2774impl AssocItemTag for AssocTag {
2775 type AssocItem<'tcx> = &'tcx AssocItem;
2776
2777 fn descr(self) -> &'static str {
2778 match self {
2779 AssocTag::Const => "constant",
2780 AssocTag::Fn => "function",
2781 AssocTag::Type => "type",
2782 }
2783 }
2784
2785 fn trait_defines_item_named<'tcx>(
2786 self,
2787 genv: GlobalEnv<'_, 'tcx>,
2788 trait_def_id: DefId,
2789 assoc_name: Ident,
2790 ) -> QueryResult<Option<Self::AssocItem<'tcx>>> {
2791 Ok(genv
2792 .tcx()
2793 .associated_items(trait_def_id)
2794 .find_by_ident_and_kind(genv.tcx(), assoc_name, self, trait_def_id))
2795 }
2796
2797 fn transitive_bounds_that_define_assoc_item<'tcx>(
2798 self,
2799 genv: GlobalEnv<'_, 'tcx>,
2800 trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
2801 assoc_name: Ident,
2802 ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
2803 traits::transitive_bounds_that_define_assoc_item(genv.tcx(), trait_refs, assoc_name)
2804 }
2805}
2806
2807#[derive(Copy, Clone)]
2808struct AssocReftTag;
2809
2810impl AssocItemTag for AssocReftTag {
2811 type AssocItem<'tcx> = AssocReft;
2812
2813 fn descr(self) -> &'static str {
2814 "refinement"
2815 }
2816
2817 fn trait_defines_item_named<'tcx>(
2818 self,
2819 genv: GlobalEnv<'_, 'tcx>,
2820 trait_def_id: DefId,
2821 assoc_name: Ident,
2822 ) -> QueryResult<Option<Self::AssocItem<'tcx>>> {
2823 Ok(genv
2824 .assoc_refinements_of(trait_def_id)?
2825 .find(assoc_name.name))
2826 }
2827
2828 fn transitive_bounds_that_define_assoc_item<'tcx>(
2829 self,
2830 genv: GlobalEnv<'_, 'tcx>,
2831 trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
2832 _assoc_name: Ident,
2833 ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
2834 transitive_bounds(genv.tcx(), trait_refs)
2835 }
2836}
2837
2838fn type_param_predicates<'tcx>(
2845 tcx: TyCtxt<'tcx>,
2846 item_def_id: DefId,
2847 param_id: DefId,
2848) -> impl Iterator<Item = ty::PolyTraitPredicate<'tcx>> {
2849 let param_index = tcx
2850 .generics_of(item_def_id)
2851 .param_def_id_to_index(tcx, param_id)
2852 .unwrap();
2853 let predicates = tcx.predicates_of(item_def_id).instantiate_identity(tcx);
2854 predicates.into_iter().filter_map(move |(clause, _)| {
2855 clause
2856 .as_trait_clause()
2857 .filter(|trait_pred| trait_pred.self_ty().skip_binder().is_param(param_index))
2858 })
2859}
2860
2861fn transitive_bounds<'tcx>(
2869 tcx: TyCtxt<'tcx>,
2870 trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
2871) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
2872 let mut seen = FxHashSet::default();
2873 let mut stack: Vec<_> = trait_refs.collect();
2874
2875 std::iter::from_fn(move || {
2876 while let Some(trait_ref) = stack.pop() {
2877 if !seen.insert(tcx.anonymize_bound_vars(trait_ref)) {
2878 continue;
2879 }
2880
2881 stack.extend(
2882 tcx.explicit_super_predicates_of(trait_ref.def_id())
2883 .iter_identity_copied()
2884 .map(|(clause, _)| clause.instantiate_supertrait(tcx, trait_ref))
2885 .filter_map(|clause| clause.as_trait_clause())
2886 .filter(|clause| clause.polarity() == ty::PredicatePolarity::Positive)
2887 .map(|clause| clause.map_bound(|clause| clause.trait_ref)),
2888 );
2889
2890 return Some(trait_ref);
2891 }
2892
2893 None
2894 })
2895}
2896
2897mod errors {
2898 use flux_errors::E0999;
2899 use flux_macros::Diagnostic;
2900 use flux_middle::{fhir, global_env::GlobalEnv, rty::Sort};
2901 use rustc_hir::def_id::DefId;
2902 use rustc_span::{Span, Symbol, symbol::Ident};
2903
2904 #[derive(Diagnostic)]
2905 #[diag(fhir_analysis_assoc_item_not_found, code = E0999)]
2906 #[note]
2907 pub(super) struct AssocItemNotFound {
2908 #[primary_span]
2909 #[label]
2910 pub span: Span,
2911 pub tag: &'static str,
2912 }
2913
2914 #[derive(Diagnostic)]
2915 #[diag(fhir_analysis_ambiguous_assoc_item, code = E0999)]
2916 pub(super) struct AmbiguousAssocItem {
2917 #[primary_span]
2918 pub span: Span,
2919 pub name: Ident,
2920 pub tag: &'static str,
2921 }
2922
2923 #[derive(Diagnostic)]
2924 #[diag(fhir_analysis_invalid_base_instance, code = E0999)]
2925 pub(super) struct InvalidBaseInstance {
2926 #[primary_span]
2927 span: Span,
2928 }
2929
2930 impl InvalidBaseInstance {
2931 pub(super) fn new(span: Span) -> Self {
2932 Self { span }
2933 }
2934 }
2935
2936 #[derive(Diagnostic)]
2937 #[diag(fhir_analysis_generic_argument_count_mismatch, code = E0999)]
2938 pub(super) struct GenericArgCountMismatch {
2939 #[primary_span]
2940 #[label]
2941 span: Span,
2942 found: usize,
2943 expected: usize,
2944 def_descr: &'static str,
2945 }
2946
2947 impl GenericArgCountMismatch {
2948 pub(super) fn new(
2949 genv: GlobalEnv,
2950 def_id: DefId,
2951 segment: &fhir::PathSegment,
2952 expected: usize,
2953 ) -> Self {
2954 GenericArgCountMismatch {
2955 span: segment.ident.span,
2956 found: segment.args.len(),
2957 expected,
2958 def_descr: genv.tcx().def_descr(def_id),
2959 }
2960 }
2961 }
2962
2963 #[derive(Diagnostic)]
2964 #[diag(fhir_analysis_too_few_generic_args, code = E0999)]
2965 pub(super) struct TooFewGenericArgs {
2966 #[primary_span]
2967 #[label]
2968 span: Span,
2969 found: usize,
2970 min: usize,
2971 def_descr: &'static str,
2972 }
2973
2974 impl TooFewGenericArgs {
2975 pub(super) fn new(
2976 genv: GlobalEnv,
2977 def_id: DefId,
2978 segment: &fhir::PathSegment,
2979 min: usize,
2980 ) -> Self {
2981 Self {
2982 span: segment.ident.span,
2983 found: segment.args.len(),
2984 min,
2985 def_descr: genv.tcx().def_descr(def_id),
2986 }
2987 }
2988 }
2989
2990 #[derive(Diagnostic)]
2991 #[diag(fhir_analysis_too_many_generic_args, code = E0999)]
2992 pub(super) struct TooManyGenericArgs {
2993 #[primary_span]
2994 #[label]
2995 span: Span,
2996 found: usize,
2997 max: usize,
2998 def_descr: &'static str,
2999 }
3000
3001 impl TooManyGenericArgs {
3002 pub(super) fn new(
3003 genv: GlobalEnv,
3004 def_id: DefId,
3005 segment: &fhir::PathSegment,
3006 max: usize,
3007 ) -> Self {
3008 Self {
3009 span: segment.ident.span,
3010 found: segment.args.len(),
3011 max,
3012 def_descr: genv.tcx().def_descr(def_id),
3013 }
3014 }
3015 }
3016
3017 #[derive(Diagnostic)]
3018 #[diag(fhir_analysis_refined_unrefinable_type, code = E0999)]
3019 pub(super) struct RefinedUnrefinableType {
3020 #[primary_span]
3021 span: Span,
3022 }
3023
3024 impl RefinedUnrefinableType {
3025 pub(super) fn new(span: Span) -> Self {
3026 Self { span }
3027 }
3028 }
3029
3030 #[derive(Diagnostic)]
3031 #[diag(fhir_analysis_generics_on_primitive_sort, code = E0999)]
3032 pub(super) struct GenericsOnPrimitiveSort {
3033 #[primary_span]
3034 #[label]
3035 span: Span,
3036 name: &'static str,
3037 found: usize,
3038 expected: usize,
3039 }
3040
3041 impl GenericsOnPrimitiveSort {
3042 pub(super) fn new(span: Span, name: &'static str, found: usize, expected: usize) -> Self {
3043 Self { span, found, expected, name }
3044 }
3045 }
3046
3047 #[derive(Diagnostic)]
3048 #[diag(fhir_analysis_incorrect_generics_on_sort, code = E0999)]
3049 pub(super) struct IncorrectGenericsOnSort {
3050 #[primary_span]
3051 #[label]
3052 span: Span,
3053 found: usize,
3054 expected: usize,
3055 def_descr: &'static str,
3056 }
3057
3058 impl IncorrectGenericsOnSort {
3059 pub(super) fn new(
3060 genv: GlobalEnv,
3061 def_id: DefId,
3062 span: Span,
3063 found: usize,
3064 expected: usize,
3065 ) -> Self {
3066 Self { span, found, expected, def_descr: genv.tcx().def_descr(def_id) }
3067 }
3068 }
3069
3070 #[derive(Diagnostic)]
3071 #[diag(fhir_analysis_generics_on_sort_ty_param, code = E0999)]
3072 pub(super) struct GenericsOnSortTyParam {
3073 #[primary_span]
3074 #[label]
3075 span: Span,
3076 found: usize,
3077 }
3078
3079 impl GenericsOnSortTyParam {
3080 pub(super) fn new(span: Span, found: usize) -> Self {
3081 Self { span, found }
3082 }
3083 }
3084
3085 #[derive(Diagnostic)]
3086 #[diag(fhir_analysis_generics_on_self_alias, code = E0999)]
3087 pub(super) struct GenericsOnSelf {
3088 #[primary_span]
3089 #[label]
3090 span: Span,
3091 found: usize,
3092 }
3093
3094 impl GenericsOnSelf {
3095 pub(super) fn new(span: Span, found: usize) -> Self {
3096 Self { span, found }
3097 }
3098 }
3099
3100 #[derive(Diagnostic)]
3101 #[diag(fhir_analysis_fields_on_reflected_enum_variant, code = E0999)]
3102 pub(super) struct FieldsOnReflectedEnumVariant {
3103 #[primary_span]
3104 #[label]
3105 span: Span,
3106 }
3107
3108 impl FieldsOnReflectedEnumVariant {
3109 pub(super) fn new(span: Span) -> Self {
3110 Self { span }
3111 }
3112 }
3113
3114 #[derive(Diagnostic)]
3115 #[diag(fhir_analysis_incorrect_generics_on_opaque_sort, code = E0999)]
3116 pub(super) struct IncorrectGenericsOnUserDefinedOpaqueSort {
3117 #[primary_span]
3118 #[label]
3119 span: Span,
3120 name: Symbol,
3121 expected: usize,
3122 found: usize,
3123 }
3124
3125 impl IncorrectGenericsOnUserDefinedOpaqueSort {
3126 pub(super) fn new(span: Span, name: Symbol, expected: usize, found: usize) -> Self {
3127 Self { span, name, expected, found }
3128 }
3129 }
3130
3131 #[derive(Diagnostic)]
3132 #[diag(fhir_analysis_generics_on_prim_ty, code = E0999)]
3133 pub(super) struct GenericsOnPrimTy {
3134 #[primary_span]
3135 pub span: Span,
3136 pub name: &'static str,
3137 }
3138
3139 #[derive(Diagnostic)]
3140 #[diag(fhir_analysis_generics_on_ty_param, code = E0999)]
3141 pub(super) struct GenericsOnTyParam {
3142 #[primary_span]
3143 pub span: Span,
3144 pub name: Symbol,
3145 }
3146
3147 #[derive(Diagnostic)]
3148 #[diag(fhir_analysis_generics_on_self_ty, code = E0999)]
3149 pub(super) struct GenericsOnSelfTy {
3150 #[primary_span]
3151 pub span: Span,
3152 }
3153
3154 #[derive(Diagnostic)]
3155 #[diag(fhir_analysis_generics_on_foreign_ty, code = E0999)]
3156 pub(super) struct GenericsOnForeignTy {
3157 #[primary_span]
3158 pub span: Span,
3159 }
3160
3161 #[derive(Diagnostic)]
3162 #[diag(fhir_analysis_invalid_bitvector_constant, code = E0999)]
3163 pub struct InvalidBitVectorConstant {
3164 #[primary_span]
3165 #[label]
3166 span: Span,
3167 sort: Sort,
3168 }
3169
3170 impl InvalidBitVectorConstant {
3171 pub(crate) fn new(span: Span, sort: Sort) -> Self {
3172 Self { span, sort }
3173 }
3174 }
3175
3176 #[derive(Diagnostic)]
3177 #[diag(fhir_analysis_invalid_assoc_reft, code = E0999)]
3178 pub struct InvalidAssocReft {
3179 #[primary_span]
3180 span: Span,
3181 trait_: String,
3182 name: Symbol,
3183 }
3184
3185 impl InvalidAssocReft {
3186 pub(crate) fn new(span: Span, name: Symbol, trait_: String) -> Self {
3187 Self { span, trait_, name }
3188 }
3189 }
3190
3191 #[derive(Diagnostic)]
3192 #[diag(fhir_analysis_refine_arg_mismatch, code = E0999)]
3193 pub(super) struct RefineArgMismatch {
3194 #[primary_span]
3195 #[label]
3196 pub span: Span,
3197 pub expected: usize,
3198 pub found: usize,
3199 pub kind: &'static str,
3200 }
3201
3202 #[derive(Diagnostic)]
3203 #[diag(fhir_analysis_expected_type, code = E0999)]
3204 pub(super) struct ExpectedType {
3205 #[primary_span]
3206 pub span: Span,
3207 pub def_descr: &'static str,
3208 pub name: String,
3209 }
3210
3211 #[derive(Diagnostic)]
3212 #[diag(fhir_analysis_fail_to_match_predicates, code = E0999)]
3213 pub(super) struct FailToMatchPredicates {
3214 #[primary_span]
3215 pub span: Span,
3216 }
3217
3218 #[derive(Diagnostic)]
3219 #[diag(fhir_analysis_invalid_res, code = E0999)]
3220 pub(super) struct InvalidRes {
3221 #[primary_span]
3222 pub span: Span,
3223 pub res_descr: &'static str,
3224 }
3225
3226 #[derive(Diagnostic)]
3227 #[diag(fhir_analysis_constant_annotation_needed, code = E0999)]
3228 pub(super) struct ConstantAnnotationNeeded {
3229 #[primary_span]
3230 #[label]
3231 span: Span,
3232 }
3233 impl ConstantAnnotationNeeded {
3234 pub(super) fn new(span: Span) -> Self {
3235 Self { span }
3236 }
3237 }
3238}