1mod lift;
2
3use std::{iter, ops::Range};
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, unord::UnordSet};
31use rustc_errors::{Diagnostic, ErrorGuaranteed};
32use rustc_hir::{self as hir, OwnerId, def::Namespace};
33use rustc_span::{
34 DUMMY_SP, Span,
35 def_id::{DefId, LocalDefId},
36};
37
38type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
39
40use crate::errors;
41
42fn collect_generics_in_params(
45 genv: GlobalEnv,
46 owner: MaybeExternId<OwnerId>,
47 resolver_output: &ResolverOutput,
48 params: &surface::RefineParams,
49) -> FxIndexSet<DefId> {
50 struct ParamCollector<'a> {
51 resolver_output: &'a ResolverOutput,
52 found: UnordSet<DefId>,
53 }
54 impl surface::visit::Visitor for ParamCollector<'_> {
55 fn visit_base_sort(&mut self, bsort: &surface::BaseSort) {
56 if let surface::BaseSort::Path(path) = bsort {
57 let res = self.resolver_output.sort_path_res_map[&path.node_id];
58 if let fhir::SortRes::TyParam(def_id) = res {
59 self.found.insert(def_id);
60 }
61 }
62 surface::visit::walk_base_sort(self, bsort);
63 }
64 }
65 let mut vis = ParamCollector { resolver_output, found: UnordSet::new() };
66 walk_list!(vis, visit_refine_param, params);
67 genv.tcx()
68 .generics_of(owner.resolved_id())
69 .own_params
70 .iter()
71 .filter_map(
72 |param| if vis.found.contains(¶m.def_id) { Some(param.def_id) } else { None },
73 )
74 .collect()
75}
76
77pub(crate) struct RustItemCtxt<'a, 'genv, 'tcx> {
78 genv: GlobalEnv<'genv, 'tcx>,
79 local_id_gen: IndexGen<fhir::ItemLocalId>,
80 owner: MaybeExternId<OwnerId>,
81 fn_sig_scope: Option<NodeId>,
82 resolver_output: &'genv ResolverOutput,
83 opaque: Option<LocalDefId>,
86 opaque_tys: Option<&'a mut Vec<&'genv fhir::OpaqueTy<'genv>>>,
89 errors: Errors<'genv>,
90}
91
92impl<'a, 'genv, 'tcx: 'genv> RustItemCtxt<'a, 'genv, 'tcx> {
93 pub(crate) fn with<T>(
94 genv: GlobalEnv<'genv, 'tcx>,
95 owner: MaybeExternId<OwnerId>,
96 resolver_output: &'genv ResolverOutput,
97 opaque_tys: Option<&'a mut Vec<&'genv fhir::OpaqueTy<'genv>>>,
98 f: impl FnOnce(&mut Self) -> Result<T>,
99 ) -> Result<T> {
100 let mut cx = RustItemCtxt {
101 genv,
102 owner,
103 fn_sig_scope: None,
104 local_id_gen: IndexGen::new(),
105 resolver_output,
106 opaque_tys,
107 errors: Errors::new(genv.sess()),
108 opaque: collect_opaque_types(genv, owner)?,
109 };
110 let r = f(&mut cx)?;
111 cx.into_result()?;
112 Ok(r)
113 }
114
115 pub(crate) fn desugar_item(&mut self, item: &surface::Item) -> Result<fhir::Item<'genv>> {
116 match &item.kind {
117 surface::ItemKind::Fn(fn_sig) => {
118 let (generics, fn_sig) = self.desugar_fn_sig(fn_sig.as_ref())?;
119 Ok(fhir::Item { generics, kind: fhir::ItemKind::Fn(fn_sig), owner_id: self.owner })
120 }
121 surface::ItemKind::Struct(struct_def) => Ok(self.desugar_struct_def(struct_def)),
122 surface::ItemKind::Enum(enum_def) => self.desugar_enum_def(enum_def),
123 surface::ItemKind::Trait(trait_) => self.desugar_trait(trait_),
124 surface::ItemKind::Impl(impl_) => Ok(self.desugar_impl(impl_)),
125 surface::ItemKind::Const(constant_info) => Ok(self.desugar_const(constant_info)),
126 surface::ItemKind::Static(static_info) => Ok(self.desugar_static(static_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_static(&mut self, static_info: &surface::StaticInfo) -> fhir::Item<'genv> {
480 let ty = self.desugar_ty(&static_info.ty);
481 let owner_id = self.owner;
482 let generics = fhir::Generics::empty(self.genv);
483 let kind = fhir::ItemKind::Static(Some(ty));
484 fhir::Item { owner_id, generics, kind }
485 }
486
487 fn desugar_fn_sig(
488 &mut self,
489 fn_sig: Option<&surface::FnSig>,
490 ) -> Result<(fhir::Generics<'genv>, fhir::FnSig<'genv>)> {
491 let mut header = self.lift_fn_header();
492 let (generics, decl, expr) = if let Some(fn_sig) = fn_sig {
493 self.fn_sig_scope = Some(fn_sig.node_id);
494
495 let mut requires = vec![];
496
497 let mut generics = self.desugar_generics(&fn_sig.generics);
498
499 for surface_requires in &fn_sig.requires {
500 let params = self.desugar_refine_params(&surface_requires.params);
501 let pred = self.desugar_expr(&surface_requires.pred);
502 requires.push(fhir::Requires { params, pred });
503 }
504
505 let inputs = self
507 .genv()
508 .alloc_slice_fill_iter(fn_sig.inputs.iter().map(|arg| self.desugar_fn_input(arg)));
509
510 let output = self.desugar_fn_output(fn_sig.asyncness, &fn_sig.output)?;
511
512 generics.refinement_params = self.desugar_fn_sig_refine_params(fn_sig);
513
514 let decl = fhir::FnDecl {
515 requires: self.genv.alloc_slice(&requires),
516 inputs,
517 output,
518 span: fn_sig.span,
519 lifted: false,
520 };
521
522 if let surface::Async::Yes { span, .. } = fn_sig.asyncness {
524 header.asyncness = hir::IsAsync::Async(span);
525 }
526 let expr = fn_sig.no_panic.as_ref().map(|e| self.desugar_expr(e));
527 (generics, decl, expr)
528 } else {
529 (self.lift_generics(), self.lift_fn_decl(), None)
530 };
531 if config::dump_fhir() {
532 dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", decl).unwrap();
533 }
534 Ok((generics, fhir::FnSig { header, decl: self.genv.alloc(decl), no_panic_if: expr }))
535 }
536
537 fn desugar_fn_sig_refine_params(
538 &mut self,
539 fn_sig: &surface::FnSig,
540 ) -> &'genv [fhir::RefineParam<'genv>] {
541 let genv = self.genv;
542 let mut params = self
543 .desugar_refine_params_iter(&fn_sig.params)
544 .collect_vec();
545 params.extend(self.implicit_params_to_params(fn_sig.node_id));
546
547 genv.alloc_slice(¶ms)
548 }
549
550 fn desugar_fn_output(
551 &mut self,
552 asyncness: surface::Async,
553 output: &surface::FnOutput,
554 ) -> Result<fhir::FnOutput<'genv>> {
555 let ret = self.desugar_asyncness(asyncness, &output.returns);
556
557 let ensures = try_alloc_slice!(self.genv, &output.ensures, |it| self.desugar_ensures(it))?;
558
559 let params = self
560 .genv
561 .alloc_slice_fill_iter(self.implicit_params_to_params(output.node_id));
562 Ok(fhir::FnOutput { params, ret, ensures })
563 }
564
565 fn desugar_ensures(&mut self, cstr: &surface::Ensures) -> Result<fhir::Ensures<'genv>> {
566 match cstr {
567 surface::Ensures::Type(loc, ty, node_id) => {
568 let res = self.desugar_loc(*loc, *node_id)?;
569 let path = fhir::PathExpr {
570 segments: self.genv().alloc_slice(&[*loc]),
571 res,
572 fhir_id: self.next_fhir_id(),
573 span: loc.span,
574 };
575 let ty = self.desugar_ty(ty);
576 Ok(fhir::Ensures::Type(path, self.genv().alloc(ty)))
577 }
578 surface::Ensures::Pred(e) => {
579 let pred = self.desugar_expr(e);
580 Ok(fhir::Ensures::Pred(pred))
581 }
582 }
583 }
584
585 fn desugar_fn_input(&mut self, input: &surface::FnInput) -> fhir::Ty<'genv> {
586 match input {
587 surface::FnInput::Constr(bind, path, pred, node_id) => {
588 let bty = self.desugar_path_to_bty(None, path);
589
590 let pred = self.desugar_expr(pred);
591
592 let ty = if let Some(idx) = self.implicit_param_into_refine_arg(*bind, *node_id) {
593 fhir::Ty { kind: fhir::TyKind::Indexed(bty, idx), span: path.span }
594 } else {
595 fhir::Ty { kind: fhir::TyKind::BaseTy(bty), span: path.span }
596 };
597
598 let span = path.span.to(pred.span);
599 let kind = fhir::TyKind::Constr(pred, self.genv.alloc(ty));
600 fhir::Ty { kind, span }
601 }
602 surface::FnInput::StrgRef(loc, ty, node_id) => {
603 let span = loc.span;
604 let (id, kind) = self.resolve_implicit_param(*node_id).unwrap();
605 let path = fhir::PathExpr {
606 segments: self.genv.alloc_slice(&[*loc]),
607 res: Res::Param(kind, id),
608 fhir_id: self.next_fhir_id(),
609 span: loc.span,
610 };
611 let ty = self.desugar_ty(ty);
612 let kind = fhir::TyKind::StrgRef(
613 self.mk_lft_hole(),
614 self.genv.alloc(path),
615 self.genv.alloc(ty),
616 );
617 fhir::Ty { kind, span }
618 }
619 surface::FnInput::Ty(bind, ty, node_id) => {
620 if let Some(bind) = bind
621 && let surface::TyKind::Base(bty) = &ty.kind
622 {
623 let bty = self.desugar_bty(bty);
624 let kind =
625 if let Some(idx) = self.implicit_param_into_refine_arg(*bind, *node_id) {
626 fhir::TyKind::Indexed(bty, idx)
627 } else {
628 fhir::TyKind::BaseTy(bty)
629 };
630 fhir::Ty { kind, span: ty.span }
631 } else {
632 self.desugar_ty(ty)
633 }
634 }
635 }
636 }
637
638 fn desugar_asyncness(
639 &mut self,
640 asyncness: surface::Async,
641 returns: &surface::FnRetTy,
642 ) -> fhir::Ty<'genv> {
643 match asyncness {
644 surface::Async::Yes { span, .. } => {
645 let def_id = self.opaque.unwrap();
647
648 let opaque_ty = self.desugar_opaque_ty_for_async(def_id, returns);
651 let opaque_ty = self.insert_opaque_ty(opaque_ty);
652 let kind = fhir::TyKind::OpaqueDef(opaque_ty);
653 fhir::Ty { kind, span }
654 }
655 surface::Async::No => self.desugar_fn_ret_ty(returns),
656 }
657 }
658
659 fn desugar_opaque_ty_for_async(
660 &mut self,
661 def_id: LocalDefId,
662 returns: &surface::FnRetTy,
663 ) -> fhir::OpaqueTy<'genv> {
664 let output = self.desugar_fn_ret_ty(returns);
665 let trait_ref = self.make_lang_item_path(
666 hir::LangItem::Future,
667 DUMMY_SP,
668 &[],
669 self.genv.alloc_slice(&[fhir::AssocItemConstraint {
670 ident: surface::Ident::with_dummy_span(sym::Output),
671 kind: fhir::AssocItemConstraintKind::Equality { term: output },
672 }]),
673 );
674 let bound = fhir::GenericBound::Trait(fhir::PolyTraitRef {
675 bound_generic_params: &[],
676 refine_params: &[],
677 modifiers: fhir::TraitBoundModifier::None,
678 trait_ref,
679 span: trait_ref.span,
680 });
681 fhir::OpaqueTy {
682 def_id: MaybeExternId::Local(def_id),
683 bounds: self.genv.alloc_slice(&[bound]),
684 }
685 }
686
687 fn make_lang_item_path(
688 &mut self,
689 lang_item: hir::LangItem,
690 span: Span,
691 args: &'genv [fhir::GenericArg<'genv>],
692 constraints: &'genv [fhir::AssocItemConstraint<'genv>],
693 ) -> fhir::Path<'genv> {
694 let def_id = self.genv.tcx().require_lang_item(lang_item, span);
695 let def_kind = self.genv.def_kind(def_id);
696 let res = Res::Def(def_kind, def_id);
697 fhir::Path {
698 span,
699 fhir_id: self.next_fhir_id(),
700 res,
701 segments: self.genv.alloc_slice_fill_iter([fhir::PathSegment {
702 ident: surface::Ident::new(lang_item.name(), span),
703 res,
704 args,
705 constraints,
706 }]),
707 refine: &[],
708 }
709 }
710
711 fn desugar_fn_ret_ty(&mut self, returns: &surface::FnRetTy) -> fhir::Ty<'genv> {
712 match returns {
713 surface::FnRetTy::Ty(ty) => self.desugar_ty(ty),
714 surface::FnRetTy::Default(span) => {
715 let kind = fhir::TyKind::Tuple(&[]);
716 fhir::Ty { kind, span: *span }
717 }
718 }
719 }
720
721 fn desugar_opaque_ty_for_impl_trait(
722 &mut self,
723 def_id: LocalDefId,
724 bounds: &[surface::TraitRef],
725 ) -> fhir::OpaqueTy<'genv> {
726 let bounds = self.desugar_generic_bounds(bounds);
727 fhir::OpaqueTy { def_id: MaybeExternId::Local(def_id), bounds }
728 }
729
730 fn desugar_variant_ret(
731 &mut self,
732 ret: &surface::VariantRet,
733 ) -> Result<fhir::VariantRet<'genv>> {
734 let Some(enum_id) = self.check_variant_ret_path(&ret.path) else {
735 return Err(self.emit(errors::InvalidVariantRet::new(&ret.path)));
736 };
737 let idx = self.desugar_indices(&ret.indices);
738 Ok(fhir::VariantRet { enum_id, idx })
739 }
740
741 fn check_variant_ret_path(&mut self, path: &surface::Path) -> Option<DefId> {
742 let resolved_id = self.owner.resolved_id();
743
744 match self.resolver_output().path_res_map[&path.node_id].full_res()? {
745 fhir::Res::Def(DefKind::Enum, def_id) if def_id == resolved_id => {}
746 fhir::Res::SelfTyAlias { .. } => return Some(resolved_id),
747 _ => return None,
748 }
749
750 let generics = self.genv.tcx().generics_of(resolved_id);
751 let args = &path.last().args;
752 if generics.own_counts().types != args.len() {
753 return None;
754 }
755 let mut i = 0;
756 for param in &generics.own_params {
757 let rustc_middle::ty::GenericParamDefKind::Type { .. } = param.kind else { continue };
758 let arg = &args[i];
759 if let surface::GenericArgKind::Type(arg_ty) = &arg.kind
760 && let surface::TyKind::Base(arg_bty) = &arg_ty.kind
761 && let surface::BaseTyKind::Path(None, arg_path) = &arg_bty.kind
762 && let fhir::Res::Def(DefKind::TyParam, def_id) =
763 self.resolver_output().path_res_map[&arg_path.node_id].full_res()?
764 && def_id == param.def_id
765 {
766 } else {
767 return None;
768 }
769 i += 1;
770 }
771
772 Some(resolved_id)
773 }
774
775 fn insert_opaque_ty(
776 &mut self,
777 opaque_ty: fhir::OpaqueTy<'genv>,
778 ) -> &'genv fhir::OpaqueTy<'genv> {
779 let opaque_ty = self.genv.alloc(opaque_ty);
780 self.opaque_tys
781 .as_mut()
782 .unwrap_or_else(|| bug!("`impl Trait` not supported in this item `{:?}`", self.owner))
783 .push(opaque_ty);
784 opaque_ty
785 }
786}
787
788impl ErrorEmitter for RustItemCtxt<'_, '_, '_> {
789 fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
790 self.errors.emit(err)
791 }
792}
793
794impl ErrorCollector<ErrorGuaranteed> for RustItemCtxt<'_, '_, '_> {
795 type Result = std::result::Result<(), ErrorGuaranteed>;
796
797 fn collect(&mut self, err: ErrorGuaranteed) {
798 self.errors.collect(err);
799 }
800
801 fn into_result(self) -> Self::Result {
802 self.errors.into_result()
803 }
804}
805
806pub(crate) struct FluxItemCtxt<'genv, 'tcx> {
807 genv: GlobalEnv<'genv, 'tcx>,
808 resolver_output: &'genv ResolverOutput,
809 local_id_gen: IndexGen<fhir::ItemLocalId>,
810 owner: FluxLocalDefId,
811 allow_primop_app: bool,
812 errors: Errors<'genv>,
813}
814
815impl<'genv, 'tcx> FluxItemCtxt<'genv, 'tcx> {
816 pub(crate) fn with<T>(
817 genv: GlobalEnv<'genv, 'tcx>,
818 resolver_output: &'genv ResolverOutput,
819 owner: FluxLocalDefId,
820 f: impl FnOnce(&mut Self) -> T,
821 ) -> Result<T> {
822 let mut cx = Self {
823 genv,
824 resolver_output,
825 local_id_gen: Default::default(),
826 owner,
827 allow_primop_app: false,
828 errors: Errors::new(genv.sess()),
829 };
830 let r = f(&mut cx);
831 cx.into_result()?;
832 Ok(r)
833 }
834
835 pub(crate) fn desugar_flux_item(&mut self, item: &surface::FluxItem) -> fhir::FluxItem<'genv> {
836 match item {
837 surface::FluxItem::Qualifier(qual) => {
838 let qual = self.desugar_qualifier(qual);
839 fhir::FluxItem::Qualifier(self.genv.alloc(qual))
840 }
841 surface::FluxItem::FuncDef(func) => {
842 let func = self.desugar_spec_func(func);
843 fhir::FluxItem::Func(self.genv.alloc(func))
844 }
845 surface::FluxItem::PrimOpProp(primop_prop) => {
846 self.allow_primop_app = true;
847 let primop_prop = self.desugar_primop_prop(primop_prop);
848 self.allow_primop_app = false;
849 fhir::FluxItem::PrimOpProp(self.genv.alloc(primop_prop))
850 }
851 surface::FluxItem::SortDecl(sort_decl) => {
852 let sort_decl = self.desugar_sort_decl(sort_decl);
853 fhir::FluxItem::SortDecl(self.genv.alloc(sort_decl))
854 }
855 }
856 }
857
858 pub(crate) fn desugar_sort_decl(&mut self, sort_decl: &surface::SortDecl) -> fhir::SortDecl {
859 fhir::SortDecl {
860 def_id: self.owner,
861 params: sort_decl.sort_vars.len(),
862 span: sort_decl.name.span,
863 }
864 }
865
866 fn desugar_qualifier_kind(qualifier: &surface::Qualifier) -> QualifierKind {
867 match qualifier.kind {
868 surface::QualifierKind::Global => QualifierKind::Global,
869 surface::QualifierKind::Local => QualifierKind::Local,
870 surface::QualifierKind::Hint => QualifierKind::Hint,
871 }
872 }
873
874 fn desugar_qualifier(&mut self, qualifier: &surface::Qualifier) -> fhir::Qualifier<'genv> {
875 let kind = Self::desugar_qualifier_kind(qualifier);
876 fhir::Qualifier {
877 def_id: self.owner,
878 args: self.desugar_refine_params(&qualifier.params),
879 kind,
880 expr: self.desugar_expr(&qualifier.expr),
881 }
882 }
883
884 fn desugar_primop_prop(
885 &mut self,
886 primop_prop: &surface::PrimOpProp,
887 ) -> fhir::PrimOpProp<'genv> {
888 let body = self.desugar_expr(&primop_prop.body);
889 let args = self.desugar_refine_params(&primop_prop.params);
890 fhir::PrimOpProp {
891 def_id: self.owner,
892 op: primop_prop.op,
893 args,
894 body,
895 span: primop_prop.span,
896 }
897 }
898
899 fn desugar_spec_func(&mut self, spec_func: &surface::SpecFunc) -> fhir::SpecFunc<'genv> {
900 let body = spec_func.body.as_ref().map(|body| self.desugar_expr(body));
901 let params = spec_func.sort_vars.len();
902 let sort = self.desugar_sort(&spec_func.output, None);
903 let args = self.desugar_refine_params(&spec_func.params);
904 let ident_span = spec_func.name.span;
905 fhir::SpecFunc {
906 def_id: self.owner,
907 params,
908 args,
909 sort,
910 body,
911 hide: spec_func.hide,
912 ident_span,
913 }
914 }
915}
916
917impl ErrorEmitter for FluxItemCtxt<'_, '_> {
918 fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
919 self.errors.emit(err)
920 }
921}
922
923impl ErrorCollector<ErrorGuaranteed> for FluxItemCtxt<'_, '_> {
924 type Result = std::result::Result<(), ErrorGuaranteed>;
925
926 fn collect(&mut self, err: ErrorGuaranteed) {
927 self.errors.collect(err);
928 }
929
930 fn into_result(self) -> Self::Result {
931 self.errors.into_result()
932 }
933}
934
935trait DesugarCtxt<'genv, 'tcx: 'genv>: ErrorEmitter + ErrorCollector<ErrorGuaranteed> {
936 fn genv(&self) -> GlobalEnv<'genv, 'tcx>;
937 fn resolver_output(&self) -> &'genv ResolverOutput;
938 fn next_fhir_id(&self) -> FhirId;
939 fn desugar_impl_trait(&mut self, bounds: &[surface::TraitRef]) -> fhir::TyKind<'genv>;
940
941 fn allow_primop_app(&self) -> bool {
942 false
943 }
944
945 fn resolve_implicit_param(&self, node_id: NodeId) -> Option<(fhir::ParamId, fhir::ParamKind)> {
946 self.resolver_output().param_res_map.get(&node_id).copied()
947 }
948
949 fn desugar_epath(&self, path: &surface::ExprPath) -> fhir::QPathExpr<'genv> {
950 let partial_res = *self
951 .resolver_output()
952 .expr_path_res_map
953 .get(&path.node_id)
954 .unwrap_or_else(|| span_bug!(path.span, "unresolved expr path"));
955
956 let unresolved_segments = partial_res.unresolved_segments();
957
958 if unresolved_segments == 0 {
959 let path = fhir::PathExpr {
960 segments: self
961 .genv()
962 .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident)),
963 res: partial_res.base_res(),
964 fhir_id: self.next_fhir_id(),
965 span: path.span,
966 };
967 return fhir::QPathExpr::Resolved(path, None);
968 }
969
970 let proj_start = path.segments.len() - unresolved_segments;
971 let ty_path = fhir::Path {
972 res: partial_res
973 .base_res()
974 .map_param_id(|_| span_bug!(path.span, "path resolved to refinement parameter")),
975 fhir_id: self.next_fhir_id(),
976 segments: self.genv().alloc_slice_fill_iter(
977 path.segments[..proj_start]
978 .iter()
979 .map(|segment| self.desugar_epath_segment(segment)),
980 ),
981 refine: &[],
982 span: path.span,
983 };
984
985 let mut ty = self
986 .genv()
987 .alloc(self.ty_path(fhir::QPath::Resolved(None, ty_path)));
988
989 for (i, segment) in path.segments.iter().enumerate().skip(proj_start) {
990 if i == path.segments.len() - 1 {
991 return fhir::QPathExpr::TypeRelative(ty, segment.ident);
992 }
993
994 let hir_segment = self.desugar_epath_segment(segment);
995 let qpath = fhir::QPath::TypeRelative(ty, self.genv().alloc(hir_segment));
996 ty = self.genv().alloc(self.ty_path(qpath));
997 }
998
999 span_bug!(
1000 path.span,
1001 "desugar_epath: no final extension segment in {}..{}",
1002 proj_start,
1003 path.segments.len()
1004 );
1005 }
1006
1007 #[track_caller]
1008 fn desugar_loc(&self, ident: surface::Ident, node_id: NodeId) -> Result<Res<ParamId>> {
1009 let partial_res = self.resolver_output().expr_path_res_map[&node_id];
1010 if let Some(res @ Res::Param(fhir::ParamKind::Loc, _)) = partial_res.full_res() {
1011 Ok(res)
1012 } else {
1013 let span = ident.span;
1014 Err(self.emit(errors::InvalidLoc { span }))
1015 }
1016 }
1017
1018 #[track_caller]
1019 fn resolve_param(&self, node_id: NodeId) -> (fhir::ParamId, fhir::ParamKind) {
1020 self.resolver_output().param_res_map[&node_id]
1021 }
1022
1023 fn resolve_implicit_params(
1024 &self,
1025 scope: NodeId,
1026 ) -> impl ExactSizeIterator<Item = (surface::Ident, fhir::ParamId, fhir::ParamKind)> {
1027 self.resolver_output()
1028 .implicit_params
1029 .get(&scope)
1030 .map_or(&[][..], |it| it)
1031 .iter()
1032 .map(|(ident, param_id)| {
1033 let (param_id, kind) = self.resolve_param(*param_id);
1034 (*ident, param_id, kind)
1035 })
1036 }
1037
1038 fn implicit_params_to_params(
1039 &self,
1040 scope: NodeId,
1041 ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
1042 self.resolve_implicit_params(scope)
1043 .map(|(ident, id, kind)| {
1044 let sort = if kind.is_loc() { fhir::Sort::Loc } else { fhir::Sort::Infer };
1045 fhir::RefineParam {
1046 id,
1047 name: ident.name,
1048 span: ident.span,
1049 kind,
1050 sort,
1051 fhir_id: self.next_fhir_id(),
1052 }
1053 })
1054 }
1055
1056 fn desugar_refine_params(
1057 &mut self,
1058 params: &[surface::RefineParam],
1059 ) -> &'genv [fhir::RefineParam<'genv>] {
1060 self.genv()
1061 .alloc_slice_fill_iter(self.desugar_refine_params_iter(params))
1062 }
1063
1064 fn desugar_refine_params_iter(
1065 &mut self,
1066 params: &[surface::RefineParam],
1067 ) -> impl ExactSizeIterator<Item = fhir::RefineParam<'genv>> {
1068 params.iter().map(|param| self.desugar_refine_param(param))
1069 }
1070
1071 fn desugar_refine_param(&mut self, param: &surface::RefineParam) -> fhir::RefineParam<'genv> {
1072 let (id, kind) = self.resolve_param(param.node_id);
1073 fhir::RefineParam {
1074 id,
1075 name: param.ident.name,
1076 span: param.ident.span,
1077 kind,
1078 sort: self.desugar_sort(¶m.sort, None),
1079 fhir_id: self.next_fhir_id(),
1080 }
1081 }
1082
1083 fn desugar_sort(
1084 &mut self,
1085 sort: &surface::Sort,
1086 generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1087 ) -> fhir::Sort<'genv> {
1088 match sort {
1089 surface::Sort::Base(bsort) => self.desugar_base_sort(bsort, generic_id_to_var_idx),
1090 surface::Sort::Func { inputs, output } => {
1091 let inputs_and_output = self.genv().alloc_slice_with_capacity(
1092 inputs.len() + 1,
1093 inputs
1094 .iter()
1095 .chain(iter::once(output))
1096 .map(|sort| self.desugar_base_sort(sort, generic_id_to_var_idx)),
1097 );
1098 fhir::Sort::Func(fhir::PolyFuncSort::new(0, inputs_and_output))
1099 }
1100 surface::Sort::Infer => fhir::Sort::Infer,
1101 }
1102 }
1103
1104 fn desugar_base_sort(
1105 &mut self,
1106 sort: &surface::BaseSort,
1107 generic_id_to_var_idx: Option<&FxIndexSet<DefId>>,
1108 ) -> fhir::Sort<'genv> {
1109 let genv = self.genv();
1110 match sort {
1111 surface::BaseSort::BitVec(width) => fhir::Sort::BitVec(*width),
1112 surface::BaseSort::Path(surface::SortPath { segments, args, node_id }) => {
1113 let res = self.resolver_output().sort_path_res_map[node_id];
1114
1115 let res = if let fhir::SortRes::TyParam(def_id) = res
1117 && let Some(generic_id_to_var_idx) = generic_id_to_var_idx
1118 {
1119 let idx = generic_id_to_var_idx.get_index_of(&def_id).unwrap();
1120 fhir::SortRes::SortParam(idx)
1121 } else {
1122 res
1123 };
1124
1125 let args = genv.alloc_slice_fill_iter(
1126 args.iter()
1127 .map(|s| self.desugar_base_sort(s, generic_id_to_var_idx)),
1128 );
1129
1130 let path = fhir::SortPath { res, segments: genv.alloc_slice(segments), args };
1131 fhir::Sort::Path(path)
1132 }
1133 surface::BaseSort::SortOf(qself, path) => {
1134 fhir::Sort::SortOf(self.desugar_path_to_bty(Some(qself), path))
1135 }
1136 surface::BaseSort::Tuple(sorts) => {
1137 let sorts = genv.alloc_slice_fill_iter(
1138 sorts
1139 .iter()
1140 .map(|s| self.desugar_base_sort(s, generic_id_to_var_idx)),
1141 );
1142 fhir::Sort::Tuple(sorts)
1143 }
1144 }
1145 }
1146
1147 fn desugar_generic_args(
1148 &mut self,
1149 res: Res,
1150 args: &[surface::GenericArg],
1151 ) -> (&'genv [fhir::GenericArg<'genv>], &'genv [fhir::AssocItemConstraint<'genv>]) {
1152 let mut fhir_args = vec![];
1153 let mut constraints = vec![];
1154 if let Res::Def(
1155 DefKind::TyAlias | DefKind::Struct | DefKind::Enum | DefKind::OpaqueTy,
1156 def_id,
1157 ) = res
1158 {
1159 let generics = self.genv().tcx().generics_of(def_id);
1160 for param in &generics.own_params {
1161 if let rustc_middle::ty::GenericParamDefKind::Lifetime = param.kind {
1162 fhir_args.push(fhir::GenericArg::Lifetime(self.mk_lft_hole()));
1163 }
1164 }
1165 }
1166 for arg in args {
1167 match &arg.kind {
1168 surface::GenericArgKind::Type(ty) => {
1169 if matches!(ty.kind, surface::TyKind::Hole) {
1170 fhir_args.push(fhir::GenericArg::Infer);
1171 continue;
1172 }
1173 if let Some(path) = ty.is_potential_const_arg()
1176 && let Some(res) =
1177 self.resolver_output().path_res_map[&path.node_id].full_res()
1178 && res.matches_ns(Namespace::ValueNS)
1179 {
1180 fhir_args.push(self.desugar_const_path_to_const_arg(path, res));
1181 continue;
1182 }
1183 let ty = self.desugar_ty(ty);
1184 fhir_args.push(fhir::GenericArg::Type(self.genv().alloc(ty)));
1185 }
1186 surface::GenericArgKind::Constraint(ident, ty) => {
1187 constraints.push(fhir::AssocItemConstraint {
1188 ident: *ident,
1189 kind: fhir::AssocItemConstraintKind::Equality { term: self.desugar_ty(ty) },
1190 });
1191 }
1192 }
1193 }
1194 (self.genv().alloc_slice(&fhir_args), self.genv().alloc_slice(&constraints))
1195 }
1196
1197 fn desugar_const_path_to_const_arg(
1198 &mut self,
1199 path: &surface::Path,
1200 res: fhir::Res<!>,
1201 ) -> fhir::GenericArg<'genv> {
1202 let kind = self.desugar_const_path_to_const_arg_kind(path, res);
1203 fhir::GenericArg::Const(fhir::ConstArg { kind, span: path.span })
1204 }
1205
1206 fn desugar_const_path_to_const_arg_kind(
1207 &mut self,
1208 path: &surface::Path,
1209 res: fhir::Res<!>,
1210 ) -> fhir::ConstArgKind {
1211 if let Res::Def(DefKind::ConstParam, def_id) = res {
1212 fhir::ConstArgKind::Param(def_id)
1213 } else {
1214 self.emit(errors::UnsupportedConstGenericArg::new(path.span, res.descr()));
1215 fhir::ConstArgKind::Infer
1216 }
1217 }
1218
1219 fn desugar_ty(&mut self, ty: &surface::Ty) -> fhir::Ty<'genv> {
1224 let node_id = ty.node_id;
1225 let span = ty.span;
1226 let kind = match &ty.kind {
1227 surface::TyKind::Base(bty) => {
1228 let bty = self.desugar_bty(bty);
1229 fhir::TyKind::BaseTy(bty)
1230 }
1231 surface::TyKind::Indexed { bty, indices } => {
1232 let bty = self.desugar_bty(bty);
1233 let idx = self.desugar_indices(indices);
1234 fhir::TyKind::Indexed(bty, idx)
1235 }
1236 surface::TyKind::Exists { bind, bty, pred } => {
1237 let ty_span = ty.span;
1238 let bty_span = bty.span;
1239
1240 let bty = self.desugar_bty(bty);
1241 let pred = self.desugar_expr(pred);
1242
1243 let (id, kind) = self.resolve_param(node_id);
1244 let param = fhir::RefineParam {
1245 id,
1246 name: bind.name,
1247 span: bind.span,
1248 sort: fhir::Sort::Infer,
1249 kind,
1250 fhir_id: self.next_fhir_id(),
1251 };
1252 let path = fhir::PathExpr {
1253 segments: self.genv().alloc_slice(&[*bind]),
1254 res: Res::Param(kind, id),
1255 fhir_id: self.next_fhir_id(),
1256 span: bind.span,
1257 };
1258 let idx = fhir::Expr {
1259 kind: fhir::ExprKind::Var(QPathExpr::Resolved(path, None)),
1260 span: bind.span,
1261 fhir_id: self.next_fhir_id(),
1262 };
1263 let indexed = fhir::Ty { kind: fhir::TyKind::Indexed(bty, idx), span: bty_span };
1264 let constr = fhir::Ty {
1265 kind: fhir::TyKind::Constr(pred, self.genv().alloc(indexed)),
1266 span: ty_span,
1267 };
1268 fhir::TyKind::Exists(self.genv().alloc_slice(&[param]), self.genv().alloc(constr))
1269 }
1270 surface::TyKind::GeneralExists { params, ty, pred } => {
1271 let mut ty = self.desugar_ty(ty);
1272 if let Some(pred) = pred {
1273 let pred = self.desugar_expr(pred);
1274 ty = fhir::Ty { kind: fhir::TyKind::Constr(pred, self.genv().alloc(ty)), span };
1275 }
1276 let params = self.desugar_refine_params(params);
1277
1278 fhir::TyKind::Exists(params, self.genv().alloc(ty))
1279 }
1280 surface::TyKind::Constr(pred, ty) => {
1281 let pred = self.desugar_expr(pred);
1282 let ty = self.desugar_ty(ty);
1283 fhir::TyKind::Constr(pred, self.genv().alloc(ty))
1284 }
1285 surface::TyKind::Ref(mutbl, ty) => {
1286 let ty = self.desugar_ty(ty);
1287 let mut_ty = fhir::MutTy { ty: self.genv().alloc(ty), mutbl: *mutbl };
1288 fhir::TyKind::Ref(self.mk_lft_hole(), mut_ty)
1289 }
1290
1291 surface::TyKind::Tuple(tys) => {
1292 let tys = self
1293 .genv()
1294 .alloc_slice_fill_iter(tys.iter().map(|ty| self.desugar_ty(ty)));
1295 fhir::TyKind::Tuple(tys)
1296 }
1297 surface::TyKind::Array(ty, len) => {
1298 let ty = self.desugar_ty(ty);
1299 let len = self.desugar_const_arg(len);
1300 fhir::TyKind::Array(self.genv().alloc(ty), len)
1301 }
1302 surface::TyKind::ImplTrait(_, bounds) => self.desugar_impl_trait(bounds),
1303 surface::TyKind::Hole => fhir::TyKind::Infer,
1304 };
1305 fhir::Ty { kind, span }
1306 }
1307
1308 fn desugar_const_arg(&mut self, const_arg: &surface::ConstArg) -> fhir::ConstArg {
1309 let kind = match &const_arg.kind {
1310 surface::ConstArgKind::Lit(val) => fhir::ConstArgKind::Lit(*val),
1311 surface::ConstArgKind::Path(path) => {
1312 let res = self.resolver_output().path_res_map[&path.node_id]
1313 .full_res()
1314 .unwrap_or(Res::Err);
1315 self.desugar_const_path_to_const_arg_kind(path, res)
1316 }
1317 surface::ConstArgKind::Infer => fhir::ConstArgKind::Infer,
1318 };
1319 fhir::ConstArg { kind, span: const_arg.span }
1320 }
1321
1322 fn desugar_bty(&mut self, bty: &surface::BaseTy) -> fhir::BaseTy<'genv> {
1323 match &bty.kind {
1324 surface::BaseTyKind::Path(qself, path) => {
1325 let qpath = self.desugar_qpath(qself.as_deref(), path);
1326 fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1327 }
1328 surface::BaseTyKind::Slice(ty) => {
1329 let ty = self.desugar_ty(ty);
1330 let kind = fhir::BaseTyKind::Slice(self.genv().alloc(ty));
1331 fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: bty.span }
1332 }
1333 surface::BaseTyKind::Ptr(mutbl, ty) => {
1334 let ty = self.desugar_ty(ty);
1335 let kind = fhir::BaseTyKind::RawPtr(self.genv().alloc(ty), *mutbl);
1336 fhir::BaseTy { kind, fhir_id: self.next_fhir_id(), span: bty.span }
1337 }
1338 }
1339 }
1340
1341 fn desugar_path_to_bty(
1342 &mut self,
1343 qself: Option<&surface::Ty>,
1344 path: &surface::Path,
1345 ) -> fhir::BaseTy<'genv> {
1346 let qpath = self.desugar_qpath(qself, path);
1347 fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())
1348 }
1349
1350 fn desugar_qpath(
1351 &mut self,
1352 qself: Option<&surface::Ty>,
1353 path: &surface::Path,
1354 ) -> fhir::QPath<'genv> {
1355 let qself = if let Some(ty) = qself {
1356 let ty = self.desugar_ty(ty);
1357 Some(self.genv().alloc(ty))
1358 } else {
1359 None
1360 };
1361 let partial_res = self.resolver_output().path_res_map[&path.node_id];
1362
1363 let unresolved_segments = partial_res.unresolved_segments();
1364
1365 let proj_start = path.segments.len() - unresolved_segments;
1366 let fhir_path = fhir::Path {
1367 res: partial_res.base_res(),
1368 fhir_id: self.next_fhir_id(),
1369 segments: self.genv().alloc_slice_fill_iter(
1370 path.segments[..proj_start]
1371 .iter()
1372 .map(|segment| self.desugar_path_segment(segment)),
1373 ),
1374 refine: self
1375 .genv()
1376 .alloc_slice_fill_iter(path.refine.iter().map(|arg| self.desugar_refine_arg(arg))),
1377 span: path.span,
1378 };
1379
1380 if unresolved_segments == 0 {
1383 return fhir::QPath::Resolved(qself, fhir_path);
1384 }
1385
1386 let mut ty = if fhir_path.segments.is_empty() {
1388 qself.expect("missing QSelf for <T>::...")
1391 } else {
1392 self.genv()
1396 .alloc(self.ty_path(fhir::QPath::Resolved(qself, fhir_path)))
1397 };
1398
1399 for (i, segment) in path.segments.iter().enumerate().skip(proj_start) {
1400 let hir_segment = self.desugar_path_segment(segment);
1401 let qpath = fhir::QPath::TypeRelative(ty, self.genv().alloc(hir_segment));
1402
1403 if i == path.segments.len() - 1 {
1404 return qpath;
1405 }
1406
1407 ty = self.genv().alloc(self.ty_path(qpath));
1408 }
1409
1410 span_bug!(
1411 path.span,
1412 "desugar_qpath: no final extension segment in {}..{}",
1413 proj_start,
1414 path.segments.len()
1415 );
1416 }
1417
1418 fn desugar_path_segment(&mut self, segment: &surface::PathSegment) -> fhir::PathSegment<'genv> {
1419 let res = self
1420 .resolver_output()
1421 .path_res_map
1422 .get(&segment.node_id)
1423 .map_or(Res::Err, |r| r.expect_full_res());
1424 let (args, constraints) = self.desugar_generic_args(res, &segment.args);
1425 fhir::PathSegment { ident: segment.ident, res, args, constraints }
1426 }
1427
1428 fn desugar_epath_segment(
1429 &self,
1430 segment: &surface::ExprPathSegment,
1431 ) -> fhir::PathSegment<'genv> {
1432 let res = self
1433 .resolver_output()
1434 .expr_path_res_map
1435 .get(&segment.node_id)
1436 .map_or(Res::Err, |r| r.expect_full_res())
1437 .map_param_id(|_| bug!("segment resolved to refinement parameter"));
1438 fhir::PathSegment { ident: segment.ident, res, args: &[], constraints: &[] }
1439 }
1440
1441 fn ty_path(&self, qpath: fhir::QPath<'genv>) -> fhir::Ty<'genv> {
1442 fhir::Ty {
1443 span: qpath.span(),
1444 kind: fhir::TyKind::BaseTy(fhir::BaseTy::from_qpath(qpath, self.next_fhir_id())),
1445 }
1446 }
1447
1448 fn mk_lft_hole(&self) -> fhir::Lifetime {
1449 fhir::Lifetime(self.next_fhir_id())
1450 }
1451
1452 fn desugar_indices(&mut self, idxs: &surface::Indices) -> fhir::Expr<'genv> {
1453 if let [arg] = &idxs.indices[..] {
1454 self.desugar_refine_arg(arg)
1455 } else {
1456 let flds = self
1457 .genv()
1458 .alloc_slice_fill_iter(idxs.indices.iter().map(|arg| self.desugar_refine_arg(arg)));
1459 fhir::Expr {
1460 kind: fhir::ExprKind::Record(flds),
1461 fhir_id: self.next_fhir_id(),
1462 span: idxs.span,
1463 }
1464 }
1465 }
1466
1467 fn desugar_refine_arg(&mut self, arg: &surface::RefineArg) -> fhir::Expr<'genv> {
1468 match arg {
1469 surface::RefineArg::Bind(ident, .., node_id) => {
1470 self.implicit_param_into_refine_arg(*ident, *node_id)
1471 .unwrap()
1472 }
1473 surface::RefineArg::Expr(expr) => self.desugar_expr(expr),
1474 surface::RefineArg::Abs(params, body, span, _) => {
1475 let body = self.genv().alloc(self.desugar_expr(body));
1476 let params = self.desugar_refine_params(params);
1477 fhir::Expr {
1478 kind: fhir::ExprKind::Abs(params, body),
1479 fhir_id: self.next_fhir_id(),
1480 span: *span,
1481 }
1482 }
1483 }
1484 }
1485
1486 fn implicit_param_into_refine_arg(
1487 &self,
1488 ident: surface::Ident,
1489 node_id: NodeId,
1490 ) -> Option<fhir::Expr<'genv>> {
1491 let (id, kind) = self.resolve_implicit_param(node_id)?;
1492 let path = fhir::PathExpr {
1493 segments: self.genv().alloc_slice(&[ident]),
1494 res: Res::Param(kind, id),
1495 fhir_id: self.next_fhir_id(),
1496 span: ident.span,
1497 };
1498 Some(fhir::Expr {
1499 kind: fhir::ExprKind::Var(QPathExpr::Resolved(path, Some(kind))),
1500 span: ident.span,
1501 fhir_id: self.next_fhir_id(),
1502 })
1503 }
1504
1505 fn desugar_quant_dom(&mut self, dom: &Option<Range<usize>>) -> fhir::QuantDom {
1506 match dom {
1507 Some(rng) => fhir::QuantDom::Bounded { start: rng.start, end: rng.end },
1508 None => fhir::QuantDom::Unbounded,
1509 }
1510 }
1511
1512 fn desugar_expr(&mut self, expr: &surface::Expr) -> fhir::Expr<'genv> {
1513 let kind = match &expr.kind {
1514 surface::ExprKind::Path(path) => fhir::ExprKind::Var(self.desugar_epath(path)),
1515 surface::ExprKind::Literal(lit) => self.desugar_lit(expr.span, *lit),
1516 surface::ExprKind::BinaryOp(op, box [e1, e2]) => {
1517 let e1 = self.desugar_expr(e1);
1518 let e2 = self.desugar_expr(e2);
1519 fhir::ExprKind::BinaryOp(*op, self.genv().alloc(e1), self.genv().alloc(e2))
1520 }
1521 surface::ExprKind::UnaryOp(op, box e) => {
1522 fhir::ExprKind::UnaryOp(*op, self.genv().alloc(self.desugar_expr(e)))
1523 }
1524 surface::ExprKind::Dot(base, fld) => {
1525 let base = self.desugar_expr(base);
1526 fhir::ExprKind::Dot(self.genv().alloc(base), *fld)
1527 }
1528 surface::ExprKind::Call(callee, args) => self.desugar_call(callee, args),
1529 surface::ExprKind::AssocReft(..) | surface::ExprKind::PrimUIF(..) => {
1530 fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(expr.span)))
1531 }
1532 surface::ExprKind::IfThenElse(box [p, e1, e2]) => {
1533 let p = self.desugar_expr(p);
1534 let e1 = self.desugar_expr(e1);
1535 let e2 = self.desugar_expr(e2);
1536 fhir::ExprKind::IfThenElse(
1537 self.genv().alloc(p),
1538 self.genv().alloc(e1),
1539 self.genv().alloc(e2),
1540 )
1541 }
1542 surface::ExprKind::Constructor(path, args) => {
1543 self.desugar_constructor(path.as_ref(), args)
1544 }
1545 surface::ExprKind::Quant(kind, param, dom, body) => {
1546 let kind = match kind {
1547 surface::QuantKind::Exists => fhir::QuantKind::Exists,
1548 surface::QuantKind::Forall => fhir::QuantKind::Forall,
1549 };
1550 let body = self.genv().alloc(self.desugar_expr(body));
1551 let param = self.desugar_refine_param(param);
1552 let rng = self.desugar_quant_dom(dom);
1553 fhir::ExprKind::Quant(kind, param, rng, body)
1554 }
1555 surface::ExprKind::Block(decls, body) => {
1556 let decls = self.genv().alloc_slice_fill_iter(decls.iter().map(|decl| {
1557 fhir::LetDecl {
1558 param: self.desugar_refine_param(&decl.param),
1559 init: self.desugar_expr(&decl.init),
1560 }
1561 }));
1562 let body = self.genv().alloc(self.desugar_expr(body));
1563 fhir::ExprKind::Block(decls, body)
1564 }
1565 surface::ExprKind::SetLiteral(exprs) => {
1566 let exprs = self
1567 .genv()
1568 .alloc_slice_fill_iter(exprs.iter().map(|expr| self.desugar_expr(expr)));
1569 fhir::ExprKind::SetLiteral(exprs)
1570 }
1571 surface::ExprKind::Tuple(exprs) => {
1572 let exprs = self
1573 .genv()
1574 .alloc_slice_fill_iter(exprs.iter().map(|expr| self.desugar_expr(expr)));
1575 fhir::ExprKind::Tuple(exprs)
1576 }
1577 };
1578
1579 fhir::Expr { kind, span: expr.span, fhir_id: self.next_fhir_id() }
1580 }
1581
1582 fn desugar_call(
1583 &mut self,
1584 callee: &surface::Expr,
1585 args: &[surface::Expr],
1586 ) -> fhir::ExprKind<'genv> {
1587 let args = self.desugar_exprs(args);
1588 match &callee.kind {
1589 surface::ExprKind::Path(path) => {
1590 match self.desugar_epath(path) {
1591 QPathExpr::Resolved(path, _) => fhir::ExprKind::App(path, args),
1592 QPathExpr::TypeRelative(qself, name) => {
1593 fhir::ExprKind::Alias(fhir::AliasReft::TypeRelative { qself, name }, args)
1594 }
1595 }
1596 }
1597 surface::ExprKind::PrimUIF(op) if args.len() == 2 && self.allow_primop_app() => {
1598 fhir::ExprKind::PrimApp(*op, &args[0], &args[1])
1599 }
1600 surface::ExprKind::AssocReft(qself, path, name) => {
1601 let qself = self.desugar_ty(qself);
1602 let fhir::QPath::Resolved(None, trait_) = self.desugar_qpath(None, path) else {
1603 span_bug!(path.span, "desugar_alias_reft: unexpected qpath")
1604 };
1605 let Res::Def(DefKind::Trait, _) = trait_.res else {
1606 return fhir::ExprKind::Err(self.emit(errors::InvalidAliasReft::new(path)));
1608 };
1609 let alias_reft = fhir::AliasReft::Qualified {
1610 qself: self.genv().alloc(qself),
1611 trait_,
1612 name: *name,
1613 };
1614 fhir::ExprKind::Alias(alias_reft, args)
1615 }
1616 _ => fhir::ExprKind::Err(self.emit(errors::UnsupportedPosition::new(callee.span))),
1617 }
1618 }
1619
1620 fn desugar_constructor(
1621 &mut self,
1622 path: Option<&surface::ExprPath>,
1623 args: &[surface::ConstructorArg],
1624 ) -> fhir::ExprKind<'genv> {
1625 let path = if let Some(path) = path {
1626 let Some(res @ Res::Def(DefKind::Struct | DefKind::Enum, _)) =
1627 self.resolver_output().expr_path_res_map[&path.node_id].full_res()
1628 else {
1629 return fhir::ExprKind::Err(
1630 self.emit(errors::InvalidConstructorPath { span: path.span }),
1631 );
1632 };
1633 let segments = self
1634 .genv()
1635 .alloc_slice_fill_iter(path.segments.iter().map(|s| s.ident));
1636 Some(fhir::PathExpr { res, segments, fhir_id: self.next_fhir_id(), span: path.span })
1637 } else {
1638 None
1639 };
1640
1641 let (field_exprs, spreads): (Vec<_>, Vec<_>) = args.iter().partition_map(|arg| {
1642 match arg {
1643 ConstructorArg::FieldExpr(e) => Either::Left(e),
1644 ConstructorArg::Spread(s) => Either::Right(s),
1645 }
1646 });
1647
1648 let field_exprs = self
1649 .genv()
1650 .alloc_slice_fill_iter(field_exprs.iter().map(|field_expr| {
1651 let e = self.desugar_refine_arg(&field_expr.expr);
1652 fhir::FieldExpr {
1653 ident: field_expr.ident,
1654 expr: e,
1655 fhir_id: self.next_fhir_id(),
1656 span: e.span,
1657 }
1658 }));
1659
1660 match &spreads[..] {
1661 [] => fhir::ExprKind::Constructor(path, field_exprs, None),
1662 [s] => {
1663 let spread = fhir::Spread {
1664 expr: self.desugar_expr(&s.expr),
1665 span: s.span,
1666 fhir_id: self.next_fhir_id(),
1667 };
1668 fhir::ExprKind::Constructor(path, field_exprs, Some(self.genv().alloc(spread)))
1669 }
1670 [s1, s2, ..] => {
1671 let err = errors::MultipleSpreadsInConstructor::new(s1.span, s2.span);
1672 fhir::ExprKind::Err(self.emit(err))
1673 }
1674 }
1675 }
1676
1677 fn desugar_exprs(&mut self, exprs: &[surface::Expr]) -> &'genv [fhir::Expr<'genv>] {
1678 self.genv()
1679 .alloc_slice_fill_iter(exprs.iter().map(|e| self.desugar_expr(e)))
1680 }
1681
1682 fn try_parse_int_lit(&self, span: Span, s: &str) -> Result<u128> {
1683 let s = s.replace("_", "");
1684 let parsed_int = if s.len() <= 2 {
1685 s.parse::<u128>()
1686 } else {
1687 match &s[0..2] {
1688 "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>(), }
1693 };
1694
1695 if let Ok(n) = parsed_int {
1696 Ok(n) } else {
1698 Err(self.emit(errors::IntTooLarge { span }))
1699 }
1700 }
1701
1702 fn desugar_lit(&self, span: Span, lit: surface::Lit) -> fhir::ExprKind<'genv> {
1704 let lit = match lit.kind {
1705 surface::LitKind::Integer => {
1706 let n = match self.try_parse_int_lit(span, lit.symbol.as_str()) {
1707 Ok(n) => n,
1708 Err(err) => return fhir::ExprKind::Err(err),
1709 };
1710 match lit.suffix {
1711 None => fhir::Lit::Int(n),
1712 Some(suffix) => {
1713 return fhir::ExprKind::Err(
1714 self.emit(errors::InvalidNumericSuffix::new(span, suffix)),
1715 );
1716 }
1717 }
1718 }
1719 surface::LitKind::Float => {
1720 if let Some(suffix) = lit.suffix {
1721 return fhir::ExprKind::Err(
1722 self.emit(errors::InvalidNumericSuffix::new(span, suffix)),
1723 );
1724 }
1725 fhir::Lit::Real(lit.symbol)
1726 }
1727 surface::LitKind::Bool => fhir::Lit::Bool(lit.symbol == kw::True),
1728 surface::LitKind::Str => fhir::Lit::Str(lit.symbol),
1729 surface::LitKind::Char => fhir::Lit::Char(lit.symbol.as_str().parse::<char>().unwrap()),
1730 _ => return fhir::ExprKind::Err(self.emit(errors::UnexpectedLiteral { span })),
1731 };
1732 fhir::ExprKind::Literal(lit)
1733 }
1734}
1735
1736impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for RustItemCtxt<'_, 'genv, 'tcx> {
1737 fn next_fhir_id(&self) -> FhirId {
1738 FhirId { owner: FluxOwnerId::Rust(self.owner), local_id: self.local_id_gen.fresh() }
1739 }
1740
1741 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1742 self.genv
1743 }
1744
1745 fn resolver_output(&self) -> &'genv ResolverOutput {
1746 self.resolver_output
1747 }
1748
1749 fn desugar_impl_trait(&mut self, bounds: &[surface::TraitRef]) -> fhir::TyKind<'genv> {
1750 let def_id = self.opaque.unwrap();
1752
1753 let opaque_ty = self.desugar_opaque_ty_for_impl_trait(def_id, bounds);
1756 let opaque_ty = self.insert_opaque_ty(opaque_ty);
1757
1758 fhir::TyKind::OpaqueDef(opaque_ty)
1759 }
1760}
1761
1762impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> for FluxItemCtxt<'genv, 'tcx> {
1763 fn next_fhir_id(&self) -> FhirId {
1764 FhirId { owner: FluxOwnerId::Flux(self.owner), local_id: self.local_id_gen.fresh() }
1765 }
1766
1767 fn allow_primop_app(&self) -> bool {
1768 self.allow_primop_app
1769 }
1770
1771 fn genv(&self) -> GlobalEnv<'genv, 'tcx> {
1772 self.genv
1773 }
1774
1775 fn resolver_output(&self) -> &'genv ResolverOutput {
1776 self.resolver_output
1777 }
1778
1779 fn desugar_impl_trait(&mut self, _: &[surface::TraitRef]) -> fhir::TyKind<'genv> {
1780 unimplemented!("`impl Trait` not supported in this item")
1781 }
1782}
1783
1784fn collect_opaque_types(
1787 genv: GlobalEnv,
1788 owner_id: MaybeExternId<OwnerId>,
1789) -> Result<Option<LocalDefId>> {
1790 let mut collector = OpaqueTypeCollector::new(genv.sess());
1791 match genv.tcx().hir_owner_node(owner_id.local_id()) {
1792 hir::OwnerNode::Item(item) => hir::intravisit::walk_item(&mut collector, item),
1793 hir::OwnerNode::ImplItem(impl_item) => {
1794 hir::intravisit::walk_impl_item(&mut collector, impl_item);
1795 }
1796 hir::OwnerNode::TraitItem(trait_item) => {
1797 hir::intravisit::walk_trait_item(&mut collector, trait_item);
1798 }
1799 hir::OwnerNode::ForeignItem(_) | hir::OwnerNode::Crate(_) | hir::OwnerNode::Synthetic => {}
1800 };
1801 collector.into_result()
1802}
1803
1804struct OpaqueTypeCollector<'sess> {
1805 opaque: Option<LocalDefId>,
1806 errors: Errors<'sess>,
1807}
1808
1809impl<'sess> OpaqueTypeCollector<'sess> {
1810 fn new(sess: &'sess FluxSession) -> Self {
1811 Self { opaque: None, errors: Errors::new(sess) }
1812 }
1813
1814 fn into_result(self) -> Result<Option<LocalDefId>> {
1815 self.errors.into_result()?;
1816 Ok(self.opaque)
1817 }
1818}
1819
1820impl<'tcx> hir::intravisit::Visitor<'tcx> for OpaqueTypeCollector<'_> {
1821 fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, rustc_hir::AmbigArg>) {
1822 if let hir::TyKind::OpaqueDef(opaque_ty, ..) = ty.kind {
1823 if self.opaque.is_some() {
1824 self.errors.emit(errors::UnsupportedSignature {
1825 span: ty.span,
1826 note: "duplicate opaque types in signature",
1827 });
1828 } else {
1829 self.opaque = Some(opaque_ty.def_id);
1830 }
1831 }
1832 hir::intravisit::walk_ty(self, ty);
1833 }
1834}