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