1#![feature(
4 rustc_private,
5 min_specialization,
6 box_patterns,
7 let_chains,
8 never_type,
9 unwrap_infallible
10)]
11
12extern crate rustc_data_structures;
13extern crate rustc_errors;
14
15extern crate rustc_hir;
16extern crate rustc_hir_pretty;
17extern crate rustc_middle;
18extern crate rustc_span;
19
20use desugar::RustItemCtxt;
21use flux_common::result::{ErrorCollector, ResultExt};
22use flux_macros::fluent_messages;
23use rustc_data_structures::unord::UnordMap;
24
25fluent_messages! { "../locales/en-US.ftl" }
26
27mod desugar;
28mod errors;
29pub mod resolver;
30
31use flux_middle::{
32 ResolverOutput, Specs,
33 def_id::FluxLocalDefId,
34 fhir,
35 global_env::GlobalEnv,
36 queries::{Providers, QueryErr, QueryResult},
37 query_bug,
38};
39use flux_syntax::surface;
40use rustc_errors::ErrorGuaranteed;
41use rustc_hir::{self as hir, OwnerId};
42use rustc_span::def_id::LocalDefId;
43
44type Result<T = ()> = std::result::Result<T, ErrorGuaranteed>;
45
46pub fn provide(providers: &mut Providers) {
47 providers.resolve_crate = resolver::resolve_crate;
48 providers.desugar = desugar;
49 providers.fhir_crate = desugar_crate;
50}
51
52pub fn desugar<'genv>(
53 genv: GlobalEnv<'genv, '_>,
54 def_id: LocalDefId,
55) -> QueryResult<UnordMap<LocalDefId, fhir::Node<'genv>>> {
56 if genv.ignored(def_id) {
57 return Err(QueryErr::Ignored { def_id: def_id.to_def_id() });
58 }
59
60 let cx = DesugarCtxt { genv, resolver_output: genv.resolve_crate() };
61 let specs = genv.collect_specs();
62 let owner_id = OwnerId { def_id };
63 let mut nodes = UnordMap::default();
64
65 match genv.tcx().hir_node_by_def_id(def_id) {
66 rustc_hir::Node::Item(item) => {
67 match item.kind {
68 hir::ItemKind::Fn { .. } => {
69 let fn_spec = specs.fn_sigs.get(&owner_id).unwrap();
70 let mut opaque_tys = Default::default();
71 let item = cx.with_rust_item_ctxt(owner_id, Some(&mut opaque_tys), |cx| {
72 cx.desugar_item_fn(fn_spec)
73 })?;
74 nodes.extend(opaque_tys.into_iter().map(|opaque_ty| {
75 (opaque_ty.def_id.local_id(), fhir::Node::OpaqueTy(opaque_ty))
76 }));
77 nodes.insert(def_id, fhir::Node::Item(genv.alloc(item)));
78 }
79 hir::ItemKind::TyAlias(..) => {
80 let ty_alias = specs.ty_aliases[&owner_id].as_ref();
81 nodes.insert(
82 def_id,
83 fhir::Node::Item(genv.alloc(cx.with_rust_item_ctxt(
84 owner_id,
85 None,
86 |cx| Ok(cx.desugar_type_alias(ty_alias)),
87 )?)),
88 );
89 }
90
91 hir::ItemKind::Enum(..) => {
92 let enum_def = &specs.enums[&owner_id];
93 nodes.insert(
94 def_id,
95 fhir::Node::Item(genv.alloc(cx.with_rust_item_ctxt(
96 owner_id,
97 None,
98 |cx| cx.desugar_enum_def(enum_def),
99 )?)),
100 );
101 }
102 hir::ItemKind::Union(..) => {
103 let union_def = &specs.structs[&owner_id];
104 nodes.insert(
105 def_id,
106 fhir::Node::Item(genv.alloc(cx.with_rust_item_ctxt(
107 owner_id,
108 None,
109 |cx| Ok(cx.desugar_struct_def(union_def)),
110 )?)),
111 );
112 }
113 hir::ItemKind::Struct(..) => {
114 let struct_def = &specs.structs[&owner_id];
115 nodes.insert(
116 def_id,
117 fhir::Node::Item(genv.alloc(cx.with_rust_item_ctxt(
118 owner_id,
119 None,
120 |cx| Ok(cx.desugar_struct_def(struct_def)),
121 )?)),
122 );
123 }
124 hir::ItemKind::Trait(..) => {
125 let trait_ = &specs.traits[&owner_id];
126 nodes.insert(
127 def_id,
128 fhir::Node::Item(genv.alloc(cx.with_rust_item_ctxt(
129 owner_id,
130 None,
131 |cx| cx.desugar_trait(trait_),
132 )?)),
133 );
134 }
135 hir::ItemKind::Impl(..) => {
136 let impl_ = &specs.impls[&owner_id];
137 nodes.insert(
138 def_id,
139 fhir::Node::Item(genv.alloc(cx.with_rust_item_ctxt(
140 owner_id,
141 None,
142 |cx| Ok(cx.desugar_impl(impl_)),
143 )?)),
144 );
145 }
146 hir::ItemKind::Const(..) => {
147 let constant_ = match specs.constants.get(&owner_id) {
148 Some(constant_) => constant_,
149 None => &surface::ConstantInfo { expr: None },
150 };
151
152 nodes.insert(
153 def_id,
154 fhir::Node::Item(genv.alloc(cx.with_rust_item_ctxt(
155 owner_id,
156 None,
157 |cx| Ok(cx.desugar_const(constant_)),
158 )?)),
159 );
160 }
161 _ => Err(query_bug!(def_id, "unsupported item"))?,
162 }
163 }
164 rustc_hir::Node::TraitItem(trait_item) => {
165 match trait_item.kind {
166 rustc_hir::TraitItemKind::Fn(..) => {
167 let fn_spec = specs.fn_sigs.get(&owner_id).unwrap();
168 let mut opaque_tys = Default::default();
169 let item = cx.with_rust_item_ctxt(owner_id, Some(&mut opaque_tys), |cx| {
170 cx.desugar_trait_fn(fn_spec)
171 })?;
172 nodes.extend(opaque_tys.into_iter().map(|opaque_ty| {
173 (opaque_ty.def_id.local_id(), fhir::Node::OpaqueTy(opaque_ty))
174 }));
175 nodes.insert(def_id, fhir::Node::TraitItem(genv.alloc(item)));
176 }
177 rustc_hir::TraitItemKind::Type(..) => {
178 let item = cx.with_rust_item_ctxt(owner_id, None, |cx| {
179 Ok(cx.desugar_trait_assoc_ty())
180 })?;
181 nodes.insert(owner_id.def_id, fhir::Node::TraitItem(genv.alloc(item)));
182 }
183 rustc_hir::TraitItemKind::Const(..) => {
184 nodes.insert(
185 def_id,
186 fhir::Node::TraitItem(genv.alloc(cx.with_rust_item_ctxt(
187 owner_id,
188 None,
189 |cx| Ok(cx.desugar_trait_const()),
190 )?)),
191 );
192 }
193 }
194 }
195 rustc_hir::Node::ImplItem(impl_item) => {
196 match &impl_item.kind {
197 rustc_hir::ImplItemKind::Fn(..) => {
198 let fn_spec = specs.fn_sigs.get(&owner_id).unwrap();
199 let mut opaque_tys = Default::default();
200 let item = cx.with_rust_item_ctxt(owner_id, Some(&mut opaque_tys), |cx| {
201 cx.desugar_impl_fn(fn_spec)
202 })?;
203 nodes.extend(opaque_tys.into_iter().map(|opaque_ty| {
204 (opaque_ty.def_id.local_id(), fhir::Node::OpaqueTy(opaque_ty))
205 }));
206 nodes.insert(def_id, fhir::Node::ImplItem(genv.alloc(item)));
207 }
208 rustc_hir::ImplItemKind::Type(..) => {
209 let item = cx
210 .with_rust_item_ctxt(owner_id, None, |cx| Ok(cx.desugar_impl_assoc_ty()))?;
211 nodes.insert(owner_id.def_id, fhir::Node::ImplItem(genv.alloc(item)));
212 }
213 rustc_hir::ImplItemKind::Const(..) => {
214 nodes.insert(
215 def_id,
216 fhir::Node::ImplItem(genv.alloc(cx.with_rust_item_ctxt(
217 owner_id,
218 None,
219 |cx| Ok(cx.desugar_impl_const()),
220 )?)),
221 );
222 }
223 }
224 }
225 rustc_hir::Node::AnonConst(..) => {
226 nodes.insert(def_id, fhir::Node::AnonConst);
227 }
228 rustc_hir::Node::Expr(..) => {
229 nodes.insert(def_id, fhir::Node::Expr);
230 }
231 rustc_hir::Node::ForeignItem(foreign) => {
232 let foreign_item = fhir::Node::ForeignItem(genv.alloc(cx.with_rust_item_ctxt(
233 owner_id,
234 None,
235 |cx| cx.desugar_foreign_item(*foreign),
236 )?));
237 nodes.insert(def_id, foreign_item);
238 }
239 rustc_hir::Node::Ctor(rustc_hir::VariantData::Tuple(_, _, _)) => {
240 nodes.insert(def_id, fhir::Node::Ctor);
241 }
242 node => {
243 if let Some(ident) = node.ident() {
244 Err(query_bug!(def_id, "unsupported item {ident:?}"))?;
245 } else {
246 Err(query_bug!(def_id, "unsupported item"))?;
247 }
248 }
249 }
250 Ok(nodes)
251}
252
253struct DesugarCtxt<'genv, 'tcx> {
254 genv: GlobalEnv<'genv, 'tcx>,
255 resolver_output: &'genv ResolverOutput,
256}
257
258impl<'genv, 'tcx> DesugarCtxt<'genv, 'tcx> {
259 fn with_rust_item_ctxt<'a, T>(
260 &'a self,
261 owner_id: OwnerId,
262 opaque_tys: Option<&'a mut Vec<&'genv fhir::OpaqueTy<'genv>>>,
263 f: impl FnOnce(&mut RustItemCtxt<'a, 'genv, 'tcx>) -> Result<T>,
264 ) -> Result<T> {
265 let owner_id = self
266 .genv
267 .maybe_extern_id(owner_id.def_id)
268 .map(|def_id| OwnerId { def_id });
269 RustItemCtxt::with(self.genv, owner_id, self.resolver_output, opaque_tys, f)
270 }
271}
272
273fn desugar_crate<'genv>(genv: GlobalEnv<'genv, '_>) -> fhir::FluxItems<'genv> {
274 match try_desugar_crate(genv) {
275 Ok(fhir) => fhir,
276 Err(err) => {
277 genv.sess().abort(err);
282 }
283 }
284}
285
286fn try_desugar_crate<'genv>(genv: GlobalEnv<'genv, '_>) -> Result<fhir::FluxItems<'genv>> {
287 let specs = genv.collect_specs();
288 let fhir = fhir::FluxItems::new();
289 let resolver_output = genv.resolve_crate();
290 let mut cx = CrateDesugar::new(genv, fhir, resolver_output);
291 cx.desugar_flux_items(specs);
292
293 cx.err.into_result()?;
294 Ok(cx.fhir)
295}
296
297struct CrateDesugar<'genv, 'tcx> {
298 genv: GlobalEnv<'genv, 'tcx>,
299 fhir: fhir::FluxItems<'genv>,
300 resolver_output: &'genv ResolverOutput,
301 err: Option<ErrorGuaranteed>,
302}
303
304impl<'genv, 'tcx> CrateDesugar<'genv, 'tcx> {
305 fn new(
306 genv: GlobalEnv<'genv, 'tcx>,
307 fhir: fhir::FluxItems<'genv>,
308 resolver_output: &'genv ResolverOutput,
309 ) -> Self {
310 Self { genv, fhir, resolver_output, err: None }
311 }
312}
313
314impl CrateDesugar<'_, '_> {
315 #[allow(clippy::disallowed_methods, reason = "`flux_items_by_parent` is the source of truth")]
316 fn desugar_flux_items(&mut self, specs: &Specs) {
317 for (parent, items) in &specs.flux_items_by_parent {
318 for item in items {
319 let def_id = FluxLocalDefId::new(parent.def_id, item.name().name);
320 match item {
321 surface::Item::Qualifier(qual) => {
322 self.desugar_qualifier(def_id, qual)
323 .collect_err(&mut self.err);
324 }
325 surface::Item::FuncDef(defn) => {
326 self.desugar_func_defn(def_id, defn)
327 .collect_err(&mut self.err);
328 }
329 surface::Item::SortDecl(_) => {}
330 surface::Item::PrimProp(prim_prop) => {
331 self.desugar_prim_prop(def_id, prim_prop)
332 .collect_err(&mut self.err);
333 }
334 }
335 }
336 }
337 }
338
339 fn desugar_prim_prop(&mut self, def_id: FluxLocalDefId, prop: &surface::PrimOpProp) -> Result {
340 let prop = desugar::desugar_prim_prop(self.genv, self.resolver_output, def_id, prop)?;
341 self.fhir
342 .items
343 .insert(def_id, fhir::FluxItem::PrimProp(self.genv.alloc(prop)));
344 Ok(())
345 }
346
347 fn desugar_func_defn(&mut self, def_id: FluxLocalDefId, func: &surface::SpecFunc) -> Result {
348 let func = desugar::desugar_spec_func(self.genv, self.resolver_output, def_id, func)?;
349 self.fhir
350 .items
351 .insert(def_id, fhir::FluxItem::Func(self.genv.alloc(func)));
352 Ok(())
353 }
354
355 fn desugar_qualifier(
356 &mut self,
357 def_id: FluxLocalDefId,
358 qualifier: &surface::Qualifier,
359 ) -> Result {
360 let qualifier =
361 desugar::desugar_qualifier(self.genv, self.resolver_output, def_id, qualifier)?;
362 self.fhir
363 .items
364 .insert(def_id, fhir::FluxItem::Qualifier(self.genv.alloc(qualifier)));
365 Ok(())
366 }
367}