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