diff options
| author | bors <bors@rust-lang.org> | 2017-06-02 19:23:14 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-06-02 19:23:14 +0000 |
| commit | 107bd67ef7fb3e8027d7234d687cdd27c3efaa0d (patch) | |
| tree | b0ed47b3c7df37b85c7a74fb2b320bcfea4de972 /src/librustc_trans | |
| parent | d7798c3d179c7c18736fc0465e7ba6618c575a34 (diff) | |
| parent | 84047db2ade806b802f36d522ea82bd5d3cbb242 (diff) | |
| download | rust-107bd67ef7fb3e8027d7234d687cdd27c3efaa0d.tar.gz rust-107bd67ef7fb3e8027d7234d687cdd27c3efaa0d.zip | |
Auto merge of #42189 - nikomatsakis:chalk-trait-env-param-env, r=eddyb
querify layout and move param env out of the infcx
The main goal of this PR is to move the parameter environment *out* of the inference context. This is because the inference environment will soon be changing over the course of inference --- for example, when we enter into a `for<'a> fn(...)` type, we will push a new environment with an increasing universe index, rather than skolemizing the `'a` references. Similarly, each obligation will soon be able to have a distinct parameter environment, and therefore the `Obligation` struct is extended to carry a `ParamEnv<'tcx>`. (I debated about putting it into the cause; seems plausible, but also weird.)
Along the way, I also reworked how layout works, moving the layout cache into a proper query along the lines of needs-drop and friends.
Finally, tweaks the inference context API. It seemed to be accumulating parameters at an alarming rate. The main way to e.g. make a subtype or equality relationship is to do the following:
infcx.at(cause, param_env).sub(a, b)
infcx.at(cause, param_env).eq(a, b)
In both cases, `a` is considered the "expected" type (this used to be specified by a boolean). I tried hard to preserve the existing notion of what was "expected", although in some cases I'm not convinced it was being set on purpose one way or the other. This is why in some cases you will see me do `sup(b, a)`, which is otherwise equivalent to `sub(a, b)`, but sets the "expected type" differently.
r? @eddyb
cc @arielb1
Diffstat (limited to 'src/librustc_trans')
| -rw-r--r-- | src/librustc_trans/base.rs | 194 | ||||
| -rw-r--r-- | src/librustc_trans/context.rs | 50 | ||||
| -rw-r--r-- | src/librustc_trans/glue.rs | 16 |
3 files changed, 28 insertions, 232 deletions
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 1b3f0ba7ce5..88c30cd8665 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -44,7 +44,7 @@ use rustc::middle::cstore::LinkMeta; use rustc::hir::map as hir_map; use rustc::util::common::time; use rustc::session::config::{self, NoDebugInfo}; -use rustc::session::{self, DataTypeKind, Session}; +use rustc::session::Session; use rustc_incremental::IncrementalHashesMap; use abi; use mir::lvalue::LvalueRef; @@ -80,7 +80,6 @@ use std::i32; use syntax_pos::Span; use syntax::attr; use rustc::hir; -use rustc::ty::layout::{self, Layout}; use syntax::ast; use mir::lvalue::Alignment; @@ -1287,10 +1286,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &exported_symbols); }); - if tcx.sess.opts.debugging_opts.print_type_sizes { - gather_type_sizes(tcx); - } - if sess.target.target.options.is_like_msvc && sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) { create_imps(sess, &llvm_modules); @@ -1322,193 +1317,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let layout_cache = tcx.layout_cache.borrow(); - for (ty, layout) in layout_cache.iter() { - - // (delay format until we actually need it) - let record = |kind, opt_discr_size, variants| { - let type_desc = format!("{:?}", ty); - let overall_size = layout.size(tcx); - let align = layout.align(tcx); - tcx.sess.code_stats.borrow_mut().record_type_size(kind, - type_desc, - align, - overall_size, - opt_discr_size, - variants); - }; - - let (adt_def, substs) = match ty.sty { - ty::TyAdt(ref adt_def, substs) => { - debug!("print-type-size t: `{:?}` process adt", ty); - (adt_def, substs) - } - - ty::TyClosure(..) => { - debug!("print-type-size t: `{:?}` record closure", ty); - record(DataTypeKind::Closure, None, vec![]); - continue; - } - - _ => { - debug!("print-type-size t: `{:?}` skip non-nominal", ty); - continue; - } - }; - - let adt_kind = adt_def.adt_kind(); - - let build_field_info = |(field_name, field_ty): (ast::Name, Ty), offset: &layout::Size| { - match layout_cache.get(&field_ty) { - None => bug!("no layout found for field {} type: `{:?}`", field_name, field_ty), - Some(field_layout) => { - session::FieldInfo { - name: field_name.to_string(), - offset: offset.bytes(), - size: field_layout.size(tcx).bytes(), - align: field_layout.align(tcx).abi(), - } - } - } - }; - - let build_primitive_info = |name: ast::Name, value: &layout::Primitive| { - session::VariantInfo { - name: Some(name.to_string()), - kind: session::SizeKind::Exact, - align: value.align(tcx).abi(), - size: value.size(tcx).bytes(), - fields: vec![], - } - }; - - enum Fields<'a> { - WithDiscrim(&'a layout::Struct), - NoDiscrim(&'a layout::Struct), - } - - let build_variant_info = |n: Option<ast::Name>, flds: &[(ast::Name, Ty)], layout: Fields| { - let (s, field_offsets) = match layout { - Fields::WithDiscrim(s) => (s, &s.offsets[1..]), - Fields::NoDiscrim(s) => (s, &s.offsets[0..]), - }; - let field_info: Vec<_> = flds.iter() - .zip(field_offsets.iter()) - .map(|(&field_name_ty, offset)| build_field_info(field_name_ty, offset)) - .collect(); - - session::VariantInfo { - name: n.map(|n|n.to_string()), - kind: if s.sized { - session::SizeKind::Exact - } else { - session::SizeKind::Min - }, - align: s.align.abi(), - size: s.min_size.bytes(), - fields: field_info, - } - }; - - match **layout { - Layout::StructWrappedNullablePointer { nonnull: ref variant_layout, - nndiscr, - discrfield: _, - discrfield_source: _ } => { - debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}", - ty, nndiscr, variant_layout); - let variant_def = &adt_def.variants[nndiscr as usize]; - let fields: Vec<_> = variant_def.fields.iter() - .map(|field_def| (field_def.name, field_def.ty(tcx, substs))) - .collect(); - record(adt_kind.into(), - None, - vec![build_variant_info(Some(variant_def.name), - &fields, - Fields::NoDiscrim(variant_layout))]); - } - Layout::RawNullablePointer { nndiscr, value } => { - debug!("print-type-size t: `{:?}` adt raw nullable nndiscr {} is {:?}", - ty, nndiscr, value); - let variant_def = &adt_def.variants[nndiscr as usize]; - record(adt_kind.into(), None, - vec![build_primitive_info(variant_def.name, &value)]); - } - Layout::Univariant { variant: ref variant_layout, non_zero: _ } => { - let variant_names = || { - adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>() - }; - debug!("print-type-size t: `{:?}` adt univariant {:?} variants: {:?}", - ty, variant_layout, variant_names()); - assert!(adt_def.variants.len() <= 1, - "univariant with variants {:?}", variant_names()); - if adt_def.variants.len() == 1 { - let variant_def = &adt_def.variants[0]; - let fields: Vec<_> = variant_def.fields.iter() - .map(|field_def| (field_def.name, field_def.ty(tcx, substs))) - .collect(); - record(adt_kind.into(), - None, - vec![build_variant_info(Some(variant_def.name), - &fields, - Fields::NoDiscrim(variant_layout))]); - } else { - // (This case arises for *empty* enums; so give it - // zero variants.) - record(adt_kind.into(), None, vec![]); - } - } - - Layout::General { ref variants, discr, .. } => { - debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}", - ty, adt_def.variants.len(), variants.len(), variants); - let variant_infos: Vec<_> = adt_def.variants.iter() - .zip(variants.iter()) - .map(|(variant_def, variant_layout)| { - let fields: Vec<_> = variant_def.fields.iter() - .map(|field_def| (field_def.name, field_def.ty(tcx, substs))) - .collect(); - build_variant_info(Some(variant_def.name), - &fields, - Fields::WithDiscrim(variant_layout)) - }) - .collect(); - record(adt_kind.into(), Some(discr.size()), variant_infos); - } - - Layout::UntaggedUnion { ref variants } => { - debug!("print-type-size t: `{:?}` adt union variants {:?}", - ty, variants); - // layout does not currently store info about each - // variant... - record(adt_kind.into(), None, Vec::new()); - } - - Layout::CEnum { discr, .. } => { - debug!("print-type-size t: `{:?}` adt c-like enum", ty); - let variant_infos: Vec<_> = adt_def.variants.iter() - .map(|variant_def| { - build_primitive_info(variant_def.name, - &layout::Primitive::Int(discr)) - }) - .collect(); - record(adt_kind.into(), Some(discr.size()), variant_infos); - } - - // other cases provide little interesting (i.e. adjustable - // via representation tweaks) size info beyond total size. - Layout::Scalar { .. } | - Layout::Vector { .. } | - Layout::Array { .. } | - Layout::FatPointer { .. } => { - debug!("print-type-size t: `{:?}` adt other", ty); - record(adt_kind.into(), None, Vec::new()) - } - } - } -} - #[inline(never)] // give this a place in the profiler fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I) where I: Iterator<Item=&'a TransItem<'tcx>> diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 0413b0ea5c8..6266452419e 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -23,11 +23,11 @@ use monomorphize::Instance; use partitioning::CodegenUnit; use type_::Type; use rustc_data_structures::base_n; -use rustc::ty::subst::Substs; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{LayoutTyper, TyLayout}; use rustc::session::config::{self, NoDebugInfo}; use rustc::session::Session; +use rustc::ty::subst::Substs; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout}; use rustc::util::nodemap::{NodeSet, DefIdMap, FxHashMap}; use std::ffi::{CStr, CString}; @@ -320,15 +320,15 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { } pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool { - ty.needs_drop(self.tcx, ty::ParamEnv::empty()) + ty.needs_drop(self.tcx, ty::ParamEnv::empty(traits::Reveal::All)) } pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx, ty::ParamEnv::empty(), DUMMY_SP) + ty.is_sized(self.tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) } pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx, ty::ParamEnv::empty(), DUMMY_SP) + ty.is_freeze(self.tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) } pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet { @@ -709,41 +709,27 @@ impl<'a, 'tcx> ty::layout::HasDataLayout for &'a SharedCrateContext<'a, 'tcx> { } } -impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a SharedCrateContext<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { - self.tcx - } -} - impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CrateContext<'a, 'tcx> { fn data_layout(&self) -> &ty::layout::TargetDataLayout { &self.shared.tcx.data_layout } } -impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CrateContext<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { - self.shared.tcx - } -} - impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> { type TyLayout = TyLayout<'tcx>; - fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { - if let Some(&layout) = self.tcx().layout_cache.borrow().get(&ty) { - return TyLayout { ty: ty, layout: layout, variant_index: None }; - } + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { + self.tcx + } - self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| { - infcx.layout_of(ty).unwrap_or_else(|e| { - match e { - ty::layout::LayoutError::SizeOverflow(_) => - self.sess().fatal(&e.to_string()), - _ => bug!("failed to get layout for `{}`: {}", ty, e) - } + fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { + let param_env = ty::ParamEnv::empty(traits::Reveal::All); + LayoutCx::new(self.tcx, param_env) + .layout_of(ty) + .unwrap_or_else(|e| match e { + LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()), + _ => bug!("failed to get layout for `{}`: {}", ty, e) }) - }) } fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -754,6 +740,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> { impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> { type TyLayout = TyLayout<'tcx>; + fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { + self.shared.tcx + } + fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { self.shared.layout_of(ty) } diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index fa400b54d27..367f0398fa8 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -46,15 +46,13 @@ pub fn needs_drop_glue<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx> ty::TyAdt(def, _) if def.is_box() => { let typ = t.boxed_ty(); if !scx.type_needs_drop(typ) && scx.type_is_sized(typ) { - scx.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| { - let layout = t.layout(&infcx).unwrap(); - if layout.size(scx).bytes() == 0 { - // `Box<ZeroSizeType>` does not allocate. - false - } else { - true - } - }) + let layout = t.layout(scx.tcx(), ty::ParamEnv::empty(traits::Reveal::All)).unwrap(); + if layout.size(scx).bytes() == 0 { + // `Box<ZeroSizeType>` does not allocate. + false + } else { + true + } } else { true } |
