Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a0e19fd

Browse files
committedAug 11, 2017
WIP implement a machine readable print-type-info API
1 parent 6c5212f commit a0e19fd

File tree

4 files changed

+365
-180
lines changed

4 files changed

+365
-180
lines changed
 

‎src/librustc/session/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
12-
pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
11+
pub use self::print_type_info::{CodeStats};
12+
// pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
13+
// pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
1314

1415
use dep_graph::DepGraph;
1516
use hir::def_id::{CrateNum, DefIndex};
@@ -51,7 +52,8 @@ use std::rc::Rc;
5152
use std::sync::{Once, ONCE_INIT};
5253
use std::time::Duration;
5354

54-
mod code_stats;
55+
// mod code_stats;
56+
pub mod print_type_info;
5557
pub mod config;
5658
pub mod filesearch;
5759
pub mod search_paths;
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
use rustc_data_structures::fx::FxHashSet;
13+
use std::mem;
14+
use std::hash::{Hash, Hasher};
15+
use std::collections::BTreeMap;
16+
use rustc_serialize::json::Json;
17+
18+
pub struct CodeStats {
19+
types: FxHashSet<Type>,
20+
}
21+
22+
/// A Type name, with certain modifiers applied.
23+
///
24+
/// While a Type can have a name like rust::u32, a ComplexTypeName
25+
/// can include nested pointer/array modifiers:
26+
///
27+
/// * `*const ComplexTypeName`
28+
/// * `[ComplexTypeName; N]`
29+
///
30+
/// This avoids metadata blowup.
31+
///
32+
/// For example: `*const [*mut [rust::u32, 12], 32]`
33+
pub type ComplexTypeName = String;
34+
35+
pub struct Type {
36+
pub name: String,
37+
pub size: u64,
38+
pub align: u64,
39+
pub public: bool,
40+
pub kind: TypeKind,
41+
}
42+
43+
pub enum TypeKind {
44+
PrimitiveInt,
45+
PrimitiveFloat,
46+
Opaque,
47+
Struct { fields: Vec<Field> },
48+
Union { fields: Vec<Field> },
49+
Enum { base_type: ComplexTypeName, cases: Vec<Case> },
50+
}
51+
52+
pub struct Field {
53+
pub name: String,
54+
pub type_name: ComplexTypeName,
55+
pub offset: u64,
56+
pub public: bool,
57+
}
58+
59+
pub struct Case {
60+
pub name: String,
61+
pub value: i64, // TODO: u64/u128/i128? (serialize doesn't support)
62+
}
63+
64+
impl PartialEq for Type {
65+
fn eq(&self, other: &Self) -> bool { self.name == other.name }
66+
}
67+
impl Eq for Type {}
68+
impl Hash for Type {
69+
fn hash<H: Hasher>(&self, state: &mut H) {
70+
self.name.hash(state);
71+
}
72+
}
73+
74+
75+
impl TypeKind {
76+
fn as_str(&self) -> &'static str {
77+
match *self {
78+
TypeKind::PrimitiveInt => "primitive_int",
79+
TypeKind::PrimitiveFloat => "primitive_float",
80+
TypeKind::Opaque => "opaque",
81+
TypeKind::Struct { .. } => "struct",
82+
TypeKind::Union { .. } => "union",
83+
TypeKind::Enum { .. } => "enum",
84+
}
85+
}
86+
}
87+
88+
impl CodeStats {
89+
pub fn new() -> Self {
90+
CodeStats { types: FxHashSet::default() }
91+
}
92+
93+
pub fn insert(&mut self, ty: Type) {
94+
self.types.insert(ty);
95+
}
96+
97+
pub fn print_type_sizes(&mut self) {
98+
let types = mem::replace(&mut self.types, FxHashSet::default());
99+
100+
let mut output = Vec::with_capacity(types.len());
101+
102+
for ty in types {
103+
let mut json = BTreeMap::new();
104+
105+
json.insert("name".to_string(), Json::String(ty.name));
106+
json.insert("size".to_string(), Json::U64(ty.size));
107+
json.insert("align".to_string(), Json::U64(ty.align));
108+
json.insert("public".to_string(), Json::Boolean(ty.public));
109+
json.insert("kind".to_string(), Json::String(ty.kind.as_str().to_string()));
110+
111+
match ty.kind {
112+
TypeKind::Struct { fields } | TypeKind::Union { fields } => {
113+
let fields_json = fields.into_iter().map(field_to_json).collect();
114+
json.insert("fields".to_string(), Json::Array(fields_json));
115+
}
116+
TypeKind::Enum { base_type, cases } => {
117+
json.insert("base_type".to_string(), Json::String(base_type));
118+
let cases_json = cases.into_iter().map(case_to_json).collect();
119+
json.insert("cases".to_string(), Json::Array(cases_json));
120+
}
121+
_ => { /* nothing */ }
122+
}
123+
124+
output.push(Json::Object(json));
125+
}
126+
127+
println!("WARNING: these values are platform-specific, implementation-specific, \
128+
and compilation-specific. They can and will change for absolutely no reason. \
129+
To use this properly, you must recompute and evaluate them on each compilation \
130+
of your crate. Yes we broke your JSON parsing just to say this. We're not \
131+
kidding here.");
132+
println!("{}", Json::Array(output));
133+
}
134+
}
135+
136+
fn case_to_json(case: Case) -> Json {
137+
let mut json = BTreeMap::new();
138+
139+
json.insert("name".to_string(), Json::String(case.name));
140+
json.insert("value".to_string(), Json::I64(case.value));
141+
142+
Json::Object(json)
143+
}
144+
145+
fn field_to_json(field: Field) -> Json {
146+
let mut json = BTreeMap::new();
147+
148+
json.insert("name".to_string(), Json::String(field.name));
149+
json.insert("type".to_string(), Json::String(field.type_name));
150+
json.insert("offset".to_string(), Json::U64(field.offset));
151+
json.insert("public".to_string(), Json::Boolean(field.public));
152+
153+
Json::Object(json)
154+
}

‎src/librustc/ty/layout.rs

Lines changed: 205 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ pub use self::Integer::*;
1212
pub use self::Layout::*;
1313
pub use self::Primitive::*;
1414

15-
use session::{self, DataTypeKind, Session};
16-
use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags};
15+
use session::Session;
16+
use ty::{self, item_path, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags, Visibility};
1717

18-
use syntax::ast::{self, FloatTy, IntTy, UintTy};
18+
use syntax::ast::{FloatTy, IntTy, UintTy};
1919
use syntax::attr;
2020
use syntax_pos::DUMMY_SP;
2121

@@ -1719,15 +1719,14 @@ impl<'a, 'tcx> Layout {
17191719
pub fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
17201720
ty: Ty<'tcx>,
17211721
param_env: ty::ParamEnv<'tcx>,
1722-
layout: &Layout) {
1722+
layout: &'tcx Layout) {
17231723
// If we are running with `-Zprint-type-sizes`, record layouts for
17241724
// dumping later. Ignore layouts that are done with non-empty
17251725
// environments or non-monomorphic layouts, as the user only wants
17261726
// to see the stuff resulting from the final trans session.
17271727
if
17281728
!tcx.sess.opts.debugging_opts.print_type_sizes ||
1729-
ty.has_param_types() ||
1730-
ty.has_self_ty() ||
1729+
!ty.is_normalized_for_trans() ||
17311730
!param_env.caller_bounds.is_empty()
17321731
{
17331732
return;
@@ -1739,197 +1738,142 @@ impl<'a, 'tcx> Layout {
17391738
fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
17401739
ty: Ty<'tcx>,
17411740
param_env: ty::ParamEnv<'tcx>,
1742-
layout: &Layout) {
1743-
// (delay format until we actually need it)
1744-
let record = |kind, opt_discr_size, variants| {
1745-
let type_desc = format!("{:?}", ty);
1746-
let overall_size = layout.size(tcx);
1747-
let align = layout.align(tcx);
1748-
tcx.sess.code_stats.borrow_mut().record_type_size(kind,
1749-
type_desc,
1750-
align,
1751-
overall_size,
1752-
opt_discr_size,
1753-
variants);
1754-
};
1741+
layout: &'tcx Layout) {
17551742

1756-
let (adt_def, substs) = match ty.sty {
1757-
ty::TyAdt(ref adt_def, substs) => {
1758-
debug!("print-type-size t: `{:?}` process adt", ty);
1759-
(adt_def, substs)
1760-
}
1743+
use session::print_type_info::{Type, TypeKind, Field, Case};
17611744

1762-
ty::TyClosure(..) => {
1763-
debug!("print-type-size t: `{:?}` record closure", ty);
1764-
record(DataTypeKind::Closure, None, vec![]);
1765-
return;
1766-
}
1745+
// Caller should have filtered out all non-monomorphic types, so we
1746+
// we don't need to worry about finding a generic Vec<T> or Vec<U::Item>
1747+
match ty.sty {
1748+
// Concrete types we should consider processing
1749+
ty::TyBool |
1750+
ty::TyChar |
1751+
ty::TyInt(..) |
1752+
ty::TyUint(..) |
1753+
ty::TyFloat(..) |
1754+
ty::TyAdt(..) |
1755+
ty::TyRawPtr(..) |
1756+
ty::TyRef(..) |
1757+
ty::TyNever |
1758+
ty::TyTuple(..) => { }
17671759

1760+
// Anonymous or generic types we should avoid
17681761
_ => {
1762+
// TODO: `-> impl Trait` means closures can technically end up
1763+
// in public signatures, so we might want to actually record them?
17691764
debug!("print-type-size t: `{:?}` skip non-nominal", ty);
17701765
return;
17711766
}
17721767
};
17731768

1774-
let adt_kind = adt_def.adt_kind();
1775-
1776-
let build_field_info = |(field_name, field_ty): (ast::Name, Ty<'tcx>), offset: &Size| {
1777-
let layout = field_ty.layout(tcx, param_env);
1778-
match layout {
1779-
Err(_) => bug!("no layout found for field {} type: `{:?}`", field_name, field_ty),
1780-
Ok(field_layout) => {
1781-
session::FieldInfo {
1782-
name: field_name.to_string(),
1783-
offset: offset.bytes(),
1784-
size: field_layout.size(tcx).bytes(),
1785-
align: field_layout.align(tcx).abi(),
1786-
}
1787-
}
1788-
}
1769+
let cx = LayoutCx::new(tcx, param_env);
1770+
1771+
let layout = TyLayout {
1772+
ty,
1773+
layout: layout,
1774+
variant_index: None
17891775
};
17901776

1791-
let build_primitive_info = |name: ast::Name, value: &Primitive| {
1792-
session::VariantInfo {
1793-
name: Some(name.to_string()),
1794-
kind: session::SizeKind::Exact,
1795-
align: value.align(tcx).abi(),
1796-
size: value.size(tcx).bytes(),
1797-
fields: vec![],
1777+
// Common code for structs and unions
1778+
let fields = || {
1779+
let field_count = layout.field_count();
1780+
let mut fields = Vec::with_capacity(field_count);
1781+
1782+
for i in 0..field_count {
1783+
let offset = layout.field_offset(cx, i).bytes();
1784+
let field_ty = layout.field_type(cx, i);
1785+
let type_name = item_path::with_forced_impl_filename_line(||{
1786+
field_ty.to_string()
1787+
});
1788+
let (name, public) = layout.field_info(cx, i);
1789+
1790+
let field = Field {
1791+
name,
1792+
offset,
1793+
type_name,
1794+
public,
1795+
};
1796+
1797+
fields.push(field);
17981798
}
1799+
1800+
fields
17991801
};
18001802

1801-
enum Fields<'a> {
1802-
WithDiscrim(&'a Struct),
1803-
NoDiscrim(&'a Struct),
1804-
}
1803+
let kind = match *layout {
1804+
// Basic primitive, nothing interesting to do
1805+
Layout::Scalar { value: Primitive::Int(..), .. } => {
1806+
TypeKind::PrimitiveInt
1807+
}
1808+
Layout::Scalar { value: Primitive::F32, .. } |
1809+
Layout::Scalar { value: Primitive::F64, .. } => {
1810+
TypeKind::PrimitiveFloat
1811+
}
18051812

1806-
let build_variant_info = |n: Option<ast::Name>,
1807-
flds: &[(ast::Name, Ty<'tcx>)],
1808-
layout: Fields| {
1809-
let (s, field_offsets) = match layout {
1810-
Fields::WithDiscrim(s) => (s, &s.offsets[1..]),
1811-
Fields::NoDiscrim(s) => (s, &s.offsets[0..]),
1812-
};
1813-
let field_info: Vec<_> =
1814-
flds.iter()
1815-
.zip(field_offsets.iter())
1816-
.map(|(&field_name_ty, offset)| build_field_info(field_name_ty, offset))
1817-
.collect();
1818-
1819-
session::VariantInfo {
1820-
name: n.map(|n|n.to_string()),
1821-
kind: if s.sized {
1822-
session::SizeKind::Exact
1823-
} else {
1824-
session::SizeKind::Min
1825-
},
1826-
align: s.align.abi(),
1827-
size: s.min_size.bytes(),
1828-
fields: field_info,
1813+
// Thin pointers; don't record these
1814+
Layout::Scalar { value: Primitive::Pointer, .. } |
1815+
Layout::RawNullablePointer { .. } => {
1816+
// TODO: do we maybe want to actually type RawNullablePointer?
1817+
// Option<Box>/Option<Rc> aren't quite the same as Option<&>...
1818+
return;
18291819
}
1830-
};
18311820

1832-
match *layout {
1833-
Layout::StructWrappedNullablePointer { nonnull: ref variant_layout,
1834-
nndiscr,
1835-
discrfield: _,
1836-
discrfield_source: _ } => {
1837-
debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}",
1838-
ty, nndiscr, variant_layout);
1839-
let variant_def = &adt_def.variants[nndiscr as usize];
1840-
let fields: Vec<_> =
1841-
variant_def.fields.iter()
1842-
.map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
1843-
.collect();
1844-
record(adt_kind.into(),
1845-
None,
1846-
vec![build_variant_info(Some(variant_def.name),
1847-
&fields,
1848-
Fields::NoDiscrim(variant_layout))]);
1849-
}
1850-
Layout::RawNullablePointer { nndiscr, value } => {
1851-
debug!("print-type-size t: `{:?}` adt raw nullable nndiscr {} is {:?}",
1852-
ty, nndiscr, value);
1853-
let variant_def = &adt_def.variants[nndiscr as usize];
1854-
record(adt_kind.into(), None,
1855-
vec![build_primitive_info(variant_def.name, &value)]);
1856-
}
1857-
Layout::Univariant { variant: ref variant_layout, non_zero: _ } => {
1858-
let variant_names = || {
1859-
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
1860-
};
1861-
debug!("print-type-size t: `{:?}` adt univariant {:?} variants: {:?}",
1862-
ty, variant_layout, variant_names());
1863-
assert!(adt_def.variants.len() <= 1,
1864-
"univariant with variants {:?}", variant_names());
1865-
if adt_def.variants.len() == 1 {
1866-
let variant_def = &adt_def.variants[0];
1867-
let fields: Vec<_> =
1868-
variant_def.fields.iter()
1869-
.map(|f| (f.name, f.ty(tcx, substs)))
1870-
.collect();
1871-
record(adt_kind.into(),
1872-
None,
1873-
vec![build_variant_info(Some(variant_def.name),
1874-
&fields,
1875-
Fields::NoDiscrim(variant_layout))]);
1876-
} else {
1877-
// (This case arises for *empty* enums; so give it
1878-
// zero variants.)
1879-
record(adt_kind.into(), None, vec![]);
1821+
// Structs
1822+
Layout::Vector { .. } |
1823+
Layout::FatPointer { .. } |
1824+
Layout::Univariant { .. } => {
1825+
TypeKind::Struct { fields: fields() }
1826+
}
1827+
1828+
// Union
1829+
Layout::UntaggedUnion { .. } => {
1830+
TypeKind::Union { fields: fields() }
1831+
}
1832+
1833+
1834+
// C-like Enums
1835+
Layout::CEnum { discr, signed, .. } => {
1836+
let base_type = item_path::with_forced_impl_filename_line(||{
1837+
discr.to_ty(&tcx, signed).to_string()
1838+
});
1839+
1840+
let def = if let ty::TyAdt(def, ..) = ty.sty { def } else { unreachable!() };
1841+
1842+
let mut cases = Vec::with_capacity(def.variants.len());
1843+
for (discr, variant) in def.discriminants(tcx).zip(def.variants.iter()) {
1844+
// TODO: i128?
1845+
let value = discr.to_u128_unchecked() as i64;
1846+
let name = variant.name.to_string();
1847+
let case = Case { name, value };
1848+
cases.push(case);
18801849
}
1850+
1851+
TypeKind::Enum { base_type, cases }
18811852
}
18821853

1883-
Layout::General { ref variants, discr, .. } => {
1884-
debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}",
1885-
ty, adt_def.variants.len(), variants.len(), variants);
1886-
let variant_infos: Vec<_> =
1887-
adt_def.variants.iter()
1888-
.zip(variants.iter())
1889-
.map(|(variant_def, variant_layout)| {
1890-
let fields: Vec<_> =
1891-
variant_def.fields
1892-
.iter()
1893-
.map(|f| (f.name, f.ty(tcx, substs)))
1894-
.collect();
1895-
build_variant_info(Some(variant_def.name),
1896-
&fields,
1897-
Fields::WithDiscrim(variant_layout))
1898-
})
1899-
.collect();
1900-
record(adt_kind.into(), Some(discr.size()), variant_infos);
1901-
}
1902-
1903-
Layout::UntaggedUnion { ref variants } => {
1904-
debug!("print-type-size t: `{:?}` adt union variants {:?}",
1905-
ty, variants);
1906-
// layout does not currently store info about each
1907-
// variant...
1908-
record(adt_kind.into(), None, Vec::new());
1909-
}
1910-
1911-
Layout::CEnum { discr, .. } => {
1912-
debug!("print-type-size t: `{:?}` adt c-like enum", ty);
1913-
let variant_infos: Vec<_> =
1914-
adt_def.variants.iter()
1915-
.map(|variant_def| {
1916-
build_primitive_info(variant_def.name,
1917-
&Primitive::Int(discr))
1918-
})
1919-
.collect();
1920-
record(adt_kind.into(), Some(discr.size()), variant_infos);
1921-
}
1922-
1923-
// other cases provide little interesting (i.e. adjustable
1924-
// via representation tweaks) size info beyond total size.
1925-
Layout::Scalar { .. } |
1926-
Layout::Vector { .. } |
1927-
Layout::Array { .. } |
1928-
Layout::FatPointer { .. } => {
1929-
debug!("print-type-size t: `{:?}` adt other", ty);
1930-
record(adt_kind.into(), None, Vec::new())
1854+
// Don't expose details of tagged unions yet, as we
1855+
// reserve the right to do pretty extreme optimizations, and don't
1856+
// want to settle on an abstraction yet.
1857+
Layout::General { .. } |
1858+
StructWrappedNullablePointer { .. } => {
1859+
TypeKind::Opaque
19311860
}
1932-
}
1861+
1862+
Layout::Array { .. } => {
1863+
bug!("Arrays shouldn't ever make it here")
1864+
}
1865+
};
1866+
1867+
let size = layout.size(tcx).bytes();
1868+
let align = layout.align(tcx).abi();
1869+
let name = item_path::with_forced_impl_filename_line(||{
1870+
ty.to_string()
1871+
});
1872+
let public = true; // TODO
1873+
1874+
tcx.sess.code_stats.borrow_mut().insert(Type {
1875+
name, size, align, public, kind
1876+
});
19331877
}
19341878
}
19351879

@@ -2264,6 +2208,91 @@ impl<'a, 'tcx> TyLayout<'tcx> {
22642208
}
22652209
}
22662210

2211+
/// Gets the field name, and whether the field is `pub`, for use in print-type-info.
2212+
///
2213+
/// Fields of builtins have synthesized names that are valid C idents.
2214+
/// e.g. tuple.0 becomes tuple.item0
2215+
///
2216+
/// Note: some of these results aren't ever used by print-type-info, because these types
2217+
/// have a natural C ABI (i.e. TyArray).
2218+
fn field_info<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> (String, bool) {
2219+
let tcx = cx.tcx();
2220+
2221+
let ptr_field_info = |pointee: Ty<'tcx>| {
2222+
assert!(i < 2);
2223+
match tcx.struct_tail(pointee).sty {
2224+
ty::TySlice(..) |
2225+
ty::TyStr => {
2226+
if i == 0 {
2227+
("ptr".to_string(), false)
2228+
} else {
2229+
("len".to_string(), false)
2230+
}
2231+
}
2232+
ty::TyDynamic(..) => {
2233+
if i == 0 {
2234+
("data".to_string(), false)
2235+
} else {
2236+
("vtable".to_string(), false)
2237+
}
2238+
}
2239+
_ => bug!("TyLayout::field_info({:?}): not applicable", self)
2240+
}
2241+
};
2242+
2243+
match self.ty.sty {
2244+
ty::TyBool |
2245+
ty::TyChar |
2246+
ty::TyInt(_) |
2247+
ty::TyUint(_) |
2248+
ty::TyFloat(_) |
2249+
ty::TyFnPtr(_) |
2250+
ty::TyNever |
2251+
ty::TyFnDef(..) |
2252+
ty::TyDynamic(..) |
2253+
ty::TySlice(..) |
2254+
ty::TyStr => {
2255+
bug!("TyLayout::field_info({:?}): not applicable", self)
2256+
}
2257+
2258+
// Potentially-fat pointers.
2259+
ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
2260+
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
2261+
ptr_field_info(pointee)
2262+
}
2263+
ty::TyAdt(def, _) if def.is_box() => {
2264+
ptr_field_info(self.ty.boxed_ty())
2265+
}
2266+
2267+
// Arrays and slices.
2268+
ty::TyArray(..) => (format!("idx{}", i), false),
2269+
2270+
// Closures.
2271+
ty::TyClosure(..) => (format!("capture{}", i), false),
2272+
2273+
// Tuples
2274+
ty::TyTuple(..) => (format!("item{}", i), true),
2275+
2276+
// SIMD vectors
2277+
ty::TyAdt(def, ..) if def.repr.simd() => {
2278+
(format!("idx{}", i), true)
2279+
}
2280+
2281+
// ADTs.
2282+
ty::TyAdt(def, ..) => {
2283+
let field = &def.variants[self.variant_index.unwrap_or(0)].fields[i];
2284+
let public = if let Visibility::Public = field.vis { true } else { false };
2285+
let name = field.name.to_string();
2286+
(name, public)
2287+
}
2288+
2289+
ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
2290+
ty::TyInfer(_) | ty::TyError => {
2291+
bug!("TyLayout::field_type: unexpected type `{}`", self.ty)
2292+
}
2293+
}
2294+
}
2295+
22672296
pub fn field<C: LayoutTyper<'tcx>>(&self,
22682297
cx: C,
22692298
i: usize)

‎src/librustc_driver/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ pub fn compile_input(sess: &Session,
226226
};
227227

228228
if sess.opts.debugging_opts.print_type_sizes {
229-
sess.code_stats.borrow().print_type_sizes();
229+
sess.code_stats.borrow_mut().print_type_sizes();
230230
}
231231

232232
let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans);

0 commit comments

Comments
 (0)
Please sign in to comment.