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