rust/compiler/rustc_ast_lowering/src/lib.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

2592 lines
105 KiB
Rust
Raw Normal View History

//! Lowers the AST to the HIR.
//!
//! Since the AST and HIR are fairly similar, this is mostly a simple procedure,
//! much like a fold. Where lowering involves a bit more work things get more
//! interesting and there are some invariants you should know about. These mostly
2019-02-08 14:53:55 +01:00
//! concern spans and IDs.
//!
//! Spans are assigned to AST nodes during parsing and then are modified during
//! expansion to indicate the origin of a node and the process it went through
2019-02-08 14:53:55 +01:00
//! being expanded. IDs are assigned to AST nodes just before lowering.
//!
2019-02-08 14:53:55 +01:00
//! For the simpler lowering steps, IDs and spans should be preserved. Unlike
//! expansion we do not preserve the process of lowering in the spans, so spans
//! should not be modified here. When creating a new node (as opposed to
//! "folding" an existing one), create a new ID using `next_id()`.
//!
2019-02-08 14:53:55 +01:00
//! You must ensure that IDs are unique. That means that you should only use the
//! ID from an AST node in a single HIR node (you can assume that AST node-IDs
2019-02-08 14:53:55 +01:00
//! are unique). Every new node must have a unique ID. Avoid cloning HIR nodes.
//! If you do, you must then set the new node's ID to a fresh one.
//!
//! Spans are used for error messages and for tools to map semantics back to
2019-02-08 14:53:55 +01:00
//! source code. It is therefore not as important with spans as IDs to be strict
//! about use (you can't break the compiler by screwing up a span). Obviously, a
//! HIR node can only have a single span. But multiple nodes can have the same
//! span and spans don't need to be kept in order, etc. Where code is preserved
//! by lowering, it should have the same span as in the AST. Where HIR nodes are
//! new it is probably best to give a span for the whole AST node being lowered.
//! All nodes should have real spans; don't use dummy spans. Tools are likely to
//! get confused if the spans from leaf AST nodes occur in multiple places
//! in the HIR, especially for multiple identifiers.
2015-07-31 00:04:06 -07:00
2021-01-29 08:31:08 +01:00
#![feature(box_patterns)]
#![feature(let_chains)]
#![feature(never_type)]
2020-02-05 02:04:14 +01:00
#![recursion_limit = "256"]
2022-02-23 08:06:22 -05:00
#![allow(rustc::potential_query_instability)]
2022-08-26 18:03:41 +02:00
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate tracing;
2022-09-02 15:57:31 +00:00
use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait, TraitFnAsync};
use rustc_arena::declare_arena;
2022-08-11 21:06:11 +10:00
use rustc_ast::ptr::P;
2021-07-14 19:53:57 +02:00
use rustc_ast::visit;
2020-04-27 23:26:11 +05:30
use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust;
use rustc_data_structures::captures::Captures;
2021-10-09 19:44:55 +02:00
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
2021-10-21 23:08:57 +02:00
use rustc_data_structures::sorted_map::SortedMap;
2021-10-09 19:44:55 +02:00
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
2022-08-19 14:55:06 +02:00
use rustc_errors::{DiagnosticArgFromDisplay, Handler, StashKey};
use rustc_hir as hir;
2021-07-05 22:26:23 +02:00
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
2021-07-13 18:45:20 +02:00
use rustc_hir::definitions::DefPathData;
2022-02-19 19:43:18 -03:00
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
use rustc_index::vec::{Idx, IndexVec};
2021-07-13 18:45:20 +02:00
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err;
use rustc_span::hygiene::MacroKind;
2022-02-13 11:30:48 +01:00
use rustc_span::source_map::DesugaringKind;
2020-04-19 13:00:18 +02:00
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
2015-07-31 00:04:06 -07:00
2021-08-04 13:09:02 -05:00
use smallvec::SmallVec;
2021-07-18 13:03:53 +02:00
use std::collections::hash_map::Entry;
2019-12-24 18:57:28 +01:00
macro_rules! arena_vec {
($this:expr; $($x:expr),*) => (
$this.arena.alloc_from_iter([$($x),*])
);
2019-12-24 18:57:28 +01:00
}
mod asm;
2021-08-04 13:09:02 -05:00
mod block;
mod errors;
2019-12-24 18:57:28 +01:00
mod expr;
mod index;
2019-12-24 18:57:28 +01:00
mod item;
mod lifetime_collector;
2020-01-06 05:51:59 +01:00
mod pat;
2020-01-06 06:28:43 +01:00
mod path;
2019-12-24 18:57:28 +01:00
2021-07-13 18:45:20 +02:00
struct LoweringContext<'a, 'hir> {
tcx: TyCtxt<'hir>,
resolver: &'a mut ResolverAstLowering,
/// Used to allocate HIR nodes.
2021-07-13 18:45:20 +02:00
arena: &'hir hir::Arena<'hir>,
2019-11-28 11:49:29 +01:00
/// Used to allocate temporary AST nodes for use during lowering.
/// This allows us to create "fake" AST -- these nodes can sometimes
/// be allocated on the stack, but other times we need them to live longer
/// than the current stack frame, so they can be collected into vectors
/// and things like that.
ast_arena: &'a Arena<'static>,
2021-10-11 22:36:37 +02:00
/// Bodies inside the owner being lowered.
2021-10-21 23:08:57 +02:00
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
2021-10-11 22:36:37 +02:00
/// Attributes inside the owner being lowered.
2021-10-21 23:08:57 +02:00
attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
2021-07-15 17:41:48 +02:00
/// Collect items that were created by lowering the current owner.
children: FxHashMap<LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>>,
generator_kind: Option<hir::GeneratorKind>,
2016-12-26 14:34:03 +01:00
/// When inside an `async` context, this is the `HirId` of the
/// `task_context` local bound to the resume argument of the generator.
task_context: Option<hir::HirId>,
/// Used to get the current `fn`'s def span to point to when using `await`
/// outside of an `async fn`.
current_item: Option<Span>,
2021-04-01 19:42:27 +02:00
catch_scope: Option<NodeId>,
loop_scope: Option<NodeId>,
is_in_loop_condition: bool,
is_in_trait_impl: bool,
is_in_dyn_type: bool,
2017-02-15 14:52:27 -08:00
current_hir_id_owner: hir::OwnerId,
item_local_id_counter: hir::ItemLocalId,
local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
2022-02-19 19:43:18 -03:00
trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
impl_trait_defs: Vec<hir::GenericParam<'hir>>,
impl_trait_bounds: Vec<hir::WherePredicate<'hir>>,
2021-07-16 14:42:26 +02:00
/// NodeIds that are lowered inside the current HIR owner.
2021-07-18 13:03:53 +02:00
node_id_to_local_id: FxHashMap<NodeId, hir::ItemLocalId>,
2021-07-16 14:42:26 +02:00
allow_try_trait: Option<Lrc<[Symbol]>>,
allow_gen_future: Option<Lrc<[Symbol]>>,
allow_into_future: Option<Lrc<[Symbol]>>,
/// Mapping from generics `def_id`s to TAIT generics `def_id`s.
/// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic
/// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
/// field from the original parameter 'a to the new parameter 'a1.
generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
}
declare_arena!([
[] tys: rustc_ast::Ty,
[] aba: rustc_ast::AngleBracketedArgs,
[] ptr: rustc_ast::PolyTraitRef,
// This _marker field is needed because `declare_arena` creates `Arena<'tcx>` and we need to
// use `'tcx`. If we don't have this we get a compile error.
[] _marker: std::marker::PhantomData<&'tcx ()>,
]);
2021-07-05 22:26:23 +02:00
trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
2022-04-07 20:54:13 +02:00
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
2021-07-05 22:26:23 +02:00
fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind;
}
impl ResolverAstLoweringExt for ResolverAstLowering {
2021-07-05 22:26:23 +02:00
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
if let ExprKind::Path(None, path) = &expr.kind {
// Don't perform legacy const generics rewriting if the path already
// has generic arguments.
if path.segments.last().unwrap().args.is_some() {
return None;
}
2021-07-05 22:26:23 +02:00
let partial_res = self.partial_res_map.get(&expr.id)?;
if partial_res.unresolved_segments() != 0 {
return None;
}
2021-07-05 22:26:23 +02:00
if let Res::Def(DefKind::Fn, def_id) = partial_res.base_res() {
// We only support cross-crate argument rewriting. Uses
// within the same crate should be updated to use the new
// const generics style.
if def_id.is_local() {
return None;
}
2020-06-12 18:13:10 +01:00
2021-07-05 22:26:23 +02:00
if let Some(v) = self.legacy_const_generic_args.get(&def_id) {
return v.clone();
}
}
}
2021-07-05 22:26:23 +02:00
None
}
/// Obtains resolution for a `NodeId` with a single resolution.
2021-07-05 22:26:23 +02:00
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
self.partial_res_map.get(&id).copied()
}
/// Obtains per-namespace resolutions for `use` statement with the given `NodeId`.
2021-07-05 22:26:23 +02:00
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>> {
self.import_res_map.get(&id).copied().unwrap_or_default()
}
2021-06-22 19:20:25 +02:00
/// Obtains resolution for a label with the given `NodeId`.
2021-07-05 22:26:23 +02:00
fn get_label_res(&self, id: NodeId) -> Option<NodeId> {
self.label_res_map.get(&id).copied()
}
2022-04-07 20:54:13 +02:00
/// Obtains resolution for a lifetime with the given `NodeId`.
2021-07-05 22:26:23 +02:00
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> {
self.lifetimes_res_map.get(&id).copied()
}
2022-04-07 20:54:13 +02:00
/// Obtain the list of lifetimes parameters to add to an item.
///
/// Extra lifetime parameters should only be added in places that can appear
/// as a `binder` in `LifetimeRes`.
///
/// The extra lifetimes that appear from the parenthesized `Fn`-trait desugaring
/// should appear at the enclosing `PolyTraitRef`.
2021-07-05 22:26:23 +02:00
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
}
2021-07-05 22:26:23 +02:00
fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind {
self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang)
}
2015-09-25 16:03:28 +12:00
}
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
/// and if so, what meaning it has.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ImplTraitContext {
/// Treat `impl Trait` as shorthand for a new universal generic parameter.
/// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
///
2018-08-19 03:40:50 +01:00
/// Newly generated parameters should be inserted into the given `Vec`.
Universal,
2019-08-01 00:41:54 +01:00
/// Treat `impl Trait` as shorthand for a new opaque type.
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
2019-08-01 00:41:54 +01:00
/// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
2018-05-22 14:31:56 +02:00
///
ReturnPositionOpaqueTy {
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
origin: hir::OpaqueTyOrigin,
2022-09-06 17:37:00 +02:00
in_trait: bool,
},
2021-07-14 12:31:58 -03:00
/// Impl trait in type aliases.
2022-03-29 15:37:21 +02:00
TypeAliasesOpaqueTy,
/// `impl Trait` is not accepted in this position.
Disallowed(ImplTraitPosition),
}
2019-03-21 18:40:00 +00:00
/// Position in which `impl Trait` is disallowed.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ImplTraitPosition {
Path,
Variable,
Type,
Trait,
AsyncBlock,
Bound,
Generic,
ExternFnParam,
ClosureParam,
PointerParam,
FnTraitParam,
TraitParam,
ImplParam,
ExternFnReturn,
ClosureReturn,
PointerReturn,
FnTraitReturn,
TraitReturn,
ImplReturn,
}
impl std::fmt::Display for ImplTraitPosition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name = match self {
ImplTraitPosition::Path => "path",
2022-02-17 19:18:42 -08:00
ImplTraitPosition::Variable => "variable binding",
ImplTraitPosition::Type => "type",
ImplTraitPosition::Trait => "trait",
ImplTraitPosition::AsyncBlock => "async block",
ImplTraitPosition::Bound => "bound",
ImplTraitPosition::Generic => "generic",
ImplTraitPosition::ExternFnParam => "`extern fn` param",
ImplTraitPosition::ClosureParam => "closure param",
ImplTraitPosition::PointerParam => "`fn` pointer param",
ImplTraitPosition::FnTraitParam => "`Fn` trait param",
ImplTraitPosition::TraitParam => "trait method param",
ImplTraitPosition::ImplParam => "`impl` method param",
ImplTraitPosition::ExternFnReturn => "`extern fn` return",
ImplTraitPosition::ClosureReturn => "closure return",
ImplTraitPosition::PointerReturn => "`fn` pointer return",
ImplTraitPosition::FnTraitReturn => "`Fn` trait return",
ImplTraitPosition::TraitReturn => "trait method return",
ImplTraitPosition::ImplReturn => "`impl` method return",
};
write!(f, "{}", name)
}
}
2022-09-06 17:16:08 +00:00
#[derive(Debug, PartialEq, Eq)]
enum FnDeclKind {
Fn,
Inherent,
ExternFn,
Closure,
Pointer,
Trait,
Impl,
}
impl FnDeclKind {
fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
_ => false,
}
}
fn async_fn_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().async_fn_in_trait => true,
FnDeclKind::Trait if tcx.features().async_fn_in_trait => true,
_ => false,
}
}
}
2021-07-15 01:18:39 +02:00
#[derive(Copy, Clone)]
enum AstOwner<'a> {
NonOwner,
Crate(&'a ast::Crate),
Item(&'a ast::Item),
AssocItem(&'a ast::AssocItem, visit::AssocCtxt),
ForeignItem(&'a ast::ForeignItem),
}
fn index_crate<'a>(
2021-07-18 20:09:20 +02:00
node_id_to_def_id: &FxHashMap<NodeId, LocalDefId>,
2021-07-15 01:18:39 +02:00
krate: &'a Crate,
) -> IndexVec<LocalDefId, AstOwner<'a>> {
2021-07-18 20:09:20 +02:00
let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() };
2021-07-15 01:18:39 +02:00
indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner);
indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate);
visit::walk_crate(&mut indexer, krate);
return indexer.index;
struct Indexer<'s, 'a> {
2021-07-18 20:09:20 +02:00
node_id_to_def_id: &'s FxHashMap<NodeId, LocalDefId>,
2021-07-15 01:18:39 +02:00
index: IndexVec<LocalDefId, AstOwner<'a>>,
}
impl<'a> visit::Visitor<'a> for Indexer<'_, 'a> {
fn visit_attribute(&mut self, _: &'a Attribute) {
// We do not want to lower expressions that appear in attributes,
// as they are not accessible to the rest of the HIR.
}
fn visit_item(&mut self, item: &'a ast::Item) {
2021-07-18 20:09:20 +02:00
let def_id = self.node_id_to_def_id[&item.id];
2021-07-15 01:18:39 +02:00
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
self.index[def_id] = AstOwner::Item(item);
visit::walk_item(self, item)
}
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) {
2021-07-18 20:09:20 +02:00
let def_id = self.node_id_to_def_id[&item.id];
2021-07-15 01:18:39 +02:00
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
self.index[def_id] = AstOwner::AssocItem(item, ctxt);
visit::walk_assoc_item(self, item, ctxt);
}
fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) {
2021-07-18 20:09:20 +02:00
let def_id = self.node_id_to_def_id[&item.id];
2021-07-15 01:18:39 +02:00
self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner);
self.index[def_id] = AstOwner::ForeignItem(item);
visit::walk_foreign_item(self, item);
}
}
}
/// Compute the hash for the HIR of the full crate.
/// This hash will then be part of the crate_hash which is stored in the metadata.
fn compute_hir_hash(
2021-07-13 18:45:20 +02:00
tcx: TyCtxt<'_>,
owners: &IndexVec<LocalDefId, hir::MaybeOwner<&hir::OwnerInfo<'_>>>,
) -> Fingerprint {
let mut hir_body_nodes: Vec<_> = owners
.iter_enumerated()
.filter_map(|(def_id, info)| {
let info = info.as_owner()?;
2021-07-13 18:45:20 +02:00
let def_path_hash = tcx.hir().def_path_hash(def_id);
Some((def_path_hash, info))
})
.collect();
hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
2021-07-13 18:45:20 +02:00
tcx.with_stable_hashing_context(|mut hcx| {
let mut stable_hasher = StableHasher::new();
hir_body_nodes.hash_stable(&mut hcx, &mut stable_hasher);
stable_hasher.finish()
})
}
2021-07-13 18:45:20 +02:00
pub fn lower_to_hir<'hir>(tcx: TyCtxt<'hir>, (): ()) -> hir::Crate<'hir> {
let sess = tcx.sess;
let krate = tcx.untracked_crate.steal();
let mut resolver = tcx.resolver_for_lowering(()).steal();
2021-07-13 18:45:20 +02:00
let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
let mut owners = IndexVec::from_fn_n(
|_| hir::MaybeOwner::Phantom,
tcx.definitions_untracked().def_index_count(),
);
let ast_arena = Arena::default();
2021-07-15 01:18:39 +02:00
for def_id in ast_index.indices() {
2021-07-05 22:26:23 +02:00
item::ItemLowerer {
2021-07-13 18:45:20 +02:00
tcx,
resolver: &mut resolver,
ast_arena: &ast_arena,
2021-07-05 22:26:23 +02:00
ast_index: &ast_index,
owners: &mut owners,
}
.lower_node(def_id);
2021-07-15 01:18:39 +02:00
}
2021-07-13 18:45:20 +02:00
// Drop AST to free memory
std::mem::drop(ast_index);
sess.time("drop_ast", || std::mem::drop(krate));
// Discard hygiene data, which isn't required after lowering to HIR.
if !sess.opts.unstable_opts.keep_hygiene_data {
2021-07-13 18:45:20 +02:00
rustc_span::hygiene::clear_syntax_context_map();
}
let hir_hash = compute_hir_hash(tcx, &owners);
hir::Crate { owners, hir_hash }
2016-05-10 05:29:13 +00:00
}
2015-09-28 15:00:15 +13:00
#[derive(Copy, Clone, PartialEq, Debug)]
enum ParamMode {
/// Any path in a type context.
Explicit,
/// Path in a type definition, where the anonymous lifetime `'_` is not allowed.
ExplicitNamed,
/// The `module::Type` in `module::Type::method` in an expression.
2018-03-21 04:24:27 -04:00
Optional,
}
enum ParenthesizedGenericArgs {
Ok,
Err,
}
2019-11-28 11:49:29 +01:00
impl<'a, 'hir> LoweringContext<'a, 'hir> {
2021-07-05 22:26:23 +02:00
fn create_def(
&mut self,
parent: LocalDefId,
node_id: ast::NodeId,
data: DefPathData,
) -> LocalDefId {
2022-04-02 16:13:01 +02:00
debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
2021-07-05 22:26:23 +02:00
assert!(
2021-07-18 20:09:20 +02:00
self.opt_local_def_id(node_id).is_none(),
2021-07-05 22:26:23 +02:00
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
node_id,
data,
2021-07-13 18:45:20 +02:00
self.tcx.hir().def_key(self.local_def_id(node_id)),
2021-07-05 22:26:23 +02:00
);
2021-07-13 18:45:20 +02:00
let def_id = self.tcx.create_def(parent, data);
2021-07-05 22:26:23 +02:00
2022-04-02 16:13:01 +02:00
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
self.resolver.node_id_to_def_id.insert(node_id, def_id);
2021-07-05 22:26:23 +02:00
def_id
}
2021-07-18 20:09:20 +02:00
fn next_node_id(&mut self) -> NodeId {
let start = self.resolver.next_node_id;
2022-06-15 19:41:41 +02:00
let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
self.resolver.next_node_id = ast::NodeId::from_u32(next);
2022-06-15 19:41:41 +02:00
start
2021-07-18 20:09:20 +02:00
}
2022-08-03 17:26:38 -03:00
/// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name
/// resolver (if any), after applying any remapping from `get_remapped_def_id`.
///
2022-08-04 12:47:58 -03:00
/// For example, in a function like `fn foo<'a>(x: &'a u32)`,
/// invoking with the id from the `ast::Lifetime` node found inside
/// the `&'a u32` type would return the `LocalDefId` of the
/// `'a` parameter declared on `foo`.
2022-08-03 17:26:38 -03:00
///
2022-08-04 12:47:58 -03:00
/// This function also applies remapping from `get_remapped_def_id`.
/// These are used when synthesizing opaque types from `-> impl Trait` return types and so forth.
/// For example, in a function like `fn foo<'a>() -> impl Debug + 'a`,
/// we would create an opaque type `type FooReturn<'a1> = impl Debug + 'a1`.
/// When lowering the `Debug + 'a` bounds, we add a remapping to map `'a` to `'a1`.
2021-07-18 20:09:20 +02:00
fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
2022-08-02 20:01:40 -03:00
self.resolver
.node_id_to_def_id
.get(&node)
.map(|local_def_id| self.get_remapped_def_id(*local_def_id))
2021-07-18 20:09:20 +02:00
}
fn local_def_id(&self, node: NodeId) -> LocalDefId {
self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node))
}
/// Get the previously recorded `to` local def id given the `from` local def id, obtained using
/// `generics_def_id_map` field.
fn get_remapped_def_id(&self, mut local_def_id: LocalDefId) -> LocalDefId {
// `generics_def_id_map` is a stack of mappings. As we go deeper in impl traits nesting we
// push new mappings so we need to try first the latest mappings, hence `iter().rev()`.
//
// Consider:
//
// `fn test<'a, 'b>() -> impl Trait<&'a u8, Ty = impl Sized + 'b> {}`
//
// We would end with a generics_def_id_map like:
//
// `[[fn#'b -> impl_trait#'b], [fn#'b -> impl_sized#'b]]`
//
// for the opaque type generated on `impl Sized + 'b`, We want the result to be:
// impl_sized#'b, so iterating forward is the wrong thing to do.
for map in self.generics_def_id_map.iter().rev() {
if let Some(r) = map.get(&local_def_id) {
debug!("def_id_remapper: remapping from `{local_def_id:?}` to `{r:?}`");
local_def_id = *r;
} else {
debug!("def_id_remapper: no remapping for `{local_def_id:?}` found in map");
}
}
local_def_id
}
2022-05-02 20:32:10 +02:00
/// Freshen the `LoweringContext` and ready it to lower a nested item.
/// The lowered item is registered into `self.children`.
///
/// This function sets up `HirId` lowering infrastructure,
/// and stashes the shared mutable state to avoid pollution by the closure.
#[instrument(level = "debug", skip(self, f))]
fn with_hir_id_owner(
&mut self,
owner: NodeId,
f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,
) {
2021-07-18 20:09:20 +02:00
let def_id = self.local_def_id(owner);
2021-07-16 14:42:26 +02:00
let current_attrs = std::mem::take(&mut self.attrs);
let current_bodies = std::mem::take(&mut self.bodies);
2021-07-18 13:03:53 +02:00
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
2022-02-19 19:43:18 -03:00
let current_trait_map = std::mem::take(&mut self.trait_map);
let current_owner =
std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
let current_local_counter =
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
let current_impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
2022-05-02 20:32:10 +02:00
// Do not reset `next_node_id` and `node_id_to_def_id`:
// we want `f` to be able to refer to the `LocalDefId`s that the caller created.
// and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s.
2021-07-14 23:50:53 +02:00
2021-07-16 14:42:26 +02:00
// Always allocate the first `HirId` for the owner itself.
2021-07-18 13:03:53 +02:00
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::new(0));
2021-07-16 14:42:26 +02:00
debug_assert_eq!(_old, None);
let item = f(self);
debug_assert_eq!(def_id, item.def_id().def_id);
// `f` should have consumed all the elements in these vectors when constructing `item`.
debug_assert!(self.impl_trait_defs.is_empty());
debug_assert!(self.impl_trait_bounds.is_empty());
2021-07-16 14:42:26 +02:00
let info = self.make_owner_info(item);
2021-07-16 14:42:26 +02:00
self.attrs = current_attrs;
self.bodies = current_bodies;
2021-07-18 13:03:53 +02:00
self.node_id_to_local_id = current_node_ids;
self.local_id_to_def_id = current_id_to_def_id;
2022-02-19 19:43:18 -03:00
self.trait_map = current_trait_map;
self.current_hir_id_owner = current_owner;
self.item_local_id_counter = current_local_counter;
self.impl_trait_defs = current_impl_trait_defs;
self.impl_trait_bounds = current_impl_trait_bounds;
2021-07-15 17:41:48 +02:00
let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info));
debug_assert!(_old.is_none())
}
2022-08-03 17:32:24 -03:00
/// Installs the remapping `remap` in scope while `f` is being executed.
/// This causes references to the `LocalDefId` keys to be changed to
/// refer to the values instead.
///
/// The remapping is used when one piece of AST expands to multiple
/// pieces of HIR. For example, the function `fn foo<'a>(...) -> impl Debug + 'a`,
/// expands to both a function definition (`foo`) and a TAIT for the return value,
/// both of which have a lifetime parameter `'a`. The remapping allows us to
/// rewrite the `'a` in the return value to refer to the
/// `'a` declared on the TAIT, instead of the function.
2022-08-02 20:01:40 -03:00
fn with_remapping<R>(
&mut self,
remap: FxHashMap<LocalDefId, LocalDefId>,
f: impl FnOnce(&mut Self) -> R,
) -> R {
self.generics_def_id_map.push(remap);
2022-08-02 20:01:40 -03:00
let res = f(self);
self.generics_def_id_map.pop();
2022-08-02 20:01:40 -03:00
res
}
2021-07-15 17:41:48 +02:00
fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
2021-07-16 14:42:26 +02:00
let attrs = std::mem::take(&mut self.attrs);
2021-10-21 23:08:57 +02:00
let mut bodies = std::mem::take(&mut self.bodies);
2021-07-15 17:41:48 +02:00
let local_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
let trait_map = std::mem::take(&mut self.trait_map);
2021-07-16 14:42:26 +02:00
#[cfg(debug_assertions)]
2021-10-21 23:08:57 +02:00
for (id, attrs) in attrs.iter() {
2021-07-16 14:42:26 +02:00
// Verify that we do not store empty slices in the map.
if attrs.is_empty() {
panic!("Stored empty attributes for {:?}", id);
}
}
2021-10-21 23:08:57 +02:00
bodies.sort_by_key(|(k, _)| *k);
let bodies = SortedMap::from_presorted_elements(bodies);
2021-10-11 22:36:37 +02:00
let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies);
2021-07-13 18:45:20 +02:00
let (nodes, parenting) =
index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies);
2021-11-21 19:04:47 +01:00
let nodes = hir::OwnerNodes {
hash_including_bodies,
hash_without_bodies,
nodes,
bodies,
2021-07-15 17:41:48 +02:00
local_id_to_def_id,
2021-11-21 19:04:47 +01:00
};
let attrs = {
2021-07-13 18:45:20 +02:00
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut stable_hasher = StableHasher::new();
attrs.hash_stable(&mut hcx, &mut stable_hasher);
stable_hasher.finish()
});
hir::AttributeMap { map: attrs, hash }
};
2021-10-09 19:44:55 +02:00
2021-07-15 17:41:48 +02:00
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
2021-10-09 19:44:55 +02:00
}
/// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate
/// queries which depend on the full HIR tree and those which only depend on the item signature.
2021-10-11 22:36:37 +02:00
fn hash_owner(
2021-10-09 19:44:55 +02:00
&mut self,
node: hir::OwnerNode<'hir>,
2021-10-21 23:08:57 +02:00
bodies: &SortedMap<hir::ItemLocalId, &'hir hir::Body<'hir>>,
2021-10-09 19:44:55 +02:00
) -> (Fingerprint, Fingerprint) {
2021-07-13 18:45:20 +02:00
self.tcx.with_stable_hashing_context(|mut hcx| {
let mut stable_hasher = StableHasher::new();
2022-08-07 17:33:37 +02:00
hcx.with_hir_bodies(node.def_id(), bodies, |hcx| {
2021-07-13 18:45:20 +02:00
node.hash_stable(hcx, &mut stable_hasher)
});
let hash_including_bodies = stable_hasher.finish();
let mut stable_hasher = StableHasher::new();
2022-08-07 17:33:37 +02:00
hcx.without_hir_bodies(|hcx| node.hash_stable(hcx, &mut stable_hasher));
2021-07-13 18:45:20 +02:00
let hash_without_bodies = stable_hasher.finish();
(hash_including_bodies, hash_without_bodies)
})
2021-07-16 14:42:26 +02:00
}
/// This method allocates a new `HirId` for the given `NodeId` and stores it in
/// the `LoweringContext`'s `NodeId => HirId` map.
/// Take care not to call this method if the resulting `HirId` is then not
/// actually used in the HIR, as that would trigger an assertion in the
/// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
/// properly. Calling the method twice with the same `NodeId` is fine though.
2022-09-06 17:24:36 -03:00
#[instrument(level = "debug", skip(self), ret)]
2019-04-26 14:23:30 +02:00
fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
2021-07-14 23:50:53 +02:00
assert_ne!(ast_node_id, DUMMY_NODE_ID);
match self.node_id_to_local_id.entry(ast_node_id) {
Entry::Occupied(o) => {
hir::HirId { owner: self.current_hir_id_owner, local_id: *o.get() }
}
2021-07-18 13:03:53 +02:00
Entry::Vacant(v) => {
// Generate a new `HirId`.
let owner = self.current_hir_id_owner;
2021-07-18 13:03:53 +02:00
let local_id = self.item_local_id_counter;
let hir_id = hir::HirId { owner, local_id };
2021-07-18 13:03:53 +02:00
v.insert(local_id);
self.item_local_id_counter.increment_by(1);
2022-02-22 09:37:47 -03:00
assert_ne!(local_id, hir::ItemLocalId::new(0));
2021-07-18 20:09:20 +02:00
if let Some(def_id) = self.opt_local_def_id(ast_node_id) {
2021-07-15 17:41:48 +02:00
// Do not override a `MaybeOwner::Owner` that may already here.
self.children.entry(def_id).or_insert(hir::MaybeOwner::NonOwner(hir_id));
2022-02-22 09:37:47 -03:00
self.local_id_to_def_id.insert(local_id, def_id);
}
2022-02-19 19:43:18 -03:00
2021-07-05 22:26:23 +02:00
if let Some(traits) = self.resolver.trait_map.remove(&ast_node_id) {
2022-02-22 09:37:47 -03:00
self.trait_map.insert(hir_id.local_id, traits.into_boxed_slice());
}
hir_id
2021-07-18 13:03:53 +02:00
}
}
}
/// Generate a new `HirId` without a backing `NodeId`.
2022-09-06 17:24:36 -03:00
#[instrument(level = "debug", skip(self), ret)]
2019-04-26 14:23:30 +02:00
fn next_id(&mut self) -> hir::HirId {
let owner = self.current_hir_id_owner;
let local_id = self.item_local_id_counter;
assert_ne!(local_id, hir::ItemLocalId::new(0));
self.item_local_id_counter.increment_by(1);
hir::HirId { owner, local_id }
}
#[instrument(level = "trace", skip(self))]
fn lower_res(&mut self, res: Res<NodeId>) -> Res {
2021-07-18 13:03:53 +02:00
let res: Result<Res, ()> = res.apply_id(|id| {
let owner = self.current_hir_id_owner;
let local_id = self.node_id_to_local_id.get(&id).copied().ok_or(())?;
Ok(hir::HirId { owner, local_id })
});
trace!(?res);
2021-07-18 13:03:53 +02:00
// We may fail to find a HirId when the Res points to a Local from an enclosing HIR owner.
// This can happen when trying to lower the return type `x` in erroneous code like
// async fn foo(x: u8) -> x {}
// In that case, `x` is lowered as a function parameter, and the return type is lowered as
// an opaque type as a synthesized HIR owner.
2021-07-18 13:03:53 +02:00
res.unwrap_or(Res::Err)
2019-04-03 09:07:45 +02:00
}
fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> {
self.resolver.get_partial_res(id).map_or(Res::Err, |pr| {
if pr.unresolved_segments() != 0 {
2020-03-21 02:38:48 +01:00
panic!("path not fully resolved: {:?}", pr);
}
pr.base_res()
})
}
fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Res<NodeId>> {
self.resolver.get_import_res(id).present_items()
}
fn diagnostic(&self) -> &Handler {
self.tcx.sess.diagnostic()
2015-09-28 15:00:15 +13:00
}
2015-10-07 08:26:22 +13:00
/// Reuses the span but adds information like the kind of the desugaring and features that are
/// allowed inside this span.
fn mark_span_with_reason(
&self,
reason: DesugaringKind,
span: Span,
allow_internal_unstable: Option<Lrc<[Symbol]>>,
) -> Span {
2021-07-13 18:45:20 +02:00
self.tcx.with_stable_hashing_context(|hcx| {
span.mark_with_reason(allow_internal_unstable, reason, self.tcx.sess.edition(), hcx)
2021-07-13 18:45:20 +02:00
})
}
/// Intercept all spans entering HIR.
/// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
if self.tcx.sess.opts.unstable_opts.incremental_relative_spans {
span.with_parent(Some(self.current_hir_id_owner.def_id))
} else {
// Do not make spans relative when not using incremental compilation.
span
}
}
fn lower_ident(&self, ident: Ident) -> Ident {
Ident::new(ident.name, self.lower_span(ident.span))
}
/// Converts a lifetime into a new generic parameter.
#[instrument(level = "debug", skip(self))]
fn lifetime_res_to_generic_param(
&mut self,
ident: Ident,
node_id: NodeId,
res: LifetimeRes,
) -> Option<hir::GenericParam<'hir>> {
let (name, kind) = match res {
LifetimeRes::Param { .. } => {
(hir::ParamName::Plain(ident), hir::LifetimeParamKind::Explicit)
}
LifetimeRes::Fresh { param, .. } => {
// Late resolution delegates to us the creation of the `LocalDefId`.
let _def_id = self.create_def(
self.current_hir_id_owner.def_id,
param,
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
);
debug!(?_def_id);
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided)
}
LifetimeRes::Static | LifetimeRes::Error => return None,
res => panic!(
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
res, ident, ident.span
),
};
let hir_id = self.lower_node_id(node_id);
Some(hir::GenericParam {
hir_id,
name,
span: self.lower_span(ident.span),
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
2022-04-28 21:59:41 +02:00
colon_span: None,
})
2017-11-16 22:59:45 -08:00
}
/// Lowers a lifetime binder that defines `generic_params`, returning the corresponding HIR
/// nodes. The returned list includes any "extra" lifetime parameters that were added by the
/// name resolver owing to lifetime elision; this also populates the resolver's node-id->def-id
/// map, so that later calls to `opt_node_id_to_def_id` that refer to these extra lifetime
/// parameters will be successful.
#[instrument(level = "debug", skip(self))]
#[inline]
fn lower_lifetime_binder(
&mut self,
binder: NodeId,
generic_params: &[GenericParam],
) -> &'hir [hir::GenericParam<'hir>] {
let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
debug!(?extra_lifetimes);
generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
self.lifetime_res_to_generic_param(ident, node_id, res)
}));
let generic_params = self.arena.alloc_from_iter(generic_params);
debug!(?generic_params);
generic_params
}
2020-01-06 05:32:17 +01:00
fn with_dyn_type_scope<T>(&mut self, in_scope: bool, f: impl FnOnce(&mut Self) -> T) -> T {
let was_in_dyn_type = self.is_in_dyn_type;
self.is_in_dyn_type = in_scope;
let result = f(self);
self.is_in_dyn_type = was_in_dyn_type;
result
}
2020-01-06 05:32:17 +01:00
fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;
2021-04-01 19:42:27 +02:00
let catch_scope = self.catch_scope.take();
let loop_scope = self.loop_scope.take();
2018-08-19 03:40:50 +01:00
let ret = f(self);
2021-04-01 19:42:27 +02:00
self.catch_scope = catch_scope;
self.loop_scope = loop_scope;
self.is_in_loop_condition = was_in_loop_condition;
2018-08-19 03:40:50 +01:00
ret
2017-02-15 14:52:27 -08:00
}
2021-01-24 17:14:17 +01:00
fn lower_attrs(&mut self, id: hir::HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
if attrs.is_empty() {
None
} else {
2021-07-16 14:42:26 +02:00
debug_assert_eq!(id.owner, self.current_hir_id_owner);
2021-01-24 17:14:17 +01:00
let ret = self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)));
debug_assert!(!ret.is_empty());
2021-07-16 14:42:26 +02:00
self.attrs.insert(id.local_id, ret);
2021-01-24 17:14:17 +01:00
Some(ret)
}
rustc: Forbid interpolated tokens in the HIR Right now the HIR contains raw `syntax::ast::Attribute` structure but nowadays these can contain arbitrary tokens. One variant of the `Token` enum is an "interpolated" token which basically means to shove all the tokens for a nonterminal in this position. A "nonterminal" in this case is roughly analagous to a macro argument: macro_rules! foo { ($a:expr) => { // $a is a nonterminal as an expression } } Currently nonterminals contain namely items and expressions, and this poses a problem for incremental compilation! With incremental we want a stable hash of all HIR items, but this means we may transitively need a stable hash *of the entire AST*, which is certainly not stable w/ node ids and whatnot. Hence today there's a "bug" where the "stable hash" of an AST is just the raw hash value of the AST, and this only arises with interpolated nonterminals. The downside of this approach, however, is that a bunch of errors get spewed out during compilation about how this isn't a great idea. This PR is focused at fixing these warnings, basically deleting them from the compiler. The implementation here is to alter attributes as they're lowered from the AST to HIR, expanding all nonterminals in-place as we see them. This code for expanding a nonterminal to a token stream already exists for the `proc_macro` crate, so we basically just reuse the same implementation there. After this PR it's considered a bug to have an `Interpolated` token and hence the stable hash implementation simply uses `bug!` in this location. Closes #40946
2017-09-15 08:28:34 -07:00
}
2020-11-27 17:41:05 +01:00
fn lower_attr(&self, attr: &Attribute) -> Attribute {
// Note that we explicitly do not walk the path. Since we don't really
// lower attributes (we use the AST version) there is nowhere to keep
// the `HirId`s. We don't actually need HIR version of attributes anyway.
2020-11-05 20:27:48 +03:00
// Tokens are also not needed after macro expansion and parsing.
let kind = match attr.kind {
2022-08-11 21:06:11 +10:00
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
item: AttrItem {
path: normal.item.path.clone(),
args: self.lower_mac_args(&normal.item.args),
2020-11-05 20:27:48 +03:00
tokens: None,
},
2022-08-11 21:06:11 +10:00
tokens: None,
})),
AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data),
};
Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
rustc: Forbid interpolated tokens in the HIR Right now the HIR contains raw `syntax::ast::Attribute` structure but nowadays these can contain arbitrary tokens. One variant of the `Token` enum is an "interpolated" token which basically means to shove all the tokens for a nonterminal in this position. A "nonterminal" in this case is roughly analagous to a macro argument: macro_rules! foo { ($a:expr) => { // $a is a nonterminal as an expression } } Currently nonterminals contain namely items and expressions, and this poses a problem for incremental compilation! With incremental we want a stable hash of all HIR items, but this means we may transitively need a stable hash *of the entire AST*, which is certainly not stable w/ node ids and whatnot. Hence today there's a "bug" where the "stable hash" of an AST is just the raw hash value of the AST, and this only arises with interpolated nonterminals. The downside of this approach, however, is that a bunch of errors get spewed out during compilation about how this isn't a great idea. This PR is focused at fixing these warnings, basically deleting them from the compiler. The implementation here is to alter attributes as they're lowered from the AST to HIR, expanding all nonterminals in-place as we see them. This code for expanding a nonterminal to a token stream already exists for the `proc_macro` crate, so we basically just reuse the same implementation there. After this PR it's considered a bug to have an `Interpolated` token and hence the stable hash implementation simply uses `bug!` in this location. Closes #40946
2017-09-15 08:28:34 -07:00
}
2021-01-24 17:14:17 +01:00
fn alias_attrs(&mut self, id: hir::HirId, target_id: hir::HirId) {
2021-07-16 14:42:26 +02:00
debug_assert_eq!(id.owner, self.current_hir_id_owner);
debug_assert_eq!(target_id.owner, self.current_hir_id_owner);
if let Some(&a) = self.attrs.get(&target_id.local_id) {
2021-01-24 17:14:17 +01:00
debug_assert!(!a.is_empty());
2021-07-16 14:42:26 +02:00
self.attrs.insert(id.local_id, a);
2021-01-24 17:14:17 +01:00
}
}
2020-11-27 17:41:05 +01:00
fn lower_mac_args(&self, args: &MacArgs) -> MacArgs {
match *args {
MacArgs::Empty => MacArgs::Empty,
2019-12-24 17:38:22 -05:00
MacArgs::Delimited(dspan, delim, ref tokens) => {
// This is either a non-key-value attribute, or a `macro_rules!` body.
// We either not have any nonterminals present (in the case of an attribute),
// or have tokens available for all nonterminals in the case of a nested
// `macro_rules`: e.g:
//
// ```rust
// macro_rules! outer {
// ($e:expr) => {
// macro_rules! inner {
// () => { $e }
// }
// }
// }
// ```
//
// In both cases, we don't want to synthesize any tokens
MacArgs::Delimited(dspan, delim, tokens.flattened())
2019-12-24 17:38:22 -05:00
}
// This is an inert key-value attribute - it will never be visible to macros
// after it gets lowered to HIR. Therefore, we can extract literals to handle
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
MacArgs::Eq(eq_span, MacArgsEq::Ast(ref expr)) => {
// In valid code the value always ends up as a single literal. Otherwise, a dummy
// literal suffices because the error is handled elsewhere.
let lit = if let ExprKind::Lit(lit) = &expr.kind {
lit.clone()
} else {
Lit {
token_lit: token::Lit::new(token::LitKind::Err, kw::Empty, None),
kind: LitKind::Err,
span: DUMMY_SP,
}
};
MacArgs::Eq(eq_span, MacArgsEq::Hir(lit))
}
MacArgs::Eq(_, MacArgsEq::Hir(ref lit)) => {
unreachable!("in literal form when lowering mac args eq: {:?}", lit)
}
rustc: Forbid interpolated tokens in the HIR Right now the HIR contains raw `syntax::ast::Attribute` structure but nowadays these can contain arbitrary tokens. One variant of the `Token` enum is an "interpolated" token which basically means to shove all the tokens for a nonterminal in this position. A "nonterminal" in this case is roughly analagous to a macro argument: macro_rules! foo { ($a:expr) => { // $a is a nonterminal as an expression } } Currently nonterminals contain namely items and expressions, and this poses a problem for incremental compilation! With incremental we want a stable hash of all HIR items, but this means we may transitively need a stable hash *of the entire AST*, which is certainly not stable w/ node ids and whatnot. Hence today there's a "bug" where the "stable hash" of an AST is just the raw hash value of the AST, and this only arises with interpolated nonterminals. The downside of this approach, however, is that a bunch of errors get spewed out during compilation about how this isn't a great idea. This PR is focused at fixing these warnings, basically deleting them from the compiler. The implementation here is to alter attributes as they're lowered from the AST to HIR, expanding all nonterminals in-place as we see them. This code for expanding a nonterminal to a token stream already exists for the `proc_macro` crate, so we basically just reuse the same implementation there. After this PR it's considered a bug to have an `Interpolated` token and hence the stable hash implementation simply uses `bug!` in this location. Closes #40946
2017-09-15 08:28:34 -07:00
}
}
2019-05-08 15:56:39 -04:00
/// Given an associated type constraint like one of these:
///
2022-04-15 15:04:34 -07:00
/// ```ignore (illustrative)
2019-05-08 15:56:39 -04:00
/// T: Iterator<Item: Debug>
/// ^^^^^^^^^^^
/// T: Iterator<Item = Debug>
/// ^^^^^^^^^^^^
/// ```
///
/// returns a `hir::TypeBinding` representing `Item`.
#[instrument(level = "debug", skip(self))]
2019-08-19 12:24:06 -07:00
fn lower_assoc_ty_constraint(
&mut self,
constraint: &AssocConstraint,
itctx: &ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::TypeBinding<'hir> {
2019-08-19 12:24:06 -07:00
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
// lower generic arguments of identifier in constraint
let gen_args = if let Some(ref gen_args) = constraint.gen_args {
let gen_args_ctor = match gen_args {
GenericArgs::AngleBracketed(ref data) => {
2022-05-31 16:46:15 -03:00
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
}
GenericArgs::Parenthesized(ref data) => {
2022-06-15 01:06:40 +01:00
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args());
self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0
}
};
gen_args_ctor.into_generic_args(self)
} else {
self.arena.alloc(hir::GenericArgs::none())
};
let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy;
2019-08-19 12:24:06 -07:00
let kind = match constraint.kind {
AssocConstraintKind::Equality { ref term } => {
let term = match term {
2022-07-26 15:50:25 -03:00
Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(),
Term::Const(ref c) => self.lower_anon_const(c).into(),
};
hir::TypeBindingKind::Equality { term }
2019-12-24 17:38:22 -05:00
}
AssocConstraintKind::Bound { ref bounds } => {
2019-05-10 03:46:39 +01:00
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
2019-05-08 15:56:39 -04:00
let (desugar_to_impl_trait, itctx) = match itctx {
// We are in the return position:
//
2019-05-10 03:46:39 +01:00
// fn foo() -> impl Iterator<Item: Debug>
2019-05-08 15:56:39 -04:00
//
// so desugar to
//
2019-05-10 03:46:39 +01:00
// fn foo() -> impl Iterator<Item = impl Debug>
ImplTraitContext::ReturnPositionOpaqueTy { .. }
| ImplTraitContext::TypeAliasesOpaqueTy { .. } => (true, itctx),
2019-05-08 15:56:39 -04:00
// We are in the argument position, but within a dyn type:
//
2019-05-10 03:46:39 +01:00
// fn foo(x: dyn Iterator<Item: Debug>)
2019-05-08 15:56:39 -04:00
//
// so desugar to
//
2019-05-10 03:46:39 +01:00
// fn foo(x: dyn Iterator<Item = impl Debug>)
ImplTraitContext::Universal if self.is_in_dyn_type => (true, itctx),
2019-05-08 15:56:39 -04:00
2019-05-10 03:46:39 +01:00
// In `type Foo = dyn Iterator<Item: Debug>` we desugar to
// `type Foo = dyn Iterator<Item = impl Debug>` but we have to override the
// "impl trait context" to permit `impl Debug` in this position (it desugars
2019-08-01 00:41:54 +01:00
// then to an opaque type).
2019-05-08 15:56:39 -04:00
//
// FIXME: this is only needed until `impl Trait` is allowed in type aliases.
ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, itctx_tait),
2019-05-08 15:56:39 -04:00
// We are in the parameter position, but not within a dyn type:
2019-05-08 15:56:39 -04:00
//
2019-05-10 03:46:39 +01:00
// fn foo(x: impl Iterator<Item: Debug>)
2019-05-08 15:56:39 -04:00
//
2019-05-10 03:46:39 +01:00
// so we leave it as is and this gets expanded in astconv to a bound like
// `<T as Iterator>::Item: Debug` where `T` is the type parameter for the
2019-05-08 15:56:39 -04:00
// `impl Iterator`.
_ => (false, itctx),
};
2019-05-08 15:56:39 -04:00
if desugar_to_impl_trait {
2019-05-10 03:46:39 +01:00
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
2019-05-08 15:57:06 -04:00
// constructing the HIR for `impl bounds...` and then lowering that.
2021-07-18 20:09:20 +02:00
let impl_trait_node_id = self.next_node_id();
self.with_dyn_type_scope(false, |this| {
2021-07-18 20:09:20 +02:00
let node_id = this.next_node_id();
let ty = this.ast_arena.tys.alloc(Ty {
id: node_id,
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
span: this.lower_span(constraint.span),
tokens: None,
});
let ty = this.lower_ty(ty, itctx);
2019-05-08 15:57:06 -04:00
hir::TypeBindingKind::Equality { term: ty.into() }
})
} else {
2019-05-08 15:57:06 -04:00
// Desugar `AssocTy: Bounds` into a type binding where the
// later desugars into a trait predicate.
2022-07-26 15:50:25 -03:00
let bounds = self.lower_param_bounds(bounds, itctx);
2019-12-24 17:38:22 -05:00
hir::TypeBindingKind::Constraint { bounds }
}
}
};
hir::TypeBinding {
2019-08-19 12:24:06 -07:00
hir_id: self.lower_node_id(constraint.id),
ident: self.lower_ident(constraint.ident),
gen_args,
2019-05-08 15:57:06 -04:00
kind,
span: self.lower_span(constraint.span),
}
2015-07-31 00:04:06 -07:00
}
2022-06-15 01:06:40 +01:00
fn emit_bad_parenthesized_trait_in_assoc_ty(&self, data: &ParenthesizedArgs) {
// Suggest removing empty parentheses: "Trait()" -> "Trait"
let sub = if data.inputs.is_empty() {
let parentheses_span =
data.inputs_span.shrink_to_lo().to(data.inputs_span.shrink_to_hi());
AssocTyParenthesesSub::Empty { parentheses_span }
}
// Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
else {
// Start of parameters to the 1st argument
let open_param = data.inputs_span.shrink_to_lo().to(data
.inputs
.first()
.unwrap()
.span
.shrink_to_lo());
// End of last argument to end of parameters
let close_param =
data.inputs.last().unwrap().span.shrink_to_hi().to(data.inputs_span.shrink_to_hi());
AssocTyParenthesesSub::NotEmpty { open_param, close_param }
};
self.tcx.sess.emit_err(AssocTyParentheses { span: data.span, sub });
}
#[instrument(level = "debug", skip(self))]
fn lower_generic_arg(
&mut self,
arg: &ast::GenericArg,
itctx: &ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::GenericArg<'hir> {
match arg {
2022-07-26 15:50:25 -03:00
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
ast::GenericArg::Type(ty) => {
2021-04-24 21:41:57 +00:00
match ty.kind {
TyKind::Infer if self.tcx.features().generic_arg_infer => {
2021-05-06 15:33:44 +00:00
return GenericArg::Infer(hir::InferArg {
hir_id: self.lower_node_id(ty.id),
span: self.lower_span(ty.span),
2021-05-06 15:33:44 +00:00
});
2021-04-24 21:41:57 +00:00
}
// We parse const arguments as path types as we cannot distinguish them during
// parsing. We try to resolve that ambiguity by attempting resolution in both the
// type and value namespaces. If we resolved the path in the value namespace, we
// transform it into a generic const argument.
TyKind::Path(ref qself, ref path) => {
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
let res = partial_res.base_res();
if !res.matches_ns(Namespace::TypeNS) {
debug!(
"lower_generic_arg: Lowering type argument as const argument: {:?}",
ty,
);
2021-08-22 14:46:15 +02:00
// Construct an AnonConst where the expr is the "ty"'s path.
2021-04-24 21:41:57 +00:00
let parent_def_id = self.current_hir_id_owner;
2021-07-18 20:09:20 +02:00
let node_id = self.next_node_id();
2021-04-24 21:41:57 +00:00
// Add a definition for the in-band const def.
self.create_def(
parent_def_id.def_id,
node_id,
DefPathData::AnonConst,
);
2021-04-24 21:41:57 +00:00
let span = self.lower_span(ty.span);
2021-04-24 21:41:57 +00:00
let path_expr = Expr {
id: ty.id,
kind: ExprKind::Path(qself.clone(), path.clone()),
span,
2021-04-24 21:41:57 +00:00
attrs: AttrVec::new(),
tokens: None,
};
let ct = self.with_new_scopes(|this| hir::AnonConst {
hir_id: this.lower_node_id(node_id),
body: this.lower_const_body(path_expr.span, Some(&path_expr)),
});
return GenericArg::Const(ConstArg { value: ct, span });
2021-04-24 21:41:57 +00:00
}
}
}
2021-04-24 21:41:57 +00:00
_ => {}
}
GenericArg::Type(self.lower_ty(&ty, itctx))
}
2019-12-24 17:38:22 -05:00
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
value: self.lower_anon_const(&ct),
span: self.lower_span(ct.value.span),
2019-12-24 17:38:22 -05:00
}),
}
}
#[instrument(level = "debug", skip(self))]
fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> {
2022-07-26 15:50:25 -03:00
self.arena.alloc(self.lower_ty_direct(t, itctx))
}
fn lower_path_ty(
&mut self,
t: &Ty,
qself: &Option<QSelf>,
path: &Path,
param_mode: ParamMode,
itctx: &ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::Ty<'hir> {
// Check whether we should interpret this as a bare trait object.
// This check mirrors the one in late resolution. We only introduce this special case in
// the rare occurrence we need to lower `Fresh` anonymous lifetimes.
// The other cases when a qpath should be opportunistically made a trait object are handled
// by `ty_path`.
if qself.is_none()
&& let Some(partial_res) = self.resolver.get_partial_res(t.id)
&& partial_res.unresolved_segments() == 0
&& let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
{
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef {
bound_generic_params: vec![],
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
span: t.span
});
let bound = this.lower_poly_trait_ref(
poly_trait_ref,
itctx,
);
let bounds = this.arena.alloc_from_iter([bound]);
let lifetime_bound = this.elided_dyn_bound(t.span);
(bounds, lifetime_bound)
});
let kind = hir::TyKind::TraitObject(bounds, &lifetime_bound, TraitObjectSyntax::None);
return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
}
let id = self.lower_node_id(t.id);
2022-07-26 15:50:25 -03:00
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
2021-07-10 10:00:54 +02:00
self.ty_path(id, t.span, qpath)
}
2019-11-30 17:46:46 +01:00
fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> {
hir::Ty { hir_id: self.next_id(), kind, span: self.lower_span(span) }
}
2019-12-01 11:22:58 +01:00
fn ty_tup(&mut self, span: Span, tys: &'hir [hir::Ty<'hir>]) -> hir::Ty<'hir> {
self.ty(span, hir::TyKind::Tup(tys))
}
fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> {
2019-09-26 17:25:31 +01:00
let kind = match t.kind {
2018-07-11 22:41:03 +08:00
TyKind::Infer => hir::TyKind::Infer,
TyKind::Err => hir::TyKind::Err,
2022-07-26 15:50:25 -03:00
TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
2018-07-11 22:41:03 +08:00
TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
TyKind::Rptr(ref region, ref mt) => {
2022-04-07 20:54:13 +02:00
let region = region.unwrap_or_else(|| {
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
self.resolver.get_lifetime_res(t.id)
{
debug_assert_eq!(start.plus(1), end);
start
} else {
2021-07-18 20:09:20 +02:00
self.next_node_id()
2022-04-07 20:54:13 +02:00
};
let span = self.tcx.sess.source_map().start_point(t.span);
Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id }
2022-04-07 20:54:13 +02:00
});
2022-07-26 15:50:25 -03:00
let lifetime = self.lower_lifetime(&region);
2018-07-11 22:41:03 +08:00
hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx))
}
TyKind::BareFn(ref f) => {
let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params);
hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy {
generic_params,
unsafety: self.lower_unsafety(f.unsafety),
abi: self.lower_extern(f.ext),
decl: self.lower_fn_decl(&f.decl, None, t.span, FnDeclKind::Pointer, None),
param_names: self.lower_fn_params_to_names(&f.decl),
}))
}
2018-07-11 22:41:03 +08:00
TyKind::Never => hir::TyKind::Never,
2022-07-26 15:50:25 -03:00
TyKind::Tup(ref tys) => hir::TyKind::Tup(
self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))),
),
TyKind::Paren(ref ty) => {
2022-07-26 15:50:25 -03:00
return self.lower_ty_direct(ty, itctx);
}
TyKind::Path(ref qself, ref path) => {
2022-07-26 15:50:25 -03:00
return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
}
2019-04-03 09:07:45 +02:00
TyKind::ImplicitSelf => {
let hir_id = self.next_id();
let res = self.expect_full_res(t.id);
let res = self.lower_res(res);
2019-04-03 09:07:45 +02:00
hir::TyKind::Path(hir::QPath::Resolved(
None,
2019-12-01 11:22:58 +01:00
self.arena.alloc(hir::Path {
res,
2022-09-01 08:44:20 +10:00
segments: arena_vec![self; hir::PathSegment::new(
Ident::with_dummy_span(kw::SelfUpper),
hir_id,
res
2019-12-01 11:22:58 +01:00
)],
span: self.lower_span(t.span),
2019-04-03 09:07:45 +02:00
}),
))
2019-12-24 17:38:22 -05:00
}
2022-07-26 15:50:25 -03:00
TyKind::Array(ref ty, ref length) => {
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
}
2019-12-24 17:38:22 -05:00
TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
2018-02-22 22:44:44 -08:00
TyKind::TraitObject(ref bounds, kind) => {
let mut lifetime_bound = None;
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
2019-12-01 11:22:58 +01:00
let bounds =
this.arena.alloc_from_iter(bounds.iter().filter_map(
|bound| match *bound {
GenericBound::Trait(
ref ty,
TraitBoundModifier::None | TraitBoundModifier::MaybeConst,
2022-07-26 15:50:25 -03:00
) => Some(this.lower_poly_trait_ref(ty, itctx)),
// `~const ?Bound` will cause an error during AST validation
// anyways, so treat it like `?Bound` as compilation proceeds.
GenericBound::Trait(
_,
TraitBoundModifier::Maybe | TraitBoundModifier::MaybeConstMaybe,
) => None,
2019-12-01 11:22:58 +01:00
GenericBound::Outlives(ref lifetime) => {
if lifetime_bound.is_none() {
2022-07-26 15:50:25 -03:00
lifetime_bound = Some(this.lower_lifetime(lifetime));
2019-12-01 11:22:58 +01:00
}
None
}
},
));
let lifetime_bound =
lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
(bounds, lifetime_bound)
});
hir::TyKind::TraitObject(bounds, lifetime_bound, kind)
}
TyKind::ImplTrait(def_node_id, ref bounds) => {
2017-12-15 12:27:20 -08:00
let span = t.span;
match itctx {
2022-09-06 17:37:00 +02:00
ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self
.lower_opaque_impl_trait(
span,
*origin,
def_node_id,
bounds,
*in_trait,
itctx,
),
2022-09-08 00:26:01 +00:00
ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
span,
hir::OpaqueTyOrigin::TyAlias,
def_node_id,
bounds,
false,
itctx,
2022-09-08 00:26:01 +00:00
),
ImplTraitContext::Universal => {
self.create_def(
self.current_hir_id_owner.def_id,
def_node_id,
DefPathData::ImplTrait,
);
let span = t.span;
2019-09-14 21:16:51 +01:00
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let (param, bounds, path) =
self.lower_generic_and_bounds(def_node_id, span, ident, bounds);
self.impl_trait_defs.push(param);
if let Some(bounds) = bounds {
self.impl_trait_bounds.push(bounds);
}
path
2018-03-21 04:24:27 -04:00
}
2022-09-06 17:16:08 +00:00
ImplTraitContext::Disallowed(
position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
) => {
2022-09-06 17:27:47 +00:00
self.tcx
.sess
.create_feature_err(
MisplacedImplTrait {
span: t.span,
position: DiagnosticArgFromDisplay(&position),
},
sym::return_position_impl_trait_in_trait,
)
.emit();
2022-09-06 17:16:08 +00:00
hir::TyKind::Err
}
ImplTraitContext::Disallowed(position) => {
self.tcx.sess.emit_err(MisplacedImplTrait {
span: t.span,
2022-08-19 14:55:06 +02:00
position: DiagnosticArgFromDisplay(&position),
});
2018-07-11 22:41:03 +08:00
hir::TyKind::Err
}
}
}
2020-03-21 02:38:48 +01:00
TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"),
TyKind::CVarArgs => {
self.tcx.sess.delay_span_bug(
t.span,
"`TyKind::CVarArgs` should have been handled elsewhere",
);
hir::TyKind::Err
}
};
hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
}
2015-07-31 00:04:06 -07:00
2022-08-03 19:34:00 -03:00
/// Lowers a `ReturnPositionOpaqueTy` (`-> impl Trait`) or a `TypeAliasesOpaqueTy` (`type F =
/// impl Trait`): this creates the associated Opaque Type (TAIT) definition and then returns a
/// HIR type that references the TAIT.
///
/// Given a function definition like:
///
/// ```rust
/// fn test<'a, T: Debug>(x: &'a T) -> impl Debug + 'a {
/// x
/// }
/// ```
///
/// we will create a TAIT definition in the HIR like
///
/// ```
/// type TestReturn<'a, T, 'x> = impl Debug + 'x
/// ```
///
/// and return a type like `TestReturn<'static, T, 'a>`, so that the function looks like:
///
/// ```rust
/// fn test<'a, T: Debug>(x: &'a T) -> TestReturn<'static, T, 'a>
/// ```
///
2022-08-04 12:48:20 -03:00
/// Note the subtlety around type parameters! The new TAIT, `TestReturn`, inherits all the
2022-08-03 19:34:00 -03:00
/// type parameters from the function `test` (this is implemented in the query layer, they aren't
/// added explicitly in the HIR). But this includes all the lifetimes, and we only want to
/// capture the lifetimes that are referenced in the bounds. Therefore, we add *extra* lifetime parameters
/// for the lifetimes that get captured (`'x`, in our example above) and reference those.
2022-09-06 17:24:36 -03:00
#[instrument(level = "debug", skip(self), ret)]
2019-08-01 00:41:54 +01:00
fn lower_opaque_impl_trait(
2018-06-06 15:50:59 -07:00
&mut self,
span: Span,
2019-12-28 15:39:52 +00:00
origin: hir::OpaqueTyOrigin,
opaque_ty_node_id: NodeId,
bounds: &GenericBounds,
2022-09-06 17:37:00 +02:00
in_trait: bool,
itctx: &ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::TyKind<'hir> {
2018-06-06 15:50:59 -07:00
// Make sure we know that some funky desugaring has been going on here.
// This is a first: there is code in other places like for loop
// desugaring that explicitly states that we don't want to track that.
// Not tracking it makes lints in rustc and clippy very fragile, as
2018-06-06 15:50:59 -07:00
// frequently opened issues show.
2019-12-24 17:38:22 -05:00
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
2018-06-06 15:50:59 -07:00
let opaque_ty_def_id = match origin {
hir::OpaqueTyOrigin::TyAlias => self.create_def(
self.current_hir_id_owner.def_id,
opaque_ty_node_id,
DefPathData::ImplTrait,
),
hir::OpaqueTyOrigin::FnReturn(fn_def_id) => {
self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait)
}
hir::OpaqueTyOrigin::AsyncFn(..) => bug!("unreachable"),
};
2022-08-04 09:58:37 -03:00
debug!(?opaque_ty_def_id);
2018-06-06 15:50:59 -07:00
// Contains the new lifetime definitions created for the TAIT (if any).
let mut collected_lifetimes = Vec::new();
// If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
// to capture the lifetimes that appear in the bounds. So visit the bounds to find out
// exactly which ones those are.
let lifetimes_to_remap = if origin == hir::OpaqueTyOrigin::TyAlias {
// in a TAIT like `type Foo<'a> = impl Foo<'a>`, we don't keep all the lifetime parameters
Vec::new()
} else {
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
// we only keep the lifetimes that appear in the `impl Debug` itself:
lifetime_collector::lifetimes_in_bounds(&self.resolver, bounds)
};
debug!(?lifetimes_to_remap);
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
let mut new_remapping = FxHashMap::default();
// If this opaque type is only capturing a subset of the lifetimes (those that appear
// in bounds), then create the new lifetime parameters required and create a mapping
// from the old `'a` (on the function) to the new `'a` (on the opaque type).
collected_lifetimes = lctx.create_lifetime_defs(
opaque_ty_def_id,
&lifetimes_to_remap,
&mut new_remapping,
);
2022-04-07 20:54:13 +02:00
debug!(?collected_lifetimes);
debug!(?new_remapping);
2018-06-06 15:50:59 -07:00
// Install the remapping from old to new (if any):
2022-08-02 20:01:40 -03:00
lctx.with_remapping(new_remapping, |lctx| {
2022-08-04 09:52:15 -03:00
// This creates HIR lifetime definitions as `hir::GenericParam`, in the given
// example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection
// containing `&['x]`.
let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(
|&(new_node_id, lifetime)| {
let hir_id = lctx.lower_node_id(new_node_id);
debug_assert_ne!(lctx.opt_local_def_id(new_node_id), None);
2022-08-02 20:01:40 -03:00
let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime {
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided)
} else {
(
hir::ParamName::Plain(lifetime.ident),
hir::LifetimeParamKind::Explicit,
)
};
hir::GenericParam {
hir_id,
name,
span: lifetime.ident.span,
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
}
},
));
2022-08-04 09:58:37 -03:00
debug!(?lifetime_defs);
2022-08-04 09:44:18 -03:00
// Then when we lower the param bounds, references to 'a are remapped to 'a1, so we
// get back Debug + 'a1, which is suitable for use on the TAIT.
let hir_bounds = lctx.lower_param_bounds(bounds, itctx);
2022-08-04 09:58:37 -03:00
debug!(?hir_bounds);
2022-08-04 09:44:18 -03:00
2022-08-02 20:01:40 -03:00
let opaque_ty_item = hir::OpaqueTy {
generics: self.arena.alloc(hir::Generics {
params: lifetime_defs,
predicates: &[],
has_where_clause_predicates: false,
where_clause_span: lctx.lower_span(span),
span: lctx.lower_span(span),
}),
bounds: hir_bounds,
origin,
2022-09-06 17:37:00 +02:00
in_trait,
2022-08-02 20:01:40 -03:00
};
2022-08-04 09:58:37 -03:00
debug!(?opaque_ty_item);
2018-06-06 15:50:59 -07:00
2022-08-02 20:01:40 -03:00
lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
})
});
2022-08-04 09:56:12 -03:00
// This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
// TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
let lifetimes =
self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
2021-07-18 20:09:20 +02:00
let id = self.next_node_id();
let span = lifetime.ident.span;
let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
Ident::with_dummy_span(kw::UnderscoreLifetime)
} else {
lifetime.ident
};
let l = self.new_named_lifetime(lifetime.id, id, span, ident);
2022-04-07 20:54:13 +02:00
hir::GenericArg::Lifetime(l)
}));
2022-08-04 09:58:37 -03:00
debug!(?lifetimes);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir::TyKind::OpaqueDef(
hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } },
lifetimes,
in_trait,
)
}
2019-08-01 00:41:54 +01:00
/// Registers a new opaque type with the proper `NodeId`s and
/// returns the lowered node-ID for the opaque type.
fn generate_opaque_type(
&mut self,
opaque_ty_id: LocalDefId,
2019-11-30 17:46:46 +01:00
opaque_ty_item: hir::OpaqueTy<'hir>,
span: Span,
opaque_ty_span: Span,
) -> hir::OwnerNode<'hir> {
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
2019-08-01 00:41:54 +01:00
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
let opaque_ty_item = hir::Item {
def_id: hir::OwnerId { def_id: opaque_ty_id },
ident: Ident::empty(),
2019-09-26 17:51:36 +01:00
kind: opaque_ty_item_kind,
2022-02-13 11:30:48 +01:00
vis_span: self.lower_span(span.shrink_to_lo()),
span: self.lower_span(opaque_ty_span),
};
hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
}
/// Given a `parent_def_id`, a list of `lifetimes_in_bounds and a `remapping` hash to be
/// filled, this function creates new definitions for `Param` and `Fresh` lifetimes, inserts the
/// new definition, adds it to the remapping with the definition of the given lifetime and
/// returns a list of lifetimes to be lowered afterwards.
fn create_lifetime_defs(
&mut self,
parent_def_id: LocalDefId,
lifetimes_in_bounds: &[Lifetime],
remapping: &mut FxHashMap<LocalDefId, LocalDefId>,
) -> Vec<(NodeId, Lifetime)> {
let mut result = Vec::new();
for lifetime in lifetimes_in_bounds {
let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error);
debug!(?res);
match res {
LifetimeRes::Param { param: old_def_id, binder: _ } => {
if remapping.get(&old_def_id).is_none() {
let node_id = self.next_node_id();
let new_def_id = self.create_def(
parent_def_id,
node_id,
DefPathData::LifetimeNs(lifetime.ident.name),
);
remapping.insert(old_def_id, new_def_id);
result.push((node_id, *lifetime));
}
}
LifetimeRes::Fresh { param, binder: _ } => {
debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
if let Some(old_def_id) = self.opt_local_def_id(param) && remapping.get(&old_def_id).is_none() {
let node_id = self.next_node_id();
let new_def_id = self.create_def(
parent_def_id,
node_id,
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
);
remapping.insert(old_def_id, new_def_id);
result.push((node_id, *lifetime));
}
}
LifetimeRes::Static | LifetimeRes::Error => {}
2022-08-04 12:07:03 -03:00
res => {
let bug_msg = format!(
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
res, lifetime.ident, lifetime.ident.span
);
span_bug!(lifetime.ident.span, "{}", bug_msg);
}
}
}
result
}
2019-12-01 17:21:00 +01:00
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
// as they are not explicit in HIR/Ty function signatures.
// (instead, the `c_variadic` flag is set to `true`)
let mut inputs = &decl.inputs[..];
if decl.c_variadic() {
inputs = &inputs[..inputs.len() - 1];
}
2019-12-01 17:21:00 +01:00
self.arena.alloc_from_iter(inputs.iter().map(|param| match param.pat.kind {
PatKind::Ident(_, ident, _) => self.lower_ident(ident),
_ => Ident::new(kw::Empty, self.lower_span(param.pat.span)),
2019-12-01 17:21:00 +01:00
}))
}
2018-06-06 15:50:59 -07:00
// Lowers a function declaration.
//
// `decl`: the unlowered (AST) function declaration.
// `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the
2018-06-06 15:50:59 -07:00
// given DefId, otherwise impl Trait is disallowed. Must be `Some` if
// `make_ret_async` is also `Some`.
// `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the
// return type. This is used for `async fn` declarations. The `NodeId` is the ID of the
2022-09-02 15:57:31 +00:00
// return type `impl Trait` item, and the `Span` points to the `async` keyword.
#[instrument(level = "debug", skip(self))]
2018-03-21 04:24:27 -04:00
fn lower_fn_decl(
&mut self,
decl: &FnDecl,
fn_node_id: Option<NodeId>,
2022-09-02 15:57:31 +00:00
fn_span: Span,
kind: FnDeclKind,
2022-09-02 15:57:31 +00:00
make_ret_async: Option<(NodeId, Span)>,
2019-12-01 11:22:58 +01:00
) -> &'hir hir::FnDecl<'hir> {
let c_variadic = decl.c_variadic();
2022-04-07 20:54:13 +02:00
// Skip the `...` (`CVarArgs`) trailing arguments from the AST,
// as they are not explicit in HIR/Ty function signatures.
// (instead, the `c_variadic` flag is set to `true`)
let mut inputs = &decl.inputs[..];
if c_variadic {
inputs = &inputs[..inputs.len() - 1];
}
let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
if fn_node_id.is_some() {
self.lower_ty_direct(&param.ty, &ImplTraitContext::Universal)
2022-04-07 20:54:13 +02:00
} else {
self.lower_ty_direct(
&param.ty,
&ImplTraitContext::Disallowed(match kind {
2022-04-07 20:54:13 +02:00
FnDeclKind::Fn | FnDeclKind::Inherent => {
unreachable!("fn should allow in-band lifetimes")
}
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnParam,
FnDeclKind::Closure => ImplTraitPosition::ClosureParam,
FnDeclKind::Pointer => ImplTraitPosition::PointerParam,
FnDeclKind::Trait => ImplTraitPosition::TraitParam,
FnDeclKind::Impl => ImplTraitPosition::ImplParam,
}),
)
}
2022-04-07 20:54:13 +02:00
}));
2018-06-06 15:50:59 -07:00
2022-09-02 15:57:31 +00:00
let output = if let Some((ret_id, span)) = make_ret_async {
if !kind.async_fn_allowed(self.tcx) {
match kind {
FnDeclKind::Trait | FnDeclKind::Impl => {
self.tcx
.sess
.create_feature_err(
TraitFnAsync { fn_span, span },
sym::async_fn_in_trait,
)
.emit();
}
_ => {
self.tcx.sess.emit_err(TraitFnAsync { fn_span, span });
}
}
2022-09-02 15:57:31 +00:00
}
self.lower_async_fn_ret_ty(
&decl.output,
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
ret_id,
matches!(kind, FnDeclKind::Trait),
)
2018-06-06 15:50:59 -07:00
} else {
match decl.output {
2020-02-15 12:10:59 +09:00
FnRetTy::Ty(ref ty) => {
let mut context = match fn_node_id {
Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
2022-09-06 17:37:00 +02:00
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait: matches!(kind, FnDeclKind::Trait),
2022-09-06 17:37:00 +02:00
}
}
_ => ImplTraitContext::Disallowed(match kind {
FnDeclKind::Fn | FnDeclKind::Inherent => {
unreachable!("fn should allow in-band lifetimes")
}
FnDeclKind::ExternFn => ImplTraitPosition::ExternFnReturn,
FnDeclKind::Closure => ImplTraitPosition::ClosureReturn,
FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
}),
2019-12-29 14:23:20 +00:00
};
hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
2019-12-29 14:23:20 +00:00
}
FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
2018-06-06 15:50:59 -07:00
}
};
2019-12-01 11:22:58 +01:00
self.arena.alloc(hir::FnDecl {
2018-06-06 15:50:59 -07:00
inputs,
output,
c_variadic,
2019-12-24 17:38:22 -05:00
implicit_self: decl.inputs.get(0).map_or(hir::ImplicitSelfKind::None, |arg| {
2020-12-29 01:20:06 +01:00
let is_mutable_pat = matches!(
arg.pat.kind,
2022-08-30 17:34:35 -05:00
PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..)
2020-12-29 01:20:06 +01:00
);
2019-12-24 17:38:22 -05:00
match arg.ty.kind {
TyKind::ImplicitSelf if is_mutable_pat => hir::ImplicitSelfKind::Mut,
TyKind::ImplicitSelf => hir::ImplicitSelfKind::Imm,
// Given we are only considering `ImplicitSelf` types, we needn't consider
// the case where we have a mutable pattern to a reference as that would
// no longer be an `ImplicitSelf`.
TyKind::Rptr(_, ref mt)
if mt.ty.kind.is_implicit_self() && mt.mutbl == ast::Mutability::Mut =>
{
hir::ImplicitSelfKind::MutRef
}
2019-12-24 17:38:22 -05:00
TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() => {
hir::ImplicitSelfKind::ImmRef
}
_ => hir::ImplicitSelfKind::None,
}
}),
})
}
2015-07-31 00:04:06 -07:00
// Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }`
// combined with the following definition of `OpaqueTy`:
//
// type OpaqueTy<generics_from_parent_fn> = impl Future<Output = T>;
2018-06-06 15:50:59 -07:00
//
// `output`: unlowered output type (`T` in `-> T`)
// `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition)
// `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created
#[instrument(level = "debug", skip(self))]
2018-06-06 15:50:59 -07:00
fn lower_async_fn_ret_ty(
&mut self,
2020-02-15 12:10:59 +09:00
output: &FnRetTy,
2022-04-07 20:54:13 +02:00
fn_node_id: NodeId,
opaque_ty_node_id: NodeId,
2022-09-06 17:37:00 +02:00
in_trait: bool,
2020-02-15 12:10:59 +09:00
) -> hir::FnRetTy<'hir> {
let span = output.span();
2018-06-06 15:50:59 -07:00
2019-12-24 17:38:22 -05:00
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
2018-06-06 15:50:59 -07:00
2021-07-18 20:09:20 +02:00
let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
let fn_def_id = self.local_def_id(fn_node_id);
2018-06-06 15:50:59 -07:00
2019-08-12 19:21:13 -04:00
// When we create the opaque type for this async fn, it is going to have
// to capture all the lifetimes involved in the signature (including in the
// return type). This is done by introducing lifetime parameters for:
2019-08-12 19:21:13 -04:00
//
// - all the explicitly declared lifetimes from the impl and function itself;
// - all the elided lifetimes in the fn arguments;
// - all the elided lifetimes in the return type.
2019-08-12 19:21:13 -04:00
//
// So for example in this snippet:
//
// ```rust
// impl<'a> Foo<'a> {
// async fn bar<'b>(&self, x: &'b Vec<f64>, y: &str) -> &u32 {
// // ^ '0 ^ '1 ^ '2
// // elided lifetimes used below
// }
// }
// ```
//
// we would create an opaque type like:
//
// ```
// type Bar<'a, 'b, '0, '1, '2> = impl Future<Output = &'2 u32>;
2019-08-12 19:21:13 -04:00
// ```
//
// and we would then desugar `bar` to the equivalent of:
//
// ```rust
// impl<'a> Foo<'a> {
// fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_>
2019-08-12 19:21:13 -04:00
// }
// ```
//
// Note that the final parameter to `Bar` is `'_`, not `'2` --
// this is because the elided lifetimes from the return type
// should be figured out using the ordinary elision rules, and
// this desugaring achieves that.
// Calculate all the lifetimes that should be captured
// by the opaque type. This should include all in-scope
// lifetime parameters, including those defined in-band.
// Contains the new lifetime definitions created for the TAIT (if any) generated for the
// return type.
2022-08-03 23:26:10 -03:00
let mut collected_lifetimes = Vec::new();
let mut new_remapping = FxHashMap::default();
let extra_lifetime_params = self.resolver.take_extra_lifetime_params(opaque_ty_node_id);
debug!(?extra_lifetime_params);
for (ident, outer_node_id, outer_res) in extra_lifetime_params {
2021-07-18 20:09:20 +02:00
let outer_def_id = self.local_def_id(outer_node_id);
let inner_node_id = self.next_node_id();
2022-04-07 20:54:13 +02:00
2022-04-20 21:08:06 +02:00
// Add a definition for the in scope lifetime def.
let inner_def_id = self.create_def(
opaque_ty_def_id,
inner_node_id,
DefPathData::LifetimeNs(ident.name),
);
new_remapping.insert(outer_def_id, inner_def_id);
let inner_res = match outer_res {
// Input lifetime like `'a`:
LifetimeRes::Param { param, .. } => {
LifetimeRes::Param { param, binder: fn_node_id }
2022-04-07 20:54:13 +02:00
}
// Input lifetime like `'1`:
LifetimeRes::Fresh { param, .. } => {
LifetimeRes::Fresh { param, binder: fn_node_id }
}
LifetimeRes::Static | LifetimeRes::Error => continue,
res => {
panic!(
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
res, ident, ident.span
)
2022-04-07 20:54:13 +02:00
}
};
let lifetime = Lifetime { id: outer_node_id, ident };
2022-08-03 23:26:10 -03:00
collected_lifetimes.push((inner_node_id, lifetime, Some(inner_res)));
2022-04-07 20:54:13 +02:00
}
2022-08-03 23:26:10 -03:00
debug!(?collected_lifetimes);
// We only want to capture the lifetimes that appear in the bounds. So visit the bounds to
// find out exactly which ones those are.
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a` example,
// we only keep the lifetimes that appear in the `impl Debug` itself:
let lifetimes_to_remap = lifetime_collector::lifetimes_in_ret_ty(&self.resolver, output);
debug!(?lifetimes_to_remap);
self.with_hir_id_owner(opaque_ty_node_id, |this| {
// If this opaque type is only capturing a subset of the lifetimes (those that appear
// in bounds), then create the new lifetime parameters required and create a mapping
// from the old `'a` (on the function) to the new `'a` (on the opaque type).
2022-08-03 23:26:10 -03:00
collected_lifetimes.extend(
this.create_lifetime_defs(
opaque_ty_def_id,
&lifetimes_to_remap,
&mut new_remapping,
)
.into_iter()
.map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)),
);
2022-08-03 23:26:10 -03:00
debug!(?collected_lifetimes);
debug!(?new_remapping);
// Install the remapping from old to new (if any):
2022-08-02 20:01:40 -03:00
this.with_remapping(new_remapping, |this| {
// We have to be careful to get elision right here. The
// idea is that we create a lifetime parameter for each
// lifetime in the return type. So, given a return type
// like `async fn foo(..) -> &[&u32]`, we lower to `impl
// Future<Output = &'1 [ &'2 u32 ]>`.
//
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
// hence the elision takes place at the fn site.
let future_bound = this.lower_async_fn_output_type_to_future_bound(
output,
span,
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
} else {
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait,
}
},
);
2022-08-02 20:01:40 -03:00
2022-08-03 23:26:10 -03:00
let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map(
|&(new_node_id, lifetime, _)| {
let hir_id = this.lower_node_id(new_node_id);
debug_assert_ne!(this.opt_local_def_id(new_node_id), None);
2022-08-02 20:01:40 -03:00
let (name, kind) = if lifetime.ident.name == kw::UnderscoreLifetime {
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided)
} else {
(
hir::ParamName::Plain(lifetime.ident),
hir::LifetimeParamKind::Explicit,
)
};
hir::GenericParam {
hir_id,
name,
span: lifetime.ident.span,
pure_wrt_drop: false,
kind: hir::GenericParamKind::Lifetime { kind },
colon_span: None,
}
},
));
2022-08-02 20:01:40 -03:00
debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
let opaque_ty_item = hir::OpaqueTy {
generics: this.arena.alloc(hir::Generics {
params: generic_params,
predicates: &[],
has_where_clause_predicates: false,
where_clause_span: this.lower_span(span),
span: this.lower_span(span),
}),
bounds: arena_vec![this; future_bound],
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
2022-09-06 17:37:00 +02:00
in_trait,
2022-08-02 20:01:40 -03:00
};
2018-06-06 15:50:59 -07:00
2022-08-02 20:01:40 -03:00
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
})
});
2018-06-06 15:50:59 -07:00
2022-04-07 20:54:13 +02:00
// As documented above, we need to create the lifetime
// arguments to our opaque type. Continuing with our example,
// we're creating the type arguments for the return type:
//
// ```
// Bar<'a, 'b, '0, '1, '_>
// ```
//
// For the "input" lifetime parameters, we wish to create
// references to the parameters themselves, including the
// "implicit" ones created from parameter types (`'a`, `'b`,
// '`0`, `'1`).
//
// For the "output" lifetime parameters, we just want to
// generate `'_`.
2022-08-03 23:26:10 -03:00
let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
|(_, lifetime, res)| {
2021-07-18 20:09:20 +02:00
let id = self.next_node_id();
let span = lifetime.ident.span;
let ident = if lifetime.ident.name == kw::UnderscoreLifetime {
Ident::with_dummy_span(kw::UnderscoreLifetime)
} else {
lifetime.ident
};
let res = res.unwrap_or(
self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
);
hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, span, ident, res))
2022-08-03 23:26:10 -03:00
},
));
2018-06-21 22:24:24 -07:00
// Create the `Foo<...>` reference itself. Note that the `type
// Foo = impl Trait` is, internally, created as a child of the
// async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply.
2022-09-06 17:37:00 +02:00
let opaque_ty_ref = hir::TyKind::OpaqueDef(
hir::ItemId { def_id: hir::OwnerId { def_id: opaque_ty_def_id } },
2022-09-06 17:37:00 +02:00
generic_args,
in_trait,
);
let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
2020-02-15 12:10:59 +09:00
hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
}
2018-06-06 15:50:59 -07:00
/// Transforms `-> T` into `Future<Output = T>`.
fn lower_async_fn_output_type_to_future_bound(
&mut self,
2020-02-15 12:10:59 +09:00
output: &FnRetTy,
span: Span,
mut nested_impl_trait_context: ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::GenericBound<'hir> {
// Compute the `T` in `Future<Output = T>` from the return type.
let output_ty = match output {
2020-02-15 12:10:59 +09:00
FnRetTy::Ty(ty) => {
2019-12-29 14:23:20 +00:00
// Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
// `impl Future` opaque type that `async fn` implicitly
// generates.
self.lower_ty(ty, &mut nested_impl_trait_context)
2019-12-29 14:23:20 +00:00
}
2020-02-15 12:10:59 +09:00
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
};
2018-06-06 15:50:59 -07:00
// "<Output = T>"
let future_args = self.arena.alloc(hir::GenericArgs {
2019-12-01 17:10:12 +01:00
args: &[],
bindings: arena_vec![self; self.output_ty_binding(span, output_ty)],
parenthesized: false,
span_ext: DUMMY_SP,
2018-06-06 15:50:59 -07:00
});
hir::GenericBound::LangItemTrait(
// ::std::future::Future<future_params>
hir::LangItem::Future,
self.lower_span(span),
self.next_id(),
future_args,
)
2018-06-06 15:50:59 -07:00
}
#[instrument(level = "trace", skip(self))]
2018-05-28 13:33:28 +01:00
fn lower_param_bound(
2018-03-21 04:24:27 -04:00
&mut self,
tpb: &GenericBound,
itctx: &ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
2022-07-26 15:50:25 -03:00
self.lower_poly_trait_ref(p, itctx),
self.lower_trait_bound_modifier(*modifier),
2019-12-24 17:38:22 -05:00
),
GenericBound::Outlives(lifetime) => {
2022-07-26 15:50:25 -03:00
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
}
}
}
2015-07-31 00:04:06 -07:00
fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime {
let span = self.lower_span(l.ident.span);
2022-04-07 20:54:13 +02:00
let ident = self.lower_ident(l.ident);
self.new_named_lifetime(l.id, l.id, span, ident)
}
2017-11-16 22:59:45 -08:00
#[instrument(level = "debug", skip(self))]
2022-04-07 20:54:13 +02:00
fn new_named_lifetime_with_res(
&mut self,
id: NodeId,
span: Span,
2022-04-07 20:54:13 +02:00
ident: Ident,
res: LifetimeRes,
) -> &'hir hir::Lifetime {
2022-04-07 20:54:13 +02:00
let name = match res {
2022-08-02 20:01:40 -03:00
LifetimeRes::Param { param, .. } => {
2022-04-07 20:54:13 +02:00
let p_name = ParamName::Plain(ident);
let param = self.get_remapped_def_id(param);
hir::LifetimeName::Param(param, p_name)
2022-04-07 20:54:13 +02:00
}
LifetimeRes::Fresh { param, .. } => {
2022-04-07 20:54:13 +02:00
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
2022-08-02 20:01:40 -03:00
let param = self.local_def_id(param);
hir::LifetimeName::Param(param, ParamName::Fresh)
2022-04-07 20:54:13 +02:00
}
LifetimeRes::Infer => hir::LifetimeName::Infer,
2022-04-07 20:54:13 +02:00
LifetimeRes::Static => hir::LifetimeName::Static,
LifetimeRes::Error => hir::LifetimeName::Error,
res => panic!("Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, span),
};
2022-08-02 20:01:40 -03:00
debug!(?name);
self.arena.alloc(hir::Lifetime {
hir_id: self.lower_node_id(id),
span: self.lower_span(span),
name,
})
2015-07-31 00:04:06 -07:00
}
#[instrument(level = "debug", skip(self))]
fn new_named_lifetime(
&mut self,
id: NodeId,
new_id: NodeId,
span: Span,
ident: Ident,
) -> &'hir hir::Lifetime {
let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error);
self.new_named_lifetime_with_res(new_id, span, ident, res)
}
2019-12-26 17:57:50 +01:00
fn lower_generic_params_mut<'s>(
&'s mut self,
params: &'s [GenericParam],
) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
params.iter().map(move |param| self.lower_generic_param(param))
2019-12-24 17:38:22 -05:00
}
fn lower_generic_params(&mut self, params: &[GenericParam]) -> &'hir [hir::GenericParam<'hir>] {
self.arena.alloc_from_iter(self.lower_generic_params_mut(params))
2019-12-01 17:10:12 +01:00
}
#[instrument(level = "trace", skip(self))]
fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> {
2022-05-20 17:32:48 -03:00
let (name, kind) = self.lower_generic_param_kind(param);
let hir_id = self.lower_node_id(param.id);
self.lower_attrs(hir_id, &param.attrs);
hir::GenericParam {
hir_id,
name,
span: self.lower_span(param.span()),
pure_wrt_drop: self.tcx.sess.contains_name(&param.attrs, sym::may_dangle),
2022-05-20 17:32:48 -03:00
kind,
colon_span: param.colon_span.map(|s| self.lower_span(s)),
}
}
fn lower_generic_param_kind(
&mut self,
param: &GenericParam,
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
match param.kind {
GenericParamKind::Lifetime => {
// AST resolution emitted an error on those parameters, so we lower them using
// `ParamName::Error`.
let param_name =
if let Some(LifetimeRes::Error) = self.resolver.get_lifetime_res(param.id) {
ParamName::Error
} else {
let ident = self.lower_ident(param.ident);
ParamName::Plain(ident)
};
2019-12-24 17:38:22 -05:00
let kind =
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit };
2017-11-16 22:59:45 -08:00
(param_name, kind)
2018-05-26 00:27:54 +01:00
}
2018-05-28 13:33:28 +01:00
GenericParamKind::Type { ref default, .. } => {
let kind = hir::GenericParamKind::Type {
2019-12-28 15:39:52 +00:00
default: default.as_ref().map(|x| {
self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type))
2019-12-28 15:39:52 +00:00
}),
synthetic: false,
};
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
2018-05-26 00:27:54 +01:00
}
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type));
let default = default.as_ref().map(|def| self.lower_anon_const(def));
(
hir::ParamName::Plain(self.lower_ident(param.ident)),
hir::GenericParamKind::Const { ty, default },
)
}
2018-05-26 00:27:54 +01:00
}
}
2015-07-31 00:04:06 -07:00
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
2022-07-26 15:50:25 -03:00
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
hir::QPath::Resolved(None, path) => path,
2020-03-21 02:38:48 +01:00
qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath),
};
2019-12-24 17:38:22 -05:00
hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) }
}
#[instrument(level = "debug", skip(self))]
2018-03-21 04:24:27 -04:00
fn lower_poly_trait_ref(
&mut self,
p: &PolyTraitRef,
itctx: &ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params =
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx);
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
}
fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> {
2022-07-26 15:50:25 -03:00
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
}
2015-07-31 00:04:06 -07:00
2022-09-06 17:24:36 -03:00
#[instrument(level = "debug", skip(self), ret)]
2019-12-24 17:38:22 -05:00
fn lower_param_bounds(
&mut self,
bounds: &[GenericBound],
itctx: &ImplTraitContext,
2019-11-30 17:46:46 +01:00
) -> hir::GenericBounds<'hir> {
2022-07-26 15:50:25 -03:00
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
2019-12-01 11:22:58 +01:00
}
fn lower_param_bounds_mut<'s>(
2019-12-26 17:36:54 +01:00
&'s mut self,
bounds: &'s [GenericBound],
itctx: &'s ImplTraitContext,
) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> {
2022-07-26 15:50:25 -03:00
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
}
2022-09-06 17:24:36 -03:00
#[instrument(level = "debug", skip(self), ret)]
fn lower_generic_and_bounds(
&mut self,
node_id: NodeId,
span: Span,
ident: Ident,
bounds: &[GenericBound],
) -> (hir::GenericParam<'hir>, Option<hir::WherePredicate<'hir>>, hir::TyKind<'hir>) {
// Add a definition for the in-band `Param`.
2021-07-18 20:09:20 +02:00
let def_id = self.local_def_id(node_id);
// Set the name to `impl Bound1 + Bound2`.
let param = hir::GenericParam {
hir_id: self.lower_node_id(node_id),
name: ParamName::Plain(self.lower_ident(ident)),
pure_wrt_drop: false,
span: self.lower_span(span),
kind: hir::GenericParamKind::Type { default: None, synthetic: true },
colon_span: None,
};
let preds = self.lower_generic_bound_predicate(
ident,
node_id,
&GenericParamKind::Type { default: None },
bounds,
&ImplTraitContext::Universal,
hir::PredicateOrigin::ImplTrait,
);
let hir_id = self.next_id();
let res = Res::Def(DefKind::TyParam, def_id.to_def_id());
let ty = hir::TyKind::Path(hir::QPath::Resolved(
None,
self.arena.alloc(hir::Path {
span: self.lower_span(span),
res,
2022-09-01 08:44:20 +10:00
segments:
arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)],
}),
));
(param, preds, ty)
}
/// Lowers a block directly to an expression, presuming that it
/// has no attributes and is not targeted by a `break`.
2019-11-29 13:43:03 +01:00
fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
let block = self.lower_block(b, false);
2019-12-03 16:38:34 +01:00
self.expr_block(block, AttrVec::new())
}
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
match c.value.kind {
ExprKind::Underscore => {
if self.tcx.features().generic_arg_infer {
hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span)
} else {
feature_err(
&self.tcx.sess.parse_sess,
sym::generic_arg_infer,
c.value.span,
"using `_` for array lengths is unstable",
)
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
hir::ArrayLen::Body(self.lower_anon_const(c))
}
}
_ => hir::ArrayLen::Body(self.lower_anon_const(c)),
}
}
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
2019-12-24 17:38:22 -05:00
self.with_new_scopes(|this| hir::AnonConst {
hir_id: this.lower_node_id(c.id),
body: this.lower_const_body(c.value.span, Some(&c.value)),
2018-07-20 15:59:00 +02:00
})
}
fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
match u {
2020-01-05 01:50:05 +01:00
CompilerGenerated => hir::UnsafeSource::CompilerGenerated,
UserProvided => hir::UnsafeSource::UserProvided,
}
2015-07-31 00:04:06 -07:00
}
fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
match f {
TraitBoundModifier::None => hir::TraitBoundModifier::None,
TraitBoundModifier::MaybeConst => hir::TraitBoundModifier::MaybeConst,
// `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a
// placeholder for compilation to proceed.
2020-01-20 01:20:45 -08:00
TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => {
hir::TraitBoundModifier::Maybe
}
}
2015-07-31 00:04:06 -07:00
}
2015-09-28 15:00:15 +13:00
// Helper methods for building HIR.
2015-09-28 15:00:15 +13:00
2019-11-29 13:43:03 +01:00
fn stmt(&mut self, span: Span, kind: hir::StmtKind<'hir>) -> hir::Stmt<'hir> {
hir::Stmt { span: self.lower_span(span), kind, hir_id: self.next_id() }
}
2019-11-29 13:43:03 +01:00
fn stmt_expr(&mut self, span: Span, expr: hir::Expr<'hir>) -> hir::Stmt<'hir> {
2019-11-29 19:01:31 +01:00
self.stmt(span, hir::StmtKind::Expr(self.arena.alloc(expr)))
2019-08-10 12:38:19 +02:00
}
2018-03-21 04:24:27 -04:00
fn stmt_let_pat(
&mut self,
2021-01-24 17:14:17 +01:00
attrs: Option<&'hir [Attribute]>,
span: Span,
2019-11-29 19:01:31 +01:00
init: Option<&'hir hir::Expr<'hir>>,
pat: &'hir hir::Pat<'hir>,
2018-03-21 04:24:27 -04:00
source: hir::LocalSource,
2019-11-29 13:43:03 +01:00
) -> hir::Stmt<'hir> {
let hir_id = self.next_id();
2021-01-24 17:14:17 +01:00
if let Some(a) = attrs {
debug_assert!(!a.is_empty());
2021-07-16 14:42:26 +02:00
self.attrs.insert(hir_id.local_id, a);
2021-01-24 17:14:17 +01:00
}
let local = hir::Local {
hir_id,
init,
pat,
els: None,
source,
span: self.lower_span(span),
ty: None,
};
self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local)))
}
2019-02-02 15:40:08 +01:00
2019-12-01 21:10:43 +01:00
fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> {
2019-11-29 19:01:31 +01:00
self.block_all(expr.span, &[], Some(expr))
}
2015-09-28 15:00:15 +13:00
2018-03-21 04:24:27 -04:00
fn block_all(
&mut self,
span: Span,
2019-11-29 19:01:31 +01:00
stmts: &'hir [hir::Stmt<'hir>],
expr: Option<&'hir hir::Expr<'hir>>,
2019-12-01 21:10:43 +01:00
) -> &'hir hir::Block<'hir> {
let blk = hir::Block {
stmts,
expr,
2019-04-26 14:23:30 +02:00
hir_id: self.next_id(),
2020-01-05 01:50:05 +01:00
rules: hir::BlockCheckMode::DefaultBlock,
span: self.lower_span(span),
targeted_by_break: false,
2019-12-01 21:10:43 +01:00
};
self.arena.alloc(blk)
}
2015-09-28 15:00:15 +13:00
fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
let field = self.single_pat_field(span, pat);
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None)
}
2015-09-28 15:00:15 +13:00
fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
let field = self.single_pat_field(span, pat);
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None)
}
2019-11-29 19:01:31 +01:00
fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
let field = self.single_pat_field(span, pat);
self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None)
}
2019-11-29 19:01:31 +01:00
fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> {
self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None)
}
2015-09-28 15:00:15 +13:00
fn single_pat_field(
2018-03-21 04:24:27 -04:00
&mut self,
span: Span,
pat: &'hir hir::Pat<'hir>,
) -> &'hir [hir::PatField<'hir>] {
let field = hir::PatField {
hir_id: self.next_id(),
ident: Ident::new(sym::integer(0), self.lower_span(span)),
is_shorthand: false,
pat,
span: self.lower_span(span),
};
arena_vec![self; field]
}
fn pat_lang_item_variant(
&mut self,
span: Span,
lang_item: hir::LangItem,
fields: &'hir [hir::PatField<'hir>],
hir_id: Option<hir::HirId>,
) -> &'hir hir::Pat<'hir> {
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id);
self.pat(span, hir::PatKind::Struct(qpath, fields, false))
}
2015-09-28 15:00:15 +13:00
2019-11-29 19:01:31 +01:00
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, hir::HirId) {
2022-08-30 17:34:35 -05:00
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::NONE)
}
2015-09-28 15:00:15 +13:00
2021-07-14 16:17:04 -05:00
fn pat_ident_mut(&mut self, span: Span, ident: Ident) -> (hir::Pat<'hir>, hir::HirId) {
2022-08-30 17:34:35 -05:00
self.pat_ident_binding_mode_mut(span, ident, hir::BindingAnnotation::NONE)
2021-07-14 16:17:04 -05:00
}
2018-03-21 04:24:27 -04:00
fn pat_ident_binding_mode(
&mut self,
span: Span,
2018-06-10 17:40:45 +03:00
ident: Ident,
2018-03-21 04:24:27 -04:00
bm: hir::BindingAnnotation,
2019-11-29 19:01:31 +01:00
) -> (&'hir hir::Pat<'hir>, hir::HirId) {
2021-07-14 16:17:04 -05:00
let (pat, hir_id) = self.pat_ident_binding_mode_mut(span, ident, bm);
(self.arena.alloc(pat), hir_id)
}
fn pat_ident_binding_mode_mut(
&mut self,
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
) -> (hir::Pat<'hir>, hir::HirId) {
2019-04-26 14:23:30 +02:00
let hir_id = self.next_id();
2015-09-28 17:24:42 +13:00
(
2021-07-14 16:17:04 -05:00
hir::Pat {
hir_id,
kind: hir::PatKind::Binding(bm, hir_id, self.lower_ident(ident), None),
span: self.lower_span(span),
default_binding_modes: true,
2021-07-14 16:17:04 -05:00
},
2019-12-24 17:38:22 -05:00
hir_id,
)
}
2015-09-28 15:00:15 +13:00
2019-11-29 19:01:31 +01:00
fn pat(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir> {
self.arena.alloc(hir::Pat {
hir_id: self.next_id(),
kind,
span: self.lower_span(span),
default_binding_modes: true,
})
}
2021-07-14 16:17:04 -05:00
fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> {
hir::Pat {
hir_id: self.next_id(),
kind,
span: self.lower_span(span),
default_binding_modes: false,
}
}
2015-09-28 15:00:15 +13:00
2019-11-30 17:46:46 +01:00
fn ty_path(
&mut self,
mut hir_id: hir::HirId,
span: Span,
qpath: hir::QPath<'hir>,
) -> hir::Ty<'hir> {
2019-09-26 17:25:31 +01:00
let kind = match qpath {
hir::QPath::Resolved(None, path) => {
2018-07-11 22:41:03 +08:00
// Turn trait object paths into `TyKind::TraitObject` instead.
match path.res {
Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
let principal = hir::PolyTraitRef {
2019-12-01 11:22:58 +01:00
bound_generic_params: &[],
2019-12-24 17:38:22 -05:00
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
span: self.lower_span(span),
};
// The original ID is taken by the `PolyTraitRef`,
// so the `Ty` itself needs a different one.
2019-04-26 14:23:30 +02:00
hir_id = self.next_id();
2019-12-01 11:22:58 +01:00
hir::TyKind::TraitObject(
arena_vec![self; principal],
self.elided_dyn_bound(span),
TraitObjectSyntax::None,
2019-12-01 11:22:58 +01:00
)
}
_ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),
}
}
2018-07-11 22:41:03 +08:00
_ => hir::TyKind::Path(qpath),
};
2019-09-26 17:25:31 +01:00
hir::Ty { hir_id, kind, span: self.lower_span(span) }
}
/// Invoked to create the lifetime argument(s) for an elided trait object
/// bound, like the bound in `Box<dyn Debug>`. This method is not invoked
/// when the bound is written, even if it is written with `'_` like in
/// `Box<dyn Debug + '_>`. In those cases, `lower_lifetime` is invoked.
fn elided_dyn_bound(&mut self, span: Span) -> &'hir hir::Lifetime {
let r = hir::Lifetime {
hir_id: self.next_id(),
span: self.lower_span(span),
name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
};
debug!("elided_dyn_bound: r={:?}", r);
self.arena.alloc(r)
}
}
2017-02-21 12:23:47 -05:00
2019-12-01 17:10:12 +01:00
/// Helper struct for delayed construction of GenericArgs.
struct GenericArgsCtor<'hir> {
2019-12-30 23:25:47 +01:00
args: SmallVec<[hir::GenericArg<'hir>; 4]>,
2019-12-01 17:10:12 +01:00
bindings: &'hir [hir::TypeBinding<'hir>],
parenthesized: bool,
span: Span,
2019-12-01 17:10:12 +01:00
}
impl<'hir> GenericArgsCtor<'hir> {
2019-12-01 17:10:12 +01:00
fn is_empty(&self) -> bool {
self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
}
fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> {
let ga = hir::GenericArgs {
args: this.arena.alloc_from_iter(self.args),
2019-12-01 17:10:12 +01:00
bindings: self.bindings,
parenthesized: self.parenthesized,
span_ext: this.lower_span(self.span),
};
this.arena.alloc(ga)
2019-12-01 17:10:12 +01:00
}
}