1mod lift;
2
3use std::iter;
4
5use flux_common::{
6 bug, dbg,
7 index::IndexGen,
8 iter::IterExt,
9 result::{ErrorCollector, ErrorEmitter},
10 span_bug,
11};
12use flux_config as config;
13use flux_errors::Errors;
14use flux_middle::{
15 ResolverOutput,
16 def_id::{FluxLocalDefId, MaybeExternId},
17 fhir::{self, ExprRes, FhirId, FluxOwnerId, Res},
18 global_env::GlobalEnv,
19 try_alloc_slice,
20};
21use flux_syntax::{
22 surface::{self, ConstructorArg, NodeId, visit::Visitor as _},
23 walk_list,
24};
25use hir::{ItemKind, def::DefKind};
26use itertools::{Either, Itertools};
27use rustc_data_structures::fx::FxIndexSet;
28use rustc_errors::{Diagnostic, ErrorGuaranteed};
29use rustc_hash::FxHashSet;
30use rustc_hir::{self as hir, OwnerId};
31use rustc_span::{
32 DUMMY_SP, Span,
33 def_id::{DefId, LocalDefId},
34 sym,
35 symbol::kw,
36};
37
38type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
39
40use crate::{errors, resolver::refinement_resolver::SORTS};
41
42pub(crate) fn desugar_qualifier<'genv>(
43 genv: GlobalEnv<'genv, '_>,
44 resolver_output: &'genv ResolverOutput,
45 def_id: FluxLocalDefId,
46 qualifier: &surface::Qualifier,
47) -> Result<fhir::Qualifier<'genv>> {
48 FluxItemCtxt::with(genv, resolver_output, def_id, FluxItemKind::Qualifier, |cx| {
49 fhir::Qualifier {
50 def_id,
51 args: cx.desugar_refine_params(&qualifier.params),
52 global: qualifier.global,
53 expr: cx.desugar_expr(&qualifier.expr),
54 }
55 })
56}
57
58pub(crate) fn desugar_prim_prop<'genv>(
59 genv: GlobalEnv<'genv, '_>,
60 resolver_output: &'genv ResolverOutput,
61 def_id: FluxLocalDefId,
62 prim_prop: &surface::PrimOpProp,
63) -> Result<fhir::PrimProp<'genv>> {
64 FluxItemCtxt::with(genv, resolver_output, def_id, FluxItemKind::PrimProp, |cx| {
65 let body = cx.desugar_expr(&prim_prop.body);
66 let args = cx.desugar_refine_params(&prim_prop.params);
67 fhir::PrimProp { def_id, op: prim_prop.op, args, body, span: prim_prop.span }
68 })
69}
70
71pub(crate) fn desugar_spec_func<'genv>(
72 genv: GlobalEnv<'genv, '_>,
73 resolver_output: &'genv ResolverOutput,
74 def_id: FluxLocalDefId,
75 spec_func: &surface::SpecFunc,
76) -> Result<fhir::SpecFunc<'genv>> {
77 FluxItemCtxt::with(genv, resolver_output, def_id, FluxItemKind::SpecFunc, |cx| {
78 let body = spec_func.body.as_ref().map(|body| cx.desugar_expr(body));
79 let params = spec_func.sort_vars.len();
80 let sort = cx.desugar_sort(&spec_func.output, None);
81 let args = cx.desugar_refine_params(&spec_func.params);
82 fhir::SpecFunc { def_id, params, args, sort, body, hide: spec_func.hide }
83 })
84}
85
86fn collect_generics_in_params(
89 genv: GlobalEnv,
90 owner: MaybeExternId<OwnerId>,
91 resolver_output: &ResolverOutput,
92 params: &surface::RefineParams,
93) -> FxIndexSet<DefId> {
94 struct ParamCollector<'a> {
95 resolver_output: &'a ResolverOutput,
96 found: FxHashSet<DefId>,
97 }
98 impl surface::visit::Visitor for ParamCollector<'_> {
99 fn visit_base_sort(&mut self, bsort: &surface::BaseSort) {
100 if let surface::BaseSort::Path(path) = bsort {
101 let res = self.resolver_output.sort_path_res_map[&path.node_id];
102 if let fhir::SortRes::TyParam(def_id) = res {
103 self.found.insert(def_id);
104 }
105 }
106 surface::visit::walk_base_sort(self, bsort);
107 }
108 }
109 let mut vis = ParamCollector { resolver_output, found: FxHashSet::default() };
110 walk_list!(vis, visit_refine_param, params);
111 genv.tcx()
112 .generics_of(owner.resolved_id())
113 .own_params
114 .iter()
115 .filter_map(
116 |param| if vis.found.contains(¶m.def_id) { Some(param.def_id) } else { None },
117 )
118 .collect()
119}
120
121pub(crate) struct RustItemCtxt<'a, 'genv, 'tcx> {
122 genv: GlobalEnv<'genv, 'tcx>,
123 local_id_gen: IndexGen<fhir::ItemLocalId>,
124 owner: MaybeExternId<OwnerId>,
125 fn_sig_scope: Option<NodeId>,
126 resolver_output: &'genv ResolverOutput,
127 opaque_tys: Option<&'a mut Vec<&'genv fhir::OpaqueTy<'genv>>>,
128 errors: Errors<'genv>,
129}
130
131impl<'a, 'genv, 'tcx: 'genv> RustItemCtxt<'a, 'genv, 'tcx> {
132 pub(crate) fn with<T>(
133 genv: GlobalEnv<'genv, 'tcx>,
134 owner: MaybeExternId<OwnerId>,
135 resolver_output: &'genv ResolverOutput,
136 opaque_tys: Option<&'a mut Vec<&'genv fhir::OpaqueTy<'genv>>>,
137 f: impl FnOnce(&mut Self) -> Result<T>,
138 ) -> Result<T> {
139 let mut cx = RustItemCtxt {
140 genv,
141 owner,
142 fn_sig_scope: None,
143 local_id_gen: IndexGen::new(),
144 resolver_output,
145 opaque_tys,
146 errors: Errors::new(genv.sess()),
147 };
148 let r = f(&mut cx)?;
149 cx.into_result()?;
150 Ok(r)
151 }
152
153 pub(crate) fn desugar_trait(&mut self, trait_: &surface::Trait) -> Result<fhir::Item<'genv>> {
154 let generics = if let Some(generics) = &trait_.generics {
155 self.desugar_generics(generics)
156 } else {
157 self.lift_generics()
158 };
159 let assoc_refinements = self.desugar_trait_assoc_refts(&trait_.assoc_refinements)?;
160 let trait_ = fhir::Trait { assoc_refinements };
161
162 if config::dump_fhir() {
163 dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", &trait_).unwrap();
164 }
165
166 Ok(fhir::Item { generics, kind: fhir::ItemKind::Trait(trait_), owner_id: self.owner })
167 }
168
169 fn desugar_trait_assoc_refts(
170 &mut self,
171 assoc_refts: &[surface::TraitAssocReft],
172 ) -> Result<&'genv [fhir::TraitAssocReft<'genv>]> {
173 let iter = assoc_refts
174 .iter()
175 .map(|assoc_reft| {
176 let name = assoc_reft.name.name;
177 let params = self.desugar_refine_params(&assoc_reft.params);
178 let output = self.desugar_base_sort(&assoc_reft.output, None);
179 let body = assoc_reft.body.as_ref().map(|expr| self.desugar_expr(expr));
180 if body.is_none() && assoc_reft.final_ {
181 Err(self.emit(errors::FinalAssocReftWithoutBody::new(assoc_reft.span)))
182 } else {
183 Ok(fhir::TraitAssocReft {
184 name,
185 params,
186 output,
187 body,
188 span: assoc_reft.span,
189 final_: assoc_reft.final_,
190 })
191 }
192 })
193 .try_collect_vec()?
194 .into_iter();
195 Ok(self.genv().alloc_slice_fill_iter(iter))
196 }
197
198 pub(crate) fn desugar_impl(&mut self, impl_: &surface::Impl) -> fhir::Item<'genv> {
199 let generics = if let Some(generics) = &impl_.generics {
200 self.desugar_generics(generics)
201 } else {
202 self.lift_generics()
203 };
204 let assoc_refinements = self.desugar_impl_assoc_refts(&impl_.assoc_refinements);
205 let impl_ = fhir::Impl { assoc_refinements };
206
207 if config::dump_fhir() {
208 dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", &impl_).unwrap();
209 }
210
211 fhir::Item { generics, kind: fhir::ItemKind::Impl(impl_), owner_id: self.owner }
212 }
213
214 fn desugar_impl_assoc_refts(
215 &mut self,
216 assoc_refts: &[surface::ImplAssocReft],
217 ) -> &'genv [fhir::ImplAssocReft<'genv>] {
218 self.genv()
219 .alloc_slice_fill_iter(assoc_refts.iter().map(|assoc_reft| {
220 let name = assoc_reft.name.name;
221 let body = self.desugar_expr(&assoc_reft.body);
222 let params = self.desugar_refine_params(&assoc_reft.params);
223 let output = self.desugar_base_sort(&assoc_reft.output, None);
224 fhir::ImplAssocReft { name, params, output, body, span: assoc_reft.span }
225 }))
226 }
227
228 pub(crate) fn desugar_generics(
229 &mut self,
230 generics: &surface::Generics,
231 ) -> fhir::Generics<'genv> {
232 let params = self.genv.alloc_slice_fill_iter(
233 self.genv
234 .tcx()
235 .hir_get_generics(self.owner.local_id().def_id)
236 .unwrap()
237 .params
238 .iter()
239 .map(|hir_param| self.lift_generic_param(hir_param)),
240 );
241
242 let predicates = generics
243 .predicates
244 .as_ref()
245 .map(|preds| self.desugar_generic_predicates(preds));
246 fhir::Generics { params, refinement_params: &[], predicates }
247 }
248
249 fn desugar_opt_generics(
250 &mut self,
251 generics: Option<&surface::Generics>,
252 ) -> fhir::Generics<'genv> {
253 if let Some(generics) = generics {
254 self.desugar_generics(generics)
255 } else {
256 self.lift_generics()
257 }
258 }
259
260 fn desugar_generic_predicates(
261 &mut self,
262 predicates: &[surface::WhereBoundPredicate],
263 ) -> &'genv [fhir::WhereBoundPredicate<'genv>] {
264 self.genv
265 .alloc_slice_fill_iter(predicates.iter().map(|pred| {
266 let bounded_ty = self.desugar_ty(&pred.bounded_ty);
267 let bounds = self.desugar_generic_bounds(&pred.bounds);
268 fhir::WhereBoundPredicate { span: pred.span, bounded_ty, bounds }
269 }))
270 }
271
272 fn desugar_generic_bounds(
273 &mut self,
274 bounds: &[surface::TraitRef],
275 ) -> fhir::GenericBounds<'genv> {
276 self.genv().alloc_slice_fill_iter(
277 bounds
278 .iter()
279 .map(|bound| fhir::GenericBound::Trait(self.desugar_trait_ref(bound))),
280 )
281 }
282
283 fn desugar_trait_ref(&mut self, trait_ref: &surface::TraitRef) -> fhir::PolyTraitRef<'genv> {
284 let fhir::QPath::Resolved(None, path) = self.desugar_qpath(None, &trait_ref.path) else {
285 span_bug!(trait_ref.path.span, "desugar_alias_reft: unexpected qpath")
286 };
287 let span = path.span;
288
289 let refine_params = self
290 .genv
291 .alloc_slice_fill_iter(self.implicit_params_to_params(trait_ref.node_id));
292
293 fhir::PolyTraitRef {
294 bound_generic_params: &[],
295 refine_params,
296 modifiers: fhir::TraitBoundModifier::None,
297 trait_ref: path,
298 span,
299 }
300 }
301
302 fn desugar_refined_by(&mut self, refined_by: &surface::RefineParams) -> fhir::RefinedBy<'genv> {
303 let generic_id_to_var_idx =
304 collect_generics_in_params(self.genv, self.owner, self.resolver_output, refined_by);
305
306 let fields = refined_by
307 .iter()
308 .map(|param| {
309 (param.ident.name, self.desugar_sort(¶m.sort, Some(&generic_id_to_var_idx)))
310 })
311 .collect();
312
313 fhir::RefinedBy::new(fields, generic_id_to_var_idx)
314 }
315
316 pub(crate) fn desugar_struct_def(
317 &mut self,
318 struct_def: &surface::StructDef,
319 ) -> fhir::Item<'genv> {
320 let refined_by = if let Some(refined_by) = &struct_def.refined_by {
321 self.desugar_refined_by(refined_by)
322 } else {
323 fhir::RefinedBy::trivial()
324 };
325
326 let generics = self.desugar_opt_generics(struct_def.generics.as_ref());
327
328 let invariants = self.genv().alloc_slice_fill_iter(
329 struct_def
330 .invariants
331 .iter()
332 .map(|invariant| self.desugar_expr(invariant)),
333 );
334
335 let kind = if struct_def.opaque {
336 fhir::StructKind::Opaque
337 } else {
338 let kind = &self
339 .genv
340 .tcx()
341 .hir_expect_item(self.owner.local_id().def_id)
342 .kind;
343 match kind {
344 hir::ItemKind::Struct(_, _, variant_data)
345 | hir::ItemKind::Union(_, _, variant_data) => {
346 debug_assert_eq!(struct_def.fields.len(), variant_data.fields().len());
347 let fields = self.genv.alloc_slice_fill_iter(
348 iter::zip(&struct_def.fields, variant_data.fields()).map(
349 |(ty, hir_field)| {
350 if let Some(ty) = ty {
351 fhir::FieldDef { ty: self.desugar_ty(ty), lifted: false }
352 } else {
353 self.lift_field_def(hir_field)
354 }
355 },
356 ),
357 );
358 fhir::StructKind::Transparent { fields }
359 }
360 _ => bug!("expected struct or union"),
361 }
362 };
363
364 let params = self.desugar_refine_params(struct_def.refined_by.as_deref().unwrap_or(&[]));
365 let refinement = fhir::RefinementKind::Refined(refined_by);
366 let struct_def =
367 fhir::StructDef { refinement: self.genv.alloc(refinement), params, kind, invariants };
368
369 if config::dump_fhir() {
370 dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", struct_def)
371 .unwrap();
372 }
373
374 fhir::Item { generics, kind: fhir::ItemKind::Struct(struct_def), owner_id: self.owner }
375 }
376
377 pub(crate) fn desugar_enum_def(
378 &mut self,
379 enum_def: &surface::EnumDef,
380 ) -> Result<fhir::Item<'genv>> {
381 let def_id = self.owner.local_id().def_id;
382 let ItemKind::Enum(_, _, hir_enum) = self.genv.tcx().hir_expect_item(def_id).kind else {
383 bug!("expected enum");
384 };
385 let reflected = enum_def.reflected;
386 let variants = try_alloc_slice!(
387 self.genv,
388 iter::zip(&enum_def.variants, hir_enum.variants),
389 |(variant, hir_variant)| self.desugar_enum_variant_def(reflected, variant, hir_variant)
390 )?;
391
392 let kind = if enum_def.reflected {
393 fhir::RefinementKind::Reflected
394 } else if let Some(refined_by) = &enum_def.refined_by {
395 fhir::RefinementKind::Refined(self.desugar_refined_by(refined_by))
396 } else {
397 fhir::RefinementKind::Refined(fhir::RefinedBy::trivial())
398 };
399
400 let generics = self.desugar_opt_generics(enum_def.generics.as_ref());
401
402 let invariants = self.genv().alloc_slice_fill_iter(
403 enum_def
404 .invariants
405 .iter()
406 .map(|invariant| self.desugar_expr(invariant)),
407 );
408
409 let params = self.desugar_refine_params(enum_def.refined_by.as_deref().unwrap_or(&[]));
410 let enum_def =
411 fhir::EnumDef { refinement: self.genv.alloc(kind), params, variants, invariants };
412
413 if config::dump_fhir() {
414 dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", &enum_def).unwrap();
415 }
416
417 Ok(fhir::Item { generics, kind: fhir::ItemKind::Enum(enum_def), owner_id: self.owner })
418 }
419
420 fn desugar_enum_variant_def(
421 &mut self,
422 reflected: bool,
423 variant_def: &Option<surface::VariantDef>,
424 hir_variant: &hir::Variant,
425 ) -> Result<fhir::VariantDef<'genv>> {
426 if let Some(variant_def) = variant_def {
427 if reflected {
428 return Err(self.emit(errors::InvalidReflectedVariant::new(hir_variant.span)));
429 }
430 let fields = self.genv.alloc_slice_fill_iter(
431 variant_def
432 .fields
433 .iter()
434 .map(|ty| fhir::FieldDef { ty: self.desugar_ty(ty), lifted: false }),
435 );
436
437 let ret = if let Some(ret) = &variant_def.ret {
438 self.desugar_variant_ret(ret)?
439 } else {
440 self.lift_variant_ret()
441 };
442
443 let params = self
444 .genv
445 .alloc_slice_fill_iter(self.implicit_params_to_params(variant_def.node_id));
446
447 Ok(fhir::VariantDef {
448 def_id: hir_variant.def_id,
449 params,
450 fields,
451 ret,
452 span: variant_def.span,
453 lifted: false,
454 })
455 } else {
456 Ok(self.lift_enum_variant(hir_variant))
457 }
458 }
459
460 pub(crate) fn desugar_type_alias(
461 &mut self,
462 ty_alias: Option<&surface::TyAlias>,
463 ) -> fhir::Item<'genv> {
464 let Some(ty_alias) = ty_alias else {
465 return self.lift_type_alias();
466 };
467
468 let mut generics = self.desugar_generics(&ty_alias.generics);
469
470 let ty = self.desugar_ty(&ty_alias.ty);
471
472 generics.refinement_params = self.desugar_refine_params(&ty_alias.params);
473
474 let index = ty_alias
475 .index
476 .as_ref()
477 .map(|index| self.desugar_refine_param(index));
478
479 let ty_alias =
480 self.genv()
481 .alloc(fhir::TyAlias { index, ty, span: ty_alias.span, lifted: false });
482 if config::dump_fhir() {
483 dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", ty_alias).unwrap();
484 }
485 fhir::Item { generics, kind: fhir::ItemKind::TyAlias(ty_alias), owner_id: self.owner }
486 }
487
488 pub(crate) fn desugar_trait_assoc_ty(&mut self) -> fhir::TraitItem<'genv> {
489 let generics = self.lift_generics();
490 fhir::TraitItem { generics, kind: fhir::TraitItemKind::Type, owner_id: self.owner }
491 }
492
493 pub(crate) fn desugar_impl_assoc_ty(&mut self) -> fhir::ImplItem<'genv> {
494 let generics = self.lift_generics();
495 fhir::ImplItem { generics, kind: fhir::ImplItemKind::Type, owner_id: self.owner }
496 }
497
498 pub(crate) fn desugar_foreign_item(
499 &mut self,
500 foreign_item: hir::ForeignItem,
501 ) -> Result<fhir::ForeignItem<'genv>> {
502 let foreign_item = self.lift_foreign_item(foreign_item)?;
503 Ok(foreign_item)
504 }
505
506 pub(crate) fn desugar_item_fn(
507 &mut self,
508 fn_spec: &surface::FnSpec,
509 ) -> Result<fhir::Item<'genv>> {
510 let (generics, fn_sig) = self.desugar_fn_spec(fn_spec)?;
511 Ok(fhir::Item { generics, kind: fhir::ItemKind::Fn(fn_sig), owner_id: self.owner })
512 }
513
514 pub(crate) fn desugar_trait_fn(
515 &mut self,
516 fn_spec: &surface::FnSpec,
517 ) -> Result<fhir::TraitItem<'genv>> {
518 let (generics, fn_sig) = self.desugar_fn_spec(fn_spec)?;
519 Ok(fhir::TraitItem {
520 generics,
521 kind: fhir::TraitItemKind::Fn(fn_sig),
522 owner_id: self.owner,
523 })
524 }
525
526 pub(crate) fn desugar_impl_fn(
527 &mut self,
528 fn_spec: &surface::FnSpec,
529 ) -> Result<fhir::ImplItem<'genv>> {
530 let (generics, fn_sig) = self.desugar_fn_spec(fn_spec)?;
531 Ok(fhir::ImplItem { generics, kind: fhir::ImplItemKind::Fn(fn_sig), owner_id: self.owner })
532 }
533
534 pub(crate) fn desugar_const(
535 &mut self,
536 const_info: &surface::ConstantInfo,
537 ) -> fhir::Item<'genv> {
538 let expr = const_info.expr.as_ref().map(|e| self.desugar_expr(e));
539 let owner_id = self.owner;
540 let generics = self.lift_generics();
541 let kind = fhir::ItemKind::Const(expr);
542 fhir::Item { owner_id, generics, kind }
543 }
544
545 pub(crate) fn desugar_impl_const(&mut self) -> fhir::ImplItem<'genv> {
546 let owner_id = self.owner;
547 let generics = self.lift_generics();
548 fhir::ImplItem { owner_id, generics, kind: fhir::ImplItemKind::Const }
549 }
550
551 pub(crate) fn desugar_trait_const(&mut self) -> fhir::TraitItem<'genv> {
552 let owner_id = self.owner;
553 let generics = self.lift_generics();
554 fhir::TraitItem { owner_id, generics, kind: fhir::TraitItemKind::Const }
555 }
556
557 pub(crate) fn desugar_fn_spec(
558 &mut self,
559 fn_spec: &surface::FnSpec,
560 ) -> Result<(fhir::Generics<'genv>, fhir::FnSig<'genv>)> {
561 let mut header = self.lift_fn_header();
562 let (generics, decl) = if let Some(fn_sig) = &fn_spec.fn_sig {
563 self.fn_sig_scope = Some(fn_sig.node_id);
564
565 let mut requires = vec![];
566
567 let mut generics = self.desugar_generics(&fn_sig.generics);
568
569 for surface_requires in &fn_sig.requires {
570 let params = self.desugar_refine_params(&surface_requires.params);
571 let pred = self.desugar_expr(&surface_requires.pred);
572 requires.push(fhir::Requires { params, pred });
573 }
574
575 let inputs = self
577 .genv()
578 .alloc_slice_fill_iter(fn_sig.inputs.iter().map(|arg| self.desugar_fn_input(arg)));
579
580 let output = self.desugar_fn_output(fn_sig.asyncness, &fn_sig.output)?;
581
582 generics.refinement_params = self.desugar_fn_sig_refine_params(fn_sig);
583
584 let decl = fhir::FnDecl {
585 requires: self.genv.alloc_slice(&requires),
586 inputs,
587 output,
588 span: fn_sig.span,
589 lifted: false,
590 };
591 if let surface::Async::Yes { span, .. } = fn_sig.asyncness {
593 header.asyncness = hir::IsAsync::Async(span);
594 }
595 (generics, decl)
596 } else {
597 (self.lift_generics(), self.lift_fn_decl())
598 };
599 if config::dump_fhir() {
600 dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", decl).unwrap();
601 }
602
603 let qual_names = self
604 .owner
605 .as_local()
606 .map_or(&[][..], |owner_id| &self.resolver_output.qualifier_res_map[&owner_id]);
607
608 let reveal_names = self
609 .owner
610 .as_local()
611 .map_or(&[][..], |owner_id| &self.resolver_output.reveal_res_map[&owner_id]);
612
613 Ok((
614 generics,
615 fhir::FnSig {
616 header,
617 qualifiers: self.genv.alloc_slice(qual_names),
618 reveals: self.genv.alloc_slice(reveal_names),
619 decl: self.genv.alloc(decl),
620 },
621 ))
622 }
623
624 fn desugar_fn_sig_refine_params(
625 &mut self,
626 fn_sig: &surface::FnSig,
627 ) -> &'genv [fhir::RefineParam<'genv>] {
628 let genv = self.genv;
629 let mut params = self
630 .desugar_refine_params_iter(&fn_sig.params)
631 .collect_vec();
632 params.extend(self.implicit_params_to_params(fn_sig.node_id));
633
634 genv.alloc_slice(¶ms)
635 }
636
637 fn desugar_fn_output(
638 &mut self,
639 asyncness: surface::Async,
640 output: &surface::FnOutput,
641 ) -> Result<fhir::FnOutput<'genv>> {
642 let ret = self.desugar_asyncness(asyncness, &output.returns);
643
644 let ensures = try_alloc_slice!(self.genv, &output.ensures, |it| self.desugar_ensures(it))?;
645
646 let params = self
647 .genv
648 .alloc_slice_fill_iter(self.implicit_params_to_params(output.node_id));
649 Ok(fhir::FnOutput { params, ret, ensures })
650 }
651
652 fn desugar_ensures(&mut self, cstr: &surface::Ensures) -> Result<fhir::Ensures<'genv>> {
653 match cstr {
654 surface::Ensures::Type(loc, ty, node_id) => {
655 let res = self.desugar_loc(*loc, *node_id)?;
656 let path = fhir::PathExpr {
657 segments: self.genv().alloc_slice(&[*loc]),
658 res,
659 fhir_id: self.next_fhir_id(),
660 span: loc.span,
661 };
662 let ty = self.desugar_ty(ty);
663 Ok(fhir::Ensures::Type(path, ty))
664 }
665 surface::Ensures::Pred(e) => {
666 let pred = self.desugar_expr(e);
667 Ok(fhir::Ensures::Pred(pred))
668 }
669 }
670 }
671
672 fn desugar_fn_input(&mut self, input: &surface::FnInput) -> fhir::Ty<'genv> {
673 match input {
674 surface::FnInput::Constr(bind, path, pred, node_id) => {
675 let bty = self.desugar_path_to_bty(None, path);
676
677 let pred = self.desugar_expr(pred);
678
679 let ty = if let Some(idx) = self.implicit_param_into_refine_arg(*bind, *node_id) {
680 fhir::Ty { kind: fhir::TyKind::Indexed(bty, idx), span: path.span }
681 } else {
682 fhir::Ty { kind: fhir::TyKind::BaseTy(bty), span: path.span }
683 };
684
685 let span = path.span.to(pred.span);
686 let kind = fhir::TyKind::Constr(pred, self.genv.alloc(ty));
687 fhir::Ty { kind, span }
688 }
689 surface::FnInput::StrgRef(loc, ty, node_id) => {
690 let span = loc.span;
691 let (id, kind) = self.resolve_implicit_param(*node_id).unwrap();
692 let path = fhir::PathExpr {
693 segments: self.genv.alloc_slice(&[*loc]),
694 res: ExprRes::Param(kind, id),
695 fhir_id: self.next_fhir_id(),
696 span: loc.span,
697 };
698 let ty = self.desugar_ty(ty);
699 let kind = fhir::TyKind::StrgRef(
700 self.mk_lft_hole(),
701 self.genv.alloc(path),
702 self.genv.alloc(ty),
703 );
704 fhir::Ty { kind, span }
705 }
706 surface::FnInput::Ty(bind, ty, node_id) => {
707 if let Some(bind) = bind
708 && let surface::TyKind::Base(bty) = &ty.kind
709 {
710 let bty = self.desugar_bty(bty);
711 let kind =
712 if let Some(idx) = self.implicit_param_into_refine_arg(*bind, *node_id) {
713 fhir::TyKind::Indexed(bty, idx)
714 } else {
715 fhir::TyKind::BaseTy(bty)
716 };
717 fhir::Ty { kind, span: ty.span }
718 } else {
719 self.desugar_ty(ty)
720 }
721 }
722 }
723 }
724
725 fn desugar_asyncness(
726 &mut self,
727 asyncness: surface::Async,
728 returns: &surface::FnRetTy,
729 ) -> fhir::Ty<'genv> {
730 match asyncness {
731 surface::Async::Yes { node_id, span } => {
732 let def_id = self.resolver_output.impl_trait_res_map[&node_id];
733 let opaque_ty = self.desugar_opaque_ty_for_async(def_id, returns);
736 let opaque_ty = self.insert_opaque_ty(opaque_ty);
737
738 let kind = fhir::TyKind::OpaqueDef(opaque_ty);
739 fhir::Ty { kind, span }
740 }
741 surface::Async::No => self.desugar_fn_ret_ty(returns),
742 }
743 }
744
745 fn desugar_opaque_ty_for_async(
746 &mut self,
747 def_id: LocalDefId,
748 returns: &surface::FnRetTy,
749 ) -> fhir::OpaqueTy<'genv> {
750 let output = self.desugar_fn_ret_ty(returns);
751 let trait_ref = self.make_lang_item_path(
752 hir::LangItem::Future,
753 DUMMY_SP,
754 &[],
755 self.genv.alloc_slice(&[fhir::AssocItemConstraint {
756 ident: surface::Ident::with_dummy_span(sym::Output),
757 kind: fhir::AssocItemConstraintKind::Equality { term: output },
758 }]),
759 );
760 let bound = fhir::GenericBound::Trait(fhir::PolyTraitRef {
761 bound_generic_params: &[],
762 refine_params: &[],
763 modifiers: fhir::TraitBoundModifier::None,
764 trait_ref,
765 span: trait_ref.span,
766 });
767 fhir::OpaqueTy {
768 def_id: MaybeExternId::Local(def_id),
769 bounds: self.genv.alloc_slice(&[bound]),
770 }
771 }
772
773 fn make_lang_item_path(
774 &mut self,
775 lang_item: hir::LangItem,
776 span: Span,
777 args: &'genv [fhir::GenericArg<'genv>],
778 constraints: &'genv [fhir::AssocItemConstraint<'genv>],
779 ) -> fhir::Path<'genv> {
780 let def_id = self.genv.tcx().require_lang_item(lang_item, span);
781 let def_kind = self.genv.def_kind(def_id);
782 let res = Res::Def(def_kind, def_id);
783 fhir::Path {
784 span,
785 fhir_id: self.next_fhir_id(),
786 res,
787 segments: self.genv.alloc_slice_fill_iter([fhir::PathSegment {
788 ident: surface::Ident::new(lang_item.name(), span),
789 res,
790 args,
791 constraints,
792 }]),
793 refine: &[],
794 }
795 }
796
797 fn desugar_fn_ret_ty(&mut self, returns: &surface::FnRetTy) -> fhir::Ty<'genv> {
798 match returns {
799 surface::FnRetTy::Ty(ty) => self.desugar_ty(ty),
800 surface::FnRetTy::Default(span) => {
801 let kind = fhir::TyKind::Tuple(&[]);
802 fhir::Ty { kind, span: *span }
803 }
804 }
805 }
806
807 fn desugar_opaque_ty_for_impl_trait(
808 &mut self,
809 def_id: LocalDefId,
810 bounds: &[surface::TraitRef],
811 ) -> fhir::OpaqueTy<'genv> {
812 let bounds = self.desugar_generic_bounds(bounds);
813 fhir::OpaqueTy { def_id: MaybeExternId::Local(def_id), bounds }
814 }
815
816 fn desugar_variant_ret(
817 &mut self,
818 ret: &surface::VariantRet,
819 ) -> Result<fhir::VariantRet<'genv>> {
820 let Some(enum_id) = self.check_variant_ret_path(&ret.path) else {
821 return Err(self.emit(errors::InvalidVariantRet::new(&ret.path)));
822 };
823 let idx = self.desugar_indices(&ret.indices);
824 Ok(fhir::VariantRet { enum_id, idx })
825 }
826
827 fn check_variant_ret_path(&mut self, path: &surface::Path) -> Option<DefId> {
828 let resolved_id = self.owner.resolved_id();
829
830 match self.resolver_output().path_res_map[&path.node_id].full_res()? {
831 fhir::Res::Def(DefKind::Enum, def_id) if def_id == resolved_id => {}
832 fhir::Res::SelfTyAlias { .. } => return Some(resolved_id),
833 _ => return None,
834 }
835
836 let generics = self.genv.tcx().generics_of(resolved_id);
837 let args = &path.last().args;
838 if generics.own_counts().types != args.len() {
839 return None;
840 }
841 let mut i = 0;
842 for param in &generics.own_params {
843 let rustc_middle::ty::GenericParamDefKind::Type { .. } = param.kind else { continue };
844 let arg = &args[i];
845 if let surface::GenericArgKind::Type(arg_ty) = &arg.kind
846 && let surface::TyKind::Base(arg_bty) = &arg_ty.kind
847 && let surface::BaseTyKind::Path(None, arg_path) = &arg_bty.kind
848 && let fhir::Res::Def(DefKind::TyParam, def_id) =
849 self.resolver_output().path_res_map[&arg_path.node_id].full_res()?
850 && def_id == param.def_id
851 {
852 } else {
853 return None;
854 }
855 i += 1;
856 }
857
858 Some(resolved_id)
859 }
860
861 fn insert_opaque_ty(
862 &mut self,
863 opaque_ty: fhir::OpaqueTy<'genv>,
864 ) -> &'genv fhir::OpaqueTy<'genv> {
865 let opaque_ty = self.genv.alloc(opaque_ty);
866 self.opaque_tys
867 .as_mut()
868 .unwrap_or_else(|| bug!("`impl Trait` not supported in this item `{:?}`", self.owner))
869 .push(opaque_ty);
870 opaque_ty
871 }
872}
873
874impl ErrorEmitter for RustItemCtxt<'_, '_, '_> {
875 fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
876 self.errors.emit(err)
877 }
878}
879
880impl ErrorCollector<ErrorGuaranteed> for RustItemCtxt<'_, '_, '_> {
881 type Result = std::result::Result<(), ErrorGuaranteed>;
882
883 fn collect(&mut self, err: ErrorGuaranteed) {
884 self.errors.collect(err);
885 }
886
887 fn into_result(self) -> Self::Result {
888 self.errors.into_result()
889 }
890}
891
892enum FluxItemKind {
893 SpecFunc,
894 Qualifier,
895 PrimProp,
896}
897
898struct FluxItemCtxt<'genv, 'tcx> {
899 genv: GlobalEnv<'genv, 'tcx>,
900 resolver_output: &'genv ResolverOutput,
901 local_id_gen: IndexGen<fhir::ItemLocalId>,
902 owner: FluxLocalDefId,
903 kind: FluxItemKind,
904 errors: Errors<'genv>,
905}
906
907impl<'genv, 'tcx> FluxItemCtxt<'genv, 'tcx> {
908 fn with<T>(
909 genv: GlobalEnv<'genv, 'tcx>,
910 resolver_output: &'genv ResolverOutput,
911 owner: FluxLocalDefId,
912 kind: FluxItemKind,
913 f: impl FnOnce(&mut Self) -> T,
914 ) -> Result<T> {
915 let mut cx = Self {
916 genv,
917 resolver_output,
918 local_id_gen: Default::default(),
919 owner,
920 kind,
921 errors: Errors::new(genv.sess()),
922 };
923 let r = f(&mut cx);
924 cx.into_result()?;
925 Ok(r)
926 }
927}
928
929impl ErrorEmitter for FluxItemCtxt<'_, '_> {
930 fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
931 self.errors.emit(err)
932 }
933}
934
935impl ErrorCollector<ErrorGuaranteed> for FluxItemCtxt<'_, '_> {
936 type Result = std::result::Result<(), ErrorGuaranteed>;
937
938 fn collect(&mut self, err: ErrorGuaranteed) {
939 self.errors.collect(err);
940 }
941
942 fn into_result(self) -> Self::Result {
943 self.errors.into_result()
944 }
945}
946
947trait DesugarCtxt<'genv, 'tcx: 'genv>: ErrorEmitter + ErrorCollector<ErrorGuaranteed> {
948 fn genv(&self) -> GlobalEnv<'genv, 'tcx>;
949 fn resolver_output(&self) -> &'genv ResolverOutput;
950 fn next_fhir_id(&self) -> FhirId;
951 fn desugar_impl_trait(
952 &mut self,
953 node_id: NodeId,
954 bounds: &[surface::TraitRef],
955 ) -> fhir::TyKind<'genv>;
956
957 fn allow_prim_app(&self) -> bool {
958 false
959 }
960
961 fn resolve_implicit_param(&self, node_id: NodeId) -> Option<(fhir::ParamId, fhir::ParamKind)> {
962 self.resolver_output().param_res_map.get(&node_id).copied()
963 }
964
965 fn desugar_epath(&self, path: &surface::ExprPath) -> fhir::PathExpr<'genv> {
966 let res = *self
967 .resolver_output()
968 .expr_path_res_map
969 .get(&path.node_id)
970 .unwrap_or_else(|| span_bug!(path.span, "unresolved expr path"));
971
972 fhir::PathExpr {
973 segments: self
974 .genv()
975 .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident)),
976 res,
977 fhir_id: self.next_fhir_id(),
978 span: path.span,
979 }
980 }
981
982 #[track_caller]
983 fn desugar_loc(&self, ident: surface::Ident, node_id: NodeId) -> Result<ExprRes> {
984 let res = self.resolver_output().expr_path_res_map[&node_id];
985 if let ExprRes::Param(fhir::ParamKind::Loc, _) = res {
986 Ok(res)
987 } else {
988 let span = ident.span;
989 Err(self.emit(errors::InvalidLoc { span }))
990 }
991 }
992
993 #[track_caller]
994 fn resolve_param(&self, node_id: NodeId) -> (fhir::ParamId, fhir::ParamKind) {
995 self.resolver_output().param_res_map[&node_id]
996 }
997
998 fn resolve_implicit_params(
999 &self,
1000 scope: NodeId,
1001 ) -> impl ExactSizeIterator<Item = (surface::Ident, fhir::ParamId, fhir::ParamKind)> {
1002 self.resolver_output()
1003 .implicit_params
1004 .get(&scope)
1005 .map_or(&[][..], |it| it)
1006 .iter()
1007 .map(|(ident, param_id)| {
1008 let (param_id, kind) = self.resolve_param(*param_id);
1009 (*ident, param_id, kind)
1010 })
1011 }
1012
1013 fn implicit_params_to_params(
1014 &self,
1015 scope: NodeId,
1016 ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
1017 self.resolve_implicit_params(scope)
1018 .map(|(ident, id, kind)| {
1019 let sort = if kind.is_loc() { fhir::Sort::Loc } else { fhir::Sort::Infer };
1020 fhir::RefineParam {
1021 id,
1022 name: ident.name,
1023 span: ident.span,
1024 kind,
1025 sort,
1026 fhir_id: self.next_fhir_id(),
1027 }
1028 })
1029 }
1030
1031 fn desugar_refine_params(
1032 &mut self,
1033 params: &[surface::RefineParam],
1034 ) -> &'genv [fhir::RefineParam<'genv>] {
1035 self.genv()
1036 .alloc_slice_fill_iter(self.desugar_refine_params_iter(params))
1037 }
1038
1039 fn desugar_refine_params_iter(
1040 &mut self,
1041 params: &[surface::RefineParam],
1042 ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
1043 params.iter().map(|param| self.desugar_refine_param(param))
1044 }
1045
1046 fn desugar_refine_param(&mut self, param: &surface::RefineParam) -> fhir::RefineParam<'genv> {
1047 let (id, kind) = self.resolve_param(param.node_id);
1048 fhir::RefineParam {
1049 id,
1050 name: param.ident.name,
1051 span: param.ident.span,
1052 kind,
1053 sort: self.desugar_sort(¶m.sort, None),
1054 fhir_id: self.next_fhir_id(),
1055 }
1056 }
1057
1058 fn desugar_sort(
1059 &mut self,
1060 sort: &surface::Sort,
1061 generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1062 ) -> fhir::Sort<'genv> {
1063 match sort {
1064 surface::Sort::Base(bsort) => self.desugar_base_sort(bsort, generic_id_to_var_idx),
1065 surface::Sort::Func { inputs, output } => {
1066 let inputs_and_output = self.genv().alloc_slice_with_capacity(
1067 inputs.len() + 1,
1068 inputs
1069 .iter()
1070 .chain(iter::once(output))
1071 .map(|sort| self.desugar_base_sort(sort, generic_id_to_var_idx)),
1072 );
1073 fhir::Sort::Func(fhir::PolyFuncSort::new(0, inputs_and_output))
1074 }
1075 surface::Sort::Infer => fhir::Sort::Infer,
1076 }
1077 }
1078
1079 fn desugar_base_sort(
1080 &mut self,
1081 sort: &surface::BaseSort,
1082 generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1083 ) -> fhir::Sort<'genv> {
1084 let genv = self.genv();
1085 match sort {
1086 surface::BaseSort::BitVec(width) => fhir::Sort::BitVec(*width),
1087 surface::BaseSort::Path(surface::SortPath { segments, args, node_id }) => {
1088 let res = self.resolver_output().sort_path_res_map[node_id];
1089
1090 let res = if let fhir::SortRes::TyParam(def_id) = res
1092 && let Some(generic_id_to_var_idx) = generic_id_to_var_idx
1093 {
1094 let idx = generic_id_to_var_idx.get_index_of(&def_id).unwrap();
1095 fhir::SortRes::SortParam(idx)
1096 } else {
1097 res
1098 };
1099
1100 let args = genv.alloc_slice_fill_iter(
1101 args.iter()
1102 .map(|s| self.desugar_base_sort(s, generic_id_to_var_idx)),
1103 );
1104
1105 let path = fhir::SortPath { res, segments: genv.alloc_slice(segments), args };
1106 fhir::Sort::Path(path)
1107 }
1108 surface::BaseSort::SortOf(qself, path) => {
1109 fhir::Sort::SortOf(self.desugar_path_to_bty(Some(qself), path))
1110 }
1111 }
1112 }
1113
1114 fn desugar_generic_args(
1115 &mut self,
1116 res: Res,
1117 args: &[surface::GenericArg],
1118 ) -> (&'genv [fhir::GenericArg<'genv>], &'genv [fhir::AssocItemConstraint<'genv>]) {
1119 let mut fhir_args = vec![];
1120 let mut constraints = vec![];
1121 if let Res::Def(
1122 DefKind::TyAlias | DefKind::Struct | DefKind::Enum | DefKind::OpaqueTy,
1123 def_id,
1124 ) = res
1125 {
1126 let generics = self.genv().tcx().generics_of(def_id);
1127 for param in &generics.own_params {
1128 if let rustc_middle::ty::GenericParamDefKind::Lifetime = param.kind {
1129 fhir_args.push(fhir::GenericArg::Lifetime(self.mk_lft_hole()));
1130 }
1131 }
1132 }
1133 for arg in args {
1134 match &arg.kind {
1135 surface::GenericArgKind::Type(ty) if matches!(ty.kind, surface::TyKind::Hole) => {
1136 fhir_args.push(fhir::GenericArg::Infer);
1137 }
1138 surface::GenericArgKind::Type(ty) => {
1139 let ty = self.desugar_ty(ty);
1140 fhir_args.push(fhir::GenericArg::Type(self.genv().alloc(ty)));
1141 }
1142 surface::GenericArgKind::Constraint(ident, ty) => {
1143 constraints.push(fhir::AssocItemConstraint {
1144 ident: *ident,
1145 kind: fhir::AssocItemConstraintKind::Equality { term: self.desugar_ty(ty) },
1146 });
1147 }
1148 }
1149 }
1150 (self.genv().alloc_slice(&fhir_args), self.genv().alloc_slice(&constraints))
1151 }
1152
1153 fn desugar_ty(&mut self, ty: &surface::Ty) -> fhir::Ty<'genv> {
1158 let node_id = ty.node_id;
1159 let span = ty.span;
1160 let kind = match &ty.kind {
1161 surface::TyKind::Base(bty) => {
1162 let bty = self.desugar_bty(bty);
1163 fhir::TyKind::BaseTy(bty)
1164 }
1165 surface::TyKind::Indexed { bty, indices } => {
1166 let bty = self.desugar_bty(bty);
1167 let idx = self.desugar_indices(indices);
1168 fhir::TyKind::Indexed(bty, idx)
1169 }
1170 surface::TyKind::Exists { bind, bty, pred } => {
1171 let ty_span = ty.span;
1172 let bty_span = bty.span;
1173
1174 let bty = self.desugar_bty(bty);
1175 let pred = self.desugar_expr(pred);
1176
1177 let (id, kind) = self.resolve_param(node_id);
1178 let param = fhir::RefineParam {
1179 id,
1180 name: bind.name,
1181 span: bind.span,
1182 sort: fhir::Sort::Infer,
1183 kind,
1184 fhir_id: self.next_fhir_id(),
1185 };
1186 let path = fhir::PathExpr {
1187 segments: self.genv().alloc_slice(&[*bind]),
1188 res: ExprRes::Param(kind, id),
1189 fhir_id: self.next_fhir_id(),
1190 span: bind.span,
1191 };
1192 let idx = fhir::Expr {
1193 kind: fhir::ExprKind::Var(path, None),
1194 span: bind.span,
1195 fhir_id: self.next_fhir_id(),
1196 };
1197 let indexed = fhir::Ty { kind: fhir::TyKind::Indexed(bty, idx), span: bty_span };
1198 let constr = fhir::Ty {
1199 kind: fhir::TyKind::Constr(pred, self.genv().alloc(indexed)),
1200 span: ty_span,
1201 };
1202 fhir::TyKind::Exists(self.genv().alloc_slice(&[param]), self.genv().alloc(constr))
1203 }
1204 surface::TyKind::GeneralExists { params, ty, pred } => {
1205 let mut ty = self.desugar_ty(ty);
1206 if let Some(pred) = pred {
1207 let pred = self.desugar_expr(pred);
1208 ty = fhir::Ty { kind: fhir::TyKind::Constr(pred, self.genv().alloc(ty)), span };
1209 }
1210 let params = self.desugar_refine_params(params);
1211
1212 fhir::TyKind::Exists(params, self.genv().alloc(ty))
1213 }
1214 surface::TyKind::Constr(pred, ty) => {
1215 let pred = self.desugar_expr(pred);
1216 let ty = self.desugar_ty(ty);
1217 fhir::TyKind::Constr(pred, self.genv().alloc(ty))
1218 }
1219 surface::TyKind::Ref(mutbl, ty) => {
1220 let ty = self.desugar_ty(ty);
1221 let mut_ty = fhir::MutTy { ty: self.genv().alloc(ty), mutbl: *mutbl };
1222 fhir::TyKind::Ref(self.mk_lft_hole(), mut_ty)
1223 }
1224 surface::TyKind::Tuple(tys) => {
1225 let tys = self
1226 .genv()
1227 .alloc_slice_fill_iter(tys.iter().map(|ty| self.desugar_ty(ty)));
1228 fhir::TyKind::Tuple(tys)
1229 }
1230 surface::TyKind::Array(ty, len) => {
1231 let ty = self.desugar_ty(ty);
1232 let len = Self::desugar_const_arg(len);
1233 fhir::TyKind::Array(self.genv().alloc(ty), len)
1234 }
1235 surface::TyKind::ImplTrait(node_id, bounds) => {
1236 self.desugar_impl_trait(*node_id, bounds)
1237 }
1238 surface::TyKind::Hole => fhir::TyKind::Infer,
1239 };
1240 fhir::Ty { kind, span }
1241 }
1242
1243 fn desugar_const_arg(const_arg: &surface::ConstArg) -> fhir::ConstArg {
1244 let kind = match const_arg.kind {
1245 surface::ConstArgKind::Lit(val) => fhir::ConstArgKind::Lit(val),
1246 surface::ConstArgKind::Infer => fhir::ConstArgKind::Infer,
1247 };
1248 fhir::ConstArg { kind, span: const_arg.span }
1249 }
1250
1251 fn desugar_bty(&mut self, bty: &surface::BaseTy) -> fhir::BaseTy<'genv> {
1252 match &bty.kind {
1253 surface::BaseTyKind::Path(qself, path) => {
1254 let qpath = self.desugar_qpath(qself.as_deref(), path);
1255 fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1256 }
1257 surface::BaseTyKind::Slice(ty) => {
1258 let ty = self.desugar_ty(ty);
1259 let kind = fhir::BaseTyKind::Slice(self.genv().alloc(ty));
1260 fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: bty.span }
1261 }
1262 }
1263 }
1264
1265 fn desugar_path_to_bty(
1266 &mut self,
1267 qself: Option<&surface::Ty>,
1268 path: &surface::Path,
1269 ) -> fhir::BaseTy<'genv> {
1270 let qpath = self.desugar_qpath(qself, path);
1271 fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1272 }
1273
1274 fn desugar_qpath(
1275 &mut self,
1276 qself: Option<&surface::Ty>,
1277 path: &surface::Path,
1278 ) -> fhir::QPath<'genv> {
1279 let qself = if let Some(ty) = qself {
1280 let ty = self.desugar_ty(ty);
1281 Some(self.genv().alloc(ty))
1282 } else {
1283 None
1284 };
1285 let partial_res = self.resolver_output().path_res_map[&path.node_id];
1286
1287 let unresolved_segments = partial_res.unresolved_segments();
1288
1289 let proj_start = path.segments.len() - unresolved_segments;
1290 let fhir_path = fhir::Path {
1291 res: partial_res.base_res(),
1292 fhir_id: self.next_fhir_id(),
1293 segments: self.genv().alloc_slice_fill_iter(
1294 path.segments[..proj_start]
1295 .iter()
1296 .map(|segment| self.desugar_path_segment(segment)),
1297 ),
1298 refine: self
1299 .genv()
1300 .alloc_slice_fill_iter(path.refine.iter().map(|arg| self.desugar_refine_arg(arg))),
1301 span: path.span,
1302 };
1303
1304 if unresolved_segments == 0 {
1307 return fhir::QPath::Resolved(qself, fhir_path);
1308 }
1309
1310 let mut ty = if fhir_path.segments.is_empty() {
1312 qself.expect("missing QSelf for <T>::...")
1315 } else {
1316 self.genv()
1320 .alloc(self.ty_path(fhir::QPath::Resolved(qself, fhir_path)))
1321 };
1322
1323 for (i, segment) in path.segments.iter().enumerate().skip(proj_start) {
1324 let hir_segment = self.desugar_path_segment(segment);
1325 let qpath = fhir::QPath::TypeRelative(ty, self.genv().alloc(hir_segment));
1326
1327 if i == path.segments.len() - 1 {
1328 return qpath;
1329 }
1330
1331 ty = self.genv().alloc(self.ty_path(qpath));
1332 }
1333
1334 span_bug!(
1335 path.span,
1336 "desugar_qpath: no final extension segment in {}..{}",
1337 proj_start,
1338 path.segments.len()
1339 );
1340 }
1341
1342 fn desugar_path_segment(&mut self, segment: &surface::PathSegment) -> fhir::PathSegment<'genv> {
1343 let res = self
1344 .resolver_output()
1345 .path_res_map
1346 .get(&segment.node_id)
1347 .map_or(Res::Err, |r| r.expect_full_res());
1348 let (args, constraints) = self.desugar_generic_args(res, &segment.args);
1349 fhir::PathSegment { ident: segment.ident, res, args, constraints }
1350 }
1351
1352 fn ty_path(&self, qpath: fhir::QPath<'genv>) -> fhir::Ty<'genv> {
1353 fhir::Ty {
1354 span: qpath.span(),
1355 kind: fhir::TyKind::BaseTy(fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())),
1356 }
1357 }
1358
1359 fn mk_lft_hole(&self) -> fhir::Lifetime {
1360 fhir::Lifetime::Hole(self.next_fhir_id())
1361 }
1362
1363 fn desugar_indices(&mut self, idxs: &surface::Indices) -> fhir::Expr<'genv> {
1364 if let [arg] = &idxs.indices[..] {
1365 self.desugar_refine_arg(arg)
1366 } else {
1367 let flds = self
1368 .genv()
1369 .alloc_slice_fill_iter(idxs.indices.iter().map(|arg| self.desugar_refine_arg(arg)));
1370 fhir::Expr {
1371 kind: fhir::ExprKind::Record(flds),
1372 fhir_id: self.next_fhir_id(),
1373 span: idxs.span,
1374 }
1375 }
1376 }
1377
1378 fn desugar_refine_arg(&mut self, arg: &surface::RefineArg) -> fhir::Expr<'genv> {
1379 match arg {
1380 surface::RefineArg::Bind(ident, .., node_id) => {
1381 self.implicit_param_into_refine_arg(*ident, *node_id)
1382 .unwrap()
1383 }
1384 surface::RefineArg::Expr(expr) => self.desugar_expr(expr),
1385 surface::RefineArg::Abs(params, body, span, _) => {
1386 let body = self.genv().alloc(self.desugar_expr(body));
1387 let params = self.desugar_refine_params(params);
1388 fhir::Expr {
1389 kind: fhir::ExprKind::Abs(params, body),
1390 fhir_id: self.next_fhir_id(),
1391 span: *span,
1392 }
1393 }
1394 }
1395 }
1396
1397 fn implicit_param_into_refine_arg(
1398 &self,
1399 ident: surface::Ident,
1400 node_id: NodeId,
1401 ) -> Option<fhir::Expr<'genv>> {
1402 let (id, kind) = self.resolve_implicit_param(node_id)?;
1403 let path = fhir::PathExpr {
1404 segments: self.genv().alloc_slice(&[ident]),
1405 res: ExprRes::Param(kind, id),
1406 fhir_id: self.next_fhir_id(),
1407 span: ident.span,
1408 };
1409 Some(fhir::Expr {
1410 kind: fhir::ExprKind::Var(path, Some(kind)),
1411 span: ident.span,
1412 fhir_id: self.next_fhir_id(),
1413 })
1414 }
1415
1416 fn desugar_expr(&mut self, expr: &surface::Expr) -> fhir::Expr<'genv> {
1417 let kind = match &expr.kind {
1418 surface::ExprKind::Path(path) => fhir::ExprKind::Var(self.desugar_epath(path), None),
1419 surface::ExprKind::Literal(lit) => self.desugar_lit(expr.span, *lit),
1420 surface::ExprKind::BinaryOp(op, box [e1, e2]) => {
1421 let e1 = self.desugar_expr(e1);
1422 let e2 = self.desugar_expr(e2);
1423 fhir::ExprKind::BinaryOp(*op, self.genv().alloc(e1), self.genv().alloc(e2))
1424 }
1425 surface::ExprKind::UnaryOp(op, box e) => {
1426 fhir::ExprKind::UnaryOp(*op, self.genv().alloc(self.desugar_expr(e)))
1427 }
1428 surface::ExprKind::Dot(base, fld) => {
1429 let base = self.desugar_expr(base);
1430 fhir::ExprKind::Dot(self.genv().alloc(base), *fld)
1431 }
1432 surface::ExprKind::Call(callee, args) => self.desugar_call(callee, args),
1433 surface::ExprKind::AssocReft(..) | surface::ExprKind::PrimUIF(..) => {
1434 fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(expr.span)))
1435 }
1436 surface::ExprKind::IfThenElse(box [p, e1, e2]) => {
1437 let p = self.desugar_expr(p);
1438 let e1 = self.desugar_expr(e1);
1439 let e2 = self.desugar_expr(e2);
1440 fhir::ExprKind::IfThenElse(
1441 self.genv().alloc(p),
1442 self.genv().alloc(e1),
1443 self.genv().alloc(e2),
1444 )
1445 }
1446 surface::ExprKind::Constructor(path, args) => {
1447 self.desugar_constructor(path.as_ref(), args)
1448 }
1449 surface::ExprKind::BoundedQuant(kind, param, rng, body) => {
1450 let kind = match kind {
1451 surface::QuantKind::Exists => fhir::QuantKind::Exists,
1452 surface::QuantKind::Forall => fhir::QuantKind::Forall,
1453 };
1454 let body = self.genv().alloc(self.desugar_expr(body));
1455 let param = self.desugar_refine_param(param);
1456 let rng = fhir::Range { start: rng.start, end: rng.end };
1457 fhir::ExprKind::BoundedQuant(kind, param, rng, body)
1458 }
1459 surface::ExprKind::Block(decls, body) => {
1460 let decls = self.genv().alloc_slice_fill_iter(decls.iter().map(|decl| {
1461 fhir::LetDecl {
1462 param: self.desugar_refine_param(&decl.param),
1463 init: self.desugar_expr(&decl.init),
1464 }
1465 }));
1466 let body = self.genv().alloc(self.desugar_expr(body));
1467 fhir::ExprKind::Block(decls, body)
1468 }
1469 };
1470
1471 fhir::Expr { kind, span: expr.span, fhir_id: self.next_fhir_id() }
1472 }
1473
1474 fn desugar_call(
1475 &mut self,
1476 callee: &surface::Expr,
1477 args: &[surface::Expr],
1478 ) -> fhir::ExprKind<'genv> {
1479 let args = self.desugar_exprs(args);
1480 match &callee.kind {
1481 surface::ExprKind::Path(path) => {
1482 let path = self.desugar_epath(path);
1483 fhir::ExprKind::App(path, args)
1484 }
1485 surface::ExprKind::PrimUIF(op) if args.len() == 2 && self.allow_prim_app() => {
1486 fhir::ExprKind::PrimApp(*op, &args[0], &args[1])
1487 }
1488 surface::ExprKind::AssocReft(qself, path, name) => {
1489 let qself = self.desugar_ty(qself);
1490 let fhir::QPath::Resolved(None, fpath) = self.desugar_qpath(None, path) else {
1491 span_bug!(path.span, "desugar_alias_reft: unexpected qpath")
1492 };
1493 let Res::Def(DefKind::Trait, _) = fpath.res else {
1494 return fhir::ExprKind::Err(self.emit(errors::InvalidAliasReft::new(path)));
1496 };
1497 let alias_reft = fhir::AliasReft {
1498 qself: self.genv().alloc(qself),
1499 path: fpath,
1500 name: name.name,
1501 };
1502 fhir::ExprKind::Alias(alias_reft, args)
1503 }
1504 _ => fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(callee.span))),
1505 }
1506 }
1507
1508 fn desugar_constructor(
1509 &mut self,
1510 path: Option<&surface::ExprPath>,
1511 args: &[surface::ConstructorArg],
1512 ) -> fhir::ExprKind<'genv> {
1513 let path = if let Some(path) = path {
1514 let res = self.resolver_output().expr_path_res_map[&path.node_id];
1515 if !matches!(res, ExprRes::Ctor(..)) {
1516 return fhir::ExprKind::Err(
1517 self.emit(errors::InvalidConstructorPath { span: path.span }),
1518 );
1519 };
1520 let segments = self
1521 .genv()
1522 .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident));
1523 Some(fhir::PathExpr { segments, res, fhir_id: self.next_fhir_id(), span: path.span })
1524 } else {
1525 None
1526 };
1527
1528 let (field_exprs, spreads): (Vec<_>, Vec<_>) = args.iter().partition_map(|arg| {
1529 match arg {
1530 ConstructorArg::FieldExpr(e) => Either::Left(e),
1531 ConstructorArg::Spread(s) => Either::Right(s),
1532 }
1533 });
1534
1535 let field_exprs = self
1536 .genv()
1537 .alloc_slice_fill_iter(field_exprs.iter().map(|field_expr| {
1538 let e = self.desugar_expr(&field_expr.expr);
1539 fhir::FieldExpr {
1540 ident: field_expr.ident,
1541 expr: e,
1542 fhir_id: self.next_fhir_id(),
1543 span: e.span,
1544 }
1545 }));
1546
1547 match &spreads[..] {
1548 [] => fhir::ExprKind::Constructor(path, field_exprs, None),
1549 [s] => {
1550 let spread = fhir::Spread {
1551 expr: self.desugar_expr(&s.expr),
1552 span: s.span,
1553 fhir_id: self.next_fhir_id(),
1554 };
1555 fhir::ExprKind::Constructor(path, field_exprs, Some(self.genv().alloc(spread)))
1556 }
1557 [s1, s2, ..] => {
1558 let err = errors::MultipleSpreadsInConstructor::new(s1.span, s2.span);
1559 fhir::ExprKind::Err(self.emit(err))
1560 }
1561 }
1562 }
1563
1564 fn desugar_exprs(&mut self, exprs: &[surface::Expr]) -> &'genv [fhir::Expr<'genv>] {
1565 self.genv()
1566 .alloc_slice_fill_iter(exprs.iter().map(|e| self.desugar_expr(e)))
1567 }
1568
1569 fn try_parse_int_lit(&self, span: Span, s: &str) -> Result<u128> {
1570 let s = s.replace("_", "");
1571 let parsed_int = if s.len() <= 2 {
1572 s.parse::<u128>()
1573 } else {
1574 match &s[0..2] {
1575 "0x" => u128::from_str_radix(&s[2..], 16), "0o" => u128::from_str_radix(&s[2..], 8), "0b" => u128::from_str_radix(&s[2..], 2), _ => s.parse::<u128>(), }
1580 };
1581
1582 if let Ok(n) = parsed_int {
1583 Ok(n) } else {
1585 Err(self.emit(errors::IntTooLarge { span }))
1586 }
1587 }
1588
1589 fn desugar_lit(&self, span: Span, lit: surface::Lit) -> fhir::ExprKind<'genv> {
1591 let lit = match lit.kind {
1592 surface::LitKind::Integer => {
1593 let n = match self.try_parse_int_lit(span, lit.symbol.as_str()) {
1594 Ok(n) => n,
1595 Err(err) => return fhir::ExprKind::Err(err),
1596 };
1597 let suffix = lit.suffix.unwrap_or(SORTS.int);
1598 if suffix == SORTS.int {
1599 fhir::Lit::Int(n)
1600 } else if suffix == SORTS.real {
1601 fhir::Lit::Real(n)
1602 } else {
1603 return fhir::ExprKind::Err(
1604 self.emit(errors::InvalidNumericSuffix::new(span, suffix)),
1605 );
1606 }
1607 }
1608 surface::LitKind::Bool => fhir::Lit::Bool(lit.symbol == kw::True),
1609 surface::LitKind::Str => fhir::Lit::Str(lit.symbol),
1610 surface::LitKind::Char => fhir::Lit::Char(lit.symbol.as_str().parse::<char>().unwrap()),
1611 _ => return fhir::ExprKind::Err(self.emit(errors::UnexpectedLiteral { span })),
1612 };
1613 fhir::ExprKind::Literal(lit)
1614 }
1615}
1616
1617impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for RustItemCtxt<'_, 'genv, 'tcx> {
1618 fn next_fhir_id(&self) -> FhirId {
1619 FhirId {
1620 owner: FluxOwnerId::Rust(self.owner.local_id()),
1621 local_id: self.local_id_gen.fresh(),
1622 }
1623 }
1624
1625 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1626 self.genv
1627 }
1628
1629 fn resolver_output(&self) -> &'genv ResolverOutput {
1630 self.resolver_output
1631 }
1632
1633 fn desugar_impl_trait(
1634 &mut self,
1635 node_id: NodeId,
1636 bounds: &[surface::TraitRef],
1637 ) -> fhir::TyKind<'genv> {
1638 let def_id = self.resolver_output().impl_trait_res_map[&node_id];
1639
1640 let opaque_ty = self.desugar_opaque_ty_for_impl_trait(def_id, bounds);
1643 let opaque_ty = self.insert_opaque_ty(opaque_ty);
1644
1645 fhir::TyKind::OpaqueDef(opaque_ty)
1646 }
1647}
1648
1649impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for FluxItemCtxt<'genv, 'tcx> {
1650 fn next_fhir_id(&self) -> FhirId {
1651 FhirId { owner: FluxOwnerId::Flux(self.owner), local_id: self.local_id_gen.fresh() }
1652 }
1653
1654 fn allow_prim_app(&self) -> bool {
1655 matches!(self.kind, FluxItemKind::PrimProp)
1656 }
1657
1658 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1659 self.genv
1660 }
1661
1662 fn resolver_output(&self) -> &'genv ResolverOutput {
1663 self.resolver_output
1664 }
1665
1666 fn desugar_impl_trait(&mut self, _: NodeId, _: &[surface::TraitRef]) -> fhir::TyKind<'genv> {
1667 unimplemented!("`impl Trait` not supported in this item")
1668 }
1669}