]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #30570 - fhartwig:dead-doc-links, r=steveklabnik
authorbors <bors@rust-lang.org>
Mon, 28 Dec 2015 09:55:45 +0000 (09:55 +0000)
committerbors <bors@rust-lang.org>
Mon, 28 Dec 2015 09:55:45 +0000 (09:55 +0000)
r? @steveklabnik

42 files changed:
src/doc/book/error-handling.md
src/doc/book/references-and-borrowing.md
src/doc/book/syntax-index.md
src/grammar/parser-lalr.y
src/librustc/front/map/mod.rs
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/ty/mod.rs
src/librustc/middle/ty/sty.rs
src/librustc/mir/repr.rs
src/librustc/session/config.rs
src/librustc/util/ppaux.rs
src/librustc_driver/driver.rs
src/librustc_driver/test.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/tydecode.rs
src/librustc_metadata/tyencode.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/mir/did.rs
src/librustc_trans/trans/mir/rvalue.rs
src/librustc_trans/trans/mir/statement.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/variance.rs
src/libstd/panic.rs
src/libstd/panicking.rs
src/snapshots.txt
src/test/compile-fail/issue-17740.rs
src/test/compile-fail/issue-17905.rs
src/test/compile-fail/issue-26194.rs
src/test/compile-fail/ufcs-explicit-self-bad.rs
src/test/run-fail/panic-set-handler.rs [new file with mode: 0644]
src/test/run-fail/panic-set-unset-handler.rs [new file with mode: 0644]
src/test/run-fail/panic-take-handler-nop.rs [new file with mode: 0644]
src/test/run-make/simd-ffi/simd.rs
src/test/run-pass/mir_refs_correct.rs
src/test/run-pass/panic-handler-chain.rs [new file with mode: 0644]
src/test/run-pass/panic-handler-flail-wildly.rs [new file with mode: 0644]
src/test/run-pass/panic-handler-set-twice.rs [new file with mode: 0644]
src/test/run-pass/panic-safe.rs

index de41a8fe03b61daa8cbb008d935ca77507280223..3479230f774683b8f8c9bb724c1f950dd5f967a2 100644 (file)
@@ -887,7 +887,7 @@ fn main() {
 }
 ```
 
-Reasonable people can disagree over whether this code is better that the code
+Reasonable people can disagree over whether this code is better than the code
 that uses combinators, but if you aren't familiar with the combinator approach,
 this code looks simpler to read to me. It uses explicit case analysis with
 `match` and `if let`. If an error occurs, it simply stops executing the
index d8758e0c695c21fa394675062133ac856a80bce0..546636720ca212d295cb665639a0f68ba6cafd2a 100644 (file)
@@ -263,7 +263,7 @@ for i in &v {
 }
 ```
 
-This prints out one through three. As we iterate through the vectors, we’re
+This prints out one through three. As we iterate through the vector, we’re
 only given references to the elements. And `v` is itself borrowed as immutable,
 which means we can’t change it while we’re iterating:
 
index 01f06f718f857c2ad3366db48df6756e5e028e51..f7e32943c638e470b76d4930f69a71009022a42f 100644 (file)
@@ -41,6 +41,7 @@
 
 * `!` (`ident!(…)`, `ident!{…}`, `ident![…]`): denotes macro expansion.  See [Macros].
 * `!` (`!expr`): bitwise or logical complement.  Overloadable (`Not`).
+* `!=` (`var != expr`): nonequality comparison.  Overloadable (`PartialEq`).
 * `%` (`expr % expr`): arithmetic remainder.  Overloadable (`Rem`).
 * `%=` (`var %= expr`): arithmetic remainder & assignment.
 * `&` (`expr & expr`): bitwise and.  Overloadable (`BitAnd`).
 * `;` (`[…; len]`): part of fixed-size array syntax.  See [Primitive Types (Arrays)].
 * `<<` (`expr << expr`): left-shift.  Overloadable (`Shl`).
 * `<<=` (`var <<= expr`): left-shift & assignment.
-* `<` (`expr < expr`): less-than comparison.  Overloadable (`Cmp`, `PartialCmp`).
-* `<=` (`var <= expr`): less-than or equal-to comparison.  Overloadable (`Cmp`, `PartialCmp`).
+* `<` (`expr < expr`): less-than comparison.  Overloadable (`PartialOrd`).
+* `<=` (`var <= expr`): less-than or equal-to comparison.  Overloadable (`PartialOrd`).
 * `=` (`var = expr`, `ident = type`): assignment/equivalence.  See [Variable Bindings], [`type` Aliases], generic parameter defaults.
-* `==` (`var == expr`): comparison.  Overloadable (`Eq`, `PartialEq`).
+* `==` (`var == expr`): equality comparison.  Overloadable (`PartialEq`).
 * `=>` (`pat => expr`): part of match arm syntax.  See [Match].
-* `>` (`expr > expr`): greater-than comparison.  Overloadable (`Cmp`, `PartialCmp`).
-* `>=` (`var >= expr`): greater-than or equal-to comparison.  Overloadable (`Cmp`, `PartialCmp`).
+* `>` (`expr > expr`): greater-than comparison.  Overloadable (`PartialOrd`).
+* `>=` (`var >= expr`): greater-than or equal-to comparison.  Overloadable (`PartialOrd`).
 * `>>` (`expr >> expr`): right-shift.  Overloadable (`Shr`).
 * `>>=` (`var >>= expr`): right-shift & assignment.
 * `@` (`ident @ pat`): pattern binding.  See [Patterns (Bindings)].
index b310b2b3351c557d296307b0f203d4e8558219b0..3aa76d168df077ae02358f8a247ee96e104661d8 100644 (file)
@@ -1822,8 +1822,8 @@ unpaired_token
 | LIT_FLOAT                  { $$ = mk_atom(yytext); }
 | LIT_STR                    { $$ = mk_atom(yytext); }
 | LIT_STR_RAW                { $$ = mk_atom(yytext); }
-| LIT_BYTE_STR                 { $$ = mk_atom(yytext); }
-| LIT_BYTE_STR_RAW             { $$ = mk_atom(yytext); }
+| LIT_BYTE_STR               { $$ = mk_atom(yytext); }
+| LIT_BYTE_STR_RAW           { $$ = mk_atom(yytext); }
 | IDENT                      { $$ = mk_atom(yytext); }
 | UNDERSCORE                 { $$ = mk_atom(yytext); }
 | LIFETIME                   { $$ = mk_atom(yytext); }
index cbda1e8880b66c4532f902aeaea3211265dd1aa1..7de6099544525328e259949cc1a247abe96ba50e 100644 (file)
@@ -839,11 +839,10 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
 }
 
 /// Used for items loaded from external crate that are being inlined into this
-/// crate.  The `path` should be the path to the item but should not include
-/// the item itself.
+/// crate.
 pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
-                                          path: Vec<PathElem>,
-                                          def_path: DefPath,
+                                          parent_path: Vec<PathElem>,
+                                          parent_def_path: DefPath,
                                           ii: InlinedItem,
                                           fold_ops: F)
                                           -> &'ast InlinedItem {
@@ -862,7 +861,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     };
 
     let ii_parent = map.forest.inlined_items.alloc(InlinedParent {
-        path: path,
+        path: parent_path,
         ii: ii
     });
 
@@ -872,7 +871,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
             map.krate(),
             ii_parent,
             ii_parent_id,
-            def_path,
+            parent_def_path,
             mem::replace(&mut *map.map.borrow_mut(), vec![]),
             mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()));
     ii_parent.ii.visit(&mut collector);
index a63c662de6165212a945793ea579bbe384759b57..2c2b69ff85b4ebda02f76a8a492bb52c06e2e0c5 100644 (file)
@@ -489,13 +489,6 @@ pub fn make_subregion(&self, origin: SubregionOrigin<'tcx>, sub: Region, sup: Re
                origin);
 
         match (sub, sup) {
-            (ReEarlyBound(..), ReEarlyBound(..)) => {
-                // This case is used only to make sure that explicitly-specified
-                // `Self` types match the real self type in implementations.
-                //
-                // FIXME(NDM) -- we really shouldn't be comparing bound things
-                self.add_verify(VerifyRegSubReg(origin, sub, sup));
-            }
             (ReEarlyBound(..), _) |
             (ReLateBound(..), _) |
             (_, ReEarlyBound(..)) |
index 308883cf063df723e002e90db60c731477d156f9..50c9a1a31f2208b047638d239f2fe4f6a586d646 100644 (file)
@@ -633,7 +633,6 @@ pub struct RegionParameterDef {
 impl RegionParameterDef {
     pub fn to_early_bound_region(&self) -> ty::Region {
         ty::ReEarlyBound(ty::EarlyBoundRegion {
-            def_id: self.def_id,
             space: self.space,
             index: self.index,
             name: self.name,
index 66b2a9d3ad0bfeb8dfab458cb7dc137adf5668e3..6f72d3df07e37774ac248854c648f2368a4cda78 100644 (file)
@@ -695,7 +695,6 @@ pub enum Region {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub struct EarlyBoundRegion {
-    pub def_id: DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
     pub name: Name,
index e83fe60f419a6dcb928df5d9a59ca7302e35658e..be6bb8689eefab0674e5e978cadec17f50887764 100644 (file)
@@ -701,9 +701,9 @@ pub struct Constant<'tcx> {
 #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum ItemKind {
     Constant,
+    /// This is any sort of callable (usually those that have a type of `fn(…) -> …`). This
+    /// includes functions, constructors, but not methods which have their own ItemKind.
     Function,
-    Struct,
-    Variant,
     Method,
 }
 
index b275480a6fc68347113837514bdd6ee58374f7f8..d1c7da1d1075fcb1d6672e1d058400be9d402444 100644 (file)
@@ -622,6 +622,8 @@ fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
           "force nonzeroing move optimization on"),
     keep_mtwt_tables: bool = (false, parse_bool,
           "don't clear the resolution tables after analysis"),
+    keep_ast: bool = (false, parse_bool,
+          "keep the AST after lowering it to HIR"),
 }
 
 pub fn default_lib_output() -> CrateType {
index 3c0a395f57ccbdb5247d6f9d876e32c0ba892ab1..0b362be215dfef40e6b9bc83158bb7430523436a 100644 (file)
@@ -462,8 +462,7 @@ impl fmt::Debug for ty::Region {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::ReEarlyBound(ref data) => {
-                write!(f, "ReEarlyBound({:?}, {:?}, {}, {})",
-                       data.def_id,
+                write!(f, "ReEarlyBound({:?}, {}, {})",
                        data.space,
                        data.index,
                        data.name)
index 89299c01199756ca5e7c6578f1806e6ee7b5d56e..1ac1b5978cfb609cacc6bd9ccf055e9e635ab35b 100644 (file)
@@ -121,7 +121,7 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
         }
 
         let arenas = ty::CtxtArenas::new();
-        let ast_map = make_map(&sess, &mut hir_forest);
+        let hir_map = make_map(&sess, &mut hir_forest);
 
         write_out_deps(&sess, &outputs, &id);
 
@@ -130,9 +130,9 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
                                 CompileState::state_after_write_deps(input,
                                                                      &sess,
                                                                      outdir,
-                                                                     &ast_map,
+                                                                     &hir_map,
                                                                      &expanded_crate,
-                                                                     &ast_map.krate(),
+                                                                     &hir_map.krate(),
                                                                      &id[..],
                                                                      &lcx));
 
@@ -144,9 +144,17 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
              "early lint checks",
              || lint::check_ast_crate(&sess, &expanded_crate));
 
+        let opt_crate = if sess.opts.debugging_opts.keep_ast ||
+                           sess.opts.debugging_opts.save_analysis {
+            Some(&expanded_crate)
+        } else {
+            drop(expanded_crate);
+            None
+        };
+
         phase_3_run_analysis_passes(&sess,
                                     &cstore,
-                                    ast_map,
+                                    hir_map,
                                     &arenas,
                                     &id,
                                     control.make_glob_map,
@@ -157,7 +165,7 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
                                                 CompileState::state_after_analysis(input,
                                                                                    &tcx.sess,
                                                                                    outdir,
-                                                                                   &expanded_crate,
+                                                                                   opt_crate,
                                                                                    tcx.map.krate(),
                                                                                    &analysis,
                                                                                    &mir_map,
@@ -341,7 +349,7 @@ fn state_after_expand(input: &'a Input,
     fn state_after_write_deps(input: &'a Input,
                               session: &'a Session,
                               out_dir: &'a Option<PathBuf>,
-                              ast_map: &'a hir_map::Map<'ast>,
+                              hir_map: &'a hir_map::Map<'ast>,
                               krate: &'a ast::Crate,
                               hir_crate: &'a hir::Crate,
                               crate_name: &'a str,
@@ -349,7 +357,7 @@ fn state_after_write_deps(input: &'a Input,
                               -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             crate_name: Some(crate_name),
-            ast_map: Some(ast_map),
+            ast_map: Some(hir_map),
             krate: Some(krate),
             hir_crate: Some(hir_crate),
             lcx: Some(lcx),
@@ -360,7 +368,7 @@ fn state_after_write_deps(input: &'a Input,
     fn state_after_analysis(input: &'a Input,
                             session: &'a Session,
                             out_dir: &'a Option<PathBuf>,
-                            krate: &'a ast::Crate,
+                            krate: Option<&'a ast::Crate>,
                             hir_crate: &'a hir::Crate,
                             analysis: &'a ty::CrateAnalysis,
                             mir_map: &'a MirMap<'tcx>,
@@ -372,7 +380,7 @@ fn state_after_analysis(input: &'a Input,
             analysis: Some(analysis),
             mir_map: Some(mir_map),
             tcx: Some(tcx),
-            krate: Some(krate),
+            krate: krate,
             hir_crate: Some(hir_crate),
             lcx: Some(lcx),
             crate_name: Some(crate_name),
@@ -670,14 +678,12 @@ fn new_id(&mut self, old_id: ast::NodeId) -> ast::NodeId {
 }
 
 pub fn make_map<'ast>(sess: &Session,
-                      forest: &'ast mut front::map::Forest)
-                      -> front::map::Map<'ast> {
-    // Construct the 'ast'-map
-    let map = time(sess.time_passes(),
-                   "indexing hir",
-                   move || front::map::map_crate(forest));
-
-    map
+                      forest: &'ast mut hir_map::Forest)
+                      -> hir_map::Map<'ast> {
+    // Construct the HIR map
+    time(sess.time_passes(),
+         "indexing hir",
+         move || hir_map::map_crate(forest))
 }
 
 /// Run the resolution, typechecking, region checking and other
@@ -685,7 +691,7 @@ pub fn make_map<'ast>(sess: &Session,
 /// structures carrying the results of the analysis.
 pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                cstore: &CStore,
-                                               ast_map: front::map::Map<'tcx>,
+                                               hir_map: hir_map::Map<'tcx>,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
                                                name: &str,
                                                make_glob_map: resolve::MakeGlobMap,
@@ -694,15 +700,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>, MirMap<'tcx>, ty::CrateAnalysis) -> R
 {
     let time_passes = sess.time_passes();
-    let krate = ast_map.krate();
+    let krate = hir_map.krate();
 
     time(time_passes,
          "external crate/lib resolution",
-         || LocalCrateReader::new(sess, cstore, &ast_map).read_crates(krate));
+         || LocalCrateReader::new(sess, cstore, &hir_map).read_crates(krate));
 
     let lang_items = time(time_passes,
                           "language item collection",
-                          || middle::lang_items::collect_language_items(&sess, &ast_map));
+                          || middle::lang_items::collect_language_items(&sess, &hir_map));
 
     let resolve::CrateMap {
         def_map,
@@ -713,7 +719,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
         glob_map,
     } = time(time_passes,
              "resolution",
-             || resolve::resolve_crate(sess, &ast_map, make_glob_map));
+             || resolve::resolve_crate(sess, &hir_map, make_glob_map));
 
     let named_region_map = time(time_passes,
                                 "lifetime resolution",
@@ -721,7 +727,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     time(time_passes,
          "looking for entry point",
-         || middle::entry::find_entry_point(sess, &ast_map));
+         || middle::entry::find_entry_point(sess, &hir_map));
 
     sess.plugin_registrar_fn.set(time(time_passes, "looking for plugin registrar", || {
         plugin::build::find_plugin_registrar(sess.diagnostic(), krate)
@@ -737,13 +743,13 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     time(time_passes,
          "static item recursion checking",
-         || middle::check_static_recursion::check_crate(sess, krate, &def_map.borrow(), &ast_map));
+         || middle::check_static_recursion::check_crate(sess, krate, &def_map.borrow(), &hir_map));
 
     ty::ctxt::create_and_enter(sess,
                                arenas,
                                def_map,
                                named_region_map,
-                               ast_map,
+                               hir_map,
                                freevars,
                                region_map,
                                lang_items,
index df9294a9d5bfb518cbcab55efb94e6b909154294..50a672a4b69e700414629c453f10dd460010a89b 100644 (file)
@@ -289,7 +289,6 @@ pub fn re_early_bound(&self,
                           -> ty::Region {
         let name = token::intern(name);
         ty::ReEarlyBound(ty::EarlyBoundRegion {
-            def_id: self.infcx.tcx.map.local_def_id(ast::DUMMY_NODE_ID),
             space: space,
             index: index,
             name: name,
index 714f0a4350b3df8f4cffc58342b3643b58d4e5eb..8f74acd9ebdf6f8da88694d89f608ee60df1d5c8 100644 (file)
@@ -124,20 +124,20 @@ fn new_span(&self, span: codemap::Span) -> codemap::Span {
 /// ast-map.
 pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
                                  tcx: &ty::ctxt<'tcx>,
-                                 path: Vec<ast_map::PathElem>,
-                                 def_path: ast_map::DefPath,
+                                 parent_path: Vec<ast_map::PathElem>,
+                                 parent_def_path: ast_map::DefPath,
                                  par_doc: rbml::Doc,
                                  orig_did: DefId)
                                  -> Result<&'tcx InlinedItem, (Vec<ast_map::PathElem>,
                                                                ast_map::DefPath)> {
     match par_doc.opt_child(c::tag_ast) {
-      None => Err((path, def_path)),
+      None => Err((parent_path, parent_def_path)),
       Some(ast_doc) => {
         let mut path_as_str = None;
         debug!("> Decoding inlined fn: {:?}::?",
         {
             // Do an Option dance to use the path after it is moved below.
-            let s = ast_map::path_to_string(path.iter().cloned());
+            let s = ast_map::path_to_string(parent_path.iter().cloned());
             path_as_str = Some(s);
             path_as_str.as_ref().map(|x| &x[..])
         });
@@ -152,8 +152,11 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
             last_filemap_index: Cell::new(0)
         };
         let raw_ii = decode_ast(ast_doc);
-        let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, def_path, raw_ii, dcx);
-
+        let ii = ast_map::map_decoded_item(&dcx.tcx.map,
+                                           parent_path,
+                                           parent_def_path,
+                                           raw_ii,
+                                           dcx);
         let name = match *ii {
             InlinedItem::Item(ref i) => i.name,
             InlinedItem::Foreign(ref i) => i.name,
index 357158c24bacda8809525246b087e7af956e3b31..8126970759e6dcc7e0adaaf3c202126fa0820422 100644 (file)
@@ -763,29 +763,54 @@ pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: DefIndex) -> ast::Nam
 pub type DecodeInlinedItem<'a> =
     Box<for<'tcx> FnMut(Cmd,
                         &ty::ctxt<'tcx>,
-                        Vec<hir_map::PathElem>,
-                        hir_map::DefPath,
+                        Vec<hir_map::PathElem>, // parent_path
+                        hir_map::DefPath,       // parent_def_path
                         rbml::Doc,
                         DefId)
                         -> Result<&'tcx InlinedItem, (Vec<hir_map::PathElem>,
                                                       hir_map::DefPath)> + 'a>;
 
-pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: DefIndex,
+pub fn maybe_get_item_ast<'tcx>(cdata: Cmd,
+                                tcx: &ty::ctxt<'tcx>,
+                                id: DefIndex,
                                 mut decode_inlined_item: DecodeInlinedItem)
                                 -> FoundAst<'tcx> {
     debug!("Looking up item: {:?}", id);
     let item_doc = cdata.lookup_item(id);
     let item_did = item_def_id(item_doc, cdata);
-    let path = item_path(item_doc).split_last().unwrap().1.to_vec();
-    let def_path = def_path(cdata, id);
-    match decode_inlined_item(cdata, tcx, path, def_path, item_doc, item_did) {
+    let parent_path = {
+        let mut path = item_path(item_doc);
+        path.pop();
+        path
+    };
+    let parent_def_path = {
+        let mut def_path = def_path(cdata, id);
+        def_path.pop();
+        def_path
+    };
+    match decode_inlined_item(cdata,
+                              tcx,
+                              parent_path,
+                              parent_def_path,
+                              item_doc,
+                              item_did) {
         Ok(ii) => FoundAst::Found(ii),
-        Err((path, def_path)) => {
+        Err((mut parent_path, mut parent_def_path)) => {
             match item_parent_item(cdata, item_doc) {
-                Some(did) => {
-                    let parent_item = cdata.lookup_item(did.index);
-                    match decode_inlined_item(cdata, tcx, path, def_path, parent_item, did) {
-                        Ok(ii) => FoundAst::FoundParent(did, ii),
+                Some(parent_did) => {
+                    // Remove the last element from the paths, since we are now
+                    // trying to inline the parent.
+                    parent_path.pop();
+                    parent_def_path.pop();
+
+                    let parent_item = cdata.lookup_item(parent_did.index);
+                    match decode_inlined_item(cdata,
+                                              tcx,
+                                              parent_path,
+                                              parent_def_path,
+                                              parent_item,
+                                              parent_did) {
+                        Ok(ii) => FoundAst::FoundParent(parent_did, ii),
                         Err(_) => FoundAst::NotFound
                     }
                 }
index 4d4db062329e07c60cc2c7ba23b6e9cb9449ecf6..b99431d265618a4c02438b6417615927415dbd42 100644 (file)
@@ -192,14 +192,12 @@ pub fn parse_region(&mut self) -> ty::Region {
             }
             'B' => {
                 assert_eq!(self.next(), '[');
-                let def_id = self.parse_def();
                 let space = self.parse_param_space();
                 assert_eq!(self.next(), '|');
                 let index = self.parse_u32();
                 assert_eq!(self.next(), '|');
                 let name = token::intern(&self.parse_str(']'));
                 ty::ReEarlyBound(ty::EarlyBoundRegion {
-                    def_id: def_id,
                     space: space,
                     index: index,
                     name: name
index 0119f1d5cc109bc0343148da32c62f4036b464a5..6d42871201b8e792610a568fcdf57e3fa451c7e4 100644 (file)
@@ -253,8 +253,7 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
             mywrite!(w, "]");
         }
         ty::ReEarlyBound(ref data) => {
-            mywrite!(w, "B[{}|{}|{}|{}]",
-                     (cx.ds)(data.def_id),
+            mywrite!(w, "B[{}|{}|{}]",
                      data.space.to_uint(),
                      data.index,
                      data.name);
index 5cb12627d6ba882eac4e03f2925a4d2f45bbe0e5..ce78a39d599a518d6bd4cf6d2600f249bc61f11b 100644 (file)
@@ -519,51 +519,64 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
     let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
     // Otherwise there may be def_map borrow conflicts
     let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
-    match def {
-        def::DefVariant(_, def_id, false) |
-        def::DefStruct(def_id) |
-        def::DefFn(def_id, _) |
-        def::DefMethod(def_id) => {
-            let kind = match def {
-                def::DefVariant(..) => ItemKind::Variant,
-                def::DefStruct(..) => ItemKind::Struct,
-                def::DefFn(..) => ItemKind::Function,
-                def::DefMethod(..) => ItemKind::Method,
-                _ => panic!()
-            };
-            ExprKind::Literal {
-                literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
-            }
+    let (def_id, kind) = match def {
+        // A regular function.
+        def::DefFn(def_id, _) => (def_id, ItemKind::Function),
+        def::DefMethod(def_id) => (def_id, ItemKind::Method),
+        def::DefStruct(def_id) => match cx.tcx.node_id_to_type(expr.id).sty {
+            // A tuple-struct constructor.
+            ty::TyBareFn(..) => (def_id, ItemKind::Function),
+            // This is a special case: a unit struct which is used as a value. We return a
+            // completely different ExprKind here to account for this special case.
+            ty::TyStruct(adt_def, substs) => return ExprKind::Adt {
+                adt_def: adt_def,
+                variant_index: 0,
+                substs: substs,
+                fields: vec![],
+                base: None
+            },
+            ref sty => panic!("unexpected sty: {:?}", sty)
+        },
+        def::DefVariant(enum_id, variant_id, false) => match cx.tcx.node_id_to_type(expr.id).sty {
+            // A variant constructor.
+            ty::TyBareFn(..) => (variant_id, ItemKind::Function),
+            // A unit variant, similar special case to the struct case above.
+            ty::TyEnum(adt_def, substs) => {
+                debug_assert!(adt_def.did == enum_id);
+                let index = adt_def.variant_index_with_id(variant_id);
+                return ExprKind::Adt {
+                    adt_def: adt_def,
+                    substs: substs,
+                    variant_index: index,
+                    fields: vec![],
+                    base: None
+                };
+            },
+            ref sty => panic!("unexpected sty: {:?}", sty)
         },
         def::DefConst(def_id) |
         def::DefAssociatedConst(def_id) => {
             if let Some(v) = cx.try_const_eval_literal(expr) {
-                ExprKind::Literal { literal: v }
+                return ExprKind::Literal { literal: v };
             } else {
-                ExprKind::Literal {
-                    literal: Literal::Item {
-                        def_id: def_id,
-                        kind: ItemKind::Constant,
-                        substs: substs
-                    }
-                }
+                (def_id, ItemKind::Constant)
             }
         }
 
-
-        def::DefStatic(node_id, _) =>
-            ExprKind::StaticRef {
-                id: node_id,
-            },
+        def::DefStatic(node_id, _) => return ExprKind::StaticRef {
+            id: node_id,
+        },
 
         def @ def::DefLocal(..) |
-        def @ def::DefUpvar(..) =>
-            convert_var(cx, expr, def),
+        def @ def::DefUpvar(..) => return convert_var(cx, expr, def),
 
         def =>
             cx.tcx.sess.span_bug(
                 expr.span,
                 &format!("def `{:?}` not yet implemented", def)),
+    };
+    ExprKind::Literal {
+        literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
     }
 }
 
index ecf54cde9f63a7ba5ce37df816f4399b3a756d96..85d4876d160be491fbe79552d86bad56645a7a3b 100644 (file)
@@ -2187,15 +2187,19 @@ fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let referent_ty = lv_datum.ty;
     let ptr_ty = bcx.tcx().mk_imm_ref(bcx.tcx().mk_region(ty::ReStatic), referent_ty);
 
+    // Construct the resulting datum. The right datum to return here would be an Lvalue datum,
+    // because there is cleanup scheduled and the datum doesn't own the data, but for thin pointers
+    // we microoptimize it to be an Rvalue datum to avoid the extra alloca and level of
+    // indirection and for thin pointers, this has no ill effects.
+    let kind  = if type_is_sized(bcx.tcx(), referent_ty) {
+        RvalueExpr(Rvalue::new(ByValue))
+    } else {
+        LvalueExpr(lv_datum.kind)
+    };
+
     // Get the pointer.
     let llref = lv_datum.to_llref();
-
-    // Construct the resulting datum, using what was the "by ref"
-    // ValueRef of type `referent_ty` to be the "by value" ValueRef
-    // of type `&referent_ty`.
-    // Pointers to DST types are non-immediate, and therefore still use ByRef.
-    let kind  = if type_is_sized(bcx.tcx(), referent_ty) { ByValue } else { ByRef };
-    DatumBlock::new(bcx, Datum::new(llref, ptr_ty, RvalueExpr(Rvalue::new(kind))))
+    DatumBlock::new(bcx, Datum::new(llref, ptr_ty, kind))
 }
 
 fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
index 368708d470bef12c94aae6d1565160a9b7b62759..d4a7a7c8b48ff3234be80857dfae5c084e39d550 100644 (file)
@@ -39,9 +39,7 @@ pub fn trans_item_ref(&mut self,
                           did: DefId)
                           -> OperandRef<'tcx> {
         match kind {
-            ItemKind::Function |
-            ItemKind::Struct |
-            ItemKind::Variant => self.trans_fn_ref(bcx, ty, substs, did),
+            ItemKind::Function => self.trans_fn_ref(bcx, ty, substs, did),
             ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() {
                 ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did),
                 ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs)
index 529e65dace04cea804e843f8f1b5bf93a92f76a5..a08ec123895df0cf2d164d670b69e1a266fa418f 100644 (file)
@@ -19,6 +19,7 @@
 use trans::debuginfo::DebugLoc;
 use trans::declare;
 use trans::expr;
+use trans::adt;
 use trans::machine;
 use trans::type_::Type;
 use trans::type_of;
 
 use super::MirContext;
 use super::operand::{OperandRef, OperandValue};
+use super::lvalue::LvalueRef;
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_rvalue(&mut self,
                         bcx: Block<'bcx, 'tcx>,
-                        lldest: ValueRef,
+                        dest: LvalueRef<'tcx>,
                         rvalue: &mir::Rvalue<'tcx>)
                         -> Block<'bcx, 'tcx>
     {
-        debug!("trans_rvalue(lldest={}, rvalue={:?})",
-               bcx.val_to_string(lldest),
+        debug!("trans_rvalue(dest.llval={}, rvalue={:?})",
+               bcx.val_to_string(dest.llval),
                rvalue);
 
         match *rvalue {
             mir::Rvalue::Use(ref operand) => {
-                self.trans_operand_into(bcx, lldest, operand);
+                self.trans_operand_into(bcx, dest.llval, operand);
                 bcx
             }
 
@@ -49,7 +51,7 @@ pub fn trans_rvalue(&mut self,
                     // into-coerce of a thin pointer to a fat pointer - just
                     // use the operand path.
                     let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                    self.store_operand(bcx, lldest, temp);
+                    self.store_operand(bcx, dest.llval, temp);
                     return bcx;
                 }
 
@@ -72,12 +74,12 @@ pub fn trans_rvalue(&mut self,
                         base::store_ty(bcx, llval, lltemp, operand.ty);
                         base::coerce_unsized_into(bcx,
                                                   lltemp, operand.ty,
-                                                  lldest, cast_ty);
+                                                  dest.llval, cast_ty);
                     }
                     OperandValue::Ref(llref) => {
                         base::coerce_unsized_into(bcx,
                                                   llref, operand.ty,
-                                                  lldest, cast_ty);
+                                                  dest.llval, cast_ty);
                     }
                 }
                 bcx
@@ -86,20 +88,31 @@ pub fn trans_rvalue(&mut self,
             mir::Rvalue::Repeat(ref elem, ref count) => {
                 let elem = self.trans_operand(bcx, elem);
                 let size = self.trans_constant(bcx, count).immediate();
-                let base = expr::get_dataptr(bcx, lldest);
+                let base = expr::get_dataptr(bcx, dest.llval);
                 tvec::iter_vec_raw(bcx, base, elem.ty, size, |bcx, llslot, _| {
                     self.store_operand(bcx, llslot, elem);
                     bcx
                 })
             }
 
-            mir::Rvalue::Aggregate(_, ref operands) => {
-                for (i, operand) in operands.iter().enumerate() {
-                    // Note: perhaps this should be StructGep, but
-                    // note that in some cases the values here will
-                    // not be structs but arrays.
-                    let lldest_i = build::GEPi(bcx, lldest, &[0, i]);
-                    self.trans_operand_into(bcx, lldest_i, operand);
+            mir::Rvalue::Aggregate(ref kind, ref operands) => {
+                match *kind {
+                    // Unit struct or variant; both are translated very differently compared to any
+                    // other aggregate
+                    mir::AggregateKind::Adt(adt_def, index, _)
+                    if adt_def.variants[index].kind() == ty::VariantKind::Unit => {
+                        let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
+                        adt::trans_set_discr(bcx, &*repr, dest.llval, 0);
+                    },
+                    _ => {
+                        for (i, operand) in operands.iter().enumerate() {
+                            // Note: perhaps this should be StructGep, but
+                            // note that in some cases the values here will
+                            // not be structs but arrays.
+                            let lldest_i = build::GEPi(bcx, dest.llval, &[0, i]);
+                            self.trans_operand_into(bcx, lldest_i, operand);
+                        }
+                    }
                 }
                 bcx
             }
@@ -113,9 +126,9 @@ pub fn trans_rvalue(&mut self,
                 let llbase1 = build::GEPi(bcx, llbase, &[from_start]);
                 let adj = common::C_uint(ccx, from_start + from_end);
                 let lllen1 = build::Sub(bcx, lllen, adj, DebugLoc::None);
-                let lladdrdest = expr::get_dataptr(bcx, lldest);
+                let lladdrdest = expr::get_dataptr(bcx, dest.llval);
                 build::Store(bcx, llbase1, lladdrdest);
-                let llmetadest = expr::get_meta(bcx, lldest);
+                let llmetadest = expr::get_meta(bcx, dest.llval);
                 build::Store(bcx, lllen1, llmetadest);
                 bcx
             }
@@ -127,7 +140,7 @@ pub fn trans_rvalue(&mut self,
             _ => {
                 assert!(rvalue_creates_operand(rvalue));
                 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                self.store_operand(bcx, lldest, temp);
+                self.store_operand(bcx, dest.llval, temp);
                 bcx
             }
         }
index 9894626e284a2495c4ef51d26b6380695cb5bce3..dae0d3b55c0ba2bec9c3bfee01abd13aa2197929 100644 (file)
@@ -31,7 +31,7 @@ pub fn trans_statement(&mut self,
                         let index = index as usize;
                         match self.temps[index as usize] {
                             TempRef::Lvalue(tr_dest) => {
-                                self.trans_rvalue(bcx, tr_dest.llval, rvalue)
+                                self.trans_rvalue(bcx, tr_dest, rvalue)
                             }
                             TempRef::Operand(None) => {
                                 let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue);
@@ -47,7 +47,7 @@ pub fn trans_statement(&mut self,
                     }
                     _ => {
                         let tr_dest = self.trans_lvalue(bcx, lvalue);
-                        self.trans_rvalue(bcx, tr_dest.llval, rvalue)
+                        self.trans_rvalue(bcx, tr_dest, rvalue)
                     }
                 }
             }
index 98ae3071b87d22c3927dca80f286c65a2bd55802..95d85964044da7be0ef5175ed104128ecf6d213a 100644 (file)
@@ -57,7 +57,7 @@
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
 use middle::traits;
-use middle::ty::{self, RegionEscape, Ty, ToPredicate, HasTypeFlags};
+use middle::ty::{self, Ty, ToPredicate, HasTypeFlags};
 use middle::ty::wf::object_region_bounds;
 use require_c_abi_if_variadic;
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
@@ -169,10 +169,8 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &hir::Lifetime)
             ty::ReLateBound(debruijn, ty::BrNamed(tcx.map.local_def_id(id), lifetime.name))
         }
 
-        Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
-            let def_id = tcx.map.local_def_id(id);
+        Some(&rl::DefEarlyBoundRegion(space, index, _)) => {
             ty::ReEarlyBound(ty::EarlyBoundRegion {
-                def_id: def_id,
                 space: space,
                 index: index,
                 name: lifetime.name
@@ -1797,75 +1795,31 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
     // lifetime elision, we can determine it in two ways. First (determined
     // here), if self is by-reference, then the implied output region is the
     // region of the self parameter.
-    let mut explicit_self_category_result = None;
-    let (self_ty, implied_output_region) = match opt_self_info {
+    let (self_ty, explicit_self_category) = match opt_self_info {
         None => (None, None),
-        Some(self_info) => {
-            // This type comes from an impl or trait; no late-bound
-            // regions should be present.
-            assert!(!self_info.untransformed_self_ty.has_escaping_regions());
-
-            // Figure out and record the explicit self category.
-            let explicit_self_category =
-                determine_explicit_self_category(this, &rb, &self_info);
-            explicit_self_category_result = Some(explicit_self_category);
-            match explicit_self_category {
-                ty::StaticExplicitSelfCategory => {
-                    (None, None)
-                }
-                ty::ByValueExplicitSelfCategory => {
-                    (Some(self_info.untransformed_self_ty), None)
-                }
-                ty::ByReferenceExplicitSelfCategory(region, mutability) => {
-                    (Some(this.tcx().mk_ref(
-                                      this.tcx().mk_region(region),
-                                      ty::TypeAndMut {
-                                        ty: self_info.untransformed_self_ty,
-                                        mutbl: mutability
-                                      })),
-                     Some(region))
-                }
-                ty::ByBoxExplicitSelfCategory => {
-                    (Some(this.tcx().mk_box(self_info.untransformed_self_ty)), None)
-                }
-            }
-        }
+        Some(self_info) => determine_self_type(this, &rb, self_info)
     };
 
     // HACK(eddyb) replace the fake self type in the AST with the actual type.
-    let input_params = if self_ty.is_some() {
+    let arg_params = if self_ty.is_some() {
         &decl.inputs[1..]
     } else {
         &decl.inputs[..]
     };
-    let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None));
-    let input_pats: Vec<String> = input_params.iter()
-                                              .map(|a| pprust::pat_to_string(&*a.pat))
-                                              .collect();
-    let self_and_input_tys: Vec<Ty> =
-        self_ty.into_iter().chain(input_tys).collect();
-
+    let arg_tys: Vec<Ty> =
+        arg_params.iter().map(|a| ty_of_arg(this, &rb, a, None)).collect();
+    let arg_pats: Vec<String> =
+        arg_params.iter().map(|a| pprust::pat_to_string(&*a.pat)).collect();
 
     // Second, if there was exactly one lifetime (either a substitution or a
     // reference) in the arguments, then any anonymous regions in the output
     // have that lifetime.
-    let implied_output_region = match implied_output_region {
-        Some(r) => Ok(r),
-        None => {
-            let input_tys = if self_ty.is_some() {
-                // Skip the first argument if `self` is present.
-                &self_and_input_tys[1..]
-            } else {
-                &self_and_input_tys[..]
-            };
-
-            find_implied_output_region(this.tcx(), input_tys, input_pats)
-        }
+    let implied_output_region = match explicit_self_category {
+        Some(ty::ByReferenceExplicitSelfCategory(region, _)) => Ok(region),
+        _ => find_implied_output_region(this.tcx(), &arg_tys, arg_pats)
     };
 
     let output_ty = match decl.output {
-        hir::Return(ref output) if output.node == hir::TyInfer =>
-            ty::FnConverging(this.ty_infer(None, None, None, output.span)),
         hir::Return(ref output) =>
             ty::FnConverging(convert_ty_with_lifetime_elision(this,
                                                               implied_output_region,
@@ -1878,28 +1832,37 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
         unsafety: unsafety,
         abi: abi,
         sig: ty::Binder(ty::FnSig {
-            inputs: self_and_input_tys,
+            inputs: self_ty.into_iter().chain(arg_tys).collect(),
             output: output_ty,
             variadic: decl.variadic
         }),
-    }, explicit_self_category_result)
+    }, explicit_self_category)
 }
 
-fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
-                                              rscope: &RegionScope,
-                                              self_info: &SelfInfo<'a, 'tcx>)
-                                              -> ty::ExplicitSelfCategory
+fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx>,
+                                 rscope: &RegionScope,
+                                 self_info: SelfInfo<'a, 'tcx>)
+                                 -> (Option<Ty<'tcx>>, Option<ty::ExplicitSelfCategory>)
 {
+    let self_ty = self_info.untransformed_self_ty;
     return match self_info.explicit_self.node {
-        hir::SelfStatic => ty::StaticExplicitSelfCategory,
-        hir::SelfValue(_) => ty::ByValueExplicitSelfCategory,
+        hir::SelfStatic => (None, Some(ty::StaticExplicitSelfCategory)),
+        hir::SelfValue(_) => {
+            (Some(self_ty), Some(ty::ByValueExplicitSelfCategory))
+        }
         hir::SelfRegion(ref lifetime, mutability, _) => {
             let region =
                 opt_ast_region_to_region(this,
                                          rscope,
                                          self_info.explicit_self.span,
                                          lifetime);
-            ty::ByReferenceExplicitSelfCategory(region, mutability)
+            (Some(this.tcx().mk_ref(
+                this.tcx().mk_region(region),
+                ty::TypeAndMut {
+                    ty: self_ty,
+                    mutbl: mutability
+                })),
+             Some(ty::ByReferenceExplicitSelfCategory(region, mutability)))
         }
         hir::SelfExplicit(ref ast_type, _) => {
             let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type);
@@ -1944,7 +1907,7 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
                    impl_modifiers,
                    method_modifiers);
 
-            if impl_modifiers >= method_modifiers {
+            let category = if impl_modifiers >= method_modifiers {
                 ty::ByValueExplicitSelfCategory
             } else {
                 match explicit_type.sty {
@@ -1952,7 +1915,9 @@ fn determine_explicit_self_category<'a, 'tcx>(this: &AstConv<'tcx>,
                     ty::TyBox(_) => ty::ByBoxExplicitSelfCategory,
                     _ => ty::ByValueExplicitSelfCategory,
                 }
-            }
+            };
+
+            (Some(explicit_type), Some(category))
         }
     };
 
index 5d0e713012f2a618d63ca1efd8933d0d588649b9..230422b7044cd5d366463efc59d885daf57eec84 100644 (file)
@@ -136,9 +136,10 @@ fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
 
             let item = fcx.tcx().impl_or_trait_item(fcx.tcx().map.local_def_id(item_id));
 
-            let mut implied_bounds = match item.container() {
-                ty::TraitContainer(_) => vec![],
-                ty::ImplContainer(def_id) => impl_implied_bounds(fcx, def_id, span)
+            let (mut implied_bounds, self_ty) = match item.container() {
+                ty::TraitContainer(_) => (vec![], fcx.tcx().mk_self_type()),
+                ty::ImplContainer(def_id) => (impl_implied_bounds(fcx, def_id, span),
+                                              fcx.tcx().lookup_item_type(def_id).ty)
             };
 
             match item {
@@ -152,6 +153,8 @@ fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
                     let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates);
                     this.check_fn_or_method(fcx, span, &method_ty, &predicates,
                                             free_id_outlive, &mut implied_bounds);
+                    this.check_method_receiver(fcx, span, &method,
+                                               free_id_outlive, self_ty);
                 }
                 ty::TypeTraitItem(assoc_type) => {
                     if let Some(ref ty) = assoc_type.ty {
@@ -377,6 +380,47 @@ fn check_fn_or_method<'fcx>(&mut self,
         self.check_where_clauses(fcx, span, predicates);
     }
 
+    fn check_method_receiver<'fcx>(&mut self,
+                                   fcx: &FnCtxt<'fcx,'tcx>,
+                                   span: Span,
+                                   method: &ty::Method<'tcx>,
+                                   free_id_outlive: CodeExtent,
+                                   self_ty: ty::Ty<'tcx>)
+    {
+        // check that the type of the method's receiver matches the
+        // method's first parameter.
+
+        let free_substs = &fcx.inh.infcx.parameter_environment.free_substs;
+        let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
+        let sig = fcx.tcx().liberate_late_bound_regions(free_id_outlive, &fty.sig);
+
+        debug!("check_method_receiver({:?},cat={:?},self_ty={:?},sig={:?})",
+               method.name, method.explicit_self, self_ty, sig);
+
+        let rcvr_ty = match method.explicit_self {
+            ty::StaticExplicitSelfCategory => return,
+            ty::ByValueExplicitSelfCategory => self_ty,
+            ty::ByReferenceExplicitSelfCategory(region, mutability) => {
+                fcx.tcx().mk_ref(fcx.tcx().mk_region(region), ty::TypeAndMut {
+                    ty: self_ty,
+                    mutbl: mutability
+                })
+            }
+            ty::ByBoxExplicitSelfCategory => fcx.tcx().mk_box(self_ty)
+        };
+        let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
+        let rcvr_ty = fcx.tcx().liberate_late_bound_regions(free_id_outlive,
+                                                            &ty::Binder(rcvr_ty));
+
+        debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
+
+        let _ = ::require_same_types(
+            fcx.tcx(), Some(fcx.infcx()), false, span,
+            sig.inputs[0], rcvr_ty,
+            || "mismatched method receiver".to_owned()
+        );
+    }
+
     fn check_variances_for_type_defn(&self,
                                      item: &hir::Item,
                                      ast_generics: &hir::Generics)
index bfe4151da5c91c3c99cff4b6b722ed057b9a47a9..b7ce91d331723a572220c211d2ac8e70ca9dae5b 100644 (file)
 use middle::def_id::DefId;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
-use middle::free_region::FreeRegionMap;
-use middle::region;
 use middle::resolve_lifetime;
 use middle::const_eval::{self, ConstVal};
 use middle::const_eval::EvalHint::UncheckedExprHint;
 use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
 use middle::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
-use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
+use middle::ty::{self, ToPolyTraitRef, Ty, TypeScheme};
 use middle::ty::{VariantKind};
-use middle::ty::fold::{TypeFolder, TypeFoldable};
+use middle::ty::fold::{TypeFolder};
 use middle::ty::util::IntTypeExt;
-use middle::infer;
 use rscope::*;
 use rustc::front::map as hir_map;
 use util::common::{ErrorReported, memoized};
@@ -195,16 +192,6 @@ fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,
         ItemCtxt { ccx: self, param_bounds: param_bounds }
     }
 
-    fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
-        let def_id = self.tcx.map.local_def_id(method_id);
-        match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
-            ty::MethodTraitItem(ref mty) => mty.clone(),
-            _ => {
-                self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
-            }
-        }
-    }
-
     fn cycle_check<F,R>(&self,
                         span: Span,
                         request: AstConvRequest,
@@ -573,10 +560,10 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
 
 fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             container: ImplOrTraitItemContainer,
-                            sig: &hir::MethodSig,
-                            id: ast::NodeId,
                             name: ast::Name,
+                            id: ast::NodeId,
                             vis: hir::Visibility,
+                            sig: &hir::MethodSig,
                             untransformed_rcvr_ty: Ty<'tcx>,
                             rcvr_ty_generics: &ty::Generics<'tcx>,
                             rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
@@ -681,33 +668,6 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
        .insert(ccx.tcx.map.local_def_id(id), ty::TypeTraitItem(associated_type));
 }
 
-fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
-                                 container: ImplOrTraitItemContainer,
-                                 methods: I,
-                                 untransformed_rcvr_ty: Ty<'tcx>,
-                                 rcvr_ty_generics: &ty::Generics<'tcx>,
-                                 rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
-    where I: Iterator<Item=(&'i hir::MethodSig, ast::NodeId, ast::Name, hir::Visibility, Span)>
-{
-    debug!("convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?}, \
-                            rcvr_ty_predicates={:?})",
-           untransformed_rcvr_ty,
-           rcvr_ty_generics,
-           rcvr_ty_predicates);
-
-    for (sig, id, name, vis, _span) in methods {
-        convert_method(ccx,
-                       container,
-                       sig,
-                       id,
-                       name,
-                       vis,
-                       untransformed_rcvr_ty,
-                       rcvr_ty_generics,
-                       rcvr_ty_predicates);
-    }
-}
-
 fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
                                  span: Span,
                                  generics: &hir::Generics,
@@ -867,36 +827,17 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                 }
             }
 
-            let methods = impl_items.iter().filter_map(|ii| {
-                if let hir::ImplItemKind::Method(ref sig, _) = ii.node {
+            for impl_item in impl_items {
+                if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
                     // if the method specifies a visibility, use that, otherwise
                     // inherit the visibility from the impl (so `foo` in `pub impl
                     // { fn foo(); }` is public, but private in `impl { fn
                     // foo(); }`).
-                    let method_vis = ii.vis.inherit_from(parent_visibility);
-                    Some((sig, ii.id, ii.name, method_vis, ii.span))
-                } else {
-                    None
-                }
-            });
-            convert_methods(ccx,
-                            ImplContainer(def_id),
-                            methods,
-                            selfty,
-                            &ty_generics,
-                            &ty_predicates);
+                    let method_vis = impl_item.vis.inherit_from(parent_visibility);
 
-            for impl_item in impl_items {
-                if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
-                    let body_id = body.id;
-                    let body_scope = ccx.tcx.region_maps.call_site_extent(impl_item.id, body_id);
-                    check_method_self_type(ccx,
-                                           &BindingRscope::new(),
-                                           ccx.method_ty(impl_item.id),
-                                           selfty,
-                                           &sig.explicit_self,
-                                           body_scope,
-                                           body_id);
+                    convert_method(ccx, ImplContainer(def_id),
+                                   impl_item.name, impl_item.id, method_vis,
+                                   sig, selfty, &ty_generics, &ty_predicates);
                 }
             }
 
@@ -904,112 +845,80 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
         },
         hir::ItemTrait(_, _, _, ref trait_items) => {
             let trait_def = trait_def_of_item(ccx, it);
+            let def_id = trait_def.trait_ref.def_id;
             let _: Result<(), ErrorReported> = // any error is already reported, can ignore
-                ccx.ensure_super_predicates(it.span, ccx.tcx.map.local_def_id(it.id));
+                ccx.ensure_super_predicates(it.span, def_id);
             convert_trait_predicates(ccx, it);
-            let trait_predicates = tcx.lookup_predicates(ccx.tcx.map.local_def_id(it.id));
+            let trait_predicates = tcx.lookup_predicates(def_id);
 
             debug!("convert: trait_bounds={:?}", trait_predicates);
 
-            // Convert all the associated types.
+            // FIXME: is the ordering here important? I think it is.
+            let container = TraitContainer(def_id);
+
+            // Convert all the associated constants.
             for trait_item in trait_items {
-                match trait_item.node {
-                    hir::ConstTraitItem(ref ty, ref default) => {
-                        let ty = ccx.icx(&trait_predicates)
-                                    .to_ty(&ExplicitRscope, ty);
-                        tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id),
-                                               TypeScheme {
-                                                   generics: trait_def.generics.clone(),
-                                                   ty: ty,
-                                               });
-                        convert_associated_const(ccx,
-                                                 TraitContainer(ccx.tcx.map.local_def_id(it.id)),
-                                                 trait_item.name,
-                                                 trait_item.id,
-                                                 hir::Public,
-                                                 ty,
-                                                 default.is_some())
-                    }
-                    _ => {}
+                if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node {
+                    let ty = ccx.icx(&trait_predicates)
+                        .to_ty(&ExplicitRscope, ty);
+                    tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id),
+                                           TypeScheme {
+                                               generics: trait_def.generics.clone(),
+                                               ty: ty,
+                                           });
+                    convert_associated_const(ccx,
+                                             container,
+                                             trait_item.name,
+                                             trait_item.id,
+                                             hir::Public,
+                                             ty,
+                                             default.is_some())
                 }
-            };
+            }
 
             // Convert all the associated types.
             for trait_item in trait_items {
-                match trait_item.node {
-                    hir::TypeTraitItem(_, ref opt_ty) => {
-                        let typ = opt_ty.as_ref().map({
-                            |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
-                        });
-
-                        convert_associated_type(ccx,
-                                                TraitContainer(ccx.tcx.map.local_def_id(it.id)),
-                                                trait_item.name,
-                                                trait_item.id,
-                                                hir::Public,
-                                                typ);
-                    }
-                    _ => {}
+                if let hir::TypeTraitItem(_, ref opt_ty) = trait_item.node {
+                    let typ = opt_ty.as_ref().map({
+                        |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
+                    });
+
+                    convert_associated_type(ccx,
+                                            container,
+                                            trait_item.name,
+                                            trait_item.id,
+                                            hir::Public,
+                                            typ);
                 }
-            };
+            }
 
-            let methods = trait_items.iter().filter_map(|ti| {
-                let sig = match ti.node {
-                    hir::MethodTraitItem(ref sig, _) => sig,
-                    _ => return None,
-                };
-                Some((sig, ti.id, ti.name, hir::Inherited, ti.span))
-            });
+            // Convert all the methods
+            for trait_item in trait_items {
+                if let hir::MethodTraitItem(ref sig, _) = trait_item.node {
+                    convert_method(ccx,
+                                   container,
+                                   trait_item.name,
+                                   trait_item.id,
+                                   hir::Inherited,
+                                   sig,
+                                   tcx.mk_self_type(),
+                                   &trait_def.generics,
+                                   &trait_predicates);
 
-            // Run convert_methods on the trait methods.
-            convert_methods(ccx,
-                            TraitContainer(ccx.tcx.map.local_def_id(it.id)),
-                            methods,
-                            tcx.mk_self_type(),
-                            &trait_def.generics,
-                            &trait_predicates);
+                }
+            }
 
             // Add an entry mapping
             let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
                 let def_id = ccx.tcx.map.local_def_id(trait_item.id);
                 match trait_item.node {
-                    hir::ConstTraitItem(..) => {
-                        ty::ConstTraitItemId(def_id)
-                    }
-                    hir::MethodTraitItem(..) => {
-                        ty::MethodTraitItemId(def_id)
-                    }
-                    hir::TypeTraitItem(..) => {
-                        ty::TypeTraitItemId(def_id)
-                    }
+                    hir::ConstTraitItem(..) => ty::ConstTraitItemId(def_id),
+                    hir::MethodTraitItem(..) => ty::MethodTraitItemId(def_id),
+                    hir::TypeTraitItem(..) => ty::TypeTraitItemId(def_id)
                 }
             }).collect());
             tcx.trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
                                                        trait_item_def_ids);
-
-            // This must be done after `collect_trait_methods` so that
-            // we have a method type stored for every method.
-            for trait_item in trait_items {
-                let (sig, the_scope, the_id) = match trait_item.node {
-                    hir::MethodTraitItem(ref sig, Some(ref body)) => {
-                        let body_scope =
-                            ccx.tcx.region_maps.call_site_extent(trait_item.id, body.id);
-                        (sig, body_scope, body.id)
-                    }
-                    hir::MethodTraitItem(ref sig, None) => {
-                        let item_scope = ccx.tcx.region_maps.item_extent(trait_item.id);
-                        (sig, item_scope, it.id)
-                    }
-                    _ => continue
-                };
-                check_method_self_type(ccx,
-                                       &BindingRscope::new(),
-                                       ccx.method_ty(trait_item.id),
-                                       tcx.mk_self_type(),
-                                       &sig.explicit_self,
-                                       the_scope,
-                                       the_id)
-            }
         },
         hir::ItemStruct(ref struct_def, _) => {
             let (scheme, predicates) = convert_typed_item(ccx, it);
@@ -1395,7 +1304,6 @@ fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     .iter()
                     .enumerate()
                     .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
-                        def_id: tcx.map.local_def_id(def.lifetime.id),
                         space: TypeSpace,
                         index: i as u32,
                         name: def.lifetime.name
@@ -1870,10 +1778,8 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
     for (index, param) in early_lifetimes.iter().enumerate() {
         let index = index as u32;
-        let def_id = tcx.map.local_def_id(param.lifetime.id);
         let region =
             ty::ReEarlyBound(ty::EarlyBoundRegion {
-                def_id: def_id,
                 space: space,
                 index: index,
                 name: param.lifetime.name
@@ -2281,106 +2187,6 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     Substs::new(types, regions)
 }
 
-/// Verifies that the explicit self type of a method matches the impl
-/// or trait. This is a bit weird but basically because right now we
-/// don't handle the general case, but instead map it to one of
-/// several pre-defined options using various heuristics, this method
-/// comes back to check after the fact that explicit type the user
-/// wrote actually matches what the pre-defined option said.
-fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
-    ccx: &CrateCtxt<'a, 'tcx>,
-    rs: &RS,
-    method_type: Rc<ty::Method<'tcx>>,
-    required_type: Ty<'tcx>,
-    explicit_self: &hir::ExplicitSelf,
-    body_scope: region::CodeExtent,
-    body_id: ast::NodeId)
-{
-    let tcx = ccx.tcx;
-    if let hir::SelfExplicit(ref ast_type, _) = explicit_self.node {
-        let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
-        let base_type = match typ.sty {
-            ty::TyRef(_, tm) => tm.ty,
-            ty::TyBox(typ) => typ,
-            _ => typ,
-        };
-
-        // "Required type" comes from the trait definition. It may
-        // contain late-bound regions from the method, but not the
-        // trait (since traits only have early-bound region
-        // parameters).
-        assert!(!base_type.has_regions_escaping_depth(1));
-        let required_type_free =
-            liberate_early_bound_regions(
-                tcx, body_scope,
-                &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(required_type)));
-
-        // The "base type" comes from the impl. It too may have late-bound
-        // regions from the method.
-        assert!(!base_type.has_regions_escaping_depth(1));
-        let base_type_free =
-            liberate_early_bound_regions(
-                tcx, body_scope,
-                &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(base_type)));
-
-        debug!("required_type={:?} required_type_free={:?} \
-                base_type={:?} base_type_free={:?}",
-               required_type,
-               required_type_free,
-               base_type,
-               base_type_free);
-
-        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
-        drop(::require_same_types(tcx,
-                                  Some(&infcx),
-                                  false,
-                                  explicit_self.span,
-                                  base_type_free,
-                                  required_type_free,
-                                  || {
-                format!("mismatched self type: expected `{}`",
-                         required_type)
-        }));
-
-        // We could conceviably add more free-region relations here,
-        // but since this code is just concerned with checking that
-        // the `&Self` types etc match up, it's not really necessary.
-        // It would just allow people to be more approximate in some
-        // cases. In any case, we can do it later as we feel the need;
-        // I'd like this function to go away eventually.
-        let free_regions = FreeRegionMap::new();
-
-        infcx.resolve_regions_and_report_errors(&free_regions, body_id);
-    }
-
-    fn liberate_early_bound_regions<'tcx,T>(
-        tcx: &ty::ctxt<'tcx>,
-        scope: region::CodeExtent,
-        value: &T)
-        -> T
-        where T : TypeFoldable<'tcx>
-    {
-        /*!
-         * Convert early-bound regions into free regions; normally this is done by
-         * applying the `free_substs` from the `ParameterEnvironment`, but this particular
-         * method-self-type check is kind of hacky and done very early in the process,
-         * before we really have a `ParameterEnvironment` to check.
-         */
-
-        tcx.fold_regions(value, &mut false, |region, _| {
-            match region {
-                ty::ReEarlyBound(data) => {
-                    ty::ReFree(ty::FreeRegion {
-                        scope: scope,
-                        bound_region: ty::BrNamed(data.def_id, data.name)
-                    })
-                }
-                _ => region
-            }
-        })
-    }
-}
-
 /// Checks that all the type parameters on an impl
 fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
                                              ast_generics: &hir::Generics,
@@ -2450,9 +2256,7 @@ fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
                   .collect();
 
     for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
-        let def_id = tcx.map.local_def_id(lifetime_def.lifetime.id);
-        let region = ty::EarlyBoundRegion { def_id: def_id,
-                                            space: TypeSpace,
+        let region = ty::EarlyBoundRegion { space: TypeSpace,
                                             index: index as u32,
                                             name: lifetime_def.lifetime.name };
         if
index 1fafe3484f0f24c9410606c225b94719f398424d..8c7967c7078073d424112c38b759b3d1f6445364 100644 (file)
@@ -1002,12 +1002,14 @@ fn add_constraints_from_sig(&mut self,
     /// Adds constraints appropriate for a region appearing in a
     /// context with ambient variance `variance`
     fn add_constraints_from_region(&mut self,
-                                   _generics: &ty::Generics<'tcx>,
+                                   generics: &ty::Generics<'tcx>,
                                    region: ty::Region,
                                    variance: VarianceTermPtr<'a>) {
         match region {
             ty::ReEarlyBound(ref data) => {
-                let node_id = self.tcx().map.as_local_node_id(data.def_id).unwrap();
+                let def_id =
+                    generics.regions.get(data.space, data.index as usize).def_id;
+                let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
                 if self.is_to_be_inferred(node_id) {
                     let index = self.inferred_index(node_id);
                     self.add_constraint(index, variance);
index 6e4ba337b08ee4817eeb4af6a80680d9cf06f61a..b42d1d1b8d4ce5fb95d4cdc7d1d09207b150d6fc 100644 (file)
@@ -21,6 +21,8 @@
 use sys_common::unwind;
 use thread::Result;
 
+pub use panicking::{take_handler, set_handler, PanicInfo, Location};
+
 /// A marker trait which represents "panic safe" types in Rust.
 ///
 /// This trait is implemented by default for many types and behaves similarly in
                             across a recover boundary"]
 pub trait RecoverSafe {}
 
-/// A marker trait representing types which do not contain an `UnsafeCell` by
-/// value internally.
+/// A marker trait representing types where a shared reference is considered
+/// recover safe.
+///
+/// This trait is namely not implemented by `UnsafeCell`, the root of all
+/// interior mutability.
 ///
 /// This is a "helper marker trait" used to provide impl blocks for the
 /// `RecoverSafe` trait, for more information see that documentation.
@@ -108,7 +113,7 @@ pub trait RecoverSafe {}
 #[rustc_on_unimplemented = "the type {Self} contains interior mutability \
                             and a reference may not be safely transferrable \
                             across a recover boundary"]
-pub trait NoUnsafeCell {}
+pub trait RefRecoverSafe {}
 
 /// A simple wrapper around a type to assert that it is panic safe.
 ///
@@ -157,11 +162,11 @@ pub trait NoUnsafeCell {}
 // * Our custom AssertRecoverSafe wrapper is indeed recover safe
 impl RecoverSafe for .. {}
 impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
-impl<'a, T: NoUnsafeCell + ?Sized> RecoverSafe for &'a T {}
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *const T {}
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for *mut T {}
+impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
+impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
+impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
 impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Shared<T> {}
+impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
 impl<T: ?Sized> RecoverSafe for Mutex<T> {}
 impl<T: ?Sized> RecoverSafe for RwLock<T> {}
 impl<T> RecoverSafe for AssertRecoverSafe<T> {}
@@ -169,15 +174,16 @@ impl<T> RecoverSafe for AssertRecoverSafe<T> {}
 // not covered via the Shared impl above b/c the inner contents use
 // Cell/AtomicUsize, but the usage here is recover safe so we can lift the
 // impl up one level to Arc/Rc itself
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Rc<T> {}
-impl<T: NoUnsafeCell + ?Sized> RecoverSafe for Arc<T> {}
+impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
+impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}
 
-// Pretty simple implementations for the `NoUnsafeCell` marker trait, basically
-// just saying that this is a marker trait and `UnsafeCell` is the only thing
-// which doesn't implement it (which then transitively applies to everything
-// else.
-impl NoUnsafeCell for .. {}
-impl<T: ?Sized> !NoUnsafeCell for UnsafeCell<T> {}
+// Pretty simple implementations for the `RefRecoverSafe` marker trait,
+// basically just saying that this is a marker trait and `UnsafeCell` is the
+// only thing which doesn't implement it (which then transitively applies to
+// everything else.
+impl RefRecoverSafe for .. {}
+impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {}
+impl<T> RefRecoverSafe for AssertRecoverSafe<T> {}
 
 impl<T> AssertRecoverSafe<T> {
     /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
index 2b2af350c992cc874737ccfe547e65ef9f7ffc2b..3f9a1c30ef4936c6d4767fcc27c1d767aa91af0d 100644 (file)
 use cell::Cell;
 use cell::RefCell;
 use intrinsics;
+use sync::StaticRwLock;
 use sys::stdio::Stderr;
 use sys_common::backtrace;
 use sys_common::thread_info;
 use sys_common::util;
+use thread;
 
 thread_local! { pub static PANIC_COUNT: Cell<usize> = Cell::new(0) }
 
     }
 }
 
-fn log_panic(obj: &(Any+Send), file: &'static str, line: u32,
-             log_backtrace: bool) {
-    let msg = match obj.downcast_ref::<&'static str>() {
+#[derive(Copy, Clone)]
+enum Handler {
+    Default,
+    Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)),
+}
+
+static HANDLER_LOCK: StaticRwLock = StaticRwLock::new();
+static mut HANDLER: Handler = Handler::Default;
+
+/// Registers a custom panic handler, replacing any that was previously
+/// registered.
+///
+/// The panic handler is invoked when a thread panics, but before it begins
+/// unwinding the stack. The default handler prints a message to standard error
+/// and generates a backtrace if requested, but this behavior can be customized
+/// with the `set_handler` and `take_handler` functions.
+///
+/// The handler is provided with a `PanicInfo` struct which contains information
+/// about the origin of the panic, including the payload passed to `panic!` and
+/// the source code location from which the panic originated.
+///
+/// The panic handler is a global resource.
+///
+/// # Panics
+///
+/// Panics if called from a panicking thread.
+#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+pub fn set_handler<F>(handler: F) where F: Fn(&PanicInfo) + 'static + Sync + Send {
+    if thread::panicking() {
+        panic!("cannot modify the panic handler from a panicking thread");
+    }
+
+    let handler = Box::new(handler);
+    unsafe {
+        let lock = HANDLER_LOCK.write();
+        let old_handler = HANDLER;
+        HANDLER = Handler::Custom(Box::into_raw(handler));
+        drop(lock);
+
+        if let Handler::Custom(ptr) = old_handler {
+            Box::from_raw(ptr);
+        }
+    }
+}
+
+/// Unregisters the current panic handler, returning it.
+///
+/// If no custom handler is registered, the default handler will be returned.
+///
+/// # Panics
+///
+/// Panics if called from a panicking thread.
+#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+pub fn take_handler() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
+    if thread::panicking() {
+        panic!("cannot modify the panic handler from a panicking thread");
+    }
+
+    unsafe {
+        let lock = HANDLER_LOCK.write();
+        let handler = HANDLER;
+        HANDLER = Handler::Default;
+        drop(lock);
+
+        match handler {
+            Handler::Default => Box::new(default_handler),
+            Handler::Custom(ptr) => {Box::from_raw(ptr)} // FIXME #30530
+        }
+    }
+}
+
+/// A struct providing information about a panic.
+#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+pub struct PanicInfo<'a> {
+    payload: &'a (Any + Send),
+    location: Location<'a>,
+}
+
+impl<'a> PanicInfo<'a> {
+    /// Returns the payload associated with the panic.
+    ///
+    /// This will commonly, but not always, be a `&'static str` or `String`.
+    #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+    pub fn payload(&self) -> &(Any + Send) {
+        self.payload
+    }
+
+    /// Returns information about the location from which the panic originated,
+    /// if available.
+    ///
+    /// This method will currently always return `Some`, but this may change
+    /// in future versions.
+    #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+    pub fn location(&self) -> Option<&Location> {
+        Some(&self.location)
+    }
+}
+
+/// A struct containing information about the location of a panic.
+#[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+pub struct Location<'a> {
+    file: &'a str,
+    line: u32,
+}
+
+impl<'a> Location<'a> {
+    /// Returns the name of the source file from which the panic originated.
+    #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+    pub fn file(&self) -> &str {
+        self.file
+    }
+
+    /// Returns the line number from which the panic originated.
+    #[unstable(feature = "panic_handler", reason = "awaiting feedback", issue = "30449")]
+    pub fn line(&self) -> u32 {
+        self.line
+    }
+}
+
+fn default_handler(info: &PanicInfo) {
+    let panics = PANIC_COUNT.with(|s| s.get());
+
+    // If this is a double panic, make sure that we print a backtrace
+    // for this panic. Otherwise only print it if logging is enabled.
+    let log_backtrace = panics >= 2 || backtrace::log_enabled();
+
+    let file = info.location.file;
+    let line = info.location.line;
+
+    let msg = match info.payload.downcast_ref::<&'static str>() {
         Some(s) => *s,
-        None => match obj.downcast_ref::<String>() {
+        None => match info.payload.downcast_ref::<String>() {
             Some(s) => &s[..],
             None => "Box<Any>",
         }
@@ -81,10 +210,21 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
         unsafe { intrinsics::abort() }
     }
 
-    // If this is a double panic, make sure that we print a backtrace
-    // for this panic. Otherwise only print it if logging is enabled.
-    let log_backtrace = panics >= 2 || backtrace::log_enabled();
-    log_panic(obj, file, line, log_backtrace);
+    let info = PanicInfo {
+        payload: obj,
+        location: Location {
+            file: file,
+            line: line,
+        },
+    };
+
+    unsafe {
+        let _lock = HANDLER_LOCK.read();
+        match HANDLER {
+            Handler::Default => default_handler(&info),
+            Handler::Custom(ptr) => (*ptr)(&info),
+        }
+    }
 
     if panics >= 2 {
         // If a thread panics while it's already unwinding then we
index 81ff9b051721d60721840366929e3daac58140f2..34773e1657c2d220f2272648cb4edd9ecb223275 100644 (file)
@@ -3,6 +3,7 @@ S 2015-12-18 3391630
   linux-x86_64 97e2a5eb8904962df8596e95d6e5d9b574d73bf4
   macos-i386 ca52d2d3ba6497ed007705ee3401cf7efc136ca1
   macos-x86_64 3c44ffa18f89567c2b81f8d695e711c86d81ffc7
+  openbsd-x86_64 6c8aab2c8a169274942f9a15e460069a3ff64be9
   winnt-i386 f9056ebd3db9611d31c2dc6dc5f96c7208d5d227
   winnt-x86_64 a85a40e535d828016181d3aa40afe34c3e36ab8c
 
index b4791eba76e264fb3c071feaaf502b54dfa28a6d..4381bf22e2acee44f667826dd86fdd94cd92725b 100644 (file)
@@ -15,12 +15,12 @@ struct Foo<'a> {
 impl <'a> Foo<'a>{
     fn bar(self: &mut Foo) {
     //~^ mismatched types
-    //~| expected `Foo<'a>`
-    //~| found `Foo<'_>`
+    //~| expected `&mut Foo<'a>`
+    //~| found `&mut Foo<'_>`
     //~| lifetime mismatch
     //~| mismatched types
-    //~| expected `Foo<'a>`
-    //~| found `Foo<'_>`
+    //~| expected `&mut Foo<'a>`
+    //~| found `&mut Foo<'_>`
     //~| lifetime mismatch
     }
 }
index eabdb36a7efc6989eee874982a150201a5bc08ed..f11d482ea16db55a42a9ad695a80a1c01f5c192b 100644 (file)
@@ -16,10 +16,6 @@ impl Pair<
     isize
 > {
     fn say(self: &Pair<&str, isize>) {
-//~^ ERROR mismatched types
-//~| expected `Pair<&'static str, isize>`
-//~| found `Pair<&str, isize>`
-//~| lifetime mismatch
         println!("{}", self);
     }
 }
index b5c875cc4cbd200c57efa5d4bdcaacc319296b3e..ef91188c5d166bd1d8de2e11c18a3a82517627f2 100644 (file)
@@ -12,7 +12,7 @@
 
 impl S {
     fn f(self: *mut S) -> String { self.0 }
-    //~^ ERROR mismatched self type
+    //~^ ERROR mismatched method receiver
 }
 
 fn main() { S("".to_owned()).f(); }
index 5d2b5fa52db41b29910a9952974f2c2258f12358..e54a7623cb0c3c4a5b7c5787e94d0d1545425f7b 100644 (file)
@@ -15,7 +15,7 @@ struct Foo {
 }
 
 impl Foo {
-    fn foo(self: isize, x: isize) -> isize {  //~ ERROR mismatched self type
+    fn foo(self: isize, x: isize) -> isize {  //~ ERROR mismatched method receiver
         self.f + x
     }
 }
@@ -25,10 +25,10 @@ struct Bar<T> {
 }
 
 impl<T> Bar<T> {
-    fn foo(self: Bar<isize>, x: isize) -> isize { //~ ERROR mismatched self type
+    fn foo(self: Bar<isize>, x: isize) -> isize { //~ ERROR mismatched method receiver
         x
     }
-    fn bar(self: &Bar<usize>, x: isize) -> isize {   //~ ERROR mismatched self type
+    fn bar(self: &Bar<usize>, x: isize) -> isize {   //~ ERROR mismatched method receiver
         x
     }
 }
@@ -41,15 +41,16 @@ trait SomeTrait {
 
 impl<'a, T> SomeTrait for &'a Bar<T> {
     fn dummy1(self: &&'a Bar<T>) { }
-    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched self type
+    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched types
+    //~^ ERROR mismatched types
     fn dummy3(self: &&Bar<T>) {}
     //~^ ERROR mismatched types
-    //~| expected `&'a Bar<T>`
-    //~| found `&Bar<T>`
+    //~| expected `&&'a Bar<T>`
+    //~| found `&&Bar<T>`
     //~| lifetime mismatch
     //~| ERROR mismatched types
-    //~| expected `&'a Bar<T>`
-    //~| found `&Bar<T>`
+    //~| expected `&&'a Bar<T>`
+    //~| found `&&Bar<T>`
     //~| lifetime mismatch
 }
 
diff --git a/src/test/run-fail/panic-set-handler.rs b/src/test/run-fail/panic-set-handler.rs
new file mode 100644 (file)
index 0000000..bfeb407
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 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.
+
+// error-pattern:greetings from the panic handler
+
+#![feature(std_panic, panic_handler)]
+use std::panic;
+use std::io::{self, Write};
+
+fn main() {
+    panic::set_handler(|i| {
+        write!(io::stderr(), "greetings from the panic handler");
+    });
+    panic!("foobar");
+}
diff --git a/src/test/run-fail/panic-set-unset-handler.rs b/src/test/run-fail/panic-set-unset-handler.rs
new file mode 100644 (file)
index 0000000..6999aa7
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'foobar'
+
+#![feature(std_panic, panic_handler)]
+use std::panic;
+use std::io::{self, Write};
+
+fn main() {
+    panic::set_handler(|i| {
+        write!(io::stderr(), "greetings from the panic handler");
+    });
+    panic::take_handler();
+    panic!("foobar");
+}
diff --git a/src/test/run-fail/panic-take-handler-nop.rs b/src/test/run-fail/panic-take-handler-nop.rs
new file mode 100644 (file)
index 0000000..fec1db2
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'foobar'
+
+#![feature(std_panic, panic_handler)]
+use std::panic;
+
+fn main() {
+    panic::take_handler();
+    panic!("foobar");
+}
index c0c4b1e7f3f312e4516c38d1e2fea8368eedf4c1..49fec6f3619e4fa9c7ed48562281a8cfaf8d50e9 100644 (file)
@@ -47,11 +47,11 @@ pub fn foo(x: f32x4) -> f32x4 {
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 
     // vmaxq_s32
-    #[cfg(any(target_arch = "arm"))]
+    #[cfg(target_arch = "arm")]
     #[link_name = "llvm.arm.neon.vmaxs.v4i32"]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
     // vmaxq_s32
-    #[cfg(any(target_arch = "aarch64"))]
+    #[cfg(target_arch = "aarch64")]
     #[link_name = "llvm.aarch64.neon.maxs.v4i32"]
     fn integer(a: i32x4, b: i32x4) -> i32x4;
 
index 2da1a7587096433a3a95dab0900b1c9ef5fc9335..2c0cd5d6c8ad66c424b1f537d886ca114452d0be 100644 (file)
@@ -14,6 +14,8 @@
 extern crate mir_external_refs as ext;
 
 struct S(u8);
+#[derive(Debug, PartialEq, Eq)]
+struct Unit;
 
 impl S {
     fn hey() -> u8 { 42 }
@@ -175,6 +177,16 @@ fn t20() -> fn(u64, u32)->(u64, u32) {
     <u32 as T<_, _>>::staticmeth
 }
 
+#[rustc_mir]
+fn t21() -> Unit {
+    Unit
+}
+
+#[rustc_mir]
+fn t22() -> Option<u8> {
+    None
+}
+
 fn main(){
     unsafe {
         assert_eq!(t1()(), regular());
@@ -214,5 +226,7 @@ fn main(){
         assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64));
         assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32));
         assert_eq!(t20()(123u64, 38u32), <u32 as T<_, _>>::staticmeth(123, 38));
+        assert_eq!(t21(), Unit);
+        assert_eq!(t22(), None);
     }
 }
diff --git a/src/test/run-pass/panic-handler-chain.rs b/src/test/run-pass/panic-handler-chain.rs
new file mode 100644 (file)
index 0000000..1ed592d
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+#![feature(panic_handler, const_fn, std_panic)]
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::panic;
+use std::thread;
+
+static A: AtomicUsize = AtomicUsize::new(0);
+static B: AtomicUsize = AtomicUsize::new(0);
+
+fn main() {
+    panic::set_handler(|_| { A.fetch_add(1, Ordering::SeqCst); });
+    let handler = panic::take_handler();
+    panic::set_handler(move |info| {
+        B.fetch_add(1, Ordering::SeqCst);
+        handler(info);
+    });
+
+    let _ = thread::spawn(|| {
+        panic!();
+    }).join();
+
+    assert_eq!(1, A.load(Ordering::SeqCst));
+    assert_eq!(1, B.load(Ordering::SeqCst));
+}
diff --git a/src/test/run-pass/panic-handler-flail-wildly.rs b/src/test/run-pass/panic-handler-flail-wildly.rs
new file mode 100644 (file)
index 0000000..783a44b
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2015 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.
+#![feature(panic_handler, std_panic)]
+
+use std::panic;
+use std::thread;
+
+fn a() {
+    panic::set_handler(|_| println!("hello yes this is a"));
+    panic::take_handler();
+    panic::set_handler(|_| println!("hello yes this is a part 2"));
+    panic::take_handler();
+}
+
+fn b() {
+    panic::take_handler();
+    panic::take_handler();
+    panic::take_handler();
+    panic::take_handler();
+    panic::take_handler();
+    panic!();
+}
+
+fn c() {
+    panic::set_handler(|_| ());
+    panic::set_handler(|_| ());
+    panic::set_handler(|_| ());
+    panic::set_handler(|_| ());
+    panic::set_handler(|_| ());
+    panic::set_handler(|_| ());
+    panic!();
+}
+
+fn main() {
+    for _ in 0..10 {
+        let mut handles = vec![];
+        for _ in 0..10 {
+            handles.push(thread::spawn(a));
+        }
+        for _ in 0..10 {
+            handles.push(thread::spawn(b));
+        }
+        for _ in 0..10 {
+            handles.push(thread::spawn(c));
+        }
+        for handle in handles {
+            let _ = handle.join();
+        }
+    }
+}
diff --git a/src/test/run-pass/panic-handler-set-twice.rs b/src/test/run-pass/panic-handler-set-twice.rs
new file mode 100644 (file)
index 0000000..edf65e8
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2015 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.
+#![feature(panic_handler, const_fn, std_panic)]
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::panic;
+use std::thread;
+
+static A: AtomicUsize = AtomicUsize::new(0);
+
+fn main() {
+    panic::set_handler(|_| ());
+    panic::set_handler(|info| { A.fetch_add(1, Ordering::SeqCst); });
+
+    let _ = thread::spawn(|| {
+        panic!();
+    }).join();
+
+    assert_eq!(1, A.load(Ordering::SeqCst));
+}
index cd2457e8a52f765a0c9f138349640a6782ac28c1..9949b79278c11a2ecb871557a17ce481302d57d1 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(dead_code)]
 #![feature(recover)]
 
-use std::panic::RecoverSafe;
+use std::panic::{RecoverSafe, AssertRecoverSafe};
 use std::cell::RefCell;
 use std::sync::{Mutex, RwLock, Arc};
 use std::rc::Rc;
@@ -47,5 +47,9 @@ fn baz<T: RecoverSafe>() {
         assert::<Box<T>>();
         assert::<Vec<T>>();
         assert::<RefCell<T>>();
+        assert::<AssertRecoverSafe<T>>();
+        assert::<&AssertRecoverSafe<T>>();
+        assert::<Rc<AssertRecoverSafe<T>>>();
+        assert::<Arc<AssertRecoverSafe<T>>>();
     }
 }