diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2014-12-18 09:26:10 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2014-12-30 09:32:42 -0500 |
| commit | 4946e1a46317a890b3e8d0157e045adf80b535d3 (patch) | |
| tree | ca0d88d978a05054d81c7be244e251ed4a3315ec | |
| parent | 0b64e5796ba3f501042f02d416a7a625802e9e44 (diff) | |
| download | rust-4946e1a46317a890b3e8d0157e045adf80b535d3.tar.gz rust-4946e1a46317a890b3e8d0157e045adf80b535d3.zip | |
Move the TypeContents-based "Sized" queries into trans, where the full
types are always known and hence the ParameterEnvironment is not necessary. For other `Sized` queries, use the trait infrastructure just like `Copy`.
| -rw-r--r-- | src/librustc/middle/check_rvalues.rs | 14 | ||||
| -rw-r--r-- | src/librustc/middle/traits/mod.rs | 38 | ||||
| -rw-r--r-- | src/librustc/middle/ty.rs | 120 | ||||
| -rw-r--r-- | src/librustc_trans/trans/adt.rs | 8 | ||||
| -rw-r--r-- | src/librustc_trans/trans/base.rs | 10 | ||||
| -rw-r--r-- | src/librustc_trans/trans/common.rs | 56 | ||||
| -rw-r--r-- | src/librustc_trans/trans/consts.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/datum.rs | 4 | ||||
| -rw-r--r-- | src/librustc_trans/trans/expr.rs | 16 | ||||
| -rw-r--r-- | src/librustc_trans/trans/glue.rs | 26 | ||||
| -rw-r--r-- | src/librustc_trans/trans/intrinsic.rs | 4 | ||||
| -rw-r--r-- | src/librustc_trans/trans/type_of.rs | 10 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 18 |
13 files changed, 207 insertions, 119 deletions
diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs index 494d85f7ba5..3b4ea5234f4 100644 --- a/src/librustc/middle/check_rvalues.rs +++ b/src/librustc/middle/check_rvalues.rs @@ -28,7 +28,7 @@ pub fn check_crate(tcx: &ty::ctxt, } struct RvalueContext<'a, 'tcx: 'a> { - tcx: &'a ty::ctxt<'tcx> + tcx: &'a ty::ctxt<'tcx>, } impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> { @@ -40,21 +40,27 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> { fn_id: ast::NodeId) { { let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); - let mut euv = euv::ExprUseVisitor::new(self, self.tcx, ¶m_env); + let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: ¶m_env }; + let mut euv = euv::ExprUseVisitor::new(&mut delegate, self.tcx, ¶m_env); euv.walk_fn(fd, b); } visit::walk_fn(self, fk, fd, b, s) } } -impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContext<'a, 'tcx> { +struct RvalueContextDelegate<'a, 'tcx: 'a> { + tcx: &'a ty::ctxt<'tcx>, + param_env: &'a ty::ParameterEnvironment<'tcx>, +} + +impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> { fn consume(&mut self, _: ast::NodeId, span: Span, cmt: mc::cmt<'tcx>, _: euv::ConsumeMode) { debug!("consume; cmt: {}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty)); - if !ty::type_is_sized(self.tcx, cmt.ty) { + if !ty::type_is_sized(self.tcx, cmt.ty, self.param_env) { span_err!(self.tcx.sess, span, E0161, "cannot move a value of type {0}: the size of {0} cannot be statically determined", ty_to_string(self.tcx, cmt.ty)); diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 6597730846d..5676ba6f665 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -22,6 +22,7 @@ use std::rc::Rc; use std::slice::Iter; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; +use util::ppaux::Repr; pub use self::error_reporting::report_fulfillment_errors; pub use self::fulfill::{FulfillmentContext, RegionObligation}; @@ -265,6 +266,43 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>, util::predicates_for_generics(tcx, cause, 0, generic_bounds) } +/// Determines whether the type `ty` is known to meet `bound` and +/// returns true if so. Returns false if `ty` either does not meet +/// `bound` or is not known to meet bound (note that this is +/// conservative towards *no impl*, which is the opposite of the +/// `evaluate` methods). +pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, + param_env: &ty::ParameterEnvironment<'tcx>, + ty: Ty<'tcx>, + bound: ty::BuiltinBound) + -> bool +{ + debug!("type_known_to_meet_builtin_bound(ty={}, bound={})", + ty.repr(infcx.tcx), + bound); + + let mut fulfill_cx = FulfillmentContext::new(); + + // We can use dummy values here because we won't report any errors + // that result nor will we pay any mind to region obligations that arise + // (there shouldn't really be any anyhow). + let cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); + + fulfill_cx.register_builtin_bound(infcx.tcx, ty, bound, cause); + + // Note: we only assume something is `Copy` if we can + // *definitively* show that it implements `Copy`. Otherwise, + // assume it is move; linear is always ok. + let result = fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx).is_ok(); + + debug!("type_known_to_meet_builtin_bound: ty={} bound={} result={}", + ty.repr(infcx.tcx), + bound, + result); + + result +} + impl<'tcx,O> Obligation<'tcx,O> { pub fn new(cause: ObligationCause<'tcx>, trait_ref: O) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d09efb006f2..731ad64799e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -56,7 +56,6 @@ use middle::resolve_lifetime; use middle::infer; use middle::stability; use middle::subst::{mod, Subst, Substs, VecPerParamSpace}; -use middle::traits::ObligationCause; use middle::traits; use middle::ty; use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; @@ -65,7 +64,7 @@ use util::ppaux::{trait_store_to_string, ty_to_string}; use util::ppaux::{Repr, UserString}; use util::common::{indenter, memoized, ErrorReported}; use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; -use util::nodemap::{FnvHashMap, FnvHashSet}; +use util::nodemap::{FnvHashMap}; use arena::TypedArena; use std::borrow::BorrowFrom; @@ -80,13 +79,13 @@ use collections::enum_set::{EnumSet, CLike}; use std::collections::{HashMap, HashSet}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use syntax::abi; -use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, Ident, ItemTrait, LOCAL_CRATE}; +use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE}; use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField}; use syntax::ast::{Visibility}; use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod}; use syntax::attr::{mod, AttrMetaMethods}; -use syntax::codemap::{DUMMY_SP, Span}; +use syntax::codemap::Span; use syntax::parse::token::{mod, InternedString}; use syntax::{ast, ast_map}; @@ -780,8 +779,15 @@ pub struct ctxt<'tcx> { /// Caches the representation hints for struct definitions. pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>, - /// Caches whether types move by default. - pub type_moves_by_default_cache: RefCell<HashMap<Ty<'tcx>,bool>>, + /// Caches whether types are known to impl Copy. Note that type + /// parameters are never placed into this cache, because their + /// results are dependent on the parameter environment. + pub type_impls_copy_cache: RefCell<HashMap<Ty<'tcx>,bool>>, + + /// Caches whether types are known to impl Sized. Note that type + /// parameters are never placed into this cache, because their + /// results are dependent on the parameter environment. + pub type_impls_sized_cache: RefCell<HashMap<Ty<'tcx>,bool>>, } // Flags that we track on types. These flags are propagated upwards @@ -2142,7 +2148,8 @@ pub fn mk_ctxt<'tcx>(s: Session, associated_types: RefCell::new(DefIdMap::new()), selection_cache: traits::SelectionCache::new(), repr_hint_cache: RefCell::new(DefIdMap::new()), - type_moves_by_default_cache: RefCell::new(HashMap::new()), + type_impls_copy_cache: RefCell::new(HashMap::new()), + type_impls_sized_cache: RefCell::new(HashMap::new()), } } @@ -2791,14 +2798,6 @@ pub fn type_is_unique(ty: Ty) -> bool { } } -pub fn type_is_fat_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..}) - | ty_uniq(ty) if !type_is_sized(cx, ty) => true, - _ => false, - } -} - /* A scalar type is one that denotes an atomic datum, with no sub-components. (A ty_ptr is scalar because it represents a non-managed pointer, so its @@ -3289,17 +3288,22 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { } } -pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, - ty: Ty<'tcx>, - param_env: &ParameterEnvironment<'tcx>) - -> bool +fn type_impls_bound<'tcx>(cx: &ctxt<'tcx>, + cache: &RefCell<HashMap<Ty<'tcx>,bool>>, + param_env: &ParameterEnvironment<'tcx>, + ty: Ty<'tcx>, + bound: ty::BuiltinBound) + -> bool { + assert!(!ty::type_needs_infer(ty)); + if !type_has_params(ty) && !type_has_self(ty) { - match cx.type_moves_by_default_cache.borrow().get(&ty) { + match cache.borrow().get(&ty) { None => {} Some(&result) => { - debug!("determined whether {} moves by default (cached): {}", + debug!("type_impls_bound({}, {}) = {} (cached)", ty_to_string(cx, ty), + bound, result); return result } @@ -3307,27 +3311,35 @@ pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, } let infcx = infer::new_infer_ctxt(cx); - let mut fulfill_cx = traits::FulfillmentContext::new(); + let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound); - // we can use dummy values here because we won't report any errors - // that result nor will we pay any mind to region obligations that arise - // (there shouldn't really be any anyhow) - let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID); + debug!("type_impls_bound({}, {}) = {}", + ty_to_string(cx, ty), + bound, + is_impld); - fulfill_cx.register_builtin_bound(cx, ty, ty::BoundCopy, cause); + if !type_has_params(ty) && !type_has_self(ty) { + let old_value = cache.borrow_mut().insert(ty, is_impld); + assert!(old_value.is_none()); + } - // Note: we only assuming something is `Copy` if we can - // *definitively* show that it implements `Copy`. Otherwise, - // assume it is move; linear is always ok. - let is_copy = fulfill_cx.select_all_or_error(&infcx, param_env, cx).is_ok(); - let is_move = !is_copy; + is_impld +} - debug!("determined whether {} moves by default: {}", - ty_to_string(cx, ty), - is_move); +pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, + ty: Ty<'tcx>, + param_env: &ParameterEnvironment<'tcx>) + -> bool +{ + !type_impls_bound(cx, &cx.type_impls_copy_cache, param_env, ty, ty::BoundCopy) +} - cx.type_moves_by_default_cache.borrow_mut().insert(ty, is_move); - is_move +pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>, + ty: Ty<'tcx>, + param_env: &ParameterEnvironment<'tcx>) + -> bool +{ + type_impls_bound(cx, &cx.type_impls_sized_cache, param_env, ty, ty::BoundSized) } pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { @@ -3699,40 +3711,6 @@ pub fn type_is_machine(ty: Ty) -> bool { } } -// Is the type's representation size known at compile time? -pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - type_contents(cx, ty).is_sized(cx) -} - -pub fn lltype_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty_open(_) => true, - _ => type_contents(cx, ty).is_sized(cx) - } -} - -// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized. -// 'Smallest' here means component of the static representation of the type; not -// the size of an object at runtime. -pub fn unsized_part_of_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { - ty_str | ty_trait(..) | ty_vec(..) => ty, - ty_struct(def_id, substs) => { - let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter() - .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect(); - // Exactly one of the fields must be unsized. - assert!(unsized_fields.len() == 1); - - unsized_part_of_type(cx, unsized_fields[0]) - } - _ => { - assert!(type_is_sized(cx, ty), - "unsized_part_of_type failed even though ty is unsized"); - panic!("called unsized_part_of_type with sized ty"); - } - } -} - // Whether a type is enum like, that is an enum type with only nullary // constructors pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool { diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 595d252a0b1..717c2af2beb 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -343,7 +343,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>, mut path: DiscrField) -> Option<DiscrField> { match ty.sty { // Fat &T/&mut T/Box<T> i.e. T is [T], str, or Trait - ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) if !ty::type_is_sized(tcx, ty) => { + ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) if !type_is_sized(tcx, ty) => { path.push(FAT_PTR_ADDR); Some(path) }, @@ -447,12 +447,12 @@ fn mk_struct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, tys: &[Ty<'tcx>], packed: bool, scapegoat: Ty<'tcx>) -> Struct<'tcx> { - let sized = tys.iter().all(|&ty| ty::type_is_sized(cx.tcx(), ty)); + let sized = tys.iter().all(|&ty| type_is_sized(cx.tcx(), ty)); let lltys : Vec<Type> = if sized { tys.iter() .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() } else { - tys.iter().filter(|&ty| ty::type_is_sized(cx.tcx(), *ty)) + tys.iter().filter(|&ty| type_is_sized(cx.tcx(), *ty)) .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() }; @@ -704,7 +704,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>, sizing: bool, dst: bool) -> Vec<Type> { if sizing { - st.fields.iter().filter(|&ty| !dst || ty::type_is_sized(cx.tcx(), *ty)) + st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty)) .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() } else { st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect() diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index f0d738d839d..397baac960d 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -581,7 +581,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>, match t.sty { ty::ty_tup(ref tys) if tys.is_empty() => f(nil_type), ty::ty_bool | ty::ty_uint(_) | ty::ty_char => f(unsigned_int), - ty::ty_ptr(mt) if ty::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int), + ty::ty_ptr(mt) if common::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int), ty::ty_int(_) => f(signed_int), ty::ty_float(_) => f(floating_point), // Should never get here, because t is scalar. @@ -719,7 +719,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, return cx; } - let (data_ptr, info) = if ty::type_is_sized(cx.tcx(), t) { + let (data_ptr, info) = if common::type_is_sized(cx.tcx(), t) { (av, None) } else { let data = GEPi(cx, av, &[0, abi::FAT_PTR_ADDR]); @@ -736,7 +736,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, let field_ty = field_ty.mt.ty; let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, discr, i); - let val = if ty::type_is_sized(cx.tcx(), field_ty) { + let val = if common::type_is_sized(cx.tcx(), field_ty) { llfld_a } else { let boxed_ty = ty::mk_open(cx.tcx(), field_ty); @@ -2522,7 +2522,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< match ret_ty.sty { // `~` pointer return values never alias because ownership // is transferred - ty::ty_uniq(it) if !ty::type_is_sized(ccx.tcx(), it) => {} + ty::ty_uniq(it) if !common::type_is_sized(ccx.tcx(), it) => {} ty::ty_uniq(_) => { attrs.ret(llvm::NoAliasAttribute); } @@ -2533,7 +2533,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< match ret_ty.sty { // These are not really pointers but pairs, (pointer, len) ty::ty_uniq(it) | - ty::ty_rptr(_, ty::mt { ty: it, .. }) if !ty::type_is_sized(ccx.tcx(), it) => {} + ty::ty_rptr(_, ty::mt { ty: it, .. }) if !common::type_is_sized(ccx.tcx(), it) => {} ty::ty_uniq(inner) | ty::ty_rptr(_, ty::mt { ty: inner, .. }) => { let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, inner)); attrs.ret(llvm::DereferenceableAttribute(llret_sz)); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 7ee4be0ae56..f052a20bc89 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -58,6 +58,58 @@ use util::nodemap::FnvHashSet; pub use trans::context::CrateContext; +// Is the type's representation size known at compile time? +pub fn type_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + ty::type_contents(cx, ty).is_sized(cx) +} + +pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::ty_open(_) => true, + _ => type_is_sized(cx, ty), + } +} + +pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::ty_ptr(ty::mt{ty, ..}) | + ty::ty_rptr(_, ty::mt{ty, ..}) | + ty::ty_uniq(ty) => { + !type_is_sized(cx, ty) + } + _ => { + false + } + } +} + +// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized. +// 'Smallest' here means component of the static representation of the type; not +// the size of an object at runtime. +pub fn unsized_part_of_type<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.sty { + ty::ty_str | ty::ty_trait(..) | ty::ty_vec(..) => ty, + ty::ty_struct(def_id, substs) => { + let unsized_fields: Vec<_> = + ty::struct_fields(cx, def_id, substs) + .iter() + .map(|f| f.mt.ty) + .filter(|ty| !type_is_sized(cx, *ty)) + .collect(); + + // Exactly one of the fields must be unsized. + assert!(unsized_fields.len() == 1); + + unsized_part_of_type(cx, unsized_fields[0]) + } + _ => { + assert!(type_is_sized(cx, ty), + "unsized_part_of_type failed even though ty is unsized"); + panic!("called unsized_part_of_type with sized ty"); + } + } +} + // Some things don't need cleanups during unwinding because the // task can free them all at once later. Currently only things // that only contain scalars and shared boxes can avoid unwind @@ -128,10 +180,10 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) - ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) || type_is_newtype_immediate(ccx, ty) || ty::type_is_simd(tcx, ty); - if simple && !ty::type_is_fat_ptr(tcx, ty) { + if simple && !type_is_fat_ptr(tcx, ty) { return true; } - if !ty::type_is_sized(tcx, ty) { + if !type_is_sized(tcx, ty) { return false; } match ty.sty { diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index bc386dc96a4..0fd6d286e8b 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -138,7 +138,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, v: ValueRef, Some(ref mt) => { match t.sty { ty::ty_ptr(mt) | ty::ty_rptr(_, mt) => { - if ty::type_is_sized(cx.tcx(), mt.ty) { + if type_is_sized(cx.tcx(), mt.ty) { (const_deref_ptr(cx, v), mt.ty) } else { // Derefing a fat pointer does not change the representation, diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index ca274ab605e..83bf06383a8 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -398,7 +398,7 @@ impl<'tcx> Datum<'tcx, Expr> { -> DatumBlock<'blk, 'tcx, Lvalue> { debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx())); - assert!(ty::lltype_is_sized(bcx.tcx(), self.ty), + assert!(lltype_is_sized(bcx.tcx(), self.ty), "Trying to convert unsized value to lval"); self.match_kind( |l| DatumBlock::new(bcx, l), @@ -456,7 +456,7 @@ impl<'tcx> Datum<'tcx, Lvalue> { F: FnOnce(ValueRef) -> ValueRef, { let val = match self.ty.sty { - _ if ty::type_is_sized(bcx.tcx(), self.ty) => gep(self.val), + _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val), ty::ty_open(_) => { let base = Load(bcx, expr::get_dataptr(bcx, self.val)); gep(base) diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index ae07e094a5c..fc2e6c7b7fd 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -280,7 +280,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr.repr(bcx.tcx()), datum.to_string(bcx.ccx())); - if !ty::type_is_sized(bcx.tcx(), datum.ty) { + if !type_is_sized(bcx.tcx(), datum.ty) { debug!("Taking address of unsized type {}", bcx.ty_to_string(datum.ty)); ref_fat_ptr(bcx, expr, datum) @@ -693,7 +693,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, field_tys[ix].mt.ty, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix)); - if ty::type_is_sized(bcx.tcx(), d.ty) { + if type_is_sized(bcx.tcx(), d.ty) { DatumBlock { datum: d.to_expr_datum(), bcx: bcx } } else { let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), ""); @@ -773,7 +773,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Some(SaveIn(scratch.val)), true)); let datum = scratch.to_expr_datum(); - if ty::type_is_sized(bcx.tcx(), elt_ty) { + if type_is_sized(bcx.tcx(), elt_ty) { Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr) } else { Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr) @@ -1522,7 +1522,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, for &(i, t) in base.fields.iter() { let datum = base_datum.get_element( bcx, t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i)); - assert!(ty::type_is_sized(bcx.tcx(), datum.ty)); + assert!(type_is_sized(bcx.tcx(), datum.ty)); let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); bcx = datum.store_to(bcx, dest); } @@ -1650,7 +1650,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, -> DatumBlock<'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_uniq_expr"); let fcx = bcx.fcx; - assert!(ty::type_is_sized(bcx.tcx(), contents_ty)); + assert!(type_is_sized(bcx.tcx(), contents_ty)); let llty = type_of::type_of(bcx.ccx(), contents_ty); let size = llsize_of(bcx.ccx(), llty); let align = C_uint(bcx.ccx(), type_of::align_of(bcx.ccx(), contents_ty)); @@ -1985,7 +1985,7 @@ pub fn cast_type_kind<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> cast_kind { ty::ty_char => cast_integral, ty::ty_float(..) => cast_float, ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => { - if ty::type_is_sized(tcx, mt.ty) { + if type_is_sized(tcx, mt.ty) { cast_pointer } else { cast_other @@ -2217,7 +2217,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let r = match datum.ty.sty { ty::ty_uniq(content_ty) => { - if ty::type_is_sized(bcx.tcx(), content_ty) { + if type_is_sized(bcx.tcx(), content_ty) { deref_owned_pointer(bcx, expr, datum, content_ty) } else { // A fat pointer and an opened DST value have the same @@ -2236,7 +2236,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty::ty_ptr(ty::mt { ty: content_ty, .. }) | ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => { - if ty::type_is_sized(bcx.tcx(), content_ty) { + if type_is_sized(bcx.tcx(), content_ty) { let ptr = datum.to_llscalarish(bcx); // Always generate an lvalue datum, even if datum.mode is diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 4217dd4c671..31455920c10 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -63,7 +63,7 @@ pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, content_ty: Ty<'tcx>) -> Block<'blk, 'tcx> { - assert!(ty::type_is_sized(bcx.ccx().tcx(), content_ty)); + assert!(type_is_sized(bcx.ccx().tcx(), content_ty)); let sizing_type = sizing_type_of(bcx.ccx(), content_ty); let content_size = llsize_of_alloc(bcx.ccx(), sizing_type); @@ -81,7 +81,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let tcx = ccx.tcx(); // Even if there is no dtor for t, there might be one deeper down and we // might need to pass in the vtable ptr. - if !ty::type_is_sized(tcx, t) { + if !type_is_sized(tcx, t) { return t } if !type_needs_drop(tcx, t) { @@ -89,7 +89,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } match t.sty { ty::ty_uniq(typ) if !type_needs_drop(tcx, typ) - && ty::type_is_sized(tcx, typ) => { + && type_is_sized(tcx, typ) => { let llty = sizing_type_of(ccx, typ); // `Box<ZeroSizeType>` does not allocate. if llsize_of_alloc(ccx, llty) == 0 { @@ -150,7 +150,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val _ => { } } - let llty = if ty::type_is_sized(ccx.tcx(), t) { + let llty = if type_is_sized(ccx.tcx(), t) { type_of(ccx, t).ptr_to() } else { type_of(ccx, ty::mk_uniq(ccx.tcx(), t)).ptr_to() @@ -193,7 +193,7 @@ fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, substs: &subst::Substs<'tcx>) -> Block<'blk, 'tcx> { let repr = adt::represent_type(bcx.ccx(), t); - let struct_data = if ty::type_is_sized(bcx.tcx(), t) { + let struct_data = if type_is_sized(bcx.tcx(), t) { v0 } else { let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); @@ -234,7 +234,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.ty_to_string(fty))[]) }; - let (struct_data, info) = if ty::type_is_sized(bcx.tcx(), t) { + let (struct_data, info) = if type_is_sized(bcx.tcx(), t) { (v0, None) } else { let data = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); @@ -251,7 +251,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Class dtors have no explicit args, so the params should // just consist of the environment (self). assert_eq!(params.len(), 1); - let self_arg = if ty::type_is_fat_ptr(bcx.tcx(), self_ty) { + let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) { // The dtor expects a fat pointer, so make one, even if we have to fake it. let boxed_ty = ty::mk_open(bcx.tcx(), t); let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self"); @@ -275,7 +275,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, for (i, ty) in st.fields.iter().enumerate().rev() { let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false); - let val = if ty::type_is_sized(bcx.tcx(), *ty) { + let val = if type_is_sized(bcx.tcx(), *ty) { llfld_a } else { let boxed_ty = ty::mk_open(bcx.tcx(), *ty); @@ -303,7 +303,7 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: -> (ValueRef, ValueRef) { debug!("calculate size of DST: {}; with lost info: {}", bcx.ty_to_string(t), bcx.val_to_string(info)); - if ty::type_is_sized(bcx.tcx(), t) { + if type_is_sized(bcx.tcx(), t) { let sizing_type = sizing_type_of(bcx.ccx(), t); let size = C_uint(bcx.ccx(), llsize_of_alloc(bcx.ccx(), sizing_type)); let align = C_uint(bcx.ccx(), align_of(bcx.ccx(), t)); @@ -383,7 +383,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) bcx }) } - ty::ty_struct(..) if !ty::type_is_sized(bcx.tcx(), content_ty) => { + ty::ty_struct(..) if !type_is_sized(bcx.tcx(), content_ty) => { let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]); let llbox = Load(bcx, llval); let not_null = IsNotNull(bcx, llbox); @@ -396,7 +396,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) }) } _ => { - assert!(ty::type_is_sized(bcx.tcx(), content_ty)); + assert!(type_is_sized(bcx.tcx(), content_ty)); let llval = v0; let llbox = Load(bcx, llval); let not_null = IsNotNull(bcx, llbox); @@ -415,7 +415,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) // find the drop flag (which is at the end of the struct). // Lets just ignore the flag and pretend everything will be // OK. - if ty::type_is_sized(bcx.tcx(), t) { + if type_is_sized(bcx.tcx(), t) { trans_struct_drop_flag(bcx, t, v0, dtor, did, substs) } else { // Give the user a heads up that we are doing something @@ -468,7 +468,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) } ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false), _ => { - assert!(ty::type_is_sized(bcx.tcx(), t)); + assert!(type_is_sized(bcx.tcx(), t)); if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None)) diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index f471a92f6c3..6b0baa5d05e 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -120,8 +120,8 @@ pub fn check_intrinsics(ccx: &CrateContext) { "s" })[]); } - if ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) || - ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) { + if type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) || + type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) { ccx.sess() .add_lint(::lint::builtin::FAT_PTR_TRANSMUTES, transmute_restriction.id, diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 499195b51b9..aaec82bb177 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -187,7 +187,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } let llsizingty = match t.sty { - _ if !ty::lltype_is_sized(cx.tcx(), t) => { + _ if !lltype_is_sized(cx.tcx(), t) => { cx.sess().bug(format!("trying to take the sizing type of {}, an unsized type", ppaux::ty_to_string(cx.tcx(), t))[]) } @@ -199,7 +199,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ ty::ty_float(t) => Type::float_from_ty(cx, t), ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => { - if ty::type_is_sized(cx.tcx(), ty) { + if type_is_sized(cx.tcx(), ty) { Type::i8p(cx) } else { Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) @@ -267,11 +267,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // struct which might be unsized, but is monomorphised to a sized type. // In this case we'll fake a fat pointer with no unsize info (we use 0). // However, its still a fat pointer, so we need some type use. - if ty::type_is_sized(cx.tcx(), t) { + if type_is_sized(cx.tcx(), t) { return Type::i8p(cx); } - match ty::unsized_part_of_type(cx.tcx(), t).sty { + match unsized_part_of_type(cx.tcx(), t).sty { ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyU), ty::ty_trait(_) => Type::vtable_ptr(cx), _ => panic!("Unexpected type returned from unsized_part_of_type : {}", @@ -342,7 +342,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { cx.tn().find_type("str_slice").unwrap() } ty::ty_trait(..) => Type::opaque_trait(cx), - _ if !ty::type_is_sized(cx.tcx(), ty) => { + _ if !type_is_sized(cx.tcx(), ty) => { let p_ty = type_of(cx, ty).ptr_to(); Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c8c8211f292..dfa41c2707e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1356,7 +1356,7 @@ fn check_cast(fcx: &FnCtxt, return } - if !ty::type_is_sized(fcx.tcx(), t_1) { + if !fcx.type_is_known_to_be_sized(t_1) { let tstr = fcx.infcx().ty_to_string(t_1); fcx.type_error_message(span, |actual| { format!("cast to unsized type: `{}` as `{}`", actual, tstr) @@ -1545,10 +1545,14 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx } - pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> { + pub fn infcx(&self) -> &infer::InferCtxt<'a, 'tcx> { &self.inh.infcx } + pub fn param_env(&self) -> &ty::ParameterEnvironment<'tcx> { + &self.inh.param_env + } + pub fn sess(&self) -> &Session { &self.tcx().sess } @@ -1792,6 +1796,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized(self.expr_ty(expr), expr.span, code); } + pub fn type_is_known_to_be_sized(&self, + ty: Ty<'tcx>) + -> bool + { + traits::type_known_to_meet_builtin_bound(self.infcx(), + self.param_env(), + ty, + ty::BoundSized) + } + pub fn register_builtin_bound(&self, ty: Ty<'tcx>, builtin_bound: ty::BuiltinBound, |
