diff --git a/src/libextra/uuid.rs b/src/libextra/uuid.rs index 9163a89203913..cefd94377d7ae 100644 --- a/src/libextra/uuid.rs +++ b/src/libextra/uuid.rs @@ -58,7 +58,6 @@ Examples of string representations: use std::str; use std::vec; use std::num::FromStrRadix; -use std::char::Char; use std::container::Container; use std::to_str::ToStr; use std::rand; diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 09531e80ae59c..3a11fd0043da3 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -208,6 +208,11 @@ pub static tag_macro_registrar_fn: uint = 0x110; pub static tag_exported_macros: uint = 0x111; pub static tag_macro_def: uint = 0x112; +pub static tag_prim_dids: uint = 0x113; +pub static tag_prim_did: uint = 0x114; +pub static tag_prim_did_ty: uint = 0x115; +pub static tag_prim_did_did: uint = 0x116; + #[deriving(Clone)] pub struct LinkMeta { crateid: CrateId, diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index ea55e0d3d7297..1eb0e687d901b 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -311,3 +311,10 @@ pub fn get_exported_macros(cstore: @cstore::CStore, let cdata = cstore.get_crate_data(crate_num); decoder::get_exported_macros(cdata) } + +pub fn prim_dids(cstore: @cstore::CStore, + crate_num: ast::CrateNum, + tcx: ty::ctxt) -> ~[(ty::t, ast::DefId)] { + let cdata = cstore.get_crate_data(crate_num); + decoder::prim_dids(cdata, tcx) +} diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index abf5b051c7de7..cc690c40402e6 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1292,3 +1292,19 @@ pub fn get_exported_macros(cdata: Cmd) -> ~[@ast::Item] { }); result } + +pub fn prim_dids(cdata: Cmd, tcx: ty::ctxt) -> ~[(ty::t, ast::DefId)] { + let dids = reader::get_doc(reader::Doc(cdata.data()), tag_prim_dids); + let mut result = ~[]; + reader::tagged_docs(dids, tag_prim_did, |did_doc| { + let ty_doc = reader::get_doc(did_doc, tag_prim_did_ty); + let id_doc = reader::get_doc(did_doc, tag_prim_did_did); + let did = ast::DefId { + node: reader::doc_as_u32(id_doc), + crate: cdata.cnum, + }; + result.push((doc_type(ty_doc, tcx, cdata), did)); + true + }); + return result; +} diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a7c82ba431778..ba9af6bb64fba 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -82,6 +82,7 @@ struct Stats { macro_registrar_fn_bytes: Cell, macro_defs_bytes: Cell, impl_bytes: Cell, + prim_did_bytes: Cell, misc_bytes: Cell, item_bytes: Cell, index_bytes: Cell, @@ -1455,6 +1456,21 @@ fn encode_info_for_items(ecx: &EncodeContext, visit::walk_crate(&mut visitor, crate, ()); } + for (_, did) in ty::prim_dids(ecx.tcx).move_iter() { + if !ast_util::is_local(did) { continue } + { + let mut index = index.borrow_mut(); + index.get().push(entry { + val: did.node as i64, + pos: ebml_w.writer.tell(), + }); + } + ebml_w.start_tag(tag_items_data_item); + encode_def_id(ebml_w, did); + encode_inherent_implementations(ecx, ebml_w, did); + ebml_w.end_tag(); + } + ebml_w.end_tag(); return /*bad*/(*index).get(); } @@ -1818,6 +1834,23 @@ fn encode_misc_info(ecx: &EncodeContext, ebml_w.end_tag(); } +fn encode_prim_dids(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) { + ebml_w.start_tag(tag_prim_dids); + for (ty, did) in ty::prim_dids(ecx.tcx).move_iter() { + if !ast_util::is_local(did) { continue } + ebml_w.start_tag(tag_prim_did); + + ebml_w.start_tag(tag_prim_did_ty); + encode_type(ecx, ebml_w, ty); + ebml_w.end_tag(); + + ebml_w.wr_tagged_u32(tag_prim_did_did, did.node); + + ebml_w.end_tag(); + } + ebml_w.end_tag(); +} + fn encode_crate_dep(ecx: &EncodeContext, ebml_w: &mut writer::Encoder, dep: decoder::CrateDep) { @@ -1865,6 +1898,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) macro_registrar_fn_bytes: Cell::new(0), macro_defs_bytes: Cell::new(0), impl_bytes: Cell::new(0), + prim_did_bytes: Cell::new(0), misc_bytes: Cell::new(0), item_bytes: Cell::new(0), index_bytes: Cell::new(0), @@ -1937,6 +1971,11 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) encode_impls(&ecx, crate, &mut ebml_w); ecx.stats.impl_bytes.set(ebml_w.writer.tell() - i); + // Encode the def IDs of primitives (if we have any) + i = ebml_w.writer.tell(); + encode_prim_dids(&ecx, &mut ebml_w); + ecx.stats.prim_did_bytes.set(ebml_w.writer.tell() - i); + // Encode miscellaneous info. i = ebml_w.writer.tell(); encode_misc_info(&ecx, crate, &mut ebml_w); @@ -1969,6 +2008,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) println!(" dep bytes: {}", ecx.stats.dep_bytes.get()); println!(" lang item bytes: {}", ecx.stats.lang_item_bytes.get()); println!(" native bytes: {}", ecx.stats.native_lib_bytes.get()); + println!(" prim did bytes: {}", ecx.stats.prim_did_bytes.get()); println!("macro registrar bytes: {}", ecx.stats.macro_registrar_fn_bytes.get()); println!(" macro def bytes: {}", ecx.stats.macro_defs_bytes.get()); println!(" impl bytes: {}", ecx.stats.impl_bytes.get()); diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index d11cd4b3f3819..b9f76a59435ac 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -33,41 +33,28 @@ use std::hashmap::HashMap; use std::iter::Enumerate; use std::vec; - -// Get the last "argument" (has to be done recursively to avoid phoney local ambiguity error) -macro_rules! last { - ( $first:expr, $( $remainder:expr, )+ ) => ( last!( $( $remainder, )+ ) ); - ( $first:expr, ) => ( $first ) -} - // The actual lang items defined come at the end of this file in one handy table. // So you probably just want to nip down to the end. macro_rules! lets_do_this { - // secondary rule to allow us to use `$num` as both an expression - // and a pattern. ( - $( $num:tt, $variant:ident, $name:expr, $method:ident; )* - ) => { - lets_do_this!(count = 1 + last!($($num,)*), - $($num, $variant, $name, $method; )*) - }; - - ( - count = $num_lang_items:expr, $( $num:pat, $variant:ident, $name:expr, $method:ident; )* + $( $variant:ident, $name:expr, $method:ident; )* ) => { +#[deriving(FromPrimitive)] pub enum LangItem { $($variant),* } pub struct LanguageItems { - items: [Option, ..$num_lang_items] + items: ~[Option], } impl LanguageItems { pub fn new() -> LanguageItems { + fn foo(_: LangItem) -> Option { None } + LanguageItems { - items: [ None, ..$num_lang_items ] + items: ~[$(foo($variant)),*] } } @@ -76,9 +63,10 @@ impl LanguageItems { } pub fn item_name(index: uint) -> &'static str { - match index { - $( $num => $name, )* - _ => "???" + let item: Option = FromPrimitive::from_uint(index); + match item { + $( Some($variant) => $name, )* + None => "???" } } @@ -208,13 +196,12 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<@str> { } pub fn collect_language_items(crate: &ast::Crate, - session: Session) - -> LanguageItems { + session: Session) -> @LanguageItems { let mut collector = LanguageItemCollector::new(session); collector.collect(crate); let LanguageItemCollector { items, .. } = collector; session.abort_if_errors(); - items + @items } // End of the macro @@ -222,55 +209,71 @@ pub fn collect_language_items(crate: &ast::Crate, } lets_do_this! { -// ID, Variant name, Name, Method name; - 0, FreezeTraitLangItem, "freeze", freeze_trait; - 1, SendTraitLangItem, "send", send_trait; - 2, SizedTraitLangItem, "sized", sized_trait; - 3, PodTraitLangItem, "pod", pod_trait; - - 4, DropTraitLangItem, "drop", drop_trait; - - 5, AddTraitLangItem, "add", add_trait; - 6, SubTraitLangItem, "sub", sub_trait; - 7, MulTraitLangItem, "mul", mul_trait; - 8, DivTraitLangItem, "div", div_trait; - 9, RemTraitLangItem, "rem", rem_trait; - 10, NegTraitLangItem, "neg", neg_trait; - 11, NotTraitLangItem, "not", not_trait; - 12, BitXorTraitLangItem, "bitxor", bitxor_trait; - 13, BitAndTraitLangItem, "bitand", bitand_trait; - 14, BitOrTraitLangItem, "bitor", bitor_trait; - 15, ShlTraitLangItem, "shl", shl_trait; - 16, ShrTraitLangItem, "shr", shr_trait; - 17, IndexTraitLangItem, "index", index_trait; - - 18, EqTraitLangItem, "eq", eq_trait; - 19, OrdTraitLangItem, "ord", ord_trait; - - 20, StrEqFnLangItem, "str_eq", str_eq_fn; - 21, UniqStrEqFnLangItem, "uniq_str_eq", uniq_str_eq_fn; - 22, FailFnLangItem, "fail_", fail_fn; - 23, FailBoundsCheckFnLangItem, "fail_bounds_check", fail_bounds_check_fn; - 24, ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; - 25, ClosureExchangeMallocFnLangItem, "closure_exchange_malloc", closure_exchange_malloc_fn; - 26, ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn; - 27, MallocFnLangItem, "malloc", malloc_fn; - 28, FreeFnLangItem, "free", free_fn; - 29, StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn; - - 30, StartFnLangItem, "start", start_fn; - - 31, TyDescStructLangItem, "ty_desc", ty_desc; - 32, TyVisitorTraitLangItem, "ty_visitor", ty_visitor; - 33, OpaqueStructLangItem, "opaque", opaque; - - 34, EventLoopFactoryLangItem, "event_loop_factory", event_loop_factory; - - 35, TypeIdLangItem, "type_id", type_id; - - 36, EhPersonalityLangItem, "eh_personality", eh_personality_fn; - - 37, ManagedHeapLangItem, "managed_heap", managed_heap; - 38, ExchangeHeapLangItem, "exchange_heap", exchange_heap; - 39, GcLangItem, "gc", gc; +// Variant name, Name, Method name; + FreezeTraitLangItem, "freeze", freeze_trait; + SendTraitLangItem, "send", send_trait; + SizedTraitLangItem, "sized", sized_trait; + PodTraitLangItem, "pod", pod_trait; + + DropTraitLangItem, "drop", drop_trait; + + AddTraitLangItem, "add", add_trait; + SubTraitLangItem, "sub", sub_trait; + MulTraitLangItem, "mul", mul_trait; + DivTraitLangItem, "div", div_trait; + RemTraitLangItem, "rem", rem_trait; + NegTraitLangItem, "neg", neg_trait; + NotTraitLangItem, "not", not_trait; + BitXorTraitLangItem, "bitxor", bitxor_trait; + BitAndTraitLangItem, "bitand", bitand_trait; + BitOrTraitLangItem, "bitor", bitor_trait; + ShlTraitLangItem, "shl", shl_trait; + ShrTraitLangItem, "shr", shr_trait; + IndexTraitLangItem, "index", index_trait; + + EqTraitLangItem, "eq", eq_trait; + OrdTraitLangItem, "ord", ord_trait; + + StrEqFnLangItem, "str_eq", str_eq_fn; + UniqStrEqFnLangItem, "uniq_str_eq", uniq_str_eq_fn; + FailFnLangItem, "fail_", fail_fn; + FailBoundsCheckFnLangItem, "fail_bounds_check", fail_bounds_check_fn; + ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn; + ClosureExchangeMallocFnLangItem, "closure_exchange_malloc", closure_exchange_malloc_fn; + ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn; + MallocFnLangItem, "malloc", malloc_fn; + FreeFnLangItem, "free", free_fn; + StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn; + + StartFnLangItem, "start", start_fn; + + TyDescStructLangItem, "ty_desc", ty_desc; + TyVisitorTraitLangItem, "ty_visitor", ty_visitor; + OpaqueStructLangItem, "opaque", opaque; + + EventLoopFactoryLangItem, "event_loop_factory", event_loop_factory; + + TypeIdLangItem, "type_id", type_id; + + ManagedHeapLangItem, "managed_heap", managed_heap; + ExchangeHeapLangItem, "exchange_heap", exchange_heap; + GcLangItem, "gc", gc; + + EhPersonalityLangItem, "eh_personality", eh_personality_fn; + + CharImplLangItem, "char_impl", char_impl; + IntImplLangItem, "int_impl", int_impl; + I8ImplLangItem, "i8_impl", i8_impl; + I16ImplLangItem, "i16_impl", i16_impl; + I32ImplLangItem, "i32_impl", i32_impl; + I64ImplLangItem, "i64_impl", i64_impl; + UintImplLangItem, "uint_impl", uint_impl; + U8ImplLangItem, "u8_impl", u8_impl; + U16ImplLangItem, "u16_impl", u16_impl; + U32ImplLangItem, "u32_impl", u32_impl; + U64ImplLangItem, "u64_impl", u64_impl; + BoolImplLangItem, "bool_impl", bool_impl; + NilImplLangItem, "nil_impl", nil_impl; + F32ImplLangItem, "f32_impl", f32_impl; + F64ImplLangItem, "f64_impl", f64_impl; } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 082c755b8321e..039b5534967ed 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -779,7 +779,7 @@ fn namespace_error_to_str(ns: NamespaceError) -> &'static str { } fn Resolver(session: Session, - lang_items: LanguageItems, + lang_items: @LanguageItems, crate_span: Span) -> Resolver { let graph_root = @NameBindings(); @@ -837,7 +837,7 @@ fn Resolver(session: Session, /// The main resolver class. struct Resolver { session: @Session, - lang_items: LanguageItems, + lang_items: @LanguageItems, intr: @IdentInterner, @@ -5656,7 +5656,7 @@ pub struct CrateMap { /// Entry point to crate resolution. pub fn resolve_crate(session: Session, - lang_items: LanguageItems, + lang_items: @LanguageItems, crate: &Crate) -> CrateMap { let mut resolver = Resolver(session, lang_items, crate.span); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 01fb18d73c26a..5ec89373d3e8f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -309,7 +309,7 @@ struct ctxt_ { ty_param_defs: RefCell>, adjustments: RefCell>, normalized_cache: RefCell>, - lang_items: middle::lang_items::LanguageItems, + lang_items: @middle::lang_items::LanguageItems, // A mapping of fake provided method def_ids to the default implementation provided_method_sources: RefCell>, supertraits: RefCell>, @@ -361,6 +361,9 @@ struct ctxt_ { // is used for lazy resolution of traits. populated_external_traits: RefCell>, + // TODO: dox + prim_dids: RefCell>, + // These two caches are used by const_eval when decoding external statics // and variants that are found. extern_const_statics: RefCell>>, @@ -957,7 +960,7 @@ pub fn mk_ctxt(s: session::Session, amap: ast_map::Map, freevars: freevars::freevar_map, region_maps: middle::region::RegionMaps, - lang_items: middle::lang_items::LanguageItems) + lang_items: @middle::lang_items::LanguageItems) -> ctxt { @ctxt_ { named_region_map: named_region_map, @@ -1003,6 +1006,7 @@ pub fn mk_ctxt(s: session::Session, impl_vtables: RefCell::new(HashMap::new()), populated_external_types: RefCell::new(HashSet::new()), populated_external_traits: RefCell::new(HashSet::new()), + prim_dids: RefCell::new(HashMap::new()), extern_const_statics: RefCell::new(HashMap::new()), extern_const_variants: RefCell::new(HashMap::new()), @@ -5012,3 +5016,39 @@ impl substs { } } } + +/// Register a primitive type as having its lang-item implementation in this +/// crate. This method will create a DefId if one doesn't already exist for it. +pub fn add_local_prim_did(tcx: ctxt, t: t) -> ast::DefId { + let mut map = tcx.prim_dids.borrow_mut(); + match map.get().find(&t) { + Some(&did) => return did, + None => {} + } + let id = tcx.next_id.get(); + tcx.next_id.set(id + 1); + map.get().insert(t, ast_util::local_def(id as ast::NodeId)); + return ast_util::local_def(id as ast::NodeId); +} + +/// Fetch the DefId of the lang-item implementation of a primitive type. This +/// may not succeed (as the local crate or linked crates may not provide an +/// implementation). +pub fn maybe_prim_did(tcx: ctxt, t: t) -> Option { + let map = tcx.prim_dids.borrow(); + map.get().find(&t).map(|&x| x) +} + +/// Adds the DefId of a lang-item implementation of a primitive from an external +/// crate. +pub fn add_extern_prim_did(tcx: ctxt, t: t, did: ast::DefId) { + let mut map = tcx.prim_dids.borrow_mut(); + assert!(map.get().insert(t, did)); +} + +/// Fetch all primitive type implementations known to this crate. This includes +/// local as well as external primitive types. +pub fn prim_dids(tcx: ctxt) -> ~[(t, ast::DefId)] { + let map = tcx.prim_dids.borrow(); + map.get().iter().map(|(&a, &b)| (a, b)).collect() +} diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 293442417d2be..6b7fb5c94c13a 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -295,6 +295,12 @@ impl<'a> LookupContext<'a> { */ let mut self_ty = self_ty; + macro_rules! add( ($t:expr) => ({ + match ty::maybe_prim_did(self.fcx.tcx(), $t) { + Some(did) => self.push_inherent_impl_candidates_for_type(did), + None => {} + } + }) ) loop { match get(self_ty).sty { ty_trait(did, ref substs, _, _, _) => { @@ -306,6 +312,26 @@ impl<'a> LookupContext<'a> { self.push_inherent_impl_candidates_for_type(did); } } + ty_nil | ty_bool | ty_char | ty_int(..) | ty_uint(..) | + ty_float(..) => { + add!(self_ty); + } + ty_infer(FloatVar(..)) => { + add!(ty::mk_f32()); + add!(ty::mk_f64()); + } + ty_infer(IntVar(..)) => { + add!(ty::mk_uint()); + add!(ty::mk_u8()); + add!(ty::mk_u16()); + add!(ty::mk_u32()); + add!(ty::mk_u64()); + add!(ty::mk_int()); + add!(ty::mk_i8()); + add!(ty::mk_i16()); + add!(ty::mk_i32()); + add!(ty::mk_i64()); + } _ => { /* No inherent methods in these types */ } } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 89c24cf411675..430c97fd0c249 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -35,7 +35,7 @@ use middle::typeck::infer::InferCtxt; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type}; use middle::typeck::infer; use util::ppaux::Repr; -use syntax::ast::{Crate, DefId, DefStruct, DefTy}; +use syntax::ast::{Crate, DefId, DefStruct, DefTy, DefPrimTy}; use syntax::ast::{Item, ItemEnum, ItemImpl, ItemMod, ItemStruct}; use syntax::ast::{LOCAL_CRATE, TraitRef, TyPath}; use syntax::ast; @@ -81,7 +81,12 @@ pub fn get_base_type(inference_context: @InferCtxt, Some(resolved_type) } - ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) | + ty_nil | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) => { + debug!("(getting base type) found primitive base type"); + Some(resolved_type) + } + + ty_bot | ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) | ty_infer(..) | ty_param(..) | ty_self(..) | ty_type | ty_opaque_closure_ptr(..) | ty_unboxed_vec(..) | ty_err | ty_box(_) | @@ -121,6 +126,7 @@ pub fn type_is_defined_in_local_crate(original_type: t) -> bool { // Returns the def ID of the base type, if there is one. pub fn get_base_type_def_id(inference_context: @InferCtxt, + id: ast::NodeId, span: Span, original_type: t) -> Option { @@ -129,17 +135,61 @@ pub fn get_base_type_def_id(inference_context: @InferCtxt, return None; } Some(base_type) => { + let did = local_def(id); + let li = inference_context.tcx.lang_items; match get(base_type).sty { ty_enum(def_id, _) | ty_struct(def_id, _) | ty_trait(def_id, _, _, _, _) => { return Some(def_id); } + + ty_char => { if li.char_impl() != Some(did) { return None } } + ty_nil => { if li.nil_impl() != Some(did) { return None } } + ty_bool => { if li.bool_impl() != Some(did) { return None } } + ty_float(ast::TyF32) => { + if li.f32_impl() != Some(did) { return None } + } + ty_float(ast::TyF64) => { + if li.f64_impl() != Some(did) { return None } + } + ty_uint(ast::TyU) => { + if li.uint_impl() != Some(did) { return None } + } + ty_int(ast::TyI) => { + if li.int_impl() != Some(did) { return None } + } + ty_int(ast::TyI8) => { + if li.i8_impl() != Some(did) { return None } + } + ty_int(ast::TyI16) => { + if li.i16_impl() != Some(did) { return None } + } + ty_int(ast::TyI32) => { + if li.i32_impl() != Some(did) { return None } + } + ty_int(ast::TyI64) => { + if li.i64_impl() != Some(did) { return None } + } + ty_uint(ast::TyU8) => { + if li.u8_impl() != Some(did) { return None } + } + ty_uint(ast::TyU16) => { + if li.u16_impl() != Some(did) { return None } + } + ty_uint(ast::TyU32) => { + if li.u32_impl() != Some(did) { return None } + } + ty_uint(ast::TyU64) => { + if li.u64_impl() != Some(did) { return None } + } + _ => { fail!("get_base_type() returned a type that wasn't an \ - enum, struct, or trait"); + enum, struct, trait, or known primitive"); } } + return Some(ty::add_local_prim_did(inference_context.tcx, base_type)); } } } @@ -273,7 +323,7 @@ impl CoherenceChecker { self.crate_context.tcx.sess.str_of(item.ident)); match get_base_type_def_id(self.inference_context, - item.span, + item.id, item.span, self_type.ty) { None => { let session = self.crate_context.tcx.sess; @@ -303,7 +353,7 @@ impl CoherenceChecker { // type def ID, if there is a base type for this implementation and // the implementation does not have any associated traits. match get_base_type_def_id(self.inference_context, - item.span, + item.id, item.span, self_type.ty) { None => { // Nothing to do. @@ -585,9 +635,12 @@ impl CoherenceChecker { Some(_) => false, } } + DefPrimTy(ast::TyStr) => false, + DefPrimTy(..) => true, _ => false } } + ast::TyNil => true, _ => false } } @@ -688,7 +741,12 @@ impl CoherenceChecker { each_impl(crate_store, crate_number, |def_id| { assert_eq!(crate_number, def_id.crate); self.add_external_impl(&mut impls_seen, def_id) - }) + }); + let prims = csearch::prim_dids(crate_store, crate_number, + self.crate_context.tcx); + for (t, did) in prims.move_iter() { + ty::add_extern_prim_did(self.crate_context.tcx, t, did); + } }) } diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index e48c0800506f9..b0b3cbef2c446 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -24,6 +24,7 @@ use syntax::codemap::Pos; use rustc::metadata::cstore; use rustc::metadata::csearch; use rustc::metadata::decoder; +use rustc::middle::ty; use std; use std::hashmap::HashMap; @@ -182,6 +183,7 @@ pub enum ItemEnum { VariantItem(Variant), ForeignFunctionItem(Function), ForeignStaticItem(Static), + PrimitiveType(ast::PrimTy), } #[deriving(Clone, Encodable, Decodable)] @@ -196,6 +198,8 @@ impl Clean for doctree::Module { } else { ~"" }; + let impls = self.impls.clean(); + let impls = impls.move_iter().flat_map(|i| i.move_iter()).collect(); Item { name: Some(name), attrs: self.attrs.clean(), @@ -207,7 +211,7 @@ impl Clean for doctree::Module { self.fns.clean(), self.foreigns.clean().concat_vec(), self.mods.clean(), self.typedefs.clean(), self.statics.clean(), self.traits.clean(), - self.impls.clean(), self.view_items.clean()].concat_vec() + impls, self.view_items.clean()].concat_vec() }) } } @@ -615,6 +619,7 @@ pub enum TypeKind { TypeEnum, TypeTrait, TypeFunction, + TypePrimitive, } impl Clean for ast::Ty { @@ -961,23 +966,100 @@ pub struct Impl { trait_: Option, for_: Type, methods: ~[Item], + is_primitive_impl: bool, } -impl Clean for doctree::Impl { - fn clean(&self) -> Item { - Item { +impl Clean<~[Item]> for doctree::Impl { + fn clean(&self) -> ~[Item] { + let tcx = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx; + let is_primitive_impl = match tcx { + Some(tcx) => { + let did = Some(ast::DefId { + node: self.id, + crate: ast::LOCAL_CRATE, + }); + did == tcx.lang_items.char_impl() || + did == tcx.lang_items.bool_impl() || + did == tcx.lang_items.u8_impl() || + did == tcx.lang_items.u16_impl() || + did == tcx.lang_items.u32_impl() || + did == tcx.lang_items.u64_impl() || + did == tcx.lang_items.uint_impl() || + did == tcx.lang_items.i8_impl() || + did == tcx.lang_items.i16_impl() || + did == tcx.lang_items.i32_impl() || + did == tcx.lang_items.i64_impl() || + did == tcx.lang_items.int_impl() || + did == tcx.lang_items.f32_impl() || + did == tcx.lang_items.f64_impl() + } + None => false + }; + let mut items = ~[]; + if is_primitive_impl { + items.push(primitive_item(self)); + } + items.push(Item { name: None, - attrs: self.attrs.clean(), + attrs: if is_primitive_impl {~[]} else {self.attrs.clean()}, source: self.where.clean(), id: self.id, visibility: self.vis.clean(), inner: ImplItem(Impl { + is_primitive_impl: is_primitive_impl, generics: self.generics.clean(), trait_: self.trait_.clean(), for_: self.for_.clean(), methods: self.methods.clean(), }), + }); + return items; + } +} + +fn primitive_item(imp: &doctree::Impl) -> Item { + let tcx = local_data::get(super::ctxtkey, |x| *x.unwrap()).tycx.unwrap(); + let def_map = tcx.def_map.borrow(); + let id = match imp.for_.node { + ast::TyPath(_, _, id) => id, + _ => fail!("not a primitive path"), + }; + let d = def_map.get().get(&id); + + macro_rules! primitive( ($li:ident, $prim:expr) => ({ + match tycx.lang_items.$li() { + Some(did) => (did, TypePrimitive), + None => return if $prim == ast::TyBool {Bool} else {Primitive($prim)} } + }) ) + + let (ty, name, prim_ty) = match *d { + ast::DefPrimTy(p) => match p { + ast::TyBool => (ty::mk_bool(), "bool", p), + ast::TyChar => (ty::mk_char(), "char", p), + ast::TyFloat(ast::TyF32) => (ty::mk_f32(), "f32", p), + ast::TyFloat(ast::TyF64) => (ty::mk_f64(), "f64", p), + ast::TyUint(ast::TyU) => (ty::mk_uint(), "uint", p), + ast::TyUint(ast::TyU8) => (ty::mk_u8(), "u8", p), + ast::TyUint(ast::TyU16) => (ty::mk_u16(), "u16", p), + ast::TyUint(ast::TyU32) => (ty::mk_u32(), "u32", p), + ast::TyUint(ast::TyU64) => (ty::mk_u64(), "u64", p), + ast::TyInt(ast::TyI) => (ty::mk_int(), "int", p), + ast::TyInt(ast::TyI8) => (ty::mk_i8(), "i8", p), + ast::TyInt(ast::TyI16) => (ty::mk_i16(), "i16", p), + ast::TyInt(ast::TyI32) => (ty::mk_i32(), "i32", p), + ast::TyInt(ast::TyI64) => (ty::mk_i64(), "i64", p), + ast::TyStr => fail!("can't handle string primitive yet"), + }, + x => fail!("resolved type maps to not a primitive {:?}", x), + }; + Item { + name: Some(name.to_owned()), + attrs: imp.attrs.clean(), + source: imp.where.clean(), + id: ty::maybe_prim_did(tcx, ty).unwrap().node, + visibility: ast::Public.clean(), + inner: PrimitiveType(prim_ty), } } @@ -1176,6 +1258,15 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>, } }; + macro_rules! primitive( ($ty:expr, $prim:expr) => ({ + match ty::maybe_prim_did(tycx, $ty) { + Some(did) => (did, TypePrimitive), + None => { + return if $prim == ast::TyBool {Bool} else {Primitive($prim)} + } + } + }) ) + let (def_id, kind) = match *d { ast::DefFn(i, _) => (i, TypeFunction), ast::DefSelf(i, _) | ast::DefSelfTy(i) => return Self(i), @@ -1186,8 +1277,20 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>, }, ast::DefPrimTy(p) => match p { ast::TyStr => return String, - ast::TyBool => return Bool, - _ => return Primitive(p) + ast::TyBool => primitive!(ty::mk_bool(), p), + ast::TyChar => primitive!(ty::mk_char(), p), + ast::TyFloat(ast::TyF32) => primitive!(ty::mk_f32(), p), + ast::TyFloat(ast::TyF64) => primitive!(ty::mk_f64(), p), + ast::TyUint(ast::TyU) => primitive!(ty::mk_uint(), p), + ast::TyUint(ast::TyU8) => primitive!(ty::mk_u8(), p), + ast::TyUint(ast::TyU16) => primitive!(ty::mk_u16(), p), + ast::TyUint(ast::TyU32) => primitive!(ty::mk_u32(), p), + ast::TyUint(ast::TyU64) => primitive!(ty::mk_u64(), p), + ast::TyInt(ast::TyI) => primitive!(ty::mk_int(), p), + ast::TyInt(ast::TyI8) => primitive!(ty::mk_i8(), p), + ast::TyInt(ast::TyI16) => primitive!(ty::mk_i16(), p), + ast::TyInt(ast::TyI32) => primitive!(ty::mk_i32(), p), + ast::TyInt(ast::TyI64) => primitive!(ty::mk_i64(), p), }, ast::DefTyParam(i, _) => return Generic(i.node), ast::DefStruct(i) => (i, TypeStruct), @@ -1200,7 +1303,30 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>, if ast_util::is_local(def_id) { ResolvedPath{ path: path, typarams: tpbs, id: def_id.node } } else { - let fqn = csearch::get_item_path(tycx, def_id); + let fqn = match *d { + ast::DefPrimTy(p) => { + let did = match p { + ast::TyBool => tycx.lang_items.bool_impl(), + ast::TyChar => tycx.lang_items.char_impl(), + ast::TyFloat(ast::TyF32) => tycx.lang_items.f32_impl(), + ast::TyFloat(ast::TyF64) => tycx.lang_items.f64_impl(), + ast::TyInt(ast::TyI) => tycx.lang_items.int_impl(), + ast::TyInt(ast::TyI8) => tycx.lang_items.i8_impl(), + ast::TyInt(ast::TyI16) => tycx.lang_items.i16_impl(), + ast::TyInt(ast::TyI32) => tycx.lang_items.i32_impl(), + ast::TyInt(ast::TyI64) => tycx.lang_items.i64_impl(), + ast::TyUint(ast::TyU) => tycx.lang_items.uint_impl(), + ast::TyUint(ast::TyU8) => tycx.lang_items.u8_impl(), + ast::TyUint(ast::TyU16) => tycx.lang_items.u16_impl(), + ast::TyUint(ast::TyU32) => tycx.lang_items.u32_impl(), + ast::TyUint(ast::TyU64) => tycx.lang_items.u64_impl(), + + _ => None, + }; + csearch::get_item_path(tycx, did.unwrap()) + } + _ => csearch::get_item_path(tycx, def_id) + }; let fqn = fqn.move_iter().map(|i| { match i { ast_map::PathMod(id) | ast_map::PathName(id) | diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 9b1caaa152ce3..495ed3bb0c80e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -155,6 +155,7 @@ fn external_path(w: &mut io::Writer, p: &clean::Path, print_all: bool, clean::TypeEnum => "enum", clean::TypeFunction => "fn", clean::TypeTrait => "trait", + clean::TypePrimitive => "primitive", })) }) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b0a56cb402b5f..6fa09c52eb3e4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -568,7 +568,8 @@ impl DocFolder for Cache { clean::StructItem(..) | clean::EnumItem(..) | clean::TypedefItem(..) | clean::TraitItem(..) | clean::FunctionItem(..) | clean::ModuleItem(..) | - clean::ForeignFunctionItem(..) | clean::VariantItem(..) => { + clean::ForeignFunctionItem(..) | clean::VariantItem(..) | + clean::PrimitiveType(..) => { self.paths.insert(item.id, (self.stack.clone(), shortty(&item))); } _ => {} @@ -596,25 +597,22 @@ impl DocFolder for Cache { Some(item) => { match item { clean::Item{ attrs, inner: clean::ImplItem(i), .. } => { + // extract relevant documentation for this impl + let dox = match attrs.move_iter().find(|a| { + match *a { + clean::NameValue(~"doc", _) => true, + _ => false + } + }) { + Some(clean::NameValue(_, dox)) => Some(dox), + Some(..) | None => None, + }; match i.for_ { clean::ResolvedPath { id, .. } => { let v = self.impls.find_or_insert_with(id, |_| { ~[] }); - // extract relevant documentation for this impl - match attrs.move_iter().find(|a| { - match *a { - clean::NameValue(~"doc", _) => true, - _ => false - } - }) { - Some(clean::NameValue(_, dox)) => { - v.push((i, Some(dox))); - } - Some(..) | None => { - v.push((i, None)); - } - } + v.push((i, dox)); } _ => {} } @@ -789,6 +787,7 @@ fn shortty(item: &clean::Item) -> &'static str { clean::VariantItem(..) => "variant", clean::ForeignFunctionItem(..) => "ffi", clean::ForeignStaticItem(..) => "ffs", + clean::PrimitiveType(..) => "primitive", } } @@ -813,6 +812,10 @@ impl<'a> fmt::Default for Item<'a> { } None => {} } + let primitive = match it.item.inner { + clean::PrimitiveType(..) => true, + _ => false, + }; if it.cx.include_sources { let mut path = ~[]; @@ -841,17 +844,20 @@ impl<'a> fmt::Default for Item<'a> { clean::TraitItem(..) => write!(fmt.buf, "Trait "), clean::StructItem(..) => write!(fmt.buf, "Struct "), clean::EnumItem(..) => write!(fmt.buf, "Enum "), + clean::PrimitiveType(..) => write!(fmt.buf, "Primitive Type "), _ => {} } - let cur = it.cx.current.as_slice(); - let amt = if it.ismodule() { cur.len() - 1 } else { cur.len() }; - for (i, component) in cur.iter().enumerate().take(amt) { - let mut trail = ~""; - for _ in range(0, cur.len() - i - 1) { - trail.push_str("../"); + if !primitive { + let cur = it.cx.current.as_slice(); + let amt = if it.ismodule() { cur.len() - 1 } else { cur.len() }; + for (i, component) in cur.iter().enumerate().take(amt) { + let mut trail = ~""; + for _ in range(0, cur.len() - i - 1) { + trail.push_str("../"); + } + write!(fmt.buf, "{}::", + trail, component.as_slice()); } - write!(fmt.buf, "{}::", - trail, component.as_slice()); } write!(fmt.buf, "{}", shortty(it.item), it.item.name.get_ref().as_slice()); @@ -865,6 +871,7 @@ impl<'a> fmt::Default for Item<'a> { clean::StructItem(ref s) => item_struct(fmt.buf, it.item, s), clean::EnumItem(ref e) => item_enum(fmt.buf, it.item, e), clean::TypedefItem(ref t) => item_typedef(fmt.buf, it.item, t), + clean::PrimitiveType(p) => item_primitive(fmt.buf, it.item, p), _ => {} } } @@ -930,6 +937,8 @@ fn item_module(w: &mut Writer, cx: &Context, } (&clean::ViewItemItem(..), _) => Less, (_, &clean::ViewItemItem(..)) => Greater, + (&clean::PrimitiveType(..), _) => Less, + (_, &clean::PrimitiveType(..)) => Greater, (&clean::ModuleItem(..), _) => Less, (_, &clean::ModuleItem(..)) => Greater, (&clean::StructItem(..), _) => Less, @@ -982,6 +991,7 @@ fn item_module(w: &mut Writer, cx: &Context, clean::VariantItem(..) => "Variants", clean::ForeignFunctionItem(..) => "Foreign Functions", clean::ForeignStaticItem(..) => "Foreign Statics", + clean::PrimitiveType(..) => "Primitive Types", }); } @@ -1574,3 +1584,8 @@ impl<'a> fmt::Default for Source<'a> { write!(fmt.buf, ""); } } + +fn item_primitive(w: &mut Writer, it: &clean::Item, _p: ast::PrimTy) { + document(w, it); + render_methods(w, it); +} diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 393be290506e1..5a70566a32f73 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -13,7 +13,7 @@ #[license = "MIT/ASL2"]; #[crate_type = "dylib"]; -#[feature(globs, struct_variant, managed_boxes)]; +#[feature(globs, struct_variant, managed_boxes, macro_rules)]; extern mod syntax; extern mod rustc; diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index cd3d3ecddfec2..35f96250b5b35 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -112,6 +112,9 @@ impl<'a> fold::DocFolder for Stripper<'a> { // impls/tymethods have no control over privacy clean::ImplItem(..) | clean::TyMethodItem(..) => {} + + // primitives never get stripped + clean::PrimitiveType(..) => {} } let fastreturn = match i.inner { diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs index af745f94fb519..198ea83586a94 100644 --- a/src/libstd/bool.rs +++ b/src/libstd/bool.rs @@ -66,8 +66,13 @@ pub fn all_values(blk: |v: bool|) { // Methods on `bool` ///////////////////////////////////////////////////////////////////////////// -/// Extension methods on a `bool` -pub trait Bool { +#[cfg(not(stage0), not(test))] +#[lang = "bool_impl"] +/// The boolean primitive for Rust. +/// +/// This primitive can have two values, `true` and `false`, and is type type +/// that is used to conditions in `if` statements and `while` loops. +impl bool { /// Conjunction of two boolean values. /// /// # Examples @@ -78,7 +83,7 @@ pub trait Bool { /// assert_eq!(false.and(true), false); /// assert_eq!(false.and(false), false); /// ``` - fn and(self, b: bool) -> bool; + pub fn and(self, b: bool) -> bool { self && b } /// Disjunction of two boolean values. /// @@ -90,7 +95,8 @@ pub trait Bool { /// assert_eq!(false.or(true), true); /// assert_eq!(false.or(false), false); /// ``` - fn or(self, b: bool) -> bool; + #[inline] + pub fn or(self, b: bool) -> bool { self || b } /// An 'exclusive or' of two boolean values. /// @@ -104,7 +110,8 @@ pub trait Bool { /// assert_eq!(false.xor(true), true); /// assert_eq!(false.xor(false), false); /// ``` - fn xor(self, b: bool) -> bool; + #[inline] + pub fn xor(self, b: bool) -> bool { self ^ b } /// Implication between two boolean values. /// @@ -120,7 +127,8 @@ pub trait Bool { /// assert_eq!(false.implies(true), true); /// assert_eq!(false.implies(false), true); /// ``` - fn implies(self, b: bool) -> bool; + #[inline] + pub fn implies(self, b: bool) -> bool { !self || b } /// Convert a `bool` to a `u8`. /// @@ -130,9 +138,24 @@ pub trait Bool { /// assert_eq!(true.to_bit::(), 1u8); /// assert_eq!(false.to_bit::(), 0u8); /// ``` + #[inline] + pub fn to_bit(self) -> N { + if self { FromPrimitive::from_u8(1).unwrap() } + else { FromPrimitive::from_u8(0).unwrap() } + } +} + +#[cfg(stage0)] +#[allow(missing_doc)] +pub trait Bool { + fn and(self, b: bool) -> bool; + fn or(self, b: bool) -> bool; + fn xor(self, b: bool) -> bool; + fn implies(self, b: bool) -> bool; fn to_bit(self) -> N; } +#[cfg(stage0)] impl Bool for bool { #[inline] fn and(self, b: bool) -> bool { self && b } diff --git a/src/libstd/char.rs b/src/libstd/char.rs index 71a297d71765e..4f7147a88fa5b 100644 --- a/src/libstd/char.rs +++ b/src/libstd/char.rs @@ -350,7 +350,61 @@ impl ToStr for char { } } +#[cfg(not(stage0), not(test))] +#[lang = "char_impl"] #[allow(missing_doc)] +/// The character primitive type in Rust. +/// +/// A `char` represents a unicode codepoint, and is represented as a 32-bit +/// value on all architectures. This type is not equivalent with the C `char` +/// type because it is used to represent more than just ASCII. +impl char { + pub fn is_alphabetic(&self) -> bool { is_alphabetic(*self) } + pub fn is_XID_start(&self) -> bool { is_XID_start(*self) } + pub fn is_XID_continue(&self) -> bool { is_XID_continue(*self) } + pub fn is_lowercase(&self) -> bool { is_lowercase(*self) } + pub fn is_uppercase(&self) -> bool { is_uppercase(*self) } + pub fn is_whitespace(&self) -> bool { is_whitespace(*self) } + pub fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) } + pub fn is_control(&self) -> bool { is_control(*self) } + pub fn is_digit(&self) -> bool { is_digit(*self) } + pub fn is_digit_radix(&self, radix: uint) -> bool { is_digit_radix(*self, radix) } + pub fn to_digit(&self, radix: uint) -> Option { to_digit(*self, radix) } + pub fn from_digit(num: uint, radix: uint) -> Option { from_digit(num, radix) } + pub fn escape_unicode(&self, f: |char|) { escape_unicode(*self, f) } + pub fn escape_default(&self, f: |char|) { escape_default(*self, f) } + pub fn len_utf8_bytes(&self) -> uint { len_utf8_bytes(*self) } + + /// Encodes this character as utf-8 into the provided byte-buffer. The + /// buffer must be at least 4 bytes long or a runtime failure will occur. + /// + /// This will then return the number of characters written to the slice. + pub fn encode_utf8<'a>(&self, dst: &'a mut [u8]) -> uint { + let code = *self as uint; + if code < MAX_ONE_B { + dst[0] = code as u8; + return 1; + } else if code < MAX_TWO_B { + dst[0] = (code >> 6u & 31u | TAG_TWO_B) as u8; + dst[1] = (code & 63u | TAG_CONT) as u8; + return 2; + } else if code < MAX_THREE_B { + dst[0] = (code >> 12u & 15u | TAG_THREE_B) as u8; + dst[1] = (code >> 6u & 63u | TAG_CONT) as u8; + dst[2] = (code & 63u | TAG_CONT) as u8; + return 3; + } else { + dst[0] = (code >> 18u & 7u | TAG_FOUR_B) as u8; + dst[1] = (code >> 12u & 63u | TAG_CONT) as u8; + dst[2] = (code >> 6u & 63u | TAG_CONT) as u8; + dst[3] = (code & 63u | TAG_CONT) as u8; + return 4; + } + } +} + +#[allow(missing_doc)] +#[cfg(stage0)] pub trait Char { fn is_alphabetic(&self) -> bool; fn is_XID_start(&self) -> bool; @@ -367,14 +421,10 @@ pub trait Char { fn escape_unicode(&self, f: |char|); fn escape_default(&self, f: |char|); fn len_utf8_bytes(&self) -> uint; - - /// Encodes this character as utf-8 into the provided byte-buffer. The - /// buffer must be at least 4 bytes long or a runtime failure will occur. - /// - /// This will then return the number of characters written to the slice. fn encode_utf8(&self, dst: &mut [u8]) -> uint; } +#[cfg(stage0)] impl Char for char { fn is_alphabetic(&self) -> bool { is_alphabetic(*self) } diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 5b2a792a05b10..f92dfcf67eec7 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -471,7 +471,7 @@ will look like `"\\{"`. use prelude::*; use cast; -use char::Char; +#[cfg(stage0)] use char::Char; use io::MemWriter; use io; use str; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 3082798336069..31a6014c60008 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -289,7 +289,7 @@ Out of scope #[allow(missing_doc)]; use cast; -use char::Char; +#[cfg(stage0)] use char::Char; use condition::Guard; use container::Container; use int; diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 0af8f155c6878..c81e832205701 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -169,6 +169,13 @@ pub mod consts { pub static LN_10: f32 = 2.30258509299404568401799145468436421_f32; } +#[cfg(not(stage0), not(test))] +#[lang = "f32_impl"] +/// The `f32` primitive is an 32-bit floating point type. This is generally +/// equivalent to the C `float` type. +impl f32 { +} + impl Num for f32 {} #[cfg(not(test))] diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 1155a89876e5a..34a9ee2b049c1 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -176,6 +176,13 @@ pub mod consts { pub static LN_10: f64 = 2.30258509299404568401799145468436421_f64; } +#[cfg(not(stage0), not(test))] +#[lang = "f64_impl"] +/// The `f64` primitive is an 32-bit floating point type. This is generally +/// equivalent to the C `double` type. +impl f64 { +} + impl Num for f64 {} #[cfg(not(test))] diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index e19e7c6c3b8bd..91f8392a8e447 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -24,6 +24,12 @@ use unstable::intrinsics; int_module!(i16, 16) +#[cfg(not(stage0), not(test))] +#[lang = "i16_impl"] +/// The `i16` primitive is a signed 16-bit integer type. +impl i16 { +} + impl Bitwise for i16 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. #[inline] diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 372d9f680d72e..721fe3d7ef59d 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -24,6 +24,12 @@ use unstable::intrinsics; int_module!(i32, 32) +#[cfg(not(stage0), not(test))] +#[lang = "i32_impl"] +/// The `i32` primitive is a signed 32-bit integer type. +impl i32 { +} + impl Bitwise for i32 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. #[inline] diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index 2a91ee4dd71cc..b785cd408f066 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -26,6 +26,12 @@ use unstable::intrinsics; int_module!(i64, 64) +#[cfg(not(stage0), not(test))] +#[lang = "i64_impl"] +/// The `i64` primitive is a signed 64-bit integer type. +impl i64 { +} + impl Bitwise for i64 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. #[inline] diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 66162ce350269..45bef1ef6df21 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -24,6 +24,12 @@ use unstable::intrinsics; int_module!(i8, 8) +#[cfg(not(stage0), not(test))] +#[lang = "i8_impl"] +/// The `i8` primitive is a signed 8-bit integer type. +impl i8 { +} + impl Bitwise for i8 { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. #[inline] diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index dbc7c67d97b9e..d52b888c85593 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -25,6 +25,15 @@ use unstable::intrinsics; #[cfg(target_word_size = "32")] int_module!(int, 32) #[cfg(target_word_size = "64")] int_module!(int, 64) +#[cfg(not(stage0), not(test))] +#[lang = "int_impl"] +/// The `int` primitive type is an architecture-sized signed integer. +/// +/// The size of a `int` is equivalent to the size of a `pointer` on the +/// particular architecture in question. +impl int { +} + #[cfg(target_word_size = "32")] impl Bitwise for int { /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 34dd313d4421f..23de0ad51de47 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -147,6 +147,7 @@ pub trait Unsigned: Num {} /// ten.times(|| { accum += 1; }) /// ``` /// +#[cfg(stage0)] pub trait Times { fn times(&self, it: ||); } diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index 770db889af55f..ad68a89877f72 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -25,6 +25,12 @@ use unstable::intrinsics; uint_module!(u16, i16, 16) +#[cfg(not(stage0), not(test))] +#[lang = "u16_impl"] +/// The `u16` primitive is an unsigned 8-bit integer type. +impl u16 { +} + impl CheckedAdd for u16 { #[inline] fn checked_add(&self, v: &u16) -> Option { diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index 9e08ffed3b70b..1b8240bc12fd6 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -25,6 +25,12 @@ use unstable::intrinsics; uint_module!(u32, i32, 32) +#[cfg(not(stage0), not(test))] +#[lang = "u32_impl"] +/// The `u32` primitive is an unsigned 32-bit integer type. +impl u32 { +} + impl CheckedAdd for u32 { #[inline] fn checked_add(&self, v: &u32) -> Option { diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index a579e7ebbbe4a..1ba459e85fdfd 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -27,6 +27,12 @@ use unstable::intrinsics; uint_module!(u64, i64, 64) +#[cfg(not(stage0), not(test))] +#[lang = "u64_impl"] +/// The `u64` primitive is an unsigned 64-bit integer type. +impl u64 { +} + impl CheckedAdd for u64 { #[inline] fn checked_add(&self, v: &u64) -> Option { diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index 4aa34b6d88044..aa68282518137 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -25,6 +25,12 @@ use unstable::intrinsics; uint_module!(u8, i8, 8) +#[cfg(not(stage0), not(test))] +#[lang = "u8_impl"] +/// The `u8` primitive is an unsigned 8-bit integer type. +impl u8 { +} + impl CheckedAdd for u8 { #[inline] fn checked_add(&self, v: &u8) -> Option { diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index d304f94754214..2191819afaf88 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -20,13 +20,40 @@ use num::{Bitwise, Bounded}; use num::{CheckedAdd, CheckedSub, CheckedMul}; use num::{CheckedDiv, Zero, One, strconv}; use num::{ToStrRadix, FromStrRadix}; -use num; +#[cfg(stage0)] use num; use option::{Option, Some, None}; use str; use unstable::intrinsics; uint_module!(uint, int, ::int::bits) +#[cfg(not(stage0), not(test))] +#[lang = "uint_impl"] +/// The `uint` primitive type is an architecture-sized unsigned integer. +/// +/// The size of a `uint` is equivalent to the size of a pointer on the +/// particular architecture in question. +impl uint { + /// + /// A convenience form for basic repetition. Given a uint `x`, + /// `x.times(|| { ... })` executes the given block x times. + /// + /// Equivalent to `for _ in range(0, x) { ... }`. + /// + /// Not defined on all integer types to permit unambiguous + /// use with integer literals of inferred integer-type as + /// the self-value (eg. `100.times(|| { ... })`). + /// + #[inline] + pub fn times(&self, it: ||) { + let mut i = *self; + while i > 0 { + it(); + i -= 1; + } + } +} + /// /// Divide two numbers, return the result, rounded up. /// @@ -80,8 +107,8 @@ pub fn div_round(x: uint, y: uint) -> uint { /// pub fn div_floor(x: uint, y: uint) -> uint { return x / y; } +#[cfg(stage0)] impl num::Times for uint { - #[inline] /// /// A convenience form for basic repetition. Given a uint `x`, /// `x.times(|| { ... })` executes the given block x times. @@ -92,6 +119,7 @@ impl num::Times for uint { /// use with integer literals of inferred integer-type as /// the self-value (eg. `100.times(|| { ... })`). /// + #[inline] fn times(&self, it: ||) { let mut i = *self; while i > 0 { diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 2f5f3e8f4568d..59d59567e11cb 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -45,9 +45,9 @@ pub use iter::range; pub use any::{Any, AnyOwnExt, AnyRefExt, AnyMutRefExt}; pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, IntoBytes}; -pub use bool::Bool; +#[cfg(stage0)] pub use bool::Bool; +#[cfg(stage0)] pub use char::Char; pub use c_str::ToCStr; -pub use char::Char; pub use clone::{Clone, DeepClone}; pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv}; pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet}; @@ -57,7 +57,7 @@ pub use hash::Hash; pub use iter::{FromIterator, Extendable}; pub use iter::{Iterator, DoubleEndedIterator, RandomAccessIterator, CloneableIterator}; pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize}; -pub use num::Times; +#[cfg(stage0)] pub use num::Times; pub use num::{Integer, Real, Num, NumCast, CheckedAdd, CheckedSub, CheckedMul}; pub use num::{Orderable, Signed, Unsigned, Round}; pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive}; diff --git a/src/libstd/rand/isaac.rs b/src/libstd/rand/isaac.rs index 6fd2cde9dfbc6..62718093e1a41 100644 --- a/src/libstd/rand/isaac.rs +++ b/src/libstd/rand/isaac.rs @@ -12,6 +12,7 @@ use rand::{Rng, SeedableRng, OSRng}; use iter::{Iterator, range, range_step, Repeat}; +#[cfg(stage0)] use num::Times; use option::{None, Some}; use vec::{raw, MutableVector, ImmutableVector}; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 95a02e1631a9a..d2e39313540d0 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -97,7 +97,7 @@ use at_vec; use cast; use cast::transmute; use char; -use char::Char; +#[cfg(stage0)] use char::Char; use clone::{Clone, DeepClone}; use container::{Container, Mutable}; use iter::{Iterator, FromIterator, Extendable, range}; diff --git a/src/libstd/unit.rs b/src/libstd/unit.rs index 786a7f42bb394..ec154be5e9927 100644 --- a/src/libstd/unit.rs +++ b/src/libstd/unit.rs @@ -13,6 +13,11 @@ #[cfg(not(test))] use prelude::*; +#[cfg(not(stage0), not(test))] +#[lang = "nil_impl"] +impl () { +} + #[cfg(not(test))] impl Eq for () { #[inline]