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(const_default)]35#![feature(const_trait_impl)]36#![feature(default_field_values)]37#![feature(deref_patterns)]38#![recursion_limit = "256"]39// tidy-alphabetical-end4041use std::mem;42use std::sync::Arc;4344use rustc_ast::mut_visit::{self, MutVisitor};45use rustc_ast::node_id::NodeMap;46use rustc_ast::visit::{self, Visitor};47use rustc_ast::{self as ast, *};48use rustc_attr_parsing::{AttributeParser, OmitDoc, Recovery, ShouldEmit};49use rustc_data_structures::fx::FxIndexMap;50use rustc_data_structures::sorted_map::SortedMap;51use rustc_data_structures::stable_hash::{StableHash, StableHasher};52use rustc_data_structures::steal::Steal;53use rustc_data_structures::tagged_ptr::TaggedRef;54use rustc_data_structures::unord::ExtendUnord;55use rustc_errors::codes::*;56use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed};57use rustc_hir::attrs::lang_items::LangItem;58use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};59use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};60use rustc_hir::definitions::PerParentDisambiguatorState;61use rustc_hir::lints::DelayedLint;62use rustc_hir::{63 self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,64 LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, find_attr,65};66use rustc_index::{Idx, IndexVec};67use rustc_macros::extension;68use rustc_middle::queries::Providers;69use rustc_middle::span_bug;70use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt};71use rustc_session::diagnostics::add_feature_diagnostics;72use rustc_span::symbol::{Ident, Symbol, kw, sym};73use rustc_span::{DUMMY_SP, DesugaringKind, Span};74use smallvec::{SmallVec, smallvec};75use thin_vec::ThinVec;76use tracing::{debug, instrument, trace};7778use crate::diagnostics::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};7980macro_rules! arena_vec {81 ($this:expr; $($x:expr),*) => (82 $this.arena.alloc_from_iter([$($x),*])83 );84}8586mod asm;87mod block;88mod contract;89mod delegation;90mod diagnostics;91mod expr;92mod format;93mod index;94mod item;95mod pat;96mod path;97pub mod stability;9899pub fn provide(providers: &mut Providers) {100 providers.index_ast = index_ast;101 providers.lower_to_hir = lower_to_hir;102}103104#[cfg(debug_assertions)]105pub(crate) mod re_lowering {106 use rustc_ast::NodeId;107 use rustc_ast::node_id::NodeMap;108 use rustc_hir as hir;109110 use crate::LoweringContext;111112 #[derive(Debug, Default)]113 pub(crate) struct ReloweringChecker {114 node_id_to_local_id: NodeMap<hir::ItemLocalId>,115 can_relower: bool,116 }117118 impl ReloweringChecker {119 pub(crate) fn assert_node_is_not_relowered(120 &mut self,121 ast_node_id: NodeId,122 local_id: hir::ItemLocalId,123 ) {124 if !self.can_relower {125 let old = self.node_id_to_local_id.insert(ast_node_id, local_id);126 assert_eq!(old, None);127 }128 }129130 pub(crate) fn allow_relowering<'a, 'hir, TRes>(131 ctx: &mut LoweringContext<'a, 'hir>,132 op: impl FnOnce(&mut LoweringContext<'a, 'hir>) -> TRes,133 ) -> TRes {134 assert!(!ctx.relowering_checker.can_relower, "reentrant relowering is not supported");135136 ctx.relowering_checker.can_relower = true;137138 let res = op(ctx);139140 ctx.relowering_checker.can_relower = false;141142 res143 }144 }145}146147struct LoweringContext<'a, 'hir> {148 tcx: TyCtxt<'hir>,149 resolver: &'a ResolverAstLowering<'hir>,150 current_disambiguator: PerParentDisambiguatorState,151152 /// Used to allocate HIR nodes.153 arena: &'hir hir::Arena<'hir>,154155 /// Bodies inside the owner being lowered.156 bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,157 /// `#[define_opaque]` attributes158 define_opaque: Option<&'hir [(Span, LocalDefId)]>,159 /// Attributes inside the owner being lowered.160 attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,161 /// Collect items that were created by lowering the current owner.162 children: LocalDefIdMap<hir::MaybeOwner<'hir>>,163164 contract_ensures: Option<(Span, Ident, HirId)>,165166 coroutine_kind: Option<hir::CoroutineKind>,167168 /// When inside an `async` context, this is the `HirId` of the169 /// `task_context` local bound to the resume argument of the coroutine.170 task_context: Option<HirId>,171172 /// Used to get the current `fn`'s def span to point to when using `await`173 /// outside of an `async fn`.174 current_item: Option<Span>,175176 try_block_scope: TryBlockScope,177 loop_scope: Option<HirId>,178 is_in_loop_condition: bool,179 is_in_dyn_type: bool,180181 current_hir_id_owner: hir::OwnerId,182 owner: &'a PerOwnerResolverData<'hir>,183 item_local_id_counter: hir::ItemLocalId,184 trait_map: ItemLocalMap<&'hir [TraitCandidate<'hir>]>,185186 impl_trait_defs: Vec<hir::GenericParam<'hir>>,187 impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,188189 /// NodeIds of pattern identifiers and labelled nodes that are lowered inside the current HIR owner.190 ident_and_label_to_local_id: NodeMap<hir::ItemLocalId>,191 /// NodeIds that are lowered inside the current HIR owner. Only used for duplicate lowering check.192 #[cfg(debug_assertions)]193 relowering_checker: re_lowering::ReloweringChecker,194 /// The `NodeId` space is split in two.195 /// `0..resolver.next_node_id` are created by the resolver on the AST.196 /// The higher part `resolver.next_node_id..next_node_id` are created during lowering.197 next_node_id: NodeId,198 /// Maps the `NodeId`s created during lowering to `LocalDefId`s.199 node_id_to_def_id: NodeMap<LocalDefId>,200 /// Overlay over resolver's `partial_res_map` used by delegation.201 /// This only contains `PartialRes::new(Res::Local(self_param_id))`,202 /// so we only store `self_param_id`.203 partial_res_overrides: NodeMap<NodeId>,204205 allow_contracts: Arc<[Symbol]>,206 allow_try_trait: Arc<[Symbol]>,207 allow_gen_future: Arc<[Symbol]>,208 allow_pattern_type: Arc<[Symbol]>,209 allow_async_gen: Arc<[Symbol]>,210 allow_async_iterator: Arc<[Symbol]>,211 allow_for_await: Arc<[Symbol]>,212 allow_async_fn_traits: Arc<[Symbol]>,213214 delayed_lints: Vec<DelayedLint>,215216 /// Stack of `move(...)` collection states. A plain closure body pushes217 /// `Some`, so `move(...)` expressions can record the generated locals they218 /// should lower to. Nested bodies that cannot use `move(...)` push `None`.219 move_expr_bindings: Vec<Option<expr::MoveExprState<'hir>>>,220221 attribute_parser: AttributeParser<'hir>,222}223224impl<'a, 'hir> LoweringContext<'a, 'hir> {225 fn new(tcx: TyCtxt<'hir>, resolver: &'a ResolverAstLowering<'hir>, owner: NodeId) -> Self {226 let current_ast_owner = &resolver.owners[&owner];227 let current_hir_id_owner = hir::OwnerId { def_id: current_ast_owner.def_id };228 let current_disambiguator = resolver229 .disambiguators230 .get(¤t_hir_id_owner.def_id)231 .map(|s| s.steal())232 .unwrap_or_else(|| PerParentDisambiguatorState::new(current_hir_id_owner.def_id));233234 Self {235 tcx,236 resolver,237 current_disambiguator,238 owner: current_ast_owner,239 arena: tcx.hir_arena,240241 // HirId handling.242 bodies: Vec::new(),243 define_opaque: None,244 attrs: SortedMap::default(),245 children: LocalDefIdMap::default(),246 contract_ensures: None,247 current_hir_id_owner,248 // 0 corresponds to `owner` lowered as `current_hir_id_owner`,249 // and we never call `lower_node_id(owner)`.250 item_local_id_counter: hir::ItemLocalId::new(1),251 ident_and_label_to_local_id: Default::default(),252253 #[cfg(debug_assertions)]254 relowering_checker: Default::default(),255256 trait_map: Default::default(),257 next_node_id: resolver.next_node_id,258 node_id_to_def_id: NodeMap::default(),259 partial_res_overrides: NodeMap::default(),260261 // Lowering state.262 try_block_scope: TryBlockScope::Function,263 loop_scope: None,264 is_in_loop_condition: false,265 is_in_dyn_type: false,266 coroutine_kind: None,267 task_context: None,268 current_item: None,269 impl_trait_defs: Vec::new(),270 impl_trait_bounds: Vec::new(),271 allow_contracts: [sym::contracts_internals].into(),272 allow_try_trait: [273 sym::try_trait_v2,274 sym::try_trait_v2_residual,275 sym::yeet_desugar_details,276 ]277 .into(),278 allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),279 allow_gen_future: if tcx.features().async_fn_track_caller() {280 [sym::gen_future, sym::closure_track_caller].into()281 } else {282 [sym::gen_future].into()283 },284 allow_for_await: [sym::async_gen_internals, sym::async_iterator].into(),285 allow_async_fn_traits: [sym::async_fn_traits].into(),286 allow_async_gen: [sym::async_gen_internals].into(),287 // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller`288 // interact with `gen`/`async gen` blocks289 allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),290291 move_expr_bindings: Vec::new(),292 attribute_parser: AttributeParser::new(293 tcx.sess,294 tcx.features(),295 tcx.registered_attr_tools(()),296 ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },297 ),298 delayed_lints: Vec::new(),299 }300 }301302 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'hir> {303 self.tcx.dcx()304 }305}306307struct SpanLowerer {308 is_incremental: bool,309 def_id: LocalDefId,310}311312impl SpanLowerer {313 fn lower(&self, span: Span) -> Span {314 if self.is_incremental {315 span.with_parent(Some(self.def_id))316 } else {317 // Do not make spans relative when not using incremental compilation.318 span319 }320 }321}322323#[extension(trait ResolverAstLoweringExt<'tcx>)]324impl<'tcx> ResolverAstLowering<'tcx> {325 fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option<Vec<usize>> {326 let ExprKind::Path(None, path) = &expr.kind else {327 return None;328 };329330 // Don't perform legacy const generics rewriting if the path already331 // has generic arguments.332 if path.segments.last().unwrap().args.is_some() {333 return None;334 }335336 // We do not need to look at `partial_res_overrides`. That map only contains overrides for337 // `self_param` locals. And here we are looking for the function definition that `expr`338 // resolves to.339 let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?;340341 // We only support cross-crate argument rewriting. Uses342 // within the same crate should be updated to use the new343 // const generics style.344 if def_id.is_local() {345 return None;346 }347348 // we can use parsed attrs here since for other crates they're already available349 find_attr!(350 tcx, def_id,351 RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes352 )353 .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect())354 }355}356357/// How relaxed bounds `?Trait` should be treated.358///359/// Relaxed bounds should only be allowed in places where we later360/// (namely during HIR ty lowering) perform *sized elaboration*.361#[derive(Debug)]362enum RelaxedBoundPolicy<'a> {363 /// The `DefId` refers to the trait that is being relaxed.364 Allowed(&'a mut FxIndexMap<DefId, Span>),365 Forbidden(RelaxedBoundForbiddenReason),366}367impl RelaxedBoundPolicy<'_> {368 fn reborrow(&mut self) -> RelaxedBoundPolicy<'_> {369 match self {370 RelaxedBoundPolicy::Allowed(m) => RelaxedBoundPolicy::Allowed(m),371 RelaxedBoundPolicy::Forbidden(reason) => RelaxedBoundPolicy::Forbidden(*reason),372 }373 }374}375376#[derive(Clone, Copy, Debug)]377enum RelaxedBoundForbiddenReason {378 TraitObjectTy,379 SuperTrait,380 TraitAlias,381 AssocTyBounds,382 /// We do not allow where bounds doing relaxed bounds,383 /// except if it's for generic parameters of the current item.384 WhereBound,385}386387/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,388/// and if so, what meaning it has.389#[derive(Debug, Copy, Clone, PartialEq, Eq)]390enum ImplTraitContext {391 /// Treat `impl Trait` as shorthand for a new universal generic parameter.392 /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually393 /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.394 ///395 /// Newly generated parameters should be inserted into the given `Vec`.396 Universal,397398 /// Treat `impl Trait` as shorthand for a new opaque type.399 /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually400 /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.401 ///402 OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> },403404 /// Treat `impl Trait` as a "trait ascription", which is like a type405 /// variable but that also enforces that a set of trait goals hold.406 ///407 /// This is useful to guide inference for unnameable types.408 InBinding,409410 /// `impl Trait` is unstably accepted in this position.411 FeatureGated(ImplTraitPosition, Symbol),412 /// `impl Trait` is not accepted in this position.413 Disallowed(ImplTraitPosition),414415 /// An error has already been emitted for this type.416 AlreadyErrored(ErrorGuaranteed),417}418419/// Position in which `impl Trait` is disallowed.420#[derive(Debug, Copy, Clone, PartialEq, Eq)]421enum ImplTraitPosition {422 Path,423 Variable,424 Trait,425 Bound,426 Generic,427 ExternFnParam,428 ClosureParam,429 PointerParam,430 FnTraitParam,431 ExternFnReturn,432 ClosureReturn,433 PointerReturn,434 FnTraitReturn,435 GenericDefault,436 ConstTy,437 StaticTy,438 AssocTy,439 FieldTy,440 Cast,441 ImplSelf,442 OffsetOf,443}444445impl std::fmt::Display for ImplTraitPosition {446 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {447 let name = match self {448 ImplTraitPosition::Path => "paths",449 ImplTraitPosition::Variable => "the type of variable bindings",450 ImplTraitPosition::Trait => "traits",451 ImplTraitPosition::Bound => "bounds",452 ImplTraitPosition::Generic => "generics",453 ImplTraitPosition::ExternFnParam => "`extern fn` parameters",454 ImplTraitPosition::ClosureParam => "closure parameters",455 ImplTraitPosition::PointerParam => "`fn` pointer parameters",456 ImplTraitPosition::FnTraitParam => "the parameters of `Fn` trait bounds",457 ImplTraitPosition::ExternFnReturn => "`extern fn` return types",458 ImplTraitPosition::ClosureReturn => "closure return types",459 ImplTraitPosition::PointerReturn => "`fn` pointer return types",460 ImplTraitPosition::FnTraitReturn => "the return type of `Fn` trait bounds",461 ImplTraitPosition::GenericDefault => "generic parameter defaults",462 ImplTraitPosition::ConstTy => "const types",463 ImplTraitPosition::StaticTy => "static types",464 ImplTraitPosition::AssocTy => "associated types",465 ImplTraitPosition::FieldTy => "field types",466 ImplTraitPosition::Cast => "cast expression types",467 ImplTraitPosition::ImplSelf => "impl headers",468 ImplTraitPosition::OffsetOf => "`offset_of!` parameters",469 };470471 write!(f, "{name}")472 }473}474475#[derive(Copy, Clone, Debug, PartialEq, Eq)]476enum FnDeclKind {477 Fn,478 Inherent,479 ExternFn,480 Closure,481 Pointer,482 Trait,483 Impl,484}485486#[derive(Copy, Clone, Debug)]487enum TryBlockScope {488 /// There isn't a `try` block, so a `?` will use `return`.489 Function,490 /// We're inside a `try { … }` block, so a `?` will block-break491 /// from that block using a type depending only on the argument.492 Homogeneous(HirId),493 /// We're inside a `try as _ { … }` block, so a `?` will block-break494 /// from that block using the type specified.495 Heterogeneous(HirId),496}497498fn index_ast<'tcx>(499 tcx: TyCtxt<'tcx>,500 (): (),501) -> IndexVec<LocalDefId, Steal<(Arc<ResolverAstLowering<'tcx>>, AstOwner)>> {502 // Queries that borrow `resolver_for_lowering`.503 tcx.ensure_done().output_filenames(());504 tcx.ensure_done().early_lint_checks(());505 tcx.ensure_done().get_lang_items(());506 tcx.ensure_done().debugger_visualizers(LOCAL_CRATE);507508 let (resolver, krate) = tcx.resolver_for_lowering();509 let mut resolver = resolver.steal();510 let mut krate = krate.steal();511512 let mut indexer = Indexer {513 owners: &resolver.owners,514 index: IndexVec::new(),515 next_node_id: resolver.next_node_id,516 };517 indexer.visit_crate(&mut krate);518 indexer.insert(CRATE_NODE_ID, AstOwner::Crate(Box::new(krate)));519 resolver.next_node_id = indexer.next_node_id;520521 let index = indexer.index;522 let resolver = Arc::new(resolver);523 let index = index.into_iter().map(|owner| Steal::new((Arc::clone(&resolver), owner))).collect();524 return index;525526 struct Indexer<'s, 'hir> {527 owners: &'s NodeMap<PerOwnerResolverData<'hir>>,528 index: IndexVec<LocalDefId, AstOwner>,529 next_node_id: NodeId,530 }531532 impl Indexer<'_, '_> {533 fn insert(&mut self, id: NodeId, node: AstOwner) {534 let def_id = self.owners[&id].def_id;535 self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);536 self.index[def_id] = node;537 }538539 fn make_dummy<K>(540 &mut self,541 id: NodeId,542 span: Span,543 dummy: impl FnOnce(Box<MacCall>) -> K,544 ) -> Box<Item<K>> {545 use rustc_ast::token::Delimiter;546 use rustc_ast::tokenstream::{DelimSpan, TokenStream};547 use thin_vec::thin_vec;548549 Box::new(Item {550 attrs: AttrVec::default(),551 id,552 span,553 vis: Visibility { kind: VisibilityKind::Public, span },554 // Lacking a better choice, we replace the contents with a macro call.555 // Unexpanded macros should never reach lowering, so this is not confusing.556 kind: dummy(Box::new(MacCall {557 path: Path { span, segments: thin_vec![] },558 args: Box::new(DelimArgs {559 dspan: DelimSpan::from_single(span),560 delim: Delimiter::Parenthesis,561 tokens: TokenStream::new(Vec::new()),562 }),563 })),564 tokens: None,565 })566 }567568 fn replace_with_dummy<K>(569 &mut self,570 item: &mut ast::Item<K>,571 dummy: impl FnOnce(Box<MacCall>) -> K,572 node: impl FnOnce(Box<Item<K>>) -> AstOwner,573 ) {574 let dummy = self.make_dummy(item.id, item.span, dummy);575 let item = mem::replace(item, *dummy);576 self.insert(item.id, node(Box::new(item)));577 }578579 #[tracing::instrument(level = "trace", skip(self))]580 fn visit_item_id_use_tree(581 &mut self,582 tree: &UseTree,583 parent: LocalDefId,584 items: &mut SmallVec<[Box<Item>; 1]>,585 ) {586 match tree.kind {587 UseTreeKind::Glob(_) | UseTreeKind::Simple(_) => {}588 UseTreeKind::Nested { items: ref nested_vec, span } => {589 for &(ref nested, id) in nested_vec {590 self.insert(id, AstOwner::NestedUseTree(parent));591 items.push(self.make_dummy(id, span, ItemKind::MacCall));592593 let def_id = self.owners[&id].def_id;594 self.visit_item_id_use_tree(nested, def_id, items);595 }596 }597 }598 }599 }600601 impl MutVisitor for Indexer<'_, '_> {602 fn visit_attribute(&mut self, _: &mut Attribute) {603 // We do not want to lower expressions that appear in attributes,604 // as they are not accessible to the rest of the HIR.605 }606607 fn flat_map_item(&mut self, mut item: Box<Item>) -> SmallVec<[Box<Item>; 1]> {608 let def_id = self.owners[&item.id].def_id;609 mut_visit::walk_item(self, &mut *item);610 let dummy = self.make_dummy(item.id, item.span, ItemKind::MacCall);611 let mut items = smallvec![dummy];612 if let ItemKind::Use(ref use_tree) = item.kind {613 self.visit_item_id_use_tree(use_tree, def_id, &mut items);614 }615 self.insert(item.id, AstOwner::Item(item));616 items617 }618619 fn flat_map_stmt(&mut self, stmt: Stmt) -> SmallVec<[Stmt; 1]> {620 let Stmt { id, span, kind } = stmt;621 let mut id = Some(id);622 mut_visit::walk_flat_map_stmt_kind(self, kind)623 .into_iter()624 .map(|kind| {625 // Expanding the current statement is a nested `use` item,626 // it is expanded into several flat `use` items.627 // Create new NodeIds for the corresponding statements628 // as two statements cannot have the same.629 let id = id.take().unwrap_or_else(|| {630 let next = self.next_node_id;631 self.next_node_id.increment_by(1);632 next633 });634 Stmt { id, kind, span }635 })636 .collect()637 }638639 fn visit_assoc_item(&mut self, item: &mut AssocItem, ctxt: visit::AssocCtxt) {640 mut_visit::walk_assoc_item(self, item, ctxt);641 match ctxt {642 visit::AssocCtxt::Trait => {643 self.replace_with_dummy(item, AssocItemKind::MacCall, AstOwner::TraitItem)644 }645 visit::AssocCtxt::Impl { .. } => {646 self.replace_with_dummy(item, AssocItemKind::MacCall, AstOwner::ImplItem)647 }648 }649 }650651 fn visit_foreign_item(&mut self, item: &mut ForeignItem) {652 mut_visit::walk_item(self, item);653 self.replace_with_dummy(item, ForeignItemKind::MacCall, AstOwner::ForeignItem);654 }655 }656}657658#[instrument(level = "trace", skip(tcx))]659fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> {660 let ast_index = tcx.index_ast(());661 let resolver_and_node = ast_index.get(def_id).map(Steal::steal);662663 let fallback_to_ancestor = |parent_id| {664 // The item did not exist in the AST, it was created while lowering another item.665 // `parent_id` may be different from the direct parent of `def_id`,666 // for instance use-trees are lowered by the first sibling.667 let mut parent_info = tcx.lower_to_hir(parent_id);668 if let hir::MaybeOwner::NonOwner(hir_id) = parent_info {669 // `parent_id` could also not be a owner either.670 // For instance if `def_id` is an enum variant field,671 // the direct parent is the enum variant.672 // In that case `hir_id.owner` point to the actual HIR owner673 // and skips all non-owner parents, so fetch the HIR associated to it.674 parent_info = tcx.lower_to_hir(hir_id.owner);675 }676677 let parent_info = parent_info.unwrap();678 *parent_info.children.get(&def_id).unwrap_or_else(|| {679 panic!(680 "{:?} does not appear in children of {:?}",681 def_id,682 parent_info.nodes.node().def_id()683 )684 })685 };686687 let Some((resolver, node)) = resolver_and_node else {688 // `ast_index` does not contain all definitions, only up-to the highest689 // `LocalDefId` which has a non-trivial `AstOwner`. Gracefully handle690 // other definitions, in particular those nested inside this highest definition.691 return fallback_to_ancestor(tcx.local_parent(def_id));692 };693694 let mut item_lowerer = item::ItemLowerer { tcx, resolver: &*resolver };695696 let item = match &node {697 // The item existed in the AST.698 AstOwner::Crate(c) => item_lowerer.lower_crate(&c),699 AstOwner::Item(item) => item_lowerer.lower_item(&item),700 AstOwner::TraitItem(item) => item_lowerer.lower_trait_item(&item),701 AstOwner::ImplItem(item) => item_lowerer.lower_impl_item(&item),702 AstOwner::ForeignItem(item) => item_lowerer.lower_foreign_item(&item),703 AstOwner::NestedUseTree(owner_id) => fallback_to_ancestor(*owner_id),704 // The item existed in the AST, but is not a HIR owner.705 // Fetch the correct information from its parent.706 AstOwner::NonOwner => fallback_to_ancestor(tcx.local_parent(def_id)),707 };708709 tcx.sess.time("drop_ast", || mem::drop(node));710711 item712}713714#[derive(Copy, Clone, PartialEq, Debug)]715enum ParamMode {716 /// Any path in a type context.717 Explicit,718 /// The `module::Type` in `module::Type::method` in an expression.719 Optional,720}721722#[derive(Copy, Clone, Debug)]723enum AllowReturnTypeNotation {724 /// Only in types, since RTN is denied later during HIR lowering.725 Yes,726 /// All other positions (path expr, method, use tree).727 No,728}729730enum GenericArgsMode {731 /// Allow paren sugar, don't allow RTN.732 ParenSugar,733 /// Allow RTN, don't allow paren sugar.734 ReturnTypeNotation,735 // Error if parenthesized generics or RTN are encountered.736 Err,737 /// Silence errors when lowering generics. Only used with `Res::Err`.738 Silence,739}740741impl<'hir> LoweringContext<'_, 'hir> {742 fn create_def(743 &mut self,744 node_id: NodeId,745 name: Option<Symbol>,746 def_kind: DefKind,747 span: Span,748 ) -> LocalDefId {749 let parent = self.current_hir_id_owner.def_id;750 assert_ne!(node_id, ast::DUMMY_NODE_ID);751 assert!(752 self.opt_local_def_id(node_id).is_none(),753 "adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",754 node_id,755 def_kind,756 self.tcx.hir_def_key(self.local_def_id(node_id)),757 );758759 let def_id = self760 .tcx761 .at(span)762 .create_def(parent, name, def_kind, None, &mut self.current_disambiguator)763 .def_id();764765 debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);766 self.node_id_to_def_id.insert(node_id, def_id);767768 def_id769 }770771 fn next_node_id(&mut self) -> NodeId {772 let start = self.next_node_id;773 let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");774 self.next_node_id = NodeId::from_u32(next);775 start776 }777778 /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name779 /// resolver (if any).780 #[instrument(level = "trace", skip(self), ret)]781 fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {782 self.node_id_to_def_id783 .get(&node)784 .or_else(|| self.owner.node_id_to_def_id.get(&node))785 .copied()786 }787788 fn local_def_id(&self, node: NodeId) -> LocalDefId {789 self.opt_local_def_id(node).unwrap_or_else(|| {790 self.resolver.owners.items().any(|(id, items)| {791 items.node_id_to_def_id.items().any(|(node_id, def_id)| {792 if *node_id == node {793 let actual_owner = items.node_id_to_def_id.get(id);794 panic!("{def_id:?} ({node_id}) was found in {actual_owner:?} ({id})",)795 }796 false797 })798 });799 panic!("no entry for node id: `{node:?}`");800 })801 }802803 fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {804 match self.partial_res_overrides.get(&id) {805 Some(self_param_id) => Some(PartialRes::new(Res::Local(*self_param_id))),806 None => self.resolver.partial_res_map.get(&id).copied(),807 }808 }809810 /// Given the id of an owner node in the AST, returns the corresponding `OwnerId`.811 fn owner_id(&self, node: NodeId) -> hir::OwnerId {812 hir::OwnerId { def_id: self.resolver.owners[&node].def_id }813 }814815 /// Freshen the `LoweringContext` and ready it to lower a nested item.816 /// The lowered item is registered into `self.children`.817 ///818 /// This function sets up `HirId` lowering infrastructure,819 /// and stashes the shared mutable state to avoid pollution by the closure.820 #[instrument(level = "debug", skip(self, f))]821 fn with_hir_id_owner(822 &mut self,823 owner: NodeId,824 f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,825 ) {826 let owner_id = self.owner_id(owner);827 let def_id = owner_id.def_id;828829 let new_disambig = self830 .resolver831 .disambiguators832 .get(&def_id)833 .map(|s| s.steal())834 .unwrap_or_else(|| PerParentDisambiguatorState::new(def_id));835836 let disambiguator = mem::replace(&mut self.current_disambiguator, new_disambig);837 let current_ast_owner = mem::replace(&mut self.owner, &self.resolver.owners[&owner]);838 let current_attrs = mem::take(&mut self.attrs);839 let current_bodies = mem::take(&mut self.bodies);840 let current_define_opaque = mem::take(&mut self.define_opaque);841 let current_ident_and_label_to_local_id = mem::take(&mut self.ident_and_label_to_local_id);842843 #[cfg(debug_assertions)]844 let current_relowering_checker = mem::take(&mut self.relowering_checker);845 let current_trait_map = mem::take(&mut self.trait_map);846 let current_owner = mem::replace(&mut self.current_hir_id_owner, owner_id);847 let current_local_counter =848 mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));849 let current_impl_trait_defs = mem::take(&mut self.impl_trait_defs);850 let current_impl_trait_bounds = mem::take(&mut self.impl_trait_bounds);851 let current_delayed_lints = mem::take(&mut self.delayed_lints);852 let current_children = mem::take(&mut self.children);853854 // Do not reset `next_node_id` and `node_id_to_def_id`:855 // we want `f` to be able to refer to the `LocalDefId`s that the caller created.856 // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s.857858 // Always allocate the first `HirId` for the owner itself.859 #[cfg(debug_assertions)]860 self.relowering_checker.assert_node_is_not_relowered(owner, hir::ItemLocalId::ZERO);861862 let item = f(self);863 assert_eq!(owner_id, item.def_id());864 // `f` should have consumed all the elements in these vectors when constructing `item`.865 assert!(self.impl_trait_defs.is_empty());866 assert!(self.impl_trait_bounds.is_empty());867 let info = self.make_owner_info(item);868869 self.current_disambiguator = disambiguator;870 self.owner = current_ast_owner;871 self.attrs = current_attrs;872 self.bodies = current_bodies;873 self.define_opaque = current_define_opaque;874 self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;875876 #[cfg(debug_assertions)]877 {878 self.relowering_checker = current_relowering_checker;879 }880 self.trait_map = current_trait_map;881 self.current_hir_id_owner = current_owner;882 self.item_local_id_counter = current_local_counter;883 self.impl_trait_defs = current_impl_trait_defs;884 self.impl_trait_bounds = current_impl_trait_bounds;885 self.delayed_lints = current_delayed_lints;886 self.children = current_children;887 self.children.extend_unord(info.children.items().map(|(&def_id, &info)| (def_id, info)));888889 debug_assert!(!self.children.contains_key(&owner_id.def_id));890 self.children.insert(owner_id.def_id, hir::MaybeOwner::Owner(info));891 }892893 fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {894 let attrs = mem::take(&mut self.attrs);895 let mut bodies = mem::take(&mut self.bodies);896 let define_opaque = mem::take(&mut self.define_opaque);897 let trait_map = mem::take(&mut self.trait_map);898 let delayed_lints = Steal::new(mem::take(&mut self.delayed_lints).into_boxed_slice());899 let children = mem::take(&mut self.children);900901 #[cfg(debug_assertions)]902 for (id, attrs) in attrs.iter() {903 // Verify that we do not store empty slices in the map.904 if attrs.is_empty() {905 panic!("Stored empty attributes for {:?}", id);906 }907 }908909 bodies.sort_by_key(|(k, _)| *k);910 let bodies = SortedMap::from_presorted_elements(bodies);911912 // Don't hash unless necessary, because it's expensive.913 let rustc_middle::hir::Hashes { bodies_hash, attrs_hash } =914 self.tcx.hash_owner_nodes(node, &bodies, &attrs, define_opaque);915 let num_nodes = self.item_local_id_counter.as_usize();916 let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);917 let nodes = hir::OwnerNodes { opt_hash: bodies_hash, nodes, bodies };918 let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };919920 let opt_hash = self.tcx.needs_hir_hash().then(|| {921 self.tcx.with_stable_hashing_context(|mut hcx| {922 let mut stable_hasher = StableHasher::new();923 bodies_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);924 attrs_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher);925 // Do not hash delayed_lints.926 parenting.stable_hash(&mut hcx, &mut stable_hasher);927 trait_map.stable_hash(&mut hcx, &mut stable_hasher);928 children.stable_hash(&mut hcx, &mut stable_hasher);929 stable_hasher.finish()930 })931 });932933 self.arena.alloc(hir::OwnerInfo {934 opt_hash,935 nodes,936 parenting,937 attrs,938 trait_map,939 delayed_lints,940 children,941 })942 }943944 /// This method allocates a new `HirId` for the given `NodeId`.945 /// Take care not to call this method if the resulting `HirId` is then not946 /// actually used in the HIR, as that would trigger an assertion in the947 /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped948 /// properly. Calling the method twice with the same `NodeId` is also forbidden.949 #[instrument(level = "debug", skip(self), ret)]950 fn lower_node_id(&mut self, ast_node_id: NodeId) -> HirId {951 assert_ne!(ast_node_id, DUMMY_NODE_ID);952953 let owner = self.current_hir_id_owner;954 let local_id = self.item_local_id_counter;955 assert_ne!(local_id, hir::ItemLocalId::ZERO);956 self.item_local_id_counter.increment_by(1);957 let hir_id = HirId { owner, local_id };958959 if let Some(def_id) = self.opt_local_def_id(ast_node_id) {960 self.children.insert(def_id, hir::MaybeOwner::NonOwner(hir_id));961 }962963 if let Some(traits) = self.owner.trait_map.get(&ast_node_id) {964 self.trait_map.insert(hir_id.local_id, *traits);965 }966967 // Check whether the same `NodeId` is lowered more than once.968 #[cfg(debug_assertions)]969 self.relowering_checker.assert_node_is_not_relowered(ast_node_id, local_id);970971 hir_id972 }973974 /// Generate a new `HirId` without a backing `NodeId`.975 #[instrument(level = "debug", skip(self), ret)]976 fn next_id(&mut self) -> HirId {977 let owner = self.current_hir_id_owner;978 let local_id = self.item_local_id_counter;979 assert_ne!(local_id, hir::ItemLocalId::ZERO);980 self.item_local_id_counter.increment_by(1);981 HirId { owner, local_id }982 }983984 #[instrument(level = "trace", skip(self))]985 fn lower_res(&mut self, res: Res<NodeId>) -> Res {986 let res: Result<Res, ()> = res.apply_id(|id| {987 let owner = self.current_hir_id_owner;988 let local_id = self.ident_and_label_to_local_id.get(&id).copied().ok_or(())?;989 Ok(HirId { owner, local_id })990 });991 trace!(?res);992993 // We may fail to find a HirId when the Res points to a Local from an enclosing HIR owner.994 // This can happen when trying to lower the return type `x` in erroneous code like995 // async fn foo(x: u8) -> x {}996 // In that case, `x` is lowered as a function parameter, and the return type is lowered as997 // an opaque type as a synthesized HIR owner.998 res.unwrap_or(Res::Err)999 }10001001 fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> {1002 self.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())1003 }10041005 fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS<Option<Res>> {1006 debug_assert_eq!(id, self.owner.id);1007 let per_ns = self.owner.import_res.map(|res| res.map(|res| self.lower_res(res)));1008 if per_ns.is_empty() {1009 // Propagate the error to all namespaces, just to be sure.1010 self.dcx().span_delayed_bug(span, "no resolution for an import");1011 let err = Some(Res::Err);1012 return PerNS { type_ns: err, value_ns: err, macro_ns: err };1013 }1014 per_ns1015 }10161017 fn make_lang_item_qpath(1018 &mut self,1019 lang_item: LangItem,1020 span: Span,1021 args: Option<&'hir hir::GenericArgs<'hir>>,1022 ) -> hir::QPath<'hir> {1023 hir::QPath::Resolved(None, self.make_lang_item_path(lang_item, span, args))1024 }10251026 fn make_lang_item_path(1027 &mut self,1028 lang_item: LangItem,1029 span: Span,1030 args: Option<&'hir hir::GenericArgs<'hir>>,1031 ) -> &'hir hir::Path<'hir> {1032 let def_id = self.tcx.require_lang_item(lang_item, span);1033 let def_kind = self.tcx.def_kind(def_id);1034 let res = Res::Def(def_kind, def_id);1035 self.arena.alloc(hir::Path {1036 span,1037 res,1038 segments: self.arena.alloc_from_iter([hir::PathSegment {1039 ident: Ident::new(lang_item.name(), span),1040 hir_id: self.next_id(),1041 res,1042 args,1043 infer_args: args.is_none(),1044 delegation_child_segment: false,1045 }]),1046 })1047 }10481049 /// Reuses the span but adds information like the kind of the desugaring and features that are1050 /// allowed inside this span.1051 fn mark_span_with_reason(1052 &self,1053 reason: DesugaringKind,1054 span: Span,1055 allow_internal_unstable: Option<Arc<[Symbol]>>,1056 ) -> Span {1057 self.tcx.with_stable_hashing_context(|hcx| {1058 span.mark_with_reason(allow_internal_unstable, reason, span.edition(), hcx)1059 })1060 }10611062 fn span_lowerer(&self) -> SpanLowerer {1063 SpanLowerer {1064 is_incremental: self.tcx.sess.opts.incremental.is_some(),1065 def_id: self.current_hir_id_owner.def_id,1066 }1067 }10681069 /// Intercept all spans entering HIR.1070 /// Mark a span as relative to the current owning item.1071 fn lower_span(&self, span: Span) -> Span {1072 self.span_lowerer().lower(span)1073 }10741075 fn lower_ident(&self, ident: Ident) -> Ident {1076 Ident::new(ident.name, self.lower_span(ident.span))1077 }10781079 /// Converts a lifetime into a new generic parameter.1080 #[instrument(level = "debug", skip(self))]1081 fn lifetime_res_to_generic_param(1082 &mut self,1083 ident: Ident,1084 node_id: NodeId,1085 kind: MissingLifetimeKind,1086 source: hir::GenericParamSource,1087 ) -> hir::GenericParam<'hir> {1088 // Late resolution delegates to us the creation of the `LocalDefId`.1089 let _def_id = self.create_def(1090 node_id,1091 Some(kw::UnderscoreLifetime),1092 DefKind::LifetimeParam,1093 ident.span,1094 );1095 debug!(?_def_id);10961097 let hir_id = self.lower_node_id(node_id);1098 let def_id = self.local_def_id(node_id);1099 hir::GenericParam {1100 hir_id,1101 def_id,1102 name: hir::ParamName::Fresh,1103 span: self.lower_span(ident.span),1104 pure_wrt_drop: false,1105 kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided(kind) },1106 colon_span: None,1107 source,1108 }1109 }11101111 /// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR1112 /// nodes. The returned list includes any "extra" lifetime parameters that were added by the1113 /// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id1114 /// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime1115 /// parameters will be successful.1116 #[instrument(level = "debug", skip(self), ret)]1117 #[inline]1118 fn lower_lifetime_binder(1119 &mut self,1120 binder: NodeId,1121 generic_params: &[GenericParam],1122 ) -> &'hir [hir::GenericParam<'hir>] {1123 // Start by creating params for extra lifetimes params, as this creates the definitions1124 // that may be referred to by the AST inside `generic_params`.1125 let extra_lifetimes = self.owner.extra_lifetime_params(binder);1126 debug!(?extra_lifetimes);1127 let extra_lifetimes: Vec<_> = extra_lifetimes1128 .iter()1129 .map(|&(ident, node_id, res)| {1130 self.lifetime_res_to_generic_param(1131 ident,1132 node_id,1133 res,1134 hir::GenericParamSource::Binder,1135 )1136 })1137 .collect();1138 let arena = self.arena;1139 let explicit_generic_params =1140 self.lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder);1141 arena.alloc_from_iter(explicit_generic_params.chain(extra_lifetimes.into_iter()))1142 }11431144 fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {1145 let was_in_dyn_type = self.is_in_dyn_type;1146 self.is_in_dyn_type = in_scope;11471148 let result = f(self);11491150 self.is_in_dyn_type = was_in_dyn_type;11511152 result1153 }11541155 fn with_new_scopes<T>(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T {1156 let current_item = self.current_item;1157 self.current_item = Some(scope_span);11581159 let was_in_loop_condition = self.is_in_loop_condition;1160 self.is_in_loop_condition = false;11611162 let old_contract = self.contract_ensures.take();11631164 let try_block_scope = mem::replace(&mut self.try_block_scope, TryBlockScope::Function);1165 let loop_scope = self.loop_scope.take();1166 let ret = f(self);1167 self.try_block_scope = try_block_scope;1168 self.loop_scope = loop_scope;11691170 self.contract_ensures = old_contract;11711172 self.is_in_loop_condition = was_in_loop_condition;11731174 self.current_item = current_item;11751176 ret1177 }11781179 fn lower_attrs(1180 &mut self,1181 id: HirId,1182 attrs: &[Attribute],1183 target_span: Span,1184 target: Target,1185 ) -> &'hir [hir::Attribute] {1186 self.lower_attrs_with_extra(id, attrs, target_span, target, &[])1187 }11881189 fn lower_attrs_with_extra(1190 &mut self,1191 id: HirId,1192 attrs: &[Attribute],1193 target_span: Span,1194 target: Target,1195 extra_hir_attributes: &[hir::Attribute],1196 ) -> &'hir [hir::Attribute] {1197 if attrs.is_empty() && extra_hir_attributes.is_empty() {1198 &[]1199 } else {1200 let mut lowered_attrs =1201 self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target);1202 lowered_attrs.extend(extra_hir_attributes.iter().cloned());12031204 assert_eq!(id.owner, self.current_hir_id_owner);1205 let ret = self.arena.alloc_from_iter(lowered_attrs);12061207 // this is possible if an item contained syntactical attribute,1208 // but none of them parse successfully or all of them were ignored1209 // for not being built-in attributes at all. They could be remaining1210 // unexpanded attributes used as markers in proc-macro derives for example.1211 // This will have emitted some diagnostics for the misparse, but will then1212 // not emit the attribute making the list empty.1213 if ret.is_empty() {1214 &[]1215 } else {1216 self.attrs.insert(id.local_id, ret);1217 ret1218 }1219 }1220 }12211222 fn lower_attrs_vec(1223 &mut self,1224 attrs: &[Attribute],1225 target_span: Span,1226 target_hir_id: HirId,1227 target: Target,1228 ) -> Vec<hir::Attribute> {1229 let l = self.span_lowerer();1230 self.attribute_parser.parse_attribute_list(1231 attrs,1232 target_span,1233 target,1234 OmitDoc::Lower,1235 |s| l.lower(s),1236 |lint_id, span, kind| {1237 self.delayed_lints.push(DelayedLint {1238 lint_id,1239 id: target_hir_id,1240 span,1241 callback: Box::new(move |dcx, level, sess: &dyn std::any::Any| {1242 let sess = sess1243 .downcast_ref::<rustc_session::Session>()1244 .expect("expected `Session`");1245 (kind.0)(dcx, level, sess)1246 }),1247 });1248 },1249 )1250 }12511252 fn alias_attrs(&mut self, id: HirId, target_id: HirId) {1253 assert_eq!(id.owner, self.current_hir_id_owner);1254 assert_eq!(target_id.owner, self.current_hir_id_owner);1255 if let Some(&a) = self.attrs.get(&target_id.local_id) {1256 assert!(!a.is_empty());1257 self.attrs.insert(id.local_id, a);1258 }1259 }12601261 fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs {1262 args.clone()1263 }12641265 /// Lower an associated item constraint.1266 #[instrument(level = "debug", skip_all)]1267 fn lower_assoc_item_constraint(1268 &mut self,1269 constraint: &AssocItemConstraint,1270 itctx: ImplTraitContext,1271 ) -> hir::AssocItemConstraint<'hir> {1272 debug!(?constraint, ?itctx);1273 // Lower the generic arguments for the associated item.1274 let gen_args = if let Some(gen_args) = &constraint.gen_args {1275 let gen_args_ctor = match gen_args {1276 GenericArgs::AngleBracketed(data) => {1277 self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).01278 }1279 GenericArgs::Parenthesized(data) => {1280 if let Some(first_char) = constraint.ident.as_str().chars().next()1281 && first_char.is_ascii_lowercase()1282 {1283 let err = match (&data.inputs[..], &data.output) {1284 ([_, ..], FnRetTy::Default(_)) => {1285 diagnostics::BadReturnTypeNotation::Inputs {1286 span: data.inputs_span,1287 }1288 }1289 ([], FnRetTy::Default(_)) => {1290 diagnostics::BadReturnTypeNotation::NeedsDots {1291 span: data.inputs_span,1292 }1293 }1294 // The case `T: Trait<method(..) -> Ret>` is handled in the parser.1295 (_, FnRetTy::Ty(ty)) => {1296 let span = data.inputs_span.shrink_to_hi().to(ty.span);1297 diagnostics::BadReturnTypeNotation::Output {1298 span,1299 suggestion: diagnostics::RTNSuggestion {1300 output: span,1301 input: data.inputs_span,1302 },1303 }1304 }1305 };1306 let mut err = self.dcx().create_err(err);1307 if !self.tcx.features().return_type_notation()1308 && self.tcx.sess.is_nightly_build()1309 {1310 add_feature_diagnostics(1311 &mut err,1312 &self.tcx.sess,1313 sym::return_type_notation,1314 );1315 }1316 err.emit();1317 GenericArgsCtor {1318 args: Default::default(),1319 constraints: &[],1320 parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,1321 span: data.span,1322 }1323 } else {1324 let guar = self.emit_bad_parenthesized_trait_in_assoc_ty(data);1325 self.lower_angle_bracketed_parameter_data(1326 &data.as_angle_bracketed_args(),1327 ParamMode::Explicit,1328 ImplTraitContext::AlreadyErrored(guar),1329 )1330 .01331 }1332 }1333 GenericArgs::ParenthesizedElided(span) => GenericArgsCtor {1334 args: Default::default(),1335 constraints: &[],1336 parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,1337 span: *span,1338 },1339 };1340 gen_args_ctor.into_generic_args(self)1341 } else {1342 hir::GenericArgs::NONE1343 };1344 let kind = match &constraint.kind {1345 AssocItemConstraintKind::Equality { term } => {1346 let term = match term {1347 Term::Ty(ty) => self.lower_ty_alloc(ty, itctx).into(),1348 Term::Const(c) => self.lower_anon_const_to_const_arg_and_alloc(c).into(),1349 };1350 hir::AssocItemConstraintKind::Equality { term }1351 }1352 AssocItemConstraintKind::Bound { bounds } => {1353 // Disallow ATB in dyn types1354 if self.is_in_dyn_type {1355 let suggestion = match itctx {1356 ImplTraitContext::OpaqueTy { .. } | ImplTraitContext::Universal => {1357 let bound_end_span = constraint1358 .gen_args1359 .as_ref()1360 .map_or(constraint.ident.span, |args| args.span());1361 if bound_end_span.eq_ctxt(constraint.span) {1362 Some(self.tcx.sess.source_map().next_point(bound_end_span))1363 } else {1364 None1365 }1366 }1367 _ => None,1368 };13691370 let guar = self.dcx().emit_err(diagnostics::MisplacedAssocTyBinding {1371 span: constraint.span,1372 suggestion,1373 });1374 let err_ty =1375 &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));1376 hir::AssocItemConstraintKind::Equality { term: err_ty.into() }1377 } else {1378 let bounds = self.lower_param_bounds(1379 bounds,1380 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::AssocTyBounds),1381 itctx,1382 );1383 hir::AssocItemConstraintKind::Bound { bounds }1384 }1385 }1386 };13871388 hir::AssocItemConstraint {1389 hir_id: self.lower_node_id(constraint.id),1390 ident: self.lower_ident(constraint.ident),1391 gen_args,1392 kind,1393 span: self.lower_span(constraint.span),1394 }1395 }13961397 fn emit_bad_parenthesized_trait_in_assoc_ty(1398 &self,1399 data: &ParenthesizedArgs,1400 ) -> ErrorGuaranteed {1401 // Suggest removing empty parentheses: "Trait()" -> "Trait"1402 let sub = if data.inputs.is_empty() {1403 let parentheses_span =1404 data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi());1405 AssocTyParenthesesSub::Empty { parentheses_span }1406 }1407 // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`1408 else {1409 // Start of parameters to the 1st argument1410 let open_param = data.inputs_span.shrink_to_lo().to(data1411 .inputs1412 .first()1413 .unwrap()1414 .span1415 .shrink_to_lo());1416 // End of last argument to end of parameters1417 let close_param =1418 data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi());1419 AssocTyParenthesesSub::NotEmpty { open_param, close_param }1420 };1421 self.dcx().emit_err(AssocTyParentheses { span: data.span, sub })1422 }14231424 #[instrument(level = "debug", skip(self))]1425 fn lower_generic_arg(1426 &mut self,1427 arg: &ast::GenericArg,1428 itctx: ImplTraitContext,1429 ) -> hir::GenericArg<'hir> {1430 match arg {1431 ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(1432 lt,1433 LifetimeSource::Path { angle_brackets: hir::AngleBrackets::Full },1434 lt.ident.into(),1435 )),1436 ast::GenericArg::Type(ty) => {1437 // We cannot just match on `TyKind::Infer` as `(_)` is represented as1438 // `TyKind::Paren(TyKind::Infer)` and should also be lowered to `GenericArg::Infer`1439 if ty.is_maybe_parenthesised_infer() {1440 return GenericArg::Infer(self.arena.alloc(hir::InferArg {1441 hir_id: self.lower_node_id(ty.id),1442 span: self.lower_span(ty.span),1443 kind: hir::InferArgKind::TypeOrConst,1444 }));1445 }14461447 match &ty.kind {1448 // We parse const arguments as path types as we cannot distinguish them during1449 // parsing. We try to resolve that ambiguity by attempting resolution in both the1450 // type and value namespaces. If we resolved the path in the value namespace, we1451 // transform it into a generic const argument.1452 //1453 // Note that even under `#![feature(min_generic_const_args)]`, only plain paths1454 // to constants are allowed - e.g. `A::<T::ASSOC_CONST>` and1455 // `A::<CONST_WITH_PARAM::<2>>` are disallowed (they must be wrapped in `{ }`).1456 //1457 // FIXME: Should we be handling `(PATH_TO_CONST)`?1458 TyKind::Path(None, path)1459 if path.is_single_argless_ident()1460 && let Some(res) = self1461 .get_partial_res(ty.id)1462 .and_then(|partial_res| partial_res.full_res())1463 && !res.matches_ns(Namespace::TypeNS) =>1464 {1465 let ct =1466 self.lower_const_path_to_const_arg(&None, path, res, ty.id, ty.span);1467 let ct = self.arena.alloc(ct);1468 return GenericArg::Const(ct.try_as_ambig_ct().unwrap());1469 }1470 TyKind::DirectConstArg(expr)1471 if self.tcx.features().min_generic_const_args() =>1472 {1473 let ct = match self.can_lower_expr_to_const_arg_direct(1474 expr,1475 DirectConstArgContext::MacrolessMinGenericConstArgs,1476 ) {1477 Ok(()) => self.lower_expr_to_const_arg_direct(expr, None),1478 Err(e) => e.emit(self),1479 };1480 let ct = self.arena.alloc(ct);1481 return match ct.try_as_ambig_ct() {1482 Some(ct) => GenericArg::Const(ct),1483 None => GenericArg::Infer(self.arena.alloc(hir::InferArg {1484 hir_id: ct.hir_id,1485 span: ct.span,1486 kind: hir::InferArgKind::Const,1487 })),1488 };1489 }1490 _ => {}1491 }1492 GenericArg::Type(self.lower_ty_alloc(ty, itctx).try_as_ambig_ty().unwrap())1493 }1494 ast::GenericArg::Const(ct) => {1495 let ct = self.lower_anon_const_to_const_arg_and_alloc(ct);1496 match ct.try_as_ambig_ct() {1497 Some(ct) => GenericArg::Const(ct),1498 None => GenericArg::Infer(self.arena.alloc(hir::InferArg {1499 hir_id: ct.hir_id,1500 span: ct.span,1501 kind: hir::InferArgKind::Const,1502 })),1503 }1504 }1505 }1506 }15071508 #[instrument(level = "debug", skip(self))]1509 fn lower_ty_alloc(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> {1510 self.arena.alloc(self.lower_ty(t, itctx))1511 }15121513 fn lower_path_ty(1514 &mut self,1515 t: &Ty,1516 qself: &Option<Box<QSelf>>,1517 path: &Path,1518 param_mode: ParamMode,1519 itctx: ImplTraitContext,1520 ) -> hir::Ty<'hir> {1521 // Check whether we should interpret this as a bare trait object.1522 // This check mirrors the one in late resolution. We only introduce this special case in1523 // the rare occurrence we need to lower `Fresh` anonymous lifetimes.1524 // The other cases when a qpath should be opportunistically made a trait object are handled1525 // by `ty_path`.1526 if qself.is_none()1527 && let Some(partial_res) = self.get_partial_res(t.id)1528 && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()1529 {1530 let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {1531 let bound = this.lower_poly_trait_ref(1532 &PolyTraitRef {1533 bound_generic_params: ThinVec::new(),1534 modifiers: TraitBoundModifiers::NONE,1535 trait_ref: TraitRef { path: path.clone(), ref_id: t.id },1536 span: t.span,1537 parens: ast::Parens::No,1538 },1539 RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy),1540 itctx,1541 );1542 let bounds = this.arena.alloc_from_iter([bound]);1543 let lifetime_bound = this.elided_dyn_bound(t.span);1544 (bounds, lifetime_bound)1545 });1546 let kind = hir::TyKind::TraitObject(1547 bounds,1548 TaggedRef::new(lifetime_bound, TraitObjectSyntax::None),1549 );1550 return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };1551 }15521553 let id = self.lower_node_id(t.id);1554 let qpath = self.lower_qpath(1555 t.id,1556 qself,1557 path,1558 param_mode,1559 AllowReturnTypeNotation::Yes,1560 itctx,1561 None,1562 );1563 self.ty_path(id, t.span, qpath)1564 }15651566 fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> {1567 hir::Ty { hir_id: self.next_id(), kind, span: self.lower_span(span) }1568 }15691570 fn ty_tup(&mut self, span: Span, tys: &'hir [hir::Ty<'hir>]) -> hir::Ty<'hir> {1571 self.ty(span, hir::TyKind::Tup(tys))1572 }15731574 fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {1575 let kind = match &t.kind {1576 TyKind::Infer => hir::TyKind::Infer(()),1577 TyKind::Err(guar) => hir::TyKind::Err(*guar),1578 TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty_alloc(ty, itctx)),1579 TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),1580 TyKind::Ref(region, mt) => {1581 let lifetime = self.lower_ty_direct_lifetime(t, *region);1582 hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx))1583 }1584 TyKind::PinnedRef(region, mt) => {1585 let lifetime = self.lower_ty_direct_lifetime(t, *region);1586 let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx));1587 let span = self.lower_span(t.span);1588 let arg = hir::Ty { kind, span, hir_id: self.next_id() };1589 let args = self.arena.alloc(hir::GenericArgs {1590 args: self.arena.alloc([hir::GenericArg::Type(self.arena.alloc(arg))]),1591 constraints: &[],1592 parenthesized: hir::GenericArgsParentheses::No,1593 span_ext: span,1594 });1595 let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));1596 hir::TyKind::Path(path)1597 }1598 TyKind::FnPtr(f) => {1599 let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);1600 hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy {1601 generic_params,1602 safety: self.lower_safety(f.safety, hir::Safety::Safe),1603 abi: self.lower_extern(f.ext),1604 decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None),1605 param_idents: self.lower_fn_params_to_idents(&f.decl),1606 }))1607 }1608 TyKind::UnsafeBinder(f) => {1609 let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);1610 hir::TyKind::UnsafeBinder(self.arena.alloc(hir::UnsafeBinderTy {1611 generic_params,1612 inner_ty: self.lower_ty_alloc(&f.inner_ty, itctx),1613 }))1614 }1615 TyKind::Never => hir::TyKind::Never,1616 TyKind::Tup(tys) => hir::TyKind::Tup(1617 self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty(ty, itctx))),1618 ),1619 TyKind::Paren(ty) => {1620 return self.lower_ty(ty, itctx);1621 }1622 TyKind::Path(qself, path) => {1623 return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);1624 }1625 TyKind::ImplicitSelf => {1626 let hir_id = self.next_id();1627 let res = self.expect_full_res(t.id);1628 let res = self.lower_res(res);1629 hir::TyKind::Path(hir::QPath::Resolved(1630 None,1631 self.arena.alloc(hir::Path {1632 res,1633 segments: arena_vec![self; hir::PathSegment::new(1634 Ident::with_dummy_span(kw::SelfUpper),1635 hir_id,1636 res1637 )],1638 span: self.lower_span(t.span),1639 }),1640 ))1641 }1642 TyKind::Array(ty, length) => hir::TyKind::Array(1643 self.lower_ty_alloc(ty, itctx),1644 self.lower_array_length_to_const_arg(length),1645 ),1646 TyKind::TraitObject(bounds, kind) => {1647 let mut lifetime_bound = None;1648 let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {1649 let bounds =1650 this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {1651 // We can safely ignore constness here since AST validation1652 // takes care of rejecting invalid modifier combinations and1653 // const trait bounds in trait object types.1654 GenericBound::Trait(ty) => {1655 let trait_ref = this.lower_poly_trait_ref(1656 ty,1657 RelaxedBoundPolicy::Forbidden(1658 RelaxedBoundForbiddenReason::TraitObjectTy,1659 ),1660 itctx,1661 );1662 Some(trait_ref)1663 }1664 GenericBound::Outlives(lifetime) => {1665 if lifetime_bound.is_none() {1666 lifetime_bound = Some(this.lower_lifetime(1667 lifetime,1668 LifetimeSource::Other,1669 lifetime.ident.into(),1670 ));1671 }1672 None1673 }1674 // Ignore `use` syntax since that is not valid in objects.1675 GenericBound::Use(_, span) => {1676 this.dcx()1677 .span_delayed_bug(*span, "use<> not allowed in dyn types");1678 None1679 }1680 }));1681 let lifetime_bound =1682 lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));1683 (bounds, lifetime_bound)1684 });1685 hir::TyKind::TraitObject(bounds, TaggedRef::new(lifetime_bound, *kind))1686 }1687 TyKind::ImplTrait(def_node_id, bounds) => {1688 let span = t.span;1689 match itctx {1690 ImplTraitContext::OpaqueTy { origin } => {1691 self.lower_opaque_impl_trait(span, origin, *def_node_id, bounds, itctx)1692 }1693 ImplTraitContext::Universal => {1694 if let Some(span) = bounds.iter().find_map(|bound| match *bound {1695 ast::GenericBound::Use(_, span) => Some(span),1696 _ => None,1697 }) {1698 self.tcx.dcx().emit_err(diagnostics::NoPreciseCapturesOnApit { span });1699 }17001701 let def_id = self.local_def_id(*def_node_id);1702 let name = self.tcx.item_name(def_id.to_def_id());1703 let ident = Ident::new(name, span);1704 let (param, bounds, path) = self.lower_universal_param_and_bounds(1705 *def_node_id,1706 span,1707 ident,1708 bounds,1709 );1710 self.impl_trait_defs.push(param);1711 if let Some(bounds) = bounds {1712 self.impl_trait_bounds.push(bounds);1713 }1714 path1715 }1716 ImplTraitContext::InBinding => {1717 hir::TyKind::TraitAscription(self.lower_param_bounds(1718 bounds,1719 RelaxedBoundPolicy::Allowed(&mut Default::default()),1720 itctx,1721 ))1722 }1723 ImplTraitContext::FeatureGated(position, feature) => {1724 let guar = self1725 .tcx1726 .sess1727 .create_feature_err(1728 MisplacedImplTrait {1729 span: t.span,1730 position: DiagArgFromDisplay(&position),1731 },1732 feature,1733 )1734 .emit();1735 hir::TyKind::Err(guar)1736 }1737 ImplTraitContext::Disallowed(position) => {1738 let guar = self.dcx().emit_err(MisplacedImplTrait {1739 span: t.span,1740 position: DiagArgFromDisplay(&position),1741 });1742 hir::TyKind::Err(guar)1743 }1744 ImplTraitContext::AlreadyErrored(guar) => {1745 // `GenericArgs::Parenthesized` stores its inputs as `Param`s, so the def1746 // collector visits `impl Trait` in a universal context and creates a1747 // `DefKind::TyParam`. During recovery we reinterpret these arguments as1748 // angle-bracketed, where lowering may otherwise expect an opaque type.1749 // The parenthesized syntax has already been rejected, so avoid lowering1750 // this `impl Trait` with the inconsistent `DefKind`.1751 hir::TyKind::Err(guar)1752 }1753 }1754 }1755 TyKind::Pat(ty, pat) => {1756 hir::TyKind::Pat(self.lower_ty_alloc(ty, itctx), self.lower_ty_pat(pat, ty.span))1757 }1758 TyKind::FieldOf(ty, variant, field) => hir::TyKind::FieldOf(1759 self.lower_ty_alloc(ty, itctx),1760 self.arena.alloc(hir::TyFieldPath {1761 variant: variant.map(|variant| self.lower_ident(variant)),1762 field: self.lower_ident(*field),1763 }),1764 ),1765 TyKind::MacCall(_) => {1766 span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")1767 }1768 TyKind::CVarArgs => {1769 let guar = self.dcx().span_delayed_bug(1770 t.span,1771 "`TyKind::CVarArgs` should have been handled elsewhere",1772 );1773 hir::TyKind::Err(guar)1774 }1775 TyKind::View(ty, fields) => {1776 let ty = self.lower_ty_alloc(ty, itctx);1777 let fields = self.arena.alloc_slice(fields);1778 hir::TyKind::View(ty, fields)1779 }1780 TyKind::DirectConstArg(expr) => {1781 let e = self.emit_bad_direct_const_arg(t.span, expr, "type");1782 hir::TyKind::Err(e)1783 }1784 TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"),1785 };17861787 hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }1788 }17891790 pub(crate) fn emit_bad_direct_const_arg(1791 &mut self,1792 span: Span,1793 expr: &Expr,1794 expected: &'static str,1795 ) -> ErrorGuaranteed {1796 let msg = format!("expected {expected}, found `direct_const_arg!()` constant");1797 if expr::WillCreateDefIdsVisitor.visit_expr(expr).is_break() {1798 // FIXME(mgca): make this non-fatal once we have a better way to handle1799 // nested items in invalid `direct_const_arg!()` arguments.1800 self.dcx().struct_span_fatal(span, msg).emit()1801 } else {1802 self.dcx().struct_span_err(span, msg).emit()1803 }1804 }18051806 fn lower_ty_direct_lifetime(1807 &mut self,1808 t: &Ty,1809 region: Option<Lifetime>,1810 ) -> &'hir hir::Lifetime {1811 let (region, syntax) = match region {1812 Some(region) => (region, region.ident.into()),18131814 None => {1815 let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =1816 self.owner.get_lifetime_res(t.id)1817 {1818 assert_eq!(start.plus(1), end);1819 start1820 } else {1821 self.next_node_id()1822 };1823 let span = self.tcx.sess.source_map().start_point(t.span).shrink_to_hi();1824 let region = Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id };1825 (region, LifetimeSyntax::Implicit)1826 }1827 };1828 self.lower_lifetime(®ion, LifetimeSource::Reference, syntax)1829 }18301831 /// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F =1832 /// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a1833 /// HIR type that references the TAIT.1834 ///1835 /// Given a function definition like:1836 ///1837 /// ```rust1838 /// use std::fmt::Debug;1839 ///1840 /// fn test<'a, T: Debug>(x: &'a T) -> impl Debug + 'a {1841 /// x1842 /// }1843 /// ```1844 ///1845 /// we will create a TAIT definition in the HIR like1846 ///1847 /// ```rust,ignore (pseudo-Rust)1848 /// type TestReturn<'a, T, 'x> = impl Debug + 'x1849 /// ```1850 ///1851 /// and return a type like `TestReturn<'static, T, 'a>`, so that the function looks like:1852 ///1853 /// ```rust,ignore (pseudo-Rust)1854 /// fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a>1855 /// ```1856 ///1857 /// Note the subtlety around type parameters! The new TAIT, `TestReturn`, inherits all the1858 /// type parameters from the function `test` (this is implemented in the query layer, they aren't1859 /// added explicitly in the HIR). But this includes all the lifetimes, and we only want to1860 /// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters1861 /// for the lifetimes that get captured (`'x`, in our example above) and reference those.1862 #[instrument(level = "debug", skip(self), ret)]1863 fn lower_opaque_impl_trait(1864 &mut self,1865 span: Span,1866 origin: hir::OpaqueTyOrigin<LocalDefId>,1867 opaque_ty_node_id: NodeId,1868 bounds: &GenericBounds,1869 itctx: ImplTraitContext,1870 ) -> hir::TyKind<'hir> {1871 // Make sure we know that some funky desugaring has been going on here.1872 // This is a first: there is code in other places like for loop1873 // desugaring that explicitly states that we don't want to track that.1874 // Not tracking it makes lints in rustc and clippy very fragile, as1875 // frequently opened issues show.1876 let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);18771878 self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {1879 this.lower_param_bounds(1880 bounds,1881 RelaxedBoundPolicy::Allowed(&mut Default::default()),1882 itctx,1883 )1884 })1885 }18861887 fn lower_opaque_inner(1888 &mut self,1889 opaque_ty_node_id: NodeId,1890 origin: hir::OpaqueTyOrigin<LocalDefId>,1891 opaque_ty_span: Span,1892 lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],1893 ) -> hir::TyKind<'hir> {1894 let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);1895 let opaque_ty_hir_id = self.lower_node_id(opaque_ty_node_id);1896 debug!(?opaque_ty_def_id, ?opaque_ty_hir_id);18971898 let bounds = lower_item_bounds(self);1899 let opaque_ty_def = hir::OpaqueTy {1900 hir_id: opaque_ty_hir_id,1901 def_id: opaque_ty_def_id,1902 bounds,1903 origin,1904 span: self.lower_span(opaque_ty_span),1905 };1906 let opaque_ty_def = self.arena.alloc(opaque_ty_def);19071908 hir::TyKind::OpaqueDef(opaque_ty_def)1909 }19101911 fn lower_precise_capturing_args(1912 &mut self,1913 precise_capturing_args: &[PreciseCapturingArg],1914 ) -> &'hir [hir::PreciseCapturingArg<'hir>] {1915 self.arena.alloc_from_iter(precise_capturing_args.iter().map(|arg| match arg {1916 PreciseCapturingArg::Lifetime(lt) => hir::PreciseCapturingArg::Lifetime(1917 self.lower_lifetime(lt, LifetimeSource::PreciseCapturing, lt.ident.into()),1918 ),1919 PreciseCapturingArg::Arg(path, id) => {1920 let [segment] = path.segments.as_slice() else {1921 panic!();1922 };1923 let res = self.get_partial_res(*id).map_or(Res::Err, |partial_res| {1924 partial_res.full_res().expect("no partial res expected for precise capture arg")1925 });1926 hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {1927 hir_id: self.lower_node_id(*id),1928 ident: self.lower_ident(segment.ident),1929 res: self.lower_res(res),1930 })1931 }1932 }))1933 }19341935 fn lower_fn_params_to_idents(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] {1936 self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind {1937 PatKind::Missing => None,1938 PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)),1939 PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))),1940 _ => {1941 self.dcx().span_delayed_bug(1942 param.pat.span,1943 "non-missing/ident/wild param pat must trigger an error",1944 );1945 None1946 }1947 }))1948 }19491950 /// Lowers a function declaration.1951 ///1952 /// `decl`: the unlowered (AST) function declaration.1953 ///1954 /// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given1955 /// `NodeId`.1956 ///1957 /// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is1958 /// needed for `async fn` and `gen fn`. See [`CoroutineKind`] for more details.1959 #[instrument(level = "debug", skip(self))]1960 fn lower_fn_decl(1961 &mut self,1962 decl: &FnDecl,1963 fn_node_id: NodeId,1964 fn_span: Span,1965 kind: FnDeclKind,1966 coro: Option<CoroutineMarker>,1967 ) -> &'hir hir::FnDecl<'hir> {1968 let c_variadic = decl.c_variadic();1969 let mut splatted = decl.splatted();19701971 // Skip the `...` (`CVarArgs`) trailing arguments from the AST,1972 // as they are not explicit in HIR/Ty function signatures.1973 // (instead, the `c_variadic` flag is set to `true`)1974 let mut inputs = &decl.inputs[..];1975 if decl.c_variadic() {1976 // Splat + variadic errors in AST validation, so just ignore one of them here.1977 splatted = None;1978 inputs = &inputs[..inputs.len() - 1];1979 }1980 let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {1981 let itctx = match kind {1982 FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => {1983 ImplTraitContext::Universal1984 }1985 FnDeclKind::ExternFn => {1986 ImplTraitContext::Disallowed(ImplTraitPosition::ExternFnParam)1987 }1988 FnDeclKind::Closure => {1989 ImplTraitContext::Disallowed(ImplTraitPosition::ClosureParam)1990 }1991 FnDeclKind::Pointer => {1992 ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam)1993 }1994 };1995 self.lower_ty(¶m.ty, itctx)1996 }));19971998 let output = match coro {1999 Some(coro) => {2000 let fn_def_id = self.owner.def_id;
Findings
✓ No findings reported for this file.