Auto merge of #88703 - cjgillot:lazymod, r=petrochenkov
Gather module items after lowering. This avoids having a non-local analysis inside lowering. By implementing `hir_module_items` using a visitor, we make sure that iterations and visitors are consistent.
This commit is contained in:
commit
7b5f95270f
@ -51,12 +51,6 @@ fn visit_item(&mut self, item: &'a Item) {
|
||||
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
|
||||
let this = &mut ItemLowerer { lctx: this };
|
||||
match item.kind {
|
||||
ItemKind::Mod(..) => {
|
||||
let def_id = this.lctx.lower_node_id(item.id).expect_owner();
|
||||
let old_current_module = mem::replace(&mut this.lctx.current_module, def_id);
|
||||
visit::walk_item(this, item);
|
||||
this.lctx.current_module = old_current_module;
|
||||
}
|
||||
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
|
||||
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
|
||||
}
|
||||
|
@ -102,8 +102,6 @@ struct LoweringContext<'a, 'hir: 'a> {
|
||||
owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
|
||||
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
|
||||
|
||||
modules: BTreeMap<LocalDefId, hir::ModuleItems>,
|
||||
|
||||
generator_kind: Option<hir::GeneratorKind>,
|
||||
|
||||
attrs: BTreeMap<hir::HirId, &'hir [Attribute]>,
|
||||
@ -152,8 +150,6 @@ struct LoweringContext<'a, 'hir: 'a> {
|
||||
/// vector.
|
||||
in_scope_lifetimes: Vec<ParamName>,
|
||||
|
||||
current_module: LocalDefId,
|
||||
|
||||
current_hir_id_owner: (LocalDefId, u32),
|
||||
item_local_id_counters: NodeMap<u32>,
|
||||
node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
|
||||
@ -327,7 +323,6 @@ pub fn lower_crate<'a, 'hir>(
|
||||
arena,
|
||||
owners: IndexVec::default(),
|
||||
bodies: BTreeMap::new(),
|
||||
modules: BTreeMap::new(),
|
||||
attrs: BTreeMap::default(),
|
||||
catch_scope: None,
|
||||
loop_scope: None,
|
||||
@ -335,7 +330,6 @@ pub fn lower_crate<'a, 'hir>(
|
||||
is_in_trait_impl: false,
|
||||
is_in_dyn_type: false,
|
||||
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
|
||||
current_module: CRATE_DEF_ID,
|
||||
current_hir_id_owner: (CRATE_DEF_ID, 0),
|
||||
item_local_id_counters: Default::default(),
|
||||
node_id_to_hir_id: IndexVec::new(),
|
||||
@ -457,13 +451,8 @@ fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
let krate = hir::Crate {
|
||||
owners: self.owners,
|
||||
bodies: self.bodies,
|
||||
modules: self.modules,
|
||||
trait_map,
|
||||
attrs: self.attrs,
|
||||
};
|
||||
let krate =
|
||||
hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs };
|
||||
self.arena.alloc(krate)
|
||||
}
|
||||
|
||||
@ -472,7 +461,6 @@ fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
|
||||
let item = self.arena.alloc(item);
|
||||
self.owners.ensure_contains_elem(id.def_id, || None);
|
||||
self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
|
||||
self.modules.entry(self.current_module).or_default().items.insert(id);
|
||||
id
|
||||
}
|
||||
|
||||
@ -481,7 +469,6 @@ fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignI
|
||||
let item = self.arena.alloc(item);
|
||||
self.owners.ensure_contains_elem(id.def_id, || None);
|
||||
self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
|
||||
self.modules.entry(self.current_module).or_default().foreign_items.insert(id);
|
||||
id
|
||||
}
|
||||
|
||||
@ -490,7 +477,6 @@ fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId {
|
||||
let item = self.arena.alloc(item);
|
||||
self.owners.ensure_contains_elem(id.def_id, || None);
|
||||
self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
|
||||
self.modules.entry(self.current_module).or_default().impl_items.insert(id);
|
||||
id
|
||||
}
|
||||
|
||||
@ -499,7 +485,6 @@ fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId
|
||||
let item = self.arena.alloc(item);
|
||||
self.owners.ensure_contains_elem(id.def_id, || None);
|
||||
self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
|
||||
self.modules.entry(self.current_module).or_default().trait_items.insert(id);
|
||||
id
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use smallvec::SmallVec;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Copy, Clone, Encodable, HashStable_Generic)]
|
||||
@ -653,16 +653,6 @@ pub struct WhereEqPredicate<'hir> {
|
||||
pub rhs_ty: &'hir Ty<'hir>,
|
||||
}
|
||||
|
||||
#[derive(Default, Encodable, Debug, HashStable_Generic)]
|
||||
pub struct ModuleItems {
|
||||
// Use BTreeSets here so items are in the same order as in the
|
||||
// list of all items in Crate
|
||||
pub items: BTreeSet<ItemId>,
|
||||
pub trait_items: BTreeSet<TraitItemId>,
|
||||
pub impl_items: BTreeSet<ImplItemId>,
|
||||
pub foreign_items: BTreeSet<ForeignItemId>,
|
||||
}
|
||||
|
||||
/// The top-level data structure that stores the entire contents of
|
||||
/// the crate currently being compiled.
|
||||
///
|
||||
@ -674,10 +664,6 @@ pub struct Crate<'hir> {
|
||||
pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
|
||||
pub bodies: BTreeMap<BodyId, Body<'hir>>,
|
||||
|
||||
/// A list of modules written out in the order in which they
|
||||
/// appear in the crate. This includes the main crate module.
|
||||
pub modules: BTreeMap<LocalDefId, ModuleItems>,
|
||||
|
||||
/// Map indicating what traits are in scope for places where this
|
||||
/// is relevant; generated by resolve.
|
||||
pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>,
|
||||
|
@ -8,7 +8,7 @@
|
||||
use rustc_codegen_ssa::back::link::emit_metadata;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::parallel;
|
||||
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
|
||||
use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_errors::{ErrorReported, PResult};
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
@ -861,7 +861,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
||||
CStore::from_tcx(tcx).report_unused_deps(tcx);
|
||||
},
|
||||
{
|
||||
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
tcx.ensure().check_mod_loops(module);
|
||||
tcx.ensure().check_mod_attrs(module);
|
||||
tcx.ensure().check_mod_naked_functions(module);
|
||||
@ -893,7 +893,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
||||
},
|
||||
{
|
||||
sess.time("liveness_and_intrinsic_checking", || {
|
||||
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
// this must run before MIR dump, because
|
||||
// "not all control paths return a value" is reported here.
|
||||
//
|
||||
@ -963,7 +963,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
|
||||
},
|
||||
{
|
||||
sess.time("privacy_checking_modules", || {
|
||||
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
|
||||
tcx.hir().par_for_each_module(|module| {
|
||||
tcx.ensure().check_mod_privacy(module);
|
||||
});
|
||||
});
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
|
||||
use rustc_data_structures::sync::join;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit as hir_visit;
|
||||
@ -501,9 +501,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
|
||||
|| {
|
||||
tcx.sess.time("module_lints", || {
|
||||
// Run per-module lints
|
||||
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
|
||||
tcx.ensure().lint_mod(module);
|
||||
});
|
||||
tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use self::collector::NodeCollector;
|
||||
|
||||
use crate::hir::{AttributeMap, IndexedHir, Owner};
|
||||
use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner};
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
@ -19,6 +19,7 @@
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
pub mod blocks;
|
||||
mod collector;
|
||||
@ -536,23 +537,55 @@ pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
|
||||
{
|
||||
let module = self.tcx.hir_module_items(module);
|
||||
|
||||
for id in &module.items {
|
||||
for id in module.items.iter() {
|
||||
visitor.visit_item(self.item(*id));
|
||||
}
|
||||
|
||||
for id in &module.trait_items {
|
||||
for id in module.trait_items.iter() {
|
||||
visitor.visit_trait_item(self.trait_item(*id));
|
||||
}
|
||||
|
||||
for id in &module.impl_items {
|
||||
for id in module.impl_items.iter() {
|
||||
visitor.visit_impl_item(self.impl_item(*id));
|
||||
}
|
||||
|
||||
for id in &module.foreign_items {
|
||||
for id in module.foreign_items.iter() {
|
||||
visitor.visit_foreign_item(self.foreign_item(*id));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each_module(&self, f: impl Fn(LocalDefId)) {
|
||||
let mut queue = VecDeque::new();
|
||||
queue.push_back(CRATE_DEF_ID);
|
||||
|
||||
while let Some(id) = queue.pop_front() {
|
||||
f(id);
|
||||
let items = self.tcx.hir_module_items(id);
|
||||
queue.extend(items.submodules.iter().copied())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(parallel_compiler))]
|
||||
#[inline]
|
||||
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) {
|
||||
self.for_each_module(f)
|
||||
}
|
||||
|
||||
#[cfg(parallel_compiler)]
|
||||
pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) {
|
||||
use rustc_data_structures::sync::{par_iter, ParallelIterator};
|
||||
par_iter_submodules(self.tcx, CRATE_DEF_ID, &f);
|
||||
|
||||
fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F)
|
||||
where
|
||||
F: Fn(LocalDefId) + Sync,
|
||||
{
|
||||
(*f)(module);
|
||||
let items = tcx.hir_module_items(module);
|
||||
par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f));
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
|
||||
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
|
||||
pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
|
||||
@ -1113,3 +1146,69 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
|
||||
None => format!("unknown node{}", id_str),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems {
|
||||
let mut collector = ModuleCollector {
|
||||
tcx,
|
||||
submodules: Vec::default(),
|
||||
items: Vec::default(),
|
||||
trait_items: Vec::default(),
|
||||
impl_items: Vec::default(),
|
||||
foreign_items: Vec::default(),
|
||||
};
|
||||
|
||||
let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
|
||||
collector.visit_mod(hir_mod, span, hir_id);
|
||||
|
||||
let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } =
|
||||
collector;
|
||||
return ModuleItems {
|
||||
submodules: submodules.into_boxed_slice(),
|
||||
items: items.into_boxed_slice(),
|
||||
trait_items: trait_items.into_boxed_slice(),
|
||||
impl_items: impl_items.into_boxed_slice(),
|
||||
foreign_items: foreign_items.into_boxed_slice(),
|
||||
};
|
||||
|
||||
struct ModuleCollector<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
submodules: Vec<LocalDefId>,
|
||||
items: Vec<ItemId>,
|
||||
trait_items: Vec<TraitItemId>,
|
||||
impl_items: Vec<ImplItemId>,
|
||||
foreign_items: Vec<ForeignItemId>,
|
||||
}
|
||||
|
||||
impl<'hir> Visitor<'hir> for ModuleCollector<'hir> {
|
||||
type Map = Map<'hir>;
|
||||
|
||||
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
|
||||
intravisit::NestedVisitorMap::All(self.tcx.hir())
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &'hir Item<'hir>) {
|
||||
self.items.push(item.item_id());
|
||||
if let ItemKind::Mod(..) = item.kind {
|
||||
// If this declares another module, do not recurse inside it.
|
||||
self.submodules.push(item.def_id);
|
||||
} else {
|
||||
intravisit::walk_item(self, item)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
|
||||
self.trait_items.push(item.trait_item_id());
|
||||
intravisit::walk_trait_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
|
||||
self.impl_items.push(item.impl_item_id());
|
||||
intravisit::walk_impl_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
|
||||
self.foreign_items.push(item.foreign_item_id());
|
||||
intravisit::walk_foreign_item(self, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,17 @@ fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[At
|
||||
}
|
||||
}
|
||||
|
||||
/// Gather the LocalDefId for each item-like within a module, including items contained within
|
||||
/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
|
||||
#[derive(Debug, HashStable)]
|
||||
pub struct ModuleItems {
|
||||
submodules: Box<[LocalDefId]>,
|
||||
items: Box<[ItemId]>,
|
||||
trait_items: Box<[TraitItemId]>,
|
||||
impl_items: Box<[ImplItemId]>,
|
||||
foreign_items: Box<[ForeignItemId]>,
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
#[inline(always)]
|
||||
pub fn hir(self) -> map::Map<'tcx> {
|
||||
@ -140,7 +151,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
|
||||
providers.index_hir = map::index_hir;
|
||||
providers.crate_hash = map::crate_hash;
|
||||
providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
|
||||
providers.hir_module_items = map::hir_module_items;
|
||||
providers.hir_owner = |tcx, id| {
|
||||
let owner = tcx.index_hir(()).map[id].as_ref()?;
|
||||
let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#![feature(discriminant_kind)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(map_first_last)]
|
||||
#![feature(never_type)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(new_uninit)]
|
||||
|
@ -52,8 +52,8 @@
|
||||
///
|
||||
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
|
||||
/// Avoid calling this query directly.
|
||||
query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems {
|
||||
eval_always
|
||||
query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
|
||||
storage(ArenaCacheSelector<'tcx>)
|
||||
desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
|
||||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
|
||||
use rustc_hir::intravisit;
|
||||
@ -18,9 +18,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||
let errors = Lock::new(Vec::new());
|
||||
let hir_map = tcx.hir();
|
||||
|
||||
par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| {
|
||||
hir_map.par_for_each_module(|module_id| {
|
||||
hir_map
|
||||
.visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors });
|
||||
.visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors })
|
||||
});
|
||||
|
||||
let errors = errors.into_inner();
|
||||
|
@ -58,9 +58,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
|
||||
// We will tag this as part of the WF check -- logically, it is,
|
||||
// but it's one that we must perform earlier than the rest of
|
||||
// WfCheck.
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
tcx.ensure().check_mod_impl_wf(module);
|
||||
}
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
|
||||
}
|
||||
|
||||
fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
|
||||
|
@ -473,9 +473,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
|
||||
// FIXME(matthewjasper) We shouldn't need to use `track_errors`.
|
||||
tcx.sess.track_errors(|| {
|
||||
tcx.sess.time("type_collecting", || {
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
tcx.ensure().collect_mod_item_types(module);
|
||||
}
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
|
||||
});
|
||||
})?;
|
||||
|
||||
@ -505,9 +503,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
|
||||
|
||||
// NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
|
||||
tcx.sess.time("item_types_checking", || {
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
tcx.ensure().check_mod_item_types(module);
|
||||
}
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
|
||||
});
|
||||
|
||||
tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
|
||||
|
@ -329,18 +329,14 @@ impl<'tcx> DocContext<'tcx> {
|
||||
|
||||
// NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
|
||||
tcx.sess.time("item_types_checking", || {
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
tcx.ensure().check_mod_item_types(module);
|
||||
}
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
|
||||
});
|
||||
tcx.sess.abort_if_errors();
|
||||
tcx.sess.time("missing_docs", || {
|
||||
rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
|
||||
});
|
||||
tcx.sess.time("check_mod_attrs", || {
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
tcx.ensure().check_mod_attrs(module);
|
||||
}
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module))
|
||||
});
|
||||
rustc_passes::stability::check_unused_or_stable_features(tcx);
|
||||
|
||||
|
@ -8,6 +8,17 @@ LL | a: &'b str,
|
||||
|
|
||||
= help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
|
||||
|
|
||||
LL | #[derive(Eq, PartialEq)]
|
||||
| -- lifetime `'b` is missing in item created through this procedural macro
|
||||
LL | struct Test {
|
||||
LL | a: &'b str,
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13
|
||||
|
|
||||
@ -24,17 +35,6 @@ help: consider introducing lifetime `'b` here
|
||||
LL | fn foo<'b>(&'b self) {}
|
||||
| ++++
|
||||
|
||||
error[E0261]: use of undeclared lifetime name `'b`
|
||||
--> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
|
||||
|
|
||||
LL | #[derive(Eq, PartialEq)]
|
||||
| -- lifetime `'b` is missing in item created through this procedural macro
|
||||
LL | struct Test {
|
||||
LL | a: &'b str,
|
||||
| ^^ undeclared lifetime
|
||||
|
|
||||
= help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0261`.
|
||||
|
Loading…
Reference in New Issue
Block a user