1//! Lowers the AST to the HIR.2//!3//! Since the AST and HIR are fairly similar, this is mostly a simple procedure,4//! much like a fold. Where lowering involves a bit more work things get more5//! interesting and there are some invariants you should know about. These mostly6//! concern spans and IDs.7//!8//! Spans are assigned to AST nodes during parsing and then are modified during9//! expansion to indicate the origin of a node and the process it went through10//! being expanded. IDs are assigned to AST nodes just before lowering.11//!12//! For the simpler lowering steps, IDs and spans should be preserved. Unlike13//! expansion we do not preserve the process of lowering in the spans, so spans14//! should not be modified here. When creating a new node (as opposed to15//! "folding" an existing one), create a new ID using `next_id()`.16//!17//! You must ensure that IDs are unique. That means that you should only use the18//! ID from an AST node in a single HIR node (you can assume that AST node-IDs19//! are unique). Every new node must have a unique ID. Avoid cloning HIR nodes.20//! If you do, you must then set the new node's ID to a fresh one.21//!22//! Spans are used for error messages and for tools to map semantics back to23//! source code. It is therefore not as important with spans as IDs to be strict24//! about use (you can't break the compiler by screwing up a span). Obviously, a25//! HIR node can only have a single span. But multiple nodes can have the same26//! span and spans don't need to be kept in order, etc. Where code is preserved27//! by lowering, it should have the same span as in the AST. Where HIR nodes are28//! new it is probably best to give a span for the whole AST node being lowered.29//! All nodes should have real spans; don't use dummy spans. Tools are likely to30//! get confused if the spans from leaf AST nodes occur in multiple places31//! in the HIR, especially for multiple identifiers.3233// tidy-alphabetical-start34#![feature(deref_patterns)]35#![recursion_limit = "256"]36// tidy-alphabetical-end3738use std::mem;39use std::sync::Arc;4041use rustc_ast::mut_visit::{self, MutVisitor};42use rustc_ast::node_id::NodeMap;43use rustc_ast::visit::{self, Visitor};44use rustc_ast::{self as ast, *};45use rustc_attr_parsing::{AttributeParser, OmitDoc, Recovery, ShouldEmit};46use rustc_data_structures::fx::FxIndexMap;47use rustc_data_structures::sorted_map::SortedMap;48use rustc_data_structures::stable_hash::{StableHash, StableHasher};49use rustc_data_structures::steal::Steal;50use rustc_data_structures::tagged_ptr::TaggedRef;51use rustc_data_structures::unord::ExtendUnord;52use rustc_errors::codes::*;53use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle};54use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};55use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};56use rustc_hir::definitions::PerParentDisambiguatorState;57use rustc_hir::lints::DelayedLint;58use rustc_hir::{59 self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,60 LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, find_attr,61};62use rustc_index::{Idx, IndexVec};63use rustc_macros::extension;64use rustc_middle::queries::Providers;65use rustc_middle::span_bug;66use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt};67use rustc_session::errors::add_feature_diagnostics;68use rustc_span::symbol::{Ident, Symbol, kw, sym};69use rustc_span::{DUMMY_SP, DesugaringKind, Span};70use smallvec::{SmallVec, smallvec};71use thin_vec::ThinVec;72use tracing::{debug, instrument, trace};7374use crate::diagnostics::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};7576macro_rules! arena_vec {77 ($this:expr; $($x:expr),*) => (78 $this.arena.alloc_from_iter([$($x),*])79 );80}8182mod asm;83mod block;84mod contract;85mod delegation;86mod diagnostics;87mod expr;88mod format;89mod index;90mod item;91mod pat;92mod path;93pub mod stability;9495pub fn provide(providers: &mut Providers) {96 providers.index_ast = index_ast;97 providers.lower_to_hir = lower_to_hir;98}99100struct LoweringContext<'a, 'hir> {101 tcx: TyCtxt<'hir>,102 resolver: &'a ResolverAstLowering<'hir>,103 current_disambiguator: PerParentDisambiguatorState,104105 /// Used to allocate HIR nodes.106 arena: &'hir hir::Arena<'hir>,107108 /// Bodies inside the owner being lowered.109 bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,110 /// `#[define_opaque]` attributes111 define_opaque: Option<&'hir [(Span, LocalDefId)]>,112 /// Attributes inside the owner being lowered.113 attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,114 /// Collect items that were created by lowering the current owner.115 children: LocalDefIdMap<hir::MaybeOwner<'hir>>,116117 contract_ensures: Option<(Span, Ident, HirId)>,118119 coroutine_kind: Option<hir::CoroutineKind>,120121 /// When inside an `async` context, this is the `HirId` of the122 /// `task_context` local bound to the resume argument of the coroutine.123 task_context: Option<HirId>,124125 /// Used to get the current `fn`'s def span to point to when using `await`126 /// outside of an `async fn`.127 current_item: Option<Span>,128129 try_block_scope: TryBlockScope,130 loop_scope: Option<HirId>,131 is_in_loop_condition: bool,132 is_in_dyn_type: bool,133134 current_hir_id_owner: hir::OwnerId,135 owner: &'a PerOwnerResolverData<'hir>,136 item_local_id_counter: hir::ItemLocalId,137 trait_map: ItemLocalMap<&'hir [TraitCandidate<'hir>]>,138139 impl_trait_defs: Vec<hir::GenericParam<'hir>>,140 impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,141142 /// NodeIds of pattern identifiers and labelled nodes that are lowered inside the current HIR owner.143 ident_and_label_to_local_id: NodeMap<hir::ItemLocalId>,144 /// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering check.145 #[cfg(debug_assertions)]146 node_id_to_local_id: NodeMap<hir::ItemLocalId>,147 /// The `NodeId` space is split in two.148 /// `0..resolver.next_node_id` are created by the resolver on the AST.149 /// The higher part `resolver.next_node_id..next_node_id` are created during lowering.150 next_node_id: NodeId,151 /// Maps the `NodeId`s created during lowering to `LocalDefId`s.152 node_id_to_def_id: NodeMap<LocalDefId>,153 /// Overlay over resolver's `partial_res_map` used by delegation.154 /// This only contains `PartialRes::new(Res::Local(self_param_id))`,155 /// so we only store `self_param_id`.156 partial_res_overrides: NodeMap<NodeId>,157158 allow_contracts: Arc<[Symbol]>,159 allow_try_trait: Arc<[Symbol]>,160 allow_gen_future: Arc<[Symbol]>,161 allow_pattern_type: Arc<[Symbol]>,162 allow_async_gen: Arc<[Symbol]>,163 allow_async_iterator: Arc<[Symbol]>,164 allow_for_await: Arc<[Symbol]>,165 allow_async_fn_traits: Arc<[Symbol]>,166167 delayed_lints: Vec<DelayedLint>,168169 /// Stack of `move(...)` collection states. A plain closure body pushes170 /// `Some`, so `move(...)` expressions can record the generated locals they171 /// should lower to. Nested bodies that cannot use `move(...)` push `None`.172 move_expr_bindings: Vec<Option<expr::MoveExprState<'hir>>>,173174 attribute_parser: AttributeParser<'hir>,175}176177impl<'a, 'hir> LoweringContext<'a, 'hir> {178 fn new(tcx: TyCtxt<'hir>, resolver: &'a ResolverAstLowering<'hir>, owner: NodeId) -> Self {179 let current_ast_owner = &resolver.owners[&owner];180 let current_hir_id_owner = hir::OwnerId { def_id: current_ast_owner.def_id };181 let current_disambiguator = resolver182 .disambiguators183 .get(¤t_hir_id_owner.def_id)184 .map(|s| s.steal())185 .unwrap_or_else(|| PerParentDisambiguatorState::new(current_hir_id_owner.def_id));186187 Self {188 tcx,189 resolver,190 current_disambiguator,191 owner: current_ast_owner,192 arena: tcx.hir_arena,193194 // HirId handling.195 bodies: Vec::new(),196 define_opaque: None,197 attrs: SortedMap::default(),198 children: LocalDefIdMap::default(),199 contract_ensures: None,200 current_hir_id_owner,201 // 0 corresponds to `owner` lowered as `current_hir_id_owner`,202 // and we never call `lower_node_id(owner)`.203 item_local_id_counter: hir::ItemLocalId::new(1),204 ident_and_label_to_local_id: Default::default(),205 #[cfg(debug_assertions)]206 node_id_to_local_id: Default::default(),207 trait_map: Default::default(),208 next_node_id: resolver.next_node_id,209 node_id_to_def_id: NodeMap::default(),210 partial_res_overrides: NodeMap::default(),211212 // Lowering state.213 try_block_scope: TryBlockScope::Function,214 loop_scope: None,215 is_in_loop_condition: false,216 is_in_dyn_type: false,217 coroutine_kind: None,218 task_context: None,219 current_item: None,220 impl_trait_defs: Vec::new(),221 impl_trait_bounds: Vec::new(),222 allow_contracts: [sym::contracts_internals].into(),223 allow_try_trait: [224 sym::try_trait_v2,225 sym::try_trait_v2_residual,226 sym::yeet_desugar_details,227 ]228 .into(),229 allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),230 allow_gen_future: if tcx.features().async_fn_track_caller() {231 [sym::gen_future, sym::closure_track_caller].into()232 } else {233 [sym::gen_future].into()234 },235 allow_for_await: [sym::async_gen_internals, sym::async_iterator].into(),236 allow_async_fn_traits: [sym::async_fn_traits].into(),237 allow_async_gen: [sym::async_gen_internals].into(),238 // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`239 // interact with `gen`/`async gen` blocks240 allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),241242 move_expr_bindings: Vec::new(),243 attribute_parser: AttributeParser::new(244 tcx.sess,245 tcx.features(),246 tcx.registered_tools(()),247 ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },248 ),249 delayed_lints: Vec::new(),250 }251 }252253 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'hir> {254 self.tcx.dcx()255 }256}257258struct SpanLowerer {259 is_incremental: bool,260 def_id: LocalDefId,261}262263impl SpanLowerer {264 fn lower(&self, span: Span) -> Span {265 if self.is_incremental {266 span.with_parent(Some(self.def_id))267 } else {268 // Do not make spans relative when not using incremental compilation.269 span270 }271 }272}273274#[extension(trait ResolverAstLoweringExt<'tcx>)]275impl<'tcx> ResolverAstLowering<'tcx> {276 fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option<Vec<usize>> {277 let ExprKind::Path(None, path) = &expr.kind else {278 return None;279 };280281 // Don't perform legacy const generics rewriting if the path already282 // has generic arguments.283 if path.segments.last().unwrap().args.is_some() {284 return None;285 }286287 // We do not need to look at `partial_res_overrides`. That map only contains overrides for288 // `self_param` locals. And here we are looking for the function definition that `expr`289 // resolves to.290 let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?;291292 // We only support cross-crate argument rewriting. Uses293 // within the same crate should be updated to use the new294 // const generics style.295 if def_id.is_local() {296 return None;297 }298299 // we can use parsed attrs here since for other crates they're already available300 find_attr!(301 tcx, def_id,302 RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes303 )304 .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect())305 }306307 /// Obtain the list of lifetimes parameters to add to an item.308 ///309 /// Extra lifetime parameters should only be added in places that can appear310 /// as a `binder` in `LifetimeRes`.311 ///312 /// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring313 /// should appear at the enclosing `PolyTraitRef`.314 fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] {315 self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..])316 }317}318319/// How relaxed bounds `?Trait` should be treated.320///321/// Relaxed bounds should only be allowed in places where we later322/// (namely during HIR ty lowering) perform *sized elaboration*.323#[derive(Debug)]324enum RelaxedBoundPolicy<'a> {325 /// The `DefId` refers to the trait that is being relaxed.326 Allowed(&'a mut FxIndexMap<DefId, Span>),327 Forbidden(RelaxedBoundForbiddenReason),328}329impl RelaxedBoundPolicy<'_> {330 fn reborrow(&mut self) -> RelaxedBoundPolicy<'_> {331 match self {332 RelaxedBoundPolicy::Allowed(m) => RelaxedBoundPolicy::Allowed(m),333 RelaxedBoundPolicy::Forbidden(reason) => RelaxedBoundPolicy::Forbidden(*reason),334 }335 }336}337338#[derive(Clone, Copy, Debug)]339enum RelaxedBoundForbiddenReason {340 TraitObjectTy,341 SuperTrait,342 TraitAlias,343 AssocTyBounds,344 /// We do not allow where bounds doing relaxed bounds,345 /// except if it's for generic parameters of the current item.346 WhereBound,347}348349/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,350/// and if so, what meaning it has.351#[derive(Debug, Copy, Clone, PartialEq, Eq)]352enum ImplTraitContext {353 /// Treat `impl Trait` as shorthand for a new universal generic parameter.354 /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually355 /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.356 ///357 /// Newly generated parameters should be inserted into the given `Vec`.358 Universal,359360 /// Treat `impl Trait` as shorthand for a new opaque type.361 /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually362 /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.363 ///364 OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> },365366 /// Treat `impl Trait` as a "trait ascription", which is like a type367 /// variable but that also enforces that a set of trait goals hold.368 ///369 /// This is useful to guide inference for unnameable types.370 InBinding,371372 /// `impl Trait` is unstably accepted in this position.373 FeatureGated(ImplTraitPosition, Symbol),374 /// `impl Trait` is not accepted in this position.375 Disallowed(ImplTraitPosition),376}377378/// Position in which `impl Trait` is disallowed.379#[derive(Debug, Copy, Clone, PartialEq, Eq)]380enum ImplTraitPosition {381 Path,382 Variable,383 Trait,384 Bound,385 Generic,386 ExternFnParam,387 ClosureParam,388 PointerParam,389 FnTraitParam,390 ExternFnReturn,391 ClosureReturn,392 PointerReturn,393 FnTraitReturn,394 GenericDefault,395 ConstTy,396 StaticTy,397 AssocTy,398 FieldTy,399 Cast,400 ImplSelf,401 OffsetOf,402}403404impl std::fmt::Display for ImplTraitPosition {405 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {406 let name = match self {407 ImplTraitPosition::Path => "paths",408 ImplTraitPosition::Variable => "the type of variable bindings",409 ImplTraitPosition::Trait => "traits",410 ImplTraitPosition::Bound => "bounds",411 ImplTraitPosition::Generic => "generics",412 ImplTraitPosition::ExternFnParam => "`extern fn` parameters",413 ImplTraitPosition::ClosureParam => "closure parameters",414 ImplTraitPosition::PointerParam => "`fn` pointer parameters",415 ImplTraitPosition::FnTraitParam => "the parameters of `Fn` trait bounds",416 ImplTraitPosition::ExternFnReturn => "`extern fn` return types",417 ImplTraitPosition::ClosureReturn => "closure return types",418 ImplTraitPosition::PointerReturn => "`fn` pointer return types",419 ImplTraitPosition::FnTraitReturn => "the return type of `Fn` trait bounds",420 ImplTraitPosition::GenericDefault => "generic parameter defaults",421 ImplTraitPosition::ConstTy => "const types",422 ImplTraitPosition::StaticTy => "static types",423 ImplTraitPosition::AssocTy => "associated types",424 ImplTraitPosition::FieldTy => "field types",425 ImplTraitPosition::Cast => "cast expression types",426 ImplTraitPosition::ImplSelf => "impl headers",427 ImplTraitPosition::OffsetOf => "`offset_of!` parameters",428 };429430 write!(f, "{name}")431 }432}433434#[derive(Copy, Clone, Debug, PartialEq, Eq)]435enum FnDeclKind {436 Fn,437 Inherent,438 ExternFn,439 Closure,440 Pointer,441 Trait,442 Impl,443}444445#[derive(Copy, Clone, Debug)]446enum TryBlockScope {447 /// There isn't a `try` block, so a `?` will use `return`.448 Function,449 /// We're inside a `try { … }` block, so a `?` will block-break450 /// from that block using a type depending only on the argument.451 Homogeneous(HirId),452 /// We're inside a `try as _ { … }` block, so a `?` will block-break453 /// from that block using the type specified.454 Heterogeneous(HirId),455}456457fn index_ast<'tcx>(458 tcx: TyCtxt<'tcx>,459 (): (),460) -> IndexVec<LocalDefId, Steal<(Arc<ResolverAstLowering<'tcx>>, AstOwner)>> {461 // Queries that borrow `resolver_for_lowering`.462 tcx.ensure_done().output_filenames(());463 tcx.ensure_done().early_lint_checks(());464 tcx.ensure_done().get_lang_items(());465 tcx.ensure_done().debugger_visualizers(LOCAL_CRATE);466467 let (resolver, krate) = tcx.resolver_for_lowering();468 let mut resolver = resolver.steal();469 let mut krate = krate.steal();470471 let mut indexer = Indexer {472 owners: &resolver.owners,473 index: IndexVec::new(),474 next_node_id: resolver.next_node_id,475 };476 indexer.visit_crate(&mut krate);477 indexer.insert(CRATE_NODE_ID, AstOwner::Crate(Box::new(krate)));478 resolver.next_node_id = indexer.next_node_id;479480 let index = indexer.index;481 let resolver = Arc::new(resolver);482 let index = index.into_iter().map(|owner| Steal::new((Arc::clone(&resolver), owner))).collect();483 return index;484485 struct Indexer<'s, 'hir> {486 owners: &'s NodeMap<PerOwnerResolverData<'hir>>,487 index: IndexVec<LocalDefId, AstOwner>,488 next_node_id: NodeId,489 }490491 impl Indexer<'_, '_> {492 fn insert(&mut self, id: NodeId, node: AstOwner) {493 let def_id = self.owners[&id].def_id;494 self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);495 self.index[def_id] = node;496 }497498 fn make_dummy<K>(499 &mut self,500 id: NodeId,501 span: Span,502 dummy: impl FnOnce(Box<MacCall>) -> K,503 ) -> Box<Item<K>> {504 use rustc_ast::token::Delimiter;505 use rustc_ast::tokenstream::{DelimSpan, TokenStream};506 use thin_vec::thin_vec;507508 Box::new(Item {509 attrs: AttrVec::default(),510 id,511 span,512 vis: Visibility { kind: VisibilityKind::Public, span, tokens: None },513 // Lacking a better choice, we replace the contents with a macro call.514 // Unexpanded macros should never reach lowering, so this is not confusing.515 kind: dummy(Box::new(MacCall {516 path: Path { span, segments: thin_vec![], tokens: None },517 args: Box::new(DelimArgs {518 dspan: DelimSpan::from_single(span),519 delim: Delimiter::Parenthesis,520 tokens: TokenStream::new(Vec::new()),521 }),522 })),523 tokens: None,524 })525 }526527 fn replace_with_dummy<K>(528 &mut self,529 item: &mut ast::Item<K>,530 dummy: impl FnOnce(Box<MacCall>) -> K,531 node: impl FnOnce(Box<Item<K>>) -> AstOwner,532 ) {533 let dummy = self.make_dummy(item.id, item.span, dummy);534 let item = mem::replace(item, *dummy);535 self.insert(item.id, node(Box::new(item)));536 }537538 #[tracing::instrument(level = "trace", skip(self))]539 fn visit_item_id_use_tree(540 &mut self,541 tree: &UseTree,542 parent: LocalDefId,543 items: &mut SmallVec<[Box<Item>; 1]>,544 ) {545 match tree.kind {546 UseTreeKind::Glob(_) | UseTreeKind::Simple(_) => {}547 UseTreeKind::Nested { items: ref nested_vec, span } => {548 for &(ref nested, id) in nested_vec {549 self.insert(id, AstOwner::NestedUseTree(parent));550 items.push(self.make_dummy(id, span, ItemKind::MacCall));551552 let def_id = self.owners[&id].def_id;553 self.visit_item_id_use_tree(nested, def_id, items);554 }555 }556 }557 }558 }559560 impl MutVisitor for Indexer<'_, '_> {561 fn visit_attribute(&mut self, _: &mut Attribute) {562 // We do not want to lower expressions that appear in attributes,563 // as they are not accessible to the rest of the HIR.564 }565566 fn flat_map_item(&mut self, mut item: Box<Item>) -> SmallVec<[Box<Item>; 1]> {567 let def_id = self.owners[&item.id].def_id;568 mut_visit::walk_item(self, &mut *item);569 let dummy = self.make_dummy(item.id, item.span, ItemKind::MacCall);570 let mut items = smallvec![dummy];571 if let ItemKind::Use(ref use_tree) = item.kind {572 self.visit_item_id_use_tree(use_tree, def_id, &mut items);573 }574 self.insert(item.id, AstOwner::Item(item));575 items576 }577578 fn flat_map_stmt(&mut self, stmt: Stmt) -> SmallVec<[Stmt; 1]> {579 let Stmt { id, span, kind } = stmt;580 let mut id = Some(id);581 mut_visit::walk_flat_map_stmt_kind(self, kind)582 .into_iter()583 .map(|kind| {584 // Expanding the current statement is a nested `use` item,585 // it is expanded into several flat `use` items.586 // Create new NodeIds for the corresponding statements587 // as two statements cannot have the same.588 let id = id.take().unwrap_or_else(|| {589 let next = self.next_node_id;590 self.next_node_id.increment_by(1);591 next592 });593 Stmt { id, kind, span }594 })595 .collect()596 }597598 fn visit_assoc_item(&mut self, item: &mut AssocItem, ctxt: visit::AssocCtxt) {599 mut_visit::walk_assoc_item(self, item, ctxt);600 match ctxt {601 visit::AssocCtxt::Trait => {602 self.replace_with_dummy(item, AssocItemKind::MacCall, AstOwner::TraitItem)603 }604 visit::AssocCtxt::Impl { .. } => {605 self.replace_with_dummy(item, AssocItemKind::MacCall, AstOwner::ImplItem)606 }607 }608 }609610 fn visit_foreign_item(&mut self, item: &mut ForeignItem) {611 mut_visit::walk_item(self, item);612 self.replace_with_dummy(item, ForeignItemKind::MacCall, AstOwner::ForeignItem);613 }614 }615}616617#[instrument(level = "trace", skip(tcx))]618fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> {619 // Queries that borrow `resolver_for_lowering`.620 tcx.ensure_done().output_filenames(());621 tcx.ensure_done().early_lint_checks(());622 tcx.ensure_done().debugger_visualizers(LOCAL_CRATE);623 tcx.ensure_done().get_lang_items(());624 let ast_index = tcx.index_ast(());625 let resolver_and_node = ast_index.get(def_id).map(Steal::steal);626627 let fallback_to_ancestor = |parent_id| {628 // The item did not exist in the AST, it was created while lowering another item.629 // `parent_id` may be different from the direct parent of `def_id`,630 // for instance use-trees are lowered by the first sibling.631 let mut parent_info = tcx.lower_to_hir(parent_id);632 if let hir::MaybeOwner::NonOwner(hir_id) = parent_info {633 // `parent_id` could also not be a owner either.634 // For instance if `def_id` is an enum variant field,635 // the direct parent is the enum variant.636 // In that case `hir_id.owner` point to the actual HIR owner637 // and skips all non-owner parents, so fetch the HIR associated to it.638 parent_info = tcx.lower_to_hir(hir_id.owner);639 }640641 let parent_info = parent_info.unwrap();642 *parent_info.children.get(&def_id).unwrap_or_else(|| {643 panic!(644 "{:?} does not appear in children of {:?}",645 def_id,646 parent_info.nodes.node().def_id()647 )648 })649 };650651 let Some((resolver, node)) = resolver_and_node else {652 // `ast_index` does not contain all definitions, only up-to the highest653 // `LocalDefId` which has a non-trivial `AstOwner`. Gracefully handle654 // other definitions, in particular those nested inside this highest definition.655 return fallback_to_ancestor(tcx.local_parent(def_id));656 };657658 let mut item_lowerer = item::ItemLowerer { tcx, resolver: &*resolver };659660 let item = match &node {661 // The item existed in the AST.662 AstOwner::Crate(c) => item_lowerer.lower_crate(&c),663 AstOwner::Item(item) => item_lowerer.lower_item(&item),664 AstOwner::TraitItem(item) => item_lowerer.lower_trait_item(&item),665 AstOwner::ImplItem(item) => item_lowerer.lower_impl_item(&item),666 AstOwner::ForeignItem(item) => item_lowerer.lower_foreign_item(&item),667 AstOwner::NestedUseTree(owner_id) => fallback_to_ancestor(*owner_id),668 // The item existed in the AST, but is not a HIR owner.669 // Fetch the correct information from its parent.670 AstOwner::NonOwner => fallback_to_ancestor(tcx.local_parent(def_id)),671 };672673 tcx.sess.time("drop_ast", || mem::drop(node));674675 item676}677678#[derive(Copy, Clone, PartialEq, Debug)]679enum ParamMode {680 /// Any path in a type context.681 Explicit,682 /// The `module::Type` in `module::Type::method` in an expression.683 Optional,684}685686#[derive(Copy, Clone, Debug)]687enum AllowReturnTypeNotation {688 /// Only in types, since RTN is denied later during HIR lowering.689 Yes,690 /// All other positions (path expr, method, use tree).691 No,692}693694enum GenericArgsMode {695 /// Allow paren sugar, don't allow RTN.696 ParenSugar,697 /// Allow RTN, don't allow paren sugar.698 ReturnTypeNotation,699 // Error if parenthesized generics or RTN are encountered.700 Err,701 /// Silence errors when lowering generics. Only used with `Res::Err`.702 Silence,703}704705impl<'hir> LoweringContext<'_, 'hir> {706 fn create_def(707 &mut self,708 node_id: NodeId,709 name: Option<Symbol>,710 def_kind: DefKind,711 span: Span,712 ) -> LocalDefId {713 let parent = self.current_hir_id_owner.def_id;714 assert_ne!(node_id, ast::DUMMY_NODE_ID);715 assert!(716 self.opt_local_def_id(node_id).is_none(),717 "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",718 node_id,719 def_kind,720 self.tcx.hir_def_key(self.local_def_id(node_id)),721 );722723 let def_id = self724 .tcx725 .at(span)726 .create_def(parent, name, def_kind, None, &mut self.current_disambiguator)727 .def_id();728729 debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);730 self.node_id_to_def_id.insert(node_id, def_id);731732 def_id733 }734735 fn next_node_id(&mut self) -> NodeId {736 let start = self.next_node_id;737 let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");738 self.next_node_id = NodeId::from_u32(next);739 start740 }741742 /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name743 /// resolver (if any).744 #[instrument(level = "trace", skip(self), ret)]745 fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {746 self.node_id_to_def_id747 .get(&node)748 .or_else(|| self.owner.node_id_to_def_id.get(&node))749 .copied()750 }751752 fn local_def_id(&self, node: NodeId) -> LocalDefId {753 self.opt_local_def_id(node).unwrap_or_else(|| {754 self.resolver.owners.items().any(|(id, items)| {755 items.node_id_to_def_id.items().any(|(node_id, def_id)| {756 if *node_id == node {757 let actual_owner = items.node_id_to_def_id.get(id);758 panic!("{def_id:?} ({node_id}) was found in {actual_owner:?} ({id})",)759 }760 false761 })762 });763 panic!("no entry for node id: `{node:?}`");764 })765 }766767 fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {768 match self.partial_res_overrides.get(&id) {769 Some(self_param_id) => Some(PartialRes::new(Res::Local(*self_param_id))),770 None => self.resolver.partial_res_map.get(&id).copied(),771 }772 }773774 /// Given the id of an owner node in the AST, returns the corresponding `OwnerId`.775 fn owner_id(&self, node: NodeId) -> hir::OwnerId {776 hir::OwnerId { def_id: self.resolver.owners[&node].def_id }777 }778779 /// Freshen the `LoweringContext` and ready it to lower a nested item.780 /// The lowered item is registered into `self.children`.781 ///782 /// This function sets up `HirId` lowering infrastructure,783 /// and stashes the shared mutable state to avoid pollution by the closure.784 #[instrument(level = "debug", skip(self, f))]785 fn with_hir_id_owner(786 &mut self,787 owner: NodeId,788 f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,789 ) {790 let owner_id = self.owner_id(owner);791 let def_id = owner_id.def_id;792793 let new_disambig = self794 .resolver795 .disambiguators796 .get(&def_id)797 .map(|s| s.steal())798 .unwrap_or_else(|| PerParentDisambiguatorState::new(def_id));799800 let disambiguator = mem::replace(&mut self.current_disambiguator, new_disambig);801 let current_ast_owner = mem::replace(&mut self.owner, &self.resolver.owners[&owner]);802 let current_attrs = mem::take(&mut self.attrs);803 let current_bodies = mem::take(&mut self.bodies);804 let current_define_opaque = mem::take(&mut self.define_opaque);805 let current_ident_and_label_to_local_id = mem::take(&mut self.ident_and_label_to_local_id);806807 #[cfg(debug_assertions)]808 let current_node_id_to_local_id = mem::take(&mut self.node_id_to_local_id);809 let current_trait_map = mem::take(&mut self.trait_map);810 let current_owner = mem::replace(&mut self.current_hir_id_owner, owner_id);811 let current_local_counter =812 mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));813 let current_impl_trait_defs = mem::take(&mut self.impl_trait_defs);814 let current_impl_trait_bounds = mem::take(&mut self.impl_trait_bounds);815 let current_delayed_lints = mem::take(&mut self.delayed_lints);816 let current_children = mem::take(&mut self.children);817818 // Do not reset `next_node_id` and `node_id_to_def_id`:819 // we want `f` to be able to refer to the `LocalDefId`s that the caller created.820 // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s.821822 // Always allocate the first `HirId` for the owner itself.823 #[cfg(debug_assertions)]824 {825 let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);826 debug_assert_eq!(_old, None);827 }828829 let item = f(self);830 assert_eq!(owner_id, item.def_id());831 // `f` should have consumed all the elements in these vectors when constructing `item`.832 assert!(self.impl_trait_defs.is_empty());833 assert!(self.impl_trait_bounds.is_empty());834 let info = self.make_owner_info(item);835836 self.current_disambiguator = disambiguator;837 self.owner = current_ast_owner;838 self.attrs = current_attrs;839 self.bodies = current_bodies;840 self.define_opaque = current_define_opaque;841 self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;842843 #[cfg(debug_assertions)]844 {845 self.node_id_to_local_id = current_node_id_to_local_id;846 }847 self.trait_map = current_trait_map;848 self.current_hir_id_owner = current_owner;849 self.item_local_id_counter = current_local_counter;850 self.impl_trait_defs = current_impl_trait_defs;851 self.impl_trait_bounds = current_impl_trait_bounds;852 self.delayed_lints = current_delayed_lints;853 self.children = current_children;854 self.children.extend_unord(info.children.items().map(|(&def_id, &info)| (def_id, info)));855856 debug_assert!(!self.children.contains_key(&owner_id.def_id));857 self.children.insert(owner_id.def_id, hir::MaybeOwner::Owner(info));858 }859860 fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {861 let attrs = mem::take(&mut self.attrs);862 let mut bodies = mem::take(&mut self.bodies);863 let define_opaque = mem::take(&mut self.define_opaque);864 let trait_map = mem::take(&mut self.trait_map);865 let delayed_lints = Steal::new(mem::take(&mut self.delayed_lints).into_boxed_slice());866 let children = mem::take(&mut self.children);867868 #[cfg(debug_assertions)]869 for (id, attrs) in attrs.iter() {870 // Verify that we do not store empty slices in the map.871 if attrs.is_empty() {872 panic!("Stored empty attributes for {:?}", id);873 }874 }875876 bodies.sort_by_key(|(k, _)| *k);877 let bodies = SortedMap::from_presorted_elements(bodies);878879 // Don't hash unless necessary, because it's expensive.880 let rustc_middle::hir::Hashes { bodies_hash, attrs_hash } =881 self.tcx.hash_owner_nodes(node, &bodies, &attrs, define_opaque);882 let num_nodes = self.item_local_id_counter.as_usize();883 let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);884 let nodes = hir::OwnerNodes { opt_hash: bodies_hash, nodes, bodies };885 let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };886887 let opt_hash = self.tcx.needs_hir_hash().then(|| {888 self.tcx.with_stable_hashing_context(|mut hcx| {889 let mut stable_hasher = StableHasher::new();890 bodies_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);891 attrs_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);892 // Do not hash delayed_lints.893 parenting.stable_hash(&mut hcx, &mut stable_hasher);894 trait_map.stable_hash(&mut hcx, &mut stable_hasher);895 children.stable_hash(&mut hcx, &mut stable_hasher);896 stable_hasher.finish()897 })898 });899900 self.arena.alloc(hir::OwnerInfo {901 opt_hash,902 nodes,903 parenting,904 attrs,905 trait_map,906 delayed_lints,907 children,908 })909 }910911 /// This method allocates a new `HirId` for the given `NodeId`.912 /// Take care not to call this method if the resulting `HirId` is then not913 /// actually used in the HIR, as that would trigger an assertion in the914 /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped915 /// properly. Calling the method twice with the same `NodeId` is also forbidden.916 #[instrument(level = "debug", skip(self), ret)]917 fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {918 assert_ne!(ast_node_id, DUMMY_NODE_ID);919920 let owner = self.current_hir_id_owner;921 let local_id = self.item_local_id_counter;922 assert_ne!(local_id, hir::ItemLocalId::ZERO);923 self.item_local_id_counter.increment_by(1);924 let hir_id = HirId { owner, local_id };925926 if let Some(def_id) = self.opt_local_def_id(ast_node_id) {927 self.children.insert(def_id, hir::MaybeOwner::NonOwner(hir_id));928 }929930 if let Some(traits) = self.owner.trait_map.get(&ast_node_id) {931 self.trait_map.insert(hir_id.local_id, *traits);932 }933934 // Check whether the same `NodeId` is lowered more than once.935 #[cfg(debug_assertions)]936 {937 let old = self.node_id_to_local_id.insert(ast_node_id, local_id);938 assert_eq!(old, None);939 }940941 hir_id942 }943944 /// Generate a new `HirId` without a backing `NodeId`.945 #[instrument(level = "debug", skip(self), ret)]946 fn next_id(&mut self) -> HirId {947 let owner = self.current_hir_id_owner;948 let local_id = self.item_local_id_counter;949 assert_ne!(local_id, hir::ItemLocalId::ZERO);950 self.item_local_id_counter.increment_by(1);951 HirId { owner, local_id }952 }953954 #[instrument(level = "trace", skip(self))]955 fn lower_res(&mut self, res: Res<NodeId>) -> Res {956 let res: Result<Res, ()> = res.apply_id(|id| {957 let owner = self.current_hir_id_owner;958 let local_id = self.ident_and_label_to_local_id.get(&id).copied().ok_or(())?;959 Ok(HirId { owner, local_id })960 });961 trace!(?res);962963 // We may fail to find a HirId when the Res points to a Local from an enclosing HIR owner.964 // This can happen when trying to lower the return type `x` in erroneous code like965 // async fn foo(x: u8) -> x {}966 // In that case, `x` is lowered as a function parameter, and the return type is lowered as967 // an opaque type as a synthesized HIR owner.968 res.unwrap_or(Res::Err)969 }970971 fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> {972 self.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())973 }974975 fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS<Option<Res>> {976 debug_assert_eq!(id, self.owner.id);977 let per_ns = self.owner.import_res.map(|res| res.map(|res| self.lower_res(res)));978 if per_ns.is_empty() {979 // Propagate the error to all namespaces, just to be sure.980 self.dcx().span_delayed_bug(span, "no resolution for an import");981 let err = Some(Res::Err);982 return PerNS { type_ns: err, value_ns: err, macro_ns: err };983 }984 per_ns985 }986987 fn make_lang_item_qpath(988 &mut self,989 lang_item: hir::LangItem,990 span: Span,991 args: Option<&'hir hir::GenericArgs<'hir>>,992 ) -> hir::QPath<'hir> {993 hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, args))994 }995996 fn make_lang_item_path(997 &mut self,998 lang_item: hir::LangItem,999 span: Span,1000 args: Option<&'hir hir::GenericArgs<'hir>>,1001 ) -> &'hir hir::Path<'hir> {1002 let def_id = self.tcx.require_lang_item(lang_item, span);1003 let def_kind = self.tcx.def_kind(def_id);1004 let res = Res::Def(def_kind, def_id);1005 self.arena.alloc(hir::Path {1006 span,1007 res,1008 segments: self.arena.alloc_from_iter([hir::PathSegment {1009 ident: Ident::new(lang_item.name(), span),1010 hir_id: self.next_id(),1011 res,1012 args,1013 infer_args: args.is_none(),1014 }]),1015 })1016 }10171018 /// Reuses the span but adds information like the kind of the desugaring and features that are1019 /// allowed inside this span.1020 fn mark_span_with_reason(1021 &self,1022 reason: DesugaringKind,1023 span: Span,1024 allow_internal_unstable: Option<Arc<[Symbol]>>,1025 ) -> Span {1026 self.tcx.with_stable_hashing_context(|hcx| {1027 span.mark_with_reason(allow_internal_unstable, reason, span.edition(), hcx)1028 })1029 }10301031 fn span_lowerer(&self) -> SpanLowerer {1032 SpanLowerer {1033 is_incremental: self.tcx.sess.opts.incremental.is_some(),1034 def_id: self.current_hir_id_owner.def_id,1035 }1036 }10371038 /// Intercept all spans entering HIR.1039 /// Mark a span as relative to the current owning item.1040 fn lower_span(&self, span: Span) -> Span {1041 self.span_lowerer().lower(span)1042 }10431044 fn lower_ident(&self, ident: Ident) -> Ident {1045 Ident::new(ident.name, self.lower_span(ident.span))1046 }10471048 /// Converts a lifetime into a new generic parameter.1049 #[instrument(level = "debug", skip(self))]1050 fn lifetime_res_to_generic_param(1051 &mut self,1052 ident: Ident,1053 node_id: NodeId,1054 kind: MissingLifetimeKind,1055 source: hir::GenericParamSource,1056 ) -> hir::GenericParam<'hir> {1057 // Late resolution delegates to us the creation of the `LocalDefId`.1058 let _def_id = self.create_def(1059 node_id,1060 Some(kw::UnderscoreLifetime),1061 DefKind::LifetimeParam,1062 ident.span,1063 );1064 debug!(?_def_id);10651066 let hir_id = self.lower_node_id(node_id);1067 let def_id = self.local_def_id(node_id);1068 hir::GenericParam {1069 hir_id,1070 def_id,1071 name: hir::ParamName::Fresh,1072 span: self.lower_span(ident.span),1073 pure_wrt_drop: false,1074 kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided(kind) },1075 colon_span: None,1076 source,1077 }1078 }10791080 /// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR1081 /// nodes. The returned list includes any "extra" lifetime parameters that were added by the1082 /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id1083 /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime1084 /// parameters will be successful.1085 #[instrument(level = "debug", skip(self), ret)]1086 #[inline]1087 fn lower_lifetime_binder(1088 &mut self,1089 binder: NodeId,1090 generic_params: &[GenericParam],1091 ) -> &'hir [hir::GenericParam<'hir>] {1092 // Start by creating params for extra lifetimes params, as this creates the definitions1093 // that may be referred to by the AST inside `generic_params`.1094 let extra_lifetimes = self.resolver.extra_lifetime_params(binder);1095 debug!(?extra_lifetimes);1096 let extra_lifetimes: Vec<_> = extra_lifetimes1097 .iter()1098 .map(|&(ident, node_id, res)| {1099 self.lifetime_res_to_generic_param(1100 ident,1101 node_id,1102 res,1103 hir::GenericParamSource::Binder,1104 )1105 })1106 .collect();1107 let arena = self.arena;1108 let explicit_generic_params =1109 self.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder);1110 arena.alloc_from_iter(explicit_generic_params.chain(extra_lifetimes.into_iter()))1111 }11121113 fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {1114 let was_in_dyn_type = self.is_in_dyn_type;1115 self.is_in_dyn_type = in_scope;11161117 let result = f(self);11181119 self.is_in_dyn_type = was_in_dyn_type;11201121 result1122 }11231124 fn with_new_scopes<T>(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T {1125 let current_item = self.current_item;1126 self.current_item = Some(scope_span);11271128 let was_in_loop_condition = self.is_in_loop_condition;1129 self.is_in_loop_condition = false;11301131 let old_contract = self.contract_ensures.take();11321133 let try_block_scope = mem::replace(&mut self.try_block_scope, TryBlockScope::Function);1134 let loop_scope = self.loop_scope.take();1135 let ret = f(self);1136 self.try_block_scope = try_block_scope;1137 self.loop_scope = loop_scope;11381139 self.contract_ensures = old_contract;11401141 self.is_in_loop_condition = was_in_loop_condition;11421143 self.current_item = current_item;11441145 ret1146 }11471148 fn lower_attrs(1149 &mut self,1150 id: HirId,1151 attrs: &[Attribute],1152 target_span: Span,1153 target: Target,1154 ) -> &'hir [hir::Attribute] {1155 self.lower_attrs_with_extra(id, attrs, target_span, target, &[])1156 }11571158 fn lower_attrs_with_extra(1159 &mut self,1160 id: HirId,1161 attrs: &[Attribute],1162 target_span: Span,1163 target: Target,1164 extra_hir_attributes: &[hir::Attribute],1165 ) -> &'hir [hir::Attribute] {1166 if attrs.is_empty() && extra_hir_attributes.is_empty() {1167 &[]1168 } else {1169 let mut lowered_attrs =1170 self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target);1171 lowered_attrs.extend(extra_hir_attributes.iter().cloned());11721173 assert_eq!(id.owner, self.current_hir_id_owner);1174 let ret = self.arena.alloc_from_iter(lowered_attrs);11751176 // this is possible if an item contained syntactical attribute,1177 // but none of them parse successfully or all of them were ignored1178 // for not being built-in attributes at all. They could be remaining1179 // unexpanded attributes used as markers in proc-macro derives for example.1180 // This will have emitted some diagnostics for the misparse, but will then1181 // not emit the attribute making the list empty.1182 if ret.is_empty() {1183 &[]1184 } else {1185 self.attrs.insert(id.local_id, ret);1186 ret1187 }1188 }1189 }11901191 fn lower_attrs_vec(1192 &mut self,1193 attrs: &[Attribute],1194 target_span: Span,1195 target_hir_id: HirId,1196 target: Target,1197 ) -> Vec<hir::Attribute> {1198 let l = self.span_lowerer();1199 self.attribute_parser.parse_attribute_list(1200 attrs,1201 target_span,1202 target,1203 OmitDoc::Lower,1204 |s| l.lower(s),1205 |lint_id, span, kind| {1206 self.delayed_lints.push(DelayedLint {1207 lint_id,1208 id: target_hir_id,1209 span,1210 callback: Box::new(move |dcx, level, sess: &dyn std::any::Any| {1211 let sess = sess1212 .downcast_ref::<rustc_session::Session>()1213 .expect("expected `Session`");1214 (kind.0)(dcx, level, sess)1215 }),1216 });1217 },1218 )1219 }12201221 fn alias_attrs(&mut self, id: HirId, target_id: HirId) {1222 assert_eq!(id.owner, self.current_hir_id_owner);1223 assert_eq!(target_id.owner, self.current_hir_id_owner);1224 if let Some(&a) = self.attrs.get(&target_id.local_id) {1225 assert!(!a.is_empty());1226 self.attrs.insert(id.local_id, a);1227 }1228 }12291230 fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs {1231 args.clone()1232 }12331234 /// Lower an associated item constraint.1235 #[instrument(level = "debug", skip_all)]1236 fn lower_assoc_item_constraint(1237 &mut self,1238 constraint: &AssocItemConstraint,1239 itctx: ImplTraitContext,1240 ) -> hir::AssocItemConstraint<'hir> {1241 debug!(?constraint, ?itctx);1242 // Lower the generic arguments for the associated item.1243 let gen_args = if let Some(gen_args) = &constraint.gen_args {1244 let gen_args_ctor = match gen_args {1245 GenericArgs::AngleBracketed(data) => {1246 self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).01247 }1248 GenericArgs::Parenthesized(data) => {1249 if let Some(first_char) = constraint.ident.as_str().chars().next()1250 && first_char.is_ascii_lowercase()1251 {1252 let err = match (&data.inputs[..], &data.output) {1253 ([_, ..], FnRetTy::Default(_)) => {1254 diagnostics::BadReturnTypeNotation::Inputs {1255 span: data.inputs_span,1256 }1257 }1258 ([], FnRetTy::Default(_)) => {1259 diagnostics::BadReturnTypeNotation::NeedsDots {1260 span: data.inputs_span,1261 }1262 }1263 // The case `T: Trait<method(..) -> Ret>` is handled in the parser.1264 (_, FnRetTy::Ty(ty)) => {1265 let span = data.inputs_span.shrink_to_hi().to(ty.span);1266 diagnostics::BadReturnTypeNotation::Output {1267 span,1268 suggestion: diagnostics::RTNSuggestion {1269 output: span,1270 input: data.inputs_span,1271 },1272 }1273 }1274 };1275 let mut err = self.dcx().create_err(err);1276 if !self.tcx.features().return_type_notation()1277 && self.tcx.sess.is_nightly_build()1278 {1279 add_feature_diagnostics(1280 &mut err,1281 &self.tcx.sess,1282 sym::return_type_notation,1283 );1284 }1285 err.emit();1286 GenericArgsCtor {1287 args: Default::default(),1288 constraints: &[],1289 parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,1290 span: data.span,1291 }1292 } else {1293 self.emit_bad_parenthesized_trait_in_assoc_ty(data);1294 self.lower_angle_bracketed_parameter_data(1295 &data.as_angle_bracketed_args(),1296 ParamMode::Explicit,1297 itctx,1298 )1299 .01300 }1301 }1302 GenericArgs::ParenthesizedElided(span) => GenericArgsCtor {1303 args: Default::default(),1304 constraints: &[],1305 parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,1306 span: *span,1307 },1308 };1309 gen_args_ctor.into_generic_args(self)1310 } else {1311 hir::GenericArgs::NONE1312 };1313 let kind = match &constraint.kind {1314 AssocItemConstraintKind::Equality { term } => {1315 let term = match term {1316 Term::Ty(ty) => self.lower_ty_alloc(ty, itctx).into(),1317 Term::Const(c) => self.lower_anon_const_to_const_arg_and_alloc(c).into(),1318 };1319 hir::AssocItemConstraintKind::Equality { term }1320 }1321 AssocItemConstraintKind::Bound { bounds } => {1322 // Disallow ATB in dyn types1323 if self.is_in_dyn_type {1324 let suggestion = match itctx {1325 ImplTraitContext::OpaqueTy { .. } | ImplTraitContext::Universal => {1326 let bound_end_span = constraint1327 .gen_args1328 .as_ref()1329 .map_or(constraint.ident.span, |args| args.span());1330 if bound_end_span.eq_ctxt(constraint.span) {1331 Some(self.tcx.sess.source_map().next_point(bound_end_span))1332 } else {1333 None1334 }1335 }1336 _ => None,1337 };13381339 let guar = self.dcx().emit_err(diagnostics::MisplacedAssocTyBinding {1340 span: constraint.span,1341 suggestion,1342 });1343 let err_ty =1344 &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));1345 hir::AssocItemConstraintKind::Equality { term: err_ty.into() }1346 } else {1347 let bounds = self.lower_param_bounds(1348 bounds,1349 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::AssocTyBounds),1350 itctx,1351 );1352 hir::AssocItemConstraintKind::Bound { bounds }1353 }1354 }1355 };13561357 hir::AssocItemConstraint {1358 hir_id: self.lower_node_id(constraint.id),1359 ident: self.lower_ident(constraint.ident),1360 gen_args,1361 kind,1362 span: self.lower_span(constraint.span),1363 }1364 }13651366 fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) {1367 // Suggest removing empty parentheses: "Trait()" -> "Trait"1368 let sub = if data.inputs.is_empty() {1369 let parentheses_span =1370 data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi());1371 AssocTyParenthesesSub::Empty { parentheses_span }1372 }1373 // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`1374 else {1375 // Start of parameters to the 1st argument1376 let open_param = data.inputs_span.shrink_to_lo().to(data1377 .inputs1378 .first()1379 .unwrap()1380 .span1381 .shrink_to_lo());1382 // End of last argument to end of parameters1383 let close_param =1384 data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi());1385 AssocTyParenthesesSub::NotEmpty { open_param, close_param }1386 };1387 self.dcx().emit_err(AssocTyParentheses { span: data.span, sub });1388 }13891390 #[instrument(level = "debug", skip(self))]1391 fn lower_generic_arg(1392 &mut self,1393 arg: &ast::GenericArg,1394 itctx: ImplTraitContext,1395 ) -> hir::GenericArg<'hir> {1396 match arg {1397 ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(1398 lt,1399 LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },1400 lt.ident.into(),1401 )),1402 ast::GenericArg::Type(ty) => {1403 // We cannot just match on `TyKind::Infer` as `(_)` is represented as1404 // `TyKind::Paren(TyKind::Infer)` and should also be lowered to `GenericArg::Infer`1405 if ty.is_maybe_parenthesised_infer() {1406 return GenericArg::Infer(hir::InferArg {1407 hir_id: self.lower_node_id(ty.id),1408 span: self.lower_span(ty.span),1409 });1410 }14111412 match &ty.kind {1413 // We parse const arguments as path types as we cannot distinguish them during1414 // parsing. We try to resolve that ambiguity by attempting resolution in both the1415 // type and value namespaces. If we resolved the path in the value namespace, we1416 // transform it into a generic const argument.1417 //1418 // FIXME: Should we be handling `(PATH_TO_CONST)`?1419 TyKind::Path(None, path) => {1420 if let Some(res) = self1421 .get_partial_res(ty.id)1422 .and_then(|partial_res| partial_res.full_res())1423 {1424 if !res.matches_ns(Namespace::TypeNS)1425 && path.is_potential_trivial_const_arg()1426 {1427 debug!(1428 "lower_generic_arg: Lowering type argument as const argument: {:?}",1429 ty,1430 );14311432 let ct =1433 self.lower_const_path_to_const_arg(path, res, ty.id, ty.span);1434 return GenericArg::Const(ct.try_as_ambig_ct().unwrap());1435 }1436 }1437 }1438 _ => {}1439 }1440 GenericArg::Type(self.lower_ty_alloc(ty, itctx).try_as_ambig_ty().unwrap())1441 }1442 ast::GenericArg::Const(ct) => {1443 let ct = self.lower_anon_const_to_const_arg_and_alloc(ct);1444 match ct.try_as_ambig_ct() {1445 Some(ct) => GenericArg::Const(ct),1446 None => GenericArg::Infer(hir::InferArg { hir_id: ct.hir_id, span: ct.span }),1447 }1448 }1449 }1450 }14511452 #[instrument(level = "debug", skip(self))]1453 fn lower_ty_alloc(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> {1454 self.arena.alloc(self.lower_ty(t, itctx))1455 }14561457 fn lower_path_ty(1458 &mut self,1459 t: &Ty,1460 qself: &Option<Box<QSelf>>,1461 path: &Path,1462 param_mode: ParamMode,1463 itctx: ImplTraitContext,1464 ) -> hir::Ty<'hir> {1465 // Check whether we should interpret this as a bare trait object.1466 // This check mirrors the one in late resolution. We only introduce this special case in1467 // the rare occurrence we need to lower `Fresh` anonymous lifetimes.1468 // The other cases when a qpath should be opportunistically made a trait object are handled1469 // by `ty_path`.1470 if qself.is_none()1471 && let Some(partial_res) = self.get_partial_res(t.id)1472 && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()1473 {1474 let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {1475 let bound = this.lower_poly_trait_ref(1476 &PolyTraitRef {1477 bound_generic_params: ThinVec::new(),1478 modifiers: TraitBoundModifiers::NONE,1479 trait_ref: TraitRef { path: path.clone(), ref_id: t.id },1480 span: t.span,1481 parens: ast::Parens::No,1482 },1483 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy),1484 itctx,1485 );1486 let bounds = this.arena.alloc_from_iter([bound]);1487 let lifetime_bound = this.elided_dyn_bound(t.span);1488 (bounds, lifetime_bound)1489 });1490 let kind = hir::TyKind::TraitObject(1491 bounds,1492 TaggedRef::new(lifetime_bound, TraitObjectSyntax::None),1493 );1494 return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };1495 }14961497 let id = self.lower_node_id(t.id);1498 let qpath = self.lower_qpath(1499 t.id,1500 qself,1501 path,1502 param_mode,1503 AllowReturnTypeNotation::Yes,1504 itctx,1505 None,1506 );1507 self.ty_path(id, t.span, qpath)1508 }15091510 fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> {1511 hir::Ty { hir_id: self.next_id(), kind, span: self.lower_span(span) }1512 }15131514 fn ty_tup(&mut self, span: Span, tys: &'hir [hir::Ty<'hir>]) -> hir::Ty<'hir> {1515 self.ty(span, hir::TyKind::Tup(tys))1516 }15171518 fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {1519 let kind = match &t.kind {1520 TyKind::Infer => hir::TyKind::Infer(()),1521 TyKind::Err(guar) => hir::TyKind::Err(*guar),1522 TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty_alloc(ty, itctx)),1523 TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),1524 TyKind::Ref(region, mt) => {1525 let lifetime = self.lower_ty_direct_lifetime(t, *region);1526 hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))1527 }1528 TyKind::PinnedRef(region, mt) => {1529 let lifetime = self.lower_ty_direct_lifetime(t, *region);1530 let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));1531 let span = self.lower_span(t.span);1532 let arg = hir::Ty { kind, span, hir_id: self.next_id() };1533 let args = self.arena.alloc(hir::GenericArgs {1534 args: self.arena.alloc([hir::GenericArg::Type(self.arena.alloc(arg))]),1535 constraints: &[],1536 parenthesized: hir::GenericArgsParentheses::No,1537 span_ext: span,1538 });1539 let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args));1540 hir::TyKind::Path(path)1541 }1542 TyKind::FnPtr(f) => {1543 let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);1544 hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy {1545 generic_params,1546 safety: self.lower_safety(f.safety, hir::Safety::Safe),1547 abi: self.lower_extern(f.ext),1548 decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),1549 param_idents: self.lower_fn_params_to_idents(&f.decl),1550 }))1551 }1552 TyKind::UnsafeBinder(f) => {1553 let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);1554 hir::TyKind::UnsafeBinder(self.arena.alloc(hir::UnsafeBinderTy {1555 generic_params,1556 inner_ty: self.lower_ty_alloc(&f.inner_ty, itctx),1557 }))1558 }1559 TyKind::Never => hir::TyKind::Never,1560 TyKind::Tup(tys) => hir::TyKind::Tup(1561 self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty(ty, itctx))),1562 ),1563 TyKind::Paren(ty) => {1564 return self.lower_ty(ty, itctx);1565 }1566 TyKind::Path(qself, path) => {1567 return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);1568 }1569 TyKind::ImplicitSelf => {1570 let hir_id = self.next_id();1571 let res = self.expect_full_res(t.id);1572 let res = self.lower_res(res);1573 hir::TyKind::Path(hir::QPath::Resolved(1574 None,1575 self.arena.alloc(hir::Path {1576 res,1577 segments: arena_vec![self; hir::PathSegment::new(1578 Ident::with_dummy_span(kw::SelfUpper),1579 hir_id,1580 res1581 )],1582 span: self.lower_span(t.span),1583 }),1584 ))1585 }1586 TyKind::Array(ty, length) => hir::TyKind::Array(1587 self.lower_ty_alloc(ty, itctx),1588 self.lower_array_length_to_const_arg(length),1589 ),1590 TyKind::TraitObject(bounds, kind) => {1591 let mut lifetime_bound = None;1592 let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {1593 let bounds =1594 this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {1595 // We can safely ignore constness here since AST validation1596 // takes care of rejecting invalid modifier combinations and1597 // const trait bounds in trait object types.1598 GenericBound::Trait(ty) => {1599 let trait_ref = this.lower_poly_trait_ref(1600 ty,1601 RelaxedBoundPolicy::Forbidden(1602 RelaxedBoundForbiddenReason::TraitObjectTy,1603 ),1604 itctx,1605 );1606 Some(trait_ref)1607 }1608 GenericBound::Outlives(lifetime) => {1609 if lifetime_bound.is_none() {1610 lifetime_bound = Some(this.lower_lifetime(1611 lifetime,1612 LifetimeSource::Other,1613 lifetime.ident.into(),1614 ));1615 }1616 None1617 }1618 // Ignore `use` syntax since that is not valid in objects.1619 GenericBound::Use(_, span) => {1620 this.dcx()1621 .span_delayed_bug(*span, "use<> not allowed in dyn types");1622 None1623 }1624 }));1625 let lifetime_bound =1626 lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));1627 (bounds, lifetime_bound)1628 });1629 hir::TyKind::TraitObject(bounds, TaggedRef::new(lifetime_bound, *kind))1630 }1631 TyKind::ImplTrait(def_node_id, bounds) => {1632 let span = t.span;1633 match itctx {1634 ImplTraitContext::OpaqueTy { origin } => {1635 self.lower_opaque_impl_trait(span, origin, *def_node_id, bounds, itctx)1636 }1637 ImplTraitContext::Universal => {1638 if let Some(span) = bounds.iter().find_map(|bound| match *bound {1639 ast::GenericBound::Use(_, span) => Some(span),1640 _ => None,1641 }) {1642 self.tcx.dcx().emit_err(diagnostics::NoPreciseCapturesOnApit { span });1643 }16441645 let def_id = self.local_def_id(*def_node_id);1646 let name = self.tcx.item_name(def_id.to_def_id());1647 let ident = Ident::new(name, span);1648 let (param, bounds, path) = self.lower_universal_param_and_bounds(1649 *def_node_id,1650 span,1651 ident,1652 bounds,1653 );1654 self.impl_trait_defs.push(param);1655 if let Some(bounds) = bounds {1656 self.impl_trait_bounds.push(bounds);1657 }1658 path1659 }1660 ImplTraitContext::InBinding => {1661 hir::TyKind::TraitAscription(self.lower_param_bounds(1662 bounds,1663 RelaxedBoundPolicy::Allowed(&mut Default::default()),1664 itctx,1665 ))1666 }1667 ImplTraitContext::FeatureGated(position, feature) => {1668 let guar = self1669 .tcx1670 .sess1671 .create_feature_err(1672 MisplacedImplTrait {1673 span: t.span,1674 position: DiagArgFromDisplay(&position),1675 },1676 feature,1677 )1678 .emit();1679 hir::TyKind::Err(guar)1680 }1681 ImplTraitContext::Disallowed(position) => {1682 let guar = self.dcx().emit_err(MisplacedImplTrait {1683 span: t.span,1684 position: DiagArgFromDisplay(&position),1685 });1686 hir::TyKind::Err(guar)1687 }1688 }1689 }1690 TyKind::Pat(ty, pat) => {1691 hir::TyKind::Pat(self.lower_ty_alloc(ty, itctx), self.lower_ty_pat(pat, ty.span))1692 }1693 TyKind::FieldOf(ty, variant, field) => hir::TyKind::FieldOf(1694 self.lower_ty_alloc(ty, itctx),1695 self.arena.alloc(hir::TyFieldPath {1696 variant: variant.map(|variant| self.lower_ident(variant)),1697 field: self.lower_ident(*field),1698 }),1699 ),1700 TyKind::MacCall(_) => {1701 span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")1702 }1703 TyKind::CVarArgs => {1704 let guar = self.dcx().span_delayed_bug(1705 t.span,1706 "`TyKind::CVarArgs` should have been handled elsewhere",1707 );1708 hir::TyKind::Err(guar)1709 }1710 TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"),1711 };17121713 hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }1714 }17151716 fn lower_ty_direct_lifetime(1717 &mut self,1718 t: &Ty,1719 region: Option<Lifetime>,1720 ) -> &'hir hir::Lifetime {1721 let (region, syntax) = match region {1722 Some(region) => (region, region.ident.into()),17231724 None => {1725 let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =1726 self.owner.get_lifetime_res(t.id)1727 {1728 assert_eq!(start.plus(1), end);1729 start1730 } else {1731 self.next_node_id()1732 };1733 let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();1734 let region = Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id };1735 (region, LifetimeSyntax::Implicit)1736 }1737 };1738 self.lower_lifetime(®ion, LifetimeSource::Reference, syntax)1739 }17401741 /// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F =1742 /// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a1743 /// HIR type that references the TAIT.1744 ///1745 /// Given a function definition like:1746 ///1747 /// ```rust1748 /// use std::fmt::Debug;1749 ///1750 /// fn test<'a, T: Debug>(x: &'a T) -> impl Debug + 'a {1751 /// x1752 /// }1753 /// ```1754 ///1755 /// we will create a TAIT definition in the HIR like1756 ///1757 /// ```rust,ignore (pseudo-Rust)1758 /// type TestReturn<'a, T, 'x> = impl Debug + 'x1759 /// ```1760 ///1761 /// and return a type like `TestReturn<'static, T, 'a>`, so that the function looks like:1762 ///1763 /// ```rust,ignore (pseudo-Rust)1764 /// fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a>1765 /// ```1766 ///1767 /// Note the subtlety around type parameters! The new TAIT, `TestReturn`, inherits all the1768 /// type parameters from the function `test` (this is implemented in the query layer, they aren't1769 /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to1770 /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters1771 /// for the lifetimes that get captured (`'x`, in our example above) and reference those.1772 #[instrument(level = "debug", skip(self), ret)]1773 fn lower_opaque_impl_trait(1774 &mut self,1775 span: Span,1776 origin: hir::OpaqueTyOrigin<LocalDefId>,1777 opaque_ty_node_id: NodeId,1778 bounds: &GenericBounds,1779 itctx: ImplTraitContext,1780 ) -> hir::TyKind<'hir> {1781 // Make sure we know that some funky desugaring has been going on here.1782 // This is a first: there is code in other places like for loop1783 // desugaring that explicitly states that we don't want to track that.1784 // Not tracking it makes lints in rustc and clippy very fragile, as1785 // frequently opened issues show.1786 let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);17871788 self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {1789 this.lower_param_bounds(1790 bounds,1791 RelaxedBoundPolicy::Allowed(&mut Default::default()),1792 itctx,1793 )1794 })1795 }17961797 fn lower_opaque_inner(1798 &mut self,1799 opaque_ty_node_id: NodeId,1800 origin: hir::OpaqueTyOrigin<LocalDefId>,1801 opaque_ty_span: Span,1802 lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],1803 ) -> hir::TyKind<'hir> {1804 let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);1805 let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id);1806 debug!(?opaque_ty_def_id, ?opaque_ty_hir_id);18071808 let bounds = lower_item_bounds(self);1809 let opaque_ty_def = hir::OpaqueTy {1810 hir_id: opaque_ty_hir_id,1811 def_id: opaque_ty_def_id,1812 bounds,1813 origin,1814 span: self.lower_span(opaque_ty_span),1815 };1816 let opaque_ty_def = self.arena.alloc(opaque_ty_def);18171818 hir::TyKind::OpaqueDef(opaque_ty_def)1819 }18201821 fn lower_precise_capturing_args(1822 &mut self,1823 precise_capturing_args: &[PreciseCapturingArg],1824 ) -> &'hir [hir::PreciseCapturingArg<'hir>] {1825 self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {1826 PreciseCapturingArg::Lifetime(lt) => hir::PreciseCapturingArg::Lifetime(1827 self.lower_lifetime(lt, LifetimeSource::PreciseCapturing, lt.ident.into()),1828 ),1829 PreciseCapturingArg::Arg(path, id) => {1830 let [segment] = path.segments.as_slice() else {1831 panic!();1832 };1833 let res = self.get_partial_res(*id).map_or(Res::Err, |partial_res| {1834 partial_res.full_res().expect("no partial res expected for precise capture arg")1835 });1836 hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {1837 hir_id: self.lower_node_id(*id),1838 ident: self.lower_ident(segment.ident),1839 res: self.lower_res(res),1840 })1841 }1842 }))1843 }18441845 fn lower_fn_params_to_idents(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {1846 self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {1847 PatKind::Missing => None,1848 PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)),1849 PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))),1850 _ => {1851 self.dcx().span_delayed_bug(1852 param.pat.span,1853 "non-missing/ident/wild param pat must trigger an error",1854 );1855 None1856 }1857 }))1858 }18591860 /// Lowers a function declaration.1861 ///1862 /// `decl`: the unlowered (AST) function declaration.1863 ///1864 /// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given1865 /// `NodeId`.1866 ///1867 /// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is1868 /// needed for `async fn` and `gen fn`. See [`CoroutineKind`] for more details.1869 #[instrument(level = "debug", skip(self))]1870 fn lower_fn_decl(1871 &mut self,1872 decl: &FnDecl,1873 fn_node_id: NodeId,1874 fn_span: Span,1875 kind: FnDeclKind,1876 coro: Option<CoroutineKind>,1877 ) -> &'hir hir::FnDecl<'hir> {1878 let c_variadic = decl.c_variadic();1879 let mut splatted = decl.splatted();18801881 // Skip the `...` (`CVarArgs`) trailing arguments from the AST,1882 // as they are not explicit in HIR/Ty function signatures.1883 // (instead, the `c_variadic` flag is set to `true`)1884 let mut inputs = &decl.inputs[..];1885 if decl.c_variadic() {1886 // Splat + variadic errors in AST validation, so just ignore one of them here.1887 splatted = None;1888 inputs = &inputs[..inputs.len() - 1];1889 }1890 let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {1891 let itctx = match kind {1892 FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => {1893 ImplTraitContext::Universal1894 }1895 FnDeclKind::ExternFn => {1896 ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnParam)1897 }1898 FnDeclKind::Closure => {1899 ImplTraitContext::Disallowed(ImplTraitPosition::ClosureParam)1900 }1901 FnDeclKind::Pointer => {1902 ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam)1903 }1904 };1905 self.lower_ty(¶m.ty, itctx)1906 }));19071908 let output = match coro {1909 Some(coro) => {1910 let fn_def_id = self.owner.def_id;1911 self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, coro, kind)1912 }1913 None => match &decl.output {1914 FnRetTy::Ty(ty) => {1915 let itctx = match kind {1916 FnDeclKind::Fn | FnDeclKind::Inherent => ImplTraitContext::OpaqueTy {1917 origin: hir::OpaqueTyOrigin::FnReturn {1918 parent: self.owner.def_id,1919 in_trait_or_impl: None,1920 },1921 },1922 FnDeclKind::Trait => ImplTraitContext::OpaqueTy {1923 origin: hir::OpaqueTyOrigin::FnReturn {1924 parent: self.owner.def_id,1925 in_trait_or_impl: Some(hir::RpitContext::Trait),1926 },1927 },1928 FnDeclKind::Impl => ImplTraitContext::OpaqueTy {1929 origin: hir::OpaqueTyOrigin::FnReturn {1930 parent: self.owner.def_id,1931 in_trait_or_impl: Some(hir::RpitContext::TraitImpl),1932 },1933 },1934 FnDeclKind::ExternFn => {1935 ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnReturn)1936 }1937 FnDeclKind::Closure => {1938 ImplTraitContext::Disallowed(ImplTraitPosition::ClosureReturn)1939 }1940 FnDeclKind::Pointer => {1941 ImplTraitContext::Disallowed(ImplTraitPosition::PointerReturn)1942 }1943 };1944 hir::FnRetTy::Return(self.lower_ty_alloc(ty, itctx))1945 }1946 FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),1947 },1948 };19491950 let fn_decl_kind = hir::FnDeclFlags::default()1951 .set_implicit_self(decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {1952 let is_mutable_pat = matches!(1953 arg.pat.kind,1954 PatKind::Ident(hir::BindingMode(_, Mutability::Mut), ..)1955 );19561957 match &arg.ty.kind {1958 TyKind::ImplicitSelf if is_mutable_pat => hir::ImplicitSelfKind::Mut,1959 TyKind::ImplicitSelf => hir::ImplicitSelfKind::Imm,1960 // Given we are only considering `ImplicitSelf` types, we needn't consider1961 // the case where we have a mutable pattern to a reference as that would1962 // no longer be an `ImplicitSelf`.1963 TyKind::Ref(_, mt) | TyKind::PinnedRef(_, mt)1964 if mt.ty.kind.is_implicit_self() =>1965 {1966 match mt.mutbl {1967 hir::Mutability::Not => hir::ImplicitSelfKind::RefImm,1968 hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut,1969 }1970 }1971 _ => hir::ImplicitSelfKind::None,1972 }1973 }))1974 .set_lifetime_elision_allowed(1975 self.owner.id == fn_node_id && self.owner.lifetime_elision_allowed,1976 )1977 .set_c_variadic(c_variadic)1978 .set_splatted(splatted, inputs.len())1979 .unwrap();19801981 self.arena.alloc(hir::FnDecl { inputs, output, fn_decl_kind })1982 }19831984 // Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }`1985 // combined with the following definition of `OpaqueTy`:1986 //1987 // type OpaqueTy<generics_from_parent_fn> = impl Future<Output = T>;1988 //1989 // `output`: unlowered output type (`T` in `-> T`)1990 // `fn_node_id`: `NodeId` of the parent function (used to create child impl trait definition)1991 // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created1992 #[instrument(level = "debug", skip(self))]1993 fn lower_coroutine_fn_ret_ty(1994 &mut self,1995 output: &FnRetTy,1996 fn_def_id: LocalDefId,1997 coro: CoroutineKind,1998 fn_kind: FnDeclKind,1999 ) -> hir::FnRetTy<'hir> {2000 let span = self.lower_span(output.span());
Findings
✓ No findings reported for this file.