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