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