]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #40261 - infinity0:patch-1, r=alexcrichton
authorAlex Crichton <alex@alexcrichton.com>
Fri, 10 Mar 2017 22:51:23 +0000 (16:51 -0600)
committerAlex Crichton <alex@alexcrichton.com>
Sat, 11 Mar 2017 00:18:27 +0000 (16:18 -0800)
Support armhf abi on 64-bit ARM cpus

They report their `uname -m` as armv8l rather than aarch64.

Patch originally by Matthias Klose <doko@debian.org>

23 files changed:
.travis.yml
src/bootstrap/check.rs
src/ci/docker/dist-fuchsia/Dockerfile [new file with mode: 0644]
src/ci/docker/dist-fuchsia/build-toolchain.sh [new file with mode: 0755]
src/ci/docker/dist-fuchsia/shared.sh [new file with mode: 0644]
src/librustc_driver/driver.rs
src/librustc_errors/lib.rs
src/librustc_lint/unused.rs
src/librustc_plugin/registry.rs
src/librustc_save_analysis/data.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/external_data.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/libstd/sys_common/gnu/libbacktrace.rs
src/test/compile-fail/lint-unused-unsafe.rs [deleted file]
src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs [deleted file]
src/test/run-pass-fulldeps/mir-pass.rs [deleted file]
src/test/ui/span/lint-unused-unsafe.rs [new file with mode: 0644]
src/test/ui/span/lint-unused-unsafe.stderr [new file with mode: 0644]
src/test/ui/span/suggestion-non-ascii.rs [new file with mode: 0644]
src/test/ui/span/suggestion-non-ascii.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs

index fa6c9cf0748647c5d2a48593f1c2f6e127ebda8d..7fcf128ff0b031a468a6770a85aa42d2ce73e425 100644 (file)
@@ -20,6 +20,7 @@ matrix:
     - env: IMAGE=dist-armv7-aarch64-linux DEPLOY=1
     - env: IMAGE=dist-freebsd DEPLOY=1
     - env: IMAGE=dist-i586-gnu-i686-musl DEPLOY=1
+    - env: IMAGE=dist-fuchsia DEPLOY=1
     - env: IMAGE=dist-mips-linux DEPLOY=1
     - env: IMAGE=dist-mips64-linux DEPLOY=1
     - env: IMAGE=dist-powerpc-linux DEPLOY=1
index dfe96b51799c0f5813442a69fbc020513370e5b6..68b3623a53f255243ade5a90f8b328b390405e58 100644 (file)
@@ -550,7 +550,7 @@ fn find_tests(dir: &Path,
         let filename = e.file_name().into_string().unwrap();
         if (target.contains("windows") && filename.ends_with(".exe")) ||
            (!target.contains("windows") && !filename.contains(".")) ||
-           (target.contains("emscripten") && filename.contains(".js")){
+           (target.contains("emscripten") && filename.ends_with(".js")) {
             dst.push(e.path());
         }
     }
diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile
new file mode 100644 (file)
index 0000000..25a47c5
--- /dev/null
@@ -0,0 +1,47 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  ninja-build \
+  file \
+  curl \
+  ca-certificates \
+  python2.7-dev \
+  git \
+  sudo \
+  bzip2 \
+  xz-utils \
+  swig \
+  libedit-dev \
+  libncurses5-dev
+
+RUN curl -L https://cmake.org/files/v3.8/cmake-3.8.0-rc1-Linux-x86_64.tar.gz | \
+      tar xzf - -C /usr/local --strip-components=1
+
+WORKDIR /tmp
+COPY shared.sh build-toolchain.sh /tmp/
+RUN /tmp/build-toolchain.sh
+
+RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
+    dpkg -i dumb-init_*.deb && \
+    rm dumb-init_*.deb
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+
+RUN curl -o /usr/local/bin/sccache \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-02-25-sccache-x86_64-unknown-linux-musl && \
+      chmod +x /usr/local/bin/sccache
+
+ENV \
+    AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \
+    CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \
+    CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \
+    AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \
+    CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \
+    CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++
+
+ENV TARGETS=x86_64-unknown-fuchsia
+ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
+
+ENV RUST_CONFIGURE_ARGS --target=$TARGETS
+ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
diff --git a/src/ci/docker/dist-fuchsia/build-toolchain.sh b/src/ci/docker/dist-fuchsia/build-toolchain.sh
new file mode 100755 (executable)
index 0000000..cad73ee
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/bash
+# 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.
+
+set -ex
+source shared.sh
+
+# Download sources
+SRCS=(
+  "https://fuchsia.googlesource.com/magenta magenta ac69119"
+  "https://fuchsia.googlesource.com/third_party/llvm llvm 5463083"
+  "https://fuchsia.googlesource.com/third_party/clang llvm/tools/clang 4ff7b4b"
+  "https://fuchsia.googlesource.com/third_party/lld llvm/tools/lld fd465a3"
+  "https://fuchsia.googlesource.com/third_party/lldb llvm/tools/lldb 6bb11f8"
+  "https://fuchsia.googlesource.com/third_party/compiler-rt llvm/runtimes/compiler-rt 52d4ecc"
+  "https://fuchsia.googlesource.com/third_party/libcxx llvm/runtimes/libcxx e891cc8"
+  "https://fuchsia.googlesource.com/third_party/libcxxabi llvm/runtimes/libcxxabi f0f0257"
+  "https://fuchsia.googlesource.com/third_party/libunwind llvm/runtimes/libunwind 50bddc1"
+)
+
+fetch() {
+  mkdir -p $2
+  pushd $2 > /dev/null
+  curl -sL $1/+archive/$3.tar.gz | tar xzf -
+  popd > /dev/null
+}
+
+for i in "${SRCS[@]}"; do
+  fetch $i
+done
+
+# Build toolchain
+cd llvm
+mkdir build
+cd build
+hide_output cmake -GNinja \
+  -DFUCHSIA_SYSROOT=${PWD}/../../magenta/third_party/ulib/musl \
+  -DLLVM_ENABLE_LTO=OFF \
+  -DCLANG_BOOTSTRAP_PASSTHROUGH=LLVM_ENABLE_LTO \
+  -C ../tools/clang/cmake/caches/Fuchsia.cmake \
+  ..
+hide_output ninja stage2-distribution
+hide_output ninja stage2-install-distribution
+cd ../..
+
+# Build sysroot
+rm -rf llvm/runtimes/compiler-rt
+./magenta/scripts/download-toolchain
+
+build_sysroot() {
+  local arch="$1"
+
+  case "${arch}" in
+    x86_64) tgt="magenta-pc-x86-64" ;;
+    aarch64) tgt="magenta-qemu-arm64" ;;
+  esac
+
+  hide_output make -C magenta -j$(getconf _NPROCESSORS_ONLN) $tgt
+  dst=/usr/local/${arch}-unknown-fuchsia
+  mkdir -p $dst
+  cp -r magenta/build-${tgt}/sysroot/include $dst/
+  cp -r magenta/build-${tgt}/sysroot/lib $dst/
+
+  cd llvm
+  mkdir build-runtimes-${arch}
+  cd build-runtimes-${arch}
+  hide_output cmake -GNinja \
+    -DCMAKE_C_COMPILER=clang \
+    -DCMAKE_CXX_COMPILER=clang++ \
+    -DCMAKE_AR=/usr/local/bin/llvm-ar \
+    -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib \
+    -DCMAKE_INSTALL_PREFIX= \
+    -DLLVM_MAIN_SRC_DIR=${PWD}/.. \
+    -DLLVM_BINARY_DIR=${PWD}/../build \
+    -DLLVM_ENABLE_WERROR=OFF \
+    -DCMAKE_BUILD_TYPE=Release \
+    -DLLVM_INCLUDE_TESTS=ON \
+    -DCMAKE_SYSTEM_NAME=Fuchsia \
+    -DCMAKE_C_COMPILER_TARGET=${arch}-fuchsia \
+    -DCMAKE_CXX_COMPILER_TARGET=${arch}-fuchsia \
+    -DUNIX=1 \
+    -DLIBCXX_HAS_MUSL_LIBC=ON \
+    -DLIBCXXABI_USE_LLVM_UNWINDER=ON \
+    -DCMAKE_SYSROOT=${dst} \
+    -DCMAKE_C_COMPILER_FORCED=TRUE \
+    -DCMAKE_CXX_COMPILER_FORCED=TRUE \
+    -DLLVM_ENABLE_LIBCXX=ON \
+    -DCMAKE_EXE_LINKER_FLAGS="-nodefaultlibs -lc" \
+    -DCMAKE_SHARED_LINKER_FLAGS="$(clang --target=${arch}-fuchsia -print-libgcc-file-name)" \
+    ../runtimes
+  hide_output env DESTDIR="${dst}" ninja install
+  cd ../..
+}
+
+build_sysroot "x86_64"
+build_sysroot "aarch64"
+
+rm -rf magenta llvm
+
+for arch in x86_64 aarch64; do
+  for tool in clang clang++; do
+    cat >/usr/local/bin/${arch}-unknown-fuchsia-${tool} <<EOF
+#!/bin/sh
+${tool} --target=${arch}-unknown-fuchsia --sysroot=/usr/local/${arch}-unknown-fuchsia "\$@"
+EOF
+    chmod +x /usr/local/bin/${arch}-unknown-fuchsia-${tool}
+  done
+  ln -s /usr/local/bin/llvm-ar /usr/local/bin/${arch}-unknown-fuchsia-ar
+done
diff --git a/src/ci/docker/dist-fuchsia/shared.sh b/src/ci/docker/dist-fuchsia/shared.sh
new file mode 100644 (file)
index 0000000..e26c6eb
--- /dev/null
@@ -0,0 +1,25 @@
+# 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.
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  "$@" &> /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
index 9619ba8472404bb70e0a1fffca1e620841dbe528..dda118fb4408e6abededcb3f19e3aabe63c091bb 100644 (file)
@@ -604,7 +604,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
 
     let whitelisted_legacy_custom_derives = registry.take_whitelisted_custom_derives();
     let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
-                   llvm_passes, attributes, mir_passes, .. } = registry;
+                   llvm_passes, attributes, .. } = registry;
 
     sess.track_errors(|| {
         let mut ls = sess.lint_store.borrow_mut();
@@ -620,7 +620,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         }
 
         *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
-        sess.mir_passes.borrow_mut().extend(mir_passes);
         *sess.plugin_attributes.borrow_mut() = attributes.clone();
     })?;
 
index d7bd5ed23c2b0af883ce9687447d15d233f63755..4c889dad8ca5050b0803be1a360b84bfda96fbb0 100644 (file)
@@ -90,7 +90,8 @@ fn push_trailing(buf: &mut String,
                          hi_opt: Option<&Loc>) {
             let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize()));
             if let Some(line) = line_opt {
-                if line.len() > lo {
+                if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) {
+                    let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi));
                     buf.push_str(match hi_opt {
                         Some(hi) => &line[lo..hi],
                         None => &line[lo..],
index 28ce9126019ebdebb86da7436e62674b52e30474..f9b7c68587678dea4a5f6a0edecbcfe8c5500583 100644 (file)
@@ -189,11 +189,38 @@ fn get_lints(&self) -> LintArray {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedUnsafe {
     fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        /// Return the NodeId for an enclosing scope that is also `unsafe`
+        fn is_enclosed(cx: &LateContext, id: ast::NodeId) -> Option<(String, ast::NodeId)> {
+            let parent_id = cx.tcx.hir.get_parent_node(id);
+            if parent_id != id {
+                if cx.tcx.used_unsafe.borrow().contains(&parent_id) {
+                    Some(("block".to_string(), parent_id))
+                } else if let Some(hir::map::NodeItem(&hir::Item {
+                    node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
+                    ..
+                })) = cx.tcx.hir.find(parent_id) {
+                    Some(("fn".to_string(), parent_id))
+                } else {
+                    is_enclosed(cx, parent_id)
+                }
+            } else {
+                None
+            }
+        }
         if let hir::ExprBlock(ref blk) = e.node {
             // Don't warn about generated blocks, that'll just pollute the output.
             if blk.rules == hir::UnsafeBlock(hir::UserProvided) &&
                !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
-                cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
+
+                let mut db = cx.struct_span_lint(UNUSED_UNSAFE, blk.span,
+                                                 "unnecessary `unsafe` block");
+
+                db.span_label(blk.span, &"unnecessary `unsafe` block");
+                if let Some((kind, id)) = is_enclosed(cx, blk.id) {
+                    db.span_note(cx.tcx.hir.span(id),
+                                 &format!("because it's nested under this `unsafe` {}", kind));
+                }
+                db.emit();
             }
         }
     }
index 3700d0295e9639dd50a7a08a85a3263a0d3c92f8..cdde56f5f634be75a2d0917a5a1885bf59606e2d 100644 (file)
@@ -13,8 +13,6 @@
 use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
 use rustc::session::Session;
 
-use rustc::mir::transform::MirMapPass;
-
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT};
 use syntax::ext::base::MacroExpanderFn;
 use syntax::symbol::Symbol;
@@ -53,9 +51,6 @@ pub struct Registry<'a> {
     #[doc(hidden)]
     pub late_lint_passes: Vec<LateLintPassObject>,
 
-    #[doc(hidden)]
-    pub mir_passes: Vec<Box<for<'pcx> MirMapPass<'pcx>>>,
-
     #[doc(hidden)]
     pub lint_groups: HashMap<&'static str, Vec<LintId>>,
 
@@ -81,7 +76,6 @@ pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
             lint_groups: HashMap::new(),
             llvm_passes: vec![],
             attributes: vec![],
-            mir_passes: Vec::new(),
             whitelisted_custom_derives: Vec::new(),
         }
     }
@@ -157,11 +151,6 @@ pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>
         self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
     }
 
-    /// Register a MIR pass
-    pub fn register_mir_pass(&mut self, pass: Box<for<'pcx> MirMapPass<'pcx>>) {
-        self.mir_passes.push(pass);
-    }
-
     /// Register an LLVM pass.
     ///
     /// Registration with LLVM itself is handled through static C++ objects with
index 0a6281bf8c54ccaf4357f956fc97844fe136a41d..6caf81380e40dad51f8c33c1d90a51c7dd5f7065 100644 (file)
@@ -15,7 +15,7 @@
 
 use rustc::hir;
 use rustc::hir::def_id::{CrateNum, DefId};
-use syntax::ast::{self, NodeId};
+use syntax::ast::{self, Attribute, NodeId};
 use syntax_pos::Span;
 
 pub struct CrateData {
@@ -136,6 +136,7 @@ pub struct EnumData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for extern crates.
@@ -171,6 +172,7 @@ pub struct FunctionData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data about a function call.
@@ -256,6 +258,7 @@ pub struct MethodData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for modules.
@@ -271,6 +274,7 @@ pub struct ModData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for a reference to a module.
@@ -295,6 +299,7 @@ pub struct StructData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -309,6 +314,7 @@ pub struct StructVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -323,6 +329,7 @@ pub struct TraitData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -337,6 +344,7 @@ pub struct TupleVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for a typedef.
@@ -351,6 +359,7 @@ pub struct TypeDefData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for a reference to a type or trait.
@@ -396,6 +405,7 @@ pub struct VariableData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
index 3c275e0996dac0c3877c693f5bad6a7763cf0274..cbb1a3e5023638d0c60217e60d9c182dd93ada8e 100644 (file)
@@ -373,6 +373,7 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
                         visibility: Visibility::Inherited,
                         docs: String::new(),
                         sig: None,
+                        attributes: vec![],
                     }.lower(self.tcx));
                 }
             }
@@ -448,6 +449,7 @@ fn process_method(&mut self,
                     visibility: vis,
                     docs: docs_for_attrs(attrs),
                     sig: method_data.sig,
+                    attributes: attrs.to_vec(),
                 }.lower(self.tcx));
             }
 
@@ -519,6 +521,7 @@ fn process_generic_params(&mut self,
                     parent: None,
                     docs: String::new(),
                     sig: None,
+                    attributes: vec![],
                 }.lower(self.tcx));
             }
         }
@@ -592,6 +595,7 @@ fn process_assoc_const(&mut self,
                 visibility: vis,
                 docs: docs_for_attrs(attrs),
                 sig: None,
+                attributes: attrs.to_vec(),
             }.lower(self.tcx));
         }
 
@@ -636,6 +640,7 @@ fn process_struct(&mut self,
                 visibility: From::from(&item.vis),
                 docs: docs_for_attrs(&item.attrs),
                 sig: self.save_ctxt.sig_base(item),
+                attributes: item.attrs.clone(),
             }.lower(self.tcx));
         }
 
@@ -701,6 +706,7 @@ fn process_enum(&mut self,
                             parent: Some(make_def_id(item.id, &self.tcx.hir)),
                             docs: docs_for_attrs(&variant.node.attrs),
                             sig: sig,
+                            attributes: variant.node.attrs.clone(),
                         }.lower(self.tcx));
                     }
                 }
@@ -727,6 +733,7 @@ fn process_enum(&mut self,
                             parent: Some(make_def_id(item.id, &self.tcx.hir)),
                             docs: docs_for_attrs(&variant.node.attrs),
                             sig: sig,
+                            attributes: variant.node.attrs.clone(),
                         }.lower(self.tcx));
                     }
                 }
@@ -798,6 +805,7 @@ fn process_trait(&mut self,
                 visibility: From::from(&item.vis),
                 docs: docs_for_attrs(&item.attrs),
                 sig: self.save_ctxt.sig_base(item),
+                attributes: item.attrs.clone(),
             }.lower(self.tcx));
         }
 
@@ -1064,6 +1072,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
                     visibility: Visibility::Inherited,
                     docs: String::new(),
                     sig: None,
+                    attributes: vec![],
                 }.lower(self.tcx));
             }
         }
@@ -1305,6 +1314,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         parent: None,
                         docs: docs_for_attrs(&item.attrs),
                         sig: Some(self.save_ctxt.sig_base(item)),
+                        attributes: item.attrs.clone(),
                     }.lower(self.tcx));
                 }
 
@@ -1527,6 +1537,7 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                             visibility: Visibility::Inherited,
                             docs: String::new(),
                             sig: None,
+                            attributes: vec![],
                         }.lower(self.tcx));
                     }
                 }
index fccb56e88b3de801a55eb08a7e77f6f175b072e2..41658dc5b1b48b043b9faf344768803a1db2b52b 100644 (file)
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex};
 use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
-use syntax::ast::NodeId;
+use syntax::ast::{self, NodeId};
 use syntax::codemap::CodeMap;
+use syntax::print::pprust;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 use data::{self, Visibility, SigElement};
@@ -64,6 +66,39 @@ pub fn from_span(span: Span, cm: &CodeMap) -> SpanData {
     }
 }
 
+/// Represent an arbitrary attribute on a code element
+#[derive(Clone, Debug, RustcEncodable)]
+pub struct Attribute {
+    value: String,
+    span: SpanData,
+}
+
+impl Lower for Vec<ast::Attribute> {
+    type Target = Vec<Attribute>;
+
+    fn lower(self, tcx: TyCtxt) -> Vec<Attribute> {
+        let doc = Symbol::intern("doc");
+        self.into_iter()
+        // Only retain real attributes. Doc comments are lowered separately.
+        .filter(|attr| attr.name() != doc)
+        .map(|mut attr| {
+            // Remove the surrounding '#[..]' or '#![..]' of the pretty printed
+            // attribute. First normalize all inner attribute (#![..]) to outer
+            // ones (#[..]), then remove the two leading and the one trailing character.
+            attr.style = ast::AttrStyle::Outer;
+            let value = pprust::attribute_to_string(&attr);
+            // This str slicing works correctly, because the leading and trailing characters
+            // are in the ASCII range and thus exactly one byte each.
+            let value = value[2..value.len()-1].to_string();
+
+            Attribute {
+                value: value,
+                span: SpanData::from_span(attr.span, tcx.sess.codemap()),
+            }
+        }).collect()
+    }
+}
+
 #[derive(Debug, RustcEncodable)]
 pub struct CratePreludeData {
     pub crate_name: String,
@@ -98,6 +133,7 @@ pub struct EnumData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::EnumData {
@@ -115,6 +151,7 @@ fn lower(self, tcx: TyCtxt) -> EnumData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -179,6 +216,7 @@ pub struct FunctionData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::FunctionData {
@@ -197,6 +235,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -346,6 +385,7 @@ pub struct MethodData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::MethodData {
@@ -364,6 +404,7 @@ fn lower(self, tcx: TyCtxt) -> MethodData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -381,6 +422,7 @@ pub struct ModData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::ModData {
@@ -398,6 +440,7 @@ fn lower(self, tcx: TyCtxt) -> ModData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -437,6 +480,7 @@ pub struct StructData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::StructData {
@@ -455,6 +499,7 @@ fn lower(self, tcx: TyCtxt) -> StructData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -471,6 +516,7 @@ pub struct StructVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::StructVariantData {
@@ -488,6 +534,7 @@ fn lower(self, tcx: TyCtxt) -> StructVariantData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -504,6 +551,7 @@ pub struct TraitData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::TraitData {
@@ -521,6 +569,7 @@ fn lower(self, tcx: TyCtxt) -> TraitData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -537,6 +586,7 @@ pub struct TupleVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::TupleVariantData {
@@ -554,6 +604,7 @@ fn lower(self, tcx: TyCtxt) -> TupleVariantData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -570,6 +621,7 @@ pub struct TypeDefData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::TypeDefData {
@@ -586,6 +638,7 @@ fn lower(self, tcx: TyCtxt) -> TypeDefData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.map(|s| s.lower(tcx)),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -675,6 +728,7 @@ pub struct VariableData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::VariableData {
@@ -694,6 +748,7 @@ fn lower(self, tcx: TyCtxt) -> VariableData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.map(|s| s.lower(tcx)),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
index 09752994290c9c3490ec0ec4f1a4397c98740992..1b72489f83c67da2d611710b757001966994c3f5 100644 (file)
@@ -87,6 +87,7 @@ fn mod_data(&mut self, data: ModData) {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         };
         if def.span.file_name != def.value {
             // If the module is an out-of-line defintion, then we'll make the
@@ -232,6 +233,7 @@ struct Def {
     decl_id: Option<Id>,
     docs: String,
     sig: Option<JsonSignature>,
+    attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -274,6 +276,7 @@ fn from(data: EnumData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -291,6 +294,7 @@ fn from(data: TupleVariantData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -307,6 +311,7 @@ fn from(data: StructVariantData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -323,6 +328,7 @@ fn from(data: StructData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -339,6 +345,7 @@ fn from(data: TraitData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -355,6 +362,7 @@ fn from(data: FunctionData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -371,6 +379,7 @@ fn from(data: MethodData) -> Def {
             decl_id: data.decl_id.map(|id| From::from(id)),
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -387,6 +396,7 @@ fn from(data: MacroData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: None,
+            attributes: vec![],
         }
     }
 }
@@ -403,6 +413,7 @@ fn from(data: TypeDefData) -> Def {
             decl_id: None,
             docs: String::new(),
             sig: data.sig.map(|s| From::from(s)),
+            attributes: data.attributes,
         }
     }
 }
@@ -424,6 +435,7 @@ fn from(data: VariableData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: None,
+            attributes: data.attributes,
         }
     }
 }
index b1e435dcc751c40b1bdff58ed027eb1f212f1a84..2153b30b62cd52d9e4bcb201ca1e6ab758d2567f 100644 (file)
@@ -136,6 +136,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     parent: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: self.sig_base(item),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Static(ref typ, mt, ref expr) => {
@@ -164,6 +165,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: Some(self.sig_base(item)),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Const(ref typ, ref expr) => {
@@ -183,6 +185,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: Some(self.sig_base(item)),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Mod(ref m) => {
@@ -205,6 +208,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: self.sig_base(item),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Enum(ref def, _) => {
@@ -228,6 +232,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: self.sig_base(item),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => {
@@ -315,6 +320,7 @@ pub fn get_field_data(&self,
                 visibility: From::from(&field.vis),
                 docs: docs_for_attrs(&field.attrs),
                 sig: Some(sig),
+                attributes: field.attrs.clone(),
             })
         } else {
             None
@@ -327,7 +333,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
                            name: ast::Name, span: Span) -> Option<FunctionData> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
-        let (qualname, parent_scope, decl_id, vis, docs) =
+        let (qualname, parent_scope, decl_id, vis, docs, attributes) =
           match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) {
             Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) {
                 Some(Node::NodeItem(item)) => {
@@ -349,7 +355,8 @@ pub fn get_method_data(&self, id: ast::NodeId,
 
                             (result, trait_id, decl_id,
                              From::from(&item.vis),
-                             docs_for_attrs(&item.attrs))
+                             docs_for_attrs(&item.attrs),
+                             item.attrs.to_vec())
                         }
                         _ => {
                             span_bug!(span,
@@ -374,7 +381,8 @@ pub fn get_method_data(&self, id: ast::NodeId,
                             (format!("::{}", self.tcx.item_path_str(def_id)),
                              Some(def_id), None,
                              From::from(&item.vis),
-                             docs_for_attrs(&item.attrs))
+                             docs_for_attrs(&item.attrs),
+                             item.attrs.to_vec())
                         }
                         r => {
                             span_bug!(span,
@@ -423,6 +431,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
             parent: parent_scope,
             docs: docs,
             sig: sig,
+            attributes: attributes,
         })
     }
 
index 1ea5cca44c7e40154f383bce344187a8b703a94e..14c0e8699bc060b2cbbf9255e4fbff86701ce1b7 100644 (file)
@@ -105,9 +105,6 @@ pub fn resolve_symname<F>(frame: Frame,
               msg: *const libc::c_char,
               errnum: libc::c_int);
 enum backtrace_state {}
-#[link(name = "backtrace", kind = "static")]
-#[cfg(all(not(test), not(cargobuild)))]
-extern {}
 
 extern {
     fn backtrace_create_state(filename: *const libc::c_char,
diff --git a/src/test/compile-fail/lint-unused-unsafe.rs b/src/test/compile-fail/lint-unused-unsafe.rs
deleted file mode 100644 (file)
index 5c8e73e..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Exercise the unused_unsafe attribute in some positive and negative cases
-
-#![allow(dead_code)]
-#![deny(unused_unsafe)]
-
-
-mod foo {
-    extern {
-        pub fn bar();
-    }
-}
-
-fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() }
-unsafe fn unsf() {}
-
-fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
-fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
-unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
-fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
-unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
-fn bad6() {
-    unsafe {                             // don't put the warning here
-        unsafe {                         //~ ERROR: unnecessary `unsafe` block
-            unsf()
-        }
-    }
-}
-unsafe fn bad7() {
-    unsafe {                             //~ ERROR: unnecessary `unsafe` block
-        unsafe {                         //~ ERROR: unnecessary `unsafe` block
-            unsf()
-        }
-    }
-}
-
-unsafe fn good0() { unsf() }
-fn good1() { unsafe { unsf() } }
-fn good2() {
-    /* bug uncovered when implementing warning about unused unsafe blocks. Be
-       sure that when purity is inherited that the source of the unsafe-ness
-       is tracked correctly */
-    unsafe {
-        unsafe fn what() -> Vec<String> { panic!() }
-
-        callback(|| {
-            what();
-        });
-    }
-}
-
-unsafe fn good3() { foo::bar() }
-fn good4() { unsafe { foo::bar() } }
-
-#[allow(unused_unsafe)] fn allowed() { unsafe {} }
-
-fn main() {}
diff --git a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs
deleted file mode 100644 (file)
index 3bc4a40..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-// force-host
-
-#![feature(plugin_registrar, rustc_private)]
-#![feature(box_syntax)]
-
-#[macro_use] extern crate rustc;
-extern crate rustc_plugin;
-extern crate rustc_const_math;
-extern crate syntax;
-
-use rustc::mir::transform::{self, MirPass, MirSource};
-use rustc::mir::{Mir, Literal, Location};
-use rustc::mir::visit::MutVisitor;
-use rustc::ty::TyCtxt;
-use rustc::middle::const_val::ConstVal;
-use rustc_const_math::ConstInt;
-use rustc_plugin::Registry;
-
-struct Pass;
-
-impl transform::Pass for Pass {}
-
-impl<'tcx> MirPass<'tcx> for Pass {
-    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>,
-                    _: MirSource, mir: &mut Mir<'tcx>) {
-        Visitor.visit_mir(mir)
-    }
-}
-
-struct Visitor;
-
-impl<'tcx> MutVisitor<'tcx> for Visitor {
-    fn visit_literal(&mut self, literal: &mut Literal<'tcx>, _: Location) {
-        if let Literal::Value { ref mut value } = *literal {
-            if let ConstVal::Integral(ConstInt::I32(ref mut i @ 11)) = *value {
-                *i = 42;
-            }
-        }
-    }
-}
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_mir_pass(box Pass);
-}
diff --git a/src/test/run-pass-fulldeps/mir-pass.rs b/src/test/run-pass-fulldeps/mir-pass.rs
deleted file mode 100644 (file)
index 8ac4bf9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.
-
-// aux-build:dummy_mir_pass.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(dummy_mir_pass)]
-
-fn math() -> i32 {
-    11
-}
-
-pub fn main() {
-    assert_eq!(math(), 42);
-}
diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs
new file mode 100644 (file)
index 0000000..5c8e73e
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Exercise the unused_unsafe attribute in some positive and negative cases
+
+#![allow(dead_code)]
+#![deny(unused_unsafe)]
+
+
+mod foo {
+    extern {
+        pub fn bar();
+    }
+}
+
+fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() }
+unsafe fn unsf() {}
+
+fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
+fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
+fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+fn bad6() {
+    unsafe {                             // don't put the warning here
+        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+            unsf()
+        }
+    }
+}
+unsafe fn bad7() {
+    unsafe {                             //~ ERROR: unnecessary `unsafe` block
+        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+            unsf()
+        }
+    }
+}
+
+unsafe fn good0() { unsf() }
+fn good1() { unsafe { unsf() } }
+fn good2() {
+    /* bug uncovered when implementing warning about unused unsafe blocks. Be
+       sure that when purity is inherited that the source of the unsafe-ness
+       is tracked correctly */
+    unsafe {
+        unsafe fn what() -> Vec<String> { panic!() }
+
+        callback(|| {
+            what();
+        });
+    }
+}
+
+unsafe fn good3() { foo::bar() }
+fn good4() { unsafe { foo::bar() } }
+
+#[allow(unused_unsafe)] fn allowed() { unsafe {} }
+
+fn main() {}
diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr
new file mode 100644 (file)
index 0000000..0df3fa4
--- /dev/null
@@ -0,0 +1,116 @@
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:26:13
+   |
+26 | fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
+   |             ^^^^^^^^^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-unsafe.rs:14:9
+   |
+14 | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:27:13
+   |
+27 | fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
+   |             ^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:28:20
+   |
+28 | unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
+   |                    ^^^^^^^^^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:28:1
+   |
+28 | unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:29:13
+   |
+29 | fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:30:20
+   |
+30 | unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+   |                    ^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:30:1
+   |
+30 | unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:33:9
+   |
+33 |           unsafe {                         //~ ERROR: unnecessary `unsafe` block
+   |  _________^ starting here...
+34 | |             unsf()
+35 | |         }
+   | |_________^ ...ending here: unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:32:5
+   |
+32 |       unsafe {                             // don't put the warning here
+   |  _____^ starting here...
+33 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+34 | |             unsf()
+35 | |         }
+36 | |     }
+   | |_____^ ...ending here
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:39:5
+   |
+39 |       unsafe {                             //~ ERROR: unnecessary `unsafe` block
+   |  _____^ starting here...
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+41 | |             unsf()
+42 | |         }
+43 | |     }
+   | |_____^ ...ending here: unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:38:1
+   |
+38 |   unsafe fn bad7() {
+   |  _^ starting here...
+39 | |     unsafe {                             //~ ERROR: unnecessary `unsafe` block
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+41 | |             unsf()
+42 | |         }
+43 | |     }
+44 | | }
+   | |_^ ...ending here
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:40:9
+   |
+40 |           unsafe {                         //~ ERROR: unnecessary `unsafe` block
+   |  _________^ starting here...
+41 | |             unsf()
+42 | |         }
+   | |_________^ ...ending here: unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:38:1
+   |
+38 |   unsafe fn bad7() {
+   |  _^ starting here...
+39 | |     unsafe {                             //~ ERROR: unnecessary `unsafe` block
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+41 | |             unsf()
+42 | |         }
+43 | |     }
+44 | | }
+   | |_^ ...ending here
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/span/suggestion-non-ascii.rs b/src/test/ui/span/suggestion-non-ascii.rs
new file mode 100644 (file)
index 0000000..67dbe1d
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+
+fn main() {
+    let tup = (1,);
+    println!("☃{}", tup[0]);
+}
+
diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr
new file mode 100644 (file)
index 0000000..385c211
--- /dev/null
@@ -0,0 +1,11 @@
+error: cannot index a value of type `({integer},)`
+  --> $DIR/suggestion-non-ascii.rs:14:21
+   |
+14 |     println!("☃{}", tup[0]);
+   |                     ^^^^^^
+   |
+help: to access tuple elements, use tuple indexing syntax as shown
+   |     println!("☃{}", tup.0);
+
+error: aborting due to previous error
+
index ceefcc9e0ec46b80c0c07ea491f967ee96c15104..c2ec42195fcb7e16a76601780e46a10334e1ac60 100644 (file)
@@ -45,6 +45,7 @@
 
 static TARGETS: &'static [&'static str] = &[
     "aarch64-apple-ios",
+    "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
     "aarch64-unknown-linux-gnu",
     "arm-linux-androideabi",
@@ -86,6 +87,7 @@
     "x86_64-pc-windows-msvc",
     "x86_64-rumprun-netbsd",
     "x86_64-unknown-freebsd",
+    "x86_64-unknown-fuchsia",
     "x86_64-unknown-linux-gnu",
     "x86_64-unknown-linux-musl",
     "x86_64-unknown-netbsd",
@@ -183,15 +185,19 @@ fn build(&mut self) {
         let mut manifest = BTreeMap::new();
         manifest.insert("manifest-version".to_string(),
                         toml::Value::String(manifest_version));
-        manifest.insert("date".to_string(), toml::Value::String(date));
+        manifest.insert("date".to_string(), toml::Value::String(date.clone()));
         manifest.insert("pkg".to_string(), toml::encode(&pkg));
         let manifest = toml::Value::Table(manifest).to_string();
 
         let filename = format!("channel-rust-{}.toml", self.rust_release);
         self.write_manifest(&manifest, &filename);
 
+        let filename = format!("channel-rust-{}-date.txt", self.rust_release);
+        self.write_date_stamp(&date, &filename);
+
         if self.rust_release != "beta" && self.rust_release != "nightly" {
             self.write_manifest(&manifest, "channel-rust-stable.toml");
+            self.write_date_stamp(&date, "channel-rust-stable-date.txt");
         }
     }
 
@@ -218,7 +224,7 @@ fn build_manifest(&mut self) -> Manifest {
         self.package("rust-docs", &mut manifest.pkg, TARGETS);
         self.package("rust-src", &mut manifest.pkg, &["*"]);
 
-        if self.channel == "nightly" {
+        if self.rust_release == "nightly" {
             self.package("rust-analysis", &mut manifest.pkg, TARGETS);
         }
 
@@ -271,7 +277,7 @@ fn build_manifest(&mut self) -> Manifest {
                         target: target.to_string(),
                     });
                 }
-                if self.channel == "nightly" {
+                if self.rust_release == "nightly" {
                     extensions.push(Component {
                         pkg: "rust-analysis".to_string(),
                         target: target.to_string(),
@@ -411,4 +417,11 @@ fn write_manifest(&self, manifest: &str, name: &str) {
         self.hash(&dst);
         self.sign(&dst);
     }
+
+    fn write_date_stamp(&self, date: &str, name: &str) {
+        let dst = self.output.join(name);
+        t!(t!(File::create(&dst)).write_all(date.as_bytes()));
+        self.hash(&dst);
+        self.sign(&dst);
+    }
 }