Rollup merge of #122922 - kpreid:print-async, r=compiler-errors
-Zprint-type-sizes: print the types of awaitees and unnamed coroutine locals. This should assist comprehending the size of coroutines. In particular, whenever a future is suspended while awaiting another future, the latter is given the special name `__awaitee`, and now the type of the awaited future will be printed, allowing identifying caller/callee — er, I mean, poller/pollee — relationships. It would be possible to include the type name in more cases, but I thought that that might be overly verbose (`print-type-sizes` is already a lot of text) and ordinary named fields or variables are easier for readers to discover the types of. This change will also synergize with my other PR #122923 which changes type printing to print the path of the `async fn` instead of the span. Implementation note: I'm not sure if `Symbol::intern` is appropriate for this application, but it was the obvious way to not have to remove the `Copy` implementation from `FieldInfo`, or add a `'tcx` lifetime, while avoiding keeping a lot of possibly redundant strings in memory. I don't know what the proper tradeoff to make here is (though presumably it is not too important for a `-Z` debugging option).
This commit is contained in:
commit
9418f69446
@ -44,6 +44,10 @@ pub struct FieldInfo {
|
|||||||
pub offset: u64,
|
pub offset: u64,
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
pub align: u64,
|
pub align: u64,
|
||||||
|
/// Name of the type of this field.
|
||||||
|
/// Present only if the creator thought that this would be important for identifying the field,
|
||||||
|
/// typically because the field name is uninformative.
|
||||||
|
pub type_name: Option<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
@ -192,7 +196,7 @@ impl CodeStats {
|
|||||||
fields.sort_by_key(|f| (f.offset, f.size));
|
fields.sort_by_key(|f| (f.offset, f.size));
|
||||||
|
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let FieldInfo { kind, ref name, offset, size, align } = field;
|
let FieldInfo { kind, ref name, offset, size, align, type_name } = field;
|
||||||
|
|
||||||
if offset > min_offset {
|
if offset > min_offset {
|
||||||
let pad = offset - min_offset;
|
let pad = offset - min_offset;
|
||||||
@ -201,21 +205,27 @@ impl CodeStats {
|
|||||||
|
|
||||||
if offset < min_offset {
|
if offset < min_offset {
|
||||||
// If this happens it's probably a union.
|
// If this happens it's probably a union.
|
||||||
println!(
|
print!(
|
||||||
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
|
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
|
||||||
offset: {offset} bytes, \
|
offset: {offset} bytes, \
|
||||||
alignment: {align} bytes"
|
alignment: {align} bytes"
|
||||||
);
|
);
|
||||||
} else if info.packed || offset == min_offset {
|
} else if info.packed || offset == min_offset {
|
||||||
println!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
|
print!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
|
||||||
} else {
|
} else {
|
||||||
// Include field alignment in output only if it caused padding injection
|
// Include field alignment in output only if it caused padding injection
|
||||||
println!(
|
print!(
|
||||||
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
|
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
|
||||||
alignment: {align} bytes"
|
alignment: {align} bytes"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(type_name) = type_name {
|
||||||
|
println!(", type: {type_name}");
|
||||||
|
} else {
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
|
||||||
min_offset = offset + size;
|
min_offset = offset + size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ use rustc_middle::ty::layout::{
|
|||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
|
use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
|
||||||
|
use rustc_span::sym;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::abi::*;
|
use rustc_target::abi::*;
|
||||||
|
|
||||||
@ -1007,6 +1008,7 @@ fn variant_info_for_adt<'tcx>(
|
|||||||
offset: offset.bytes(),
|
offset: offset.bytes(),
|
||||||
size: field_layout.size.bytes(),
|
size: field_layout.size.bytes(),
|
||||||
align: field_layout.align.abi.bytes(),
|
align: field_layout.align.abi.bytes(),
|
||||||
|
type_name: None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -1090,6 +1092,7 @@ fn variant_info_for_coroutine<'tcx>(
|
|||||||
offset: offset.bytes(),
|
offset: offset.bytes(),
|
||||||
size: field_layout.size.bytes(),
|
size: field_layout.size.bytes(),
|
||||||
align: field_layout.align.abi.bytes(),
|
align: field_layout.align.abi.bytes(),
|
||||||
|
type_name: None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -1104,19 +1107,24 @@ fn variant_info_for_coroutine<'tcx>(
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(field_idx, local)| {
|
.map(|(field_idx, local)| {
|
||||||
|
let field_name = coroutine.field_names[*local];
|
||||||
let field_layout = variant_layout.field(cx, field_idx);
|
let field_layout = variant_layout.field(cx, field_idx);
|
||||||
let offset = variant_layout.fields.offset(field_idx);
|
let offset = variant_layout.fields.offset(field_idx);
|
||||||
// The struct is as large as the last field's end
|
// The struct is as large as the last field's end
|
||||||
variant_size = variant_size.max(offset + field_layout.size);
|
variant_size = variant_size.max(offset + field_layout.size);
|
||||||
FieldInfo {
|
FieldInfo {
|
||||||
kind: FieldKind::CoroutineLocal,
|
kind: FieldKind::CoroutineLocal,
|
||||||
name: coroutine.field_names[*local].unwrap_or(Symbol::intern(&format!(
|
name: field_name.unwrap_or(Symbol::intern(&format!(
|
||||||
".coroutine_field{}",
|
".coroutine_field{}",
|
||||||
local.as_usize()
|
local.as_usize()
|
||||||
))),
|
))),
|
||||||
offset: offset.bytes(),
|
offset: offset.bytes(),
|
||||||
size: field_layout.size.bytes(),
|
size: field_layout.size.bytes(),
|
||||||
align: field_layout.align.abi.bytes(),
|
align: field_layout.align.abi.bytes(),
|
||||||
|
// Include the type name if there is no field name, or if the name is the
|
||||||
|
// __awaitee placeholder symbol which means a child future being `.await`ed.
|
||||||
|
type_name: (field_name.is_none() || field_name == Some(sym::__awaitee))
|
||||||
|
.then(|| Symbol::intern(&field_layout.ty.to_string())),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.chain(upvar_fields.iter().copied())
|
.chain(upvar_fields.iter().copied())
|
||||||
|
@ -2,7 +2,7 @@ print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2}`:
|
|||||||
print-type-size discriminant: 1 bytes
|
print-type-size discriminant: 1 bytes
|
||||||
print-type-size variant `Unresumed`: 0 bytes
|
print-type-size variant `Unresumed`: 0 bytes
|
||||||
print-type-size variant `Suspend0`: 3077 bytes
|
print-type-size variant `Suspend0`: 3077 bytes
|
||||||
print-type-size local `.__awaitee`: 3077 bytes
|
print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}
|
||||||
print-type-size variant `Returned`: 0 bytes
|
print-type-size variant `Returned`: 0 bytes
|
||||||
print-type-size variant `Panicked`: 0 bytes
|
print-type-size variant `Panicked`: 0 bytes
|
||||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
|
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
|
||||||
@ -19,19 +19,19 @@ print-type-size variant `Suspend0`: 2052 bytes
|
|||||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||||
print-type-size padding: 1 bytes
|
print-type-size padding: 1 bytes
|
||||||
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
||||||
print-type-size local `..coroutine_field4`: 1 bytes
|
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
|
||||||
print-type-size local `.__awaitee`: 1 bytes
|
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
|
||||||
print-type-size variant `Suspend1`: 3076 bytes
|
print-type-size variant `Suspend1`: 3076 bytes
|
||||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||||
print-type-size padding: 1026 bytes
|
print-type-size padding: 1026 bytes
|
||||||
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes
|
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
|
||||||
print-type-size local `.__awaitee`: 1025 bytes
|
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}
|
||||||
print-type-size variant `Suspend2`: 2052 bytes
|
print-type-size variant `Suspend2`: 2052 bytes
|
||||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||||
print-type-size padding: 1 bytes
|
print-type-size padding: 1 bytes
|
||||||
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
||||||
print-type-size local `..coroutine_field4`: 1 bytes
|
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
|
||||||
print-type-size local `.__awaitee`: 1 bytes
|
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
|
||||||
print-type-size variant `Returned`: 1025 bytes
|
print-type-size variant `Returned`: 1025 bytes
|
||||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||||
print-type-size variant `Panicked`: 1025 bytes
|
print-type-size variant `Panicked`: 1025 bytes
|
||||||
|
@ -2,7 +2,7 @@ print-type-size type: `{async fn body@$DIR/large-arg.rs:6:21: 8:2}`: 3076 bytes,
|
|||||||
print-type-size discriminant: 1 bytes
|
print-type-size discriminant: 1 bytes
|
||||||
print-type-size variant `Unresumed`: 0 bytes
|
print-type-size variant `Unresumed`: 0 bytes
|
||||||
print-type-size variant `Suspend0`: 3075 bytes
|
print-type-size variant `Suspend0`: 3075 bytes
|
||||||
print-type-size local `.__awaitee`: 3075 bytes
|
print-type-size local `.__awaitee`: 3075 bytes, type: {async fn body@$DIR/large-arg.rs:10:30: 12:2}
|
||||||
print-type-size variant `Returned`: 0 bytes
|
print-type-size variant `Returned`: 0 bytes
|
||||||
print-type-size variant `Panicked`: 0 bytes
|
print-type-size variant `Panicked`: 0 bytes
|
||||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
|
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
|
||||||
@ -17,7 +17,7 @@ print-type-size variant `Unresumed`: 1024 bytes
|
|||||||
print-type-size upvar `.t`: 1024 bytes
|
print-type-size upvar `.t`: 1024 bytes
|
||||||
print-type-size variant `Suspend0`: 3074 bytes
|
print-type-size variant `Suspend0`: 3074 bytes
|
||||||
print-type-size upvar `.t`: 1024 bytes
|
print-type-size upvar `.t`: 1024 bytes
|
||||||
print-type-size local `.__awaitee`: 2050 bytes
|
print-type-size local `.__awaitee`: 2050 bytes, type: {async fn body@$DIR/large-arg.rs:13:26: 15:2}
|
||||||
print-type-size variant `Returned`: 1024 bytes
|
print-type-size variant `Returned`: 1024 bytes
|
||||||
print-type-size upvar `.t`: 1024 bytes
|
print-type-size upvar `.t`: 1024 bytes
|
||||||
print-type-size variant `Panicked`: 1024 bytes
|
print-type-size variant `Panicked`: 1024 bytes
|
||||||
@ -34,7 +34,7 @@ print-type-size variant `Unresumed`: 1024 bytes
|
|||||||
print-type-size upvar `.t`: 1024 bytes
|
print-type-size upvar `.t`: 1024 bytes
|
||||||
print-type-size variant `Suspend0`: 2049 bytes
|
print-type-size variant `Suspend0`: 2049 bytes
|
||||||
print-type-size upvar `.t`: 1024 bytes
|
print-type-size upvar `.t`: 1024 bytes
|
||||||
print-type-size local `.__awaitee`: 1025 bytes
|
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/large-arg.rs:16:26: 18:2}
|
||||||
print-type-size variant `Returned`: 1024 bytes
|
print-type-size variant `Returned`: 1024 bytes
|
||||||
print-type-size upvar `.t`: 1024 bytes
|
print-type-size upvar `.t`: 1024 bytes
|
||||||
print-type-size variant `Panicked`: 1024 bytes
|
print-type-size variant `Panicked`: 1024 bytes
|
||||||
|
@ -5,7 +5,7 @@ print-type-size upvar `.arg`: 8192 bytes
|
|||||||
print-type-size variant `Suspend0`: 16385 bytes
|
print-type-size variant `Suspend0`: 16385 bytes
|
||||||
print-type-size upvar `.arg`: 8192 bytes
|
print-type-size upvar `.arg`: 8192 bytes
|
||||||
print-type-size local `.arg`: 8192 bytes
|
print-type-size local `.arg`: 8192 bytes
|
||||||
print-type-size local `.__awaitee`: 1 bytes
|
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async.rs:8:17: 8:19}
|
||||||
print-type-size variant `Returned`: 8192 bytes
|
print-type-size variant `Returned`: 8192 bytes
|
||||||
print-type-size upvar `.arg`: 8192 bytes
|
print-type-size upvar `.arg`: 8192 bytes
|
||||||
print-type-size variant `Panicked`: 8192 bytes
|
print-type-size variant `Panicked`: 8192 bytes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user