]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #42734 - MaloJaffre:tests, r=Mark-Simulacrum
authorMark Simulacrum <mark.simulacrum@gmail.com>
Sun, 18 Jun 2017 16:34:14 +0000 (10:34 -0600)
committerGitHub <noreply@github.com>
Sun, 18 Jun 2017 16:34:14 +0000 (10:34 -0600)
Add tests for various issues

Fixes #11740.
Fixes #19601.
Fixes #22603
Fixes #22789.
Fixes #26614.

r? @Mark-Simulacrum.

28 files changed:
src/Cargo.lock
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/doc/grammar.md
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/library-features/collections.md [new file with mode: 0644]
src/libcollections/Cargo.toml [new file with mode: 0644]
src/libcollections/lib.rs [new file with mode: 0644]
src/libcore/str/pattern.rs
src/librustc/ich/impls_syntax.rs
src/librustc_const_eval/_match.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_metadata/decoder.rs
src/libstd/Cargo.toml
src/libsyntax/codemap.rs
src/libsyntax/json.rs
src/libsyntax_pos/Cargo.toml
src/libsyntax_pos/lib.rs
src/test/run-pass/issue-42679.rs [new file with mode: 0644]
src/test/ui/coercion-missing-tail-expected-type.rs
src/test/ui/coercion-missing-tail-expected-type.stderr
src/test/ui/issue-38875/auxiliary/issue_38875_b.rs [new file with mode: 0644]
src/test/ui/issue-38875/issue_38875.rs [new file with mode: 0644]
src/test/ui/issue-38875/issue_38875.stderr [new file with mode: 0644]
src/test/ui/issue-41652/issue_41652.stderr

index 9fae4b7e924c349898234141af2751d05ae49ff5..61f46bfbe5bbf2f44c1a89e7679527751ea70a7d 100644 (file)
@@ -251,6 +251,14 @@ dependencies = [
  "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "collections"
+version = "0.0.0"
+dependencies = [
+ "alloc 0.0.0",
+ "core 0.0.0",
+]
+
 [[package]]
 name = "compiler_builtins"
 version = "0.0.0"
@@ -1586,6 +1594,7 @@ dependencies = [
  "alloc_jemalloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
+ "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
  "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1682,6 +1691,7 @@ dependencies = [
 name = "syntax_pos"
 version = "0.0.0"
 dependencies = [
+ "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
 ]
 
index 4d58620ca648c6328a9effb697915e97c333244c..f92e6f50eb3e2047cbaf8b3ab79f96ac307c169b 100644 (file)
@@ -550,6 +550,7 @@ pub fn rust_src(build: &Build) {
         "src/liballoc_jemalloc",
         "src/liballoc_system",
         "src/libbacktrace",
+        "src/libcollections",
         "src/libcompiler_builtins",
         "src/libcore",
         "src/liblibc",
index 23a38f6a8969395faeaa9bf7b3a3e2fc3520025a..30f631ca2df646d301e3c7fe562937c2817b67ce 100644 (file)
@@ -254,7 +254,7 @@ pub fn std(build: &Build, stage: u32, target: &str) {
     // for which docs must be built.
     if !build.config.compiler_docs {
         cargo.arg("--no-deps");
-        for krate in &["alloc", "core", "std", "std_unicode"] {
+        for krate in &["alloc", "collections", "core", "std", "std_unicode"] {
             cargo.arg("-p").arg(krate);
             // Create all crate output directories first to make sure rustdoc uses
             // relative links.
index 56cbb4cecf2a5b08f2a3a006ed9f144ce41a3020..dc9dac73627880b864916fc24816c3a23fd185b5 100644 (file)
@@ -242,11 +242,18 @@ pub fn parse(args: &[String]) -> Flags {
         let cwd = t!(env::current_dir());
         let paths = matches.free[1..].iter().map(|p| cwd.join(p)).collect::<Vec<_>>();
 
+        let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| {
+            if fs::metadata("config.toml").is_ok() {
+                Some(PathBuf::from("config.toml"))
+            } else {
+                None
+            }
+        });
 
         // All subcommands can have an optional "Available paths" section
         if matches.opt_present("verbose") {
             let flags = Flags::parse(&["build".to_string()]);
-            let mut config = Config::default();
+            let mut config = Config::parse(&flags.build, cfg_file.clone());
             config.build = flags.build.clone();
             let mut build = Build::new(flags, config);
             metadata::build(&mut build);
@@ -307,14 +314,6 @@ pub fn parse(args: &[String]) -> Flags {
         };
 
 
-        let cfg_file = matches.opt_str("config").map(PathBuf::from).or_else(|| {
-            if fs::metadata("config.toml").is_ok() {
-                Some(PathBuf::from("config.toml"))
-            } else {
-                None
-            }
-        });
-
         let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap());
 
         if matches.opt_present("incremental") {
index 12daa24e857fcbfa62a4f292c1aab804936a57d9..78432b6a9659370cac1ae373770e795f0b8469b7 100644 (file)
@@ -154,19 +154,19 @@ token : simple_token | ident | literal | symbol | whitespace token ;
 
 <p id="keyword-table-marker"></p>
 
-|          |          |          |          |         |
-|----------|----------|----------|----------|---------|
-| abstract | alignof  | as       | become   | box     |
-| break    | const    | continue | crate    | do      |
-| else     | enum     | extern   | false    | final   |
-| fn       | for      | if       | impl     | in      |
-| let      | loop     | macro    | match    | mod     |
-| move     | mut      | offsetof | override | priv    |
-| proc     | pub      | pure     | ref      | return  |
-| Self     | self     | sizeof   | static   | struct  |
-| super    | trait    | true     | type     | typeof  |
-| unsafe   | unsized  | use      | virtual  | where   |
-| while    | yield    |          |          |         |
+|          |          |          |          |          |
+|----------|----------|----------|----------|----------|
+| _        | abstract | alignof  | as       | become   |
+| box      | break    | const    | continue | crate    |
+| do       | else     | enum     | extern   | false    |
+| final    | fn       | for      | if       | impl     |
+| in       | let      | loop     | macro    | match    |
+| mod      | move     | mut      | offsetof | override |
+| priv     | proc     | pub      | pure     | ref      |
+| return   | Self     | self     | sizeof   | static   |
+| struct   | super    | trait    | true     | type     |
+| typeof   | unsafe   | unsized  | use      | virtual  |
+| where    | while    | yield    |          |          |
 
 
 Each of these keywords has special meaning in its grammar, and all of them are
index d8f742735a8d5ac4d5507535501801c849a81e2d..d7c368292115de3443d240922000229301324386 100644 (file)
     - [char_escape_debug](library-features/char-escape-debug.md)
     - [coerce_unsized](library-features/coerce-unsized.md)
     - [collection_placement](library-features/collection-placement.md)
+    - [collections](library-features/collections.md)
     - [collections_range](library-features/collections-range.md)
     - [command_envs](library-features/command-envs.md)
     - [compiler_builtins_lib](library-features/compiler-builtins-lib.md)
diff --git a/src/doc/unstable-book/src/library-features/collections.md b/src/doc/unstable-book/src/library-features/collections.md
new file mode 100644 (file)
index 0000000..5c93783
--- /dev/null
@@ -0,0 +1,5 @@
+# `collections`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/libcollections/Cargo.toml b/src/libcollections/Cargo.toml
new file mode 100644 (file)
index 0000000..800e361
--- /dev/null
@@ -0,0 +1,12 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "collections"
+version = "0.0.0"
+
+[lib]
+name = "collections"
+path = "lib.rs"
+
+[dependencies]
+alloc = { path = "../liballoc" }
+core = { path = "../libcore" }
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
new file mode 100644 (file)
index 0000000..de5d6df
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2017 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.
+
+#![crate_name = "collections"]
+#![crate_type = "rlib"]
+#![allow(unused_attributes)]
+#![unstable(feature = "collections",
+            reason = "this library is unlikely to be stabilized in its current \
+                      form or name",
+            issue = "27783")]
+#![rustc_deprecated(since = "1.20.0",
+                    reason = "collections moved to `alloc`")]
+#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/",
+       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
+       test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
+#![no_std]
+#![needs_allocator]
+#![deny(warnings)]
+
+#![feature(alloc)]
+#![feature(collections_range)]
+#![feature(macro_reexport)]
+#![feature(needs_allocator)]
+#![feature(staged_api)]
+
+//! Collection types
+//!
+//! See [`std::collections`](../std/collections/index.html) for a detailed
+//! discussion of collections in Rust.
+
+#[macro_reexport(vec, format)]
+extern crate alloc;
+
+pub use alloc::Bound;
+
+pub use alloc::binary_heap;
+pub use alloc::borrow;
+pub use alloc::fmt;
+pub use alloc::linked_list;
+pub use alloc::range;
+pub use alloc::slice;
+pub use alloc::str;
+pub use alloc::string;
+pub use alloc::vec;
+pub use alloc::vec_deque;
+
+pub use alloc::btree_map;
+pub use alloc::btree_set;
+
+#[doc(no_inline)]
+pub use alloc::binary_heap::BinaryHeap;
+#[doc(no_inline)]
+pub use alloc::btree_map::BTreeMap;
+#[doc(no_inline)]
+pub use alloc::btree_set::BTreeSet;
+#[doc(no_inline)]
+pub use alloc::linked_list::LinkedList;
+#[doc(no_inline)]
+pub use alloc::vec_deque::VecDeque;
+#[doc(no_inline)]
+pub use alloc::string::String;
+#[doc(no_inline)]
+pub use alloc::vec::Vec;
index 4918e37eb35f08a266122920a2def0a07bb2ea81..5a007285e48735657bf07308064636051e87b3ea 100644 (file)
@@ -618,7 +618,10 @@ fn new(haystack: &'a str, needle: &'b str) -> StrSearcher<'a, 'b> {
 }
 
 unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b> {
-    fn haystack(&self) -> &'a str { self.haystack }
+    #[inline]
+    fn haystack(&self) -> &'a str {
+        self.haystack
+    }
 
     #[inline]
     fn next(&mut self) -> SearchStep {
index 995f797df2fbead6a1e2dfcac87eadcc267aa97e..b9cc3b5fb937fe1927ecba066a1e2d5f4940b3dd 100644 (file)
@@ -336,6 +336,8 @@ fn hash_stable<W: StableHasherResult>(&self,
             crate_of_origin,
             // Do not hash the source as it is not encoded
             src: _,
+            src_hash,
+            external_src: _,
             start_pos,
             end_pos: _,
             ref lines,
@@ -350,6 +352,8 @@ fn hash_stable<W: StableHasherResult>(&self,
             index: CRATE_DEF_INDEX,
         }.hash_stable(hcx, hasher);
 
+        src_hash.hash_stable(hcx, hasher);
+
         // We only hash the relative position within this filemap
         let lines = lines.borrow();
         lines.len().hash_stable(hcx, hasher);
index c1dc5f5f7a2b8d10e0f5a99565480dfab83f9993..98d90188312df752de79898db0671cc40db568e6 100644 (file)
@@ -774,21 +774,26 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
         },
         ty::TyRef(_, ref ty_and_mut) => vec![ty_and_mut.ty],
         ty::TyAdt(adt, substs) => {
-            adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
-                let is_visible = adt.is_enum()
-                    || field.vis.is_accessible_from(cx.module, cx.tcx);
-                if is_visible {
-                    field.ty(cx.tcx, substs)
-                } else {
-                    // Treat all non-visible fields as nil. They
-                    // can't appear in any other pattern from
-                    // this match (because they are private),
-                    // so their type does not matter - but
-                    // we don't want to know they are
-                    // uninhabited.
-                    cx.tcx.mk_nil()
-                }
-            }).collect()
+            if adt.is_box() {
+                // Use T as the sub pattern type of Box<T>.
+                vec![substs[0].as_type().unwrap()]
+            } else {
+                adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
+                    let is_visible = adt.is_enum()
+                        || field.vis.is_accessible_from(cx.module, cx.tcx);
+                    if is_visible {
+                        field.ty(cx.tcx, substs)
+                    } else {
+                        // Treat all non-visible fields as nil. They
+                        // can't appear in any other pattern from
+                        // this match (because they are private),
+                        // so their type does not matter - but
+                        // we don't want to know they are
+                        // uninhabited.
+                        cx.tcx.mk_nil()
+                    }
+                }).collect()
+            }
         }
         _ => vec![],
     }
index 634d3041bf4a7a1832ca385df599769baa5a237d..5e291ea3c152b7e00caa0fcb571f9cd09ef9ba17 100644 (file)
@@ -78,6 +78,17 @@ fn finish(mut hasher: StableHasher<Self>) -> Self {
     }
 }
 
+impl StableHasherResult for u128 {
+    fn finish(mut hasher: StableHasher<Self>) -> Self {
+        let hash_bytes: &[u8] = hasher.finalize();
+        assert!(hash_bytes.len() >= mem::size_of::<u128>());
+
+        unsafe {
+            ::std::ptr::read_unaligned(hash_bytes.as_ptr() as *const u128)
+        }
+    }
+}
+
 impl StableHasherResult for u64 {
     fn finish(mut hasher: StableHasher<Self>) -> Self {
         hasher.state.finalize();
index aa0fae508fde10a38ad792dc960973c25b2eb8d1..2d25d12d3a96e437ffec77d1a8b655498207ab18 100644 (file)
@@ -17,6 +17,7 @@
 use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
 use styled_buffer::StyledBuffer;
 
+use std::borrow::Cow;
 use std::io::prelude::*;
 use std::io;
 use std::rc::Rc;
@@ -131,7 +132,7 @@ pub fn new(dst: Box<Write + Send>, code_map: Option<Rc<CodeMapper>>) -> EmitterW
         }
     }
 
-    fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
+    fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
         fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                                   file: Rc<FileMap>,
                                   line_index: usize,
@@ -175,6 +176,7 @@ fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
                 if span_label.span == DUMMY_SP {
                     continue;
                 }
+
                 let lo = cm.lookup_char_pos(span_label.span.lo);
                 let mut hi = cm.lookup_char_pos(span_label.span.hi);
 
@@ -890,10 +892,10 @@ fn emit_message_default(&mut self,
         let mut annotated_files = self.preprocess_annotations(msp);
 
         // Make sure our primary file comes first
-        let primary_lo = if let (Some(ref cm), Some(ref primary_span)) =
+        let (primary_lo, cm) = if let (Some(cm), Some(ref primary_span)) =
             (self.cm.as_ref(), msp.primary_span().as_ref()) {
             if primary_span != &&DUMMY_SP {
-                cm.lookup_char_pos(primary_span.lo)
+                (cm.lookup_char_pos(primary_span.lo), cm)
             } else {
                 emit_to_destination(&buffer.render(), level, &mut self.dst)?;
                 return Ok(());
@@ -911,7 +913,7 @@ fn emit_message_default(&mut self,
         // Print out the annotate source lines that correspond with the error
         for annotated_file in annotated_files {
             // we can't annotate anything if the source is unavailable.
-            if annotated_file.file.src.is_none() {
+            if !cm.ensure_filemap_source_present(annotated_file.file.clone()) {
                 continue;
             }
 
@@ -1012,7 +1014,7 @@ fn emit_message_default(&mut self,
                     } else if line_idx_delta == 2 {
                         let unannotated_line = annotated_file.file
                             .get_line(annotated_file.lines[line_idx].line_index)
-                            .unwrap_or("");
+                            .unwrap_or_else(|| Cow::from(""));
 
                         let last_buffer_line_num = buffer.num_lines();
 
index 8d5e9e776ed23ec05d8e7e6f77b27dcc7b9a6961..975b720276e82b8d58c80becad14bc8e396bd147 100644 (file)
@@ -37,6 +37,7 @@
 
 use emitter::{Emitter, EmitterWriter};
 
+use std::borrow::Cow;
 use std::cell::{RefCell, Cell};
 use std::{error, fmt};
 use std::rc::Rc;
@@ -49,7 +50,7 @@
 pub mod styled_buffer;
 mod lock;
 
-use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION};
+use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION};
 
 #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum RenderSpan {
@@ -103,6 +104,7 @@ pub trait CodeMapper {
     fn span_to_filename(&self, sp: Span) -> FileName;
     fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span>;
     fn call_span_if_macro(&self, sp: Span) -> Span;
+    fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool;
 }
 
 impl CodeSuggestion {
@@ -121,7 +123,7 @@ pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<String> {
         use syntax_pos::{CharPos, Loc, Pos};
 
         fn push_trailing(buf: &mut String,
-                         line_opt: Option<&str>,
+                         line_opt: Option<&Cow<str>>,
                          lo: &Loc,
                          hi_opt: Option<&Loc>) {
             let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize()));
@@ -183,13 +185,13 @@ fn push_trailing(buf: &mut String,
             let cur_lo = cm.lookup_char_pos(sp.lo);
             for (buf, substitute) in bufs.iter_mut().zip(substitutes) {
                 if prev_hi.line == cur_lo.line {
-                    push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo));
+                    push_trailing(buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo));
                 } else {
-                    push_trailing(buf, prev_line, &prev_hi, None);
+                    push_trailing(buf, prev_line.as_ref(), &prev_hi, None);
                     // push lines between the previous and current span (if any)
                     for idx in prev_hi.line..(cur_lo.line - 1) {
                         if let Some(line) = fm.get_line(idx) {
-                            buf.push_str(line);
+                            buf.push_str(line.as_ref());
                             buf.push('\n');
                         }
                     }
@@ -205,7 +207,7 @@ fn push_trailing(buf: &mut String,
         for buf in &mut bufs {
             // if the replacement already ends with a newline, don't print the next line
             if !buf.ends_with('\n') {
-                push_trailing(buf, prev_line, &prev_hi, None);
+                push_trailing(buf, prev_line.as_ref(), &prev_hi, None);
             }
             // remove trailing newline
             buf.pop();
index 92d9a800888e61d4221110183e7e8bdb331257d6..728ab30bb17dc6a63e1fc649f5a07271a9f60952 100644 (file)
@@ -765,7 +765,7 @@ pub fn item_body(&self,
         assert!(!self.is_proc_macro(id));
         let ast = self.entry(id).ast.unwrap();
         let def_id = self.local_def_id(id);
-        let body = ast.decode(self).body.decode(self);
+        let body = ast.decode((self, tcx)).body.decode((self, tcx));
         tcx.hir.intern_inlined_body(def_id, body)
     }
 
@@ -1149,6 +1149,7 @@ pub fn imported_filemaps(&'a self,
             // containing the information we need.
             let syntax_pos::FileMap { name,
                                       name_was_remapped,
+                                      src_hash,
                                       start_pos,
                                       end_pos,
                                       lines,
@@ -1174,6 +1175,7 @@ pub fn imported_filemaps(&'a self,
             let local_version = local_codemap.new_imported_filemap(name,
                                                                    name_was_remapped,
                                                                    self.cnum.as_u32(),
+                                                                   src_hash,
                                                                    source_length,
                                                                    lines,
                                                                    multibyte_chars);
index f93af4c192016201ed30b2d88dd503a52e9cdfb7..b516cbd08ca0202d35db93cf320751197e779fa1 100644 (file)
@@ -15,6 +15,7 @@ alloc_jemalloc = { path = "../liballoc_jemalloc", optional = true }
 alloc_system = { path = "../liballoc_system" }
 panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
+collections = { path = "../libcollections" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 rand = { path = "../librand" }
index 830a457df748eeefaaf19b28f9623317d3798511..b3d9cf9da36c7669320cb43b956040b5fab6c36d 100644 (file)
@@ -158,29 +158,13 @@ fn next_start_pos(&self) -> usize {
 
     /// Creates a new filemap without setting its line information. If you don't
     /// intend to set the line information yourself, you should use new_filemap_and_lines.
-    pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
+    pub fn new_filemap(&self, filename: FileName, src: String) -> Rc<FileMap> {
         let start_pos = self.next_start_pos();
         let mut files = self.files.borrow_mut();
 
-        // Remove utf-8 BOM if any.
-        if src.starts_with("\u{feff}") {
-            src.drain(..3);
-        }
-
-        let end_pos = start_pos + src.len();
-
         let (filename, was_remapped) = self.path_mapping.map_prefix(filename);
-
-        let filemap = Rc::new(FileMap {
-            name: filename,
-            name_was_remapped: was_remapped,
-            crate_of_origin: 0,
-            src: Some(Rc::new(src)),
-            start_pos: Pos::from_usize(start_pos),
-            end_pos: Pos::from_usize(end_pos),
-            lines: RefCell::new(Vec::new()),
-            multibyte_chars: RefCell::new(Vec::new()),
-        });
+        let filemap =
+            Rc::new(FileMap::new(filename, was_remapped, src, Pos::from_usize(start_pos)));
 
         files.push(filemap.clone());
 
@@ -210,6 +194,7 @@ pub fn new_imported_filemap(&self,
                                 filename: FileName,
                                 name_was_remapped: bool,
                                 crate_of_origin: u32,
+                                src_hash: u128,
                                 source_len: usize,
                                 mut file_local_lines: Vec<BytePos>,
                                 mut file_local_multibyte_chars: Vec<MultiByteChar>)
@@ -233,6 +218,8 @@ pub fn new_imported_filemap(&self,
             name_was_remapped: name_was_remapped,
             crate_of_origin: crate_of_origin,
             src: None,
+            src_hash: src_hash,
+            external_src: RefCell::new(ExternalSource::AbsentOk),
             start_pos: start_pos,
             end_pos: end_pos,
             lines: RefCell::new(file_local_lines),
@@ -428,30 +415,31 @@ pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
                       local_end.fm.start_pos)
             }));
         } else {
-            match local_begin.fm.src {
-                Some(ref src) => {
-                    let start_index = local_begin.pos.to_usize();
-                    let end_index = local_end.pos.to_usize();
-                    let source_len = (local_begin.fm.end_pos -
-                                      local_begin.fm.start_pos).to_usize();
-
-                    if start_index > end_index || end_index > source_len {
-                        return Err(SpanSnippetError::MalformedForCodemap(
-                            MalformedCodemapPositions {
-                                name: local_begin.fm.name.clone(),
-                                source_len: source_len,
-                                begin_pos: local_begin.pos,
-                                end_pos: local_end.pos,
-                            }));
-                    }
-
-                    return Ok((&src[start_index..end_index]).to_string())
-                }
-                None => {
-                    return Err(SpanSnippetError::SourceNotAvailable {
-                        filename: local_begin.fm.name.clone()
-                    });
-                }
+            self.ensure_filemap_source_present(local_begin.fm.clone());
+
+            let start_index = local_begin.pos.to_usize();
+            let end_index = local_end.pos.to_usize();
+            let source_len = (local_begin.fm.end_pos -
+                              local_begin.fm.start_pos).to_usize();
+
+            if start_index > end_index || end_index > source_len {
+                return Err(SpanSnippetError::MalformedForCodemap(
+                    MalformedCodemapPositions {
+                        name: local_begin.fm.name.clone(),
+                        source_len: source_len,
+                        begin_pos: local_begin.pos,
+                        end_pos: local_end.pos,
+                    }));
+            }
+
+            if let Some(ref src) = local_begin.fm.src {
+                return Ok((&src[start_index..end_index]).to_string());
+            } else if let Some(src) = local_begin.fm.external_src.borrow().get_source() {
+                return Ok((&src[start_index..end_index]).to_string());
+            } else {
+                return Err(SpanSnippetError::SourceNotAvailable {
+                    filename: local_begin.fm.name.clone()
+                });
             }
         }
     }
@@ -572,6 +560,10 @@ fn call_span_if_macro(&self, sp: Span) -> Span {
         }
         sp
     }
+    fn ensure_filemap_source_present(&self, file_map: Rc<FileMap>) -> bool {
+        let src = self.file_loader.read_file(Path::new(&file_map.name)).ok();
+        return file_map.add_external_src(src)
+    }
 }
 
 #[derive(Clone)]
@@ -617,6 +609,7 @@ pub fn map_prefix(&self, path: String) -> (String, bool) {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use std::borrow::Cow;
     use std::rc::Rc;
 
     #[test]
@@ -626,12 +619,12 @@ fn t1 () {
                                 "first line.\nsecond line".to_string());
         fm.next_line(BytePos(0));
         // Test we can get lines with partial line info.
-        assert_eq!(fm.get_line(0), Some("first line."));
+        assert_eq!(fm.get_line(0), Some(Cow::from("first line.")));
         // TESTING BROKEN BEHAVIOR: line break declared before actual line break.
         fm.next_line(BytePos(10));
-        assert_eq!(fm.get_line(1), Some("."));
+        assert_eq!(fm.get_line(1), Some(Cow::from(".")));
         fm.next_line(BytePos(12));
-        assert_eq!(fm.get_line(2), Some("second line"));
+        assert_eq!(fm.get_line(2), Some(Cow::from("second line")));
     }
 
     #[test]
index f37dcfdde8985f7594b3381e8e7cf4e57a2a889f..e60edafe4ee441aba879abdf67918881685e6c8b 100644 (file)
@@ -314,7 +314,7 @@ fn line_from_filemap(fm: &syntax_pos::FileMap,
                          h_end: usize)
                          -> DiagnosticSpanLine {
         DiagnosticSpanLine {
-            text: fm.get_line(index).unwrap_or("").to_owned(),
+            text: fm.get_line(index).map_or(String::new(), |l| l.into_owned()),
             highlight_start: h_start,
             highlight_end: h_end,
         }
index 760aaa8a9578419b809032fc86a1e3f6396cfb4c..dd8129bab510fc28d7381b4c20a3fe614efb4c5b 100644 (file)
@@ -10,3 +10,4 @@ crate-type = ["dylib"]
 
 [dependencies]
 serialize = { path = "../libserialize" }
+rustc_data_structures = { path = "../librustc_data_structures" }
index 25f74aeecf4046eed1ce357fb435ed246a002203..94656b3aea79e0f5f24e77b94619f2e5fbe47ed6 100644 (file)
@@ -24,6 +24,7 @@
 
 #![feature(const_fn)]
 #![feature(custom_attribute)]
+#![feature(i128_type)]
 #![feature(optin_builtin_traits)]
 #![allow(unused_attributes)]
 #![feature(specialization)]
 #![cfg_attr(stage0, feature(rustc_private))]
 #![cfg_attr(stage0, feature(staged_api))]
 
+use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::ops::{Add, Sub};
 use std::rc::Rc;
 use std::cmp;
-
 use std::fmt;
+use std::hash::Hasher;
+
+use rustc_data_structures::stable_hasher::StableHasher;
+
+extern crate rustc_data_structures;
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -369,6 +375,35 @@ pub struct MultiByteChar {
     pub bytes: usize,
 }
 
+/// The state of the lazy external source loading mechanism of a FileMap.
+#[derive(PartialEq, Eq, Clone)]
+pub enum ExternalSource {
+    /// The external source has been loaded already.
+    Present(String),
+    /// No attempt has been made to load the external source.
+    AbsentOk,
+    /// A failed attempt has been made to load the external source.
+    AbsentErr,
+    /// No external source has to be loaded, since the FileMap represents a local crate.
+    Unneeded,
+}
+
+impl ExternalSource {
+    pub fn is_absent(&self) -> bool {
+        match *self {
+            ExternalSource::Present(_) => false,
+            _ => true,
+        }
+    }
+
+    pub fn get_source(&self) -> Option<&str> {
+        match *self {
+            ExternalSource::Present(ref src) => Some(src),
+            _ => None,
+        }
+    }
+}
+
 /// A single source in the CodeMap.
 #[derive(Clone)]
 pub struct FileMap {
@@ -382,6 +417,11 @@ pub struct FileMap {
     pub crate_of_origin: u32,
     /// The complete source code
     pub src: Option<Rc<String>>,
+    /// The source code's hash
+    pub src_hash: u128,
+    /// The external source code (used for external crates, which will have a `None`
+    /// value as `self.src`.
+    pub external_src: RefCell<ExternalSource>,
     /// The start position of this source in the CodeMap
     pub start_pos: BytePos,
     /// The end position of this source in the CodeMap
@@ -394,9 +434,10 @@ pub struct FileMap {
 
 impl Encodable for FileMap {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_struct("FileMap", 6, |s| {
+        s.emit_struct("FileMap", 7, |s| {
             s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
             s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?;
+            s.emit_struct_field("src_hash", 6, |s| self.src_hash.encode(s))?;
             s.emit_struct_field("start_pos", 2, |s| self.start_pos.encode(s))?;
             s.emit_struct_field("end_pos", 3, |s| self.end_pos.encode(s))?;
             s.emit_struct_field("lines", 4, |s| {
@@ -459,7 +500,10 @@ fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
             let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
             let name_was_remapped: bool =
                 d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?;
-            let start_pos: BytePos = d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?;
+            let src_hash: u128 =
+                d.read_struct_field("src_hash", 6, |d| Decodable::decode(d))?;
+            let start_pos: BytePos =
+                d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?;
             let end_pos: BytePos = d.read_struct_field("end_pos", 3, |d| Decodable::decode(d))?;
             let lines: Vec<BytePos> = d.read_struct_field("lines", 4, |d| {
                 let num_lines: u32 = Decodable::decode(d)?;
@@ -501,6 +545,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
                 start_pos: start_pos,
                 end_pos: end_pos,
                 src: None,
+                src_hash: src_hash,
+                external_src: RefCell::new(ExternalSource::AbsentOk),
                 lines: RefCell::new(lines),
                 multibyte_chars: RefCell::new(multibyte_chars)
             })
@@ -515,6 +561,32 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl FileMap {
+    pub fn new(name: FileName,
+               name_was_remapped: bool,
+               mut src: String,
+               start_pos: BytePos) -> FileMap {
+        remove_bom(&mut src);
+
+        let mut hasher: StableHasher<u128> = StableHasher::new();
+        hasher.write(src.as_bytes());
+        let src_hash = hasher.finish();
+
+        let end_pos = start_pos.to_usize() + src.len();
+
+        FileMap {
+            name: name,
+            name_was_remapped: name_was_remapped,
+            crate_of_origin: 0,
+            src: Some(Rc::new(src)),
+            src_hash: src_hash,
+            external_src: RefCell::new(ExternalSource::Unneeded),
+            start_pos: start_pos,
+            end_pos: Pos::from_usize(end_pos),
+            lines: RefCell::new(Vec::new()),
+            multibyte_chars: RefCell::new(Vec::new()),
+        }
+    }
+
     /// EFFECT: register a start-of-line offset in the
     /// table of line-beginnings.
     /// UNCHECKED INVARIANT: these offsets must be added in the right
@@ -532,26 +604,60 @@ pub fn next_line(&self, pos: BytePos) {
         lines.push(pos);
     }
 
-    /// get a line from the list of pre-computed line-beginnings.
-    /// line-number here is 0-based.
-    pub fn get_line(&self, line_number: usize) -> Option<&str> {
-        match self.src {
-            Some(ref src) => {
-                let lines = self.lines.borrow();
-                lines.get(line_number).map(|&line| {
-                    let begin: BytePos = line - self.start_pos;
-                    let begin = begin.to_usize();
-                    // We can't use `lines.get(line_number+1)` because we might
-                    // be parsing when we call this function and thus the current
-                    // line is the last one we have line info for.
-                    let slice = &src[begin..];
-                    match slice.find('\n') {
-                        Some(e) => &slice[..e],
-                        None => slice
-                    }
-                })
+    /// Add externally loaded source.
+    /// If the hash of the input doesn't match or no input is supplied via None,
+    /// it is interpreted as an error and the corresponding enum variant is set.
+    /// The return value signifies whether some kind of source is present.
+    pub fn add_external_src(&self, src: Option<String>) -> bool {
+        if *self.external_src.borrow() == ExternalSource::AbsentOk {
+            let mut external_src = self.external_src.borrow_mut();
+            if let Some(src) = src {
+                let mut hasher: StableHasher<u128> = StableHasher::new();
+                hasher.write(src.as_bytes());
+
+                if hasher.finish() == self.src_hash {
+                    *external_src = ExternalSource::Present(src);
+                    return true;
+                }
+            } else {
+                *external_src = ExternalSource::AbsentErr;
             }
-            None => None
+
+            false
+        } else {
+            self.src.is_some() || self.external_src.borrow().get_source().is_some()
+        }
+    }
+
+    /// Get a line from the list of pre-computed line-beginnings.
+    /// The line number here is 0-based.
+    pub fn get_line(&self, line_number: usize) -> Option<Cow<str>> {
+        fn get_until_newline(src: &str, begin: usize) -> &str {
+            // We can't use `lines.get(line_number+1)` because we might
+            // be parsing when we call this function and thus the current
+            // line is the last one we have line info for.
+            let slice = &src[begin..];
+            match slice.find('\n') {
+                Some(e) => &slice[..e],
+                None => slice
+            }
+        }
+
+        let lines = self.lines.borrow();
+        let line = if let Some(line) = lines.get(line_number) {
+            line
+        } else {
+            return None;
+        };
+        let begin: BytePos = *line - self.start_pos;
+        let begin = begin.to_usize();
+
+        if let Some(ref src) = self.src {
+            Some(Cow::from(get_until_newline(src, begin)))
+        } else if let Some(src) = self.external_src.borrow().get_source() {
+            Some(Cow::Owned(String::from(get_until_newline(src, begin))))
+        } else {
+            None
         }
     }
 
@@ -614,6 +720,13 @@ pub fn line_bounds(&self, line_index: usize) -> (BytePos, BytePos) {
     }
 }
 
+/// Remove utf-8 BOM if any.
+fn remove_bom(src: &mut String) {
+    if src.starts_with("\u{feff}") {
+        src.drain(..3);
+    }
+}
+
 // _____________________________________________________________________________
 // Pos, BytePos, CharPos
 //
diff --git a/src/test/run-pass/issue-42679.rs b/src/test/run-pass/issue-42679.rs
new file mode 100644 (file)
index 0000000..3128352
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(box_syntax)]
+#![feature(box_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum Test {
+    Foo(usize),
+    Bar(isize),
+}
+
+fn main() {
+    let a = box Test::Foo(10);
+    let b = box Test::Bar(-20);
+    match (a, b) {
+        (_, box Test::Foo(_)) => unreachable!(),
+        (box Test::Foo(x), b) => {
+            assert_eq!(x, 10);
+            assert_eq!(b, box Test::Bar(-20));
+        },
+        _ => unreachable!(),
+    }
+}
index 489ad817ea8b1e0a957fefb23029be0133393a5c..15ce79a054f26c2a33a91275309daac3f3437952 100644 (file)
@@ -14,6 +14,10 @@ fn plus_one(x: i32) -> i32 {
     x + 1;
 }
 
+fn foo() -> Result<u8, u64> {
+    Ok(1);
+}
+
 fn main() {
     let x = plus_one(5);
     println!("X = {}", x);
index 28a99e58eca89d954f8aedb62625a15eb96ea9ac..e96bc425e0b45fad9e2732758f5160d7cabec188 100644 (file)
@@ -15,5 +15,22 @@ help: consider removing this semicolon:
 14 |     x + 1;
    |          ^
 
+error[E0308]: mismatched types
+  --> $DIR/coercion-missing-tail-expected-type.rs:17:29
+   |
+17 |   fn foo() -> Result<u8, u64> {
+   |  _____________________________^
+18 | |     Ok(1);
+19 | | }
+   | |_^ expected enum `std::result::Result`, found ()
+   |
+   = note: expected type `std::result::Result<u8, u64>`
+              found type `()`
+help: consider removing this semicolon:
+  --> $DIR/coercion-missing-tail-expected-type.rs:18:10
+   |
+18 |     Ok(1);
+   |          ^
+
 error: aborting due to previous error(s)
 
diff --git a/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs b/src/test/ui/issue-38875/auxiliary/issue_38875_b.rs
new file mode 100644 (file)
index 0000000..dd58735
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2017 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.
+
+pub const FOO: usize = *&0;
diff --git a/src/test/ui/issue-38875/issue_38875.rs b/src/test/ui/issue-38875/issue_38875.rs
new file mode 100644 (file)
index 0000000..42e3c05
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 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.
+
+// aux-build:issue_38875_b.rs
+
+extern crate issue_38875_b;
+
+fn main() {
+    let test_x = [0; issue_38875_b::FOO];
+}
diff --git a/src/test/ui/issue-38875/issue_38875.stderr b/src/test/ui/issue-38875/issue_38875.stderr
new file mode 100644 (file)
index 0000000..ceed83d
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0080]: constant evaluation error
+  --> $DIR/auxiliary/issue_38875_b.rs:11:24
+   |
+11 | pub const FOO: usize = *&0;
+   |                        ^^^ unimplemented constant expression: deref operation
+   |
+note: for repeat count here
+  --> $DIR/issue_38875.rs:16:22
+   |
+16 |     let test_x = [0; issue_38875_b::FOO];
+   |                      ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error(s)
+
index 4625e9269c9950de08e585d8cdfc5ebb9d329774..b7b1ddb7b88d8ca54c1f219ffd271a77e56661b1 100644 (file)
@@ -6,6 +6,11 @@ error[E0599]: no method named `f` found for type `{integer}` in the current scop
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
 note: candidate #1 is defined in the trait `issue_41652_b::Tr`
+  --> $DIR/auxiliary/issue_41652_b.rs:14:5
+   |
+14 | /     fn f()
+15 | |         where Self: Sized;
+   | |__________________________^
    = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead
 
 error: aborting due to previous error(s)