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