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