Critical: Use of 'unsafe' keyword bypasses Rust's safety guarantees. Requires careful auditing, clear justification (FFI, specific optimizations), and minimal scope.
EiiDecl { foreign_item, impl_unsafe }: &EiiDecl,
1use rustc_abi::ExternAbi;2use rustc_ast::visit::AssocCtxt;3use rustc_ast::*;4use rustc_data_structures::fx::FxIndexMap;5use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};6use rustc_hir::attrs::{AttributeKind, EiiImplResolution};7use rustc_hir::def::{DefKind, PerNS, Res};8use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};9use rustc_hir::{10 self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr,11};12use rustc_index::{IndexSlice, IndexVec};13use rustc_middle::span_bug;14use rustc_middle::ty::{ResolverAstLowering, TyCtxt};15use rustc_span::def_id::DefId;16use rustc_span::edit_distance::find_best_match_for_name;17use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};18use smallvec::{SmallVec, smallvec};19use thin_vec::ThinVec;20use tracing::instrument;2122use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};23use super::stability::{enabled_names, gate_unstable_abi};24use super::{25 AstOwner, FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext,26 ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,27};2829/// Wraps either IndexVec (during `hir_crate`), which acts like a primary30/// storage for most of the MaybeOwners, or FxIndexMap during delayed AST -> HIR31/// lowering of delegations (`lower_delayed_owner`),32/// in this case we can not modify already created IndexVec, so we use other map.33pub(super) enum Owners<'a, 'hir> {34 IndexVec(&'a mut IndexVec<LocalDefId, hir::MaybeOwner<'hir>>),35 Map(&'a mut FxIndexMap<LocalDefId, hir::MaybeOwner<'hir>>),36}3738impl<'hir> Owners<'_, 'hir> {39 fn get_or_insert_mut(&mut self, def_id: LocalDefId) -> &mut hir::MaybeOwner<'hir> {40 match self {41 Owners::IndexVec(index_vec) => {42 index_vec.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom)43 }44 Owners::Map(map) => map.entry(def_id).or_insert(hir::MaybeOwner::Phantom),45 }46 }47}4849pub(super) struct ItemLowerer<'a, 'hir> {50 pub(super) tcx: TyCtxt<'hir>,51 pub(super) resolver: &'a ResolverAstLowering<'hir>,52 pub(super) ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,53 pub(super) owners: Owners<'a, 'hir>,54}5556/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span57/// to the where clause that is preferred, if it exists. Otherwise, it sets the span to the other where58/// clause if it exists.59fn add_ty_alias_where_clause(60 generics: &mut ast::Generics,61 after_where_clause: &ast::WhereClause,62 prefer_first: bool,63) {64 generics.where_clause.predicates.extend_from_slice(&after_where_clause.predicates);6566 let mut before = (generics.where_clause.has_where_token, generics.where_clause.span);67 let mut after = (after_where_clause.has_where_token, after_where_clause.span);68 if !prefer_first {69 (before, after) = (after, before);70 }71 (generics.where_clause.has_where_token, generics.where_clause.span) =72 if before.0 || !after.0 { before } else { after };73}7475impl<'hir> ItemLowerer<'_, 'hir> {76 fn with_lctx(77 &mut self,78 owner: NodeId,79 f: impl for<'a> FnOnce(&mut LoweringContext<'a, 'hir>) -> hir::OwnerNode<'hir>,80 ) {81 let mut lctx = LoweringContext::new(self.tcx, self.resolver);82 lctx.with_hir_id_owner(owner, |lctx| f(lctx));8384 for (def_id, info) in lctx.children {85 let owner = self.owners.get_or_insert_mut(def_id);86 assert!(87 matches!(owner, hir::MaybeOwner::Phantom),88 "duplicate copy of {def_id:?} in lctx.children"89 );90 *owner = info;91 }92 }9394 pub(super) fn lower_node(&mut self, def_id: LocalDefId) {95 let owner = self.owners.get_or_insert_mut(def_id);96 if let hir::MaybeOwner::Phantom = owner {97 let node = self.ast_index[def_id];98 match node {99 AstOwner::NonOwner => {}100 AstOwner::Crate(c) => {101 assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID);102 self.with_lctx(CRATE_NODE_ID, |lctx| {103 let module = lctx.lower_mod(&c.items, &c.spans);104 // FIXME(jdonszelman): is dummy span ever a problem here?105 lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP, Target::Crate);106 hir::OwnerNode::Crate(module)107 })108 }109 AstOwner::Item(item) => {110 self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))111 }112 AstOwner::AssocItem(item, ctxt) => {113 self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))114 }115 AstOwner::ForeignItem(item) => self.with_lctx(item.id, |lctx| {116 hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))117 }),118 }119 }120 }121}122123impl<'hir> LoweringContext<'_, 'hir> {124 pub(super) fn lower_mod(125 &mut self,126 items: &[Box<Item>],127 spans: &ModSpans,128 ) -> &'hir hir::Mod<'hir> {129 self.arena.alloc(hir::Mod {130 spans: hir::ModSpans {131 inner_span: self.lower_span(spans.inner_span),132 inject_use_span: self.lower_span(spans.inject_use_span),133 },134 item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),135 })136 }137138 pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {139 let mut node_ids = smallvec![hir::ItemId { owner_id: self.owner_id(i.id) }];140 if let ItemKind::Use(use_tree) = &i.kind {141 self.lower_item_id_use_tree(use_tree, &mut node_ids);142 }143 node_ids144 }145146 fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) {147 match &tree.kind {148 UseTreeKind::Nested { items, .. } => {149 for &(ref nested, id) in items {150 vec.push(hir::ItemId { owner_id: self.owner_id(id) });151 self.lower_item_id_use_tree(nested, vec);152 }153 }154 UseTreeKind::Simple(..) | UseTreeKind::Glob(_) => {}155 }156 }157158 fn lower_eii_decl(159 &mut self,160 id: NodeId,161 name: Ident,162 EiiDecl { foreign_item, impl_unsafe }: &EiiDecl,163 ) -> Option<hir::attrs::EiiDecl> {164 self.lower_path_simple_eii(id, foreign_item).map(|did| hir::attrs::EiiDecl {165 foreign_item: did,166 impl_unsafe: *impl_unsafe,167 name,168 })169 }170171 fn lower_eii_impl(172 &mut self,173 EiiImpl {174 node_id,175 eii_macro_path,176 impl_safety,177 span,178 inner_span,179 is_default,180 known_eii_macro_resolution,181 }: &EiiImpl,182 ) -> hir::attrs::EiiImpl {183 let resolution = if let Some(target) = known_eii_macro_resolution184 && let Some(decl) = self.lower_eii_decl(185 *node_id,186 // the expect is ok here since we always generate this path in the eii macro.187 eii_macro_path.segments.last().expect("at least one segment").ident,188 target,189 ) {190 EiiImplResolution::Known(decl)191 } else if let Some(macro_did) = self.lower_path_simple_eii(*node_id, eii_macro_path) {192 EiiImplResolution::Macro(macro_did)193 } else {194 EiiImplResolution::Error(195 self.dcx().span_delayed_bug(*span, "eii never resolved without errors given"),196 )197 };198199 hir::attrs::EiiImpl {200 span: self.lower_span(*span),201 inner_span: self.lower_span(*inner_span),202 impl_marked_unsafe: self.lower_safety(*impl_safety, hir::Safety::Safe).is_unsafe(),203 is_default: *is_default,204 resolution,205 }206 }207208 fn generate_extra_attrs_for_item_kind(209 &mut self,210 id: NodeId,211 i: &ItemKind,212 ) -> Vec<hir::Attribute> {213 match i {214 ItemKind::Fn(Fn { eii_impls, .. }) | ItemKind::Static(StaticItem { eii_impls, .. })215 if eii_impls.is_empty() =>216 {217 Vec::new()218 }219 ItemKind::Fn(Fn { eii_impls, .. }) | ItemKind::Static(StaticItem { eii_impls, .. }) => {220 vec![hir::Attribute::Parsed(AttributeKind::EiiImpls(221 eii_impls.iter().map(|i| self.lower_eii_impl(i)).collect(),222 ))]223 }224 ItemKind::MacroDef(name, MacroDef { eii_declaration: Some(target), .. }) => self225 .lower_eii_decl(id, *name, target)226 .map(|decl| vec![hir::Attribute::Parsed(AttributeKind::EiiDeclaration(decl))])227 .unwrap_or_default(),228229 ItemKind::ExternCrate(..)230 | ItemKind::Use(..)231 | ItemKind::Const(..)232 | ItemKind::ConstBlock(..)233 | ItemKind::Mod(..)234 | ItemKind::ForeignMod(..)235 | ItemKind::GlobalAsm(..)236 | ItemKind::TyAlias(..)237 | ItemKind::Enum(..)238 | ItemKind::Struct(..)239 | ItemKind::Union(..)240 | ItemKind::Trait(..)241 | ItemKind::TraitAlias(..)242 | ItemKind::Impl(..)243 | ItemKind::MacCall(..)244 | ItemKind::MacroDef(..)245 | ItemKind::Delegation(..)246 | ItemKind::DelegationMac(..) => Vec::new(),247 }248 }249250 fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {251 let vis_span = self.lower_span(i.vis.span);252 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);253254 let extra_hir_attributes = self.generate_extra_attrs_for_item_kind(i.id, &i.kind);255 let attrs = self.lower_attrs_with_extra(256 hir_id,257 &i.attrs,258 i.span,259 Target::from_ast_item(i),260 &extra_hir_attributes,261 );262263 let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind);264 let item = hir::Item {265 owner_id: hir_id.expect_owner(),266 kind,267 vis_span,268 span: self.lower_span(i.span),269 has_delayed_lints: !self.delayed_lints.is_empty(),270 eii: find_attr!(attrs, EiiImpls(..) | EiiDeclaration(..)),271 };272 self.arena.alloc(item)273 }274275 fn lower_item_kind(276 &mut self,277 span: Span,278 id: NodeId,279 hir_id: hir::HirId,280 attrs: &'hir [hir::Attribute],281 vis_span: Span,282 i: &ItemKind,283 ) -> hir::ItemKind<'hir> {284 match i {285 ItemKind::ExternCrate(orig_name, ident) => {286 let ident = self.lower_ident(*ident);287 hir::ItemKind::ExternCrate(*orig_name, ident)288 }289 ItemKind::Use(use_tree) => {290 // Start with an empty prefix.291 let prefix = Path {292 segments: ThinVec::new(),293 span: use_tree.prefix.span.shrink_to_lo(),294 tokens: None,295 };296297 self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)298 }299 ItemKind::Static(ast::StaticItem {300 ident,301 ty,302 safety: _,303 mutability: m,304 expr: e,305 define_opaque,306 eii_impls: _,307 }) => {308 let ident = self.lower_ident(*ident);309 let ty = self310 .lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));311 let body_id = self.lower_const_body(span, e.as_deref());312 self.lower_define_opaque(hir_id, define_opaque);313 hir::ItemKind::Static(*m, ident, ty, body_id)314 }315 ItemKind::Const(ConstItem {316 defaultness: _,317 ident,318 generics,319 ty,320 rhs_kind,321 define_opaque,322 }) => {323 let ident = self.lower_ident(*ident);324 let (generics, (ty, rhs)) = self.lower_generics(325 generics,326 id,327 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),328 |this| {329 let ty = this.lower_ty_alloc(330 ty,331 ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),332 );333 let rhs = this.lower_const_item_rhs(rhs_kind, span);334 (ty, rhs)335 },336 );337 self.lower_define_opaque(hir_id, &define_opaque);338 hir::ItemKind::Const(ident, generics, ty, rhs)339 }340 ItemKind::ConstBlock(ConstBlockItem { span, id, block }) => hir::ItemKind::Const(341 self.lower_ident(ConstBlockItem::IDENT),342 hir::Generics::empty(),343 self.arena.alloc(self.ty_tup(DUMMY_SP, &[])),344 hir::ConstItemRhs::Body({345 let body = hir::Expr {346 hir_id: self.lower_node_id(*id),347 kind: hir::ExprKind::Block(self.lower_block(block, false), None),348 span: self.lower_span(*span),349 };350 self.record_body(&[], body)351 }),352 ),353 ItemKind::Fn(Fn {354 sig: FnSig { decl, header, span: fn_sig_span },355 ident,356 generics,357 body,358 contract,359 define_opaque,360 ..361 }) => {362 self.with_new_scopes(*fn_sig_span, |this| {363 // Note: we don't need to change the return type from `T` to364 // `impl Future<Output = T>` here because lower_body365 // only cares about the input argument patterns in the function366 // declaration (decl), not the return types.367 let coroutine_kind = header.coroutine_kind;368 let body_id = this.lower_maybe_coroutine_body(369 *fn_sig_span,370 span,371 hir_id,372 decl,373 coroutine_kind,374 body.as_deref(),375 attrs,376 contract.as_deref(),377 );378379 let itctx = ImplTraitContext::Universal;380 let (generics, decl) = this.lower_generics(generics, id, itctx, |this| {381 this.lower_fn_decl(decl, id, *fn_sig_span, FnDeclKind::Fn, coroutine_kind)382 });383 let sig = hir::FnSig {384 decl,385 header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),386 span: this.lower_span(*fn_sig_span),387 };388 this.lower_define_opaque(hir_id, define_opaque);389 let ident = this.lower_ident(*ident);390 hir::ItemKind::Fn {391 ident,392 sig,393 generics,394 body: body_id,395 has_body: body.is_some(),396 }397 })398 }399 ItemKind::Mod(_, ident, mod_kind) => {400 let ident = self.lower_ident(*ident);401 match mod_kind {402 ModKind::Loaded(items, _, spans) => {403 hir::ItemKind::Mod(ident, self.lower_mod(items, spans))404 }405 ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),406 }407 }408 ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod {409 abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)),410 items: self411 .arena412 .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),413 },414 ItemKind::GlobalAsm(asm) => {415 let asm = self.lower_inline_asm(span, asm);416 let fake_body =417 self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));418 hir::ItemKind::GlobalAsm { asm, fake_body }419 }420 ItemKind::TyAlias(TyAlias { ident, generics, after_where_clause, ty, .. }) => {421 // We lower422 //423 // type Foo = impl Trait424 //425 // to426 //427 // type Foo = Foo1428 // opaque type Foo1: Trait429 let ident = self.lower_ident(*ident);430 let mut generics = generics.clone();431 add_ty_alias_where_clause(&mut generics, after_where_clause, true);432 let (generics, ty) = self.lower_generics(433 &generics,434 id,435 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),436 |this| match ty {437 None => {438 let guar = this.dcx().span_delayed_bug(439 span,440 "expected to lower type alias type, but it was missing",441 );442 this.arena.alloc(this.ty(span, hir::TyKind::Err(guar)))443 }444 Some(ty) => this.lower_ty_alloc(445 ty,446 ImplTraitContext::OpaqueTy {447 origin: hir::OpaqueTyOrigin::TyAlias {448 parent: this.local_def_id(id),449 in_assoc_ty: false,450 },451 },452 ),453 },454 );455 hir::ItemKind::TyAlias(ident, generics, ty)456 }457 ItemKind::Enum(ident, generics, enum_definition) => {458 let ident = self.lower_ident(*ident);459 let (generics, variants) = self.lower_generics(460 generics,461 id,462 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),463 |this| {464 this.arena.alloc_from_iter(465 enum_definition.variants.iter().map(|x| this.lower_variant(i, x)),466 )467 },468 );469 hir::ItemKind::Enum(ident, generics, hir::EnumDef { variants })470 }471 ItemKind::Struct(ident, generics, struct_def) => {472 let ident = self.lower_ident(*ident);473 let (generics, struct_def) = self.lower_generics(474 generics,475 id,476 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),477 |this| this.lower_variant_data(hir_id, i, struct_def),478 );479 hir::ItemKind::Struct(ident, generics, struct_def)480 }481 ItemKind::Union(ident, generics, vdata) => {482 let ident = self.lower_ident(*ident);483 let (generics, vdata) = self.lower_generics(484 generics,485 id,486 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),487 |this| this.lower_variant_data(hir_id, i, vdata),488 );489 hir::ItemKind::Union(ident, generics, vdata)490 }491 ItemKind::Impl(Impl {492 generics: ast_generics,493 of_trait,494 self_ty: ty,495 items: impl_items,496 constness,497 }) => {498 // Lower the "impl header" first. This ordering is important499 // for in-band lifetimes! Consider `'a` here:500 //501 // impl Foo<'a> for u32 {502 // fn method(&'a self) { .. }503 // }504 //505 // Because we start by lowering the `Foo<'a> for u32`506 // part, we will add `'a` to the list of generics on507 // the impl. When we then encounter it later in the508 // method, it will not be considered an in-band509 // lifetime to be added, but rather a reference to a510 // parent lifetime.511 let itctx = ImplTraitContext::Universal;512 let (generics, (of_trait, lowered_ty)) =513 self.lower_generics(ast_generics, id, itctx, |this| {514 let of_trait = of_trait515 .as_deref()516 .map(|of_trait| this.lower_trait_impl_header(of_trait));517518 let lowered_ty = this.lower_ty_alloc(519 ty,520 ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),521 );522523 (of_trait, lowered_ty)524 });525526 let new_impl_items = self527 .arena528 .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));529530 let constness = self.lower_constness(*constness);531532 hir::ItemKind::Impl(hir::Impl {533 generics,534 of_trait,535 self_ty: lowered_ty,536 items: new_impl_items,537 constness,538 })539 }540 ItemKind::Trait(Trait {541 impl_restriction,542 constness,543 is_auto,544 safety,545 ident,546 generics,547 bounds,548 items,549 }) => {550 let constness = self.lower_constness(*constness);551 let impl_restriction = self.lower_impl_restriction(impl_restriction);552 let ident = self.lower_ident(*ident);553 let (generics, (safety, items, bounds)) = self.lower_generics(554 generics,555 id,556 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),557 |this| {558 let bounds = this.lower_param_bounds(559 bounds,560 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),561 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),562 );563 let items = this.arena.alloc_from_iter(564 items.iter().map(|item| this.lower_trait_item_ref(item)),565 );566 let safety = this.lower_safety(*safety, hir::Safety::Safe);567 (safety, items, bounds)568 },569 );570 hir::ItemKind::Trait {571 impl_restriction,572 constness,573 is_auto: *is_auto,574 safety,575 ident,576 generics,577 bounds,578 items,579 }580 }581 ItemKind::TraitAlias(TraitAlias { constness, ident, generics, bounds }) => {582 let constness = self.lower_constness(*constness);583 let ident = self.lower_ident(*ident);584 let (generics, bounds) = self.lower_generics(585 generics,586 id,587 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),588 |this| {589 this.lower_param_bounds(590 bounds,591 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitAlias),592 ImplTraitContext::Disallowed(ImplTraitPosition::Bound),593 )594 },595 );596 hir::ItemKind::TraitAlias(constness, ident, generics, bounds)597 }598 ItemKind::MacroDef(ident, MacroDef { body, macro_rules, eii_declaration: _ }) => {599 let ident = self.lower_ident(*ident);600 let body = Box::new(self.lower_delim_args(body));601 let def_id = self.local_def_id(id);602 let def_kind = self.tcx.def_kind(def_id);603 let DefKind::Macro(macro_kinds) = def_kind else {604 unreachable!(605 "expected DefKind::Macro for macro item, found {}",606 def_kind.descr(def_id.to_def_id())607 );608 };609 let macro_def = self.arena.alloc(ast::MacroDef {610 body,611 macro_rules: *macro_rules,612 eii_declaration: None,613 });614 hir::ItemKind::Macro(ident, macro_def, macro_kinds)615 }616 ItemKind::Delegation(delegation) => {617 let delegation_results = self.lower_delegation(delegation, id);618 hir::ItemKind::Fn {619 sig: delegation_results.sig,620 ident: delegation_results.ident,621 generics: delegation_results.generics,622 body: delegation_results.body_id,623 has_body: true,624 }625 }626 ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {627 panic!("macros should have been expanded by now")628 }629 }630 }631632 fn lower_path_simple_eii(&mut self, id: NodeId, path: &Path) -> Option<DefId> {633 let res = self.get_partial_res(id)?;634 let Some(did) = res.expect_full_res().opt_def_id() else {635 self.dcx().span_delayed_bug(path.span, "should have errored in resolve");636 return None;637 };638639 Some(did)640 }641642 #[instrument(level = "debug", skip(self))]643 fn lower_use_tree(644 &mut self,645 tree: &UseTree,646 prefix: &Path,647 id: NodeId,648 vis_span: Span,649 attrs: &'hir [hir::Attribute],650 ) -> hir::ItemKind<'hir> {651 let path = &tree.prefix;652 let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();653654 match tree.kind {655 UseTreeKind::Simple(rename) => {656 let mut ident = tree.ident();657658 // First, apply the prefix to the path.659 let mut path = Path { segments, span: path.span, tokens: None };660661 // Correctly resolve `self` imports.662 if path.segments.len() > 1663 && path.segments.last().unwrap().ident.name == kw::SelfLower664 {665 let _ = path.segments.pop();666 if rename.is_none() {667 ident = path.segments.last().unwrap().ident;668 }669 }670671 let res = self.lower_import_res(id, path.span);672 let path = self.lower_use_path(res, &path, ParamMode::Explicit);673 let ident = self.lower_ident(ident);674 hir::ItemKind::Use(path, hir::UseKind::Single(ident))675 }676 UseTreeKind::Glob(_) => {677 let res = self.expect_full_res(id);678 let res = self.lower_res(res);679 // Put the result in the appropriate namespace.680 let res = match res {681 Res::Def(DefKind::Mod | DefKind::Trait, _) => {682 PerNS { type_ns: Some(res), value_ns: None, macro_ns: None }683 }684 Res::Def(DefKind::Enum, _) => {685 PerNS { type_ns: None, value_ns: Some(res), macro_ns: None }686 }687 Res::Err => {688 // Propagate the error to all namespaces, just to be sure.689 let err = Some(Res::Err);690 PerNS { type_ns: err, value_ns: err, macro_ns: err }691 }692 _ => span_bug!(path.span, "bad glob res {:?}", res),693 };694 let path = Path { segments, span: path.span, tokens: None };695 let path = self.lower_use_path(res, &path, ParamMode::Explicit);696 hir::ItemKind::Use(path, hir::UseKind::Glob)697 }698 UseTreeKind::Nested { items: ref trees, .. } => {699 // Nested imports are desugared into simple imports.700 // So, if we start with701 //702 // ```703 // pub(x) use foo::{a, b};704 // ```705 //706 // we will create three items:707 //708 // ```709 // pub(x) use foo::a;710 // pub(x) use foo::b;711 // pub(x) use foo::{}; // <-- this is called the `ListStem`712 // ```713 //714 // The first two are produced by recursively invoking715 // `lower_use_tree` (and indeed there may be things716 // like `use foo::{a::{b, c}}` and so forth). They717 // wind up being directly added to718 // `self.items`. However, the structure of this719 // function also requires us to return one item, and720 // for that we return the `{}` import (called the721 // `ListStem`).722723 let span = prefix.span.to(path.span);724 let prefix = Path { segments, span, tokens: None };725726 // Add all the nested `PathListItem`s to the HIR.727 for &(ref use_tree, id) in trees {728 let owner_id = self.owner_id(id);729730 // Each `use` import is an item and thus are owners of the731 // names in the path. Up to this point the nested import is732 // the current owner, since we want each desugared import to733 // own its own names, we have to adjust the owner before734 // lowering the rest of the import.735 self.with_hir_id_owner(id, |this| {736 // `prefix` is lowered multiple times, but in different HIR owners.737 // So each segment gets renewed `HirId` with the same738 // `ItemLocalId` and the new owner. (See `lower_node_id`)739 let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, attrs);740 if !attrs.is_empty() {741 this.attrs.insert(hir::ItemLocalId::ZERO, attrs);742 }743744 let item = hir::Item {745 owner_id,746 kind,747 vis_span,748 span: this.lower_span(use_tree.span()),749 has_delayed_lints: !this.delayed_lints.is_empty(),750 eii: find_attr!(attrs, EiiImpls(..) | EiiDeclaration(..)),751 };752 hir::OwnerNode::Item(this.arena.alloc(item))753 });754 }755756 // Condition should match `build_reduced_graph_for_use_tree`.757 let path = if trees.is_empty()758 && !(prefix.segments.is_empty()759 || prefix.segments.len() == 1760 && prefix.segments[0].ident.name == kw::PathRoot)761 {762 // For empty lists we need to lower the prefix so it is checked for things763 // like stability later.764 let res = self.lower_import_res(id, span);765 self.lower_use_path(res, &prefix, ParamMode::Explicit)766 } else {767 // For non-empty lists we can just drop all the data, the prefix is already768 // present in HIR as a part of nested imports.769 let span = self.lower_span(span);770 self.arena.alloc(hir::UsePath { res: PerNS::default(), segments: &[], span })771 };772 hir::ItemKind::Use(path, hir::UseKind::ListStem)773 }774 }775 }776777 fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) -> hir::OwnerNode<'hir> {778 // Evaluate with the lifetimes in `params` in-scope.779 // This is used to track which lifetimes have already been defined,780 // and which need to be replicated when lowering an async fn.781 match ctxt {782 AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),783 AssocCtxt::Impl { of_trait } => {784 hir::OwnerNode::ImplItem(self.lower_impl_item(item, of_trait))785 }786 }787 }788789 fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {790 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);791 let owner_id = hir_id.expect_owner();792 let attrs =793 self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_foreign_item_kind(&i.kind));794 let (ident, kind) = match &i.kind {795 ForeignItemKind::Fn(Fn { sig, ident, generics, define_opaque, .. }) => {796 let fdec = &sig.decl;797 let itctx = ImplTraitContext::Universal;798 let (generics, (decl, fn_args)) =799 self.lower_generics(generics, i.id, itctx, |this| {800 (801 // Disallow `impl Trait` in foreign items.802 this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None),803 this.lower_fn_params_to_idents(fdec),804 )805 });806807 // Unmarked safety in unsafe block defaults to unsafe.808 let header = self.lower_fn_header(sig.header, hir::Safety::Unsafe, attrs);809810 if define_opaque.is_some() {811 self.dcx().span_err(i.span, "foreign functions cannot define opaque types");812 }813814 (815 ident,816 hir::ForeignItemKind::Fn(817 hir::FnSig { header, decl, span: self.lower_span(sig.span) },818 fn_args,819 generics,820 ),821 )822 }823 ForeignItemKind::Static(StaticItem {824 ident,825 ty,826 mutability,827 expr: _,828 safety,829 define_opaque,830 eii_impls: _,831 }) => {832 let ty = self833 .lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));834 let safety = self.lower_safety(*safety, hir::Safety::Unsafe);835 if define_opaque.is_some() {836 self.dcx().span_err(i.span, "foreign statics cannot define opaque types");837 }838 (ident, hir::ForeignItemKind::Static(ty, *mutability, safety))839 }840 ForeignItemKind::TyAlias(TyAlias { ident, .. }) => (ident, hir::ForeignItemKind::Type),841 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),842 };843844 let item = hir::ForeignItem {845 owner_id,846 ident: self.lower_ident(*ident),847 kind,848 vis_span: self.lower_span(i.vis.span),849 span: self.lower_span(i.span),850 has_delayed_lints: !self.delayed_lints.is_empty(),851 };852 self.arena.alloc(item)853 }854855 fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemId {856 hir::ForeignItemId { owner_id: self.owner_id(i.id) }857 }858859 fn lower_variant(&mut self, item_kind: &ItemKind, v: &Variant) -> hir::Variant<'hir> {860 let hir_id = self.lower_node_id(v.id);861 self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant);862 hir::Variant {863 hir_id,864 def_id: self.local_def_id(v.id),865 data: self.lower_variant_data(hir_id, item_kind, &v.data),866 disr_expr: v867 .disr_expr868 .as_ref()869 .map(|e| self.lower_anon_const_to_anon_const(e, e.value.span)),870 ident: self.lower_ident(v.ident),871 span: self.lower_span(v.span),872 }873 }874875 fn lower_variant_data(876 &mut self,877 parent_id: hir::HirId,878 item_kind: &ItemKind,879 vdata: &VariantData,880 ) -> hir::VariantData<'hir> {881 match vdata {882 VariantData::Struct { fields, recovered } => {883 let fields = self884 .arena885 .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f)));886887 if let ItemKind::Union(..) = item_kind {888 for field in &fields[..] {889 if let Some(default) = field.default {890 // Unions cannot derive `Default`, and it's not clear how to use default891 // field values of unions if that was supported. Therefore, blanket reject892 // trying to use field values with unions.893 if self.tcx.features().default_field_values() {894 self.dcx().emit_err(UnionWithDefault { span: default.span });895 } else {896 let _ = self.dcx().span_delayed_bug(897 default.span,898 "expected union default field values feature gate error but none \899 was produced",900 );901 }902 }903 }904 }905906 hir::VariantData::Struct { fields, recovered: *recovered }907 }908 VariantData::Tuple(fields, id) => {909 let ctor_id = self.lower_node_id(*id);910 self.alias_attrs(ctor_id, parent_id);911 let fields = self912 .arena913 .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f)));914 for field in &fields[..] {915 if let Some(default) = field.default {916 // Default values in tuple struct and tuple variants are not allowed by the917 // RFC due to concerns about the syntax, both in the item definition and the918 // expression. We could in the future allow `struct S(i32 = 0);` and force919 // users to construct the value with `let _ = S { .. };`.920 if self.tcx.features().default_field_values() {921 self.dcx().emit_err(TupleStructWithDefault { span: default.span });922 } else {923 let _ = self.dcx().span_delayed_bug(924 default.span,925 "expected `default values on `struct` fields aren't supported` \926 feature-gate error but none was produced",927 );928 }929 }930 }931 hir::VariantData::Tuple(fields, ctor_id, self.local_def_id(*id))932 }933 VariantData::Unit(id) => {934 let ctor_id = self.lower_node_id(*id);935 self.alias_attrs(ctor_id, parent_id);936 hir::VariantData::Unit(ctor_id, self.local_def_id(*id))937 }938 }939 }940941 pub(super) fn lower_field_def(942 &mut self,943 (index, f): (usize, &FieldDef),944 ) -> hir::FieldDef<'hir> {945 let ty =946 self.lower_ty_alloc(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy));947 let hir_id = self.lower_node_id(f.id);948 self.lower_attrs(hir_id, &f.attrs, f.span, Target::Field);949 hir::FieldDef {950 span: self.lower_span(f.span),951 hir_id,952 def_id: self.local_def_id(f.id),953 ident: match f.ident {954 Some(ident) => self.lower_ident(ident),955 // FIXME(jseyfried): positional field hygiene.956 None => Ident::new(sym::integer(index), self.lower_span(f.span)),957 },958 vis_span: self.lower_span(f.vis.span),959 default: f960 .default961 .as_ref()962 .map(|v| self.lower_anon_const_to_anon_const(v, v.value.span)),963 ty,964 safety: self.lower_safety(f.safety, hir::Safety::Safe),965 }966 }967968 fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {969 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);970 let attrs = self.lower_attrs(971 hir_id,972 &i.attrs,973 i.span,974 Target::from_assoc_item_kind(&i.kind, AssocCtxt::Trait),975 );976 let trait_item_def_id = hir_id.expect_owner();977978 let (ident, generics, kind, has_value) = match &i.kind {979 AssocItemKind::Const(ConstItem {980 ident,981 generics,982 ty,983 rhs_kind,984 define_opaque,985 ..986 }) => {987 let (generics, kind) = self.lower_generics(988 generics,989 i.id,990 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),991 |this| {992 let ty = this.lower_ty_alloc(993 ty,994 ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),995 );996 // Trait associated consts don't need an expression/body.997 let rhs = if rhs_kind.has_expr() {998 Some(this.lower_const_item_rhs(rhs_kind, i.span))999 } else {1000 None1001 };1002 hir::TraitItemKind::Const(ty, rhs, rhs_kind.is_type_const().into())1003 },1004 );10051006 if define_opaque.is_some() {1007 if rhs_kind.has_expr() {1008 self.lower_define_opaque(hir_id, &define_opaque);1009 } else {1010 self.dcx().span_err(1011 i.span,1012 "only trait consts with default bodies can define opaque types",1013 );1014 }1015 }10161017 (*ident, generics, kind, rhs_kind.has_expr())1018 }1019 AssocItemKind::Fn(Fn { sig, ident, generics, body: None, define_opaque, .. }) => {1020 // FIXME(contracts): Deny contract here since it won't apply to1021 // any impl method or callees.1022 let idents = self.lower_fn_params_to_idents(&sig.decl);1023 let (generics, sig) = self.lower_method_sig(1024 generics,1025 sig,1026 i.id,1027 FnDeclKind::Trait,1028 sig.header.coroutine_kind,1029 attrs,1030 );1031 if define_opaque.is_some() {1032 self.dcx().span_err(1033 i.span,1034 "only trait methods with default bodies can define opaque types",1035 );1036 }1037 (1038 *ident,1039 generics,1040 hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(idents)),1041 false,1042 )1043 }1044 AssocItemKind::Fn(Fn {1045 sig,1046 ident,1047 generics,1048 body: Some(body),1049 contract,1050 define_opaque,1051 ..1052 }) => {1053 let body_id = self.lower_maybe_coroutine_body(1054 sig.span,1055 i.span,1056 hir_id,1057 &sig.decl,1058 sig.header.coroutine_kind,1059 Some(body),1060 attrs,1061 contract.as_deref(),1062 );1063 let (generics, sig) = self.lower_method_sig(1064 generics,1065 sig,1066 i.id,1067 FnDeclKind::Trait,1068 sig.header.coroutine_kind,1069 attrs,1070 );1071 self.lower_define_opaque(hir_id, &define_opaque);1072 (1073 *ident,1074 generics,1075 hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)),1076 true,1077 )1078 }1079 AssocItemKind::Type(TyAlias {1080 ident,1081 generics,1082 after_where_clause,1083 bounds,1084 ty,1085 ..1086 }) => {1087 let mut generics = generics.clone();1088 add_ty_alias_where_clause(&mut generics, after_where_clause, false);1089 let (generics, kind) = self.lower_generics(1090 &generics,1091 i.id,1092 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),1093 |this| {1094 let ty = ty.as_ref().map(|x| {1095 this.lower_ty_alloc(1096 x,1097 ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),1098 )1099 });1100 hir::TraitItemKind::Type(1101 this.lower_param_bounds(1102 bounds,1103 RelaxedBoundPolicy::Allowed,1104 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),1105 ),1106 ty,1107 )1108 },1109 );1110 (*ident, generics, kind, ty.is_some())1111 }1112 AssocItemKind::Delegation(delegation) => {1113 let delegation_results = self.lower_delegation(delegation, i.id);1114 let item_kind = hir::TraitItemKind::Fn(1115 delegation_results.sig,1116 hir::TraitFn::Provided(delegation_results.body_id),1117 );1118 (delegation.ident, delegation_results.generics, item_kind, true)1119 }1120 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {1121 panic!("macros should have been expanded by now")1122 }1123 };11241125 let defaultness = match i.kind.defaultness() {1126 // We do not yet support `final` on trait associated items other than functions.1127 // Even though we reject `final` on non-functions during AST validation, we still1128 // need to stop propagating it here because later compiler passes do not expect1129 // and cannot handle such items.1130 Defaultness::Final(..) if !matches!(i.kind, AssocItemKind::Fn(..)) => {1131 Defaultness::Implicit1132 }1133 defaultness => defaultness,1134 };1135 let (defaultness, _) = self1136 .lower_defaultness(defaultness, has_value, || hir::Defaultness::Default { has_value });11371138 let item = hir::TraitItem {1139 owner_id: trait_item_def_id,1140 ident: self.lower_ident(ident),1141 generics,1142 kind,1143 span: self.lower_span(i.span),1144 defaultness,1145 has_delayed_lints: !self.delayed_lints.is_empty(),1146 };1147 self.arena.alloc(item)1148 }11491150 fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemId {1151 hir::TraitItemId { owner_id: self.owner_id(i.id) }1152 }11531154 /// Construct `ExprKind::Err` for the given `span`.1155 pub(crate) fn expr_err(&mut self, span: Span, guar: ErrorGuaranteed) -> hir::Expr<'hir> {1156 self.expr(span, hir::ExprKind::Err(guar))1157 }11581159 fn lower_trait_impl_header(1160 &mut self,1161 trait_impl_header: &TraitImplHeader,1162 ) -> &'hir hir::TraitImplHeader<'hir> {1163 let TraitImplHeader { safety, polarity, defaultness, ref trait_ref } = *trait_impl_header;1164 let safety = self.lower_safety(safety, hir::Safety::Safe);1165 let polarity = match polarity {1166 ImplPolarity::Positive => ImplPolarity::Positive,1167 ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),1168 };1169 // `defaultness.has_value()` is never called for an `impl`, always `true` in order1170 // to not cause an assertion failure inside the `lower_defaultness` function.1171 let has_val = true;1172 let (defaultness, defaultness_span) =1173 self.lower_defaultness(defaultness, has_val, || hir::Defaultness::Final);1174 let modifiers = TraitBoundModifiers {1175 constness: BoundConstness::Never,1176 asyncness: BoundAsyncness::Normal,1177 // we don't use this in bound lowering1178 polarity: BoundPolarity::Positive,1179 };1180 let trait_ref = self.lower_trait_ref(1181 modifiers,1182 trait_ref,1183 ImplTraitContext::Disallowed(ImplTraitPosition::Trait),1184 );11851186 self.arena.alloc(hir::TraitImplHeader {1187 safety,1188 polarity,1189 defaultness,1190 defaultness_span,1191 trait_ref,1192 })1193 }11941195 fn lower_impl_item(1196 &mut self,1197 i: &AssocItem,1198 is_in_trait_impl: bool,1199 ) -> &'hir hir::ImplItem<'hir> {1200 // Since `default impl` is not yet implemented, this is always true in impls.1201 let has_value = true;1202 let (defaultness, _) =1203 self.lower_defaultness(i.kind.defaultness(), has_value, || hir::Defaultness::Final);1204 let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id);1205 let attrs = self.lower_attrs(1206 hir_id,1207 &i.attrs,1208 i.span,1209 Target::from_assoc_item_kind(&i.kind, AssocCtxt::Impl { of_trait: is_in_trait_impl }),1210 );12111212 let (ident, (generics, kind)) = match &i.kind {1213 AssocItemKind::Const(ConstItem {1214 ident,1215 generics,1216 ty,1217 rhs_kind,1218 define_opaque,1219 ..1220 }) => (1221 *ident,1222 self.lower_generics(1223 generics,1224 i.id,1225 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),1226 |this| {1227 let ty = this.lower_ty_alloc(1228 ty,1229 ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),1230 );1231 this.lower_define_opaque(hir_id, &define_opaque);1232 let rhs = this.lower_const_item_rhs(rhs_kind, i.span);1233 hir::ImplItemKind::Const(ty, rhs)1234 },1235 ),1236 ),1237 AssocItemKind::Fn(Fn {1238 sig, ident, generics, body, contract, define_opaque, ..1239 }) => {1240 let body_id = self.lower_maybe_coroutine_body(1241 sig.span,1242 i.span,1243 hir_id,1244 &sig.decl,1245 sig.header.coroutine_kind,1246 body.as_deref(),1247 attrs,1248 contract.as_deref(),1249 );1250 let (generics, sig) = self.lower_method_sig(1251 generics,1252 sig,1253 i.id,1254 if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },1255 sig.header.coroutine_kind,1256 attrs,1257 );1258 self.lower_define_opaque(hir_id, &define_opaque);12591260 (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id)))1261 }1262 AssocItemKind::Type(TyAlias { ident, generics, after_where_clause, ty, .. }) => {1263 let mut generics = generics.clone();1264 add_ty_alias_where_clause(&mut generics, after_where_clause, false);1265 (1266 *ident,1267 self.lower_generics(1268 &generics,1269 i.id,1270 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),1271 |this| match ty {1272 None => {1273 let guar = this.dcx().span_delayed_bug(1274 i.span,1275 "expected to lower associated type, but it was missing",1276 );1277 let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err(guar)));1278 hir::ImplItemKind::Type(ty)1279 }1280 Some(ty) => {1281 let ty = this.lower_ty_alloc(1282 ty,1283 ImplTraitContext::OpaqueTy {1284 origin: hir::OpaqueTyOrigin::TyAlias {1285 parent: this.local_def_id(i.id),1286 in_assoc_ty: true,1287 },1288 },1289 );1290 hir::ImplItemKind::Type(ty)1291 }1292 },1293 ),1294 )1295 }1296 AssocItemKind::Delegation(delegation) => {1297 let delegation_results = self.lower_delegation(delegation, i.id);1298 (1299 delegation.ident,1300 (1301 delegation_results.generics,1302 hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id),1303 ),1304 )1305 }1306 AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {1307 panic!("macros should have been expanded by now")1308 }1309 };13101311 let span = self.lower_span(i.span);1312 let item = hir::ImplItem {1313 owner_id: hir_id.expect_owner(),1314 ident: self.lower_ident(ident),1315 generics,1316 impl_kind: if is_in_trait_impl {1317 ImplItemImplKind::Trait {1318 defaultness,1319 trait_item_def_id: self1320 .get_partial_res(i.id)1321 .and_then(|r| r.expect_full_res().opt_def_id())1322 .ok_or_else(|| {1323 self.dcx().span_delayed_bug(1324 span,1325 "could not resolve trait item being implemented",1326 )1327 }),1328 }1329 } else {1330 ImplItemImplKind::Inherent { vis_span: self.lower_span(i.vis.span) }1331 },1332 kind,1333 span,1334 has_delayed_lints: !self.delayed_lints.is_empty(),1335 };1336 self.arena.alloc(item)1337 }13381339 fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemId {1340 hir::ImplItemId { owner_id: self.owner_id(i.id) }1341 }13421343 fn lower_defaultness(1344 &self,1345 d: Defaultness,1346 has_value: bool,1347 implicit: impl FnOnce() -> hir::Defaultness,1348 ) -> (hir::Defaultness, Option<Span>) {1349 match d {1350 Defaultness::Implicit => (implicit(), None),1351 Defaultness::Default(sp) => {1352 (hir::Defaultness::Default { has_value }, Some(self.lower_span(sp)))1353 }1354 Defaultness::Final(sp) => (hir::Defaultness::Final, Some(self.lower_span(sp))),1355 }1356 }13571358 fn record_body(1359 &mut self,1360 params: &'hir [hir::Param<'hir>],1361 value: hir::Expr<'hir>,1362 ) -> hir::BodyId {1363 let body = hir::Body { params, value: self.arena.alloc(value) };1364 let id = body.id();1365 assert_eq!(id.hir_id.owner, self.current_hir_id_owner);1366 self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));1367 id1368 }13691370 pub(super) fn lower_body(1371 &mut self,1372 f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),1373 ) -> hir::BodyId {1374 let prev_coroutine_kind = self.coroutine_kind.take();1375 let task_context = self.task_context.take();1376 let (parameters, result) = f(self);1377 let body_id = self.record_body(parameters, result);1378 self.task_context = task_context;1379 self.coroutine_kind = prev_coroutine_kind;1380 body_id1381 }13821383 fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {1384 let hir_id = self.lower_node_id(param.id);1385 self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::Param);1386 hir::Param {1387 hir_id,1388 pat: self.lower_pat(¶m.pat),1389 ty_span: self.lower_span(param.ty.span),1390 span: self.lower_span(param.span),1391 }1392 }13931394 pub(super) fn lower_fn_body(1395 &mut self,1396 decl: &FnDecl,1397 contract: Option<&FnContract>,1398 body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,1399 ) -> hir::BodyId {1400 self.lower_body(|this| {1401 let params =1402 this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x)));14031404 // Optionally lower the fn contract1405 if let Some(contract) = contract {1406 (params, this.lower_contract(body, contract))1407 } else {1408 (params, body(this))1409 }1410 })1411 }14121413 fn lower_fn_body_block(1414 &mut self,1415 decl: &FnDecl,1416 body: &Block,1417 contract: Option<&FnContract>,1418 ) -> hir::BodyId {1419 self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body))1420 }14211422 pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {1423 self.lower_body(|this| {1424 (1425 &[],1426 match expr {1427 Some(expr) => this.lower_expr_mut(expr),1428 None => this.expr_err(span, this.dcx().span_delayed_bug(span, "no block")),1429 },1430 )1431 })1432 }14331434 /// Takes what may be the body of an `async fn` or a `gen fn` and wraps it in an `async {}` or1435 /// `gen {}` block as appropriate.1436 fn lower_maybe_coroutine_body(1437 &mut self,1438 fn_decl_span: Span,1439 span: Span,1440 fn_id: hir::HirId,1441 decl: &FnDecl,1442 coroutine_kind: Option<CoroutineKind>,1443 body: Option<&Block>,1444 attrs: &'hir [hir::Attribute],1445 contract: Option<&FnContract>,1446 ) -> hir::BodyId {1447 let Some(body) = body else {1448 // Functions without a body are an error, except if this is an intrinsic. For those we1449 // create a fake body so that the entire rest of the compiler doesn't have to deal with1450 // this as a special case.1451 return self.lower_fn_body(decl, contract, |this| {1452 if find_attr!(attrs, RustcIntrinsic) || this.tcx.is_sdylib_interface_build() {1453 let span = this.lower_span(span);1454 let empty_block = hir::Block {1455 hir_id: this.next_id(),1456 stmts: &[],1457 expr: None,1458 rules: hir::BlockCheckMode::DefaultBlock,1459 span,1460 targeted_by_break: false,1461 };1462 let loop_ = hir::ExprKind::Loop(1463 this.arena.alloc(empty_block),1464 None,1465 hir::LoopSource::Loop,1466 span,1467 );1468 hir::Expr { hir_id: this.next_id(), kind: loop_, span }1469 } else {1470 this.expr_err(span, this.dcx().has_errors().unwrap())1471 }1472 });1473 };1474 let Some(coroutine_kind) = coroutine_kind else {1475 // Typical case: not a coroutine.1476 return self.lower_fn_body_block(decl, body, contract);1477 };1478 // FIXME(contracts): Support contracts on async fn.1479 self.lower_body(|this| {1480 let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(1481 decl,1482 |this| this.lower_block_expr(body),1483 fn_decl_span,1484 body.span,1485 coroutine_kind,1486 hir::CoroutineSource::Fn,1487 );14881489 // FIXME(async_fn_track_caller): Can this be moved above?1490 let hir_id = expr.hir_id;1491 this.maybe_forward_track_caller(body.span, fn_id, hir_id);14921493 (parameters, expr)1494 })1495 }14961497 /// Lowers a desugared coroutine body after moving all of the arguments1498 /// into the body. This is to make sure that the future actually owns the1499 /// arguments that are passed to the function, and to ensure things like1500 /// drop order are stable.1501 pub(crate) fn lower_coroutine_body_with_moved_arguments(1502 &mut self,1503 decl: &FnDecl,1504 lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,1505 fn_decl_span: Span,1506 body_span: Span,1507 coroutine_kind: CoroutineKind,1508 coroutine_source: hir::CoroutineSource,1509 ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {1510 let mut parameters: Vec<hir::Param<'_>> = Vec::new();1511 let mut statements: Vec<hir::Stmt<'_>> = Vec::new();15121513 // Async function parameters are lowered into the closure body so that they are1514 // captured and so that the drop order matches the equivalent non-async functions.1515 //1516 // from:1517 //1518 // async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {1519 // <body>1520 // }1521 //1522 // into:1523 //1524 // fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {1525 // async move {1526 // let __arg2 = __arg2;1527 // let <pattern> = __arg2;1528 // let __arg1 = __arg1;1529 // let <pattern> = __arg1;1530 // let __arg0 = __arg0;1531 // let <pattern> = __arg0;1532 // drop-temps { <body> } // see comments later in fn for details1533 // }1534 // }1535 //1536 // If `<pattern>` is a simple ident, then it is lowered to a single1537 // `let <pattern> = <pattern>;` statement as an optimization.1538 //1539 // Note that the body is embedded in `drop-temps`; an1540 // equivalent desugaring would be `return { <body>1541 // };`. The key point is that we wish to drop all the1542 // let-bound variables and temporaries created in the body1543 // (and its tail expression!) before we drop the1544 // parameters (c.f. rust-lang/rust#64512).1545 for (index, parameter) in decl.inputs.iter().enumerate() {1546 let parameter = self.lower_param(parameter);1547 let span = parameter.pat.span;15481549 // Check if this is a binding pattern, if so, we can optimize and avoid adding a1550 // `let <pat> = __argN;` statement. In this case, we do not rename the parameter.1551 let (ident, is_simple_parameter) = match parameter.pat.kind {1552 hir::PatKind::Binding(hir::BindingMode(ByRef::No, _), _, ident, _) => (ident, true),1553 // For `ref mut` or wildcard arguments, we can't reuse the binding, but1554 // we can keep the same name for the parameter.1555 // This lets rustdoc render it correctly in documentation.1556 hir::PatKind::Binding(_, _, ident, _) => (ident, false),1557 hir::PatKind::Wild => (Ident::with_dummy_span(rustc_span::kw::Underscore), false),1558 _ => {1559 // Replace the ident for bindings that aren't simple.1560 let name = format!("__arg{index}");1561 let ident = Ident::from_str(&name);15621563 (ident, false)1564 }1565 };15661567 let desugared_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);15681569 // Construct a parameter representing `__argN: <ty>` to replace the parameter of the1570 // async function.1571 //1572 // If this is the simple case, this parameter will end up being the same as the1573 // original parameter, but with a different pattern id.1574 let stmt_attrs = self.attrs.get(¶meter.hir_id.local_id).copied();1575 let (new_parameter_pat, new_parameter_id) = self.pat_ident(desugared_span, ident);1576 let new_parameter = hir::Param {1577 hir_id: parameter.hir_id,1578 pat: new_parameter_pat,1579 ty_span: self.lower_span(parameter.ty_span),1580 span: self.lower_span(parameter.span),1581 };15821583 if is_simple_parameter {1584 // If this is the simple case, then we only insert one statement that is1585 // `let <pat> = <pat>;`. We re-use the original argument's pattern so that1586 // `HirId`s are densely assigned.1587 let expr = self.expr_ident(desugared_span, ident, new_parameter_id);1588 let stmt = self.stmt_let_pat(1589 stmt_attrs,1590 desugared_span,1591 Some(expr),1592 parameter.pat,1593 hir::LocalSource::AsyncFn,1594 );1595 statements.push(stmt);1596 } else {1597 // If this is not the simple case, then we construct two statements:1598 //1599 // ```1600 // let __argN = __argN;1601 // let <pat> = __argN;1602 // ```1603 //1604 // The first statement moves the parameter into the closure and thus ensures1605 // that the drop order is correct.1606 //1607 // The second statement creates the bindings that the user wrote.16081609 // Construct the `let mut __argN = __argN;` statement. It must be a mut binding1610 // because the user may have specified a `ref mut` binding in the next1611 // statement.1612 let (move_pat, move_id) =1613 self.pat_ident_binding_mode(desugared_span, ident, hir::BindingMode::MUT);1614 let move_expr = self.expr_ident(desugared_span, ident, new_parameter_id);1615 let move_stmt = self.stmt_let_pat(1616 None,1617 desugared_span,1618 Some(move_expr),1619 move_pat,1620 hir::LocalSource::AsyncFn,1621 );16221623 // Construct the `let <pat> = __argN;` statement. We re-use the original1624 // parameter's pattern so that `HirId`s are densely assigned.1625 let pattern_expr = self.expr_ident(desugared_span, ident, move_id);1626 let pattern_stmt = self.stmt_let_pat(1627 stmt_attrs,1628 desugared_span,1629 Some(pattern_expr),1630 parameter.pat,1631 hir::LocalSource::AsyncFn,1632 );16331634 statements.push(move_stmt);1635 statements.push(pattern_stmt);1636 };16371638 parameters.push(new_parameter);1639 }16401641 let mkbody = |this: &mut LoweringContext<'_, 'hir>| {1642 // Create a block from the user's function body:1643 let user_body = lower_body(this);16441645 // Transform into `drop-temps { <user-body> }`, an expression:1646 let desugared_span =1647 this.mark_span_with_reason(DesugaringKind::Async, user_body.span, None);1648 let user_body = this.expr_drop_temps(desugared_span, this.arena.alloc(user_body));16491650 // As noted above, create the final block like1651 //1652 // ```1653 // {1654 // let $param_pattern = $raw_param;1655 // ...1656 // drop-temps { <user-body> }1657 // }1658 // ```1659 let body = this.block_all(1660 desugared_span,1661 this.arena.alloc_from_iter(statements),1662 Some(user_body),1663 );16641665 this.expr_block(body)1666 };1667 let desugaring_kind = match coroutine_kind {1668 CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,1669 CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,1670 CoroutineKind::AsyncGen { .. } => hir::CoroutineDesugaring::AsyncGen,1671 };1672 let closure_id = coroutine_kind.closure_id();16731674 let coroutine_expr = self.make_desugared_coroutine_expr(1675 // The default capture mode here is by-ref. Later on during upvar analysis,1676 // we will force the captured arguments to by-move, but for async closures,1677 // we want to make sure that we avoid unnecessarily moving captures, or else1678 // all async closures would default to `FnOnce` as their calling mode.1679 CaptureBy::Ref,1680 closure_id,1681 None,1682 fn_decl_span,1683 body_span,1684 desugaring_kind,1685 coroutine_source,1686 mkbody,1687 );16881689 let expr = hir::Expr {1690 hir_id: self.lower_node_id(closure_id),1691 kind: coroutine_expr,1692 span: self.lower_span(body_span),1693 };16941695 (self.arena.alloc_from_iter(parameters), expr)1696 }16971698 fn lower_method_sig(1699 &mut self,1700 generics: &Generics,1701 sig: &FnSig,1702 id: NodeId,1703 kind: FnDeclKind,1704 coroutine_kind: Option<CoroutineKind>,1705 attrs: &[hir::Attribute],1706 ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {1707 let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs);1708 let itctx = ImplTraitContext::Universal;1709 let (generics, decl) = self.lower_generics(generics, id, itctx, |this| {1710 this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)1711 });1712 (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })1713 }17141715 pub(super) fn lower_fn_header(1716 &mut self,1717 h: FnHeader,1718 default_safety: hir::Safety,1719 attrs: &[hir::Attribute],1720 ) -> hir::FnHeader {1721 let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind {1722 hir::IsAsync::Async(self.lower_span(span))1723 } else {1724 hir::IsAsync::NotAsync1725 };17261727 let safety = self.lower_safety(h.safety, default_safety);17281729 // Treat safe `#[target_feature]` functions as unsafe, but also remember that we did so.1730 let safety = if find_attr!(attrs, TargetFeature { was_forced: false, .. })1731 && safety.is_safe()1732 && !self.tcx.sess.target.is_like_wasm1733 {1734 hir::HeaderSafety::SafeTargetFeatures1735 } else {1736 safety.into()1737 };17381739 hir::FnHeader {1740 safety,1741 asyncness,1742 constness: self.lower_constness(h.constness),1743 abi: self.lower_extern(h.ext),1744 }1745 }17461747 pub(super) fn lower_abi(&mut self, abi_str: StrLit) -> ExternAbi {1748 let ast::StrLit { symbol_unescaped, span, .. } = abi_str;1749 let extern_abi = symbol_unescaped.as_str().parse().unwrap_or_else(|_| {1750 self.error_on_invalid_abi(abi_str);1751 ExternAbi::Rust1752 });1753 let tcx = self.tcx;17541755 // we can't do codegen for unsupported ABIs, so error now so we won't get farther1756 if !tcx.sess.target.is_abi_supported(extern_abi) {1757 let mut err = struct_span_code_err!(1758 tcx.dcx(),1759 span,1760 E0570,1761 "{extern_abi} is not a supported ABI for the current target",1762 );17631764 if let ExternAbi::Stdcall { unwind } = extern_abi {1765 let c_abi = ExternAbi::C { unwind };1766 let system_abi = ExternAbi::System { unwind };1767 err.help(format!("if you need `extern {extern_abi}` on win32 and `extern {c_abi}` everywhere else, \1768 use `extern {system_abi}`"1769 ));1770 }1771 err.emit();1772 }1773 // Show required feature gate even if we already errored, as the user is likely to build the code1774 // for the actually intended target next and then they will need the feature gate.1775 gate_unstable_abi(tcx.sess, tcx.features(), span, extern_abi);1776 extern_abi1777 }17781779 pub(super) fn lower_extern(&mut self, ext: Extern) -> ExternAbi {1780 match ext {1781 Extern::None => ExternAbi::Rust,1782 Extern::Implicit(_) => ExternAbi::FALLBACK,1783 Extern::Explicit(abi, _) => self.lower_abi(abi),1784 }1785 }17861787 fn error_on_invalid_abi(&self, abi: StrLit) {1788 let abi_names = enabled_names(self.tcx.features(), abi.span)1789 .iter()1790 .map(|s| Symbol::intern(s))1791 .collect::<Vec<_>>();1792 let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);1793 self.dcx().emit_err(InvalidAbi {1794 abi: abi.symbol_unescaped,1795 span: abi.span,1796 suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {1797 span: abi.span,1798 suggestion: suggested_name.to_string(),1799 }),1800 command: "rustc --print=calling-conventions".to_string(),1801 });1802 }18031804 pub(super) fn lower_constness(&mut self, c: Const) -> hir::Constness {1805 match c {1806 Const::Yes(_) => hir::Constness::Const,1807 Const::No => hir::Constness::NotConst,1808 }1809 }18101811 pub(super) fn lower_safety(&self, s: Safety, default: hir::Safety) -> hir::Safety {1812 match s {1813 Safety::Unsafe(_) => hir::Safety::Unsafe,1814 Safety::Default => default,1815 Safety::Safe(_) => hir::Safety::Safe,1816 }1817 }18181819 pub(super) fn lower_impl_restriction(1820 &mut self,1821 r: &ImplRestriction,1822 ) -> &'hir hir::ImplRestriction<'hir> {1823 let kind = match &r.kind {1824 RestrictionKind::Unrestricted => hir::RestrictionKind::Unrestricted,1825 RestrictionKind::Restricted { path, id, shorthand: _ } => {1826 let res = self.get_partial_res(*id);1827 if let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) {1828 hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path {1829 res: did,1830 segments: self.arena.alloc_from_iter(path.segments.iter().map(|segment| {1831 self.lower_path_segment(1832 path.span,1833 segment,1834 ParamMode::Explicit,1835 GenericArgsMode::Err,1836 ImplTraitContext::Disallowed(ImplTraitPosition::Path),1837 None,1838 )1839 })),1840 span: self.lower_span(path.span),1841 }))1842 } else {1843 self.dcx().span_delayed_bug(path.span, "should have errored in resolve");1844 hir::RestrictionKind::Unrestricted1845 }1846 }1847 };1848 self.arena.alloc(hir::ImplRestriction { kind, span: self.lower_span(r.span) })1849 }18501851 /// Return the pair of the lowered `generics` as `hir::Generics` and the evaluation of `f` with1852 /// the carried impl trait definitions and bounds.1853 #[instrument(level = "debug", skip(self, f))]1854 fn lower_generics<T>(1855 &mut self,1856 generics: &Generics,1857 parent_node_id: NodeId,1858 itctx: ImplTraitContext,1859 f: impl FnOnce(&mut Self) -> T,1860 ) -> (&'hir hir::Generics<'hir>, T) {1861 assert!(self.impl_trait_defs.is_empty());1862 assert!(self.impl_trait_bounds.is_empty());18631864 let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();1865 predicates.extend(generics.params.iter().filter_map(|param| {1866 self.lower_generic_bound_predicate(1867 param.ident,1868 param.id,1869 ¶m.kind,1870 ¶m.bounds,1871 param.colon_span,1872 generics.span,1873 RelaxedBoundPolicy::Allowed,1874 itctx,1875 PredicateOrigin::GenericParam,1876 )1877 }));1878 predicates.extend(1879 generics1880 .where_clause1881 .predicates1882 .iter()1883 .map(|predicate| self.lower_where_predicate(predicate, &generics.params)),1884 );18851886 let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self1887 .lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)1888 .collect();18891890 // Introduce extra lifetimes if late resolution tells us to.1891 let extra_lifetimes = self.resolver.extra_lifetime_params(parent_node_id);1892 params.extend(extra_lifetimes.into_iter().filter_map(|&(ident, node_id, res)| {1893 self.lifetime_res_to_generic_param(1894 ident,1895 node_id,1896 res,1897 hir::GenericParamSource::Generics,1898 )1899 }));19001901 let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();1902 let where_clause_span = self.lower_span(generics.where_clause.span);1903 let span = self.lower_span(generics.span);1904 let res = f(self);19051906 let impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);1907 params.extend(impl_trait_defs.into_iter());19081909 let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);1910 predicates.extend(impl_trait_bounds.into_iter());19111912 let lowered_generics = self.arena.alloc(hir::Generics {1913 params: self.arena.alloc_from_iter(params),1914 predicates: self.arena.alloc_from_iter(predicates),1915 has_where_clause_predicates,1916 where_clause_span,1917 span,1918 });19191920 (lowered_generics, res)1921 }19221923 pub(super) fn lower_define_opaque(1924 &mut self,1925 hir_id: HirId,1926 define_opaque: &Option<ThinVec<(NodeId, Path)>>,1927 ) {1928 assert_eq!(self.define_opaque, None);1929 assert!(hir_id.is_owner());1930 let Some(define_opaque) = define_opaque.as_ref() else {1931 return;1932 };1933 let define_opaque = define_opaque.iter().filter_map(|(id, path)| {1934 let res = self.get_partial_res(*id);1935 let Some(did) = res.and_then(|res| res.expect_full_res().opt_def_id()) else {1936 self.dcx().span_delayed_bug(path.span, "should have errored in resolve");1937 return None;1938 };1939 let Some(did) = did.as_local() else {1940 self.dcx().span_err(1941 path.span,1942 "only opaque types defined in the local crate can be defined",1943 );1944 return None;1945 };1946 Some((self.lower_span(path.span), did))1947 });1948 let define_opaque = self.arena.alloc_from_iter(define_opaque);1949 self.define_opaque = Some(define_opaque);1950 }19511952 pub(super) fn lower_generic_bound_predicate(1953 &mut self,1954 ident: Ident,1955 id: NodeId,1956 kind: &GenericParamKind,1957 bounds: &[GenericBound],1958 colon_span: Option<Span>,1959 parent_span: Span,1960 rbp: RelaxedBoundPolicy<'_>,1961 itctx: ImplTraitContext,1962 origin: PredicateOrigin,1963 ) -> Option<hir::WherePredicate<'hir>> {1964 // Do not create a clause if we do not have anything inside it.1965 if bounds.is_empty() {1966 return None;1967 }19681969 let bounds = self.lower_param_bounds(bounds, rbp, itctx);19701971 let param_span = ident.span;19721973 // Reconstruct the span of the entire predicate from the individual generic bounds.1974 let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi());1975 let span = bounds.iter().fold(span_start, |span_accum, bound| {1976 match bound.span().find_ancestor_inside(parent_span) {1977 Some(bound_span) => span_accum.to(bound_span),1978 None => span_accum,1979 }1980 });1981 let span = self.lower_span(span);1982 let hir_id = self.next_id();1983 let kind = self.arena.alloc(match kind {1984 GenericParamKind::Const { .. } => return None,1985 GenericParamKind::Type { .. } => {1986 let def_id = self.local_def_id(id).to_def_id();1987 let hir_id = self.next_id();1988 let res = Res::Def(DefKind::TyParam, def_id);1989 let ident = self.lower_ident(ident);1990 let ty_path = self.arena.alloc(hir::Path {1991 span: self.lower_span(param_span),1992 res,1993 segments: self1994 .arena1995 .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]),1996 });1997 let ty_id = self.next_id();1998 let bounded_ty =1999 self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));2000 hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.