1
Fork 0

Record asyncness span in HIR

This commit is contained in:
Michael Goulet 2023-09-14 22:38:07 +00:00
parent 0fd7ce99b0
commit 087a571e70
22 changed files with 78 additions and 54 deletions

View file

@ -1308,7 +1308,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync { fn lower_asyncness(&mut self, a: Async) -> hir::IsAsync {
match a { match a {
Async::Yes { .. } => hir::IsAsync::Async, Async::Yes { span, .. } => hir::IsAsync::Async(span),
Async::No => hir::IsAsync::NotAsync, Async::No => hir::IsAsync::NotAsync,
} }
} }

View file

@ -302,7 +302,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
if free_region.bound_region.is_named() { if free_region.bound_region.is_named() {
// A named region that is actually named. // A named region that is actually named.
Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) }) Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) })
} else if let hir::IsAsync::Async = tcx.asyncness(self.mir_hir_id().owner) { } else if tcx.asyncness(self.mir_hir_id().owner).is_async() {
// If we spuriously thought that the region is named, we should let the // If we spuriously thought that the region is named, we should let the
// system generate a true name for error messages. Currently this can // system generate a true name for error messages. Currently this can
// happen if we have an elided name in an async fn for example: the // happen if we have an elided name in an async fn for example: the

View file

@ -2853,13 +2853,13 @@ impl ImplicitSelfKind {
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)] #[derive(HashStable_Generic)]
pub enum IsAsync { pub enum IsAsync {
Async, Async(Span),
NotAsync, NotAsync,
} }
impl IsAsync { impl IsAsync {
pub fn is_async(self) -> bool { pub fn is_async(self) -> bool {
self == IsAsync::Async matches!(self, IsAsync::Async(_))
} }
} }
@ -3296,7 +3296,7 @@ pub struct FnHeader {
impl FnHeader { impl FnHeader {
pub fn is_async(&self) -> bool { pub fn is_async(&self) -> bool {
matches!(&self.asyncness, IsAsync::Async) matches!(&self.asyncness, IsAsync::Async(_))
} }
pub fn is_const(&self) -> bool { pub fn is_const(&self) -> bool {
@ -4091,10 +4091,10 @@ mod size_asserts {
static_assert_size!(GenericBound<'_>, 48); static_assert_size!(GenericBound<'_>, 48);
static_assert_size!(Generics<'_>, 56); static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 80); static_assert_size!(Impl<'_>, 80);
static_assert_size!(ImplItem<'_>, 80); static_assert_size!(ImplItem<'_>, 88);
static_assert_size!(ImplItemKind<'_>, 32); static_assert_size!(ImplItemKind<'_>, 40);
static_assert_size!(Item<'_>, 80); static_assert_size!(Item<'_>, 88);
static_assert_size!(ItemKind<'_>, 48); static_assert_size!(ItemKind<'_>, 56);
static_assert_size!(Local<'_>, 64); static_assert_size!(Local<'_>, 64);
static_assert_size!(Param<'_>, 32); static_assert_size!(Param<'_>, 32);
static_assert_size!(Pat<'_>, 72); static_assert_size!(Pat<'_>, 72);
@ -4105,8 +4105,8 @@ mod size_asserts {
static_assert_size!(Res, 12); static_assert_size!(Res, 12);
static_assert_size!(Stmt<'_>, 32); static_assert_size!(Stmt<'_>, 32);
static_assert_size!(StmtKind<'_>, 16); static_assert_size!(StmtKind<'_>, 16);
static_assert_size!(TraitItem<'_>, 80); static_assert_size!(TraitItem<'_>, 88);
static_assert_size!(TraitItemKind<'_>, 40); static_assert_size!(TraitItemKind<'_>, 48);
static_assert_size!(Ty<'_>, 48); static_assert_size!(Ty<'_>, 48);
static_assert_size!(TyKind<'_>, 32); static_assert_size!(TyKind<'_>, 32);
// tidy-alphabetical-end // tidy-alphabetical-end

View file

@ -595,7 +595,7 @@ fn compare_asyncness<'tcx>(
trait_m: ty::AssocItem, trait_m: ty::AssocItem,
delay: bool, delay: bool,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async { if tcx.asyncness(trait_m.def_id).is_async() {
match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() { match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
ty::Alias(ty::Opaque, ..) => { ty::Alias(ty::Opaque, ..) => {
// allow both `async fn foo()` and `fn foo() -> impl Future` // allow both `async fn foo()` and `fn foo() -> impl Future`

View file

@ -112,7 +112,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
} }
let main_asyncness = tcx.asyncness(main_def_id); let main_asyncness = tcx.asyncness(main_def_id);
if let hir::IsAsync::Async = main_asyncness { if main_asyncness.is_async() {
let asyncness_span = main_fn_asyncness_span(tcx, main_def_id); let asyncness_span = main_fn_asyncness_span(tcx, main_def_id);
tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span }); tcx.sess.emit_err(errors::MainFunctionAsync { span: main_span, asyncness: asyncness_span });
error = true; error = true;
@ -212,7 +212,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
}); });
error = true; error = true;
} }
if let hir::IsAsync::Async = sig.header.asyncness { if sig.header.asyncness.is_async() {
let span = tcx.def_span(it.owner_id); let span = tcx.def_span(it.owner_id);
tcx.sess.emit_err(errors::StartAsync { span: span }); tcx.sess.emit_err(errors::StartAsync { span: span });
error = true; error = true;

View file

@ -1213,7 +1213,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
&& let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id)) && let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id) && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
&& param.is_elided_lifetime() && param.is_elided_lifetime()
&& let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
&& !self.tcx.features().anonymous_lifetime_in_impl_trait && !self.tcx.features().anonymous_lifetime_in_impl_trait
{ {
let mut diag = rustc_session::parse::feature_err( let mut diag = rustc_session::parse::feature_err(

View file

@ -2304,7 +2304,7 @@ impl<'a> State<'a> {
match header.asyncness { match header.asyncness {
hir::IsAsync::NotAsync => {} hir::IsAsync::NotAsync => {}
hir::IsAsync::Async => self.word_nbsp("async"), hir::IsAsync::Async(_) => self.word_nbsp("async"),
} }
self.print_unsafety(header.unsafety); self.print_unsafety(header.unsafety);

View file

@ -987,10 +987,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let bound_vars = self.tcx.late_bound_vars(fn_id); let bound_vars = self.tcx.late_bound_vars(fn_id);
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars)); let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = match self.tcx.asyncness(fn_id.owner) { let ty = match self.tcx.asyncness(fn_id.owner) {
hir::IsAsync::Async => self.get_impl_future_output_ty(ty).unwrap_or_else(|| { ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(fn_decl.output.span(), "failed to get output type of async function") span_bug!(fn_decl.output.span(), "failed to get output type of async function")
}), }),
hir::IsAsync::NotAsync => ty, ty::Asyncness::No => ty,
}; };
let ty = self.normalize(expr.span, ty); let ty = self.normalize(expr.span, ty);
if self.can_coerce(found, ty) { if self.can_coerce(found, ty) {

View file

@ -41,7 +41,6 @@ use crate::{
}, },
EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext, EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
}; };
use hir::IsAsync;
use rustc_ast::attr; use rustc_ast::attr;
use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::visit::{FnCtxt, FnKind};
@ -1294,7 +1293,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
span: Span, span: Span,
def_id: LocalDefId, def_id: LocalDefId,
) { ) {
if fn_kind.asyncness() == IsAsync::Async if fn_kind.asyncness().is_async()
&& !cx.tcx.features().async_fn_track_caller && !cx.tcx.features().async_fn_track_caller
// Now, check if the function has the `#[track_caller]` attribute // Now, check if the function has the `#[track_caller]` attribute
&& let Some(attr) = cx.tcx.get_attr(def_id, sym::track_caller) && let Some(attr) = cx.tcx.get_attr(def_id, sym::track_caller)

View file

@ -439,7 +439,7 @@ define_tables! {
coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>, coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>, mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
rendered_const: Table<DefIndex, LazyValue<String>>, rendered_const: Table<DefIndex, LazyValue<String>>,
asyncness: Table<DefIndex, hir::IsAsync>, asyncness: Table<DefIndex, ty::Asyncness>,
fn_arg_names: Table<DefIndex, LazyArray<Ident>>, fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
generator_kind: Table<DefIndex, LazyValue<hir::GeneratorKind>>, generator_kind: Table<DefIndex, LazyValue<hir::GeneratorKind>>,
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>, trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,

View file

@ -205,9 +205,9 @@ fixed_size_enum! {
} }
fixed_size_enum! { fixed_size_enum! {
hir::IsAsync { ty::Asyncness {
( NotAsync ) ( Yes )
( Async ) ( No )
} }
} }

View file

@ -265,6 +265,7 @@ trivial! {
rustc_middle::ty::adjustment::CoerceUnsizedInfo, rustc_middle::ty::adjustment::CoerceUnsizedInfo,
rustc_middle::ty::AssocItem, rustc_middle::ty::AssocItem,
rustc_middle::ty::AssocItemContainer, rustc_middle::ty::AssocItemContainer,
rustc_middle::ty::Asyncness,
rustc_middle::ty::BoundVariableKind, rustc_middle::ty::BoundVariableKind,
rustc_middle::ty::DeducedParamAttrs, rustc_middle::ty::DeducedParamAttrs,
rustc_middle::ty::Destructor, rustc_middle::ty::Destructor,

View file

@ -731,7 +731,7 @@ rustc_queries! {
separate_provide_extern separate_provide_extern
} }
query asyncness(key: DefId) -> hir::IsAsync { query asyncness(key: DefId) -> ty::Asyncness {
desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) }
separate_provide_extern separate_provide_extern
} }

View file

@ -280,6 +280,19 @@ impl fmt::Display for ImplPolarity {
} }
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum Asyncness {
Yes,
No,
}
impl Asyncness {
pub fn is_async(self) -> bool {
matches!(self, Asyncness::Yes)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)] #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)]
pub enum Visibility<Id = LocalDefId> { pub enum Visibility<Id = LocalDefId> {
/// Visible everywhere (including in other crates). /// Visible everywhere (including in other crates).

View file

@ -62,6 +62,7 @@ trivially_parameterized_over_tcx! {
crate::middle::resolve_bound_vars::ObjectLifetimeDefault, crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs, crate::mir::ConstQualifs,
ty::AssocItemContainer, ty::AssocItemContainer,
ty::Asyncness,
ty::DeducedParamAttrs, ty::DeducedParamAttrs,
ty::Generics, ty::Generics,
ty::ImplPolarity, ty::ImplPolarity,

View file

@ -104,7 +104,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
self.describe_generator(*body_id).or_else(|| { self.describe_generator(*body_id).or_else(|| {
Some(match sig.header { Some(match sig.header {
hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async function", hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => {
"an async function"
}
_ => "a function", _ => "a function",
}) })
}) })
@ -118,7 +120,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
.. ..
}) => self.describe_generator(*body_id).or_else(|| { }) => self.describe_generator(*body_id).or_else(|| {
Some(match sig.header { Some(match sig.header {
hir::FnHeader { asyncness: hir::IsAsync::Async, .. } => "an async method", hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => "an async method",
_ => "a method", _ => "a method",
}) })
}), }),

View file

@ -296,9 +296,12 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<'
} }
/// Check if a function is async. /// Check if a function is async.
fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::IsAsync { fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Asyncness {
let node = tcx.hir().get_by_def_id(def_id); let node = tcx.hir().get_by_def_id(def_id);
node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness) node.fn_sig().map_or(ty::Asyncness::No, |sig| match sig.header.asyncness {
hir::IsAsync::Async(_) => ty::Asyncness::Yes,
hir::IsAsync::NotAsync => ty::Asyncness::No,
})
} }
fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32> { fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32> {

View file

@ -31,7 +31,7 @@ use rustc_resolve::rustdoc::{
use rustc_session::Session; use rustc_session::Session;
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, FileName, Loc}; use rustc_span::{self, FileName, Loc, DUMMY_SP};
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
@ -622,7 +622,7 @@ impl Item {
fn build_fn_header( fn build_fn_header(
def_id: DefId, def_id: DefId,
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
asyncness: hir::IsAsync, asyncness: ty::Asyncness,
) -> hir::FnHeader { ) -> hir::FnHeader {
let sig = tcx.fn_sig(def_id).skip_binder(); let sig = tcx.fn_sig(def_id).skip_binder();
let constness = let constness =
@ -631,6 +631,10 @@ impl Item {
} else { } else {
hir::Constness::NotConst hir::Constness::NotConst
}; };
let asyncness = match asyncness {
ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
ty::Asyncness::No => hir::IsAsync::NotAsync,
};
hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness } hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness }
} }
let header = match *self.kind { let header = match *self.kind {

View file

@ -1599,7 +1599,7 @@ impl PrintWithSpace for hir::Unsafety {
impl PrintWithSpace for hir::IsAsync { impl PrintWithSpace for hir::IsAsync {
fn print_with_space(&self) -> &str { fn print_with_space(&self) -> &str {
match self { match self {
hir::IsAsync::Async => "async ", hir::IsAsync::Async(_) => "async ",
hir::IsAsync::NotAsync => "", hir::IsAsync::NotAsync => "",
} }
} }

View file

@ -10,6 +10,7 @@ use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! { declare_clippy_lint! {
@ -84,7 +85,7 @@ fn find_innermost_closure<'tcx>(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
mut expr: &'tcx hir::Expr<'tcx>, mut expr: &'tcx hir::Expr<'tcx>,
mut steps: usize, mut steps: usize,
) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, hir::IsAsync)> { ) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, ty::Asyncness)> {
let mut data = None; let mut data = None;
while let hir::ExprKind::Closure(closure) = expr.kind while let hir::ExprKind::Closure(closure) = expr.kind
@ -98,9 +99,9 @@ fn find_innermost_closure<'tcx>(
{ {
expr = body.value; expr = body.value;
data = Some((body.value, closure.fn_decl, if is_async_closure(body) { data = Some((body.value, closure.fn_decl, if is_async_closure(body) {
hir::IsAsync::Async ty::Asyncness::Yes
} else { } else {
hir::IsAsync::NotAsync ty::Asyncness::No
})); }));
steps -= 1; steps -= 1;
} }

View file

@ -90,7 +90,7 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::{ use rustc_hir::{
self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr,
ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, IsAsync, Item, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item,
ItemKind, LangItem, Local, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, ItemKind, LangItem, Local, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy,
QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
}; };
@ -1958,8 +1958,8 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
/// Checks if the given function kind is an async function. /// Checks if the given function kind is an async function.
pub fn is_async_fn(kind: FnKind<'_>) -> bool { pub fn is_async_fn(kind: FnKind<'_>) -> bool {
match kind { match kind {
FnKind::ItemFn(_, _, header) => header.asyncness == IsAsync::Async, FnKind::ItemFn(_, _, header) => header.asyncness .is_async(),
FnKind::Method(_, sig) => sig.header.asyncness == IsAsync::Async, FnKind::Method(_, sig) => sig.header.asyncness.is_async(),
FnKind::Closure => false, FnKind::Closure => false,
} }
} }

View file

@ -146,33 +146,33 @@ hir-stats - Trait 192 ( 2.1%) 4
hir-stats WherePredicate 192 ( 2.1%) 3 64 hir-stats WherePredicate 192 ( 2.1%) 3 64
hir-stats - BoundPredicate 192 ( 2.1%) 3 hir-stats - BoundPredicate 192 ( 2.1%) 3
hir-stats Block 288 ( 3.2%) 6 48 hir-stats Block 288 ( 3.2%) 6 48
hir-stats Pat 360 ( 4.0%) 5 72 hir-stats Pat 360 ( 3.9%) 5 72
hir-stats - Wild 72 ( 0.8%) 1 hir-stats - Wild 72 ( 0.8%) 1
hir-stats - Struct 72 ( 0.8%) 1 hir-stats - Struct 72 ( 0.8%) 1
hir-stats - Binding 216 ( 2.4%) 3 hir-stats - Binding 216 ( 2.4%) 3
hir-stats GenericParam 400 ( 4.4%) 5 80 hir-stats GenericParam 400 ( 4.4%) 5 80
hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Generics 560 ( 6.1%) 10 56
hir-stats Ty 720 ( 8.0%) 15 48 hir-stats Ty 720 ( 7.9%) 15 48
hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ptr 48 ( 0.5%) 1
hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1
hir-stats - Path 624 ( 6.9%) 13 hir-stats - Path 624 ( 6.8%) 13
hir-stats Expr 768 ( 8.5%) 12 64 hir-stats Expr 768 ( 8.4%) 12 64
hir-stats - Path 64 ( 0.7%) 1 hir-stats - Path 64 ( 0.7%) 1
hir-stats - Struct 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1
hir-stats - Match 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1
hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - InlineAsm 64 ( 0.7%) 1
hir-stats - Lit 128 ( 1.4%) 2 hir-stats - Lit 128 ( 1.4%) 2
hir-stats - Block 384 ( 4.2%) 6 hir-stats - Block 384 ( 4.2%) 6
hir-stats Item 880 ( 9.7%) 11 80 hir-stats Item 968 (10.6%) 11 88
hir-stats - Trait 80 ( 0.9%) 1 hir-stats - Trait 88 ( 1.0%) 1
hir-stats - Enum 80 ( 0.9%) 1 hir-stats - Enum 88 ( 1.0%) 1
hir-stats - ExternCrate 80 ( 0.9%) 1 hir-stats - ExternCrate 88 ( 1.0%) 1
hir-stats - ForeignMod 80 ( 0.9%) 1 hir-stats - ForeignMod 88 ( 1.0%) 1
hir-stats - Impl 80 ( 0.9%) 1 hir-stats - Impl 88 ( 1.0%) 1
hir-stats - Fn 160 ( 1.8%) 2 hir-stats - Fn 176 ( 1.9%) 2
hir-stats - Use 320 ( 3.5%) 4 hir-stats - Use 352 ( 3.9%) 4
hir-stats Path 1_240 (13.7%) 31 40 hir-stats Path 1_240 (13.6%) 31 40
hir-stats PathSegment 1_920 (21.2%) 40 48 hir-stats PathSegment 1_920 (21.0%) 40 48
hir-stats ---------------------------------------------------------------- hir-stats ----------------------------------------------------------------
hir-stats Total 9_048 hir-stats Total 9_136
hir-stats hir-stats