diff --git a/src/doc/reference.md b/src/doc/reference.md index 6536172e2da..dfdadb3546b 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2279,8 +2279,6 @@ These types help drive the compiler's analysis : The lifetime parameter should be considered invariant * `malloc` : Allocate memory on the managed heap. -* `opaque` - : ___Needs filling in___ * `owned_box` : ___Needs filling in___ * `stack_exhausted` @@ -2295,8 +2293,6 @@ These types help drive the compiler's analysis : The type parameter should be considered invariant * `ty_desc` : ___Needs filling in___ -* `ty_visitor` - : ___Needs filling in___ > **Note:** This list is likely to become out of date. We should auto-generate > it from `librustc/middle/lang_items.rs`. diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 2586fdc60d5..3d593a0d026 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -65,11 +65,14 @@ pub struct TyDesc { pub name: &'static str, } +#[cfg(stage0)] #[lang="opaque"] pub enum Opaque { } +#[cfg(stage0)] pub type Disr = u64; +#[cfg(stage0)] #[lang="ty_visitor"] pub trait TyVisitor { fn visit_bot(&mut self) -> bool; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 3c9ebd86b94..68411549c3c 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -284,7 +284,6 @@ lets_do_this! { StartFnLangItem, "start", start_fn; TyDescStructLangItem, "ty_desc", ty_desc; - TyVisitorTraitLangItem, "ty_visitor", ty_visitor; OpaqueStructLangItem, "opaque", opaque; TypeIdLangItem, "type_id", type_id; diff --git a/src/librustc/middle/trans/mod.rs b/src/librustc/middle/trans/mod.rs index f95825c96db..fe7697447ac 100644 --- a/src/librustc/middle/trans/mod.rs +++ b/src/librustc/middle/trans/mod.rs @@ -36,7 +36,6 @@ pub mod cabi_arm; pub mod cabi_mips; pub mod foreign; pub mod intrinsic; -pub mod reflect; pub mod debuginfo; pub mod machine; pub mod adt; diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs deleted file mode 100644 index 96c2c1f1450..00000000000 --- a/src/librustc/middle/trans/reflect.rs +++ /dev/null @@ -1,458 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use back::link::mangle_internal_name_by_path_and_seq; -use llvm::{ValueRef, get_param}; -use middle::trans::adt; -use middle::trans::base::*; -use middle::trans::build::*; -use middle::trans::callee::ArgVals; -use middle::trans::callee; -use middle::trans::common::*; -use middle::trans::datum::*; -use middle::trans::machine; -use middle::trans::meth; -use middle::trans::type_::Type; -use middle::trans::type_of::*; -use middle::ty; -use util::ppaux::ty_to_string; - -use arena::TypedArena; -use libc::c_uint; -use syntax::ast::DefId; -use syntax::ast; -use syntax::ast_map; -use syntax::parse::token::{InternedString, special_idents}; -use syntax::parse::token; - -pub struct Reflector<'a, 'blk, 'tcx: 'blk> { - visitor_val: ValueRef, - visitor_items: &'a [ty::ImplOrTraitItem], - final_bcx: Block<'blk, 'tcx>, - tydesc_ty: Type, - bcx: Block<'blk, 'tcx> -} - -impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> { - pub fn c_uint(&mut self, u: uint) -> ValueRef { - C_uint(self.bcx.ccx(), u) - } - - pub fn c_bool(&mut self, b: bool) -> ValueRef { - C_bool(self.bcx.ccx(), b) - } - - pub fn c_slice(&mut self, s: InternedString) -> ValueRef { - // We're careful to not use first class aggregates here because that - // will kick us off fast isel. (Issue #4352.) - let bcx = self.bcx; - let str_ty = ty::mk_str_slice(bcx.tcx(), ty::ReStatic, ast::MutImmutable); - let scratch = rvalue_scratch_datum(bcx, str_ty, ""); - let len = C_uint(bcx.ccx(), s.get().len()); - let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s, false), Type::i8p(bcx.ccx())); - Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ])); - Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ])); - scratch.val - } - - pub fn c_size_and_align(&mut self, t: ty::t) -> Vec { - let tr = type_of(self.bcx.ccx(), t); - let s = machine::llsize_of_real(self.bcx.ccx(), tr); - let a = align_of(self.bcx.ccx(), t); - return vec!(self.c_uint(s as uint), - self.c_uint(a as uint)); - } - - pub fn c_tydesc(&mut self, t: ty::t) -> ValueRef { - let bcx = self.bcx; - let static_ti = get_tydesc(bcx.ccx(), t); - PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to()) - } - - pub fn c_mt(&mut self, mt: &ty::mt) -> Vec { - vec!(self.c_uint(mt.mutbl as uint), - self.c_tydesc(mt.ty)) - } - - pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) { - let fcx = self.bcx.fcx; - let tcx = self.bcx.tcx(); - let mth_idx = ty::impl_or_trait_item_idx(token::str_to_ident(format!( - "visit_{}", ty_name).as_slice()), - self.visitor_items.as_slice()).expect( - format!("couldn't find visit method for {}", ty_name).as_slice()); - let method = match self.visitor_items[mth_idx] { - ty::MethodTraitItem(ref method) => (*method).clone(), - ty::TypeTraitItem(_) => return, - }; - let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone()); - debug!("Emit call visit method: visit_{}: {}", ty_name, ty_to_string(tcx, mth_ty)); - let v = self.visitor_val; - debug!("passing {} args:", args.len()); - let mut bcx = self.bcx; - for (i, a) in args.iter().enumerate() { - debug!("arg {}: {}", i, bcx.val_to_string(*a)); - } - let result = unpack_result!(bcx, callee::trans_call_inner( - self.bcx, None, mth_ty, - |bcx, _| meth::trans_trait_callee_from_llval(bcx, - mth_ty, - mth_idx, - v), - ArgVals(args), None)); - let next_bcx = fcx.new_temp_block("next"); - CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb); - self.bcx = next_bcx - } - - pub fn bracketed(&mut self, - bracket_name: &str, - extra: &[ValueRef], - inner: |&mut Reflector|) { - self.visit(format!("enter_{}", bracket_name).as_slice(), extra); - inner(self); - self.visit(format!("leave_{}", bracket_name).as_slice(), extra); - } - - pub fn leaf(&mut self, name: &str) { - self.visit(name, []); - } - - fn visit_closure_ty(&mut self, fty: &ty::ClosureTy, is_unboxed: bool) { - let pureval = ast_fn_style_constant(fty.fn_style); - let sigilval = match fty.store { - ty::UniqTraitStore => 2u, - ty::RegionTraitStore(..) => 4u, - }; - let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; - let extra = vec!(self.c_uint(pureval), - self.c_uint(sigilval), - self.c_uint(fty.sig.inputs.len()), - self.c_uint(retval)); - self.visit("enter_fn", extra.as_slice()); - self.visit_sig(retval, &fty.sig, is_unboxed); - self.visit("leave_fn", extra.as_slice()); - } - - // Entrypoint - pub fn visit_ty(&mut self, t: ty::t) { - let bcx = self.bcx; - let tcx = bcx.tcx(); - debug!("reflect::visit_ty {}", ty_to_string(bcx.tcx(), t)); - - match ty::get(t).sty { - ty::ty_bot => self.leaf("bot"), - ty::ty_nil => self.leaf("nil"), - ty::ty_bool => self.leaf("bool"), - ty::ty_char => self.leaf("char"), - ty::ty_int(ast::TyI) => self.leaf("int"), - ty::ty_int(ast::TyI8) => self.leaf("i8"), - ty::ty_int(ast::TyI16) => self.leaf("i16"), - ty::ty_int(ast::TyI32) => self.leaf("i32"), - ty::ty_int(ast::TyI64) => self.leaf("i64"), - ty::ty_uint(ast::TyU) => self.leaf("uint"), - ty::ty_uint(ast::TyU8) => self.leaf("u8"), - ty::ty_uint(ast::TyU16) => self.leaf("u16"), - ty::ty_uint(ast::TyU32) => self.leaf("u32"), - ty::ty_uint(ast::TyU64) => self.leaf("u64"), - ty::ty_float(ast::TyF32) => self.leaf("f32"), - ty::ty_float(ast::TyF64) => self.leaf("f64"), - - ty::ty_open(_) | ty::ty_str | ty::ty_vec(_, None) | ty::ty_trait(..) => { - // Unfortunately we can't do anything here because at runtime we - // pass around the value by pointer (*u8). But unsized pointers are - // fat and so we can't just cast them to *u8 and back. So we have - // to work with the pointer directly (see ty_ptr/ty_rptr/ty_uniq). - fail!("Can't reflect unsized type") - } - // FIXME(15049) Reflection for unsized structs. - ty::ty_struct(..) if !ty::type_is_sized(bcx.tcx(), t) => { - fail!("Can't reflect unsized type") - } - - // Should rename to vec_*. - ty::ty_vec(ty, Some(sz)) => { - let mut extra = (vec!(self.c_uint(sz))).append(self.c_size_and_align(t).as_slice()); - extra.push(self.c_tydesc(ty)); - self.visit("evec_fixed", extra.as_slice()) - } - ty::ty_ptr(ref mt) => { - match ty::get(mt.ty).sty { - ty::ty_vec(ty, None) => { - let extra = self.c_mt(&ty::mt{ty: ty, mutbl: mt.mutbl}); - self.visit("evec_slice", extra.as_slice()) - } - ty::ty_str => self.visit("estr_slice", &[]), - ty::ty_trait(..) => { - let extra = [ - self.c_slice(token::intern_and_get_ident( - ty_to_string(tcx, t).as_slice())) - ]; - self.visit("trait", extra); - } - _ => { - let extra = self.c_mt(mt); - self.visit("ptr", extra.as_slice()) - } - } - } - ty::ty_uniq(typ) => { - match ty::get(typ).sty { - ty::ty_trait(..) => { - let extra = [ - self.c_slice(token::intern_and_get_ident( - ty_to_string(tcx, t).as_slice())) - ]; - self.visit("trait", extra); - } - // FIXME(15049) allow reflection of Box<[T]>. You'll need to - // restore visit_evec_uniq. - ty::ty_vec(_, None) => { - fail!("Box<[T]> theoretically doesn't exist, so don't try to reflect it") - } - ty::ty_str => fail!("Can't reflect Box which shouldn't be used anyway"), - _ => { - let extra = self.c_mt(&ty::mt { - ty: typ, - mutbl: ast::MutImmutable, - }); - self.visit("uniq", extra.as_slice()) - } - } - } - ty::ty_rptr(_, ref mt) => { - match ty::get(mt.ty).sty { - ty::ty_vec(ty, None) => { - let extra = self.c_mt(&ty::mt{ty: ty, mutbl: mt.mutbl}); - self.visit("evec_slice", extra.as_slice()) - } - ty::ty_str => self.visit("estr_slice", &[]), - ty::ty_trait(..) => { - let extra = [ - self.c_slice(token::intern_and_get_ident( - ty_to_string(tcx, t).as_slice())) - ]; - self.visit("trait", extra); - } - _ => { - let extra = self.c_mt(mt); - self.visit("rptr", extra.as_slice()) - } - } - } - - ty::ty_tup(ref tys) => { - let extra = (vec!(self.c_uint(tys.len()))) - .append(self.c_size_and_align(t).as_slice()); - self.bracketed("tup", extra.as_slice(), |this| { - for (i, t) in tys.iter().enumerate() { - let extra = vec!(this.c_uint(i), this.c_tydesc(*t)); - this.visit("tup_field", extra.as_slice()); - } - }) - } - - // FIXME (#2594): fetch constants out of intrinsic - // FIXME (#4809): visitor should break out bare fns from other fns - ty::ty_closure(box ref fty) => { - self.visit_closure_ty(fty, false); - } - - // FIXME (#2594): fetch constants out of intrinsic:: for the - // numbers. - ty::ty_bare_fn(ref fty) => { - let pureval = ast_fn_style_constant(fty.fn_style); - let sigilval = 0u; - let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; - let extra = vec!(self.c_uint(pureval), - self.c_uint(sigilval), - self.c_uint(fty.sig.inputs.len()), - self.c_uint(retval)); - self.visit("enter_fn", extra.as_slice()); - self.visit_sig(retval, &fty.sig, false); - self.visit("leave_fn", extra.as_slice()); - } - - ty::ty_struct(did, ref substs) => { - let fields = ty::struct_fields(tcx, did, substs); - let mut named_fields = false; - if !fields.is_empty() { - named_fields = fields.get(0).ident.name != - special_idents::unnamed_field.name; - } - - // This and the type_is_sized check on individual field types are - // because we cannot reflect unsized types (see note above). We - // just pretend the unsized field does not exist and print nothing. - // This is sub-optimal. - let len = fields.len(); - - let extra = (vec!( - self.c_slice( - token::intern_and_get_ident(ty_to_string(tcx, - t).as_slice())), - self.c_bool(named_fields), - self.c_uint(len) - )).append(self.c_size_and_align(t).as_slice()); - self.bracketed("class", extra.as_slice(), |this| { - for (i, field) in fields.iter().enumerate() { - let extra = (vec!( - this.c_uint(i), - this.c_slice(token::get_ident(field.ident)), - this.c_bool(named_fields) - )).append(this.c_mt(&field.mt).as_slice()); - this.visit("class_field", extra.as_slice()); - } - }) - } - - // FIXME (#2595): visiting all the variants in turn is probably - // not ideal. It'll work but will get costly on big enums. Maybe - // let the visitor tell us if it wants to visit only a particular - // variant? - ty::ty_enum(did, ref substs) => { - let ccx = bcx.ccx(); - let repr = adt::represent_type(bcx.ccx(), t); - let variants = ty::substd_enum_variants(ccx.tcx(), did, substs); - let llptrty = type_of(ccx, t).ptr_to(); - let opaquety = ty::get_opaque_ty(ccx.tcx()).unwrap(); - let opaqueptrty = ty::mk_ptr(ccx.tcx(), ty::mt { ty: opaquety, - mutbl: ast::MutImmutable }); - - let make_get_disr = || { - let sym = mangle_internal_name_by_path_and_seq( - ast_map::Values([].iter()).chain(None), "get_disr"); - - let fn_ty = ty::mk_ctor_fn(ccx.tcx(), ast::DUMMY_NODE_ID, - [opaqueptrty], ty::mk_u64()); - let llfdecl = decl_internal_rust_fn(ccx, - fn_ty, - sym.as_slice()); - let arena = TypedArena::new(); - let empty_param_substs = param_substs::empty(); - let fcx = new_fn_ctxt(ccx, llfdecl, ast::DUMMY_NODE_ID, false, - ty::mk_u64(), &empty_param_substs, - None, &arena); - let bcx = init_function(&fcx, false, ty::mk_u64()); - - // we know the return type of llfdecl is an int here, so - // no need for a special check to see if the return type - // is immediate. - let arg = get_param(llfdecl, fcx.arg_pos(0u) as c_uint); - let arg = BitCast(bcx, arg, llptrty); - let ret = adt::trans_get_discr(bcx, &*repr, arg, Some(Type::i64(ccx))); - assert!(!fcx.needs_ret_allocas); - let ret_slot = fcx.get_ret_slot(bcx, ty::mk_u64(), "ret_slot"); - Store(bcx, ret, ret_slot); - match fcx.llreturn.get() { - Some(llreturn) => Br(bcx, llreturn), - None => {} - }; - finish_fn(&fcx, bcx, ty::mk_u64()); - llfdecl - }; - - let enum_args = (vec!(self.c_uint(variants.len()), make_get_disr())) - .append(self.c_size_and_align(t).as_slice()); - self.bracketed("enum", enum_args.as_slice(), |this| { - for (i, v) in variants.iter().enumerate() { - let name = token::get_ident(v.name); - let variant_args = [this.c_uint(i), - C_u64(ccx, v.disr_val), - this.c_uint(v.args.len()), - this.c_slice(name)]; - this.bracketed("enum_variant", - variant_args, - |this| { - for (j, a) in v.args.iter().enumerate() { - let bcx = this.bcx; - let null = C_null(llptrty); - let ptr = adt::trans_field_ptr(bcx, &*repr, null, v.disr_val, j); - let offset = p2i(ccx, ptr); - let field_args = [this.c_uint(j), - offset, - this.c_tydesc(*a)]; - this.visit("enum_variant_field", - field_args); - } - }) - } - }) - } - - // Miscellaneous extra types - ty::ty_infer(_) => self.leaf("infer"), - ty::ty_err => self.leaf("err"), - ty::ty_unboxed_closure(ref def_id, _) => { - let closure_map = tcx.unboxed_closures.borrow(); - let fty = &closure_map.find(def_id).unwrap().closure_type; - self.visit_closure_ty(fty, true); - } - ty::ty_param(ref p) => { - let extra = vec!(self.c_uint(p.idx)); - self.visit("param", extra.as_slice()) - } - } - } - - pub fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig, is_unboxed: bool) { - let args = if is_unboxed { - match ty::get(sig.inputs[0]).sty { - ty::ty_tup(ref contents) => contents.iter(), - ty::ty_nil => [].iter(), - _ => unreachable!() - } - } else { - sig.inputs.iter() - }; - - for (i, arg) in args.enumerate() { - let modeval = 5u; // "by copy" - let extra = vec!(self.c_uint(i), - self.c_uint(modeval), - self.c_tydesc(*arg)); - self.visit("fn_input", extra.as_slice()); - } - let extra = vec!(self.c_uint(retval), - self.c_bool(sig.variadic), - self.c_tydesc(sig.output)); - self.visit("fn_output", extra.as_slice()); - } -} - -// Emit a sequence of calls to visit_ty::visit_foo -pub fn emit_calls_to_trait_visit_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - t: ty::t, - visitor_val: ValueRef, - visitor_trait_id: DefId) - -> Block<'blk, 'tcx> { - let fcx = bcx.fcx; - let final_bcx = fcx.new_temp_block("final"); - let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap(); - let tydesc_ty = type_of(bcx.ccx(), tydesc_ty); - let visitor_items = ty::trait_items(bcx.tcx(), visitor_trait_id); - let mut r = Reflector { - visitor_val: visitor_val, - visitor_items: visitor_items.as_slice(), - final_bcx: final_bcx, - tydesc_ty: tydesc_ty, - bcx: bcx - }; - r.visit_ty(t); - Br(r.bcx, final_bcx.llbb); - return final_bcx; -} - -pub fn ast_fn_style_constant(fn_style: ast::FnStyle) -> uint { - match fn_style { - ast::UnsafeFn => 1u, - ast::NormalFn => 2u, - } -} diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d026b31b914..b84bfe95224 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -18,8 +18,7 @@ use middle::const_eval; use middle::def; use middle::dependency_format; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem}; -use middle::lang_items::{FnOnceTraitLangItem, OpaqueStructLangItem}; -use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem}; +use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem}; use middle::mem_categorization as mc; use middle::resolve; use middle::resolve_lifetime; @@ -4821,33 +4820,6 @@ pub fn get_tydesc_ty(tcx: &ctxt) -> Result { }) } -pub fn get_opaque_ty(tcx: &ctxt) -> Result { - tcx.lang_items.require(OpaqueStructLangItem).map(|opaque_lang_item| { - tcx.intrinsic_defs.borrow().find_copy(&opaque_lang_item) - .expect("Failed to resolve Opaque") - }) -} - -pub fn visitor_object_ty(tcx: &ctxt, - ptr_region: ty::Region, - trait_region: ty::Region) - -> Result<(Rc, t), String> -{ - let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) { - Ok(id) => id, - Err(s) => { return Err(s); } - }; - let substs = Substs::empty(); - let trait_ref = Rc::new(TraitRef { def_id: trait_lang_item, substs: substs }); - Ok((trait_ref.clone(), - mk_rptr(tcx, ptr_region, - mt {mutbl: ast::MutMutable, - ty: mk_trait(tcx, - trait_ref.def_id, - trait_ref.substs.clone(), - ty::region_existential_bound(trait_region))}))) -} - pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc { lookup_locally_or_in_crate_store( "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),