about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-06-25 04:38:06 -0700
committerbors <bors@rust-lang.org>2013-06-25 04:38:06 -0700
commit7aee5da08db11dc597907bf228c2e716a408fdab (patch)
tree7217207f8ec916aca96034f94d64a15746e22f79
parentb11346bb5d2659313eb96f3108137f01239785c9 (diff)
parentf8ae3cdcaacb29c7b56e546a9ddab1396b615f8f (diff)
downloadrust-7aee5da08db11dc597907bf228c2e716a408fdab.tar.gz
rust-7aee5da08db11dc597907bf228c2e716a408fdab.zip
auto merge of #7254 : Blei/rust/intrinsic-overhaul, r=cmr
This sets the `get_tydesc()` return type correctly and removes the intrinsic module. See #3730, #3475.

Update: this now also removes the unused shape fields in tydescs.
-rw-r--r--src/libextra/arena.rs53
-rw-r--r--src/libextra/dbg.rs34
-rw-r--r--src/librustc/back/abi.rs17
-rw-r--r--src/librustc/driver/driver.rs3
-rw-r--r--src/librustc/front/intrinsic.rs140
-rw-r--r--src/librustc/front/intrinsic_inject.rs47
-rw-r--r--src/librustc/middle/lang_items.rs24
-rw-r--r--src/librustc/middle/trans/foreign.rs9
-rw-r--r--src/librustc/middle/trans/glue.rs33
-rw-r--r--src/librustc/middle/trans/reflect.rs8
-rw-r--r--src/librustc/middle/trans/type_.rs20
-rw-r--r--src/librustc/middle/ty.rs27
-rw-r--r--src/librustc/middle/typeck/check/mod.rs12
-rw-r--r--src/librustc/middle/typeck/collect.rs55
-rw-r--r--src/librustc/rustc.rc1
-rw-r--r--src/libstd/at_vec.rs13
-rw-r--r--src/libstd/cleanup.rs30
-rw-r--r--src/libstd/gc.rs28
-rw-r--r--src/libstd/managed.rs2
-rw-r--r--src/libstd/reflect.rs6
-rw-r--r--src/libstd/repr.rs20
-rw-r--r--src/libstd/rt/global_heap.rs10
-rw-r--r--src/libstd/sys.rs31
-rw-r--r--src/libstd/unstable/exchange_alloc.rs10
-rw-r--r--src/libstd/unstable/intrinsics.rs132
-rw-r--r--src/libstd/vec.rs15
-rw-r--r--src/libsyntax/parse/token.rs204
-rw-r--r--src/rt/rust_builtin.cpp9
-rw-r--r--src/rt/rust_task.cpp6
-rw-r--r--src/rt/rust_type.h8
-rw-r--r--src/rt/rust_util.cpp2
-rw-r--r--src/rt/rustrt.def.in1
-rw-r--r--src/test/run-pass/extern-pub.rs8
-rw-r--r--src/test/run-pass/reflect-visit-data.rs20
-rw-r--r--src/test/run-pass/reflect-visit-type.rs181
35 files changed, 565 insertions, 654 deletions
diff --git a/src/libextra/arena.rs b/src/libextra/arena.rs
index 302f1fbeb04..4d37c244b13 100644
--- a/src/libextra/arena.rs
+++ b/src/libextra/arena.rs
@@ -41,30 +41,21 @@ use list::{MutList, MutCons, MutNil};
 use core::at_vec;
 use core::cast::{transmute, transmute_mut, transmute_mut_region};
 use core::cast;
-use core::libc::size_t;
 use core::ptr;
-use core::sys::TypeDesc;
 use core::sys;
 use core::uint;
 use core::vec;
 use core::unstable::intrinsics;
+use core::unstable::intrinsics::{TyDesc};
 
-pub mod rustrt {
-    use core::libc::size_t;
-    use core::sys::TypeDesc;
+#[cfg(not(stage0))]
+use core::unstable::intrinsics::{get_tydesc};
 
-    pub extern {
-        #[rust_stack]
-        unsafe fn rust_call_tydesc_glue(root: *u8,
-                                        tydesc: *TypeDesc,
-                                        field: size_t);
-    }
+#[cfg(stage0)]
+unsafe fn get_tydesc<T>() -> *TyDesc {
+    intrinsics::get_tydesc::<T>() as *TyDesc
 }
 
-// This probably belongs somewhere else. Needs to be kept in sync with
-// changes to glue...
-static tydesc_drop_glue_index: size_t = 3 as size_t;
-
 // The way arena uses arrays is really deeply awful. The arrays are
 // allocated, and have capacities reserved, but the fill for the array
 // will always stay at 0.
@@ -125,6 +116,19 @@ fn round_up_to(base: uint, align: uint) -> uint {
     (base + (align - 1)) & !(align - 1)
 }
 
+#[inline]
+#[cfg(not(stage0))]
+unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
+    // This function should be inlined when stage0 is gone
+    ((*tydesc).drop_glue)(data);
+}
+
+#[inline]
+#[cfg(stage0)]
+unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
+    ((*tydesc).drop_glue)(0 as **TyDesc, data);
+}
+
 // Walk down a chunk, running the destructors for any objects stored
 // in it.
 unsafe fn destroy_chunk(chunk: &Chunk) {
@@ -137,19 +141,18 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
         let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data);
         let (size, align) = ((*tydesc).size, (*tydesc).align);
 
-        let after_tydesc = idx + sys::size_of::<*TypeDesc>();
+        let after_tydesc = idx + sys::size_of::<*TyDesc>();
 
         let start = round_up_to(after_tydesc, align);
 
         //debug!("freeing object: idx = %u, size = %u, align = %u, done = %b",
         //       start, size, align, is_done);
         if is_done {
-            rustrt::rust_call_tydesc_glue(
-                ptr::offset(buf, start), tydesc, tydesc_drop_glue_index);
+            call_drop_glue(tydesc, ptr::offset(buf, start) as *i8);
         }
 
         // Find where the next tydesc lives
-        idx = round_up_to(start + size, sys::pref_align_of::<*TypeDesc>());
+        idx = round_up_to(start + size, sys::pref_align_of::<*TyDesc>());
     }
 }
 
@@ -158,12 +161,12 @@ unsafe fn destroy_chunk(chunk: &Chunk) {
 // is necessary in order to properly do cleanup if a failure occurs
 // during an initializer.
 #[inline]
-unsafe fn bitpack_tydesc_ptr(p: *TypeDesc, is_done: bool) -> uint {
+unsafe fn bitpack_tydesc_ptr(p: *TyDesc, is_done: bool) -> uint {
     let p_bits: uint = transmute(p);
     p_bits | (is_done as uint)
 }
 #[inline]
-unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) {
+unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TyDesc, bool) {
     (transmute(p & !1), p & 1 == 1)
 }
 
@@ -203,7 +206,7 @@ impl Arena {
     #[inline]
     fn alloc_pod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
         unsafe {
-            let tydesc = sys::get_type_desc::<T>();
+            let tydesc = get_tydesc::<T>();
             let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align);
             let ptr: *mut T = transmute(ptr);
             intrinsics::move_val_init(&mut (*ptr), op());
@@ -231,13 +234,13 @@ impl Arena {
             let head = transmute_mut_region(&mut self.head);
 
             let tydesc_start = head.fill;
-            let after_tydesc = head.fill + sys::size_of::<*TypeDesc>();
+            let after_tydesc = head.fill + sys::size_of::<*TyDesc>();
             let start = round_up_to(after_tydesc, align);
             let end = start + n_bytes;
             if end > at_vec::capacity(head.data) {
                 return self.alloc_nonpod_grow(n_bytes, align);
             }
-            head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>());
+            head.fill = round_up_to(end, sys::pref_align_of::<*TyDesc>());
 
             //debug!("idx = %u, size = %u, align = %u, fill = %u",
             //       start, n_bytes, align, head.fill);
@@ -250,7 +253,7 @@ impl Arena {
     #[inline]
     fn alloc_nonpod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
         unsafe {
-            let tydesc = sys::get_type_desc::<T>();
+            let tydesc = get_tydesc::<T>();
             let (ty_ptr, ptr) =
                 self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align);
             let ty_ptr: *mut uint = transmute(ty_ptr);
diff --git a/src/libextra/dbg.rs b/src/libextra/dbg.rs
index cbd7cb5e3c0..43c4aecdd27 100644
--- a/src/libextra/dbg.rs
+++ b/src/libextra/dbg.rs
@@ -13,56 +13,62 @@
 #[allow(missing_doc)];
 
 use core::cast::transmute;
-use core::sys;
+#[cfg(stage0)]
+use intrinsic::{get_tydesc};
+#[cfg(not(stage0))]
+use core::unstable::intrinsics::{get_tydesc};
 
 pub mod rustrt {
-    use core::sys;
+    #[cfg(stage0)]
+    use intrinsic::{TyDesc};
+    #[cfg(not(stage0))]
+    use core::unstable::intrinsics::{TyDesc};
 
     #[abi = "cdecl"]
     pub extern {
-        pub unsafe fn debug_tydesc(td: *sys::TypeDesc);
-        pub unsafe fn debug_opaque(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_box(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_tag(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_fn(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_ptrcast(td: *sys::TypeDesc, x: *()) -> *();
+        pub unsafe fn debug_tydesc(td: *TyDesc);
+        pub unsafe fn debug_opaque(td: *TyDesc, x: *());
+        pub unsafe fn debug_box(td: *TyDesc, x: *());
+        pub unsafe fn debug_tag(td: *TyDesc, x: *());
+        pub unsafe fn debug_fn(td: *TyDesc, x: *());
+        pub unsafe fn debug_ptrcast(td: *TyDesc, x: *()) -> *();
         pub unsafe fn rust_dbg_breakpoint();
     }
 }
 
 pub fn debug_tydesc<T>() {
     unsafe {
-        rustrt::debug_tydesc(sys::get_type_desc::<T>());
+        rustrt::debug_tydesc(get_tydesc::<T>());
     }
 }
 
 pub fn debug_opaque<T>(x: T) {
     unsafe {
-        rustrt::debug_opaque(sys::get_type_desc::<T>(), transmute(&x));
+        rustrt::debug_opaque(get_tydesc::<T>(), transmute(&x));
     }
 }
 
 pub fn debug_box<T>(x: @T) {
     unsafe {
-        rustrt::debug_box(sys::get_type_desc::<T>(), transmute(&x));
+        rustrt::debug_box(get_tydesc::<T>(), transmute(&x));
     }
 }
 
 pub fn debug_tag<T>(x: T) {
     unsafe {
-        rustrt::debug_tag(sys::get_type_desc::<T>(), transmute(&x));
+        rustrt::debug_tag(get_tydesc::<T>(), transmute(&x));
     }
 }
 
 pub fn debug_fn<T>(x: T) {
     unsafe {
-        rustrt::debug_fn(sys::get_type_desc::<T>(), transmute(&x));
+        rustrt::debug_fn(get_tydesc::<T>(), transmute(&x));
     }
 }
 
 pub unsafe fn ptr_cast<T, U>(x: @T) -> @U {
     transmute(
-        rustrt::debug_ptrcast(sys::get_type_desc::<T>(), transmute(x)))
+        rustrt::debug_ptrcast(get_tydesc::<T>(), transmute(x)))
 }
 
 /// Triggers a debugger breakpoint
diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs
index 004170dea7f..05b6e90c682 100644
--- a/src/librustc/back/abi.rs
+++ b/src/librustc/back/abi.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-
-
 pub static rc_base_field_refcnt: uint = 0u;
 
 pub static task_field_refcnt: uint = 0u;
@@ -49,9 +46,7 @@ pub static tydesc_field_take_glue: uint = 2u;
 pub static tydesc_field_drop_glue: uint = 3u;
 pub static tydesc_field_free_glue: uint = 4u;
 pub static tydesc_field_visit_glue: uint = 5u;
-pub static tydesc_field_shape: uint = 6u;
-pub static tydesc_field_shape_tables: uint = 7u;
-pub static n_tydesc_fields: uint = 8u;
+pub static n_tydesc_fields: uint = 6u;
 
 // The two halves of a closure: code and environment.
 pub static fn_field_code: uint = 0u;
@@ -71,14 +66,4 @@ pub static vec_elt_elems: uint = 2u;
 pub static slice_elt_base: uint = 0u;
 pub static slice_elt_len: uint = 1u;
 
-pub static worst_case_glue_call_args: uint = 7u;
-
 pub static abi_version: uint = 1u;
-
-pub fn memcpy_glue_name() -> ~str { return ~"rust_memcpy_glue"; }
-
-pub fn bzero_glue_name() -> ~str { return ~"rust_bzero_glue"; }
-
-pub fn yield_glue_name() -> ~str { return ~"rust_yield_glue"; }
-
-pub fn no_op_type_glue_name() -> ~str { return ~"rust_no_op_type_glue"; }
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 1a7041c0884..fbb273450df 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -206,9 +206,6 @@ pub fn compile_rest(sess: Session,
     let mut crate = crate_opt.unwrap();
 
     let (llcx, llmod, link_meta) = {
-    crate = time(time_passes, ~"intrinsic injection", ||
-                 front::intrinsic_inject::inject_intrinsic(sess, crate));
-
         crate = time(time_passes, ~"extra injection", ||
                      front::std_inject::maybe_inject_libstd_ref(sess, crate));
 
diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs
deleted file mode 100644
index fcb08180a5e..00000000000
--- a/src/librustc/front/intrinsic.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// NB: this file is include_str!'ed into the compiler, re-parsed
-// and injected into each crate the compiler builds. Keep it small.
-
-pub mod intrinsic {
-    #[allow(missing_doc)];
-
-    pub use intrinsic::rusti::visit_tydesc;
-
-    // FIXME (#3727): remove this when the interface has settled and the
-    // version in sys is no longer present.
-    pub fn get_tydesc<T>() -> *TyDesc {
-        unsafe {
-            rusti::get_tydesc::<T>() as *TyDesc
-        }
-    }
-
-    pub struct TyDesc {
-        size: uint,
-        align: uint
-        // Remaining fields not listed
-    }
-
-    pub enum Opaque { }
-
-    pub trait TyVisitor {
-        fn visit_bot(&self) -> bool;
-        fn visit_nil(&self) -> bool;
-        fn visit_bool(&self) -> bool;
-
-        fn visit_int(&self) -> bool;
-        fn visit_i8(&self) -> bool;
-        fn visit_i16(&self) -> bool;
-        fn visit_i32(&self) -> bool;
-        fn visit_i64(&self) -> bool;
-
-        fn visit_uint(&self) -> bool;
-        fn visit_u8(&self) -> bool;
-        fn visit_u16(&self) -> bool;
-        fn visit_u32(&self) -> bool;
-        fn visit_u64(&self) -> bool;
-
-        fn visit_float(&self) -> bool;
-        fn visit_f32(&self) -> bool;
-        fn visit_f64(&self) -> bool;
-
-        fn visit_char(&self) -> bool;
-        fn visit_str(&self) -> bool;
-
-        fn visit_estr_box(&self) -> bool;
-        fn visit_estr_uniq(&self) -> bool;
-        fn visit_estr_slice(&self) -> bool;
-        fn visit_estr_fixed(&self, n: uint, sz: uint, align: uint) -> bool;
-
-        fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
-
-        fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
-                            mtbl: uint, inner: *TyDesc) -> bool;
-
-        fn visit_enter_rec(&self, n_fields: uint,
-                           sz: uint, align: uint) -> bool;
-        fn visit_rec_field(&self, i: uint, name: &str,
-                           mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_leave_rec(&self, n_fields: uint,
-                           sz: uint, align: uint) -> bool;
-
-        fn visit_enter_class(&self, n_fields: uint,
-                             sz: uint, align: uint) -> bool;
-        fn visit_class_field(&self, i: uint, name: &str,
-                             mtbl: uint, inner: *TyDesc) -> bool;
-        fn visit_leave_class(&self, n_fields: uint,
-                             sz: uint, align: uint) -> bool;
-
-        fn visit_enter_tup(&self, n_fields: uint,
-                           sz: uint, align: uint) -> bool;
-        fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool;
-        fn visit_leave_tup(&self, n_fields: uint,
-                           sz: uint, align: uint) -> bool;
-
-        fn visit_enter_enum(&self, n_variants: uint,
-                            get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                            sz: uint, align: uint) -> bool;
-        fn visit_enter_enum_variant(&self, variant: uint,
-                                    disr_val: int,
-                                    n_fields: uint,
-                                    name: &str) -> bool;
-        fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool;
-        fn visit_leave_enum_variant(&self, variant: uint,
-                                    disr_val: int,
-                                    n_fields: uint,
-                                    name: &str) -> bool;
-        fn visit_leave_enum(&self, n_variants: uint,
-                            get_disr: extern unsafe fn(ptr: *Opaque) -> int,
-                            sz: uint, align: uint) -> bool;
-
-        fn visit_enter_fn(&self, purity: uint, proto: uint,
-                          n_inputs: uint, retstyle: uint) -> bool;
-        fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool;
-        fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool;
-        fn visit_leave_fn(&self, purity: uint, proto: uint,
-                          n_inputs: uint, retstyle: uint) -> bool;
-
-        fn visit_trait(&self) -> bool;
-        fn visit_var(&self) -> bool;
-        fn visit_var_integral(&self) -> bool;
-        fn visit_param(&self, i: uint) -> bool;
-        fn visit_self(&self) -> bool;
-        fn visit_type(&self) -> bool;
-        fn visit_opaque_box(&self) -> bool;
-        fn visit_constr(&self, inner: *TyDesc) -> bool;
-        fn visit_closure_ptr(&self, ck: uint) -> bool;
-    }
-
-    pub mod rusti {
-        use super::{TyDesc, TyVisitor};
-
-        #[abi = "rust-intrinsic"]
-        pub extern "rust-intrinsic" {
-            pub fn get_tydesc<T>() -> *();
-            pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor);
-        }
-    }
-}
diff --git a/src/librustc/front/intrinsic_inject.rs b/src/librustc/front/intrinsic_inject.rs
deleted file mode 100644
index 0caadc8572e..00000000000
--- a/src/librustc/front/intrinsic_inject.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use core::prelude::*;
-
-use core::vec;
-use driver::session::Session;
-use syntax::parse;
-use syntax::ast;
-use syntax::codemap::spanned;
-
-pub fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate {
-    let intrinsic_module = include_str!("intrinsic.rs").to_managed();
-
-    let item = parse::parse_item_from_source_str(@"<intrinsic>",
-                                                 intrinsic_module,
-                                                 /*bad*/copy sess.opts.cfg,
-                                                 ~[],
-                                                 sess.parse_sess);
-    let item =
-        match item {
-          Some(i) => i,
-          None => {
-            sess.fatal("no item found in intrinsic module");
-          }
-        };
-
-    let items = vec::append(~[item], crate.node.module.items);
-
-    @spanned {
-        node: ast::crate_ {
-            module: ast::_mod {
-                items: items,
-                .. /*bad*/copy crate.node.module
-            },
-            .. /*bad*/copy crate.node
-        },
-        .. /*bad*/copy *crate
-    }
-}
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 3a8d369469b..d73b019c1ea 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -76,16 +76,20 @@ pub enum LangItem {
     UnrecordBorrowFnLangItem,   // 36
 
     StartFnLangItem,            // 37
+
+    TyDescStructLangItem,       // 38
+    TyVisitorTraitLangItem,     // 39
+    OpaqueStructLangItem,       // 40
 }
 
 pub struct LanguageItems {
-    items: [Option<def_id>, ..38]
+    items: [Option<def_id>, ..41]
 }
 
 impl LanguageItems {
     pub fn new() -> LanguageItems {
         LanguageItems {
-            items: [ None, ..38 ]
+            items: [ None, ..41 ]
         }
     }
 
@@ -138,6 +142,10 @@ impl LanguageItems {
 
             37 => "start",
 
+            38 => "ty_desc",
+            39 => "ty_visitor",
+            40 => "opaque",
+
             _ => "???"
         }
     }
@@ -262,6 +270,15 @@ impl LanguageItems {
     pub fn start_fn(&const self) -> def_id {
         self.items[StartFnLangItem as uint].get()
     }
+    pub fn ty_desc(&const self) -> def_id {
+        self.items[TyDescStructLangItem as uint].get()
+    }
+    pub fn ty_visitor(&const self) -> def_id {
+        self.items[TyVisitorTraitLangItem as uint].get()
+    }
+    pub fn opaque(&const self) -> def_id {
+        self.items[OpaqueStructLangItem as uint].get()
+    }
 }
 
 fn LanguageItemCollector(crate: @crate,
@@ -313,6 +330,9 @@ fn LanguageItemCollector(crate: @crate,
     item_refs.insert(@"record_borrow", RecordBorrowFnLangItem as uint);
     item_refs.insert(@"unrecord_borrow", UnrecordBorrowFnLangItem as uint);
     item_refs.insert(@"start", StartFnLangItem as uint);
+    item_refs.insert(@"ty_desc", TyDescStructLangItem as uint);
+    item_refs.insert(@"ty_visitor", TyVisitorTraitLangItem as uint);
+    item_refs.insert(@"opaque", OpaqueStructLangItem as uint);
 
     LanguageItemCollector {
         crate: crate,
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 54bfc25244f..a5a6c1434c6 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -681,9 +681,12 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
             let static_ti = get_tydesc(ccx, tp_ty);
             glue::lazily_emit_all_tydesc_glue(ccx, static_ti);
 
-            // FIXME (#3727): change this to ccx.tydesc_ty.ptr_to() when the
-            // core::sys copy of the get_tydesc interface dies off.
-            let td = PointerCast(bcx, static_ti.tydesc, Type::nil().ptr_to());
+            // FIXME (#3730): ideally this shouldn't need a cast,
+            // but there's a circularity between translating rust types to llvm
+            // types and having a tydesc type available. So I can't directly access
+            // the llvm type of intrinsic::TyDesc struct.
+            let userland_tydesc_ty = type_of::type_of(ccx, output_type);
+            let td = PointerCast(bcx, static_ti.tydesc, userland_tydesc_ty);
             Store(bcx, td, fcx.llretptr.get());
         }
         "init" => {
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index d8ba524b2bd..3b55e843d36 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -232,7 +232,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext,
                                field: uint,
                                ti: @mut tydesc_info) {
     let _icx = push_ctxt("lazily_emit_tydesc_glue");
-    let llfnty = type_of_glue_fn(ccx);
+    let llfnty = Type::glue_fn();
 
     if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
         return;
@@ -338,9 +338,7 @@ pub fn call_tydesc_glue_full(bcx: block,
         }
     };
 
-    Call(bcx, llfn, [C_null(Type::nil().ptr_to()),
-                        C_null(bcx.ccx().tydesc_type.ptr_to().ptr_to()),
-                        llrawptr]);
+    Call(bcx, llfn, [C_null(Type::nil().ptr_to()), llrawptr]);
 }
 
 // See [Note-arg-mode]
@@ -680,7 +678,7 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
 
     let bcx = top_scope_block(fcx, None);
     let lltop = bcx.llbb;
-    let rawptr0_arg = fcx.arg_pos(1u);
+    let rawptr0_arg = fcx.arg_pos(0u);
     let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
     let llty = type_of(ccx, t);
     let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
@@ -715,7 +713,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
     let _icx = push_ctxt("emit_tydescs");
     // As of this point, allow no more tydescs to be created.
     ccx.finished_tydescs = true;
-    let glue_fn_ty = Type::generic_glue_fn(ccx);
+    let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to();
     let tyds = &mut ccx.tydescs;
     for tyds.each_value |&val| {
         let ti = val;
@@ -765,19 +763,13 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               }
             };
 
-
-        let shape = C_null(Type::i8p());
-        let shape_tables = C_null(Type::i8p());
-
         let tydesc = C_named_struct(ccx.tydesc_type,
-                           [ti.size, // size
-                            ti.align, // align
-                            take_glue, // take_glue
-                            drop_glue, // drop_glue
-                            free_glue, // free_glue
-                            visit_glue, // visit_glue
-                            shape, // shape
-                            shape_tables]); // shape_tables
+                                    [ti.size, // size
+                                    ti.align, // align
+                                    take_glue, // take_glue
+                                    drop_glue, // drop_glue
+                                    free_glue, // free_glue
+                                    visit_glue]); // visit_glue
 
         unsafe {
             let gvar = ti.tydesc;
@@ -788,8 +780,3 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
         }
     };
 }
-
-fn type_of_glue_fn(ccx: &CrateContext) -> Type {
-    let tydescpp = ccx.tydesc_type.ptr_to().ptr_to();
-    Type::func([ Type::nil().ptr_to(), tydescpp, Type::i8p() ], &Type::void())
-}
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 316eb6893f2..c2a8b47f245 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -274,9 +274,7 @@ impl Reflector {
             let repr = adt::represent_type(bcx.ccx(), t);
             let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
             let llptrty = type_of(ccx, t).ptr_to();
-            let (_, opaquety) =
-                ccx.tcx.intrinsic_defs.find_copy(&ccx.sess.ident_of("Opaque"))
-                .expect("Failed to resolve intrinsic::Opaque");
+            let opaquety = ty::get_opaque_ty(ccx.tcx);
             let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm });
 
             let make_get_disr = || {
@@ -373,10 +371,8 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block,
                                     visitor_val: ValueRef,
                                     visitor_trait_id: def_id)
                                  -> block {
-    use syntax::parse::token::special_idents::tydesc;
     let final = sub_block(bcx, "final");
-    assert!(bcx.ccx().tcx.intrinsic_defs.contains_key(&tydesc));
-    let (_, tydesc_ty) = bcx.ccx().tcx.intrinsic_defs.get_copy(&tydesc);
+    let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx);
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
     let mut r = Reflector {
         visitor_val: visitor_val,
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 34a15033109..64688ac4134 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -20,7 +20,6 @@ use middle::trans::base;
 
 use syntax::ast;
 use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
-use back::abi;
 
 use core::vec;
 use core::cast;
@@ -189,25 +188,26 @@ impl Type {
             None => ()
         }
 
-        let ty = cx.tydesc_type.get_field(abi::tydesc_field_drop_glue);
+        let ty = Type::glue_fn();
         cx.tn.associate_type("glue_fn", &ty);
 
         return ty;
     }
 
+    pub fn glue_fn() -> Type {
+        Type::func([ Type::nil().ptr_to(), Type::i8p() ],
+            &Type::void())
+    }
+
     pub fn tydesc(arch: Architecture) -> Type {
         let mut tydesc = Type::named_struct("tydesc");
-        let tydescpp = tydesc.ptr_to().ptr_to();
-        let pvoid = Type::i8p();
-        let glue_fn_ty = Type::func([ Type::nil().ptr_to(), tydescpp, pvoid ],
-            &Type::void()).ptr_to();
+        let glue_fn_ty = Type::glue_fn().ptr_to();
 
         let int_ty = Type::int(arch);
 
         let elems = [
             int_ty, int_ty,
-            glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
-            pvoid, pvoid
+            glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty
         ];
 
         tydesc.set_struct_body(elems, false);
@@ -265,10 +265,6 @@ impl Type {
         cx.int_type
     }
 
-    pub fn captured_tydescs(ctx: &CrateContext, num: uint) -> Type {
-        Type::struct_(vec::from_elem(num, ctx.tydesc_type.ptr_to()), false)
-    }
-
     pub fn opaque_trait(ctx: &CrateContext, store: ty::TraitStore) -> Type {
         let tydesc_ptr = ctx.tydesc_type.ptr_to();
         match store {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index bc163f4a725..0518e6b7cf7 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -44,7 +44,6 @@ use syntax::attr;
 use syntax::codemap::span;
 use syntax::codemap;
 use syntax::parse::token;
-use syntax::parse::token::special_idents;
 use syntax::{ast, ast_map};
 use syntax::opt_vec::OptVec;
 use syntax::opt_vec;
@@ -276,8 +275,7 @@ struct ctxt_ {
     trait_defs: @mut HashMap<def_id, @TraitDef>,
 
     items: ast_map::map,
-    intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
-    intrinsic_traits: @mut HashMap<ast::ident, @TraitRef>,
+    intrinsic_defs: @mut HashMap<ast::def_id, t>,
     freevars: freevars::freevar_map,
     tcache: type_cache,
     rcache: creader_cache,
@@ -954,7 +952,6 @@ pub fn mk_ctxt(s: session::Session,
         node_type_substs: @mut HashMap::new(),
         trait_refs: @mut HashMap::new(),
         trait_defs: @mut HashMap::new(),
-        intrinsic_traits: @mut HashMap::new(),
         items: amap,
         intrinsic_defs: @mut HashMap::new(),
         freevars: freevars,
@@ -4469,10 +4466,26 @@ pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
     }
 }
 
+pub fn get_tydesc_ty(tcx: ctxt) -> t {
+    let tydesc_lang_item = tcx.lang_items.ty_desc();
+    tcx.intrinsic_defs.find_copy(&tydesc_lang_item)
+        .expect("Failed to resolve TyDesc")
+}
+
+pub fn get_opaque_ty(tcx: ctxt) -> t {
+    let opaque_lang_item = tcx.lang_items.opaque();
+    tcx.intrinsic_defs.find_copy(&opaque_lang_item)
+        .expect("Failed to resolve Opaque")
+}
+
 pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
-    let ty_visitor_name = special_idents::ty_visitor;
-    assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
-    let trait_ref = tcx.intrinsic_traits.get_copy(&ty_visitor_name);
+    let substs = substs {
+        self_r: None,
+        self_ty: None,
+        tps: ~[]
+    };
+    let trait_lang_item = tcx.lang_items.ty_visitor();
+    let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
     (trait_ref,
      mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs,
               BoxTraitStore, ast::m_imm, EmptyBuiltinBounds()))
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 1c032466ca6..eb505338e4b 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3506,13 +3506,15 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
             }
 
             "get_tydesc" => {
-              // FIXME (#3730): return *intrinsic::tydesc, not *()
-              (1u, ~[], ty::mk_nil_ptr(ccx.tcx))
+              let tydesc_ty = ty::get_tydesc_ty(ccx.tcx);
+              let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
+                  ty: tydesc_ty,
+                  mutbl: ast::m_imm
+              });
+              (1u, ~[], td_ptr)
             }
             "visit_tydesc" => {
-              let tydesc_name = special_idents::tydesc;
-              assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
-              let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name);
+              let tydesc_ty = ty::get_tydesc_ty(ccx.tcx);
               let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
                   ty: tydesc_ty,
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 33e483e552a..3554376902c 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -62,55 +62,16 @@ use syntax::opt_vec::OptVec;
 use syntax::opt_vec;
 
 pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
-
-    // FIXME (#2592): hooking into the "intrinsic" root module is crude.
-    // There ought to be a better approach. Attributes?
-
-    for crate.node.module.items.iter().advance |crate_item| {
-        if crate_item.ident
-            == ::syntax::parse::token::special_idents::intrinsic {
-
-            match crate_item.node {
-              ast::item_mod(ref m) => {
-                for m.items.iter().advance |intrinsic_item| {
-                    let def_id = ast::def_id { crate: ast::local_crate,
-                                               node: intrinsic_item.id };
-                    let substs = substs {
-                        self_r: None,
-                        self_ty: None,
-                        tps: ~[]
-                    };
-
-                    match intrinsic_item.node {
-                      ast::item_trait(*) => {
-                          let tref = @ty::TraitRef {def_id: def_id,
-                                                    substs: substs};
-                          ccx.tcx.intrinsic_traits.insert
-                              (intrinsic_item.ident, tref);
-                      }
-
-                      ast::item_enum(*) => {
-                        let ty = ty::mk_enum(ccx.tcx, def_id, substs);
-                        ccx.tcx.intrinsic_defs.insert
-                            (intrinsic_item.ident, (def_id, ty));
-                      }
-
-                      ast::item_struct(*) => {
-                        let ty = ty::mk_struct(ccx.tcx, def_id, substs);
-                        ccx.tcx.intrinsic_defs.insert
-                            (intrinsic_item.ident, (def_id, ty));
-                      }
-
-                      _ => {}
-                    }
-                }
-              }
-              _ => { }
-            }
-            break;
-        }
+    fn collect_intrinsic_type(ccx: @mut CrateCtxt,
+                              lang_item: ast::def_id) {
+        let ty::ty_param_bounds_and_ty { ty: ty, _ } =
+            ccx.get_item_ty(lang_item);
+        ccx.tcx.intrinsic_defs.insert(lang_item, ty);
     }
 
+    collect_intrinsic_type(ccx, ccx.tcx.lang_items.ty_desc());
+    collect_intrinsic_type(ccx, ccx.tcx.lang_items.opaque());
+
     visit::visit_crate(
         crate, ((),
         visit::mk_simple_visitor(@visit::SimpleVisitor {
diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc
index d59a308beb5..20705b3d797 100644
--- a/src/librustc/rustc.rc
+++ b/src/librustc/rustc.rc
@@ -86,7 +86,6 @@ pub mod front {
     pub mod config;
     pub mod test;
     pub mod std_inject;
-    pub mod intrinsic_inject;
 }
 
 pub mod back {
diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs
index b871ed3d57a..5a2f948600a 100644
--- a/src/libstd/at_vec.rs
+++ b/src/libstd/at_vec.rs
@@ -25,13 +25,16 @@ use vec::ImmutableVector;
 
 pub mod rustrt {
     use libc;
-    use sys;
     use vec;
+    #[cfg(stage0)]
+    use intrinsic::{TyDesc};
+    #[cfg(not(stage0))]
+    use unstable::intrinsics::{TyDesc};
 
     #[abi = "cdecl"]
     #[link_name = "rustrt"]
     pub extern {
-        pub unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc,
+        pub unsafe fn vec_reserve_shared_actual(t: *TyDesc,
                                                 v: **vec::raw::VecRepr,
                                                 n: libc::size_t);
     }
@@ -197,6 +200,10 @@ pub mod raw {
     use uint;
     use unstable::intrinsics::{move_val_init};
     use vec;
+    #[cfg(stage0)]
+    use intrinsic::{get_tydesc};
+    #[cfg(not(stage0))]
+    use unstable::intrinsics::{get_tydesc};
 
     pub type VecRepr = vec::raw::VecRepr;
     pub type SliceRepr = vec::raw::SliceRepr;
@@ -258,7 +265,7 @@ pub mod raw {
         // Only make the (slow) call into the runtime if we have to
         if capacity(*v) < n {
             let ptr: **VecRepr = transmute(v);
-            rustrt::vec_reserve_shared_actual(sys::get_type_desc::<T>(),
+            rustrt::vec_reserve_shared_actual(get_tydesc::<T>(),
                                               ptr, n as libc::size_t);
         }
     }
diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs
index d1460b7a3c9..ee9fdd3c620 100644
--- a/src/libstd/cleanup.rs
+++ b/src/libstd/cleanup.rs
@@ -10,24 +10,19 @@
 
 #[doc(hidden)];
 
-use libc::{c_char, c_void, intptr_t, uintptr_t};
-use ptr::mut_null;
+use libc::{c_char, intptr_t, uintptr_t};
+use ptr::{mut_null};
 use repr::BoxRepr;
-use sys::TypeDesc;
 use cast::transmute;
+use unstable::intrinsics::TyDesc;
 #[cfg(not(test))] use unstable::lang::clear_task_borrow_list;
 
-#[cfg(not(test))] use ptr::to_unsafe_ptr;
-
 /**
  * Runtime structures
  *
  * NB: These must match the representation in the C++ runtime.
  */
 
-type DropGlue<'self> = &'self fn(**TypeDesc, *c_void);
-type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void);
-
 type TaskID = uintptr_t;
 
 struct StackSegment { priv opaque: () }
@@ -164,6 +159,19 @@ fn debug_mem() -> bool {
     false
 }
 
+#[inline]
+#[cfg(not(stage0))]
+unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
+    // This function should be inlined when stage0 is gone
+    ((*tydesc).drop_glue)(data);
+}
+
+#[inline]
+#[cfg(stage0)]
+unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
+    ((*tydesc).drop_glue)(0 as **TyDesc, data);
+}
+
 /// Destroys all managed memory (i.e. @ boxes) held by the current task.
 #[cfg(not(test))]
 #[lang="annihilate"]
@@ -205,9 +213,9 @@ pub unsafe fn annihilate() {
     // callback, as the original value may have been freed.
     for each_live_alloc(false) |box, uniq| {
         if !uniq {
-            let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
-            let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
-            drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
+            let tydesc = (*box).header.type_desc;
+            let data = transmute(&(*box).data);
+            call_drop_glue(tydesc, data);
         }
     }
 
diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs
index 611b95a7745..c9e33219fa5 100644
--- a/src/libstd/gc.rs
+++ b/src/libstd/gc.rs
@@ -40,12 +40,13 @@ with destructors.
 use cast;
 use container::{Map, Set};
 use io;
-use libc::{size_t, uintptr_t};
+use libc::{uintptr_t};
 use option::{None, Option, Some};
 use ptr;
 use hashmap::HashSet;
 use stackwalk::walk_stack;
 use sys;
+use unstable::intrinsics::{TyDesc};
 
 pub use stackwalk::Word;
 
@@ -58,18 +59,12 @@ pub struct StackSegment {
 }
 
 pub mod rustrt {
-    use libc::size_t;
     use stackwalk::Word;
     use super::StackSegment;
 
     #[link_name = "rustrt"]
     pub extern {
         #[rust_stack]
-        pub unsafe fn rust_call_tydesc_glue(root: *Word,
-                                            tydesc: *Word,
-                                            field: size_t);
-
-        #[rust_stack]
         pub unsafe fn rust_gc_metadata() -> *Word;
 
         pub unsafe fn rust_get_stack_segment() -> *StackSegment;
@@ -125,7 +120,7 @@ unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
     return None;
 }
 
-type Visitor<'self> = &'self fn(root: **Word, tydesc: *Word) -> bool;
+type Visitor<'self> = &'self fn(root: **Word, tydesc: *TyDesc) -> bool;
 
 // Walks the list of roots for the given safe point, and calls visitor
 // on each root.
@@ -139,7 +134,7 @@ unsafe fn _walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool {
     let stack_roots: *u32 = bump(sp_meta, 2);
     let reg_roots: *u8 = bump(stack_roots, num_stack_roots);
     let addrspaces: *Word = align_to_pointer(bump(reg_roots, num_reg_roots));
-    let tydescs: ***Word = bump(addrspaces, num_stack_roots);
+    let tydescs: ***TyDesc = bump(addrspaces, num_stack_roots);
 
     // Stack roots
     let mut sri = 0;
@@ -321,6 +316,19 @@ fn expect_sentinel() -> bool { true }
 #[cfg(nogc)]
 fn expect_sentinel() -> bool { false }
 
+#[inline]
+#[cfg(not(stage0))]
+unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
+    // This function should be inlined when stage0 is gone
+    ((*tydesc).drop_glue)(data);
+}
+
+#[inline]
+#[cfg(stage0)]
+unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
+    ((*tydesc).drop_glue)(0 as **TyDesc, data);
+}
+
 // Entry point for GC-based cleanup. Walks stack looking for exchange
 // heap and stack allocations requiring drop, and runs all
 // destructors.
@@ -364,7 +372,7 @@ pub fn cleanup_stack_for_failure() {
                 // FIXME #4420: Destroy this box
                 // FIXME #4330: Destroy this box
             } else {
-                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
+                call_drop_glue(tydesc, *root as *i8);
             }
         }
     }
diff --git a/src/libstd/managed.rs b/src/libstd/managed.rs
index d514612b5af..b71b3b503c2 100644
--- a/src/libstd/managed.rs
+++ b/src/libstd/managed.rs
@@ -15,7 +15,7 @@ use ptr::to_unsafe_ptr;
 #[cfg(not(test))] use cmp::{Eq, Ord};
 
 pub mod raw {
-    use intrinsic::TyDesc;
+    use std::unstable::intrinsics::TyDesc;
 
     pub static RC_EXCHANGE_UNIQUE : uint = (-1) as uint;
     pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs
index d276abf0c8b..16ab4771d0d 100644
--- a/src/libstd/reflect.rs
+++ b/src/libstd/reflect.rs
@@ -16,8 +16,10 @@ Runtime type reflection
 
 #[allow(missing_doc)];
 
-use intrinsic::{TyDesc, TyVisitor};
-use intrinsic::Opaque;
+#[cfg(stage0)]
+use intrinsic::{Opaque, TyDesc, TyVisitor};
+#[cfg(not(stage0))]
+use unstable::intrinsics::{Opaque, TyDesc, TyVisitor};
 use libc::c_void;
 use sys;
 use vec;
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs
index ab3f83d34d5..f39b5a00ed0 100644
--- a/src/libstd/repr.rs
+++ b/src/libstd/repr.rs
@@ -19,9 +19,6 @@ More runtime type reflection
 use cast::transmute;
 use char;
 use container::Container;
-use intrinsic;
-use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
-use intrinsic::Opaque;
 use io::{Writer, WriterUtil};
 use iterator::IteratorUtil;
 use libc::c_void;
@@ -34,6 +31,10 @@ use to_str::ToStr;
 use vec::raw::{VecRepr, SliceRepr};
 use vec;
 use vec::{OwnedVector, UnboxedVecRepr};
+#[cfg(stage0)]
+use intrinsic::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
+#[cfg(not(stage0))]
+use unstable::intrinsics::{Opaque, TyDesc, TyVisitor, get_tydesc, visit_tydesc};
 
 #[cfg(test)] use io;
 
@@ -564,6 +565,7 @@ impl TyVisitor for ReprVisitor {
     fn visit_self(&self) -> bool { true }
     fn visit_type(&self) -> bool { true }
 
+    #[cfg(not(stage0))]
     fn visit_opaque_box(&self) -> bool {
         self.writer.write_char('@');
         do self.get::<&managed::raw::BoxRepr> |b| {
@@ -571,6 +573,16 @@ impl TyVisitor for ReprVisitor {
             self.visit_ptr_inner(p, b.header.type_desc);
         }
     }
+    #[cfg(stage0)]
+    fn visit_opaque_box(&self) -> bool {
+        self.writer.write_char('@');
+        do self.get::<&managed::raw::BoxRepr> |b| {
+            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
+            unsafe {
+                self.visit_ptr_inner(p, transmute(b.header.type_desc));
+            }
+        }
+    }
 
     // Type no longer exists, vestigial function.
     fn visit_constr(&self, _inner: *TyDesc) -> bool { fail!(); }
@@ -581,7 +593,7 @@ impl TyVisitor for ReprVisitor {
 pub fn write_repr<T>(writer: @Writer, object: &T) {
     unsafe {
         let ptr = ptr::to_unsafe_ptr(object) as *c_void;
-        let tydesc = intrinsic::get_tydesc::<T>();
+        let tydesc = get_tydesc::<T>();
         let u = ReprVisitor(ptr, writer);
         let v = reflect::MovePtrAdaptor(u);
         visit_tydesc(tydesc, @v as @TyVisitor)
diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs
index ce7ff87b445..1e9f9aab834 100644
--- a/src/libstd/rt/global_heap.rs
+++ b/src/libstd/rt/global_heap.rs
@@ -8,26 +8,22 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use sys::{TypeDesc, size_of};
+use sys::{size_of};
 use libc::{c_void, size_t, uintptr_t};
 use c_malloc = libc::malloc;
 use c_free = libc::free;
 use managed::raw::{BoxHeaderRepr, BoxRepr};
 use cast::transmute;
-use unstable::intrinsics::{atomic_xadd,atomic_xsub};
+use unstable::intrinsics::{atomic_xadd,atomic_xsub,TyDesc};
 use ptr::null;
-use intrinsic::TyDesc;
 
-pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
+pub unsafe fn malloc(td: *TyDesc, size: uint) -> *c_void {
     assert!(td.is_not_null());
 
     let total_size = get_box_size(size, (*td).align);
     let p = c_malloc(total_size as size_t);
     assert!(p.is_not_null());
 
-    // FIXME #3475: Converting between our two different tydesc types
-    let td: *TyDesc = transmute(td);
-
     let box: &mut BoxRepr = transmute(p);
     box.header.ref_count = -1; // Exchange values not ref counted
     box.header.type_desc = td;
diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs
index 79ea60cc224..a1d6342323c 100644
--- a/src/libstd/sys.rs
+++ b/src/libstd/sys.rs
@@ -17,23 +17,11 @@ use cast;
 use gc;
 use io;
 use libc;
-use libc::{c_void, c_char, size_t};
+use libc::{c_char, size_t};
 use repr;
 use str;
 use unstable::intrinsics;
 
-pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);
-
-// Corresponds to runtime type_desc type
-pub struct TypeDesc {
-    size: uint,
-    align: uint,
-    take_glue: uint,
-    drop_glue: uint,
-    free_glue: uint
-    // Remaining fields not listed
-}
-
 /// The representation of a Rust closure
 pub struct Closure {
     code: *(),
@@ -51,23 +39,6 @@ pub mod rustrt {
     }
 }
 
-/**
- * Returns a pointer to a type descriptor.
- *
- * Useful for calling certain function in the Rust runtime or otherwise
- * performing dark magick.
- */
-#[inline]
-pub fn get_type_desc<T>() -> *TypeDesc {
-    unsafe { intrinsics::get_tydesc::<T>() as *TypeDesc }
-}
-
-/// Returns a pointer to a type descriptor.
-#[inline]
-pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc {
-    get_type_desc::<T>()
-}
-
 /// Returns the size of a type
 #[inline]
 pub fn size_of<T>() -> uint {
diff --git a/src/libstd/unstable/exchange_alloc.rs b/src/libstd/unstable/exchange_alloc.rs
index 3b35c2fb804..5c47901df48 100644
--- a/src/libstd/unstable/exchange_alloc.rs
+++ b/src/libstd/unstable/exchange_alloc.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use sys::{TypeDesc, size_of};
+use sys::size_of;
 use libc::{c_void, size_t};
 use c_malloc = libc::malloc;
 use c_free = libc::free;
@@ -16,18 +16,18 @@ use managed::raw::{BoxHeaderRepr, BoxRepr};
 use cast::transmute;
 use unstable::intrinsics::{atomic_xadd,atomic_xsub};
 use ptr::null;
+#[cfg(stage0)]
 use intrinsic::TyDesc;
+#[cfg(not(stage0))]
+use unstable::intrinsics::TyDesc;
 
-pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
+pub unsafe fn malloc(td: *TyDesc, size: uint) -> *c_void {
     assert!(td.is_not_null());
 
     let total_size = get_box_size(size, (*td).align);
     let p = c_malloc(total_size as size_t);
     assert!(p.is_not_null());
 
-    // FIXME #3475: Converting between our two different tydesc types
-    let td: *TyDesc = transmute(td);
-
     let box: &mut BoxRepr = transmute(p);
     box.header.ref_count = -1; // Exchange values not ref counted
     box.header.type_desc = td;
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index 109f665e41d..1254a591293 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -32,6 +32,130 @@ A quick refresher on memory ordering:
 
 */
 
+// This is needed to prevent duplicate lang item definitions.
+#[cfg(test)]
+pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
+
+#[cfg(not(stage0))]
+pub type GlueFn = extern "Rust" fn(*i8);
+
+#[cfg(stage0)]
+pub type GlueFn = extern "Rust" fn(**TyDesc, *i8);
+
+// NB: this has to be kept in sync with the Rust ABI.
+#[lang="ty_desc"]
+#[cfg(not(test))]
+pub struct TyDesc {
+    size: uint,
+    align: uint,
+    take_glue: GlueFn,
+    drop_glue: GlueFn,
+    free_glue: GlueFn,
+    visit_glue: GlueFn,
+}
+
+#[lang="opaque"]
+#[cfg(not(test))]
+pub enum Opaque { }
+
+#[lang="ty_visitor"]
+#[cfg(not(test))]
+pub trait TyVisitor {
+    fn visit_bot(&self) -> bool;
+    fn visit_nil(&self) -> bool;
+    fn visit_bool(&self) -> bool;
+
+    fn visit_int(&self) -> bool;
+    fn visit_i8(&self) -> bool;
+    fn visit_i16(&self) -> bool;
+    fn visit_i32(&self) -> bool;
+    fn visit_i64(&self) -> bool;
+
+    fn visit_uint(&self) -> bool;
+    fn visit_u8(&self) -> bool;
+    fn visit_u16(&self) -> bool;
+    fn visit_u32(&self) -> bool;
+    fn visit_u64(&self) -> bool;
+
+    fn visit_float(&self) -> bool;
+    fn visit_f32(&self) -> bool;
+    fn visit_f64(&self) -> bool;
+
+    fn visit_char(&self) -> bool;
+    fn visit_str(&self) -> bool;
+
+    fn visit_estr_box(&self) -> bool;
+    fn visit_estr_uniq(&self) -> bool;
+    fn visit_estr_slice(&self) -> bool;
+    fn visit_estr_fixed(&self, n: uint, sz: uint, align: uint) -> bool;
+
+    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool;
+
+    fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
+                        mtbl: uint, inner: *TyDesc) -> bool;
+
+    fn visit_enter_rec(&self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+    fn visit_rec_field(&self, i: uint, name: &str,
+                       mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_rec(&self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+
+    fn visit_enter_class(&self, n_fields: uint,
+                         sz: uint, align: uint) -> bool;
+    fn visit_class_field(&self, i: uint, name: &str,
+                         mtbl: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_class(&self, n_fields: uint,
+                         sz: uint, align: uint) -> bool;
+
+    fn visit_enter_tup(&self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_tup(&self, n_fields: uint,
+                       sz: uint, align: uint) -> bool;
+
+    fn visit_enter_enum(&self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint) -> bool;
+    fn visit_enter_enum_variant(&self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool;
+    fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_enum_variant(&self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool;
+    fn visit_leave_enum(&self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint) -> bool;
+
+    fn visit_enter_fn(&self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool;
+    fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool;
+    fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool;
+    fn visit_leave_fn(&self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool;
+
+    fn visit_trait(&self) -> bool;
+    fn visit_var(&self) -> bool;
+    fn visit_var_integral(&self) -> bool;
+    fn visit_param(&self, i: uint) -> bool;
+    fn visit_self(&self) -> bool;
+    fn visit_type(&self) -> bool;
+    fn visit_opaque_box(&self) -> bool;
+    fn visit_constr(&self, inner: *TyDesc) -> bool;
+    fn visit_closure_ptr(&self, ck: uint) -> bool;
+}
+
 #[abi = "rust-intrinsic"]
 pub extern "rust-intrinsic" {
 
@@ -159,6 +283,9 @@ pub extern "rust-intrinsic" {
     pub fn pref_align_of<T>() -> uint;
 
     /// Get a static pointer to a type descriptor.
+    #[cfg(not(stage0))]
+    pub fn get_tydesc<T>() -> *TyDesc;
+    #[cfg(stage0)]
     pub fn get_tydesc<T>() -> *();
 
     /// Create a value initialized to zero.
@@ -181,9 +308,8 @@ pub extern "rust-intrinsic" {
     /// Returns `true` if a type requires drop glue.
     pub fn needs_drop<T>() -> bool;
 
-    // XXX: intrinsic uses legacy modes and has reference to TyDesc
-    // and TyVisitor which are in librustc
-    //fn visit_tydesc(++td: *TyDesc, &&tv: TyVisitor) -> ();
+    #[cfg(not(stage0))]
+    pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor);
 
     pub fn frame_address(f: &once fn(*u8));
 
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index e39dd262cd9..72b58307849 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -30,6 +30,10 @@ use sys;
 use sys::size_of;
 use uint;
 use unstable::intrinsics;
+#[cfg(stage0)]
+use intrinsic::{get_tydesc};
+#[cfg(not(stage0))]
+use unstable::intrinsics::{get_tydesc};
 use vec;
 use util;
 
@@ -37,19 +41,22 @@ use util;
 
 pub mod rustrt {
     use libc;
-    use sys;
     use vec::raw;
+    #[cfg(stage0)]
+    use intrinsic::{TyDesc};
+    #[cfg(not(stage0))]
+    use unstable::intrinsics::{TyDesc};
 
     #[abi = "cdecl"]
     pub extern {
         // These names are terrible. reserve_shared applies
         // to ~[] and reserve_shared_actual applies to @[].
         #[fast_ffi]
-        unsafe fn vec_reserve_shared(t: *sys::TypeDesc,
+        unsafe fn vec_reserve_shared(t: *TyDesc,
                                      v: **raw::VecRepr,
                                      n: libc::size_t);
         #[fast_ffi]
-        unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc,
+        unsafe fn vec_reserve_shared_actual(t: *TyDesc,
                                             v: **raw::VecRepr,
                                             n: libc::size_t);
     }
@@ -78,7 +85,7 @@ pub fn reserve<T>(v: &mut ~[T], n: uint) {
     if capacity(v) < n {
         unsafe {
             let ptr: **raw::VecRepr = cast::transmute(v);
-            let td = sys::get_type_desc::<T>();
+            let td = get_tydesc::<T>();
             if ((**ptr).box_header.ref_count ==
                 managed::raw::RC_MANAGED_UNIQUE) {
                 rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t);
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 273a59f0a3d..d40b96f077b 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -331,21 +331,18 @@ pub mod special_idents {
     pub static str : ident = ident { name: 19, ctxt: 0}; // for the type
 
     /* outside of libsyntax */
-    pub static ty_visitor : ident = ident { name: 20, ctxt: 0};
-    pub static arg : ident = ident { name: 21, ctxt: 0};
-    pub static descrim : ident = ident { name: 22, ctxt: 0};
-    pub static clownshoe_abi : ident = ident { name: 23, ctxt: 0};
-    pub static clownshoe_stack_shim : ident = ident { name: 24, ctxt: 0};
-    pub static tydesc : ident = ident { name: 25, ctxt: 0};
-    pub static main : ident = ident { name: 26, ctxt: 0};
-    pub static opaque : ident = ident { name: 27, ctxt: 0};
-    pub static blk : ident = ident { name: 28, ctxt: 0};
-    pub static statik : ident = ident { name: 29, ctxt: 0};
-    pub static intrinsic : ident = ident { name: 30, ctxt: 0};
-    pub static clownshoes_foreign_mod: ident = ident { name: 31, ctxt: 0};
-    pub static unnamed_field: ident = ident { name: 32, ctxt: 0};
-    pub static c_abi: ident = ident { name: 33, ctxt: 0};
-    pub static type_self: ident = ident { name: 34, ctxt: 0};    // `Self`
+    pub static arg : ident = ident { name: 20, ctxt: 0};
+    pub static descrim : ident = ident { name: 21, ctxt: 0};
+    pub static clownshoe_abi : ident = ident { name: 22, ctxt: 0};
+    pub static clownshoe_stack_shim : ident = ident { name: 23, ctxt: 0};
+    pub static main : ident = ident { name: 24, ctxt: 0};
+    pub static opaque : ident = ident { name: 25, ctxt: 0};
+    pub static blk : ident = ident { name: 26, ctxt: 0};
+    pub static statik : ident = ident { name: 27, ctxt: 0};
+    pub static clownshoes_foreign_mod: ident = ident { name: 28, ctxt: 0};
+    pub static unnamed_field: ident = ident { name: 29, ctxt: 0};
+    pub static c_abi: ident = ident { name: 30, ctxt: 0};
+    pub static type_self: ident = ident { name: 31, ctxt: 0};    // `Self`
 }
 
 /**
@@ -426,59 +423,56 @@ fn mk_fresh_ident_interner() -> @ident_interner {
         "tt",                 // 17
         "matchers",           // 18
         "str",                // 19
-        "TyVisitor",          // 20
-        "arg",                // 21
-        "descrim",            // 22
-        "__rust_abi",         // 23
-        "__rust_stack_shim",  // 24
-        "TyDesc",             // 25
-        "main",               // 26
-        "<opaque>",           // 27
-        "blk",                // 28
-        "static",             // 29
-        "intrinsic",          // 30
-        "__foreign_mod__",    // 31
-        "__field__",          // 32
-        "C",                  // 33
-        "Self",               // 34
-
-        "as",                 // 35
-        "break",              // 36
-        "const",              // 37
-        "copy",               // 38
-        "do",                 // 39
-        "else",               // 40
-        "enum",               // 41
-        "extern",             // 42
-        "false",              // 43
-        "fn",                 // 44
-        "for",                // 45
-        "if",                 // 46
-        "impl",               // 47
-        "let",                // 48
-        "__log",              // 49
-        "loop",               // 50
-        "match",              // 51
-        "mod",                // 52
-        "mut",                // 53
-        "once",               // 54
-        "priv",               // 55
-        "pub",                // 56
-        "pure",               // 57
-        "ref",                // 58
-        "return",             // 59
-        "static",             // 29 -- also a special ident
+        "arg",                // 20
+        "descrim",            // 21
+        "__rust_abi",         // 22
+        "__rust_stack_shim",  // 23
+        "main",               // 24
+        "<opaque>",           // 25
+        "blk",                // 26
+        "static",             // 27
+        "__foreign_mod__",    // 28
+        "__field__",          // 29
+        "C",                  // 30
+        "Self",               // 31
+
+        "as",                 // 32
+        "break",              // 33
+        "const",              // 34
+        "copy",               // 35
+        "do",                 // 36
+        "else",               // 37
+        "enum",               // 38
+        "extern",             // 39
+        "false",              // 40
+        "fn",                 // 41
+        "for",                // 42
+        "if",                 // 43
+        "impl",               // 44
+        "let",                // 45
+        "__log",              // 46
+        "loop",               // 47
+        "match",              // 48
+        "mod",                // 49
+        "mut",                // 50
+        "once",               // 51
+        "priv",               // 52
+        "pub",                // 53
+        "pure",               // 54
+        "ref",                // 55
+        "return",             // 56
+        "static",             // 27 -- also a special ident
         "self",               //  8 -- also a special ident
-        "struct",             // 60
-        "super",              // 61
-        "true",               // 62
-        "trait",              // 63
-        "type",               // 64
-        "unsafe",             // 65
-        "use",                // 66
-        "while",              // 67
-
-        "be",                 // 68
+        "struct",             // 57
+        "super",              // 58
+        "true",               // 59
+        "trait",              // 60
+        "type",               // 61
+        "unsafe",             // 62
+        "use",                // 63
+        "while",              // 64
+
+        "be",                 // 65
     ];
 
     @ident_interner {
@@ -612,42 +606,42 @@ pub mod keywords {
     impl Keyword {
         pub fn to_ident(&self) -> ident {
             match *self {
-                As => ident { name: 35, ctxt: 0 },
-                Break => ident { name: 36, ctxt: 0 },
-                Const => ident { name: 37, ctxt: 0 },
-                Copy => ident { name: 38, ctxt: 0 },
-                Do => ident { name: 39, ctxt: 0 },
-                Else => ident { name: 40, ctxt: 0 },
-                Enum => ident { name: 41, ctxt: 0 },
-                Extern => ident { name: 42, ctxt: 0 },
-                False => ident { name: 43, ctxt: 0 },
-                Fn => ident { name: 44, ctxt: 0 },
-                For => ident { name: 45, ctxt: 0 },
-                If => ident { name: 46, ctxt: 0 },
-                Impl => ident { name: 47, ctxt: 0 },
-                Let => ident { name: 48, ctxt: 0 },
-                __Log => ident { name: 49, ctxt: 0 },
-                Loop => ident { name: 50, ctxt: 0 },
-                Match => ident { name: 51, ctxt: 0 },
-                Mod => ident { name: 52, ctxt: 0 },
-                Mut => ident { name: 53, ctxt: 0 },
-                Once => ident { name: 54, ctxt: 0 },
-                Priv => ident { name: 55, ctxt: 0 },
-                Pub => ident { name: 56, ctxt: 0 },
-                Pure => ident { name: 57, ctxt: 0 },
-                Ref => ident { name: 58, ctxt: 0 },
-                Return => ident { name: 59, ctxt: 0 },
-                Static => ident { name: 29, ctxt: 0 },
+                As => ident { name: 32, ctxt: 0 },
+                Break => ident { name: 33, ctxt: 0 },
+                Const => ident { name: 34, ctxt: 0 },
+                Copy => ident { name: 35, ctxt: 0 },
+                Do => ident { name: 36, ctxt: 0 },
+                Else => ident { name: 37, ctxt: 0 },
+                Enum => ident { name: 38, ctxt: 0 },
+                Extern => ident { name: 39, ctxt: 0 },
+                False => ident { name: 40, ctxt: 0 },
+                Fn => ident { name: 41, ctxt: 0 },
+                For => ident { name: 42, ctxt: 0 },
+                If => ident { name: 43, ctxt: 0 },
+                Impl => ident { name: 44, ctxt: 0 },
+                Let => ident { name: 45, ctxt: 0 },
+                __Log => ident { name: 46, ctxt: 0 },
+                Loop => ident { name: 47, ctxt: 0 },
+                Match => ident { name: 48, ctxt: 0 },
+                Mod => ident { name: 49, ctxt: 0 },
+                Mut => ident { name: 50, ctxt: 0 },
+                Once => ident { name: 51, ctxt: 0 },
+                Priv => ident { name: 52, ctxt: 0 },
+                Pub => ident { name: 53, ctxt: 0 },
+                Pure => ident { name: 54, ctxt: 0 },
+                Ref => ident { name: 55, ctxt: 0 },
+                Return => ident { name: 56, ctxt: 0 },
+                Static => ident { name: 27, ctxt: 0 },
                 Self => ident { name: 8, ctxt: 0 },
-                Struct => ident { name: 60, ctxt: 0 },
-                Super => ident { name: 61, ctxt: 0 },
-                True => ident { name: 62, ctxt: 0 },
-                Trait => ident { name: 63, ctxt: 0 },
-                Type => ident { name: 64, ctxt: 0 },
-                Unsafe => ident { name: 65, ctxt: 0 },
-                Use => ident { name: 66, ctxt: 0 },
-                While => ident { name: 67, ctxt: 0 },
-                Be => ident { name: 68, ctxt: 0 },
+                Struct => ident { name: 57, ctxt: 0 },
+                Super => ident { name: 58, ctxt: 0 },
+                True => ident { name: 59, ctxt: 0 },
+                Trait => ident { name: 60, ctxt: 0 },
+                Type => ident { name: 61, ctxt: 0 },
+                Unsafe => ident { name: 62, ctxt: 0 },
+                Use => ident { name: 63, ctxt: 0 },
+                While => ident { name: 64, ctxt: 0 },
+                Be => ident { name: 65, ctxt: 0 },
             }
         }
     }
@@ -663,7 +657,7 @@ pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool {
 pub fn is_any_keyword(tok: &Token) -> bool {
     match *tok {
         token::IDENT(sid, false) => match sid.name {
-            8 | 29 | 35 .. 68 => true,
+            8 | 27 | 32 .. 65 => true,
             _ => false,
         },
         _ => false
@@ -673,7 +667,7 @@ pub fn is_any_keyword(tok: &Token) -> bool {
 pub fn is_strict_keyword(tok: &Token) -> bool {
     match *tok {
         token::IDENT(sid, false) => match sid.name {
-            8 | 29 | 35 .. 67 => true,
+            8 | 27 | 32 .. 64 => true,
             _ => false,
         },
         _ => false,
@@ -683,7 +677,7 @@ pub fn is_strict_keyword(tok: &Token) -> bool {
 pub fn is_reserved_keyword(tok: &Token) -> bool {
     match *tok {
         token::IDENT(sid, false) => match sid.name {
-            68 => true,
+            65 => true,
             _ => false,
         },
         _ => false,
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 6ae5e978106..de46d7b3e8a 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -739,15 +739,6 @@ rust_task_deref(rust_task *task) {
     task->deref();
 }
 
-// Must call on rust stack.
-extern "C" CDECL void
-rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) {
-    void (*glue_fn)(void *, void *, void *) =
-        (void (*)(void *, void *, void *))tydesc[glue_index];
-    if (glue_fn)
-        glue_fn(0, 0, root);
-}
-
 // Don't run on the Rust stack!
 extern "C" void
 rust_log_str(uint32_t level, const char *str, size_t size) {
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index fe1b4622137..81ae991623f 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -183,7 +183,11 @@ void task_start_wrapper(spawn_args *a)
     if(env) {
         // free the environment (which should be a unique closure).
         const type_desc *td = env->td;
-        td->drop_glue(NULL, NULL, box_body(env));
+        td->drop_glue(NULL,
+#ifdef _RUST_STAGE0
+                      NULL,
+#endif
+                      box_body(env));
         task->kernel->region()->free(env);
     }
 
diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h
index 6d36d2c960a..30ff5f1fa54 100644
--- a/src/rt/rust_type.h
+++ b/src/rt/rust_type.h
@@ -25,7 +25,11 @@ typedef void (*CDECL spawn_fn)(rust_opaque_box*, void *);
 
 struct type_desc;
 
-typedef void CDECL (glue_fn)(void *, const type_desc **, void *);
+typedef void CDECL (glue_fn)(void *,
+#ifdef _RUST_STAGE0
+                             const type_desc **,
+#endif
+                             void *);
 
 // Corresponds to the boxed data in the @ region.  The body follows the
 // header; you can obtain a ptr via box_body() below.
@@ -57,8 +61,6 @@ struct type_desc {
     glue_fn *drop_glue;
     glue_fn *free_glue;
     glue_fn *visit_glue;
-    const uint8_t *unused;
-    const uint8_t *unused2;
 };
 
 extern "C" type_desc *rust_clone_type_desc(type_desc*);
diff --git a/src/rt/rust_util.cpp b/src/rt/rust_util.cpp
index 8d80a344063..4a15830e529 100644
--- a/src/rt/rust_util.cpp
+++ b/src/rt/rust_util.cpp
@@ -21,8 +21,6 @@ struct type_desc str_body_tydesc = {
     NULL, // drop_glue
     NULL, // free_glue
     NULL, // visit_glue
-    NULL, // shape
-    NULL, // shape_tables
 };
 
 //
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 505de6e20b7..a4876618c97 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -176,7 +176,6 @@ rust_set_task_local_data
 rust_task_local_data_atexit
 rust_task_ref
 rust_task_deref
-rust_call_tydesc_glue
 tdefl_compress_mem_to_heap
 tinfl_decompress_mem_to_heap
 rust_gc_metadata
diff --git a/src/test/run-pass/extern-pub.rs b/src/test/run-pass/extern-pub.rs
index 29b0457fc05..27c45893930 100644
--- a/src/test/run-pass/extern-pub.rs
+++ b/src/test/run-pass/extern-pub.rs
@@ -1,11 +1,5 @@
-use std::libc;
-use std::sys;
-use std::vec;
-
 extern {
-    pub unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc,
-                                            v: **vec::raw::VecRepr,
-                                            n: libc::size_t);
+    pub unsafe fn free(p: *u8);
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs
index a8571ab7325..176e49e0ea1 100644
--- a/src/test/run-pass/reflect-visit-data.rs
+++ b/src/test/run-pass/reflect-visit-data.rs
@@ -10,15 +10,14 @@
 
 // xfail-fast
 
-use std::bool;
 use std::int;
 use std::libc::c_void;
 use std::ptr;
 use std::sys;
 use std::vec::UnboxedVecRepr;
-use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque};
+use std::unstable::intrinsics::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque};
 
-#[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."]
+#[doc = "High-level interfaces to `std::unstable::intrinsics::visit_ty` reflection system."]
 
 /// Trait for visitor that wishes to reflect on data.
 trait movable_ptr {
@@ -637,7 +636,9 @@ impl TyVisitor for my_visitor {
 }
 
 fn get_tydesc_for<T>(_t: T) -> *TyDesc {
-    get_tydesc::<T>()
+    unsafe {
+        get_tydesc::<T>()
+    }
 }
 
 struct Triple { x: int, y: int, z: int }
@@ -651,8 +652,8 @@ pub fn main() {
                                        vals: ~[]});
         let v = ptr_visit_adaptor(Inner {inner: u});
         let td = get_tydesc_for(r);
-        unsafe { error!("tydesc sz: %u, align: %u",
-                        (*td).size, (*td).align); }
+        error!("tydesc sz: %u, align: %u",
+               (*td).size, (*td).align);
         let v = @v as @TyVisitor;
         visit_tydesc(td, v);
 
@@ -661,8 +662,7 @@ pub fn main() {
             println(fmt!("val: %s", *s));
         }
         error!("%?", u.vals.clone());
-        assert!(u.vals == ~[
-            ~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3", ~"12"
-        ]);
+        assert_eq!(u.vals.clone(),
+                   ~[ ~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3", ~"12"]);
     }
- }
+}
diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs
index 8a7fef95614..bb1c92dfa8a 100644
--- a/src/test/run-pass/reflect-visit-type.rs
+++ b/src/test/run-pass/reflect-visit-type.rs
@@ -8,141 +8,153 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
-use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
-struct my_visitor(@mut { types: ~[str] });
+use std::unstable::intrinsics::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque};
 
-impl TyVisitor for my_visitor {
-    fn visit_bot() -> bool {
-        self.types += ~["bot"];
+struct MyVisitor {
+    types: @mut ~[~str],
+}
+
+impl TyVisitor for MyVisitor {
+    fn visit_bot(&self) -> bool {
+        self.types.push(~"bot");
         error!("visited bot type");
         true
     }
-    fn visit_nil() -> bool {
-        self.types += ~["nil"];
+    fn visit_nil(&self) -> bool {
+        self.types.push(~"nil");
         error!("visited nil type");
         true
     }
-    fn visit_bool() -> bool {
-        self.types += ~["bool"];
+    fn visit_bool(&self) -> bool {
+        self.types.push(~"bool");
         error!("visited bool type");
         true
     }
-    fn visit_int() -> bool {
-        self.types += ~["int"];
+    fn visit_int(&self) -> bool {
+        self.types.push(~"int");
         error!("visited int type");
         true
     }
-    fn visit_i8() -> bool {
-        self.types += ~["i8"];
+    fn visit_i8(&self) -> bool {
+        self.types.push(~"i8");
         error!("visited i8 type");
         true
     }
-    fn visit_i16() -> bool {
-        self.types += ~["i16"];
+    fn visit_i16(&self) -> bool {
+        self.types.push(~"i16");
         error!("visited i16 type");
         true
     }
-    fn visit_i32() -> bool { true }
-    fn visit_i64() -> bool { true }
-
-    fn visit_uint() -> bool { true }
-    fn visit_u8() -> bool { true }
-    fn visit_u16() -> bool { true }
-    fn visit_u32() -> bool { true }
-    fn visit_u64() -> bool { true }
-
-    fn visit_float() -> bool { true }
-    fn visit_f32() -> bool { true }
-    fn visit_f64() -> bool { true }
-
-    fn visit_char() -> bool { true }
-    fn visit_str() -> bool { true }
-
-    fn visit_estr_box() -> bool { true }
-    fn visit_estr_uniq() -> bool { true }
-    fn visit_estr_slice() -> bool { true }
-    fn visit_estr_fixed(_sz: uint, _sz: uint,
+    fn visit_i32(&self) -> bool { true }
+    fn visit_i64(&self) -> bool { true }
+
+    fn visit_uint(&self) -> bool { true }
+    fn visit_u8(&self) -> bool { true }
+    fn visit_u16(&self) -> bool { true }
+    fn visit_u32(&self) -> bool { true }
+    fn visit_u64(&self) -> bool { true }
+
+    fn visit_float(&self) -> bool { true }
+    fn visit_f32(&self) -> bool { true }
+    fn visit_f64(&self) -> bool { true }
+
+    fn visit_char(&self) -> bool { true }
+    fn visit_str(&self) -> bool { true }
+
+    fn visit_estr_box(&self) -> bool { true }
+    fn visit_estr_uniq(&self) -> bool { true }
+    fn visit_estr_slice(&self) -> bool { true }
+    fn visit_estr_fixed(&self,
+                        _sz: uint, _sz: uint,
                         _align: uint) -> bool { true }
 
-    fn visit_box(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_uniq(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_ptr(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_rptr(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-
-    fn visit_vec(_mtbl: uint, inner: *TyDesc) -> bool {
-        self.types += ~["["];
-        visit_tydesc(inner, my_visitor(*self) as TyVisitor);
-        self.types += ~["]"];
+    fn visit_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_uniq(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_rptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+
+    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_unboxed_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
+        self.types.push(~"[");
+        unsafe {
+            visit_tydesc(inner, (@*self) as @TyVisitor);
+        }
+        self.types.push(~"]");
         true
     }
-    fn visit_unboxed_vec(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_box(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_uniq(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_slice(_mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_evec_fixed(_n: uint, _sz: uint, _align: uint,
+    fn visit_evec_slice(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_evec_fixed(&self, _n: uint, _sz: uint, _align: uint,
                         _mtbl: uint, _inner: *TyDesc) -> bool { true }
 
-    fn visit_enter_rec(_n_fields: uint,
+    fn visit_enter_rec(&self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
-    fn visit_rec_field(_i: uint, _name: &str,
+    fn visit_rec_field(&self, _i: uint, _name: &str,
                        _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_rec(_n_fields: uint,
+    fn visit_leave_rec(&self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_class(_n_fields: uint,
+    fn visit_enter_class(&self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool { true }
-    fn visit_class_field(_i: uint, _name: &str,
+    fn visit_class_field(&self, _i: uint, _name: &str,
                          _mtbl: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_class(_n_fields: uint,
+    fn visit_leave_class(&self, _n_fields: uint,
                          _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_tup(_n_fields: uint,
+    fn visit_enter_tup(&self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
-    fn visit_tup_field(_i: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_tup(_n_fields: uint,
+    fn visit_tup_field(&self, _i: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_leave_tup(&self, _n_fields: uint,
                        _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_enum(_n_variants: uint,
+    fn visit_enter_enum(&self, _n_variants: uint,
+                        _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint, _align: uint) -> bool { true }
-    fn visit_enter_enum_variant(_variant: uint,
+    fn visit_enter_enum_variant(&self,
+                                _variant: uint,
                                 _disr_val: int,
                                 _n_fields: uint,
                                 _name: &str) -> bool { true }
-    fn visit_enum_variant_field(_i: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_enum_variant(_variant: uint,
+    fn visit_enum_variant_field(&self, _i: uint, _offset: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_leave_enum_variant(&self,
+                                _variant: uint,
                                 _disr_val: int,
                                 _n_fields: uint,
                                 _name: &str) -> bool { true }
-    fn visit_leave_enum(_n_variants: uint,
+    fn visit_leave_enum(&self,
+                        _n_variants: uint,
+                        _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
                         _sz: uint, _align: uint) -> bool { true }
 
-    fn visit_enter_fn(_purity: uint, _proto: uint,
+    fn visit_enter_fn(&self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
-    fn visit_fn_input(_i: uint, _mode: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_fn_output(_retstyle: uint, _inner: *TyDesc) -> bool { true }
-    fn visit_leave_fn(_purity: uint, _proto: uint,
+    fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool { true }
+    fn visit_leave_fn(&self, _purity: uint, _proto: uint,
                       _n_inputs: uint, _retstyle: uint) -> bool { true }
 
 
-    fn visit_trait() -> bool { true }
-    fn visit_var() -> bool { true }
-    fn visit_var_integral() -> bool { true }
-    fn visit_param(_i: uint) -> bool { true }
-    fn visit_self() -> bool { true }
-    fn visit_type() -> bool { true }
-    fn visit_opaque_box() -> bool { true }
-    fn visit_constr(_inner: *TyDesc) -> bool { true }
-    fn visit_closure_ptr(_ck: uint) -> bool { true }
+    fn visit_trait(&self) -> bool { true }
+    fn visit_var(&self) -> bool { true }
+    fn visit_var_integral(&self) -> bool { true }
+    fn visit_param(&self, _i: uint) -> bool { true }
+    fn visit_self(&self) -> bool { true }
+    fn visit_type(&self) -> bool { true }
+    fn visit_opaque_box(&self) -> bool { true }
+    fn visit_constr(&self, _inner: *TyDesc) -> bool { true }
+    fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
 }
 
-fn visit_ty<T>(v: TyVisitor) {
-    visit_tydesc(get_tydesc::<T>(), v);
+fn visit_ty<T>(v: @TyVisitor) {
+    unsafe {
+        visit_tydesc(get_tydesc::<T>(), v);
+    }
 }
 
 pub fn main() {
-    let v = my_visitor(@mut {types: ~[]});
-    let vv = v as TyVisitor;
+    let v = @MyVisitor {types: @mut ~[]};
+    let vv = v as @TyVisitor;
 
     visit_ty::<bool>(vv);
     visit_ty::<int>(vv);
@@ -150,9 +162,8 @@ pub fn main() {
     visit_ty::<i16>(vv);
     visit_ty::<~[int]>(vv);
 
-    for (v.types.clone()).each {|s|
-        io::println(fmt!("type: %s", s));
+    for v.types.iter().advance |&s| {
+        println(fmt!("type: %s", s));
     }
-    assert!(v.types == ["bool", "int", "i8", "i16",
-                       "[", "int", "]"]);
+    assert_eq!((*v.types).clone(), ~[~"bool", ~"int", ~"i8", ~"i16", ~"[", ~"int", ~"]"]);
 }