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, FhirId, FluxOwnerId, ParamId, Res},
18 global_env::GlobalEnv,
19 try_alloc_slice,
20};
21use flux_syntax::{
22 surface::{self, ConstructorArg, NodeId, visit::Visitor as _},
23 symbols::{kw, sym},
24 walk_list,
25};
26use hir::{ItemKind, def::DefKind};
27use itertools::{Either, Itertools};
28use rustc_data_structures::fx::FxIndexSet;
29use rustc_errors::{Diagnostic, ErrorGuaranteed};
30use rustc_hash::FxHashSet;
31use rustc_hir::{self as hir, OwnerId, def::Namespace};
32use rustc_span::{
33 DUMMY_SP, Span,
34 def_id::{DefId, LocalDefId},
35};
36
37type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
38
39use crate::errors;
40
41pub(crate) fn desugar_qualifier<'genv>(
42 genv: GlobalEnv<'genv, '_>,
43 resolver_output: &'genv ResolverOutput,
44 def_id: FluxLocalDefId,
45 qualifier: &surface::Qualifier,
46) -> Result<fhir::Qualifier<'genv>> {
47 FluxItemCtxt::with(genv, resolver_output, def_id, FluxItemKind::Qualifier, |cx| {
48 fhir::Qualifier {
49 def_id,
50 args: cx.desugar_refine_params(&qualifier.params),
51 global: qualifier.global,
52 expr: cx.desugar_expr(&qualifier.expr),
53 }
54 })
55}
56
57pub(crate) fn desugar_primop_prop<'genv>(
58 genv: GlobalEnv<'genv, '_>,
59 resolver_output: &'genv ResolverOutput,
60 def_id: FluxLocalDefId,
61 primop_prop: &surface::PrimOpProp,
62) -> Result<fhir::PrimOpProp<'genv>> {
63 FluxItemCtxt::with(genv, resolver_output, def_id, FluxItemKind::PrimProp, |cx| {
64 let body = cx.desugar_expr(&primop_prop.body);
65 let args = cx.desugar_refine_params(&primop_prop.params);
66 fhir::PrimOpProp { def_id, op: primop_prop.op, args, body, span: primop_prop.span }
67 })
68}
69
70pub(crate) fn desugar_spec_func<'genv>(
71 genv: GlobalEnv<'genv, '_>,
72 resolver_output: &'genv ResolverOutput,
73 def_id: FluxLocalDefId,
74 spec_func: &surface::SpecFunc,
75) -> Result<fhir::SpecFunc<'genv>> {
76 FluxItemCtxt::with(genv, resolver_output, def_id, FluxItemKind::SpecFunc, |cx| {
77 let body = spec_func.body.as_ref().map(|body| cx.desugar_expr(body));
78 let params = spec_func.sort_vars.len();
79 let sort = cx.desugar_sort(&spec_func.output, None);
80 let args = cx.desugar_refine_params(&spec_func.params);
81 let ident_span = spec_func.name.span;
82 fhir::SpecFunc { def_id, params, args, sort, body, hide: spec_func.hide, ident_span }
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, self.genv().alloc(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: Res::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 fhir::PathExpr {
972 segments: self
973 .genv()
974 .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident)),
975 res,
976 fhir_id: self.next_fhir_id(),
977 span: path.span,
978 }
979 }
980
981 #[track_caller]
982 fn desugar_loc(&self, ident: surface::Ident, node_id: NodeId) -> Result<Res<ParamId>> {
983 let res = self.resolver_output().expr_path_res_map[&node_id];
984 if let Res::Param(fhir::ParamKind::Loc, _) = res {
985 Ok(res)
986 } else {
987 let span = ident.span;
988 Err(self.emit(errors::InvalidLoc { span }))
989 }
990 }
991
992 #[track_caller]
993 fn resolve_param(&self, node_id: NodeId) -> (fhir::ParamId, fhir::ParamKind) {
994 self.resolver_output().param_res_map[&node_id]
995 }
996
997 fn resolve_implicit_params(
998 &self,
999 scope: NodeId,
1000 ) -> impl ExactSizeIterator<Item = (surface::Ident, fhir::ParamId, fhir::ParamKind)> {
1001 self.resolver_output()
1002 .implicit_params
1003 .get(&scope)
1004 .map_or(&[][..], |it| it)
1005 .iter()
1006 .map(|(ident, param_id)| {
1007 let (param_id, kind) = self.resolve_param(*param_id);
1008 (*ident, param_id, kind)
1009 })
1010 }
1011
1012 fn implicit_params_to_params(
1013 &self,
1014 scope: NodeId,
1015 ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
1016 self.resolve_implicit_params(scope)
1017 .map(|(ident, id, kind)| {
1018 let sort = if kind.is_loc() { fhir::Sort::Loc } else { fhir::Sort::Infer };
1019 fhir::RefineParam {
1020 id,
1021 name: ident.name,
1022 span: ident.span,
1023 kind,
1024 sort,
1025 fhir_id: self.next_fhir_id(),
1026 }
1027 })
1028 }
1029
1030 fn desugar_refine_params(
1031 &mut self,
1032 params: &[surface::RefineParam],
1033 ) -> &'genv [fhir::RefineParam<'genv>] {
1034 self.genv()
1035 .alloc_slice_fill_iter(self.desugar_refine_params_iter(params))
1036 }
1037
1038 fn desugar_refine_params_iter(
1039 &mut self,
1040 params: &[surface::RefineParam],
1041 ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
1042 params.iter().map(|param| self.desugar_refine_param(param))
1043 }
1044
1045 fn desugar_refine_param(&mut self, param: &surface::RefineParam) -> fhir::RefineParam<'genv> {
1046 let (id, kind) = self.resolve_param(param.node_id);
1047 fhir::RefineParam {
1048 id,
1049 name: param.ident.name,
1050 span: param.ident.span,
1051 kind,
1052 sort: self.desugar_sort(¶m.sort, None),
1053 fhir_id: self.next_fhir_id(),
1054 }
1055 }
1056
1057 fn desugar_sort(
1058 &mut self,
1059 sort: &surface::Sort,
1060 generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1061 ) -> fhir::Sort<'genv> {
1062 match sort {
1063 surface::Sort::Base(bsort) => self.desugar_base_sort(bsort, generic_id_to_var_idx),
1064 surface::Sort::Func { inputs, output } => {
1065 let inputs_and_output = self.genv().alloc_slice_with_capacity(
1066 inputs.len() + 1,
1067 inputs
1068 .iter()
1069 .chain(iter::once(output))
1070 .map(|sort| self.desugar_base_sort(sort, generic_id_to_var_idx)),
1071 );
1072 fhir::Sort::Func(fhir::PolyFuncSort::new(0, inputs_and_output))
1073 }
1074 surface::Sort::Infer => fhir::Sort::Infer,
1075 }
1076 }
1077
1078 fn desugar_base_sort(
1079 &mut self,
1080 sort: &surface::BaseSort,
1081 generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1082 ) -> fhir::Sort<'genv> {
1083 let genv = self.genv();
1084 match sort {
1085 surface::BaseSort::BitVec(width) => fhir::Sort::BitVec(*width),
1086 surface::BaseSort::Path(surface::SortPath { segments, args, node_id }) => {
1087 let res = self.resolver_output().sort_path_res_map[node_id];
1088
1089 let res = if let fhir::SortRes::TyParam(def_id) = res
1091 && let Some(generic_id_to_var_idx) = generic_id_to_var_idx
1092 {
1093 let idx = generic_id_to_var_idx.get_index_of(&def_id).unwrap();
1094 fhir::SortRes::SortParam(idx)
1095 } else {
1096 res
1097 };
1098
1099 let args = genv.alloc_slice_fill_iter(
1100 args.iter()
1101 .map(|s| self.desugar_base_sort(s, generic_id_to_var_idx)),
1102 );
1103
1104 let path = fhir::SortPath { res, segments: genv.alloc_slice(segments), args };
1105 fhir::Sort::Path(path)
1106 }
1107 surface::BaseSort::SortOf(qself, path) => {
1108 fhir::Sort::SortOf(self.desugar_path_to_bty(Some(qself), path))
1109 }
1110 }
1111 }
1112
1113 fn desugar_generic_args(
1114 &mut self,
1115 res: Res,
1116 args: &[surface::GenericArg],
1117 ) -> (&'genv [fhir::GenericArg<'genv>], &'genv [fhir::AssocItemConstraint<'genv>]) {
1118 let mut fhir_args = vec![];
1119 let mut constraints = vec![];
1120 if let Res::Def(
1121 DefKind::TyAlias | DefKind::Struct | DefKind::Enum | DefKind::OpaqueTy,
1122 def_id,
1123 ) = res
1124 {
1125 let generics = self.genv().tcx().generics_of(def_id);
1126 for param in &generics.own_params {
1127 if let rustc_middle::ty::GenericParamDefKind::Lifetime = param.kind {
1128 fhir_args.push(fhir::GenericArg::Lifetime(self.mk_lft_hole()));
1129 }
1130 }
1131 }
1132 for arg in args {
1133 match &arg.kind {
1134 surface::GenericArgKind::Type(ty) => {
1135 if matches!(ty.kind, surface::TyKind::Hole) {
1136 fhir_args.push(fhir::GenericArg::Infer);
1137 continue;
1138 }
1139 if let Some(path) = ty.is_potential_const_arg()
1142 && let Some(res) =
1143 self.resolver_output().path_res_map[&path.node_id].full_res()
1144 && res.matches_ns(Namespace::ValueNS)
1145 {
1146 fhir_args.push(self.desugar_const_path_to_const_arg(path, res));
1147 continue;
1148 }
1149 let ty = self.desugar_ty(ty);
1150 fhir_args.push(fhir::GenericArg::Type(self.genv().alloc(ty)));
1151 }
1152 surface::GenericArgKind::Constraint(ident, ty) => {
1153 constraints.push(fhir::AssocItemConstraint {
1154 ident: *ident,
1155 kind: fhir::AssocItemConstraintKind::Equality { term: self.desugar_ty(ty) },
1156 });
1157 }
1158 }
1159 }
1160 (self.genv().alloc_slice(&fhir_args), self.genv().alloc_slice(&constraints))
1161 }
1162
1163 fn desugar_const_path_to_const_arg(
1164 &mut self,
1165 path: &surface::Path,
1166 res: fhir::Res<!>,
1167 ) -> fhir::GenericArg<'genv> {
1168 let kind = if let Res::Def(DefKind::ConstParam, def_id) = res {
1169 fhir::ConstArgKind::Param(def_id)
1170 } else {
1171 self.emit(errors::UnsupportedConstGenericArg::new(path.span, res.descr()));
1172 fhir::ConstArgKind::Infer
1173 };
1174 fhir::GenericArg::Const(fhir::ConstArg { kind, span: path.span })
1175 }
1176
1177 fn desugar_ty(&mut self, ty: &surface::Ty) -> fhir::Ty<'genv> {
1182 let node_id = ty.node_id;
1183 let span = ty.span;
1184 let kind = match &ty.kind {
1185 surface::TyKind::Base(bty) => {
1186 let bty = self.desugar_bty(bty);
1187 fhir::TyKind::BaseTy(bty)
1188 }
1189 surface::TyKind::Indexed { bty, indices } => {
1190 let bty = self.desugar_bty(bty);
1191 let idx = self.desugar_indices(indices);
1192 fhir::TyKind::Indexed(bty, idx)
1193 }
1194 surface::TyKind::Exists { bind, bty, pred } => {
1195 let ty_span = ty.span;
1196 let bty_span = bty.span;
1197
1198 let bty = self.desugar_bty(bty);
1199 let pred = self.desugar_expr(pred);
1200
1201 let (id, kind) = self.resolve_param(node_id);
1202 let param = fhir::RefineParam {
1203 id,
1204 name: bind.name,
1205 span: bind.span,
1206 sort: fhir::Sort::Infer,
1207 kind,
1208 fhir_id: self.next_fhir_id(),
1209 };
1210 let path = fhir::PathExpr {
1211 segments: self.genv().alloc_slice(&[*bind]),
1212 res: Res::Param(kind, id),
1213 fhir_id: self.next_fhir_id(),
1214 span: bind.span,
1215 };
1216 let idx = fhir::Expr {
1217 kind: fhir::ExprKind::Var(path, None),
1218 span: bind.span,
1219 fhir_id: self.next_fhir_id(),
1220 };
1221 let indexed = fhir::Ty { kind: fhir::TyKind::Indexed(bty, idx), span: bty_span };
1222 let constr = fhir::Ty {
1223 kind: fhir::TyKind::Constr(pred, self.genv().alloc(indexed)),
1224 span: ty_span,
1225 };
1226 fhir::TyKind::Exists(self.genv().alloc_slice(&[param]), self.genv().alloc(constr))
1227 }
1228 surface::TyKind::GeneralExists { params, ty, pred } => {
1229 let mut ty = self.desugar_ty(ty);
1230 if let Some(pred) = pred {
1231 let pred = self.desugar_expr(pred);
1232 ty = fhir::Ty { kind: fhir::TyKind::Constr(pred, self.genv().alloc(ty)), span };
1233 }
1234 let params = self.desugar_refine_params(params);
1235
1236 fhir::TyKind::Exists(params, self.genv().alloc(ty))
1237 }
1238 surface::TyKind::Constr(pred, ty) => {
1239 let pred = self.desugar_expr(pred);
1240 let ty = self.desugar_ty(ty);
1241 fhir::TyKind::Constr(pred, self.genv().alloc(ty))
1242 }
1243 surface::TyKind::Ref(mutbl, ty) => {
1244 let ty = self.desugar_ty(ty);
1245 let mut_ty = fhir::MutTy { ty: self.genv().alloc(ty), mutbl: *mutbl };
1246 fhir::TyKind::Ref(self.mk_lft_hole(), mut_ty)
1247 }
1248 surface::TyKind::Tuple(tys) => {
1249 let tys = self
1250 .genv()
1251 .alloc_slice_fill_iter(tys.iter().map(|ty| self.desugar_ty(ty)));
1252 fhir::TyKind::Tuple(tys)
1253 }
1254 surface::TyKind::Array(ty, len) => {
1255 let ty = self.desugar_ty(ty);
1256 let len = Self::desugar_const_arg(len);
1257 fhir::TyKind::Array(self.genv().alloc(ty), len)
1258 }
1259 surface::TyKind::ImplTrait(node_id, bounds) => {
1260 self.desugar_impl_trait(*node_id, bounds)
1261 }
1262 surface::TyKind::Hole => fhir::TyKind::Infer,
1263 };
1264 fhir::Ty { kind, span }
1265 }
1266
1267 fn desugar_const_arg(const_arg: &surface::ConstArg) -> fhir::ConstArg {
1268 let kind = match const_arg.kind {
1269 surface::ConstArgKind::Lit(val) => fhir::ConstArgKind::Lit(val),
1270 surface::ConstArgKind::Infer => fhir::ConstArgKind::Infer,
1271 };
1272 fhir::ConstArg { kind, span: const_arg.span }
1273 }
1274
1275 fn desugar_bty(&mut self, bty: &surface::BaseTy) -> fhir::BaseTy<'genv> {
1276 match &bty.kind {
1277 surface::BaseTyKind::Path(qself, path) => {
1278 let qpath = self.desugar_qpath(qself.as_deref(), path);
1279 fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1280 }
1281 surface::BaseTyKind::Slice(ty) => {
1282 let ty = self.desugar_ty(ty);
1283 let kind = fhir::BaseTyKind::Slice(self.genv().alloc(ty));
1284 fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: bty.span }
1285 }
1286 }
1287 }
1288
1289 fn desugar_path_to_bty(
1290 &mut self,
1291 qself: Option<&surface::Ty>,
1292 path: &surface::Path,
1293 ) -> fhir::BaseTy<'genv> {
1294 let qpath = self.desugar_qpath(qself, path);
1295 fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1296 }
1297
1298 fn desugar_qpath(
1299 &mut self,
1300 qself: Option<&surface::Ty>,
1301 path: &surface::Path,
1302 ) -> fhir::QPath<'genv> {
1303 let qself = if let Some(ty) = qself {
1304 let ty = self.desugar_ty(ty);
1305 Some(self.genv().alloc(ty))
1306 } else {
1307 None
1308 };
1309 let partial_res = self.resolver_output().path_res_map[&path.node_id];
1310
1311 let unresolved_segments = partial_res.unresolved_segments();
1312
1313 let proj_start = path.segments.len() - unresolved_segments;
1314 let fhir_path = fhir::Path {
1315 res: partial_res.base_res(),
1316 fhir_id: self.next_fhir_id(),
1317 segments: self.genv().alloc_slice_fill_iter(
1318 path.segments[..proj_start]
1319 .iter()
1320 .map(|segment| self.desugar_path_segment(segment)),
1321 ),
1322 refine: self
1323 .genv()
1324 .alloc_slice_fill_iter(path.refine.iter().map(|arg| self.desugar_refine_arg(arg))),
1325 span: path.span,
1326 };
1327
1328 if unresolved_segments == 0 {
1331 return fhir::QPath::Resolved(qself, fhir_path);
1332 }
1333
1334 let mut ty = if fhir_path.segments.is_empty() {
1336 qself.expect("missing QSelf for <T>::...")
1339 } else {
1340 self.genv()
1344 .alloc(self.ty_path(fhir::QPath::Resolved(qself, fhir_path)))
1345 };
1346
1347 for (i, segment) in path.segments.iter().enumerate().skip(proj_start) {
1348 let hir_segment = self.desugar_path_segment(segment);
1349 let qpath = fhir::QPath::TypeRelative(ty, self.genv().alloc(hir_segment));
1350
1351 if i == path.segments.len() - 1 {
1352 return qpath;
1353 }
1354
1355 ty = self.genv().alloc(self.ty_path(qpath));
1356 }
1357
1358 span_bug!(
1359 path.span,
1360 "desugar_qpath: no final extension segment in {}..{}",
1361 proj_start,
1362 path.segments.len()
1363 );
1364 }
1365
1366 fn desugar_path_segment(&mut self, segment: &surface::PathSegment) -> fhir::PathSegment<'genv> {
1367 let res = self
1368 .resolver_output()
1369 .path_res_map
1370 .get(&segment.node_id)
1371 .map_or(Res::Err, |r| r.expect_full_res());
1372 let (args, constraints) = self.desugar_generic_args(res, &segment.args);
1373 fhir::PathSegment { ident: segment.ident, res, args, constraints }
1374 }
1375
1376 fn ty_path(&self, qpath: fhir::QPath<'genv>) -> fhir::Ty<'genv> {
1377 fhir::Ty {
1378 span: qpath.span(),
1379 kind: fhir::TyKind::BaseTy(fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())),
1380 }
1381 }
1382
1383 fn mk_lft_hole(&self) -> fhir::Lifetime {
1384 fhir::Lifetime::Hole(self.next_fhir_id())
1385 }
1386
1387 fn desugar_indices(&mut self, idxs: &surface::Indices) -> fhir::Expr<'genv> {
1388 if let [arg] = &idxs.indices[..] {
1389 self.desugar_refine_arg(arg)
1390 } else {
1391 let flds = self
1392 .genv()
1393 .alloc_slice_fill_iter(idxs.indices.iter().map(|arg| self.desugar_refine_arg(arg)));
1394 fhir::Expr {
1395 kind: fhir::ExprKind::Record(flds),
1396 fhir_id: self.next_fhir_id(),
1397 span: idxs.span,
1398 }
1399 }
1400 }
1401
1402 fn desugar_refine_arg(&mut self, arg: &surface::RefineArg) -> fhir::Expr<'genv> {
1403 match arg {
1404 surface::RefineArg::Bind(ident, .., node_id) => {
1405 self.implicit_param_into_refine_arg(*ident, *node_id)
1406 .unwrap()
1407 }
1408 surface::RefineArg::Expr(expr) => self.desugar_expr(expr),
1409 surface::RefineArg::Abs(params, body, span, _) => {
1410 let body = self.genv().alloc(self.desugar_expr(body));
1411 let params = self.desugar_refine_params(params);
1412 fhir::Expr {
1413 kind: fhir::ExprKind::Abs(params, body),
1414 fhir_id: self.next_fhir_id(),
1415 span: *span,
1416 }
1417 }
1418 }
1419 }
1420
1421 fn implicit_param_into_refine_arg(
1422 &self,
1423 ident: surface::Ident,
1424 node_id: NodeId,
1425 ) -> Option<fhir::Expr<'genv>> {
1426 let (id, kind) = self.resolve_implicit_param(node_id)?;
1427 let path = fhir::PathExpr {
1428 segments: self.genv().alloc_slice(&[ident]),
1429 res: Res::Param(kind, id),
1430 fhir_id: self.next_fhir_id(),
1431 span: ident.span,
1432 };
1433 Some(fhir::Expr {
1434 kind: fhir::ExprKind::Var(path, Some(kind)),
1435 span: ident.span,
1436 fhir_id: self.next_fhir_id(),
1437 })
1438 }
1439
1440 fn desugar_expr(&mut self, expr: &surface::Expr) -> fhir::Expr<'genv> {
1441 let kind = match &expr.kind {
1442 surface::ExprKind::Path(path) => fhir::ExprKind::Var(self.desugar_epath(path), None),
1443 surface::ExprKind::Literal(lit) => self.desugar_lit(expr.span, *lit),
1444 surface::ExprKind::BinaryOp(op, box [e1, e2]) => {
1445 let e1 = self.desugar_expr(e1);
1446 let e2 = self.desugar_expr(e2);
1447 fhir::ExprKind::BinaryOp(*op, self.genv().alloc(e1), self.genv().alloc(e2))
1448 }
1449 surface::ExprKind::UnaryOp(op, box e) => {
1450 fhir::ExprKind::UnaryOp(*op, self.genv().alloc(self.desugar_expr(e)))
1451 }
1452 surface::ExprKind::Dot(base, fld) => {
1453 let base = self.desugar_expr(base);
1454 fhir::ExprKind::Dot(self.genv().alloc(base), *fld)
1455 }
1456 surface::ExprKind::Call(callee, args) => self.desugar_call(callee, args),
1457 surface::ExprKind::AssocReft(..) | surface::ExprKind::PrimUIF(..) => {
1458 fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(expr.span)))
1459 }
1460 surface::ExprKind::IfThenElse(box [p, e1, e2]) => {
1461 let p = self.desugar_expr(p);
1462 let e1 = self.desugar_expr(e1);
1463 let e2 = self.desugar_expr(e2);
1464 fhir::ExprKind::IfThenElse(
1465 self.genv().alloc(p),
1466 self.genv().alloc(e1),
1467 self.genv().alloc(e2),
1468 )
1469 }
1470 surface::ExprKind::Constructor(path, args) => {
1471 self.desugar_constructor(path.as_ref(), args)
1472 }
1473 surface::ExprKind::BoundedQuant(kind, param, rng, body) => {
1474 let kind = match kind {
1475 surface::QuantKind::Exists => fhir::QuantKind::Exists,
1476 surface::QuantKind::Forall => fhir::QuantKind::Forall,
1477 };
1478 let body = self.genv().alloc(self.desugar_expr(body));
1479 let param = self.desugar_refine_param(param);
1480 let rng = fhir::Range { start: rng.start, end: rng.end };
1481 fhir::ExprKind::BoundedQuant(kind, param, rng, body)
1482 }
1483 surface::ExprKind::Block(decls, body) => {
1484 let decls = self.genv().alloc_slice_fill_iter(decls.iter().map(|decl| {
1485 fhir::LetDecl {
1486 param: self.desugar_refine_param(&decl.param),
1487 init: self.desugar_expr(&decl.init),
1488 }
1489 }));
1490 let body = self.genv().alloc(self.desugar_expr(body));
1491 fhir::ExprKind::Block(decls, body)
1492 }
1493 };
1494
1495 fhir::Expr { kind, span: expr.span, fhir_id: self.next_fhir_id() }
1496 }
1497
1498 fn desugar_call(
1499 &mut self,
1500 callee: &surface::Expr,
1501 args: &[surface::Expr],
1502 ) -> fhir::ExprKind<'genv> {
1503 let args = self.desugar_exprs(args);
1504 match &callee.kind {
1505 surface::ExprKind::Path(path) => {
1506 let path = self.desugar_epath(path);
1507 fhir::ExprKind::App(path, args)
1508 }
1509 surface::ExprKind::PrimUIF(op) if args.len() == 2 && self.allow_prim_app() => {
1510 fhir::ExprKind::PrimApp(*op, &args[0], &args[1])
1511 }
1512 surface::ExprKind::AssocReft(qself, path, name) => {
1513 let qself = self.desugar_ty(qself);
1514 let fhir::QPath::Resolved(None, fpath) = self.desugar_qpath(None, path) else {
1515 span_bug!(path.span, "desugar_alias_reft: unexpected qpath")
1516 };
1517 let Res::Def(DefKind::Trait, _) = fpath.res else {
1518 return fhir::ExprKind::Err(self.emit(errors::InvalidAliasReft::new(path)));
1520 };
1521 let alias_reft =
1522 fhir::AliasReft { qself: self.genv().alloc(qself), path: fpath, name: *name };
1523 fhir::ExprKind::Alias(alias_reft, args)
1524 }
1525 _ => fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(callee.span))),
1526 }
1527 }
1528
1529 fn desugar_constructor(
1530 &mut self,
1531 path: Option<&surface::ExprPath>,
1532 args: &[surface::ConstructorArg],
1533 ) -> fhir::ExprKind<'genv> {
1534 let path = if let Some(path) = path {
1535 let res = self.resolver_output().expr_path_res_map[&path.node_id];
1536 if !matches!(res, Res::Def(DefKind::Struct | DefKind::Enum, _)) {
1537 return fhir::ExprKind::Err(
1538 self.emit(errors::InvalidConstructorPath { span: path.span }),
1539 );
1540 };
1541 let segments = self
1542 .genv()
1543 .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident));
1544 Some(fhir::PathExpr { res, segments, fhir_id: self.next_fhir_id(), span: path.span })
1545 } else {
1546 None
1547 };
1548
1549 let (field_exprs, spreads): (Vec<_>, Vec<_>) = args.iter().partition_map(|arg| {
1550 match arg {
1551 ConstructorArg::FieldExpr(e) => Either::Left(e),
1552 ConstructorArg::Spread(s) => Either::Right(s),
1553 }
1554 });
1555
1556 let field_exprs = self
1557 .genv()
1558 .alloc_slice_fill_iter(field_exprs.iter().map(|field_expr| {
1559 let e = self.desugar_expr(&field_expr.expr);
1560 fhir::FieldExpr {
1561 ident: field_expr.ident,
1562 expr: e,
1563 fhir_id: self.next_fhir_id(),
1564 span: e.span,
1565 }
1566 }));
1567
1568 match &spreads[..] {
1569 [] => fhir::ExprKind::Constructor(path, field_exprs, None),
1570 [s] => {
1571 let spread = fhir::Spread {
1572 expr: self.desugar_expr(&s.expr),
1573 span: s.span,
1574 fhir_id: self.next_fhir_id(),
1575 };
1576 fhir::ExprKind::Constructor(path, field_exprs, Some(self.genv().alloc(spread)))
1577 }
1578 [s1, s2, ..] => {
1579 let err = errors::MultipleSpreadsInConstructor::new(s1.span, s2.span);
1580 fhir::ExprKind::Err(self.emit(err))
1581 }
1582 }
1583 }
1584
1585 fn desugar_exprs(&mut self, exprs: &[surface::Expr]) -> &'genv [fhir::Expr<'genv>] {
1586 self.genv()
1587 .alloc_slice_fill_iter(exprs.iter().map(|e| self.desugar_expr(e)))
1588 }
1589
1590 fn try_parse_int_lit(&self, span: Span, s: &str) -> Result<u128> {
1591 let s = s.replace("_", "");
1592 let parsed_int = if s.len() <= 2 {
1593 s.parse::<u128>()
1594 } else {
1595 match &s[0..2] {
1596 "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>(), }
1601 };
1602
1603 if let Ok(n) = parsed_int {
1604 Ok(n) } else {
1606 Err(self.emit(errors::IntTooLarge { span }))
1607 }
1608 }
1609
1610 fn desugar_lit(&self, span: Span, lit: surface::Lit) -> fhir::ExprKind<'genv> {
1612 let lit = match lit.kind {
1613 surface::LitKind::Integer => {
1614 let n = match self.try_parse_int_lit(span, lit.symbol.as_str()) {
1615 Ok(n) => n,
1616 Err(err) => return fhir::ExprKind::Err(err),
1617 };
1618 match lit.suffix {
1619 Some(sym::int) => fhir::Lit::Int(n, Some(fhir::NumLitKind::Int)),
1620 Some(sym::real) => fhir::Lit::Int(n, Some(fhir::NumLitKind::Real)),
1621 None => fhir::Lit::Int(n, None),
1622 Some(suffix) => {
1623 return fhir::ExprKind::Err(
1624 self.emit(errors::InvalidNumericSuffix::new(span, suffix)),
1625 );
1626 }
1627 }
1628 }
1629 surface::LitKind::Bool => fhir::Lit::Bool(lit.symbol == kw::True),
1630 surface::LitKind::Str => fhir::Lit::Str(lit.symbol),
1631 surface::LitKind::Char => fhir::Lit::Char(lit.symbol.as_str().parse::<char>().unwrap()),
1632 _ => return fhir::ExprKind::Err(self.emit(errors::UnexpectedLiteral { span })),
1633 };
1634 fhir::ExprKind::Literal(lit)
1635 }
1636}
1637
1638impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for RustItemCtxt<'_, 'genv, 'tcx> {
1639 fn next_fhir_id(&self) -> FhirId {
1640 FhirId {
1641 owner: FluxOwnerId::Rust(self.owner.local_id()),
1642 local_id: self.local_id_gen.fresh(),
1643 }
1644 }
1645
1646 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1647 self.genv
1648 }
1649
1650 fn resolver_output(&self) -> &'genv ResolverOutput {
1651 self.resolver_output
1652 }
1653
1654 fn desugar_impl_trait(
1655 &mut self,
1656 node_id: NodeId,
1657 bounds: &[surface::TraitRef],
1658 ) -> fhir::TyKind<'genv> {
1659 let def_id = self.resolver_output().impl_trait_res_map[&node_id];
1660
1661 let opaque_ty = self.desugar_opaque_ty_for_impl_trait(def_id, bounds);
1664 let opaque_ty = self.insert_opaque_ty(opaque_ty);
1665
1666 fhir::TyKind::OpaqueDef(opaque_ty)
1667 }
1668}
1669
1670impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for FluxItemCtxt<'genv, 'tcx> {
1671 fn next_fhir_id(&self) -> FhirId {
1672 FhirId { owner: FluxOwnerId::Flux(self.owner), local_id: self.local_id_gen.fresh() }
1673 }
1674
1675 fn allow_prim_app(&self) -> bool {
1676 matches!(self.kind, FluxItemKind::PrimProp)
1677 }
1678
1679 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1680 self.genv
1681 }
1682
1683 fn resolver_output(&self) -> &'genv ResolverOutput {
1684 self.resolver_output
1685 }
1686
1687 fn desugar_impl_trait(&mut self, _: NodeId, _: &[surface::TraitRef]) -> fhir::TyKind<'genv> {
1688 unimplemented!("`impl Trait` not supported in this item")
1689 }
1690}