Skip to content

Commit 3173630

Browse files
committed
Support impls directly on primitive types.
1 parent a5c11b8 commit 3173630

File tree

8 files changed

+217
-9
lines changed

8 files changed

+217
-9
lines changed

src/librustc/metadata/common.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ pub static tag_macro_registrar_fn: uint = 0x110;
208208
pub static tag_exported_macros: uint = 0x111;
209209
pub static tag_macro_def: uint = 0x112;
210210

211+
pub static tag_prim_dids: uint = 0x113;
212+
pub static tag_prim_did: uint = 0x114;
213+
pub static tag_prim_did_ty: uint = 0x115;
214+
pub static tag_prim_did_did: uint = 0x116;
215+
211216
#[deriving(Clone)]
212217
pub struct LinkMeta {
213218
crateid: CrateId,

src/librustc/metadata/csearch.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,10 @@ pub fn get_exported_macros(cstore: @cstore::CStore,
311311
let cdata = cstore.get_crate_data(crate_num);
312312
decoder::get_exported_macros(cdata)
313313
}
314+
315+
pub fn prim_dids(cstore: @cstore::CStore,
316+
crate_num: ast::CrateNum,
317+
tcx: ty::ctxt) -> ~[(ty::t, ast::DefId)] {
318+
let cdata = cstore.get_crate_data(crate_num);
319+
decoder::prim_dids(cdata, tcx)
320+
}

src/librustc/metadata/decoder.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,3 +1292,19 @@ pub fn get_exported_macros(cdata: Cmd) -> ~[@ast::Item] {
12921292
});
12931293
result
12941294
}
1295+
1296+
pub fn prim_dids(cdata: Cmd, tcx: ty::ctxt) -> ~[(ty::t, ast::DefId)] {
1297+
let dids = reader::get_doc(reader::Doc(cdata.data()), tag_prim_dids);
1298+
let mut result = ~[];
1299+
reader::tagged_docs(dids, tag_prim_did, |did_doc| {
1300+
let ty_doc = reader::get_doc(did_doc, tag_prim_did_ty);
1301+
let id_doc = reader::get_doc(did_doc, tag_prim_did_did);
1302+
let did = ast::DefId {
1303+
node: reader::doc_as_u32(id_doc),
1304+
crate: cdata.cnum,
1305+
};
1306+
result.push((doc_type(ty_doc, tcx, cdata), did));
1307+
true
1308+
});
1309+
return result;
1310+
}

src/librustc/metadata/encoder.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ struct Stats {
8282
macro_registrar_fn_bytes: Cell<u64>,
8383
macro_defs_bytes: Cell<u64>,
8484
impl_bytes: Cell<u64>,
85+
prim_did_bytes: Cell<u64>,
8586
misc_bytes: Cell<u64>,
8687
item_bytes: Cell<u64>,
8788
index_bytes: Cell<u64>,
@@ -1455,6 +1456,21 @@ fn encode_info_for_items(ecx: &EncodeContext,
14551456
visit::walk_crate(&mut visitor, crate, ());
14561457
}
14571458

1459+
for (_, did) in ty::prim_dids(ecx.tcx).move_iter() {
1460+
if !ast_util::is_local(did) { continue }
1461+
{
1462+
let mut index = index.borrow_mut();
1463+
index.get().push(entry {
1464+
val: did.node as i64,
1465+
pos: ebml_w.writer.tell(),
1466+
});
1467+
}
1468+
ebml_w.start_tag(tag_items_data_item);
1469+
encode_def_id(ebml_w, did);
1470+
encode_inherent_implementations(ecx, ebml_w, did);
1471+
ebml_w.end_tag();
1472+
}
1473+
14581474
ebml_w.end_tag();
14591475
return /*bad*/(*index).get();
14601476
}
@@ -1818,6 +1834,23 @@ fn encode_misc_info(ecx: &EncodeContext,
18181834
ebml_w.end_tag();
18191835
}
18201836

1837+
fn encode_prim_dids(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1838+
ebml_w.start_tag(tag_prim_dids);
1839+
for (ty, did) in ty::prim_dids(ecx.tcx).move_iter() {
1840+
if !ast_util::is_local(did) { continue }
1841+
ebml_w.start_tag(tag_prim_did);
1842+
1843+
ebml_w.start_tag(tag_prim_did_ty);
1844+
encode_type(ecx, ebml_w, ty);
1845+
ebml_w.end_tag();
1846+
1847+
ebml_w.wr_tagged_u32(tag_prim_did_did, did.node);
1848+
1849+
ebml_w.end_tag();
1850+
}
1851+
ebml_w.end_tag();
1852+
}
1853+
18211854
fn encode_crate_dep(ecx: &EncodeContext,
18221855
ebml_w: &mut writer::Encoder,
18231856
dep: decoder::CrateDep) {
@@ -1865,6 +1898,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate)
18651898
macro_registrar_fn_bytes: Cell::new(0),
18661899
macro_defs_bytes: Cell::new(0),
18671900
impl_bytes: Cell::new(0),
1901+
prim_did_bytes: Cell::new(0),
18681902
misc_bytes: Cell::new(0),
18691903
item_bytes: Cell::new(0),
18701904
index_bytes: Cell::new(0),
@@ -1937,6 +1971,11 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate)
19371971
encode_impls(&ecx, crate, &mut ebml_w);
19381972
ecx.stats.impl_bytes.set(ebml_w.writer.tell() - i);
19391973

1974+
// Encode the def IDs of primitives (if we have any)
1975+
i = ebml_w.writer.tell();
1976+
encode_prim_dids(&ecx, &mut ebml_w);
1977+
ecx.stats.prim_did_bytes.set(ebml_w.writer.tell() - i);
1978+
19401979
// Encode miscellaneous info.
19411980
i = ebml_w.writer.tell();
19421981
encode_misc_info(&ecx, crate, &mut ebml_w);
@@ -1969,6 +2008,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate)
19692008
println!(" dep bytes: {}", ecx.stats.dep_bytes.get());
19702009
println!(" lang item bytes: {}", ecx.stats.lang_item_bytes.get());
19712010
println!(" native bytes: {}", ecx.stats.native_lib_bytes.get());
2011+
println!(" prim did bytes: {}", ecx.stats.prim_did_bytes.get());
19722012
println!("macro registrar bytes: {}", ecx.stats.macro_registrar_fn_bytes.get());
19732013
println!(" macro def bytes: {}", ecx.stats.macro_defs_bytes.get());
19742014
println!(" impl bytes: {}", ecx.stats.impl_bytes.get());

src/librustc/middle/lang_items.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,25 @@ lets_do_this! {
255255

256256
TypeIdLangItem, "type_id", type_id;
257257

258-
EhPersonalityLangItem, "eh_personality", eh_personality_fn;
259-
260258
ManagedHeapLangItem, "managed_heap", managed_heap;
261259
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
262260
GcLangItem, "gc", gc;
261+
262+
EhPersonalityLangItem, "eh_personality", eh_personality_fn;
263+
264+
CharImplLangItem, "char_impl", char_impl;
265+
IntImplLangItem, "int_impl", int_impl;
266+
I8ImplLangItem, "i8_impl", i8_impl;
267+
I16ImplLangItem, "i16_impl", i16_impl;
268+
I32ImplLangItem, "i32_impl", i32_impl;
269+
I64ImplLangItem, "i64_impl", i64_impl;
270+
UintImplLangItem, "uint_impl", uint_impl;
271+
U8ImplLangItem, "u8_impl", u8_impl;
272+
U16ImplLangItem, "u16_impl", u16_impl;
273+
U32ImplLangItem, "u32_impl", u32_impl;
274+
U64ImplLangItem, "u64_impl", u64_impl;
275+
BoolImplLangItem, "bool_impl", bool_impl;
276+
NilImplLangItem, "nil_impl", nil_impl;
277+
F32ImplLangItem, "f32_impl", f32_impl;
278+
F64ImplLangItem, "f64_impl", f64_impl;
263279
}

src/librustc/middle/ty.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,9 @@ struct ctxt_ {
361361
// is used for lazy resolution of traits.
362362
populated_external_traits: RefCell<HashSet<ast::DefId>>,
363363

364+
// TODO: dox
365+
prim_dids: RefCell<HashMap<t, ast::DefId>>,
366+
364367
// These two caches are used by const_eval when decoding external statics
365368
// and variants that are found.
366369
extern_const_statics: RefCell<HashMap<ast::DefId, Option<@ast::Expr>>>,
@@ -1003,6 +1006,7 @@ pub fn mk_ctxt(s: session::Session,
10031006
impl_vtables: RefCell::new(HashMap::new()),
10041007
populated_external_types: RefCell::new(HashSet::new()),
10051008
populated_external_traits: RefCell::new(HashSet::new()),
1009+
prim_dids: RefCell::new(HashMap::new()),
10061010

10071011
extern_const_statics: RefCell::new(HashMap::new()),
10081012
extern_const_variants: RefCell::new(HashMap::new()),
@@ -5012,3 +5016,39 @@ impl substs {
50125016
}
50135017
}
50145018
}
5019+
5020+
/// Register a primitive type as having it's lang-item implementation in this
5021+
/// crate. This method will create a DefId if one doesn't already exist for it.
5022+
pub fn add_local_prim_did(tcx: ctxt, t: t) -> ast::DefId {
5023+
let mut map = tcx.prim_dids.borrow_mut();
5024+
match map.get().find(&t) {
5025+
Some(&did) => return did,
5026+
None => {}
5027+
}
5028+
let id = tcx.next_id.get();
5029+
tcx.next_id.set(id + 1);
5030+
map.get().insert(t, ast_util::local_def(id as ast::NodeId));
5031+
return ast_util::local_def(id as ast::NodeId);
5032+
}
5033+
5034+
/// Fetch the DefId of the lang-item implementation of a primitive type. This
5035+
/// may not succeed (as the local crate or linked crates may not provided an
5036+
/// implementation).
5037+
pub fn maybe_prim_did(tcx: ctxt, t: t) -> Option<ast::DefId> {
5038+
let map = tcx.prim_dids.borrow();
5039+
map.get().find(&t).map(|&x| x)
5040+
}
5041+
5042+
/// Adds the DefId of a lang-item implementation of a primitive from an external
5043+
/// crate.
5044+
pub fn add_extern_prim_did(tcx: ctxt, t: t, did: ast::DefId) {
5045+
let mut map = tcx.prim_dids.borrow_mut();
5046+
assert!(map.get().insert(t, did));
5047+
}
5048+
5049+
/// Fetch all primitive type implementations known to this crate. This includes
5050+
/// local as well as external primitive types.
5051+
pub fn prim_dids(tcx: ctxt) -> ~[(t, ast::DefId)] {
5052+
let map = tcx.prim_dids.borrow();
5053+
map.get().iter().map(|(&a, &b)| (a, b)).collect()
5054+
}

src/librustc/middle/typeck/check/method.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,12 @@ impl<'a> LookupContext<'a> {
295295
*/
296296

297297
let mut self_ty = self_ty;
298+
macro_rules! add( ($t:expr) => ({
299+
match ty::maybe_prim_did(self.fcx.tcx(), $t) {
300+
Some(did) => self.push_inherent_impl_candidates_for_type(did),
301+
None => {}
302+
}
303+
}) )
298304
loop {
299305
match get(self_ty).sty {
300306
ty_trait(did, ref substs, _, _, _) => {
@@ -306,6 +312,26 @@ impl<'a> LookupContext<'a> {
306312
self.push_inherent_impl_candidates_for_type(did);
307313
}
308314
}
315+
ty_nil | ty_bool | ty_char | ty_int(..) | ty_uint(..) |
316+
ty_float(..) => {
317+
add!(self_ty);
318+
}
319+
ty_infer(FloatVar(..)) => {
320+
add!(ty::mk_f32());
321+
add!(ty::mk_f64());
322+
}
323+
ty_infer(IntVar(..)) => {
324+
add!(ty::mk_uint());
325+
add!(ty::mk_u8());
326+
add!(ty::mk_u16());
327+
add!(ty::mk_u32());
328+
add!(ty::mk_u64());
329+
add!(ty::mk_int());
330+
add!(ty::mk_i8());
331+
add!(ty::mk_i16());
332+
add!(ty::mk_i32());
333+
add!(ty::mk_i64());
334+
}
309335
_ => { /* No inherent methods in these types */ }
310336
}
311337

src/librustc/middle/typeck/coherence.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use middle::typeck::infer::InferCtxt;
3535
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar, resolve_type};
3636
use middle::typeck::infer;
3737
use util::ppaux::Repr;
38-
use syntax::ast::{Crate, DefId, DefStruct, DefTy};
38+
use syntax::ast::{Crate, DefId, DefStruct, DefTy, DefPrimTy};
3939
use syntax::ast::{Item, ItemEnum, ItemImpl, ItemMod, ItemStruct};
4040
use syntax::ast::{LOCAL_CRATE, TraitRef, TyPath};
4141
use syntax::ast;
@@ -81,9 +81,14 @@ pub fn get_base_type(inference_context: @InferCtxt,
8181
Some(resolved_type)
8282
}
8383

84-
ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
84+
ty_nil | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) => {
85+
debug!("(getting base type) found primitive base type");
86+
Some(resolved_type)
87+
}
88+
89+
ty_bot |
8590
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
86-
ty_infer(..) | ty_param(..) | ty_self(..) | ty_type |
91+
ty_infer(..) | ty_param(..) | ty_self(..) | ty_type | ty_opaque_box |
8792
ty_opaque_closure_ptr(..) | ty_unboxed_vec(..) | ty_err | ty_box(_) |
8893
ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
8994
debug!("(getting base type) no base type; found {:?}",
@@ -121,6 +126,7 @@ pub fn type_is_defined_in_local_crate(original_type: t) -> bool {
121126

122127
// Returns the def ID of the base type, if there is one.
123128
pub fn get_base_type_def_id(inference_context: @InferCtxt,
129+
id: ast::NodeId,
124130
span: Span,
125131
original_type: t)
126132
-> Option<DefId> {
@@ -129,17 +135,61 @@ pub fn get_base_type_def_id(inference_context: @InferCtxt,
129135
return None;
130136
}
131137
Some(base_type) => {
138+
let did = local_def(id);
139+
let li = inference_context.tcx.lang_items;
132140
match get(base_type).sty {
133141
ty_enum(def_id, _) |
134142
ty_struct(def_id, _) |
135143
ty_trait(def_id, _, _, _, _) => {
136144
return Some(def_id);
137145
}
146+
147+
ty_char => { if li.char_impl() != Some(did) { return None } }
148+
ty_nil => { if li.nil_impl() != Some(did) { return None } }
149+
ty_bool => { if li.bool_impl() != Some(did) { return None } }
150+
ty_float(ast::ty_f32) => {
151+
if li.f32_impl() != Some(did) { return None }
152+
}
153+
ty_float(ast::ty_f64) => {
154+
if li.f64_impl() != Some(did) { return None }
155+
}
156+
ty_uint(ast::ty_u) => {
157+
if li.uint_impl() != Some(did) { return None }
158+
}
159+
ty_int(ast::ty_i) => {
160+
if li.int_impl() != Some(did) { return None }
161+
}
162+
ty_int(ast::ty_i8) => {
163+
if li.i8_impl() != Some(did) { return None }
164+
}
165+
ty_int(ast::ty_i16) => {
166+
if li.i16_impl() != Some(did) { return None }
167+
}
168+
ty_int(ast::ty_i32) => {
169+
if li.i32_impl() != Some(did) { return None }
170+
}
171+
ty_int(ast::ty_i64) => {
172+
if li.i64_impl() != Some(did) { return None }
173+
}
174+
ty_uint(ast::ty_u8) => {
175+
if li.u8_impl() != Some(did) { return None }
176+
}
177+
ty_uint(ast::ty_u16) => {
178+
if li.u16_impl() != Some(did) { return None }
179+
}
180+
ty_uint(ast::ty_u32) => {
181+
if li.u32_impl() != Some(did) { return None }
182+
}
183+
ty_uint(ast::ty_u64) => {
184+
if li.u64_impl() != Some(did) { return None }
185+
}
186+
138187
_ => {
139188
fail!("get_base_type() returned a type that wasn't an \
140-
enum, struct, or trait");
189+
enum, struct, trait, or known primitive");
141190
}
142191
}
192+
return Some(ty::add_local_prim_did(inference_context.tcx, base_type));
143193
}
144194
}
145195
}
@@ -273,7 +323,7 @@ impl CoherenceChecker {
273323
self.crate_context.tcx.sess.str_of(item.ident));
274324

275325
match get_base_type_def_id(self.inference_context,
276-
item.span,
326+
item.id, item.span,
277327
self_type.ty) {
278328
None => {
279329
let session = self.crate_context.tcx.sess;
@@ -303,7 +353,7 @@ impl CoherenceChecker {
303353
// type def ID, if there is a base type for this implementation and
304354
// the implementation does not have any associated traits.
305355
match get_base_type_def_id(self.inference_context,
306-
item.span,
356+
item.id, item.span,
307357
self_type.ty) {
308358
None => {
309359
// Nothing to do.
@@ -585,9 +635,12 @@ impl CoherenceChecker {
585635
Some(_) => false,
586636
}
587637
}
638+
DefPrimTy(ast::ty_str) => false,
639+
DefPrimTy(..) => true,
588640
_ => false
589641
}
590642
}
643+
ast::ty_nil => true,
591644
_ => false
592645
}
593646
}
@@ -688,7 +741,12 @@ impl CoherenceChecker {
688741
each_impl(crate_store, crate_number, |def_id| {
689742
assert_eq!(crate_number, def_id.crate);
690743
self.add_external_impl(&mut impls_seen, def_id)
691-
})
744+
});
745+
let prims = csearch::prim_dids(crate_store, crate_number,
746+
self.crate_context.tcx);
747+
for (t, did) in prims.move_iter() {
748+
ty::add_extern_prim_did(self.crate_context.tcx, t, did);
749+
}
692750
})
693751
}
694752

0 commit comments

Comments
 (0)