From a5c11b8819b3e62acdc33064b999c01f2b0f74e5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 7 Jan 2014 20:39:15 -0800 Subject: [PATCH 1/4] Remove the need to count lang items This solves horrible diffs where all you do is renumber literally everything. --- src/librustc/middle/lang_items.rs | 139 ++++++++++++++---------------- src/librustc/middle/resolve.rs | 6 +- src/librustc/middle/ty.rs | 4 +- 3 files changed, 68 insertions(+), 81 deletions(-) diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index d11cd4b3f3819..200dd2deee43d 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,55 @@ 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; + + EhPersonalityLangItem, "eh_personality", eh_personality_fn; + + ManagedHeapLangItem, "managed_heap", managed_heap; + ExchangeHeapLangItem, "exchange_heap", exchange_heap; + GcLangItem, "gc", gc; } 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..28cc56dfafd4d 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>, @@ -957,7 +957,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, From 3173630cc4a47b4f1610d2ee03aa406d270c53be Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 7 Jan 2014 22:46:58 -0800 Subject: [PATCH 2/4] Support impls directly on primitive types. --- src/librustc/metadata/common.rs | 5 ++ src/librustc/metadata/csearch.rs | 7 +++ src/librustc/metadata/decoder.rs | 16 +++++ src/librustc/metadata/encoder.rs | 40 ++++++++++++ src/librustc/middle/lang_items.rs | 20 +++++- src/librustc/middle/ty.rs | 40 ++++++++++++ src/librustc/middle/typeck/check/method.rs | 26 ++++++++ src/librustc/middle/typeck/coherence.rs | 72 +++++++++++++++++++--- 8 files changed, 217 insertions(+), 9 deletions(-) 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 200dd2deee43d..b9f76a59435ac 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -255,9 +255,25 @@ lets_do_this! { TypeIdLangItem, "type_id", type_id; - EhPersonalityLangItem, "eh_personality", eh_personality_fn; - 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/ty.rs b/src/librustc/middle/ty.rs index 28cc56dfafd4d..0542a91aa33ed 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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>>, @@ -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 it's 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 provided 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..8bc5750cabd9d 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,9 +81,14 @@ 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_infer(..) | ty_param(..) | ty_self(..) | ty_type | ty_opaque_box | ty_opaque_closure_ptr(..) | ty_unboxed_vec(..) | ty_err | ty_box(_) | ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => { debug!("(getting base type) no base type; found {:?}", @@ -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::ty_f32) => { + if li.f32_impl() != Some(did) { return None } + } + ty_float(ast::ty_f64) => { + if li.f64_impl() != Some(did) { return None } + } + ty_uint(ast::ty_u) => { + if li.uint_impl() != Some(did) { return None } + } + ty_int(ast::ty_i) => { + if li.int_impl() != Some(did) { return None } + } + ty_int(ast::ty_i8) => { + if li.i8_impl() != Some(did) { return None } + } + ty_int(ast::ty_i16) => { + if li.i16_impl() != Some(did) { return None } + } + ty_int(ast::ty_i32) => { + if li.i32_impl() != Some(did) { return None } + } + ty_int(ast::ty_i64) => { + if li.i64_impl() != Some(did) { return None } + } + ty_uint(ast::ty_u8) => { + if li.u8_impl() != Some(did) { return None } + } + ty_uint(ast::ty_u16) => { + if li.u16_impl() != Some(did) { return None } + } + ty_uint(ast::ty_u32) => { + if li.u32_impl() != Some(did) { return None } + } + ty_uint(ast::ty_u64) => { + 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::ty_str) => false, + DefPrimTy(..) => true, _ => false } } + ast::ty_nil => 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); + } }) } From dda69ab1e2d58f1606cf3519b1b0fd67b9a6feaf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 8 Jan 2014 11:30:01 -0800 Subject: [PATCH 3/4] Add impls for primitive types in libstd These impls are mostly currently blank, but they will get filled out in the future with implementations as we remove satellite traits in favor of inherent methods on primitives. --- src/libextra/uuid.rs | 1 - src/libstd/bool.rs | 35 +++++++++++++++++++----- src/libstd/char.rs | 60 ++++++++++++++++++++++++++++++++++++++---- src/libstd/fmt/mod.rs | 2 +- src/libstd/io/mod.rs | 2 +- src/libstd/num/f32.rs | 7 +++++ src/libstd/num/f64.rs | 7 +++++ src/libstd/num/i16.rs | 6 +++++ src/libstd/num/i32.rs | 6 +++++ src/libstd/num/i64.rs | 6 +++++ src/libstd/num/i8.rs | 6 +++++ src/libstd/num/int.rs | 9 +++++++ src/libstd/num/mod.rs | 1 + src/libstd/num/u16.rs | 6 +++++ src/libstd/num/u32.rs | 6 +++++ src/libstd/num/u64.rs | 6 +++++ src/libstd/num/u8.rs | 6 +++++ src/libstd/num/uint.rs | 32 ++++++++++++++++++++-- src/libstd/prelude.rs | 6 ++--- src/libstd/str.rs | 2 +- src/libstd/unit.rs | 5 ++++ 21 files changed, 197 insertions(+), 20 deletions(-) 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/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..1d45fddca2827 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 uint::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/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] From defe3e9e9c258414cfbc043d66f992e0cd527a96 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 8 Jan 2014 11:21:53 -0800 Subject: [PATCH 4/4] rustdoc: Render/hyperlink primitive types This piggybacks on the previous commits to add impls of primitives directly. --- src/librustc/middle/ty.rs | 4 +- src/librustc/middle/typeck/coherence.rs | 30 ++--- src/librustdoc/clean.rs | 142 ++++++++++++++++++++++-- src/librustdoc/html/format.rs | 1 + src/librustdoc/html/render.rs | 61 ++++++---- src/librustdoc/lib.rs | 2 +- src/librustdoc/passes.rs | 3 + src/libstd/num/uint.rs | 4 +- src/libstd/rand/isaac.rs | 1 + 9 files changed, 197 insertions(+), 51 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 0542a91aa33ed..5ec89373d3e8f 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5017,7 +5017,7 @@ impl substs { } } -/// Register a primitive type as having it's lang-item implementation in this +/// 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(); @@ -5032,7 +5032,7 @@ pub fn add_local_prim_did(tcx: ctxt, t: t) -> ast::DefId { } /// 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 provided an +/// 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(); diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 8bc5750cabd9d..430c97fd0c249 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -88,7 +88,7 @@ pub fn get_base_type(inference_context: @InferCtxt, ty_bot | ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) | - ty_infer(..) | ty_param(..) | ty_self(..) | ty_type | ty_opaque_box | + ty_infer(..) | ty_param(..) | ty_self(..) | ty_type | ty_opaque_closure_ptr(..) | ty_unboxed_vec(..) | ty_err | ty_box(_) | ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => { debug!("(getting base type) no base type; found {:?}", @@ -147,40 +147,40 @@ pub fn get_base_type_def_id(inference_context: @InferCtxt, 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::ty_f32) => { + ty_float(ast::TyF32) => { if li.f32_impl() != Some(did) { return None } } - ty_float(ast::ty_f64) => { + ty_float(ast::TyF64) => { if li.f64_impl() != Some(did) { return None } } - ty_uint(ast::ty_u) => { + ty_uint(ast::TyU) => { if li.uint_impl() != Some(did) { return None } } - ty_int(ast::ty_i) => { + ty_int(ast::TyI) => { if li.int_impl() != Some(did) { return None } } - ty_int(ast::ty_i8) => { + ty_int(ast::TyI8) => { if li.i8_impl() != Some(did) { return None } } - ty_int(ast::ty_i16) => { + ty_int(ast::TyI16) => { if li.i16_impl() != Some(did) { return None } } - ty_int(ast::ty_i32) => { + ty_int(ast::TyI32) => { if li.i32_impl() != Some(did) { return None } } - ty_int(ast::ty_i64) => { + ty_int(ast::TyI64) => { if li.i64_impl() != Some(did) { return None } } - ty_uint(ast::ty_u8) => { + ty_uint(ast::TyU8) => { if li.u8_impl() != Some(did) { return None } } - ty_uint(ast::ty_u16) => { + ty_uint(ast::TyU16) => { if li.u16_impl() != Some(did) { return None } } - ty_uint(ast::ty_u32) => { + ty_uint(ast::TyU32) => { if li.u32_impl() != Some(did) { return None } } - ty_uint(ast::ty_u64) => { + ty_uint(ast::TyU64) => { if li.u64_impl() != Some(did) { return None } } @@ -635,12 +635,12 @@ impl CoherenceChecker { Some(_) => false, } } - DefPrimTy(ast::ty_str) => false, + DefPrimTy(ast::TyStr) => false, DefPrimTy(..) => true, _ => false } } - ast::ty_nil => true, + ast::TyNil => true, _ => false } } 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/num/uint.rs b/src/libstd/num/uint.rs index 1d45fddca2827..2191819afaf88 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -31,14 +31,14 @@ uint_module!(uint, int, ::int::bits) #[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 +/// 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 uint::range(0, x) |_| { ... }`. + /// 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 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};