1use rustc_abi::ExternAbi;
2use rustc_ast::visit::AssocCtxt;
3use rustc_ast::*;
4use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
5use rustc_hir::attrs::AttributeKind;
6use rustc_hir::def::{DefKind, PerNS, Res};
7use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
8use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, Target, find_attr};
9use rustc_index::{IndexSlice, IndexVec};
10use rustc_middle::span_bug;
11use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
12use rustc_span::edit_distance::find_best_match_for_name;
13use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
14use smallvec::{SmallVec, smallvec};
15use thin_vec::ThinVec;
16use tracing::instrument;
17
18use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
19use super::stability::{enabled_names, gate_unstable_abi};
20use super::{
21 AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
22 RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
23};
24
25pub(super) struct ItemLowerer<'a, 'hir> {
26 pub(super) tcx: TyCtxt<'hir>,
27 pub(super) resolver: &'a mut ResolverAstLowering,
28 pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
29 pub(super) owners: &'a mut IndexVec<LocalDefId, hir::MaybeOwner<'hir>>,
30}
31
32fn add_ty_alias_where_clause(
36 generics: &mut ast::Generics,
37 mut where_clauses: TyAliasWhereClauses,
38 prefer_first: bool,
39) {
40 if !prefer_first {
41 (where_clauses.before, where_clauses.after) = (where_clauses.after, where_clauses.before);
42 }
43 let where_clause =
44 if where_clauses.before.has_where_token || !where_clauses.after.has_where_token {
45 where_clauses.before
46 } else {
47 where_clauses.after
48 };
49 generics.where_clause.has_where_token = where_clause.has_where_token;
50 generics.where_clause.span = where_clause.span;
51}
52
53impl<'a, 'hir> ItemLowerer<'a, 'hir> {
54 fn with_lctx(
55 &mut self,
56 owner: NodeId,
57 f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
58 ) {
59 let mut lctx = LoweringContext::new(self.tcx, self.resolver);
60 lctx.with_hir_id_owner(owner, |lctx| f(lctx));
61
62 for (def_id, info) in lctx.children {
63 let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
64 assert!(
65 matches!(owner, hir::MaybeOwner::Phantom),
66 "duplicate copy of {def_id:?} in lctx.children"
67 );
68 *owner = info;
69 }
70 }
71
72 pub(super) fn lower_node(&mut self, def_id: LocalDefId) {
73 let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
74 if let hir::MaybeOwner::Phantom = owner {
75 let node = self.ast_index[def_id];
76 match node {
77 AstOwner::NonOwner => {}
78 AstOwner::Crate(c) => {
79 assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
80 self.with_lctx(CRATE_NODE_ID, |lctx| {
81 let module = lctx.lower_mod(&c.items, &c.spans);
82 lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP, Target::Crate);
84 hir::OwnerNode::Crate(module)
85 })
86 }
87 AstOwner::Item(item) => {
88 self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
89 }
90 AstOwner::AssocItem(item, ctxt) => {
91 self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))
92 }
93 AstOwner::ForeignItem(item) => self.with_lctx(item.id, |lctx| {
94 hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))
95 }),
96 }
97 }
98 }
99}
100
101impl<'hir> LoweringContext<'_, 'hir> {
102 pub(super) fn lower_mod(
103 &mut self,
104 items: &[Box<Item>],
105 spans: &ModSpans,
106 ) -> &'hir hir::Mod<'hir> {
107 self.arena.alloc(hir::Mod {
108 spans: hir::ModSpans {
109 inner_span: self.lower_span(spans.inner_span),
110 inject_use_span: self.lower_span(spans.inject_use_span),
111 },
112 item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
113 })
114 }
115
116 pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
117 let mut node_ids = smallvec![hir::ItemId { owner_id: self.owner_id(i.id) }];
118 if let ItemKind::Use(use_tree) = &i.kind {
119 self.lower_item_id_use_tree(use_tree, &mut node_ids);
120 }
121 node_ids
122 }
123
124 fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) {
125 match &tree.kind {
126 UseTreeKind::Nested { items, .. } => {
127 for &(ref nested, id) in items {
128 vec.push(hir::ItemId { owner_id: self.owner_id(id) });
129 self.lower_item_id_use_tree(nested, vec);
130 }
131 }
132 UseTreeKind::Simple(..) | UseTreeKind::Glob => {}
133 }
134 }
135
136 fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
137 let vis_span = self.lower_span(i.vis.span);
138 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
139 let attrs = self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_ast_item(i));
140 let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind);
141 let item = hir::Item {
142 owner_id: hir_id.expect_owner(),
143 kind,
144 vis_span,
145 span: self.lower_span(i.span),
146 has_delayed_lints: !self.delayed_lints.is_empty(),
147 };
148 self.arena.alloc(item)
149 }
150
151 fn lower_item_kind(
152 &mut self,
153 span: Span,
154 id: NodeId,
155 hir_id: hir::HirId,
156 attrs: &'hir [hir::Attribute],
157 vis_span: Span,
158 i: &ItemKind,
159 ) -> hir::ItemKind<'hir> {
160 match i {
161 ItemKind::ExternCrate(orig_name, ident) => {
162 let ident = self.lower_ident(*ident);
163 hir::ItemKind::ExternCrate(*orig_name, ident)
164 }
165 ItemKind::Use(use_tree) => {
166 let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
168
169 self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
170 }
171 ItemKind::Static(box ast::StaticItem {
172 ident,
173 ty: t,
174 safety: _,
175 mutability: m,
176 expr: e,
177 define_opaque,
178 }) => {
179 let ident = self.lower_ident(*ident);
180 let (ty, body_id) =
181 self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
182 self.lower_define_opaque(hir_id, define_opaque);
183 hir::ItemKind::Static(*m, ident, ty, body_id)
184 }
185 ItemKind::Const(box ast::ConstItem {
186 ident,
187 generics,
188 ty,
189 expr,
190 define_opaque,
191 ..
192 }) => {
193 let ident = self.lower_ident(*ident);
194 let (generics, (ty, body_id)) = self.lower_generics(
195 generics,
196 id,
197 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
198 |this| {
199 this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
200 },
201 );
202 self.lower_define_opaque(hir_id, &define_opaque);
203 hir::ItemKind::Const(ident, generics, ty, body_id)
204 }
205 ItemKind::Fn(box Fn {
206 sig: FnSig { decl, header, span: fn_sig_span },
207 ident,
208 generics,
209 body,
210 contract,
211 define_opaque,
212 ..
213 }) => {
214 self.with_new_scopes(*fn_sig_span, |this| {
215 let coroutine_kind = header.coroutine_kind;
220 let body_id = this.lower_maybe_coroutine_body(
221 *fn_sig_span,
222 span,
223 hir_id,
224 decl,
225 coroutine_kind,
226 body.as_deref(),
227 attrs,
228 contract.as_deref(),
229 );
230
231 let itctx = ImplTraitContext::Universal;
232 let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {
233 this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coroutine_kind)
234 });
235 let sig = hir::FnSig {
236 decl,
237 header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
238 span: this.lower_span(*fn_sig_span),
239 };
240 this.lower_define_opaque(hir_id, define_opaque);
241 let ident = this.lower_ident(*ident);
242 hir::ItemKind::Fn {
243 ident,
244 sig,
245 generics,
246 body: body_id,
247 has_body: body.is_some(),
248 }
249 })
250 }
251 ItemKind::Mod(_, ident, mod_kind) => {
252 let ident = self.lower_ident(*ident);
253 match mod_kind {
254 ModKind::Loaded(items, _, spans) => {
255 hir::ItemKind::Mod(ident, self.lower_mod(items, spans))
256 }
257 ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
258 }
259 }
260 ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {
261 abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),
262 items: self
263 .arena
264 .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
265 },
266 ItemKind::GlobalAsm(asm) => {
267 let asm = self.lower_inline_asm(span, asm);
268 let fake_body =
269 self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
270 hir::ItemKind::GlobalAsm { asm, fake_body }
271 }
272 ItemKind::TyAlias(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
273 let ident = self.lower_ident(*ident);
282 let mut generics = generics.clone();
283 add_ty_alias_where_clause(&mut generics, *where_clauses, true);
284 let (generics, ty) = self.lower_generics(
285 &generics,
286 id,
287 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
288 |this| match ty {
289 None => {
290 let guar = this.dcx().span_delayed_bug(
291 span,
292 "expected to lower type alias type, but it was missing",
293 );
294 this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))
295 }
296 Some(ty) => this.lower_ty(
297 ty,
298 ImplTraitContext::OpaqueTy {
299 origin: hir::OpaqueTyOrigin::TyAlias {
300 parent: this.local_def_id(id),
301 in_assoc_ty: false,
302 },
303 },
304 ),
305 },
306 );
307 hir::ItemKind::TyAlias(ident, generics, ty)
308 }
309 ItemKind::Enum(ident, generics, enum_definition) => {
310 let ident = self.lower_ident(*ident);
311 let (generics, variants) = self.lower_generics(
312 generics,
313 id,
314 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
315 |this| {
316 this.arena.alloc_from_iter(
317 enum_definition.variants.iter().map(|x| this.lower_variant(i, x)),
318 )
319 },
320 );
321 hir::ItemKind::Enum(ident, generics, hir::EnumDef { variants })
322 }
323 ItemKind::Struct(ident, generics, struct_def) => {
324 let ident = self.lower_ident(*ident);
325 let (generics, struct_def) = self.lower_generics(
326 generics,
327 id,
328 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
329 |this| this.lower_variant_data(hir_id, i, struct_def),
330 );
331 hir::ItemKind::Struct(ident, generics, struct_def)
332 }
333 ItemKind::Union(ident, generics, vdata) => {
334 let ident = self.lower_ident(*ident);
335 let (generics, vdata) = self.lower_generics(
336 generics,
337 id,
338 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
339 |this| this.lower_variant_data(hir_id, i, vdata),
340 );
341 hir::ItemKind::Union(ident, generics, vdata)
342 }
343 ItemKind::Impl(Impl {
344 generics: ast_generics,
345 of_trait,
346 self_ty: ty,
347 items: impl_items,
348 }) => {
349 let itctx = ImplTraitContext::Universal;
363 let (generics, (of_trait, lowered_ty)) =
364 self.lower_generics(ast_generics, id, itctx, |this| {
365 let of_trait = of_trait
366 .as_deref()
367 .map(|of_trait| this.lower_trait_impl_header(of_trait));
368
369 let lowered_ty = this.lower_ty(
370 ty,
371 ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
372 );
373
374 (of_trait, lowered_ty)
375 });
376
377 let new_impl_items = self
378 .arena
379 .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
380
381 hir::ItemKind::Impl(hir::Impl {
382 generics,
383 of_trait,
384 self_ty: lowered_ty,
385 items: new_impl_items,
386 })
387 }
388 ItemKind::Trait(box Trait {
389 constness,
390 is_auto,
391 safety,
392 ident,
393 generics,
394 bounds,
395 items,
396 }) => {
397 let constness = self.lower_constness(*constness);
398 let ident = self.lower_ident(*ident);
399 let (generics, (safety, items, bounds)) = self.lower_generics(
400 generics,
401 id,
402 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
403 |this| {
404 let bounds = this.lower_param_bounds(
405 bounds,
406 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),
407 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
408 );
409 let items = this.arena.alloc_from_iter(
410 items.iter().map(|item| this.lower_trait_item_ref(item)),
411 );
412 let safety = this.lower_safety(*safety, hir::Safety::Safe);
413 (safety, items, bounds)
414 },
415 );
416 hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items)
417 }
418 ItemKind::TraitAlias(ident, generics, bounds) => {
419 let ident = self.lower_ident(*ident);
420 let (generics, bounds) = self.lower_generics(
421 generics,
422 id,
423 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
424 |this| {
425 this.lower_param_bounds(
426 bounds,
427 RelaxedBoundPolicy::Allowed,
428 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
429 )
430 },
431 );
432 hir::ItemKind::TraitAlias(ident, generics, bounds)
433 }
434 ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
435 let ident = self.lower_ident(*ident);
436 let body = Box::new(self.lower_delim_args(body));
437 let def_id = self.local_def_id(id);
438 let def_kind = self.tcx.def_kind(def_id);
439 let DefKind::Macro(macro_kinds) = def_kind else {
440 unreachable!(
441 "expected DefKind::Macro for macro item, found {}",
442 def_kind.descr(def_id.to_def_id())
443 );
444 };
445 let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
446 hir::ItemKind::Macro(ident, macro_def, macro_kinds)
447 }
448 ItemKind::Delegation(box delegation) => {
449 let delegation_results = self.lower_delegation(delegation, id, false);
450 hir::ItemKind::Fn {
451 sig: delegation_results.sig,
452 ident: delegation_results.ident,
453 generics: delegation_results.generics,
454 body: delegation_results.body_id,
455 has_body: true,
456 }
457 }
458 ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
459 panic!("macros should have been expanded by now")
460 }
461 }
462 }
463
464 fn lower_const_item(
465 &mut self,
466 ty: &Ty,
467 span: Span,
468 body: Option<&Expr>,
469 impl_trait_position: ImplTraitPosition,
470 ) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
471 let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position));
472 (ty, self.lower_const_body(span, body))
473 }
474
475 #[instrument(level = "debug", skip(self))]
476 fn lower_use_tree(
477 &mut self,
478 tree: &UseTree,
479 prefix: &Path,
480 id: NodeId,
481 vis_span: Span,
482 attrs: &'hir [hir::Attribute],
483 ) -> hir::ItemKind<'hir> {
484 let path = &tree.prefix;
485 let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
486
487 match tree.kind {
488 UseTreeKind::Simple(rename) => {
489 let mut ident = tree.ident();
490
491 let mut path = Path { segments, span: path.span, tokens: None };
493
494 if path.segments.len() > 1
496 && path.segments.last().unwrap().ident.name == kw::SelfLower
497 {
498 let _ = path.segments.pop();
499 if rename.is_none() {
500 ident = path.segments.last().unwrap().ident;
501 }
502 }
503
504 let res = self.lower_import_res(id, path.span);
505 let path = self.lower_use_path(res, &path, ParamMode::Explicit);
506 let ident = self.lower_ident(ident);
507 hir::ItemKind::Use(path, hir::UseKind::Single(ident))
508 }
509 UseTreeKind::Glob => {
510 let res = self.expect_full_res(id);
511 let res = self.lower_res(res);
512 let res = match res {
514 Res::Def(DefKind::Mod | DefKind::Trait, _) => {
515 PerNS { type_ns: Some(res), value_ns: None, macro_ns: None }
516 }
517 Res::Def(DefKind::Enum, _) => {
518 PerNS { type_ns: None, value_ns: Some(res), macro_ns: None }
519 }
520 Res::Err => {
521 let err = Some(Res::Err);
523 PerNS { type_ns: err, value_ns: err, macro_ns: err }
524 }
525 _ => span_bug!(path.span, "bad glob res {:?}", res),
526 };
527 let path = Path { segments, span: path.span, tokens: None };
528 let path = self.lower_use_path(res, &path, ParamMode::Explicit);
529 hir::ItemKind::Use(path, hir::UseKind::Glob)
530 }
531 UseTreeKind::Nested { items: ref trees, .. } => {
532 let span = prefix.span.to(path.span);
557 let prefix = Path { segments, span, tokens: None };
558
559 for &(ref use_tree, id) in trees {
561 let owner_id = self.owner_id(id);
562
563 self.with_hir_id_owner(id, |this| {
569 let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, attrs);
573 if !attrs.is_empty() {
574 this.attrs.insert(hir::ItemLocalId::ZERO, attrs);
575 }
576
577 let item = hir::Item {
578 owner_id,
579 kind,
580 vis_span,
581 span: this.lower_span(use_tree.span),
582 has_delayed_lints: !this.delayed_lints.is_empty(),
583 };
584 hir::OwnerNode::Item(this.arena.alloc(item))
585 });
586 }
587
588 let path = if trees.is_empty()
590 && !(prefix.segments.is_empty()
591 || prefix.segments.len() == 1
592 && prefix.segments[0].ident.name == kw::PathRoot)
593 {
594 let res = self.lower_import_res(id, span);
597 self.lower_use_path(res, &prefix, ParamMode::Explicit)
598 } else {
599 let span = self.lower_span(span);
602 self.arena.alloc(hir::UsePath { res: PerNS::default(), segments: &[], span })
603 };
604 hir::ItemKind::Use(path, hir::UseKind::ListStem)
605 }
606 }
607 }
608
609 fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) -> hir::OwnerNode<'hir> {
610 match ctxt {
614 AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
615 AssocCtxt::Impl { of_trait } => {
616 hir::OwnerNode::ImplItem(self.lower_impl_item(item, of_trait))
617 }
618 }
619 }
620
621 fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
622 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
623 let owner_id = hir_id.expect_owner();
624 let attrs =
625 self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_foreign_item_kind(&i.kind));
626 let (ident, kind) = match &i.kind {
627 ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => {
628 let fdec = &sig.decl;
629 let itctx = ImplTraitContext::Universal;
630 let (generics, (decl, fn_args)) =
631 self.lower_generics(generics, i.id, itctx, |this| {
632 (
633 this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None),
635 this.lower_fn_params_to_idents(fdec),
636 )
637 });
638
639 let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);
641
642 if define_opaque.is_some() {
643 self.dcx().span_err(i.span, "foreign functions cannot define opaque types");
644 }
645
646 (
647 ident,
648 hir::ForeignItemKind::Fn(
649 hir::FnSig { header, decl, span: self.lower_span(sig.span) },
650 fn_args,
651 generics,
652 ),
653 )
654 }
655 ForeignItemKind::Static(box StaticItem {
656 ident,
657 ty,
658 mutability,
659 expr: _,
660 safety,
661 define_opaque,
662 }) => {
663 let ty =
664 self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
665 let safety = self.lower_safety(*safety, hir::Safety::Unsafe);
666 if define_opaque.is_some() {
667 self.dcx().span_err(i.span, "foreign statics cannot define opaque types");
668 }
669 (ident, hir::ForeignItemKind::Static(ty, *mutability, safety))
670 }
671 ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => {
672 (ident, hir::ForeignItemKind::Type)
673 }
674 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
675 };
676
677 let item = hir::ForeignItem {
678 owner_id,
679 ident: self.lower_ident(*ident),
680 kind,
681 vis_span: self.lower_span(i.vis.span),
682 span: self.lower_span(i.span),
683 has_delayed_lints: !self.delayed_lints.is_empty(),
684 };
685 self.arena.alloc(item)
686 }
687
688 fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemId {
689 hir::ForeignItemId { owner_id: self.owner_id(i.id) }
690 }
691
692 fn lower_variant(&mut self, item_kind: &ItemKind, v: &Variant) -> hir::Variant<'hir> {
693 let hir_id = self.lower_node_id(v.id);
694 self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant);
695 hir::Variant {
696 hir_id,
697 def_id: self.local_def_id(v.id),
698 data: self.lower_variant_data(hir_id, item_kind, &v.data),
699 disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)),
700 ident: self.lower_ident(v.ident),
701 span: self.lower_span(v.span),
702 }
703 }
704
705 fn lower_variant_data(
706 &mut self,
707 parent_id: hir::HirId,
708 item_kind: &ItemKind,
709 vdata: &VariantData,
710 ) -> hir::VariantData<'hir> {
711 match vdata {
712 VariantData::Struct { fields, recovered } => {
713 let fields = self
714 .arena
715 .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f)));
716
717 if let ItemKind::Union(..) = item_kind {
718 for field in &fields[..] {
719 if let Some(default) = field.default {
720 if self.tcx.features().default_field_values() {
724 self.dcx().emit_err(UnionWithDefault { span: default.span });
725 } else {
726 let _ = self.dcx().span_delayed_bug(
727 default.span,
728 "expected union default field values feature gate error but none \
729 was produced",
730 );
731 }
732 }
733 }
734 }
735
736 hir::VariantData::Struct { fields, recovered: *recovered }
737 }
738 VariantData::Tuple(fields, id) => {
739 let ctor_id = self.lower_node_id(*id);
740 self.alias_attrs(ctor_id, parent_id);
741 let fields = self
742 .arena
743 .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f)));
744 for field in &fields[..] {
745 if let Some(default) = field.default {
746 if self.tcx.features().default_field_values() {
751 self.dcx().emit_err(TupleStructWithDefault { span: default.span });
752 } else {
753 let _ = self.dcx().span_delayed_bug(
754 default.span,
755 "expected `default values on `struct` fields aren't supported` \
756 feature-gate error but none was produced",
757 );
758 }
759 }
760 }
761 hir::VariantData::Tuple(fields, ctor_id, self.local_def_id(*id))
762 }
763 VariantData::Unit(id) => {
764 let ctor_id = self.lower_node_id(*id);
765 self.alias_attrs(ctor_id, parent_id);
766 hir::VariantData::Unit(ctor_id, self.local_def_id(*id))
767 }
768 }
769 }
770
771 pub(super) fn lower_field_def(
772 &mut self,
773 (index, f): (usize, &FieldDef),
774 ) -> hir::FieldDef<'hir> {
775 let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy));
776 let hir_id = self.lower_node_id(f.id);
777 self.lower_attrs(hir_id, &f.attrs, f.span, Target::Field);
778 hir::FieldDef {
779 span: self.lower_span(f.span),
780 hir_id,
781 def_id: self.local_def_id(f.id),
782 ident: match f.ident {
783 Some(ident) => self.lower_ident(ident),
784 None => Ident::new(sym::integer(index), self.lower_span(f.span)),
786 },
787 vis_span: self.lower_span(f.vis.span),
788 default: f.default.as_ref().map(|v| self.lower_anon_const_to_anon_const(v)),
789 ty,
790 safety: self.lower_safety(f.safety, hir::Safety::Safe),
791 }
792 }
793
794 fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
795 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
796 let attrs = self.lower_attrs(
797 hir_id,
798 &i.attrs,
799 i.span,
800 Target::from_assoc_item_kind(&i.kind, AssocCtxt::Trait),
801 );
802 let trait_item_def_id = hir_id.expect_owner();
803
804 let (ident, generics, kind, has_default) = match &i.kind {
805 AssocItemKind::Const(box ConstItem {
806 ident,
807 generics,
808 ty,
809 expr,
810 define_opaque,
811 ..
812 }) => {
813 let (generics, kind) = self.lower_generics(
814 generics,
815 i.id,
816 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
817 |this| {
818 let ty = this
819 .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
820 let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
821
822 hir::TraitItemKind::Const(ty, body)
823 },
824 );
825
826 if define_opaque.is_some() {
827 if expr.is_some() {
828 self.lower_define_opaque(hir_id, &define_opaque);
829 } else {
830 self.dcx().span_err(
831 i.span,
832 "only trait consts with default bodies can define opaque types",
833 );
834 }
835 }
836
837 (*ident, generics, kind, expr.is_some())
838 }
839 AssocItemKind::Fn(box Fn {
840 sig, ident, generics, body: None, define_opaque, ..
841 }) => {
842 let idents = self.lower_fn_params_to_idents(&sig.decl);
845 let (generics, sig) = self.lower_method_sig(
846 generics,
847 sig,
848 i.id,
849 FnDeclKind::Trait,
850 sig.header.coroutine_kind,
851 attrs,
852 );
853 if define_opaque.is_some() {
854 self.dcx().span_err(
855 i.span,
856 "only trait methods with default bodies can define opaque types",
857 );
858 }
859 (
860 *ident,
861 generics,
862 hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(idents)),
863 false,
864 )
865 }
866 AssocItemKind::Fn(box Fn {
867 sig,
868 ident,
869 generics,
870 body: Some(body),
871 contract,
872 define_opaque,
873 ..
874 }) => {
875 let body_id = self.lower_maybe_coroutine_body(
876 sig.span,
877 i.span,
878 hir_id,
879 &sig.decl,
880 sig.header.coroutine_kind,
881 Some(body),
882 attrs,
883 contract.as_deref(),
884 );
885 let (generics, sig) = self.lower_method_sig(
886 generics,
887 sig,
888 i.id,
889 FnDeclKind::Trait,
890 sig.header.coroutine_kind,
891 attrs,
892 );
893 self.lower_define_opaque(hir_id, &define_opaque);
894 (
895 *ident,
896 generics,
897 hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),
898 true,
899 )
900 }
901 AssocItemKind::Type(box TyAlias {
902 ident, generics, where_clauses, bounds, ty, ..
903 }) => {
904 let mut generics = generics.clone();
905 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
906 let (generics, kind) = self.lower_generics(
907 &generics,
908 i.id,
909 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
910 |this| {
911 let ty = ty.as_ref().map(|x| {
912 this.lower_ty(
913 x,
914 ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
915 )
916 });
917 hir::TraitItemKind::Type(
918 this.lower_param_bounds(
919 bounds,
920 RelaxedBoundPolicy::Allowed,
921 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
922 ),
923 ty,
924 )
925 },
926 );
927 (*ident, generics, kind, ty.is_some())
928 }
929 AssocItemKind::Delegation(box delegation) => {
930 let delegation_results = self.lower_delegation(delegation, i.id, false);
931 let item_kind = hir::TraitItemKind::Fn(
932 delegation_results.sig,
933 hir::TraitFn::Provided(delegation_results.body_id),
934 );
935 (delegation.ident, delegation_results.generics, item_kind, true)
936 }
937 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
938 panic!("macros should have been expanded by now")
939 }
940 };
941
942 let item = hir::TraitItem {
943 owner_id: trait_item_def_id,
944 ident: self.lower_ident(ident),
945 generics,
946 kind,
947 span: self.lower_span(i.span),
948 defaultness: hir::Defaultness::Default { has_value: has_default },
949 has_delayed_lints: !self.delayed_lints.is_empty(),
950 };
951 self.arena.alloc(item)
952 }
953
954 fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemId {
955 hir::TraitItemId { owner_id: self.owner_id(i.id) }
956 }
957
958 pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {
960 self.expr(span, hir::ExprKind::Err(guar))
961 }
962
963 fn lower_trait_impl_header(
964 &mut self,
965 trait_impl_header: &TraitImplHeader,
966 ) -> &'hir hir::TraitImplHeader<'hir> {
967 let TraitImplHeader { constness, safety, polarity, defaultness, ref trait_ref } =
968 *trait_impl_header;
969 let constness = self.lower_constness(constness);
970 let safety = self.lower_safety(safety, hir::Safety::Safe);
971 let polarity = match polarity {
972 ImplPolarity::Positive => ImplPolarity::Positive,
973 ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
974 };
975 let has_val = true;
978 let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
979 let modifiers = TraitBoundModifiers {
980 constness: BoundConstness::Never,
981 asyncness: BoundAsyncness::Normal,
982 polarity: BoundPolarity::Positive,
984 };
985 let trait_ref = self.lower_trait_ref(
986 modifiers,
987 trait_ref,
988 ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
989 );
990
991 self.arena.alloc(hir::TraitImplHeader {
992 constness,
993 safety,
994 polarity,
995 defaultness,
996 defaultness_span,
997 trait_ref,
998 })
999 }
1000
1001 fn lower_impl_item(
1002 &mut self,
1003 i: &AssocItem,
1004 is_in_trait_impl: bool,
1005 ) -> &'hir hir::ImplItem<'hir> {
1006 let has_value = true;
1008 let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
1009 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);
1010 let attrs = self.lower_attrs(
1011 hir_id,
1012 &i.attrs,
1013 i.span,
1014 Target::from_assoc_item_kind(&i.kind, AssocCtxt::Impl { of_trait: is_in_trait_impl }),
1015 );
1016
1017 let (ident, (generics, kind)) = match &i.kind {
1018 AssocItemKind::Const(box ConstItem {
1019 ident,
1020 generics,
1021 ty,
1022 expr,
1023 define_opaque,
1024 ..
1025 }) => (
1026 *ident,
1027 self.lower_generics(
1028 generics,
1029 i.id,
1030 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1031 |this| {
1032 let ty = this
1033 .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
1034 let body = this.lower_const_body(i.span, expr.as_deref());
1035 this.lower_define_opaque(hir_id, &define_opaque);
1036 hir::ImplItemKind::Const(ty, body)
1037 },
1038 ),
1039 ),
1040 AssocItemKind::Fn(box Fn {
1041 sig,
1042 ident,
1043 generics,
1044 body,
1045 contract,
1046 define_opaque,
1047 ..
1048 }) => {
1049 let body_id = self.lower_maybe_coroutine_body(
1050 sig.span,
1051 i.span,
1052 hir_id,
1053 &sig.decl,
1054 sig.header.coroutine_kind,
1055 body.as_deref(),
1056 attrs,
1057 contract.as_deref(),
1058 );
1059 let (generics, sig) = self.lower_method_sig(
1060 generics,
1061 sig,
1062 i.id,
1063 if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
1064 sig.header.coroutine_kind,
1065 attrs,
1066 );
1067 self.lower_define_opaque(hir_id, &define_opaque);
1068
1069 (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id)))
1070 }
1071 AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => {
1072 let mut generics = generics.clone();
1073 add_ty_alias_where_clause(&mut generics, *where_clauses, false);
1074 (
1075 *ident,
1076 self.lower_generics(
1077 &generics,
1078 i.id,
1079 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1080 |this| match ty {
1081 None => {
1082 let guar = this.dcx().span_delayed_bug(
1083 i.span,
1084 "expected to lower associated type, but it was missing",
1085 );
1086 let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));
1087 hir::ImplItemKind::Type(ty)
1088 }
1089 Some(ty) => {
1090 let ty = this.lower_ty(
1091 ty,
1092 ImplTraitContext::OpaqueTy {
1093 origin: hir::OpaqueTyOrigin::TyAlias {
1094 parent: this.local_def_id(i.id),
1095 in_assoc_ty: true,
1096 },
1097 },
1098 );
1099 hir::ImplItemKind::Type(ty)
1100 }
1101 },
1102 ),
1103 )
1104 }
1105 AssocItemKind::Delegation(box delegation) => {
1106 let delegation_results = self.lower_delegation(delegation, i.id, is_in_trait_impl);
1107 (
1108 delegation.ident,
1109 (
1110 delegation_results.generics,
1111 hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),
1112 ),
1113 )
1114 }
1115 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
1116 panic!("macros should have been expanded by now")
1117 }
1118 };
1119
1120 let item = hir::ImplItem {
1121 owner_id: hir_id.expect_owner(),
1122 ident: self.lower_ident(ident),
1123 generics,
1124 kind,
1125 vis_span: self.lower_span(i.vis.span),
1126 span: self.lower_span(i.span),
1127 defaultness,
1128 has_delayed_lints: !self.delayed_lints.is_empty(),
1129 trait_item_def_id: self
1130 .resolver
1131 .get_partial_res(i.id)
1132 .map(|r| r.expect_full_res().opt_def_id())
1133 .unwrap_or(None),
1134 };
1135 self.arena.alloc(item)
1136 }
1137
1138 fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemId {
1139 hir::ImplItemId { owner_id: self.owner_id(i.id) }
1140 }
1141
1142 fn lower_defaultness(
1143 &self,
1144 d: Defaultness,
1145 has_value: bool,
1146 ) -> (hir::Defaultness, Option<Span>) {
1147 match d {
1148 Defaultness::Default(sp) => {
1149 (hir::Defaultness::Default { has_value }, Some(self.lower_span(sp)))
1150 }
1151 Defaultness::Final => {
1152 assert!(has_value);
1153 (hir::Defaultness::Final, None)
1154 }
1155 }
1156 }
1157
1158 fn record_body(
1159 &mut self,
1160 params: &'hir [hir::Param<'hir>],
1161 value: hir::Expr<'hir>,
1162 ) -> hir::BodyId {
1163 let body = hir::Body { params, value: self.arena.alloc(value) };
1164 let id = body.id();
1165 assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
1166 self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
1167 id
1168 }
1169
1170 pub(super) fn lower_body(
1171 &mut self,
1172 f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
1173 ) -> hir::BodyId {
1174 let prev_coroutine_kind = self.coroutine_kind.take();
1175 let task_context = self.task_context.take();
1176 let (parameters, result) = f(self);
1177 let body_id = self.record_body(parameters, result);
1178 self.task_context = task_context;
1179 self.coroutine_kind = prev_coroutine_kind;
1180 body_id
1181 }
1182
1183 fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
1184 let hir_id = self.lower_node_id(param.id);
1185 self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::Param);
1186 hir::Param {
1187 hir_id,
1188 pat: self.lower_pat(¶m.pat),
1189 ty_span: self.lower_span(param.ty.span),
1190 span: self.lower_span(param.span),
1191 }
1192 }
1193
1194 pub(super) fn lower_fn_body(
1195 &mut self,
1196 decl: &FnDecl,
1197 contract: Option<&FnContract>,
1198 body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
1199 ) -> hir::BodyId {
1200 self.lower_body(|this| {
1201 let params =
1202 this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x)));
1203
1204 if let Some(contract) = contract {
1212 let precond = if let Some(req) = &contract.requires {
1213 let lowered_req = this.lower_expr_mut(&req);
1215 let req_span = this.mark_span_with_reason(
1216 DesugaringKind::Contract,
1217 lowered_req.span,
1218 None,
1219 );
1220 let precond = this.expr_call_lang_item_fn_mut(
1221 req_span,
1222 hir::LangItem::ContractCheckRequires,
1223 &*arena_vec![this; lowered_req],
1224 );
1225 Some(this.stmt_expr(req.span, precond))
1226 } else {
1227 None
1228 };
1229 let (postcond, body) = if let Some(ens) = &contract.ensures {
1230 let ens_span = this.lower_span(ens.span);
1231 let ens_span =
1232 this.mark_span_with_reason(DesugaringKind::Contract, ens_span, None);
1233 let check_ident: Ident =
1235 Ident::from_str_and_span("__ensures_checker", ens_span);
1236 let (checker_pat, check_hir_id) = this.pat_ident_binding_mode_mut(
1237 ens_span,
1238 check_ident,
1239 hir::BindingMode::NONE,
1240 );
1241 let lowered_ens = this.lower_expr_mut(&ens);
1242 let postcond_checker = this.expr_call_lang_item_fn(
1243 ens_span,
1244 hir::LangItem::ContractBuildCheckEnsures,
1245 &*arena_vec![this; lowered_ens],
1246 );
1247 let postcond = this.stmt_let_pat(
1248 None,
1249 ens_span,
1250 Some(postcond_checker),
1251 this.arena.alloc(checker_pat),
1252 hir::LocalSource::Contract,
1253 );
1254
1255 this.contract_ensures = Some((ens_span, check_ident, check_hir_id));
1258 let body = this.arena.alloc(body(this));
1259
1260 let body = this.inject_ensures_check(body, ens_span, check_ident, check_hir_id);
1262 (Some(postcond), body)
1263 } else {
1264 let body = &*this.arena.alloc(body(this));
1265 (None, body)
1266 };
1267 let wrapped_body = this.block_all(
1269 body.span,
1270 this.arena.alloc_from_iter([precond, postcond].into_iter().flatten()),
1271 Some(body),
1272 );
1273 (params, this.expr_block(wrapped_body))
1274 } else {
1275 (params, body(this))
1276 }
1277 })
1278 }
1279
1280 fn lower_fn_body_block(
1281 &mut self,
1282 decl: &FnDecl,
1283 body: &Block,
1284 contract: Option<&FnContract>,
1285 ) -> hir::BodyId {
1286 self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body))
1287 }
1288
1289 pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
1290 self.lower_body(|this| {
1291 (
1292 &[],
1293 match expr {
1294 Some(expr) => this.lower_expr_mut(expr),
1295 None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),
1296 },
1297 )
1298 })
1299 }
1300
1301 fn lower_maybe_coroutine_body(
1304 &mut self,
1305 fn_decl_span: Span,
1306 span: Span,
1307 fn_id: hir::HirId,
1308 decl: &FnDecl,
1309 coroutine_kind: Option<CoroutineKind>,
1310 body: Option<&Block>,
1311 attrs: &'hir [hir::Attribute],
1312 contract: Option<&FnContract>,
1313 ) -> hir::BodyId {
1314 let Some(body) = body else {
1315 return self.lower_fn_body(decl, contract, |this| {
1319 if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic))
1320 || this.tcx.is_sdylib_interface_build()
1321 {
1322 let span = this.lower_span(span);
1323 let empty_block = hir::Block {
1324 hir_id: this.next_id(),
1325 stmts: &[],
1326 expr: None,
1327 rules: hir::BlockCheckMode::DefaultBlock,
1328 span,
1329 targeted_by_break: false,
1330 };
1331 let loop_ = hir::ExprKind::Loop(
1332 this.arena.alloc(empty_block),
1333 None,
1334 hir::LoopSource::Loop,
1335 span,
1336 );
1337 hir::Expr { hir_id: this.next_id(), kind: loop_, span }
1338 } else {
1339 this.expr_err(span, this.dcx().has_errors().unwrap())
1340 }
1341 });
1342 };
1343 let Some(coroutine_kind) = coroutine_kind else {
1344 return self.lower_fn_body_block(decl, body, contract);
1346 };
1347 self.lower_body(|this| {
1349 let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
1350 decl,
1351 |this| this.lower_block_expr(body),
1352 fn_decl_span,
1353 body.span,
1354 coroutine_kind,
1355 hir::CoroutineSource::Fn,
1356 );
1357
1358 let hir_id = expr.hir_id;
1360 this.maybe_forward_track_caller(body.span, fn_id, hir_id);
1361
1362 (parameters, expr)
1363 })
1364 }
1365
1366 pub(crate) fn lower_coroutine_body_with_moved_arguments(
1371 &mut self,
1372 decl: &FnDecl,
1373 lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
1374 fn_decl_span: Span,
1375 body_span: Span,
1376 coroutine_kind: CoroutineKind,
1377 coroutine_source: hir::CoroutineSource,
1378 ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
1379 let mut parameters: Vec<hir::Param<'_>> = Vec::new();
1380 let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
1381
1382 for (index, parameter) in decl.inputs.iter().enumerate() {
1415 let parameter = self.lower_param(parameter);
1416 let span = parameter.pat.span;
1417
1418 let (ident, is_simple_parameter) = match parameter.pat.kind {
1421 hir::PatKind::Binding(hir::BindingMode(ByRef::No, _), _, ident, _) => (ident, true),
1422 hir::PatKind::Binding(_, _, ident, _) => (ident, false),
1426 hir::PatKind::Wild => (Ident::with_dummy_span(rustc_span::kw::Underscore), false),
1427 _ => {
1428 let name = format!("__arg{index}");
1430 let ident = Ident::from_str(&name);
1431
1432 (ident, false)
1433 }
1434 };
1435
1436 let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
1437
1438 let stmt_attrs = self.attrs.get(¶meter.hir_id.local_id).copied();
1444 let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident);
1445 let new_parameter = hir::Param {
1446 hir_id: parameter.hir_id,
1447 pat: new_parameter_pat,
1448 ty_span: self.lower_span(parameter.ty_span),
1449 span: self.lower_span(parameter.span),
1450 };
1451
1452 if is_simple_parameter {
1453 let expr = self.expr_ident(desugared_span, ident, new_parameter_id);
1457 let stmt = self.stmt_let_pat(
1458 stmt_attrs,
1459 desugared_span,
1460 Some(expr),
1461 parameter.pat,
1462 hir::LocalSource::AsyncFn,
1463 );
1464 statements.push(stmt);
1465 } else {
1466 let (move_pat, move_id) =
1482 self.pat_ident_binding_mode(desugared_span, ident, hir::BindingMode::MUT);
1483 let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id);
1484 let move_stmt = self.stmt_let_pat(
1485 None,
1486 desugared_span,
1487 Some(move_expr),
1488 move_pat,
1489 hir::LocalSource::AsyncFn,
1490 );
1491
1492 let pattern_expr = self.expr_ident(desugared_span, ident, move_id);
1495 let pattern_stmt = self.stmt_let_pat(
1496 stmt_attrs,
1497 desugared_span,
1498 Some(pattern_expr),
1499 parameter.pat,
1500 hir::LocalSource::AsyncFn,
1501 );
1502
1503 statements.push(move_stmt);
1504 statements.push(pattern_stmt);
1505 };
1506
1507 parameters.push(new_parameter);
1508 }
1509
1510 let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
1511 let user_body = lower_body(this);
1513
1514 let desugared_span =
1516 this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);
1517 let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));
1518
1519 let body = this.block_all(
1529 desugared_span,
1530 this.arena.alloc_from_iter(statements),
1531 Some(user_body),
1532 );
1533
1534 this.expr_block(body)
1535 };
1536 let desugaring_kind = match coroutine_kind {
1537 CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
1538 CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
1539 CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,
1540 };
1541 let closure_id = coroutine_kind.closure_id();
1542
1543 let coroutine_expr = self.make_desugared_coroutine_expr(
1544 CaptureBy::Ref,
1549 closure_id,
1550 None,
1551 fn_decl_span,
1552 body_span,
1553 desugaring_kind,
1554 coroutine_source,
1555 mkbody,
1556 );
1557
1558 let expr = hir::Expr {
1559 hir_id: self.lower_node_id(closure_id),
1560 kind: coroutine_expr,
1561 span: self.lower_span(body_span),
1562 };
1563
1564 (self.arena.alloc_from_iter(parameters), expr)
1565 }
1566
1567 fn lower_method_sig(
1568 &mut self,
1569 generics: &Generics,
1570 sig: &FnSig,
1571 id: NodeId,
1572 kind: FnDeclKind,
1573 coroutine_kind: Option<CoroutineKind>,
1574 attrs: &[hir::Attribute],
1575 ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
1576 let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs);
1577 let itctx = ImplTraitContext::Universal;
1578 let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {
1579 this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
1580 });
1581 (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
1582 }
1583
1584 pub(super) fn lower_fn_header(
1585 &mut self,
1586 h: FnHeader,
1587 default_safety: hir::Safety,
1588 attrs: &[hir::Attribute],
1589 ) -> hir::FnHeader {
1590 let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {
1591 hir::IsAsync::Async(self.lower_span(span))
1592 } else {
1593 hir::IsAsync::NotAsync
1594 };
1595
1596 let safety = self.lower_safety(h.safety, default_safety);
1597
1598 let safety = if find_attr!(attrs, AttributeKind::TargetFeature { was_forced: false, .. })
1600 && safety.is_safe()
1601 && !self.tcx.sess.target.is_like_wasm
1602 {
1603 hir::HeaderSafety::SafeTargetFeatures
1604 } else {
1605 safety.into()
1606 };
1607
1608 hir::FnHeader {
1609 safety,
1610 asyncness,
1611 constness: self.lower_constness(h.constness),
1612 abi: self.lower_extern(h.ext),
1613 }
1614 }
1615
1616 pub(super) fn lower_abi(&mut self, abi_str: StrLit) -> ExternAbi {
1617 let ast::StrLit { symbol_unescaped, span, .. } = abi_str;
1618 let extern_abi = symbol_unescaped.as_str().parse().unwrap_or_else(|_| {
1619 self.error_on_invalid_abi(abi_str);
1620 ExternAbi::Rust
1621 });
1622 let tcx = self.tcx;
1623
1624 if !tcx.sess.target.is_abi_supported(extern_abi) {
1626 let mut err = struct_span_code_err!(
1627 tcx.dcx(),
1628 span,
1629 E0570,
1630 "{extern_abi} is not a supported ABI for the current target",
1631 );
1632
1633 if let ExternAbi::Stdcall { unwind } = extern_abi {
1634 let c_abi = ExternAbi::C { unwind };
1635 let system_abi = ExternAbi::System { unwind };
1636 err.help(format!("if you need `extern {extern_abi}` on win32 and `extern {c_abi}` everywhere else, \
1637 use `extern {system_abi}`"
1638 ));
1639 }
1640 err.emit();
1641 }
1642 gate_unstable_abi(tcx.sess, tcx.features(), span, extern_abi);
1645 extern_abi
1646 }
1647
1648 pub(super) fn lower_extern(&mut self, ext: Extern) -> ExternAbi {
1649 match ext {
1650 Extern::None => ExternAbi::Rust,
1651 Extern::Implicit(_) => ExternAbi::FALLBACK,
1652 Extern::Explicit(abi, _) => self.lower_abi(abi),
1653 }
1654 }
1655
1656 fn error_on_invalid_abi(&self, abi: StrLit) {
1657 let abi_names = enabled_names(self.tcx.features(), abi.span)
1658 .iter()
1659 .map(|s| Symbol::intern(s))
1660 .collect::<Vec<_>>();
1661 let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
1662 self.dcx().emit_err(InvalidAbi {
1663 abi: abi.symbol_unescaped,
1664 span: abi.span,
1665 suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
1666 span: abi.span,
1667 suggestion: suggested_name.to_string(),
1668 }),
1669 command: "rustc --print=calling-conventions".to_string(),
1670 });
1671 }
1672
1673 pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness {
1674 match c {
1675 Const::Yes(_) => hir::Constness::Const,
1676 Const::No => hir::Constness::NotConst,
1677 }
1678 }
1679
1680 pub(super) fn lower_safety(&self, s: Safety, default: hir::Safety) -> hir::Safety {
1681 match s {
1682 Safety::Unsafe(_) => hir::Safety::Unsafe,
1683 Safety::Default => default,
1684 Safety::Safe(_) => hir::Safety::Safe,
1685 }
1686 }
1687
1688 #[instrument(level = "debug", skip(self, f))]
1691 fn lower_generics<T>(
1692 &mut self,
1693 generics: &Generics,
1694 parent_node_id: NodeId,
1695 itctx: ImplTraitContext,
1696 f: impl FnOnce(&mut Self) -> T,
1697 ) -> (&'hir hir::Generics<'hir>, T) {
1698 assert!(self.impl_trait_defs.is_empty());
1699 assert!(self.impl_trait_bounds.is_empty());
1700
1701 let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
1702 predicates.extend(generics.params.iter().filter_map(|param| {
1703 self.lower_generic_bound_predicate(
1704 param.ident,
1705 param.id,
1706 ¶m.kind,
1707 ¶m.bounds,
1708 param.colon_span,
1709 generics.span,
1710 RelaxedBoundPolicy::Allowed,
1711 itctx,
1712 PredicateOrigin::GenericParam,
1713 )
1714 }));
1715 predicates.extend(
1716 generics
1717 .where_clause
1718 .predicates
1719 .iter()
1720 .map(|predicate| self.lower_where_predicate(predicate, &generics.params)),
1721 );
1722
1723 let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
1724 .lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)
1725 .collect();
1726
1727 let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id);
1729 params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
1730 self.lifetime_res_to_generic_param(
1731 ident,
1732 node_id,
1733 res,
1734 hir::GenericParamSource::Generics,
1735 )
1736 }));
1737
1738 let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
1739 let where_clause_span = self.lower_span(generics.where_clause.span);
1740 let span = self.lower_span(generics.span);
1741 let res = f(self);
1742
1743 let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
1744 params.extend(impl_trait_defs.into_iter());
1745
1746 let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
1747 predicates.extend(impl_trait_bounds.into_iter());
1748
1749 let lowered_generics = self.arena.alloc(hir::Generics {
1750 params: self.arena.alloc_from_iter(params),
1751 predicates: self.arena.alloc_from_iter(predicates),
1752 has_where_clause_predicates,
1753 where_clause_span,
1754 span,
1755 });
1756
1757 (lowered_generics, res)
1758 }
1759
1760 pub(super) fn lower_define_opaque(
1761 &mut self,
1762 hir_id: HirId,
1763 define_opaque: &Option<ThinVec<(NodeId, Path)>>,
1764 ) {
1765 assert_eq!(self.define_opaque, None);
1766 assert!(hir_id.is_owner());
1767 let Some(define_opaque) = define_opaque.as_ref() else {
1768 return;
1769 };
1770 let define_opaque = define_opaque.iter().filter_map(|(id, path)| {
1771 let res = self.resolver.get_partial_res(*id);
1772 let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else {
1773 self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
1774 return None;
1775 };
1776 let Some(did) = did.as_local() else {
1777 self.dcx().span_err(
1778 path.span,
1779 "only opaque types defined in the local crate can be defined",
1780 );
1781 return None;
1782 };
1783 Some((self.lower_span(path.span), did))
1784 });
1785 let define_opaque = self.arena.alloc_from_iter(define_opaque);
1786 self.define_opaque = Some(define_opaque);
1787 }
1788
1789 pub(super) fn lower_generic_bound_predicate(
1790 &mut self,
1791 ident: Ident,
1792 id: NodeId,
1793 kind: &GenericParamKind,
1794 bounds: &[GenericBound],
1795 colon_span: Option<Span>,
1796 parent_span: Span,
1797 rbp: RelaxedBoundPolicy<'_>,
1798 itctx: ImplTraitContext,
1799 origin: PredicateOrigin,
1800 ) -> Option<hir::WherePredicate<'hir>> {
1801 if bounds.is_empty() {
1803 return None;
1804 }
1805
1806 let bounds = self.lower_param_bounds(bounds, rbp, itctx);
1807
1808 let param_span = ident.span;
1809
1810 let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi());
1812 let span = bounds.iter().fold(span_start, |span_accum, bound| {
1813 match bound.span().find_ancestor_inside(parent_span) {
1814 Some(bound_span) => span_accum.to(bound_span),
1815 None => span_accum,
1816 }
1817 });
1818 let span = self.lower_span(span);
1819 let hir_id = self.next_id();
1820 let kind = self.arena.alloc(match kind {
1821 GenericParamKind::Const { .. } => return None,
1822 GenericParamKind::Type { .. } => {
1823 let def_id = self.local_def_id(id).to_def_id();
1824 let hir_id = self.next_id();
1825 let res = Res::Def(DefKind::TyParam, def_id);
1826 let ident = self.lower_ident(ident);
1827 let ty_path = self.arena.alloc(hir::Path {
1828 span: self.lower_span(param_span),
1829 res,
1830 segments: self
1831 .arena
1832 .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]),
1833 });
1834 let ty_id = self.next_id();
1835 let bounded_ty =
1836 self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
1837 hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
1838 bounded_ty: self.arena.alloc(bounded_ty),
1839 bounds,
1840 bound_generic_params: &[],
1841 origin,
1842 })
1843 }
1844 GenericParamKind::Lifetime => {
1845 let lt_id = self.next_node_id();
1846 let lifetime =
1847 self.new_named_lifetime(id, lt_id, ident, LifetimeSource::Other, ident.into());
1848 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1849 lifetime,
1850 bounds,
1851 in_where_clause: false,
1852 })
1853 }
1854 });
1855 Some(hir::WherePredicate { hir_id, span, kind })
1856 }
1857
1858 fn lower_where_predicate(
1859 &mut self,
1860 pred: &WherePredicate,
1861 params: &[ast::GenericParam],
1862 ) -> hir::WherePredicate<'hir> {
1863 let hir_id = self.lower_node_id(pred.id);
1864 let span = self.lower_span(pred.span);
1865 self.lower_attrs(hir_id, &pred.attrs, span, Target::WherePredicate);
1866 let kind = self.arena.alloc(match &pred.kind {
1867 WherePredicateKind::BoundPredicate(WhereBoundPredicate {
1868 bound_generic_params,
1869 bounded_ty,
1870 bounds,
1871 }) => {
1872 let rbp = if bound_generic_params.is_empty() {
1873 RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params)
1874 } else {
1875 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope)
1876 };
1877 hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
1878 bound_generic_params: self.lower_generic_params(
1879 bound_generic_params,
1880 hir::GenericParamSource::Binder,
1881 ),
1882 bounded_ty: self.lower_ty(
1883 bounded_ty,
1884 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1885 ),
1886 bounds: self.lower_param_bounds(
1887 bounds,
1888 rbp,
1889 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1890 ),
1891 origin: PredicateOrigin::WhereClause,
1892 })
1893 }
1894 WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
1895 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
1896 lifetime: self.lower_lifetime(
1897 lifetime,
1898 LifetimeSource::Other,
1899 lifetime.ident.into(),
1900 ),
1901 bounds: self.lower_param_bounds(
1902 bounds,
1903 RelaxedBoundPolicy::Allowed,
1904 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
1905 ),
1906 in_where_clause: true,
1907 })
1908 }
1909 WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => {
1910 hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
1911 lhs_ty: self
1912 .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
1913 rhs_ty: self
1914 .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
1915 })
1916 }
1917 });
1918 hir::WherePredicate { hir_id, span, kind }
1919 }
1920}