1use rustc_abi::ExternAbi;
2use rustc_ast::ptr::P;
3use rustc_ast::visit::AssocCtxt;
4use rustc_ast::*;
5use rustc_errors::ErrorGuaranteed;
6use rustc_hir as hir;
7use rustc_hir::PredicateOrigin;
8use rustc_hir::def::{DefKind, Res};
9use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
10use rustc_index::{IndexSlice, IndexVec};
11use rustc_middle::span_bug;
12use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
13use rustc_span::edit_distance::find_best_match_for_name;
14use rustc_span::{DesugaringKind, Ident, Span, Symbol, kw, sym};
15use smallvec::{SmallVec, smallvec};
16use thin_vec::ThinVec;
17use tracing::instrument;
18
19use super::errors::{
20 InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault,
21};
22use super::stability::{enabled_names, gate_unstable_abi};
23use super::{
24 AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
25 ResolverAstLoweringExt,
26};
27
28pub(super) struct ItemLowerer<'a, 'hir> {
29 pub(super) tcx: TyCtxt<'hir>,
30 pub(super) resolver: &'a mut ResolverAstLowering,
31 pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
32 pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<'hir>>,
33}
34
35fn add_ty_alias_where_clause(
39 generics: &mut ast::Generics,
40 mut where_clauses: TyAliasWhereClauses,
41 prefer_first: bool,
42) {
43 if !prefer_first {
44 (where_clauses.before, where_clauses.after) = (where_clauses.after, where_clauses.before);
45 }
46 let where_clause =
47 if where_clauses.before.has_where_token || !where_clauses.after.has_where_token {
48 where_clauses.before
49 } else {
50 where_clauses.after
51 };
52 generics.where_clause.has_where_token = where_clause.has_where_token;
53 generics.where_clause.span = where_clause.span;
54}
55
56impl<'a, 'hir> ItemLowerer<'a, 'hir> {
57 fn with_lctx(
58 &mut self,
59 owner: NodeId,
60 f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
61 ) {
62 let mut lctx = LoweringContext::new(self.tcx, self.resolver);
63 lctx.with_hir_id_owner(owner, |lctx| f(lctx));
64
65 for (def_id, info) in lctx.children {
66 let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
67 debug_assert!(
68 matches!(owner, hir::MaybeOwner::Phantom),
69 "duplicate copy of {def_id:?} in lctx.children"
70 );
71 *owner = info;
72 }
73 }
74
75 pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> {
76 let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
77 if let hir::MaybeOwner::Phantom = owner {
78 let node = self.ast_index[def_id];
79 match node {
80 AstOwner::NonOwner => {}
81 AstOwner::Crate(c) => self.lower_crate(c),
82 AstOwner::Item(item) => self.lower_item(item),
83 AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt),
84 AstOwner::ForeignItem(item) => self.lower_foreign_item(item),
85 }
86 }
87
88 self.owners[def_id]
89 }
90
91 #[instrument(level = "debug", skip(self, c))]
92 fn lower_crate(&mut self, c: &Crate) {
93 debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
94 self.with_lctx(CRATE_NODE_ID, |lctx| {
95 let module = lctx.lower_mod(&c.items, &c.spans);
96 lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
97 hir::OwnerNode::Crate(module)
98 })
99 }
100
101 #[instrument(level = "debug", skip(self))]
102 fn lower_item(&mut self, item: &Item) {
103 self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
104 }
105
106 fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
107 let def_id = self.resolver.node_id_to_def_id[&item.id];
108 let parent_id = self.tcx.local_parent(def_id);
109 let parent_hir = self.lower_node(parent_id).unwrap();
110 self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt, parent_hir))
111 }
112
113 fn lower_foreign_item(&mut self, item: &ForeignItem) {
114 self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
115 }
116}
117
118impl<'hir> LoweringContext<'_, 'hir> {
119 pub(super) fn lower_mod(
120 &mut self,
121 items: &[P<Item>],
122 spans: &ModSpans,
123 ) -> &'hir hir::Mod<'hir> {
124 self.arena.alloc(hir::Mod {
125 spans: hir::ModSpans {
126 inner_span: self.lower_span(spans.inner_span),
127 inject_use_span: self.lower_span(spans.inject_use_span),
128 },
129 item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
130 })
131 }
132
133 pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
134 let mut node_ids =
135 smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
136 if let ItemKind::Use(use_tree) = &i.kind {
137 self.lower_item_id_use_tree(use_tree, &mut node_ids);
138 }
139 node_ids
140 }
141
142 fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) {
143 match &tree.kind {
144 UseTreeKind::Nested { items, .. } => {
145 for &(ref nested, id) in items {
146 vec.push(hir::ItemId {
147 owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
148 });
149 self.lower_item_id_use_tree(nested, vec);
150 }
151 }
152 UseTreeKind::Simple(..) | UseTreeKind::Glob => {}
153 }
154 }
155
156 fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
157 let mut ident = i.ident;
158 let vis_span = self.lower_span(i.vis.span);
159 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
160 let attrs = self.lower_attrs(hir_id, &i.attrs);
161 let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
162 let item = hir::Item {
163 owner_id: hir_id.expect_owner(),
164 ident: self.lower_ident(ident),
165 kind,
166 vis_span,
167 span: self.lower_span(i.span),
168 };
169 self.arena.alloc(item)
170 }
171
172 fn lower_item_kind(
173 &mut self,
174 span: Span,
175 id: NodeId,
176 hir_id: hir::HirId,
177 ident: &mut Ident,
178 attrs: &'hir [hir::Attribute],
179 vis_span: Span,
180 i: &ItemKind,
181 ) -> hir::ItemKind<'hir> {
182 match i {
183 ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name),
184 ItemKind::Use(use_tree) => {
185 let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
187
188 self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs)
189 }
190 ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => {
191 let (ty, body_id) =
192 self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
193 hir::ItemKind::Static(ty, *m, body_id)
194 }
195 ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
196 let (generics, (ty, body_id)) = self.lower_generics(
197 generics,
198 id,
199 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
200 |this| {
201 this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
202 },
203 );
204 hir::ItemKind::Const(ty, generics, body_id)
205 }
206 ItemKind::Fn(box Fn {
207 sig: FnSig { decl, header, span: fn_sig_span },
208 generics,
209 body,
210 contract,
211 ..
212 }) => {
213 self.with_new_scopes(*fn_sig_span, |this| {
214 let coroutine_kind = header.coroutine_kind;
219 let body_id = this.lower_maybe_coroutine_body(
220 *fn_sig_span,
221 span,
222 hir_id,
223 decl,
224 coroutine_kind,
225 body.as_deref(),
226 attrs,
227 contract.as_deref(),
228 );
229
230 let itctx = ImplTraitContext::Universal;
231 let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
232 this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coroutine_kind)
233 });
234 let sig = hir::FnSig {
235 decl,
236 header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
237 span: this.lower_span(*fn_sig_span),
238 };
239 hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
240 })
241 }
242 ItemKind::Mod(_, mod_kind) => match mod_kind {
243 ModKind::Loaded(items, _, spans, _) => {
244 hir::ItemKind::Mod(self.lower_mod(items, spans))
245 }
246 ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
247 },
248 ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {
249 abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
250 items: self
251 .arena
252 .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
253 },
254 ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
255 ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
256 let mut generics = generics.clone();
265 add_ty_alias_where_clause(&mut generics, *where_clauses, true);
266 let (generics, ty) = self.lower_generics(
267 &generics,
268 id,
269 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
270 |this| match ty {
271 None => {
272 let guar = this.dcx().span_delayed_bug(
273 span,
274 "expected to lower type alias type, but it was missing",
275 );
276 this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
277 }
278 Some(ty) => this.lower_ty(
279 ty,
280 ImplTraitContext::OpaqueTy {
281 origin: hir::OpaqueTyOrigin::TyAlias {
282 parent: this.local_def_id(id),
283 in_assoc_ty: false,
284 },
285 },
286 ),
287 },
288 );
289 hir::ItemKind::TyAlias(ty, generics)
290 }
291 ItemKind::Enum(enum_definition, generics) => {
292 let (generics, variants) = self.lower_generics(
293 generics,
294 id,
295 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
296 |this| {
297 this.arena.alloc_from_iter(
298 enum_definition.variants.iter().map(|x| this.lower_variant(x)),
299 )
300 },
301 );
302 hir::ItemKind::Enum(hir::EnumDef { variants }, generics)
303 }
304 ItemKind::Struct(struct_def, generics) => {
305 let (generics, struct_def) = self.lower_generics(
306 generics,
307 id,
308 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
309 |this| this.lower_variant_data(hir_id, struct_def),
310 );
311 hir::ItemKind::Struct(struct_def, generics)
312 }
313 ItemKind::Union(vdata, generics) => {
314 let (generics, vdata) = self.lower_generics(
315 generics,
316 id,
317 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
318 |this| this.lower_variant_data(hir_id, vdata),
319 );
320 hir::ItemKind::Union(vdata, generics)
321 }
322 ItemKind::Impl(box Impl {
323 safety,
324 polarity,
325 defaultness,
326 constness,
327 generics: ast_generics,
328 of_trait: trait_ref,
329 self_ty: ty,
330 items: impl_items,
331 }) => {
332 let itctx = ImplTraitContext::Universal;
346 let (generics, (trait_ref, lowered_ty)) =
347 self.lower_generics(ast_generics, id, itctx, |this| {
348 let modifiers = TraitBoundModifiers {
349 constness: BoundConstness::Never,
350 asyncness: BoundAsyncness::Normal,
351 polarity: BoundPolarity::Positive,
353 };
354
355 let trait_ref = trait_ref.as_ref().map(|trait_ref| {
356 this.lower_trait_ref(
357 modifiers,
358 trait_ref,
359 ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
360 )
361 });
362
363 let lowered_ty = this.lower_ty(
364 ty,
365 ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
366 );
367
368 (trait_ref, lowered_ty)
369 });
370
371 self.is_in_trait_impl = trait_ref.is_some();
372 let new_impl_items = self
373 .arena
374 .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
375
376 let has_val = true;
379 let (defaultness, defaultness_span) = self.lower_defaultness(*defaultness, has_val);
380 let polarity = match polarity {
381 ImplPolarity::Positive => ImplPolarity::Positive,
382 ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
383 };
384 hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
385 constness: self.lower_constness(*constness),
386 safety: self.lower_safety(*safety, hir::Safety::Safe),
387 polarity,
388 defaultness,
389 defaultness_span,
390 generics,
391 of_trait: trait_ref,
392 self_ty: lowered_ty,
393 items: new_impl_items,
394 }))
395 }
396 ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
397 let (generics, (safety, items, bounds)) = self.lower_generics(
398 generics,
399 id,
400 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
401 |this| {
402 let bounds = this.lower_param_bounds(
403 bounds,
404 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
405 );
406 let items = this.arena.alloc_from_iter(
407 items.iter().map(|item| this.lower_trait_item_ref(item)),
408 );
409 let safety = this.lower_safety(*safety, hir::Safety::Safe);
410 (safety, items, bounds)
411 },
412 );
413 hir::ItemKind::Trait(*is_auto, safety, generics, bounds, items)
414 }
415 ItemKind::TraitAlias(generics, bounds) => {
416 let (generics, bounds) = self.lower_generics(
417 generics,
418 id,
419 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
420 |this| {
421 this.lower_param_bounds(
422 bounds,
423 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
424 )
425 },
426 );
427 hir::ItemKind::TraitAlias(generics, bounds)
428 }
429 ItemKind::MacroDef(MacroDef { body, macro_rules }) => {
430 let body = P(self.lower_delim_args(body));
431 let def_id = self.local_def_id(id);
432 let def_kind = self.tcx.def_kind(def_id);
433 let DefKind::Macro(macro_kind) = def_kind else {
434 unreachable!(
435 "expected DefKind::Macro for macro item, found {}",
436 def_kind.descr(def_id.to_def_id())
437 );
438 };
439 let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
440 hir::ItemKind::Macro(macro_def, macro_kind)
441 }
442 ItemKind::Delegation(box delegation) => {
443 let delegation_results = self.lower_delegation(delegation, id);
444 hir::ItemKind::Fn {
445 sig: delegation_results.sig,
446 generics: delegation_results.generics,
447 body: delegation_results.body_id,
448 has_body: true,
449 }
450 }
451 ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
452 panic!("macros should have been expanded by now")
453 }
454 }
455 }
456
457 fn lower_const_item(
458 &mut self,
459 ty: &Ty,
460 span: Span,
461 body: Option<&Expr>,
462 impl_trait_position: ImplTraitPosition,
463 ) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
464 let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position));
465 (ty, self.lower_const_body(span, body))
466 }
467
468 #[instrument(level = "debug", skip(self))]
469 fn lower_use_tree(
470 &mut self,
471 tree: &UseTree,
472 prefix: &Path,
473 id: NodeId,
474 vis_span: Span,
475 ident: &mut Ident,
476 attrs: &'hir [hir::Attribute],
477 ) -> hir::ItemKind<'hir> {
478 let path = &tree.prefix;
479 let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
480
481 match tree.kind {
482 UseTreeKind::Simple(rename) => {
483 *ident = tree.ident();
484
485 let mut path = Path { segments, span: path.span, tokens: None };
487
488 if path.segments.len() > 1
490 && path.segments.last().unwrap().ident.name == kw::SelfLower
491 {
492 let _ = path.segments.pop();
493 if rename.is_none() {
494 *ident = path.segments.last().unwrap().ident;
495 }
496 }
497
498 let res = self.lower_import_res(id, path.span);
499 let path = self.lower_use_path(res, &path, ParamMode::Explicit);
500 hir::ItemKind::Use(path, hir::UseKind::Single)
501 }
502 UseTreeKind::Glob => {
503 let res = self.expect_full_res(id);
504 let res = smallvec![self.lower_res(res)];
505 let path = Path { segments, span: path.span, tokens: None };
506 let path = self.lower_use_path(res, &path, ParamMode::Explicit);
507 hir::ItemKind::Use(path, hir::UseKind::Glob)
508 }
509 UseTreeKind::Nested { items: ref trees, .. } => {
510 let span = prefix.span.to(path.span);
535 let prefix = Path { segments, span, tokens: None };
536
537 for &(ref use_tree, id) in trees {
539 let new_hir_id = self.local_def_id(id);
540
541 self.with_hir_id_owner(id, |this| {
547 let mut ident = *ident;
548
549 let kind =
553 this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
554 if !attrs.is_empty() {
555 this.attrs.insert(hir::ItemLocalId::ZERO, attrs);
556 }
557
558 let item = hir::Item {
559 owner_id: hir::OwnerId { def_id: new_hir_id },
560 ident: this.lower_ident(ident),
561 kind,
562 vis_span,
563 span: this.lower_span(use_tree.span),
564 };
565 hir::OwnerNode::Item(this.arena.alloc(item))
566 });
567 }
568
569 let path = if trees.is_empty()
571 && !(prefix.segments.is_empty()
572 || prefix.segments.len() == 1
573 && prefix.segments[0].ident.name == kw::PathRoot)
574 {
575 let res = self.lower_import_res(id, span);
578 self.lower_use_path(res, &prefix, ParamMode::Explicit)
579 } else {
580 self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span })
583 };
584 hir::ItemKind::Use(path, hir::UseKind::ListStem)
585 }
586 }
587 }
588
589 fn lower_assoc_item(
590 &mut self,
591 item: &AssocItem,
592 ctxt: AssocCtxt,
593 parent_hir: &'hir hir::OwnerInfo<'hir>,
594 ) -> hir::OwnerNode<'hir> {
595 let parent_item = parent_hir.node().expect_item();
596 match parent_item.kind {
597 hir::ItemKind::Impl(impl_) => {
598 self.is_in_trait_impl = impl_.of_trait.is_some();
599 }
600 hir::ItemKind::Trait(_, _, _, _, _) => {}
601 kind => {
602 span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
603 }
604 }
605
606 match ctxt {
610 AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
611 AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
612 }
613 }
614
615 fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
616 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
617 let owner_id = hir_id.expect_owner();
618 let attrs = self.lower_attrs(hir_id, &i.attrs);
619 let item = hir::ForeignItem {
620 owner_id,
621 ident: self.lower_ident(i.ident),
622 kind: match &i.kind {
623 ForeignItemKind::Fn(box Fn { sig, generics, .. }) => {
624 let fdec = &sig.decl;
625 let itctx = ImplTraitContext::Universal;
626 let (generics, (decl, fn_args)) =
627 self.lower_generics(generics, i.id, itctx, |this| {
628 (
629 this.lower_fn_decl(
631 fdec,
632 i.id,
633 sig.span,
634 FnDeclKind::ExternFn,
635 None,
636 ),
637 this.lower_fn_params_to_names(fdec),
638 )
639 });
640
641 let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
643
644 hir::ForeignItemKind::Fn(
645 hir::FnSig { header, decl, span: self.lower_span(sig.span) },
646 fn_args,
647 generics,
648 )
649 }
650 ForeignItemKind::Static(box StaticItem { ty, mutability, expr: _, safety }) => {
651 let ty = self
652 .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
653 let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
654
655 hir::ForeignItemKind::Static(ty, *mutability, safety)
656 }
657 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
658 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
659 },
660 vis_span: self.lower_span(i.vis.span),
661 span: self.lower_span(i.span),
662 };
663 self.arena.alloc(item)
664 }
665
666 fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
667 hir::ForeignItemRef {
668 id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
669 ident: self.lower_ident(i.ident),
670 span: self.lower_span(i.span),
671 }
672 }
673
674 fn lower_variant(&mut self, v: &Variant) -> hir::Variant<'hir> {
675 let hir_id = self.lower_node_id(v.id);
676 self.lower_attrs(hir_id, &v.attrs);
677 hir::Variant {
678 hir_id,
679 def_id: self.local_def_id(v.id),
680 data: self.lower_variant_data(hir_id, &v.data),
681 disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)),
682 ident: self.lower_ident(v.ident),
683 span: self.lower_span(v.span),
684 }
685 }
686
687 fn lower_variant_data(
688 &mut self,
689 parent_id: hir::HirId,
690 vdata: &VariantData,
691 ) -> hir::VariantData<'hir> {
692 match vdata {
693 VariantData::Struct { fields, recovered } => hir::VariantData::Struct {
694 fields: self
695 .arena
696 .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))),
697 recovered: *recovered,
698 },
699 VariantData::Tuple(fields, id) => {
700 let ctor_id = self.lower_node_id(*id);
701 self.alias_attrs(ctor_id, parent_id);
702 let fields = self
703 .arena
704 .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f)));
705 for field in &fields[..] {
706 if let Some(default) = field.default {
707 if self.tcx.features().default_field_values() {
712 self.dcx().emit_err(TupleStructWithDefault { span: default.span });
713 } else {
714 let _ = self.dcx().span_delayed_bug(
715 default.span,
716 "expected `default values on `struct` fields aren't supported` \
717 feature-gate error but none was produced",
718 );
719 }
720 }
721 }
722 hir::VariantData::Tuple(fields, ctor_id, self.local_def_id(*id))
723 }
724 VariantData::Unit(id) => {
725 let ctor_id = self.lower_node_id(*id);
726 self.alias_attrs(ctor_id, parent_id);
727 hir::VariantData::Unit(ctor_id, self.local_def_id(*id))
728 }
729 }
730 }
731
732 pub(super) fn lower_field_def(
733 &mut self,
734 (index, f): (usize, &FieldDef),
735 ) -> hir::FieldDef<'hir> {
736 let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy));
737 let hir_id = self.lower_node_id(f.id);
738 self.lower_attrs(hir_id, &f.attrs);
739 hir::FieldDef {
740 span: self.lower_span(f.span),
741 hir_id,
742 def_id: self.local_def_id(f.id),
743 ident: match f.ident {
744 Some(ident) => self.lower_ident(ident),
745 None => Ident::new(sym::integer(index), self.lower_span(f.span)),
747 },
748 vis_span: self.lower_span(f.vis.span),
749 default: f.default.as_ref().map(|v| self.lower_anon_const_to_anon_const(v)),
750 ty,
751 safety: self.lower_safety(f.safety, hir::Safety::Safe),
752 }
753 }
754
755 fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
756 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
757 let attrs = self.lower_attrs(hir_id, &i.attrs);
758 let trait_item_def_id = hir_id.expect_owner();
759
760 let (generics, kind, has_default) = match &i.kind {
761 AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
762 let (generics, kind) = self.lower_generics(
763 generics,
764 i.id,
765 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
766 |this| {
767 let ty = this
768 .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
769 let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
770
771 hir::TraitItemKind::Const(ty, body)
772 },
773 );
774 (generics, kind, expr.is_some())
775 }
776 AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
777 let names = self.lower_fn_params_to_names(&sig.decl);
780 let (generics, sig) = self.lower_method_sig(
781 generics,
782 sig,
783 i.id,
784 FnDeclKind::Trait,
785 sig.header.coroutine_kind,
786 attrs,
787 );
788 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
789 }
790 AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), contract, .. }) => {
791 let body_id = self.lower_maybe_coroutine_body(
792 sig.span,
793 i.span,
794 hir_id,
795 &sig.decl,
796 sig.header.coroutine_kind,
797 Some(body),
798 attrs,
799 contract.as_deref(),
800 );
801 let (generics, sig) = self.lower_method_sig(
802 generics,
803 sig,
804 i.id,
805 FnDeclKind::Trait,
806 sig.header.coroutine_kind,
807 attrs,
808 );
809 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
810 }
811 AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
812 let mut generics = generics.clone();
813 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
814 let (generics, kind) = self.lower_generics(
815 &generics,
816 i.id,
817 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
818 |this| {
819 let ty = ty.as_ref().map(|x| {
820 this.lower_ty(
821 x,
822 ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
823 )
824 });
825 hir::TraitItemKind::Type(
826 this.lower_param_bounds(
827 bounds,
828 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
829 ),
830 ty,
831 )
832 },
833 );
834 (generics, kind, ty.is_some())
835 }
836 AssocItemKind::Delegation(box delegation) => {
837 let delegation_results = self.lower_delegation(delegation, i.id);
838 let item_kind = hir::TraitItemKind::Fn(
839 delegation_results.sig,
840 hir::TraitFn::Provided(delegation_results.body_id),
841 );
842 (delegation_results.generics, item_kind, true)
843 }
844 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
845 panic!("macros should have been expanded by now")
846 }
847 };
848
849 let item = hir::TraitItem {
850 owner_id: trait_item_def_id,
851 ident: self.lower_ident(i.ident),
852 generics,
853 kind,
854 span: self.lower_span(i.span),
855 defaultness: hir::Defaultness::Default { has_value: has_default },
856 };
857 self.arena.alloc(item)
858 }
859
860 fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
861 let kind = match &i.kind {
862 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
863 AssocItemKind::Type(..) => hir::AssocItemKind::Type,
864 AssocItemKind::Fn(box Fn { sig, .. }) => {
865 hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
866 }
867 AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
868 has_self: self.delegation_has_self(i.id, delegation.id, i.span),
869 },
870 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
871 panic!("macros should have been expanded by now")
872 }
873 };
874 let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
875 hir::TraitItemRef {
876 id,
877 ident: self.lower_ident(i.ident),
878 span: self.lower_span(i.span),
879 kind,
880 }
881 }
882
883 pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {
885 self.expr(span, hir::ExprKind::Err(guar))
886 }
887
888 fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
889 let has_value = true;
891 let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
892 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
893 let attrs = self.lower_attrs(hir_id, &i.attrs);
894
895 let (generics, kind) = match &i.kind {
896 AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
897 generics,
898 i.id,
899 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
900 |this| {
901 let ty =
902 this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
903 let body = this.lower_const_body(i.span, expr.as_deref());
904
905 hir::ImplItemKind::Const(ty, body)
906 },
907 ),
908 AssocItemKind::Fn(box Fn { sig, generics, body, contract, .. }) => {
909 let body_id = self.lower_maybe_coroutine_body(
910 sig.span,
911 i.span,
912 hir_id,
913 &sig.decl,
914 sig.header.coroutine_kind,
915 body.as_deref(),
916 attrs,
917 contract.as_deref(),
918 );
919 let (generics, sig) = self.lower_method_sig(
920 generics,
921 sig,
922 i.id,
923 if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
924 sig.header.coroutine_kind,
925 attrs,
926 );
927
928 (generics, hir::ImplItemKind::Fn(sig, body_id))
929 }
930 AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
931 let mut generics = generics.clone();
932 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
933 self.lower_generics(
934 &generics,
935 i.id,
936 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
937 |this| match ty {
938 None => {
939 let guar = this.dcx().span_delayed_bug(
940 i.span,
941 "expected to lower associated type, but it was missing",
942 );
943 let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
944 hir::ImplItemKind::Type(ty)
945 }
946 Some(ty) => {
947 let ty = this.lower_ty(
948 ty,
949 ImplTraitContext::OpaqueTy {
950 origin: hir::OpaqueTyOrigin::TyAlias {
951 parent: this.local_def_id(i.id),
952 in_assoc_ty: true,
953 },
954 },
955 );
956 hir::ImplItemKind::Type(ty)
957 }
958 },
959 )
960 }
961 AssocItemKind::Delegation(box delegation) => {
962 let delegation_results = self.lower_delegation(delegation, i.id);
963 (
964 delegation_results.generics,
965 hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
966 )
967 }
968 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
969 panic!("macros should have been expanded by now")
970 }
971 };
972
973 let item = hir::ImplItem {
974 owner_id: hir_id.expect_owner(),
975 ident: self.lower_ident(i.ident),
976 generics,
977 kind,
978 vis_span: self.lower_span(i.vis.span),
979 span: self.lower_span(i.span),
980 defaultness,
981 };
982 self.arena.alloc(item)
983 }
984
985 fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
986 hir::ImplItemRef {
987 id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
988 ident: self.lower_ident(i.ident),
989 span: self.lower_span(i.span),
990 kind: match &i.kind {
991 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
992 AssocItemKind::Type(..) => hir::AssocItemKind::Type,
993 AssocItemKind::Fn(box Fn { sig, .. }) => {
994 hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
995 }
996 AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn {
997 has_self: self.delegation_has_self(i.id, delegation.id, i.span),
998 },
999 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
1000 panic!("macros should have been expanded by now")
1001 }
1002 },
1003 trait_item_def_id: self
1004 .resolver
1005 .get_partial_res(i.id)
1006 .map(|r| r.expect_full_res().opt_def_id())
1007 .unwrap_or(None),
1008 }
1009 }
1010
1011 fn lower_defaultness(
1012 &self,
1013 d: Defaultness,
1014 has_value: bool,
1015 ) -> (hir::Defaultness, Option<Span>) {
1016 match d {
1017 Defaultness::Default(sp) => {
1018 (hir::Defaultness::Default { has_value }, Some(self.lower_span(sp)))
1019 }
1020 Defaultness::Final => {
1021 assert!(has_value);
1022 (hir::Defaultness::Final, None)
1023 }
1024 }
1025 }
1026
1027 fn record_body(
1028 &mut self,
1029 params: &'hir [hir::Param<'hir>],
1030 value: hir::Expr<'hir>,
1031 ) -> hir::BodyId {
1032 let body = hir::Body { params, value: self.arena.alloc(value) };
1033 let id = body.id();
1034 debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
1035 self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
1036 id
1037 }
1038
1039 pub(super) fn lower_body(
1040 &mut self,
1041 f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
1042 ) -> hir::BodyId {
1043 let prev_coroutine_kind = self.coroutine_kind.take();
1044 let task_context = self.task_context.take();
1045 let (parameters, result) = f(self);
1046 let body_id = self.record_body(parameters, result);
1047 self.task_context = task_context;
1048 self.coroutine_kind = prev_coroutine_kind;
1049 body_id
1050 }
1051
1052 fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
1053 let hir_id = self.lower_node_id(param.id);
1054 self.lower_attrs(hir_id, ¶m.attrs);
1055 hir::Param {
1056 hir_id,
1057 pat: self.lower_pat(¶m.pat),
1058 ty_span: self.lower_span(param.ty.span),
1059 span: self.lower_span(param.span),
1060 }
1061 }
1062
1063 pub(super) fn lower_fn_body(
1064 &mut self,
1065 decl: &FnDecl,
1066 contract: Option<&FnContract>,
1067 body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
1068 ) -> hir::BodyId {
1069 self.lower_body(|this| {
1070 let params =
1071 this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x)));
1072
1073 if let Some(contract) = contract {
1081 let precond = if let Some(req) = &contract.requires {
1082 let lowered_req = this.lower_expr_mut(&req);
1084 let precond = this.expr_call_lang_item_fn_mut(
1085 req.span,
1086 hir::LangItem::ContractCheckRequires,
1087 &*arena_vec![this; lowered_req],
1088 );
1089 Some(this.stmt_expr(req.span, precond))
1090 } else {
1091 None
1092 };
1093 let (postcond, body) = if let Some(ens) = &contract.ensures {
1094 let ens_span = this.lower_span(ens.span);
1095 let check_ident: Ident =
1097 Ident::from_str_and_span("__ensures_checker", ens_span);
1098 let (checker_pat, check_hir_id) = this.pat_ident_binding_mode_mut(
1099 ens_span,
1100 check_ident,
1101 hir::BindingMode::NONE,
1102 );
1103 let lowered_ens = this.lower_expr_mut(&ens);
1104 let postcond_checker = this.expr_call_lang_item_fn(
1105 ens_span,
1106 hir::LangItem::ContractBuildCheckEnsures,
1107 &*arena_vec![this; lowered_ens],
1108 );
1109 let postcond = this.stmt_let_pat(
1110 None,
1111 ens_span,
1112 Some(postcond_checker),
1113 this.arena.alloc(checker_pat),
1114 hir::LocalSource::Contract,
1115 );
1116
1117 this.contract_ensures = Some((ens_span, check_ident, check_hir_id));
1120 let body = this.arena.alloc(body(this));
1121
1122 let body = this.inject_ensures_check(body, ens_span, check_ident, check_hir_id);
1124 (Some(postcond), body)
1125 } else {
1126 let body = &*this.arena.alloc(body(this));
1127 (None, body)
1128 };
1129 let wrapped_body = this.block_all(
1131 body.span,
1132 this.arena.alloc_from_iter([precond, postcond].into_iter().flatten()),
1133 Some(body),
1134 );
1135 (params, this.expr_block(wrapped_body))
1136 } else {
1137 (params, body(this))
1138 }
1139 })
1140 }
1141
1142 fn lower_fn_body_block(
1143 &mut self,
1144 decl: &FnDecl,
1145 body: &Block,
1146 contract: Option<&FnContract>,
1147 ) -> hir::BodyId {
1148 self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body))
1149 }
1150
1151 pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
1152 self.lower_body(|this| {
1153 (
1154 &[],
1155 match expr {
1156 Some(expr) => this.lower_expr_mut(expr),
1157 None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
1158 },
1159 )
1160 })
1161 }
1162
1163 fn lower_maybe_coroutine_body(
1166 &mut self,
1167 fn_decl_span: Span,
1168 span: Span,
1169 fn_id: hir::HirId,
1170 decl: &FnDecl,
1171 coroutine_kind: Option<CoroutineKind>,
1172 body: Option<&Block>,
1173 attrs: &'hir [hir::Attribute],
1174 contract: Option<&FnContract>,
1175 ) -> hir::BodyId {
1176 let Some(body) = body else {
1177 return self.lower_fn_body(decl, contract, |this| {
1181 if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) {
1182 let span = this.lower_span(span);
1183 let empty_block = hir::Block {
1184 hir_id: this.next_id(),
1185 stmts: &[],
1186 expr: None,
1187 rules: hir::BlockCheckMode::DefaultBlock,
1188 span,
1189 targeted_by_break: false,
1190 };
1191 let loop_ = hir::ExprKind::Loop(
1192 this.arena.alloc(empty_block),
1193 None,
1194 hir::LoopSource::Loop,
1195 span,
1196 );
1197 hir::Expr { hir_id: this.next_id(), kind: loop_, span }
1198 } else {
1199 this.expr_err(span, this.dcx().has_errors().unwrap())
1200 }
1201 });
1202 };
1203 let Some(coroutine_kind) = coroutine_kind else {
1204 return self.lower_fn_body_block(decl, body, contract);
1206 };
1207 self.lower_body(|this| {
1209 let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
1210 decl,
1211 |this| this.lower_block_expr(body),
1212 fn_decl_span,
1213 body.span,
1214 coroutine_kind,
1215 hir::CoroutineSource::Fn,
1216 );
1217
1218 let hir_id = expr.hir_id;
1220 this.maybe_forward_track_caller(body.span, fn_id, hir_id);
1221
1222 (parameters, expr)
1223 })
1224 }
1225
1226 pub(crate) fn lower_coroutine_body_with_moved_arguments(
1231 &mut self,
1232 decl: &FnDecl,
1233 lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
1234 fn_decl_span: Span,
1235 body_span: Span,
1236 coroutine_kind: CoroutineKind,
1237 coroutine_source: hir::CoroutineSource,
1238 ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
1239 let mut parameters: Vec<hir::Param<'_>> = Vec::new();
1240 let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
1241
1242 for (index, parameter) in decl.inputs.iter().enumerate() {
1275 let parameter = self.lower_param(parameter);
1276 let span = parameter.pat.span;
1277
1278 let (ident, is_simple_parameter) = match parameter.pat.kind {
1281 hir::PatKind::Binding(hir::BindingMode(ByRef::No, _), _, ident, _) => (ident, true),
1282 hir::PatKind::Binding(_, _, ident, _) => (ident, false),
1286 hir::PatKind::Wild => (Ident::with_dummy_span(rustc_span::kw::Underscore), false),
1287 _ => {
1288 let name = format!("__arg{index}");
1290 let ident = Ident::from_str(&name);
1291
1292 (ident, false)
1293 }
1294 };
1295
1296 let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
1297
1298 let stmt_attrs = self.attrs.get(¶meter.hir_id.local_id).copied();
1304 let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident);
1305 let new_parameter = hir::Param {
1306 hir_id: parameter.hir_id,
1307 pat: new_parameter_pat,
1308 ty_span: self.lower_span(parameter.ty_span),
1309 span: self.lower_span(parameter.span),
1310 };
1311
1312 if is_simple_parameter {
1313 let expr = self.expr_ident(desugared_span, ident, new_parameter_id);
1317 let stmt = self.stmt_let_pat(
1318 stmt_attrs,
1319 desugared_span,
1320 Some(expr),
1321 parameter.pat,
1322 hir::LocalSource::AsyncFn,
1323 );
1324 statements.push(stmt);
1325 } else {
1326 let (move_pat, move_id) =
1342 self.pat_ident_binding_mode(desugared_span, ident, hir::BindingMode::MUT);
1343 let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id);
1344 let move_stmt = self.stmt_let_pat(
1345 None,
1346 desugared_span,
1347 Some(move_expr),
1348 move_pat,
1349 hir::LocalSource::AsyncFn,
1350 );
1351
1352 let pattern_expr = self.expr_ident(desugared_span, ident, move_id);
1355 let pattern_stmt = self.stmt_let_pat(
1356 stmt_attrs,
1357 desugared_span,
1358 Some(pattern_expr),
1359 parameter.pat,
1360 hir::LocalSource::AsyncFn,
1361 );
1362
1363 statements.push(move_stmt);
1364 statements.push(pattern_stmt);
1365 };
1366
1367 parameters.push(new_parameter);
1368 }
1369
1370 let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
1371 let user_body = lower_body(this);
1373
1374 let desugared_span =
1376 this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
1377 let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
1378
1379 let body = this.block_all(
1389 desugared_span,
1390 this.arena.alloc_from_iter(statements),
1391 Some(user_body),
1392 );
1393
1394 this.expr_block(body)
1395 };
1396 let desugaring_kind = match coroutine_kind {
1397 CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
1398 CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
1399 CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,
1400 };
1401 let closure_id = coroutine_kind.closure_id();
1402
1403 let coroutine_expr = self.make_desugared_coroutine_expr(
1404 CaptureBy::Ref,
1409 closure_id,
1410 None,
1411 fn_decl_span,
1412 body_span,
1413 desugaring_kind,
1414 coroutine_source,
1415 mkbody,
1416 );
1417
1418 let expr = hir::Expr {
1419 hir_id: self.lower_node_id(closure_id),
1420 kind: coroutine_expr,
1421 span: self.lower_span(body_span),
1422 };
1423
1424 (self.arena.alloc_from_iter(parameters), expr)
1425 }
1426
1427 fn lower_method_sig(
1428 &mut self,
1429 generics: &Generics,
1430 sig: &FnSig,
1431 id: NodeId,
1432 kind: FnDeclKind,
1433 coroutine_kind: Option<CoroutineKind>,
1434 attrs: &[hir::Attribute],
1435 ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
1436 let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs);
1437 let itctx = ImplTraitContext::Universal;
1438 let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
1439 this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
1440 });
1441 (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
1442 }
1443
1444 pub(super) fn lower_fn_header(
1445 &mut self,
1446 h: FnHeader,
1447 default_safety: hir::Safety,
1448 attrs: &[hir::Attribute],
1449 ) -> hir::FnHeader {
1450 let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
1451 hir::IsAsync::Async(span)
1452 } else {
1453 hir::IsAsync::NotAsync
1454 };
1455
1456 let safety = self.lower_safety(h.safety, default_safety);
1457
1458 let safety = if attrs.iter().any(|attr| attr.has_name(sym::target_feature))
1460 && safety.is_safe()
1461 && !self.tcx.sess.target.is_like_wasm
1462 {
1463 hir::HeaderSafety::SafeTargetFeatures
1464 } else {
1465 safety.into()
1466 };
1467
1468 hir::FnHeader {
1469 safety,
1470 asyncness,
1471 constness: self.lower_constness(h.constness),
1472 abi: self.lower_extern(h.ext),
1473 }
1474 }
1475
1476 pub(super) fn lower_abi(&mut self, abi_str: StrLit) -> ExternAbi {
1477 let ast::StrLit { symbol_unescaped, span, .. } = abi_str;
1478 let extern_abi = symbol_unescaped.as_str().parse().unwrap_or_else(|_| {
1479 self.error_on_invalid_abi(abi_str);
1480 ExternAbi::Rust
1481 });
1482 let sess = self.tcx.sess;
1483 let features = self.tcx.features();
1484 gate_unstable_abi(sess, features, span, extern_abi);
1485 extern_abi
1486 }
1487
1488 pub(super) fn lower_extern(&mut self, ext: Extern) -> ExternAbi {
1489 match ext {
1490 Extern::None => ExternAbi::Rust,
1491 Extern::Implicit(_) => ExternAbi::FALLBACK,
1492 Extern::Explicit(abi, _) => self.lower_abi(abi),
1493 }
1494 }
1495
1496 fn error_on_invalid_abi(&self, abi: StrLit) {
1497 let abi_names = enabled_names(self.tcx.features(), abi.span)
1498 .iter()
1499 .map(|s| Symbol::intern(s))
1500 .collect::<Vec<_>>();
1501 let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
1502 self.dcx().emit_err(InvalidAbi {
1503 abi: abi.symbol_unescaped,
1504 span: abi.span,
1505 suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
1506 span: abi.span,
1507 suggestion: format!("\"{suggested_name}\""),
1508 }),
1509 command: "rustc --print=calling-conventions".to_string(),
1510 });
1511 }
1512
1513 pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness {
1514 match c {
1515 Const::Yes(_) => hir::Constness::Const,
1516 Const::No => hir::Constness::NotConst,
1517 }
1518 }
1519
1520 pub(super) fn lower_safety(&self, s: Safety, default: hir::Safety) -> hir::Safety {
1521 match s {
1522 Safety::Unsafe(_) => hir::Safety::Unsafe,
1523 Safety::Default => default,
1524 Safety::Safe(_) => hir::Safety::Safe,
1525 }
1526 }
1527
1528 #[instrument(level = "debug", skip(self, f))]
1531 fn lower_generics<T>(
1532 &mut self,
1533 generics: &Generics,
1534 parent_node_id: NodeId,
1535 itctx: ImplTraitContext,
1536 f: impl FnOnce(&mut Self) -> T,
1537 ) -> (&'hir hir::Generics<'hir>, T) {
1538 debug_assert!(self.impl_trait_defs.is_empty());
1539 debug_assert!(self.impl_trait_bounds.is_empty());
1540
1541 for pred in &generics.where_clause.predicates {
1547 let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else {
1548 continue;
1549 };
1550 let compute_is_param = || {
1551 match self
1553 .resolver
1554 .get_partial_res(bound_pred.bounded_ty.id)
1555 .and_then(|r| r.full_res())
1556 {
1557 Some(Res::Def(DefKind::TyParam, def_id))
1558 if bound_pred.bound_generic_params.is_empty() =>
1559 {
1560 generics
1561 .params
1562 .iter()
1563 .any(|p| def_id == self.local_def_id(p.id).to_def_id())
1564 }
1565 _ => false,
1568 }
1569 };
1570 let mut is_param: Option<bool> = None;
1573 for bound in &bound_pred.bounds {
1574 if !matches!(
1575 *bound,
1576 GenericBound::Trait(PolyTraitRef {
1577 modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
1578 ..
1579 })
1580 ) {
1581 continue;
1582 }
1583 let is_param = *is_param.get_or_insert_with(compute_is_param);
1584 if !is_param && !self.tcx.features().more_maybe_bounds() {
1585 self.tcx
1586 .sess
1587 .create_feature_err(
1588 MisplacedRelaxTraitBound { span: bound.span() },
1589 sym::more_maybe_bounds,
1590 )
1591 .emit();
1592 }
1593 }
1594 }
1595
1596 let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
1597 predicates.extend(generics.params.iter().filter_map(|param| {
1598 self.lower_generic_bound_predicate(
1599 param.ident,
1600 param.id,
1601 ¶m.kind,
1602 ¶m.bounds,
1603 param.colon_span,
1604 generics.span,
1605 itctx,
1606 PredicateOrigin::GenericParam,
1607 )
1608 }));
1609 predicates.extend(
1610 generics
1611 .where_clause
1612 .predicates
1613 .iter()
1614 .map(|predicate| self.lower_where_predicate(predicate)),
1615 );
1616
1617 let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
1618 .lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)
1619 .collect();
1620
1621 let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id);
1623 params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
1624 self.lifetime_res_to_generic_param(
1625 ident,
1626 node_id,
1627 res,
1628 hir::GenericParamSource::Generics,
1629 )
1630 }));
1631
1632 let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
1633 let where_clause_span = self.lower_span(generics.where_clause.span);
1634 let span = self.lower_span(generics.span);
1635 let res = f(self);
1636
1637 let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
1638 params.extend(impl_trait_defs.into_iter());
1639
1640 let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
1641 predicates.extend(impl_trait_bounds.into_iter());
1642
1643 let lowered_generics = self.arena.alloc(hir::Generics {
1644 params: self.arena.alloc_from_iter(params),
1645 predicates: self.arena.alloc_from_iter(predicates),
1646 has_where_clause_predicates,
1647 where_clause_span,
1648 span,
1649 });
1650
1651 (lowered_generics, res)
1652 }
1653
1654 pub(super) fn lower_generic_bound_predicate(
1655 &mut self,
1656 ident: Ident,
1657 id: NodeId,
1658 kind: &GenericParamKind,
1659 bounds: &[GenericBound],
1660 colon_span: Option<Span>,
1661 parent_span: Span,
1662 itctx: ImplTraitContext,
1663 origin: PredicateOrigin,
1664 ) -> Option<hir::WherePredicate<'hir>> {
1665 if bounds.is_empty() {
1667 return None;
1668 }
1669
1670 let bounds = self.lower_param_bounds(bounds, itctx);
1671
1672 let ident = self.lower_ident(ident);
1673 let param_span = ident.span;
1674
1675 let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi());
1677 let span = bounds.iter().fold(span_start, |span_accum, bound| {
1678 match bound.span().find_ancestor_inside(parent_span) {
1679 Some(bound_span) => span_accum.to(bound_span),
1680 None => span_accum,
1681 }
1682 });
1683 let span = self.lower_span(span);
1684 let hir_id = self.next_id();
1685 let kind = self.arena.alloc(match kind {
1686 GenericParamKind::Const { .. } => return None,
1687 GenericParamKind::Type { .. } => {
1688 let def_id = self.local_def_id(id).to_def_id();
1689 let hir_id = self.next_id();
1690 let res = Res::Def(DefKind::TyParam, def_id);
1691 let ty_path = self.arena.alloc(hir::Path {
1692 span: param_span,
1693 res,
1694 segments: self
1695 .arena
1696 .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]),
1697 });
1698 let ty_id = self.next_id();
1699 let bounded_ty =
1700 self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
1701 hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
1702 bounded_ty: self.arena.alloc(bounded_ty),
1703 bounds,
1704 bound_generic_params: &[],
1705 origin,
1706 })
1707 }
1708 GenericParamKind::Lifetime => {
1709 let ident = self.lower_ident(ident);
1710 let lt_id = self.next_node_id();
1711 let lifetime = self.new_named_lifetime(id, lt_id, ident);
1712 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1713 lifetime,
1714 bounds,
1715 in_where_clause: false,
1716 })
1717 }
1718 });
1719 Some(hir::WherePredicate { hir_id, span, kind })
1720 }
1721
1722 fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
1723 let hir_id = self.lower_node_id(pred.id);
1724 let span = self.lower_span(pred.span);
1725 let kind = self.arena.alloc(match &pred.kind {
1726 WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1727 bound_generic_params,
1728 bounded_ty,
1729 bounds,
1730 }) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
1731 bound_generic_params: self
1732 .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
1733 bounded_ty: self
1734 .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
1735 bounds: self.lower_param_bounds(
1736 bounds,
1737 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1738 ),
1739 origin: PredicateOrigin::WhereClause,
1740 }),
1741 WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
1742 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1743 lifetime: self.lower_lifetime(lifetime),
1744 bounds: self.lower_param_bounds(
1745 bounds,
1746 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1747 ),
1748 in_where_clause: true,
1749 })
1750 }
1751 WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => {
1752 hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
1753 lhs_ty: self
1754 .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
1755 rhs_ty: self
1756 .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
1757 })
1758 }
1759 });
1760 hir::WherePredicate { hir_id, span, kind }
1761 }
1762}