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