]> git.lizzy.rs Git - rust.git/commitdiff
Make all lang_items optional
authorAlex Crichton <alex@alexcrichton.com>
Tue, 16 Jul 2013 03:42:13 +0000 (20:42 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 17 Jul 2013 04:37:52 +0000 (21:37 -0700)
Whenever a lang_item is required, some relevant message is displayed, often with
a span of what triggered the usage of the lang item

18 files changed:
src/librustc/middle/kind.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/resolve.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/closure.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/controlflow.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/reflect.rs
src/librustc/middle/trans/tvec.rs
src/librustc/middle/trans/write_guard.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/middle/typeck/collect.rs
src/test/run-pass/smallest-hello-world.rs [new file with mode: 0644]

index a9454d1b23096e64a2942adefd20440bc95a22a3..9a75601a08288412f1dd3f5ea4dd1191f108ef10 100644 (file)
@@ -122,7 +122,7 @@ fn check_item(item: @item, (cx, visitor): (Context, visit::vt<Context>)) {
                     None => cx.tcx.sess.bug("trait ref not in def map!"),
                     Some(&trait_def) => {
                         let trait_def_id = ast_util::def_id_of_def(trait_def);
-                        if cx.tcx.lang_items.drop_trait() == trait_def_id {
+                        if cx.tcx.lang_items.drop_trait() == Some(trait_def_id) {
                             // Yes, it's a destructor.
                             match self_type.node {
                                 ty_path(_, ref bounds, path_node_id) => {
index 0e9361193b0a31a5a9e6640d68089b51c686cb92..912096e8098f1ee4f1535e9209bf58e1c5fe5942 100644 (file)
@@ -153,135 +153,143 @@ pub fn item_name(index: uint) -> &'static str {
 
     // FIXME #4621: Method macros sure would be nice here.
 
-    pub fn freeze_trait(&self) -> def_id {
-        self.items[FreezeTraitLangItem as uint].get()
+    pub fn require(&self, it: LangItem) -> Result<def_id, ~str> {
+        match self.items[it as uint] {
+            Some(id) => Ok(id),
+            None => Err(fmt!("requires `%s` lang_item",
+                             LanguageItems::item_name(it as uint)))
+        }
+    }
+
+    pub fn freeze_trait(&self) -> Option<def_id> {
+        self.items[FreezeTraitLangItem as uint]
     }
-    pub fn copy_trait(&self) -> def_id {
-        self.items[CopyTraitLangItem as uint].get()
+    pub fn copy_trait(&self) -> Option<def_id> {
+        self.items[CopyTraitLangItem as uint]
     }
-    pub fn send_trait(&self) -> def_id {
-        self.items[SendTraitLangItem as uint].get()
+    pub fn send_trait(&self) -> Option<def_id> {
+        self.items[SendTraitLangItem as uint]
     }
-    pub fn sized_trait(&self) -> def_id {
-        self.items[SizedTraitLangItem as uint].get()
+    pub fn sized_trait(&self) -> Option<def_id> {
+        self.items[SizedTraitLangItem as uint]
     }
 
-    pub fn drop_trait(&self) -> def_id {
-        self.items[DropTraitLangItem as uint].get()
+    pub fn drop_trait(&self) -> Option<def_id> {
+        self.items[DropTraitLangItem as uint]
     }
 
-    pub fn add_trait(&self) -> def_id {
-        self.items[AddTraitLangItem as uint].get()
+    pub fn add_trait(&self) -> Option<def_id> {
+        self.items[AddTraitLangItem as uint]
     }
-    pub fn sub_trait(&self) -> def_id {
-        self.items[SubTraitLangItem as uint].get()
+    pub fn sub_trait(&self) -> Option<def_id> {
+        self.items[SubTraitLangItem as uint]
     }
-    pub fn mul_trait(&self) -> def_id {
-        self.items[MulTraitLangItem as uint].get()
+    pub fn mul_trait(&self) -> Option<def_id> {
+        self.items[MulTraitLangItem as uint]
     }
-    pub fn div_trait(&self) -> def_id {
-        self.items[DivTraitLangItem as uint].get()
+    pub fn div_trait(&self) -> Option<def_id> {
+        self.items[DivTraitLangItem as uint]
     }
-    pub fn rem_trait(&self) -> def_id {
-        self.items[RemTraitLangItem as uint].get()
+    pub fn rem_trait(&self) -> Option<def_id> {
+        self.items[RemTraitLangItem as uint]
     }
-    pub fn neg_trait(&self) -> def_id {
-        self.items[NegTraitLangItem as uint].get()
+    pub fn neg_trait(&self) -> Option<def_id> {
+        self.items[NegTraitLangItem as uint]
     }
-    pub fn not_trait(&self) -> def_id {
-        self.items[NotTraitLangItem as uint].get()
+    pub fn not_trait(&self) -> Option<def_id> {
+        self.items[NotTraitLangItem as uint]
     }
-    pub fn bitxor_trait(&self) -> def_id {
-        self.items[BitXorTraitLangItem as uint].get()
+    pub fn bitxor_trait(&self) -> Option<def_id> {
+        self.items[BitXorTraitLangItem as uint]
     }
-    pub fn bitand_trait(&self) -> def_id {
-        self.items[BitAndTraitLangItem as uint].get()
+    pub fn bitand_trait(&self) -> Option<def_id> {
+        self.items[BitAndTraitLangItem as uint]
     }
-    pub fn bitor_trait(&self) -> def_id {
-        self.items[BitOrTraitLangItem as uint].get()
+    pub fn bitor_trait(&self) -> Option<def_id> {
+        self.items[BitOrTraitLangItem as uint]
     }
-    pub fn shl_trait(&self) -> def_id {
-        self.items[ShlTraitLangItem as uint].get()
+    pub fn shl_trait(&self) -> Option<def_id> {
+        self.items[ShlTraitLangItem as uint]
     }
-    pub fn shr_trait(&self) -> def_id {
-        self.items[ShrTraitLangItem as uint].get()
+    pub fn shr_trait(&self) -> Option<def_id> {
+        self.items[ShrTraitLangItem as uint]
     }
-    pub fn index_trait(&self) -> def_id {
-        self.items[IndexTraitLangItem as uint].get()
+    pub fn index_trait(&self) -> Option<def_id> {
+        self.items[IndexTraitLangItem as uint]
     }
 
-    pub fn eq_trait(&self) -> def_id {
-        self.items[EqTraitLangItem as uint].get()
+    pub fn eq_trait(&self) -> Option<def_id> {
+        self.items[EqTraitLangItem as uint]
     }
-    pub fn ord_trait(&self) -> def_id {
-        self.items[OrdTraitLangItem as uint].get()
+    pub fn ord_trait(&self) -> Option<def_id> {
+        self.items[OrdTraitLangItem as uint]
     }
 
-    pub fn str_eq_fn(&self) -> def_id {
-        self.items[StrEqFnLangItem as uint].get()
+    pub fn str_eq_fn(&self) -> Option<def_id> {
+        self.items[StrEqFnLangItem as uint]
     }
-    pub fn uniq_str_eq_fn(&self) -> def_id {
-        self.items[UniqStrEqFnLangItem as uint].get()
+    pub fn uniq_str_eq_fn(&self) -> Option<def_id> {
+        self.items[UniqStrEqFnLangItem as uint]
     }
-    pub fn annihilate_fn(&self) -> def_id {
-        self.items[AnnihilateFnLangItem as uint].get()
+    pub fn annihilate_fn(&self) -> Option<def_id> {
+        self.items[AnnihilateFnLangItem as uint]
     }
-    pub fn log_type_fn(&self) -> def_id {
-        self.items[LogTypeFnLangItem as uint].get()
+    pub fn log_type_fn(&self) -> Option<def_id> {
+        self.items[LogTypeFnLangItem as uint]
     }
-    pub fn fail_fn(&self) -> def_id {
-        self.items[FailFnLangItem as uint].get()
+    pub fn fail_fn(&self) -> Option<def_id> {
+        self.items[FailFnLangItem as uint]
     }
-    pub fn fail_bounds_check_fn(&self) -> def_id {
-        self.items[FailBoundsCheckFnLangItem as uint].get()
+    pub fn fail_bounds_check_fn(&self) -> Option<def_id> {
+        self.items[FailBoundsCheckFnLangItem as uint]
     }
-    pub fn exchange_malloc_fn(&self) -> def_id {
-        self.items[ExchangeMallocFnLangItem as uint].get()
+    pub fn exchange_malloc_fn(&self) -> Option<def_id> {
+        self.items[ExchangeMallocFnLangItem as uint]
     }
-    pub fn closure_exchange_malloc_fn(&self) -> def_id {
-        self.items[ClosureExchangeMallocFnLangItem as uint].get()
+    pub fn closure_exchange_malloc_fn(&self) -> Option<def_id> {
+        self.items[ClosureExchangeMallocFnLangItem as uint]
     }
-    pub fn exchange_free_fn(&self) -> def_id {
-        self.items[ExchangeFreeFnLangItem as uint].get()
+    pub fn exchange_free_fn(&self) -> Option<def_id> {
+        self.items[ExchangeFreeFnLangItem as uint]
     }
-    pub fn malloc_fn(&self) -> def_id {
-        self.items[MallocFnLangItem as uint].get()
+    pub fn malloc_fn(&self) -> Option<def_id> {
+        self.items[MallocFnLangItem as uint]
     }
-    pub fn free_fn(&self) -> def_id {
-        self.items[FreeFnLangItem as uint].get()
+    pub fn free_fn(&self) -> Option<def_id> {
+        self.items[FreeFnLangItem as uint]
     }
-    pub fn borrow_as_imm_fn(&self) -> def_id {
-        self.items[BorrowAsImmFnLangItem as uint].get()
+    pub fn borrow_as_imm_fn(&self) -> Option<def_id> {
+        self.items[BorrowAsImmFnLangItem as uint]
     }
-    pub fn borrow_as_mut_fn(&self) -> def_id {
-        self.items[BorrowAsMutFnLangItem as uint].get()
+    pub fn borrow_as_mut_fn(&self) -> Option<def_id> {
+        self.items[BorrowAsMutFnLangItem as uint]
     }
-    pub fn return_to_mut_fn(&self) -> def_id {
-        self.items[ReturnToMutFnLangItem as uint].get()
+    pub fn return_to_mut_fn(&self) -> Option<def_id> {
+        self.items[ReturnToMutFnLangItem as uint]
     }
-    pub fn check_not_borrowed_fn(&self) -> def_id {
-        self.items[CheckNotBorrowedFnLangItem as uint].get()
+    pub fn check_not_borrowed_fn(&self) -> Option<def_id> {
+        self.items[CheckNotBorrowedFnLangItem as uint]
     }
-    pub fn strdup_uniq_fn(&self) -> def_id {
-        self.items[StrDupUniqFnLangItem as uint].get()
+    pub fn strdup_uniq_fn(&self) -> Option<def_id> {
+        self.items[StrDupUniqFnLangItem as uint]
     }
-    pub fn record_borrow_fn(&self) -> def_id {
-        self.items[RecordBorrowFnLangItem as uint].get()
+    pub fn record_borrow_fn(&self) -> Option<def_id> {
+        self.items[RecordBorrowFnLangItem as uint]
     }
-    pub fn unrecord_borrow_fn(&self) -> def_id {
-        self.items[UnrecordBorrowFnLangItem as uint].get()
+    pub fn unrecord_borrow_fn(&self) -> Option<def_id> {
+        self.items[UnrecordBorrowFnLangItem as uint]
     }
-    pub fn start_fn(&self) -> def_id {
-        self.items[StartFnLangItem as uint].get()
+    pub fn start_fn(&self) -> Option<def_id> {
+        self.items[StartFnLangItem as uint]
     }
-    pub fn ty_desc(&const self) -> def_id {
-        self.items[TyDescStructLangItem as uint].get()
+    pub fn ty_desc(&self) -> Option<def_id> {
+        self.items[TyDescStructLangItem as uint]
     }
-    pub fn ty_visitor(&const self) -> def_id {
-        self.items[TyVisitorTraitLangItem as uint].get()
+    pub fn ty_visitor(&self) -> Option<def_id> {
+        self.items[TyVisitorTraitLangItem as uint]
     }
-    pub fn opaque(&const self) -> def_id {
-        self.items[OpaqueStructLangItem as uint].get()
+    pub fn opaque(&self) -> Option<def_id> {
+        self.items[OpaqueStructLangItem as uint]
     }
 }
 
@@ -439,23 +447,9 @@ pub fn collect_external_language_items(&mut self) {
         }
     }
 
-    pub fn check_completeness(&self) {
-        for self.item_refs.iter().advance |(&key, &item_ref)| {
-            match self.items.items[item_ref] {
-                None => {
-                    self.session.err(fmt!("no item found for `%s`", key));
-                }
-                Some(_) => {
-                    // OK.
-                }
-            }
-        }
-    }
-
     pub fn collect(&mut self) {
         self.collect_local_language_items();
         self.collect_external_language_items();
-        self.check_completeness();
     }
 }
 
index 619bfbdb5478415bad9e5e8b289c89b04ff57d47..6a84e5682198ba32c50490eaaaf00d8e062db62f 100644 (file)
@@ -5268,8 +5268,13 @@ pub fn add_trait_info(&self,
 
     pub fn add_fixed_trait_for_expr(@mut self,
                                     expr_id: node_id,
-                                    trait_id: def_id) {
-        self.trait_map.insert(expr_id, @mut ~[trait_id]);
+                                    trait_id: Option<def_id>) {
+        match trait_id {
+            Some(trait_id) => {
+                self.trait_map.insert(expr_id, @mut ~[trait_id]);
+            }
+            None => {}
+        }
     }
 
     pub fn record_def(@mut self, node_id: node_id, def: def) {
index d5d0cde1ee0a083b720829ede4eb194251eba227..2f27949e869b4a2904b57978b9d09ac85366fd13 100644 (file)
 use lib::llvm::{llvm, ValueRef, BasicBlockRef};
 use middle::const_eval;
 use middle::borrowck::root_map_key;
+use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
 use middle::pat_util::*;
 use middle::resolve::DefMap;
 use middle::trans::adt;
@@ -1099,7 +1100,9 @@ pub fn compare_values(cx: block,
             Store(cx, lhs, scratch_lhs);
             let scratch_rhs = alloca(cx, val_ty(rhs), "__rhs");
             Store(cx, rhs, scratch_rhs);
-            let did = cx.tcx().lang_items.uniq_str_eq_fn();
+            let did = langcall(cx, None,
+                               fmt!("comparison of `%s`", cx.ty_to_str(rhs_t)),
+                               UniqStrEqFnLangItem);
             let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None);
             Result {
                 bcx: result.bcx,
@@ -1107,7 +1110,9 @@ pub fn compare_values(cx: block,
             }
         }
         ty::ty_estr(_) => {
-            let did = cx.tcx().lang_items.str_eq_fn();
+            let did = langcall(cx, None,
+                               fmt!("comparison of `%s`", cx.ty_to_str(rhs_t)),
+                               StrEqFnLangItem);
             let result = callee::trans_lang_call(cx, did, [lhs, rhs], None);
             Result {
                 bcx: result.bcx,
index fc635954237c8a35ef4b0e3964608c132eb7336e..d7c04907513321f9ce9436397f1294eb18f9d5f8 100644 (file)
@@ -34,6 +34,8 @@
 use metadata::common::LinkMeta;
 use metadata::{csearch, cstore, encoder};
 use middle::astencode;
+use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
+use middle::lang_items::{MallocFnLangItem, ClosureExchangeMallocFnLangItem};
 use middle::resolve;
 use middle::trans::_match;
 use middle::trans::adt;
@@ -284,13 +286,25 @@ pub fn malloc_raw_dyn(bcx: block,
     let _icx = push_ctxt("malloc_raw");
     let ccx = bcx.ccx();
 
+    fn require_alloc_fn(bcx: block, t: ty::t, it: LangItem) -> ast::def_id {
+        let li = &bcx.tcx().lang_items;
+        match li.require(it) {
+            Ok(id) => id,
+            Err(s) => {
+                bcx.tcx().sess.fatal(fmt!("allocation of `%s` %s",
+                                          bcx.ty_to_str(t), s));
+            }
+        }
+    }
+
     if heap == heap_exchange {
         let llty_value = type_of::type_of(ccx, t);
 
+
         // Allocate space:
         let r = callee::trans_lang_call(
             bcx,
-            bcx.tcx().lang_items.exchange_malloc_fn(),
+            require_alloc_fn(bcx, t, ExchangeMallocFnLangItem),
             [size],
             None);
         rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to()))
@@ -298,10 +312,12 @@ pub fn malloc_raw_dyn(bcx: block,
         // we treat ~fn, @fn and @[] as @ here, which isn't ideal
         let (mk_fn, langcall) = match heap {
             heap_managed | heap_managed_unique => {
-                (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
+                (ty::mk_imm_box,
+                 require_alloc_fn(bcx, t, MallocFnLangItem))
             }
             heap_exchange_closure => {
-                (ty::mk_imm_box, bcx.tcx().lang_items.closure_exchange_malloc_fn())
+                (ty::mk_imm_box,
+                 require_alloc_fn(bcx, t, ClosureExchangeMallocFnLangItem))
             }
             _ => fail!("heap_exchange already handled")
         };
@@ -2324,7 +2340,8 @@ fn create_main(ccx: @mut CrateContext, main_llfn: ValueRef) -> ValueRef {
     fn create_entry_fn(ccx: @mut CrateContext,
                        rust_main: ValueRef,
                        use_start_lang_item: bool) {
-        let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()], &ccx.int_type);
+        let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()],
+                               &ccx.int_type);
 
         // FIXME #4404 android JNI hacks
         let llfn = if *ccx.sess.building_library {
@@ -2345,25 +2362,21 @@ fn create_entry_fn(ccx: @mut CrateContext,
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
 
-            let start_def_id = ccx.tcx.lang_items.start_fn();
-            if start_def_id.crate != ast::local_crate {
-                let start_fn_type = csearch::get_type(ccx.tcx,
-                                                      start_def_id).ty;
-                trans_external_path(ccx, start_def_id, start_fn_type);
-            }
-
             let crate_map = ccx.crate_map;
             let opaque_crate_map = do "crate_map".as_c_str |buf| {
                 llvm::LLVMBuildPointerCast(bld, crate_map, Type::i8p().to_ref(), buf)
             };
 
             let (start_fn, args) = if use_start_lang_item {
-                let start_def_id = ccx.tcx.lang_items.start_fn();
+                let start_def_id = match ccx.tcx.lang_items.require(StartFnLangItem) {
+                    Ok(id) => id,
+                    Err(s) => { ccx.tcx.sess.fatal(s); }
+                };
                 let start_fn = if start_def_id.crate == ast::local_crate {
                     get_item_val(ccx, start_def_id.node)
                 } else {
                     let start_fn_type = csearch::get_type(ccx.tcx,
-                            start_def_id).ty;
+                                                          start_def_id).ty;
                     trans_external_path(ccx, start_def_id, start_fn_type)
                 };
 
@@ -2383,14 +2396,12 @@ fn create_entry_fn(ccx: @mut CrateContext,
                 (start_fn, args)
             } else {
                 debug!("using user-defined start fn");
-                let args = {
-                    ~[
-                        C_null(Type::opaque_box(ccx).ptr_to()),
-                        llvm::LLVMGetParam(llfn, 0 as c_uint),
-                        llvm::LLVMGetParam(llfn, 1 as c_uint),
-                        opaque_crate_map
-                    ]
-                };
+                let args = ~[
+                    C_null(Type::opaque_box(ccx).ptr_to()),
+                    llvm::LLVMGetParam(llfn, 0 as c_uint),
+                    llvm::LLVMGetParam(llfn, 1 as c_uint),
+                    opaque_crate_map
+                ];
 
                 (rust_main, args)
             };
@@ -2832,17 +2843,18 @@ pub fn fill_crate_map(ccx: @mut CrateContext, map: ValueRef) {
     }
     subcrates.push(C_int(ccx, 0));
 
-    let llannihilatefn;
-    let annihilate_def_id = ccx.tcx.lang_items.annihilate_fn();
-    if annihilate_def_id.crate == ast::local_crate {
-        llannihilatefn = get_item_val(ccx, annihilate_def_id.node);
-    } else {
-        let annihilate_fn_type = csearch::get_type(ccx.tcx,
-                                                   annihilate_def_id).ty;
-        llannihilatefn = trans_external_path(ccx,
-                                             annihilate_def_id,
-                                             annihilate_fn_type);
-    }
+    let llannihilatefn = match ccx.tcx.lang_items.annihilate_fn() {
+        Some(annihilate_def_id) => {
+            if annihilate_def_id.crate == ast::local_crate {
+                get_item_val(ccx, annihilate_def_id.node)
+            } else {
+                let annihilate_fn_type = csearch::get_type(ccx.tcx,
+                                                           annihilate_def_id).ty;
+                trans_external_path(ccx, annihilate_def_id, annihilate_fn_type)
+            }
+        }
+        None => { C_null(Type::i8p()) }
+    };
 
     unsafe {
         let mod_map = create_module_map(ccx);
index d2953f8913e29e4cd83d7bbfd14ce0fa4aa1f541..4e754bea91621da191570226cae045fb1c77bdb5 100644 (file)
@@ -13,6 +13,7 @@
 use back::link::{mangle_internal_name_by_path_and_seq};
 use lib::llvm::{llvm, ValueRef};
 use middle::moves;
+use middle::lang_items::ClosureExchangeMallocFnLangItem;
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::callee;
@@ -541,9 +542,13 @@ pub fn make_opaque_cbox_take_glue(
         // Allocate memory, update original ptr, and copy existing data
         let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p());
         let mut bcx = bcx;
+        let alloc_fn = langcall(bcx, None,
+                                fmt!("allocation of type with sigil `%s`",
+                                    sigil.to_str()),
+                                ClosureExchangeMallocFnLangItem);
         let llresult = unpack_result!(bcx, callee::trans_lang_call(
             bcx,
-            bcx.tcx().lang_items.closure_exchange_malloc_fn(),
+            alloc_fn,
             [opaque_tydesc, sz],
             None));
         let cbox_out = PointerCast(bcx, llresult, llopaquecboxty);
index 196807baabbe6c1c1a405ec7ab6c7a9e1c040da3..ea5068c445b5338f8f4dc0356542f4a591c2200b 100644 (file)
@@ -17,6 +17,7 @@
 use lib::llvm::{True, False, Bool};
 use lib::llvm::{llvm};
 use lib;
+use middle::lang_items::LangItem;
 use middle::trans::base;
 use middle::trans::build;
 use middle::trans::datum;
@@ -1126,3 +1127,17 @@ pub fn filename_and_line_num_from_span(bcx: block,
 pub fn bool_to_i1(bcx: block, llval: ValueRef) -> ValueRef {
     build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
 }
+
+pub fn langcall(bcx: block, span: Option<span>, msg: &str,
+                li: LangItem) -> ast::def_id {
+    match bcx.tcx().lang_items.require(li) {
+        Ok(id) => id,
+        Err(s) => {
+            let msg = fmt!("%s %s", msg, s);
+            match span {
+                Some(span) => { bcx.tcx().sess.span_fatal(span, msg); }
+                None => { bcx.tcx().sess.fatal(msg); }
+            }
+        }
+    }
+}
index 36f1f5cdbefc8b4e131621c1f8078e2354d51862..df1db4a1ab34c5c6b93b36d7bf7c2f185cdf6d89 100644 (file)
@@ -12,6 +12,8 @@
 use back::link;
 use lib;
 use lib::llvm::*;
+use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
+use middle::lang_items::LogTypeFnLangItem;
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::callee;
@@ -276,7 +278,7 @@ pub fn trans_log(log_ex: &ast::expr,
 
             // Call the polymorphic log function
             let val = val_datum.to_ref_llval(bcx);
-            let did = bcx.tcx().lang_items.log_type_fn();
+            let did = langcall(bcx, Some(e.span), "", LogTypeFnLangItem);
             let bcx = callee::trans_lang_call_with_type_params(
                 bcx, did, [level, val], [val_datum.ty], expr::Ignore);
             bcx
@@ -435,8 +437,8 @@ fn trans_fail_value(bcx: block,
     let V_str = PointerCast(bcx, V_fail_str, Type::i8p());
     let V_filename = PointerCast(bcx, V_filename, Type::i8p());
     let args = ~[V_str, V_filename, C_int(ccx, V_line)];
-    let bcx = callee::trans_lang_call(
-        bcx, bcx.tcx().lang_items.fail_fn(), args, Some(expr::Ignore)).bcx;
+    let did = langcall(bcx, sp_opt, "", FailFnLangItem);
+    let bcx = callee::trans_lang_call(bcx, did, args, Some(expr::Ignore)).bcx;
     Unreachable(bcx);
     return bcx;
 }
@@ -446,8 +448,8 @@ pub fn trans_fail_bounds_check(bcx: block, sp: span,
     let _icx = push_ctxt("trans_fail_bounds_check");
     let (filename, line) = filename_and_line_num_from_span(bcx, sp);
     let args = ~[filename, line, index, len];
-    let bcx = callee::trans_lang_call(
-        bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, Some(expr::Ignore)).bcx;
+    let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem);
+    let bcx = callee::trans_lang_call(bcx, did, args, Some(expr::Ignore)).bcx;
     Unreachable(bcx);
     return bcx;
 }
index f007aa502dc1385cd21a6b33b6aace3fc2f6d243..c92bfc23b1d3c77bd62db17db9c206f116dbf010 100644 (file)
@@ -18,6 +18,7 @@
 use driver::session;
 use lib;
 use lib::llvm::{llvm, ValueRef, True};
+use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem};
 use middle::trans::adt;
 use middle::trans::base::*;
 use middle::trans::callee;
@@ -44,7 +45,7 @@
 pub fn trans_free(cx: block, v: ValueRef) -> block {
     let _icx = push_ctxt("trans_free");
     callee::trans_lang_call(cx,
-        cx.tcx().lang_items.free_fn(),
+        langcall(cx, None, "", FreeFnLangItem),
         [PointerCast(cx, v, Type::i8p())],
         Some(expr::Ignore)).bcx
 }
@@ -52,7 +53,7 @@ pub fn trans_free(cx: block, v: ValueRef) -> block {
 pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
     let _icx = push_ctxt("trans_exchange_free");
     callee::trans_lang_call(cx,
-        cx.tcx().lang_items.exchange_free_fn(),
+        langcall(cx, None, "", ExchangeFreeFnLangItem),
         [PointerCast(cx, v, Type::i8p())],
         Some(expr::Ignore)).bcx
 }
@@ -365,7 +366,12 @@ pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) -> block {
     let _icx = push_ctxt("make_visit_glue");
     do with_scope(bcx, None, "visitor cleanup") |bcx| {
         let mut bcx = bcx;
-        let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx());
+        let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx()){
+            Ok(pair) => pair,
+            Err(s) => {
+                bcx.tcx().sess.fatal(s);
+            }
+        };
         let v = PointerCast(bcx, v, type_of::type_of(bcx.ccx(), object_ty).ptr_to());
         bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
         // The visitor is a boxed object and needs to be dropped
index 47f0a4c06aff419f3995ea8de9c19c5f621b4883..2dc3a88fe863b33a4c06b3b7dcf83bfdd7ec6295 100644 (file)
@@ -279,7 +279,7 @@ pub fn visit_ty(&mut self, t: ty::t) {
             let repr = adt::represent_type(bcx.ccx(), t);
             let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
             let llptrty = type_of(ccx, t).ptr_to();
-            let opaquety = ty::get_opaque_ty(ccx.tcx);
+            let opaquety = ty::get_opaque_ty(ccx.tcx).unwrap();
             let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm });
 
             let make_get_disr = || {
@@ -380,7 +380,7 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block,
                                     visitor_trait_id: def_id)
                                  -> block {
     let final = sub_block(bcx, "final");
-    let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx);
+    let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx).unwrap();
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
     let mut r = Reflector {
         visitor_val: visitor_val,
index 8fff23c649848ab025a1fd248ad3285ce7d028fb..2a16b13677428ceafa90cb1be7024f9990c27574 100644 (file)
@@ -12,6 +12,7 @@
 use back::abi;
 use lib;
 use lib::llvm::{llvm, ValueRef};
+use middle::lang_items::StrDupUniqFnLangItem;
 use middle::trans::base;
 use middle::trans::base::*;
 use middle::trans::build::*;
@@ -312,16 +313,18 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::e
         heap_exchange => {
             match content_expr.node {
                 ast::expr_lit(@codemap::spanned {
-                    node: ast::lit_str(s), _
+                    node: ast::lit_str(s), span
                 }) => {
                     let llptrval = C_cstr(bcx.ccx(), s);
                     let llptrval = PointerCast(bcx, llptrval, Type::i8p());
                     let llsizeval = C_uint(bcx.ccx(), s.len());
                     let typ = ty::mk_estr(bcx.tcx(), ty::vstore_uniq);
                     let lldestval = scratch_datum(bcx, typ, "", false);
+                    let alloc_fn = langcall(bcx, Some(span), "",
+                                            StrDupUniqFnLangItem);
                     let bcx = callee::trans_lang_call(
                         bcx,
-                        bcx.tcx().lang_items.strdup_uniq_fn(),
+                        alloc_fn,
                         [ llptrval, llsizeval ],
                         Some(expr::SaveIn(lldestval.to_ref_llval(bcx)))).bcx;
                     return DatumBlock {
index 1804a7334f23fb4d37475e763ce3be7c76395a9d..b9a9a57d0461d576e8b31972ac23cf4c81839d31 100644 (file)
 
 use lib::llvm::ValueRef;
 use middle::borrowck::{RootInfo, root_map_key, DynaImm, DynaMut};
+use middle::lang_items::CheckNotBorrowedFnLangItem;
+use middle::lang_items::{BorrowAsImmFnLangItem, BorrowAsMutFnLangItem};
+use middle::lang_items::{RecordBorrowFnLangItem, UnrecordBorrowFnLangItem};
+use middle::lang_items::ReturnToMutFnLangItem;
 use middle::trans::base::*;
 use middle::trans::build::*;
 use middle::trans::callee;
@@ -74,7 +78,7 @@ pub fn return_to_mut(mut bcx: block,
 
     if bcx.tcx().sess.debug_borrows() {
         bcx = callee::trans_lang_call( bcx,
-            bcx.tcx().lang_items.unrecord_borrow_fn(),
+            langcall(bcx, None, "unborrow", UnrecordBorrowFnLangItem),
             [
                 box_ptr,
                 bits_val,
@@ -86,7 +90,7 @@ pub fn return_to_mut(mut bcx: block,
 
     callee::trans_lang_call(
         bcx,
-        bcx.tcx().lang_items.return_to_mut_fn(),
+        langcall(bcx, None, "unborrow", ReturnToMutFnLangItem),
         [
             box_ptr,
             bits_val,
@@ -138,16 +142,16 @@ fn root(datum: &Datum,
             let scratch_bits = scratch_datum(bcx, ty::mk_uint(),
                                              "__write_guard_bits", false);
 
-            let freeze_did = match freeze_kind {
-                DynaImm => bcx.tcx().lang_items.borrow_as_imm_fn(),
-                DynaMut => bcx.tcx().lang_items.borrow_as_mut_fn(),
+            let freeze_item = match freeze_kind {
+                DynaImm => BorrowAsImmFnLangItem,
+                DynaMut => BorrowAsMutFnLangItem,
             };
 
             let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
 
             let llresult = unpack_result!(bcx, callee::trans_lang_call(
                 bcx,
-                freeze_did,
+                langcall(bcx, Some(span), "freeze", freeze_item),
                 [
                     box_ptr,
                     filename,
@@ -158,7 +162,7 @@ fn root(datum: &Datum,
             if bcx.tcx().sess.debug_borrows() {
                 bcx = callee::trans_lang_call(
                     bcx,
-                    bcx.tcx().lang_items.record_borrow_fn(),
+                    langcall(bcx, Some(span), "freeze", RecordBorrowFnLangItem),
                     [
                         box_ptr,
                         llresult,
@@ -187,7 +191,7 @@ fn perform_write_guard(datum: &Datum,
 
     callee::trans_lang_call(
         bcx,
-        bcx.tcx().lang_items.check_not_borrowed_fn(),
+        langcall(bcx, Some(span), "write guard", CheckNotBorrowedFnLangItem),
         [PointerCast(bcx, llval, Type::i8p()), filename, line],
         Some(expr::Ignore)).bcx
 }
index 8e23f5431bcee63cc27218784981d6085dba4f40..c9bf94776c0e23e98cda06313bea0ab0339e6cb2 100644 (file)
@@ -13,6 +13,8 @@
 use metadata::csearch;
 use metadata;
 use middle::const_eval;
+use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
+use middle::lang_items::OpaqueStructLangItem;
 use middle::freevars;
 use middle::resolve::{Impl, MethodInfo};
 use middle::resolve;
@@ -4358,29 +4360,34 @@ 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_tydesc_ty(tcx: ctxt) -> Result<t, ~str> {
+    do tcx.lang_items.require(TyDescStructLangItem).map |tydesc_lang_item| {
+        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 get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
+    do tcx.lang_items.require(OpaqueStructLangItem).map |opaque_lang_item| {
+        tcx.intrinsic_defs.find_copy(opaque_lang_item)
+            .expect("Failed to resolve Opaque")
+    }
 }
 
-pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
+pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
+    let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
+        Ok(id) => id,
+        Err(s) => { return Err(s); }
+    };
     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 };
     let mut static_trait_bound = EmptyBuiltinBounds();
     static_trait_bound.add(BoundStatic);
-    (trait_ref,
-     mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs,
-              BoxTraitStore, ast::m_imm, static_trait_bound))
+    Ok((trait_ref,
+        mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs,
+                 BoxTraitStore, ast::m_imm, static_trait_bound)))
 }
index d8185022e416d8e35f2915defd0cee547ff7ed05..d0e793160fedc9fa28afa503d0d0b7848c5352e0 100644 (file)
@@ -811,16 +811,16 @@ pub fn try_add_builtin_trait(tcx: ty::ctxt,
     //! is a builtin trait.
 
     let li = &tcx.lang_items;
-    if trait_def_id == li.send_trait() {
+    if Some(trait_def_id) == li.send_trait() {
         builtin_bounds.add(ty::BoundSend);
         true
-    } else if trait_def_id == li.copy_trait() {
+    } else if Some(trait_def_id) == li.copy_trait() {
         builtin_bounds.add(ty::BoundCopy);
         true
-    } else if trait_def_id == li.freeze_trait() {
+    } else if Some(trait_def_id) == li.freeze_trait() {
         builtin_bounds.add(ty::BoundFreeze);
         true
-    } else if trait_def_id == li.sized_trait() {
+    } else if Some(trait_def_id) == li.sized_trait() {
         builtin_bounds.add(ty::BoundSized);
         true
     } else {
index 4caf0b62a546d1b76a11b79b64055079b38fefd8..8ffff56a9c485c732cc34dcef225c86fbf0a4819 100644 (file)
@@ -3541,7 +3541,10 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
             }
 
             "get_tydesc" => {
-              let tydesc_ty = ty::get_tydesc_ty(ccx.tcx);
+              let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
+                  Ok(t) => t,
+                  Err(s) => { tcx.sess.span_fatal(it.span, s); }
+              };
               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
                   ty: tydesc_ty,
                   mutbl: ast::m_imm
@@ -3549,8 +3552,15 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
               (1u, ~[], td_ptr)
             }
             "visit_tydesc" => {
-              let tydesc_ty = ty::get_tydesc_ty(ccx.tcx);
-              let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
+              let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
+                  Ok(t) => t,
+                  Err(s) => { tcx.sess.span_fatal(it.span, s); }
+              };
+              let visitor_object_ty = match ty::visitor_object_ty(tcx) {
+                  Ok((_, vot)) => vot,
+                  Err(s) => { tcx.sess.span_fatal(it.span, s); }
+              };
+
               let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
                   ty: tydesc_ty,
                   mutbl: ast::m_imm
index 7ee731d4f46b47daef8a5cb87ebf809b45f23a12..768c4cd04e7344c03cf1a5a174de2e8bd22b0be3 100644 (file)
@@ -960,7 +960,9 @@ pub fn add_external_crates(&self) {
     pub fn populate_destructor_table(&self) {
         let coherence_info = &self.crate_context.coherence_info;
         let tcx = self.crate_context.tcx;
-        let drop_trait = tcx.lang_items.drop_trait();
+        let drop_trait = match tcx.lang_items.drop_trait() {
+            Some(id) => id, None => { return }
+        };
         let impls_opt = coherence_info.extension_methods.find(&drop_trait);
 
         let impls;
index ec384543deac10a5837f7018680bfadb8e01bf49..16ddef2b8e0f9863afcad34031b1b10f12b7a470 100644 (file)
@@ -69,8 +69,12 @@ fn collect_intrinsic_type(ccx: &CrateCtxt,
         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());
+    match ccx.tcx.lang_items.ty_desc() {
+        Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
+    }
+    match ccx.tcx.lang_items.opaque() {
+        Some(id) => { collect_intrinsic_type(ccx, id); } None => {}
+    }
 
     visit::visit_crate(
         crate, ((),
diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs
new file mode 100644 (file)
index 0000000..bbd5857
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2013 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.
+
+// xfail-fast - windows doesn't like this
+
+// Smallest hello world with no runtime
+
+#[no_std];
+
+// This is an unfortunate thing to have to do on linux :(
+#[cfg(target_os = "linux")]
+#[doc(hidden)]
+pub mod linkhack {
+    #[link_args="-lrustrt -lrt"]
+    extern {}
+}
+
+extern {
+    fn puts(s: *u8);
+}
+
+extern "rust-intrinsic" {
+    fn transmute<T, U>(t: T) -> U;
+}
+
+#[start]
+fn main(_: int, _: **u8, _: *u8) -> int {
+    unsafe {
+        let (ptr, _): (*u8, uint) = transmute("Hello!");
+        puts(ptr);
+    }
+    return 0;
+}
+