1#![feature(rustc_private, box_patterns, if_let_guard, once_cell_try, never_type)]
2
3extern crate rustc_abi;
4extern crate rustc_ast;
5extern crate rustc_data_structures;
6extern crate rustc_errors;
7extern crate rustc_hir;
8extern crate rustc_index;
9extern crate rustc_infer;
10extern crate rustc_middle;
11extern crate rustc_span;
12extern crate rustc_trait_selection;
13extern crate rustc_type_ir;
14
15mod conv;
16mod wf;
17use std::{iter, rc::Rc};
18
19use conv::{AfterSortck, ConvPhase, struct_compat};
20use flux_common::{bug, dbg, iter::IterExt, result::ResultExt};
21use flux_config as config;
22use flux_errors::Errors;
23use flux_macros::fluent_messages;
24use flux_middle::{
25 def_id::{FluxDefId, FluxId, MaybeExternId},
26 fhir::{
27 self, ForeignItem, ForeignItemKind, ImplItem, ImplItemKind, Item, ItemKind, TraitItem,
28 TraitItemKind,
29 },
30 global_env::GlobalEnv,
31 queries::{Providers, QueryResult},
32 query_bug,
33 rty::{
34 self, AssocReft, Binder, WfckResults,
35 fold::TypeFoldable,
36 refining::{self, Refiner},
37 },
38};
39use flux_rustc_bridge::lowering::Lower;
40use itertools::Itertools;
41use rustc_abi::FIRST_VARIANT;
42use rustc_data_structures::unord::UnordMap;
43use rustc_errors::ErrorGuaranteed;
44use rustc_hir::{
45 OwnerId,
46 def::{CtorOf, DefKind},
47 def_id::{DefId, LocalDefId},
48};
49use rustc_span::Span;
50
51fluent_messages! { "../locales/en-US.ftl" }
52
53pub fn provide(providers: &mut Providers) {
54 providers.normalized_defns = normalized_defns;
55 providers.func_sort = func_sort;
56 providers.func_span = flux_def_ident_span;
57 providers.qualifiers = qualifiers;
58 providers.prim_rel = prim_rel;
59 providers.adt_sort_def_of = adt_sort_def_of;
60 providers.check_wf = check_wf;
61 providers.adt_def = adt_def;
62 providers.constant_info = constant_info;
63 providers.type_of = type_of;
64 providers.variants_of = variants_of;
65 providers.fn_sig = fn_sig;
66 providers.generics_of = generics_of;
67 providers.refinement_generics_of = refinement_generics_of;
68 providers.predicates_of = predicates_of;
69 providers.assoc_refinements_of = assoc_refinements_of;
70 providers.sort_of_assoc_reft = sort_of_assoc_reft;
71 providers.assoc_refinement_body = assoc_refinement_body;
72 providers.default_assoc_refinement_body = default_assoc_refinement_body;
73 providers.item_bounds = item_bounds;
74 providers.sort_decl_param_count = sort_decl_param_count;
75}
76
77fn sort_decl_param_count(genv: GlobalEnv, def_id: FluxId<MaybeExternId>) -> usize {
78 genv.fhir_sort_decl(def_id.local_id()).unwrap().params
79}
80
81fn adt_sort_def_of(genv: GlobalEnv, def_id: MaybeExternId) -> QueryResult<rty::AdtSortDef> {
82 let kind = genv.fhir_expect_refinement_kind(def_id.local_id())?;
83 conv::conv_adt_sort_def(genv, def_id, kind)
84}
85
86fn func_sort(genv: GlobalEnv, def_id: FluxId<MaybeExternId>) -> rty::PolyFuncSort {
87 let func = genv.fhir_spec_func_body(def_id.local_id()).unwrap();
88 match conv::conv_func_decl(genv, func).emit(&genv) {
89 Ok(normalized) => normalized,
90 Err(err) => {
91 genv.sess().abort(err);
92 }
93 }
94}
95
96fn flux_def_ident_span(genv: GlobalEnv, def_id: FluxId<MaybeExternId>) -> Span {
97 genv.fhir_spec_func_body(def_id.local_id())
98 .unwrap()
99 .ident_span
100}
101
102fn normalized_defns(genv: GlobalEnv) -> rty::NormalizedDefns {
103 match try_normalized_defns(genv) {
104 Ok(normalized) => normalized,
105 Err(err) => {
106 genv.sess().abort(err);
107 }
108 }
109}
110
111fn try_normalized_defns(genv: GlobalEnv) -> Result<rty::NormalizedDefns, ErrorGuaranteed> {
112 let mut defns = vec![];
113
114 let mut errors = Errors::new(genv.sess());
116 for (_, item) in genv.fhir_iter_flux_items() {
117 let fhir::FluxItem::Func(func) = item else { continue };
118 let Some(wfckresults) = wf::check_flux_item(genv, item).collect_err(&mut errors) else {
119 continue;
120 };
121 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
122 let Ok(defn) = cx.conv_defn(func).emit(&errors) else {
123 continue;
124 };
125
126 if let Some(defn) = defn {
127 defns.push((func.def_id, defn, func.hide));
128 }
129 }
130 errors.into_result()?;
131
132 let defns = rty::NormalizedDefns::new(genv, &defns)
133 .map_err(|cycle| {
134 let span = genv
135 .fhir_spec_func_body(cycle[0])
136 .unwrap()
137 .body
138 .unwrap()
139 .span;
140 errors::DefinitionCycle::new(span, cycle)
141 })
142 .emit(&genv)?;
143
144 Ok(defns)
145}
146
147fn qualifiers(genv: GlobalEnv) -> QueryResult<Vec<rty::Qualifier>> {
148 genv.fhir_qualifiers()
149 .map(|qualifier| {
150 let wfckresults = wf::check_flux_item(genv, fhir::FluxItem::Qualifier(qualifier))?;
151 Ok(AfterSortck::new(genv, &wfckresults)
152 .into_conv_ctxt()
153 .conv_qualifier(qualifier)?
154 .normalize(genv))
155 })
156 .try_collect()
157}
158
159fn primop_props(genv: GlobalEnv) -> QueryResult<Vec<rty::PrimOpProp>> {
160 genv.fhir_primop_props()
161 .map(|primop_prop| {
162 let wfckresults = wf::check_flux_item(genv, fhir::FluxItem::PrimOpProp(primop_prop))?;
163 Ok(AfterSortck::new(genv, &wfckresults)
164 .into_conv_ctxt()
165 .conv_primop_prop(primop_prop)?
166 .normalize(genv))
167 })
168 .try_collect()
169}
170
171fn conjoin_bind_exprs(exprs: Vec<Binder<rty::Expr>>) -> Binder<rty::Expr> {
172 let mut iter = exprs.into_iter();
173 let first = iter.next().unwrap();
174 let sorts = first.sorts();
175 let bodies = iter::once(first.skip_binder()).chain(iter.map(|expr| expr.skip_binder()));
176 let expr = rty::Expr::and_from_iter(bodies);
177 Binder::bind_with_sorts(expr, &sorts)
178}
179
180fn prim_rel(genv: GlobalEnv) -> QueryResult<UnordMap<rty::BinOp, rty::PrimRel>> {
181 let primop_props = primop_props(genv)?
182 .into_iter()
183 .into_group_map_by(|primop_prop| primop_prop.op.clone());
184
185 let mut res = UnordMap::default();
186 for (op, props) in primop_props {
187 let exprs = props
188 .iter()
189 .map(|prop| prop.body.clone())
190 .collect::<Vec<_>>();
191 let body = conjoin_bind_exprs(exprs);
192 res.insert(op, rty::PrimRel { body });
193 }
194 Ok(res)
195}
196
197fn adt_def(genv: GlobalEnv, def_id: MaybeExternId) -> QueryResult<rty::AdtDef> {
198 let item = genv.fhir_expect_item(def_id.local_id())?;
199 let invariants = invariants_of(genv, item)?;
200
201 let adt_def = genv.tcx().adt_def(def_id.resolved_id()).lower(genv.tcx());
202
203 let is_opaque = matches!(item.kind, fhir::ItemKind::Struct(def) if def.is_opaque());
204
205 Ok(rty::AdtDef::new(adt_def, genv.adt_sort_def_of(def_id)?, invariants, is_opaque))
206}
207
208fn constant_info(genv: GlobalEnv, def_id: MaybeExternId) -> QueryResult<rty::ConstantInfo> {
209 let node = genv.fhir_node(def_id.local_id())?;
210 let owner = rustc_hir::OwnerId { def_id: def_id.local_id() };
211 let Some(sort) = genv.sort_of_def_id(def_id.resolved_id()).emit(&genv)? else {
212 return Ok(rty::ConstantInfo::Uninterpreted);
213 };
214 match node {
215 fhir::Node::Item(fhir::Item { kind: fhir::ItemKind::Const(Some(expr)), .. }) => {
216 let wfckresults = wf::check_constant_expr(genv, owner, expr, &sort)?;
218 let expr = AfterSortck::new(genv, &wfckresults)
219 .into_conv_ctxt()
220 .conv_constant_expr(expr)?;
221 Ok(rty::ConstantInfo::Interpreted(expr, sort))
222 }
223 fhir::Node::Item(fhir::Item { kind: fhir::ItemKind::Const(None), .. })
224 | fhir::Node::AnonConst
225 | fhir::Node::TraitItem(fhir::TraitItem { kind: fhir::TraitItemKind::Const, .. })
226 | fhir::Node::ImplItem(fhir::ImplItem { kind: fhir::ImplItemKind::Const, .. }) => {
227 conv::conv_constant(genv, def_id.resolved_id())
229 }
230 _ => Err(query_bug!(def_id.local_id(), "expected const item"))?,
231 }
232}
233
234fn invariants_of<'genv>(
235 genv: GlobalEnv<'genv, '_>,
236 item: &fhir::Item<'genv>,
237) -> QueryResult<Vec<rty::Invariant>> {
238 let (params, invariants) = match &item.kind {
239 fhir::ItemKind::Enum(enum_def) => (enum_def.params, enum_def.invariants),
240 fhir::ItemKind::Struct(struct_def) => (struct_def.params, struct_def.invariants),
241 _ => Err(query_bug!(item.owner_id.local_id(), "expected struct or enum"))?,
242 };
243 let wfckresults = wf::check_invariants(genv, item.owner_id, params, invariants)?;
244 AfterSortck::new(genv, &wfckresults)
245 .into_conv_ctxt()
246 .conv_invariants(item.owner_id.map(|it| it.def_id), params, invariants)
247}
248
249fn predicates_of(
250 genv: GlobalEnv,
251 def_id: MaybeExternId,
252) -> QueryResult<rty::EarlyBinder<rty::GenericPredicates>> {
253 match genv.def_kind(def_id) {
254 DefKind::Impl { .. }
255 | DefKind::Struct
256 | DefKind::Enum
257 | DefKind::Union
258 | DefKind::TyAlias
259 | DefKind::AssocFn
260 | DefKind::AssocTy
261 | DefKind::Trait
262 | DefKind::Fn => {
263 let did = def_id.local_id();
264 let generics = genv
265 .fhir_get_generics(did)?
266 .ok_or_else(|| query_bug!(did, "no generics for {def_id:?}"))?;
267 let wfckresults = genv.check_wf(did)?;
268 AfterSortck::new(genv, &wfckresults)
269 .into_conv_ctxt()
270 .conv_generic_predicates(def_id, generics)
271 }
272 DefKind::OpaqueTy | DefKind::Closure => {
273 Ok(rty::EarlyBinder(rty::GenericPredicates {
274 parent: genv.tcx().predicates_of(def_id).parent,
275 predicates: rty::List::empty(),
276 }))
277 }
278 kind => {
279 Err(query_bug!(
280 def_id.local_id(),
281 "predicates_of called on `{def_id:?}` with kind `{kind:?}`"
282 ))?
283 }
284 }
285}
286
287fn assoc_refinements_of(
288 genv: GlobalEnv,
289 def_id: MaybeExternId,
290) -> QueryResult<rty::AssocRefinements> {
291 #[allow(
292 clippy::disallowed_methods,
293 reason = "We are iterationg over associated refinemens in fhir, so this is the *source of of truth*"
294 )]
295 let predicates = match &genv.fhir_expect_item(def_id.local_id())?.kind {
296 fhir::ItemKind::Trait(trait_) => {
297 trait_
298 .assoc_refinements
299 .iter()
300 .map(|assoc_reft| {
301 AssocReft::new(
302 FluxDefId::new(def_id.resolved_id(), assoc_reft.name),
303 assoc_reft.final_,
304 assoc_reft.span,
305 )
306 })
307 .collect()
308 }
309 fhir::ItemKind::Impl(impl_) => {
310 impl_
311 .assoc_refinements
312 .iter()
313 .map(|assoc_reft| {
314 AssocReft::new(
315 FluxDefId::new(def_id.resolved_id(), assoc_reft.name),
316 false,
317 assoc_reft.span,
318 )
319 })
320 .collect()
321 }
322 _ => Err(query_bug!(def_id.resolved_id(), "expected trait or impl"))?,
323 };
324 Ok(rty::AssocRefinements { items: predicates })
325}
326
327fn default_assoc_refinement_body(
328 genv: GlobalEnv,
329 trait_assoc_id: FluxId<MaybeExternId>,
330) -> QueryResult<Option<rty::EarlyBinder<rty::Lambda>>> {
331 let trait_id = trait_assoc_id.parent();
332 let assoc_reft = genv
333 .fhir_expect_item(trait_id.local_id())?
334 .expect_trait()
335 .find_assoc_reft(trait_assoc_id.name())
336 .unwrap();
337 let Some(body) = assoc_reft.body else { return Ok(None) };
338 let wfckresults = genv.check_wf(trait_id.local_id())?;
339 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
340 let body = cx.conv_assoc_reft_body(assoc_reft.params, &body, &assoc_reft.output)?;
341 Ok(Some(rty::EarlyBinder(body)))
342}
343
344fn assoc_refinement_body(
345 genv: GlobalEnv,
346 impl_assoc_id: FluxId<MaybeExternId>,
347) -> QueryResult<rty::EarlyBinder<rty::Lambda>> {
348 let impl_id = impl_assoc_id.parent();
349
350 let assoc_reft = genv
351 .fhir_expect_item(impl_id.local_id())?
352 .expect_impl()
353 .find_assoc_reft(impl_assoc_id.name())
354 .unwrap();
355
356 let wfckresults = genv.check_wf(impl_id.local_id())?;
357 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
358 let body = cx.conv_assoc_reft_body(assoc_reft.params, &assoc_reft.body, &assoc_reft.output)?;
359 Ok(rty::EarlyBinder(body))
360}
361
362fn sort_of_assoc_reft(
363 genv: GlobalEnv,
364 assoc_id: FluxId<MaybeExternId>,
365) -> QueryResult<rty::EarlyBinder<rty::FuncSort>> {
366 let container_id = assoc_id.parent();
367
368 match &genv.fhir_expect_item(container_id.local_id())?.kind {
369 fhir::ItemKind::Trait(trait_) => {
370 let assoc_reft = trait_.find_assoc_reft(assoc_id.name()).unwrap();
371 let wfckresults = WfckResults::new(OwnerId { def_id: container_id.local_id() });
372 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
373 let inputs = assoc_reft
374 .params
375 .iter()
376 .map(|p| cx.conv_sort(&p.sort))
377 .try_collect_vec()?;
378 let output = cx.conv_sort(&assoc_reft.output)?;
379 Ok(rty::EarlyBinder(rty::FuncSort::new(inputs, output)))
380 }
381 fhir::ItemKind::Impl(impl_) => {
382 let assoc_reft = impl_.find_assoc_reft(assoc_id.name()).unwrap();
383 let wfckresults = WfckResults::new(OwnerId { def_id: container_id.local_id() });
384 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
385 let inputs = assoc_reft
386 .params
387 .iter()
388 .map(|p| cx.conv_sort(&p.sort))
389 .try_collect_vec()?;
390 let output = cx.conv_sort(&assoc_reft.output)?;
391 Ok(rty::EarlyBinder(rty::FuncSort::new(inputs, output)))
392 }
393 _ => Err(query_bug!(container_id.local_id(), "expected trait or impl")),
394 }
395}
396
397fn item_bounds(
398 genv: GlobalEnv,
399 def_id: MaybeExternId,
400) -> QueryResult<rty::EarlyBinder<rty::Clauses>> {
401 let parent = genv.tcx().local_parent(def_id.local_id());
402 let wfckresults = genv.check_wf(parent)?;
403 let opaque_ty = genv.fhir_node(def_id.local_id())?.expect_opaque_ty();
404 Ok(rty::EarlyBinder(
405 AfterSortck::new(genv, &wfckresults)
406 .into_conv_ctxt()
407 .conv_opaque_ty(opaque_ty)?,
408 ))
409}
410
411fn generics_of(genv: GlobalEnv, def_id: MaybeExternId) -> QueryResult<rty::Generics> {
412 let def_kind = genv.def_kind(def_id);
413 let generics = match def_kind {
414 DefKind::Impl { .. }
415 | DefKind::Struct
416 | DefKind::Enum
417 | DefKind::Union
418 | DefKind::TyAlias
419 | DefKind::AssocFn
420 | DefKind::AssocTy
421 | DefKind::Trait
422 | DefKind::Fn => {
423 let is_trait = def_kind == DefKind::Trait;
424 let generics = genv
425 .fhir_get_generics(def_id.local_id())?
426 .ok_or_else(|| query_bug!(def_id.local_id(), "no generics for {def_id:?}"))?;
427 conv::conv_generics(genv, generics, def_id, is_trait)
428 }
429 DefKind::OpaqueTy | DefKind::Closure | DefKind::TraitAlias | DefKind::Ctor(..) => {
430 let rustc_generics = genv.lower_generics_of(def_id);
431 refining::refine_generics(genv, def_id.resolved_id(), &rustc_generics)
432 }
433 kind => {
434 Err(query_bug!(
435 def_id.local_id(),
436 "generics_of called on `{def_id:?}` with kind `{kind:?}`"
437 ))?
438 }
439 };
440 if config::dump_rty() {
441 dbg::dump_item_info(genv.tcx(), def_id.resolved_id(), "generics.rty", &generics).unwrap();
442 }
443 Ok(generics)
444}
445
446fn refinement_generics_of(
447 genv: GlobalEnv,
448 def_id: MaybeExternId,
449) -> QueryResult<rty::EarlyBinder<rty::RefinementGenerics>> {
450 let parent = genv.tcx().generics_of(def_id).parent;
451 let parent_count =
452 if let Some(def_id) = parent { genv.refinement_generics_of(def_id)?.count() } else { 0 };
453 let generics = match genv.fhir_node(def_id.local_id())? {
454 fhir::Node::Item(fhir::Item {
455 kind: fhir::ItemKind::Fn(..) | fhir::ItemKind::TyAlias(..),
456 generics,
457 ..
458 })
459 | fhir::Node::TraitItem(fhir::TraitItem {
460 kind: fhir::TraitItemKind::Fn(..),
461 generics,
462 ..
463 })
464 | fhir::Node::ImplItem(fhir::ImplItem {
465 kind: fhir::ImplItemKind::Fn(..), generics, ..
466 }) => {
467 let wfckresults = genv.check_wf(def_id.local_id())?;
468 let params = conv::conv_refinement_generics(generics.refinement_params, &wfckresults)?;
469 rty::RefinementGenerics { parent, parent_count, own_params: params }
470 }
471 _ => rty::RefinementGenerics { parent, parent_count, own_params: rty::List::empty() },
472 };
473 Ok(rty::EarlyBinder(generics))
474}
475
476fn type_of(genv: GlobalEnv, def_id: MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::TyOrCtor>> {
477 let ty = match genv.def_kind(def_id) {
478 DefKind::TyAlias => {
479 let fhir_ty_alias = genv
480 .fhir_expect_item(def_id.local_id())?
481 .expect_type_alias();
482 let wfckresults = genv.check_wf(def_id.local_id())?;
483 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
484 let ty_alias = cx.conv_type_alias(def_id, fhir_ty_alias)?;
485 struct_compat::type_alias(genv, fhir_ty_alias, &ty_alias, def_id)?;
486 rty::TyOrCtor::Ctor(ty_alias)
487 }
488 DefKind::TyParam => {
489 match def_id {
490 MaybeExternId::Local(local_id) => {
491 let owner = genv.tcx().hir_ty_param_owner(local_id);
492 let param = genv.fhir_get_generics(owner)?.unwrap().get_param(local_id);
493 match param.kind {
494 fhir::GenericParamKind::Type { default: Some(ty) } => {
495 let parent = genv.tcx().local_parent(local_id);
496 let wfckresults = genv.check_wf(parent)?;
497 conv::conv_default_type_parameter(genv, def_id, &ty, &wfckresults)?
498 .into()
499 }
500 k => Err(query_bug!(local_id, "non-type def def {k:?} {def_id:?}"))?,
501 }
502 }
503 MaybeExternId::Extern(_, extern_id) => {
504 let ty = genv.lower_type_of(extern_id)?.skip_binder();
505 Refiner::default_for_item(genv, ty_param_owner(genv, extern_id))?
506 .refine_ty_or_base(&ty)?
507 .into()
508 }
509 }
510 }
511 DefKind::Impl { .. } | DefKind::Struct | DefKind::Enum | DefKind::AssocTy => {
512 let ty = genv.lower_type_of(def_id)?.skip_binder();
513 Refiner::default_for_item(genv, def_id.resolved_id())?
514 .refine_ty_or_base(&ty)?
515 .into()
516 }
517 kind => {
518 Err(query_bug!(
519 def_id.local_id(),
520 "`{:?}` not supported",
521 kind.descr(def_id.resolved_id())
522 ))?
523 }
524 };
525 Ok(rty::EarlyBinder(ty))
526}
527
528fn ty_param_owner(genv: GlobalEnv, def_id: DefId) -> DefId {
529 let def_kind = genv.def_kind(def_id);
530 match def_kind {
531 DefKind::Trait | DefKind::TraitAlias => def_id,
532 DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
533 genv.tcx().parent(def_id)
534 }
535 _ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind),
536 }
537}
538
539fn variants_of(
540 genv: GlobalEnv,
541 def_id: MaybeExternId,
542) -> QueryResult<rty::Opaqueness<rty::EarlyBinder<rty::PolyVariants>>> {
543 let local_id = def_id.local_id();
544
545 let item = &genv.fhir_expect_item(local_id)?;
546 let variants = match &item.kind {
547 fhir::ItemKind::Enum(enum_def) => {
548 let wfckresults = genv.check_wf(local_id)?;
549 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
550 let variants = cx.conv_enum_variants(def_id, enum_def)?;
551 let variants = rty::List::from_vec(struct_compat::variants(genv, &variants, def_id)?);
552 rty::Opaqueness::Transparent(rty::EarlyBinder(variants))
553 }
554 fhir::ItemKind::Struct(struct_def) => {
555 let wfckresults = genv.check_wf(local_id)?;
556 let mut cx = AfterSortck::new(genv, &wfckresults).into_conv_ctxt();
557 cx.conv_struct_variant(def_id, struct_def)?
558 .map(|variant| -> QueryResult<_> {
559 let variants = struct_compat::variants(genv, &[variant], def_id)?;
560 Ok(rty::List::from_vec(variants))
561 })
562 .transpose()?
563 .map(rty::EarlyBinder)
564 }
565 _ => Err(query_bug!(def_id.local_id(), "expected struct or enum"))?,
566 };
567 if config::dump_rty() {
568 dbg::dump_item_info(genv.tcx(), def_id.resolved_id(), "rty", &variants).unwrap();
569 }
570 Ok(variants)
571}
572
573fn fn_sig(genv: GlobalEnv, def_id: MaybeExternId) -> QueryResult<rty::EarlyBinder<rty::PolyFnSig>> {
574 match genv.fhir_node(def_id.local_id())? {
575 fhir::Node::Item(Item { kind: ItemKind::Fn(fhir_fn_sig, ..), .. })
576 | fhir::Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fhir_fn_sig), .. })
577 | fhir::Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fhir_fn_sig), .. })
578 | fhir::Node::ForeignItem(ForeignItem {
579 kind: ForeignItemKind::Fn(fhir_fn_sig, ..), ..
580 }) => {
581 let wfckresults = genv.check_wf(def_id.local_id())?;
582 let fn_sig = AfterSortck::new(genv, &wfckresults)
583 .into_conv_ctxt()
584 .conv_fn_sig(def_id, fhir_fn_sig)?;
585 let fn_sig = struct_compat::fn_sig(genv, fhir_fn_sig.decl, &fn_sig, def_id)?;
586 let fn_sig = fn_sig.hoist_input_binders();
587
588 if config::dump_rty() {
589 let generics = genv.generics_of(def_id)?;
590 let refinement_generics = genv.refinement_generics_of(def_id)?;
591 dbg::dump_item_info(
592 genv.tcx(),
593 def_id.resolved_id(),
594 "rty",
595 (generics, refinement_generics, &fn_sig),
596 )
597 .unwrap();
598 }
599 Ok(rty::EarlyBinder(fn_sig))
600 }
601 fhir::Node::Ctor => {
602 let tcx = genv.tcx();
603 let (adt_id, variant_idx) = match tcx.def_kind(def_id) {
604 DefKind::Ctor(CtorOf::Struct, _) => {
605 let struct_id = tcx.parent(def_id.resolved_id());
606 (struct_id, FIRST_VARIANT)
607 }
608 DefKind::Ctor(CtorOf::Variant, _) => {
609 let variant_id = tcx.parent(def_id.resolved_id());
610 let enum_id = tcx.parent(variant_id);
611 let variant_idx = tcx.adt_def(enum_id).variant_index_with_id(variant_id);
612 (enum_id, variant_idx)
613 }
614 _ => return Err(query_bug!("invalid `DefKind` for ctor node")),
615 };
616 genv.variant_sig(adt_id, variant_idx)?
617 .map(|sig| sig.to_poly_fn_sig(None))
618 .ok_or_query_err(adt_id)
619 }
620 node => Err(query_bug!("fn_sig called on unsupported node {node:?}")),
621 }
622}
623
624fn check_wf(genv: GlobalEnv, def_id: LocalDefId) -> QueryResult<Rc<WfckResults>> {
625 let node = genv.fhir_expect_owner_node(def_id)?;
626 let wfckresults = wf::check_node(genv, &node)?;
627 Ok(Rc::new(wfckresults))
628}
629
630mod errors {
631 use flux_errors::E0999;
632 use flux_macros::Diagnostic;
633 use flux_middle::def_id::FluxLocalDefId;
634 use rustc_span::Span;
635
636 #[derive(Diagnostic)]
637 #[diag(fhir_analysis_definition_cycle, code = E0999)]
638 pub struct DefinitionCycle {
639 #[primary_span]
640 #[label]
641 span: Span,
642 msg: String,
643 }
644
645 impl DefinitionCycle {
646 pub(super) fn new(span: Span, cycle: Vec<FluxLocalDefId>) -> Self {
647 let root = format!("`{}`", cycle[0].name());
648 let names: Vec<String> = cycle.iter().map(|s| format!("`{}`", s.name())).collect();
649 let msg = format!("{} -> {}", names.join(" -> "), root);
650 Self { span, msg }
651 }
652 }
653}