diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9d8c84f40715..1e983cfd726d6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,33 +97,38 @@ system internals, try asking in [`#rust-internals`][pound-rust-internals]. Before you can start building the compiler you need to configure the build for your system. In most cases, that will just mean using the defaults provided -for Rust. Configuring involves invoking the `configure` script in the project -root. +for Rust. -``` -./configure -``` +To change configuration, you must copy the file `src/bootstrap/config.toml.example` +to `config.toml` in the directory from which you will be running the build, and +change the settings provided. + +There are large number of options provided in this config file that will alter the +configuration used in the build process. Some options to note: -There are large number of options accepted by this script to alter the -configuration used later in the build process. Some options to note: +#### `[llvm]`: +- `ccache = true` - Use ccache when building llvm -- `--enable-debug` - Build a debug version of the compiler (disables optimizations, - which speeds up compilation of stage1 rustc) -- `--enable-optimize` - Enable optimizations (can be used with `--enable-debug` - to make a debug build with optimizations) -- `--disable-valgrind-rpass` - Don't run tests with valgrind -- `--enable-clang` - Prefer clang to gcc for building dependencies (e.g., LLVM) -- `--enable-ccache` - Invoke clang/gcc with ccache to re-use object files between builds -- `--enable-compiler-docs` - Build compiler documentation +#### `[build]`: +- `compiler-docs = true` - Build compiler documentation -To see a full list of options, run `./configure --help`. +#### `[rust]`: +- `debuginfo = true` - Build a compiler with debuginfo +- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust + +For more options, the `config.toml` file contains commented out defaults, with +descriptions of what each option will do. + +Note: Previously the `./configure` script was used to configure this +project. It can still be used, but it's recommended to use a `config.toml` +file. If you still have a `config.mk` file in your directory - from +`./configure` - you may need to delete it for `config.toml` to work. ### Building -Although the `./configure` script will generate a `Makefile`, this is actually -just a thin veneer over the actual build system driver, `x.py`. This file, at -the root of the repository, is used to build, test, and document various parts -of the compiler. You can execute it as: +The build system uses the `x.py` script to control the build process. This script +is used to build, test, and document various parts of the compiler. You can +execute it as: ```sh python x.py build @@ -185,6 +190,9 @@ To learn about all possible rules you can execute, run: python x.py build --help --verbose ``` +Note: Previously `./configure` and `make` were used to build this project. +They are still available, but `x.py` is the recommended build system. + ### Useful commands Some common invocations of `x.py` are: @@ -235,8 +243,8 @@ feature. We use the 'fork and pull' model described there. Please make pull requests against the `master` branch. -Compiling all of `make check` can take a while. When testing your pull request, -consider using one of the more specialized `make` targets to cut down on the +Compiling all of `./x.py test` can take a while. When testing your pull request, +consider using one of the more specialized `./x.py` targets to cut down on the amount of time you have to wait. You need to have built the compiler at least once before running these will work, but that’s only one full build rather than one each time. @@ -307,7 +315,7 @@ To find documentation-related issues, sort by the [A-docs label][adocs]. [adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AA-docs -In many cases, you don't need a full `make doc`. You can use `rustdoc` directly +In many cases, you don't need a full `./x.py doc`. You can use `rustdoc` directly to check small fixes. For example, `rustdoc src/doc/reference.md` will render reference to `doc/reference.html`. The CSS might be messed up, but you can verify that the HTML is right. diff --git a/README.md b/README.md index c1218e9c600ce..93415adc423f4 100644 --- a/README.md +++ b/README.md @@ -35,15 +35,15 @@ Read ["Installing Rust"] from [The Book]. 3. Build and install: ```sh - $ ./configure - $ make && sudo make install + $ ./x.py build && sudo ./x.py dist --install ``` - > ***Note:*** Install locations can be adjusted by passing a `--prefix` - > argument to `configure`. Various other options are also supported – pass - > `--help` for more information on them. + > ***Note:*** Install locations can be adjusted by copying the config file + > from `./src/bootstrap/config.toml.example` to `./config.toml`, and + > adjusting the `prefix` option under `[install]`. Various other options are + > also supported, and are documented in the config file. - When complete, `sudo make install` will place several programs into + When complete, `sudo ./x.py dist --install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the API-documentation tool. This install does not include [Cargo], Rust's package manager, which you may also want to build. @@ -59,7 +59,6 @@ for interop with software produced by Visual Studio use the MSVC build of Rust; for interop with GNU software built using the MinGW/MSYS2 toolchain use the GNU build. - #### MinGW [MSYS2][msys2] can be used to easily build Rust on Windows: @@ -94,11 +93,10 @@ build. mingw-w64-x86_64-gcc ``` -4. Navigate to Rust's source code (or clone it), then configure and build it: +4. Navigate to Rust's source code (or clone it), then build it: ```sh - $ ./configure - $ make && make install + $ ./x.py build && ./x.py dist --install ``` #### MSVC @@ -114,13 +112,6 @@ shell with: > python x.py build ``` -If you're running inside of an msys shell, however, you can run: - -```sh -$ ./configure --build=x86_64-pc-windows-msvc -$ make && make install -``` - Currently building Rust only works with some known versions of Visual Studio. If you have a more recent version installed the build system doesn't understand then you may need to force rustbuild to use an older version. This can be done @@ -131,13 +122,43 @@ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64. python x.py build ``` +#### Specifying an ABI + +Each specific ABI can also be used from either environment (for example, using +the GNU ABI in powershell) by using an explicit build triple. The available +Windows build triples are: +- GNU ABI (using GCC) + - `i686-pc-windows-gnu` + - `x86_64-pc-windows-gnu` +- The MSVC ABI + - `i686-pc-windows-msvc` + - `x86_64-pc-windows-msvc` + +The build triple can be specified by either specifying `--build=ABI` when +invoking `x.py` commands, or by copying the `config.toml` file (as described +in Building From Source), and modifying the `build` option under the `[build]` +section. + +### Configure and Make + +While it's not the recommended build system, this project also provides a +configure script and makefile (the latter of which just invokes `x.py`). + +```sh +$ ./configure +$ make && sudo make install +``` + +When using the configure script, the generated config.mk` file may override the +`config.toml` file. To go back to the `config.toml` file, delete the generated +`config.mk` file. + ## Building Documentation If you’d like to build the documentation, it’s almost the same: ```sh -$ ./configure -$ make docs +$ ./x.py doc ``` The generated documentation will appear in a top-level `doc` directory, diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index ac07535bdd6fb..bdf9f06ec7984 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -3,12 +3,12 @@ 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 \ + python2.7-dev \ git \ - cmake \ sudo \ xz-utils \ zlib1g-dev \ @@ -19,7 +19,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ bzip2 \ patch \ libssl-dev \ - pkg-config + pkg-config \ + swig \ + libedit-dev \ + libncurses5-dev + +# CMake 3.8.0 is the first version with official support for Fuchsia, +# which is needed to build the Fuchsia toolchain. +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 RUN curl -o /usr/local/bin/sccache \ https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-02-24-sccache-x86_64-unknown-linux-gnu && \ @@ -31,6 +39,10 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini ENTRYPOINT ["/usr/bin/dumb-init", "--"] WORKDIR /tmp +COPY shared.sh /tmp/ + +COPY build-fuchsia.sh /tmp/ +RUN ./build-fuchsia.sh COPY build-rumprun.sh /tmp/ RUN ./build-rumprun.sh @@ -65,10 +77,18 @@ ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu +ENV TARGETS=$TARGETS,x86_64-unknown-fuchsia +ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ - CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc + CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ + 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++ # Suppress some warnings in the openwrt toolchains we downloaded ENV STAGING_DIR=/tmp diff --git a/src/ci/docker/cross/build-fuchsia.sh b/src/ci/docker/cross/build-fuchsia.sh new file mode 100755 index 0000000000000..73bd1d93101a5 --- /dev/null +++ b/src/ci/docker/cross/build-fuchsia.sh @@ -0,0 +1,114 @@ +#!/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 or the MIT license +# , 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 \ + -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} < or the MIT license +# , 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 +} diff --git a/src/doc/book/src/lifetimes.md b/src/doc/book/src/lifetimes.md index 8bca13c28f0bd..042d9af9717d0 100644 --- a/src/doc/book/src/lifetimes.md +++ b/src/doc/book/src/lifetimes.md @@ -349,8 +349,8 @@ to it. ## Lifetime Elision -Rust supports powerful local type inference in the bodies of functions but not in their item signatures. -It's forbidden to allow reasoning about types based on the item signature alone. +Rust supports powerful local type inference in the bodies of functions, but it +deliberately does not perform any reasoning about types for item signatures. However, for ergonomic reasons, a very restricted secondary inference algorithm called “lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md index 4f5a6a7c0332d..e02b5a6cdd79b 100644 --- a/src/doc/book/src/procedural-macros.md +++ b/src/doc/book/src/procedural-macros.md @@ -128,7 +128,7 @@ pub fn hello_world(input: TokenStream) -> TokenStream { So there is a lot going on here. We have introduced two new crates: [`syn`] and [`quote`]. As you may have noticed, `input: TokenSteam` is immediately converted to a `String`. This `String` is a string representation of the Rust code for which -we are deriving `HelloWorld` for. At the moment, the only thing you can do with a +we are deriving `HelloWorld`. At the moment, the only thing you can do with a `TokenStream` is convert it to a string. A richer API will exist in the future. So what we really need is to be able to _parse_ Rust code into something diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 70ca5fe83a932..f850fd9772781 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -21,7 +21,6 @@ use super::{ SelectionContext, SelectionError, ObjectSafetyViolation, - MethodViolationCode, }; use fmt_macros::{Parser, Piece, Position}; @@ -267,61 +266,63 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let span = obligation.cause.span; let mut report = None; - for item in self.tcx.get_attrs(def_id).iter() { - if item.check_name("rustc_on_unimplemented") { - let err_sp = item.meta().span.substitute_dummy(span); - let trait_str = self.tcx.item_path_str(trait_ref.def_id); - if let Some(istring) = item.value_str() { - let istring = &*istring.as_str(); - let generics = self.tcx.item_generics(trait_ref.def_id); - let generic_map = generics.types.iter().map(|param| { - (param.name.as_str().to_string(), - trait_ref.substs.type_for_def(param).to_string()) - }).collect::>(); - let parser = Parser::new(istring); - let mut errored = false; - let err: String = parser.filter_map(|p| { - match p { - Piece::String(s) => Some(s), - Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => match generic_map.get(s) { - Some(val) => Some(val), - None => { - span_err!(self.tcx.sess, err_sp, E0272, - "the #[rustc_on_unimplemented] \ - attribute on \ - trait definition for {} refers to \ - non-existent type parameter {}", - trait_str, s); - errored = true; - None - } - }, - _ => { - span_err!(self.tcx.sess, err_sp, E0273, - "the #[rustc_on_unimplemented] attribute \ - on trait definition for {} must have \ - named format arguments, eg \ - `#[rustc_on_unimplemented = \ - \"foo {{T}}\"]`", trait_str); + if let Some(item) = self.tcx + .get_attrs(def_id) + .into_iter() + .filter(|a| a.check_name("rustc_on_unimplemented")) + .next() + { + let err_sp = item.meta().span.substitute_dummy(span); + let trait_str = self.tcx.item_path_str(trait_ref.def_id); + if let Some(istring) = item.value_str() { + let istring = &*istring.as_str(); + let generics = self.tcx.item_generics(trait_ref.def_id); + let generic_map = generics.types.iter().map(|param| { + (param.name.as_str().to_string(), + trait_ref.substs.type_for_def(param).to_string()) + }).collect::>(); + let parser = Parser::new(istring); + let mut errored = false; + let err: String = parser.filter_map(|p| { + match p { + Piece::String(s) => Some(s), + Piece::NextArgument(a) => match a.position { + Position::ArgumentNamed(s) => match generic_map.get(s) { + Some(val) => Some(val), + None => { + span_err!(self.tcx.sess, err_sp, E0272, + "the #[rustc_on_unimplemented] \ + attribute on \ + trait definition for {} refers to \ + non-existent type parameter {}", + trait_str, s); errored = true; None } + }, + _ => { + span_err!(self.tcx.sess, err_sp, E0273, + "the #[rustc_on_unimplemented] attribute \ + on trait definition for {} must have \ + named format arguments, eg \ + `#[rustc_on_unimplemented = \ + \"foo {{T}}\"]`", trait_str); + errored = true; + None } } - }).collect(); - // Report only if the format string checks out - if !errored { - report = Some(err); } - } else { - span_err!(self.tcx.sess, err_sp, E0274, - "the #[rustc_on_unimplemented] attribute on \ - trait definition for {} must have a value, \ - eg `#[rustc_on_unimplemented = \"foo\"]`", - trait_str); + }).collect(); + // Report only if the format string checks out + if !errored { + report = Some(err); } - break; + } else { + span_err!(self.tcx.sess, err_sp, E0274, + "the #[rustc_on_unimplemented] attribute on \ + trait definition for {} must have a value, \ + eg `#[rustc_on_unimplemented = \"foo\"]`", + trait_str); } } report @@ -359,34 +360,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn report_similar_impl_candidates(&self, - trait_ref: ty::PolyTraitRef<'tcx>, + impl_candidates: Vec>, err: &mut DiagnosticBuilder) { - let simp = fast_reject::simplify_type(self.tcx, - trait_ref.skip_binder().self_ty(), - true); - let mut impl_candidates = Vec::new(); - let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id()); - - match simp { - Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| { - let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, - imp.self_ty(), - true); - if let Some(imp_simp) = imp_simp { - if simp != imp_simp { - return; - } - } - impl_candidates.push(imp); - }), - None => trait_def.for_each_impl(self.tcx, |def_id| { - impl_candidates.push( - self.tcx.impl_trait_ref(def_id).unwrap()); - }) - }; - if impl_candidates.is_empty() { return; } @@ -525,127 +501,118 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { lint_id) .emit(); return; - } else { - match obligation.predicate { - ty::Predicate::Trait(ref trait_predicate) => { - let trait_predicate = - self.resolve_type_vars_if_possible(trait_predicate); - - if self.tcx.sess.has_errors() && trait_predicate.references_error() { - return; - } else { - let trait_ref = trait_predicate.to_poly_trait_ref(); - let (post_message, pre_message) = match self.get_parent_trait_ref( - &obligation.cause.code) - { - Some(t) => { - (format!(" in `{}`", t), format!("within `{}`, ", t)) - } - None => (String::new(), String::new()), - }; - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0277, - "the trait bound `{}` is not satisfied{}", - trait_ref.to_predicate(), - post_message); - err.span_label(span, - &format!("{}the trait `{}` is not \ - implemented for `{}`", - pre_message, - trait_ref, - trait_ref.self_ty())); - - // Try to report a help message - - if !trait_ref.has_infer_types() && - self.predicate_can_apply(trait_ref) { - // If a where-clause may be useful, remind the - // user that they can add it. - // - // don't display an on-unimplemented note, as - // these notes will often be of the form - // "the type `T` can't be frobnicated" - // which is somewhat confusing. - err.help(&format!("consider adding a `where {}` bound", - trait_ref.to_predicate())); - } else if let Some(s) = self.on_unimplemented_note(trait_ref, - obligation) { - // If it has a custom "#[rustc_on_unimplemented]" - // error message, let's display it! - err.note(&s); - } else { - // If we can't show anything useful, try to find - // similar impls. - let impl_candidates = - self.find_similar_impl_candidates(trait_ref); - if impl_candidates.len() > 0 { - self.report_similar_impl_candidates(trait_ref, &mut err); - } - } - err - } - } + } + match obligation.predicate { + ty::Predicate::Trait(ref trait_predicate) => { + let trait_predicate = + self.resolve_type_vars_if_possible(trait_predicate); - ty::Predicate::Equate(ref predicate) => { - let predicate = self.resolve_type_vars_if_possible(predicate); - let err = self.equality_predicate(&obligation.cause, - &predicate).err().unwrap(); - struct_span_err!(self.tcx.sess, span, E0278, - "the requirement `{}` is not satisfied (`{}`)", - predicate, err) + if self.tcx.sess.has_errors() && trait_predicate.references_error() { + return; } - - ty::Predicate::RegionOutlives(ref predicate) => { - let predicate = self.resolve_type_vars_if_possible(predicate); - let err = self.region_outlives_predicate(&obligation.cause, - &predicate).err().unwrap(); - struct_span_err!(self.tcx.sess, span, E0279, - "the requirement `{}` is not satisfied (`{}`)", - predicate, err) + let trait_ref = trait_predicate.to_poly_trait_ref(); + let (post_message, pre_message) = + self.get_parent_trait_ref(&obligation.cause.code) + .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t))) + .unwrap_or((String::new(), String::new())); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0277, + "the trait bound `{}` is not satisfied{}", + trait_ref.to_predicate(), + post_message); + err.span_label(span, + &format!("{}the trait `{}` is not \ + implemented for `{}`", + pre_message, + trait_ref, + trait_ref.self_ty())); + + // Try to report a help message + + if !trait_ref.has_infer_types() && + self.predicate_can_apply(trait_ref) { + // If a where-clause may be useful, remind the + // user that they can add it. + // + // don't display an on-unimplemented note, as + // these notes will often be of the form + // "the type `T` can't be frobnicated" + // which is somewhat confusing. + err.help(&format!("consider adding a `where {}` bound", + trait_ref.to_predicate())); + } else if let Some(s) = self.on_unimplemented_note(trait_ref, + obligation) { + // If it has a custom "#[rustc_on_unimplemented]" + // error message, let's display it! + err.note(&s); + } else { + // If we can't show anything useful, try to find + // similar impls. + let impl_candidates = self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates(impl_candidates, &mut err); } + err + } - ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { - let predicate = - self.resolve_type_vars_if_possible(&obligation.predicate); - struct_span_err!(self.tcx.sess, span, E0280, - "the requirement `{}` is not satisfied", - predicate) - } + ty::Predicate::Equate(ref predicate) => { + let predicate = self.resolve_type_vars_if_possible(predicate); + let err = self.equality_predicate(&obligation.cause, + &predicate).err().unwrap(); + struct_span_err!(self.tcx.sess, span, E0278, + "the requirement `{}` is not satisfied (`{}`)", + predicate, err) + } - ty::Predicate::ObjectSafe(trait_def_id) => { - let violations = self.tcx.object_safety_violations(trait_def_id); - self.tcx.report_object_safety_error(span, - trait_def_id, - violations) - } + ty::Predicate::RegionOutlives(ref predicate) => { + let predicate = self.resolve_type_vars_if_possible(predicate); + let err = self.region_outlives_predicate(&obligation.cause, + &predicate).err().unwrap(); + struct_span_err!(self.tcx.sess, span, E0279, + "the requirement `{}` is not satisfied (`{}`)", + predicate, err) + } - ty::Predicate::ClosureKind(closure_def_id, kind) => { - let found_kind = self.closure_kind(closure_def_id).unwrap(); - let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); - let mut err = struct_span_err!( - self.tcx.sess, closure_span, E0525, - "expected a closure that implements the `{}` trait, \ - but this closure only implements `{}`", - kind, - found_kind); - err.span_note( - obligation.cause.span, - &format!("the requirement to implement \ - `{}` derives from here", kind)); - err.emit(); - return; - } + ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { + let predicate = + self.resolve_type_vars_if_possible(&obligation.predicate); + struct_span_err!(self.tcx.sess, span, E0280, + "the requirement `{}` is not satisfied", + predicate) + } - ty::Predicate::WellFormed(ty) => { - // WF predicates cannot themselves make - // errors. They can only block due to - // ambiguity; otherwise, they always - // degenerate into other obligations - // (which may fail). - span_bug!(span, "WF predicate not satisfied for {:?}", ty); - } + ty::Predicate::ObjectSafe(trait_def_id) => { + let violations = self.tcx.object_safety_violations(trait_def_id); + self.tcx.report_object_safety_error(span, + trait_def_id, + violations) + } + + ty::Predicate::ClosureKind(closure_def_id, kind) => { + let found_kind = self.closure_kind(closure_def_id).unwrap(); + let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); + let mut err = struct_span_err!( + self.tcx.sess, closure_span, E0525, + "expected a closure that implements the `{}` trait, \ + but this closure only implements `{}`", + kind, + found_kind); + err.span_note( + obligation.cause.span, + &format!("the requirement to implement \ + `{}` derives from here", kind)); + err.emit(); + return; + } + + ty::Predicate::WellFormed(ty) => { + // WF predicates cannot themselves make + // errors. They can only block due to + // ambiguity; otherwise, they always + // degenerate into other obligations + // (which may fail). + span_bug!(span, "WF predicate not satisfied for {:?}", ty); } } } @@ -713,38 +680,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if !reported_violations.insert(violation.clone()) { continue; } - let buf; - let note = match violation { - ObjectSafetyViolation::SizedSelf => { - "the trait cannot require that `Self : Sized`" - } - - ObjectSafetyViolation::SupertraitSelf => { - "the trait cannot use `Self` as a type parameter \ - in the supertrait listing" - } - - ObjectSafetyViolation::Method(name, - MethodViolationCode::StaticMethod) => { - buf = format!("method `{}` has no receiver", name); - &buf - } - - ObjectSafetyViolation::Method(name, - MethodViolationCode::ReferencesSelf) => { - buf = format!("method `{}` references the `Self` type \ - in its arguments or return type", - name); - &buf - } - - ObjectSafetyViolation::Method(name, - MethodViolationCode::Generic) => { - buf = format!("method `{}` has generic type parameters", name); - &buf - } - }; - err.note(note); + err.note(&violation.error_msg()); } err } @@ -774,46 +710,46 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); if predicate.references_error() { - } else { - // Typically, this ambiguity should only happen if - // there are unresolved type inference variables - // (otherwise it would suggest a coherence - // failure). But given #21974 that is not necessarily - // the case -- we can have multiple where clauses that - // are only distinguished by a region, which results - // in an ambiguity even when all types are fully - // known, since we don't dispatch based on region - // relationships. - - // This is kind of a hack: it frequently happens that some earlier - // error prevents types from being fully inferred, and then we get - // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we - // could just skip over all checks where the self-ty is an - // inference variable, but I was afraid that there might be an - // inference variable created, registered as an obligation, and - // then never forced by writeback, and hence by skipping here we'd - // be ignoring the fact that we don't KNOW the type works - // out. Though even that would probably be harmless, given that - // we're only talking about builtin traits, which are known to be - // inhabited. But in any case I just threw in this check for - // has_errors() to be sure that compilation isn't happening - // anyway. In that case, why inundate the user. - if !self.tcx.sess.has_errors() { - if - self.tcx.lang_items.sized_trait() - .map_or(false, |sized_id| sized_id == trait_ref.def_id()) - { - self.need_type_info(obligation, self_ty); - } else { - let mut err = struct_span_err!(self.tcx.sess, - obligation.cause.span, E0283, - "type annotations required: \ - cannot resolve `{}`", - predicate); - self.note_obligation_cause(&mut err, obligation); - err.emit(); - } + return; + } + // Typically, this ambiguity should only happen if + // there are unresolved type inference variables + // (otherwise it would suggest a coherence + // failure). But given #21974 that is not necessarily + // the case -- we can have multiple where clauses that + // are only distinguished by a region, which results + // in an ambiguity even when all types are fully + // known, since we don't dispatch based on region + // relationships. + + // This is kind of a hack: it frequently happens that some earlier + // error prevents types from being fully inferred, and then we get + // a bunch of uninteresting errors saying something like " doesn't implement Sized". It may even be true that we + // could just skip over all checks where the self-ty is an + // inference variable, but I was afraid that there might be an + // inference variable created, registered as an obligation, and + // then never forced by writeback, and hence by skipping here we'd + // be ignoring the fact that we don't KNOW the type works + // out. Though even that would probably be harmless, given that + // we're only talking about builtin traits, which are known to be + // inhabited. But in any case I just threw in this check for + // has_errors() to be sure that compilation isn't happening + // anyway. In that case, why inundate the user. + if !self.tcx.sess.has_errors() { + if + self.tcx.lang_items.sized_trait() + .map_or(false, |sized_id| sized_id == trait_ref.def_id()) + { + self.need_type_info(obligation, self_ty); + } else { + let mut err = struct_span_err!(self.tcx.sess, + obligation.cause.span, E0283, + "type annotations required: \ + cannot resolve `{}`", + predicate); + self.note_obligation_cause(&mut err, obligation); + err.emit(); } } } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 60808fbc741fb..2ebe0d459fab1 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -23,6 +23,7 @@ use hir::def_id::DefId; use traits; use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::subst::Substs; +use std::borrow::Cow; use syntax::ast; #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -38,6 +39,25 @@ pub enum ObjectSafetyViolation { Method(ast::Name, MethodViolationCode), } +impl ObjectSafetyViolation { + pub fn error_msg(&self) -> Cow<'static, str> { + match *self { + ObjectSafetyViolation::SizedSelf => + "the trait cannot require that `Self : Sized`".into(), + ObjectSafetyViolation::SupertraitSelf => + "the trait cannot use `Self` as a type parameter \ + in the supertrait listing".into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => + format!("method `{}` has no receiver", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => + format!("method `{}` references the `Self` type \ + in its arguments or return type", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => + format!("method `{}` has generic type parameters", name).into(), + } + } +} + /// Reasons a method might not be object-safe. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum MethodViolationCode { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 7937d2ccfe46d..2a6ef13bfd2e2 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1086,24 +1086,6 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } } -impl<'tcx> TraitRef<'tcx> { - pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { - TraitRef { def_id: def_id, substs: substs } - } - - pub fn self_ty(&self) -> Ty<'tcx> { - self.substs.type_at(0) - } - - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { - // Select only the "input types" from a trait-reference. For - // now this is all the types that appear in the - // trait-reference, but it should eventually exclude - // associated types. - self.substs.types() - } -} - /// When type checking, we use the `ParameterEnvironment` to track /// details about the type/lifetime parameters that are in scope. /// It primarily stores the bounds information. diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 862bc15c05260..64e5ec6aeb24b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -389,6 +389,24 @@ pub struct TraitRef<'tcx> { pub substs: &'tcx Substs<'tcx>, } +impl<'tcx> TraitRef<'tcx> { + pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { + TraitRef { def_id: def_id, substs: substs } + } + + pub fn self_ty(&self) -> Ty<'tcx> { + self.substs.type_at(0) + } + + pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { + // Select only the "input types" from a trait-reference. For + // now this is all the types that appear in the + // trait-reference, but it should eventually exclude + // associated types. + self.substs.types() + } +} + pub type PolyTraitRef<'tcx> = Binder>; impl<'tcx> PolyTraitRef<'tcx> { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ae4c94d4b38c0..bb39c8c4f22ff 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1878,7 +1878,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec 0 => - format!(" ({} #{})", + format!(" ({} #{})", Escape(&stab.feature), tracker_url, issue_no, issue_no), (false, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 => format!(" (#{})", Escape(&tracker_url), issue_no, @@ -1890,12 +1890,12 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec\ 🔬 \ - This is a nightly-only experimental API.  {}\ + This is a nightly-only experimental API. {}\ ", - unstable_extra)); + unstable_extra)); } else { let text = format!("🔬 \ - This is a nightly-only experimental API.  {}\ + This is a nightly-only experimental API. {}\ {}", unstable_extra, MarkdownHtml(&stab.unstable_reason)); stability.push(format!("
{}
", diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 4ff35738b50fb..f846ef3e69e09 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -27,6 +27,31 @@ //! //! assert!(ecode.success()); //! ``` +//! +//! Calling a command with input and reading its output: +//! +//! ```no_run +//! use std::process::{Command, Stdio}; +//! use std::io::Write; +//! +//! let mut child = Command::new("/bin/cat") +//! .stdin(Stdio::piped()) +//! .stdout(Stdio::piped()) +//! .spawn() +//! .expect("failed to execute child"); +//! +//! { +//! // limited borrow of stdin +//! let stdin = child.stdin.as_mut().expect("failed to get stdin"); +//! stdin.write_all(b"test").expect("failed to write to stdin"); +//! } +//! +//! let output = child +//! .wait_with_output() +//! .expect("failed to wait on child"); +//! +//! assert_eq!(b"test", output.stdout.as_slice()); +//! ``` #![stable(feature = "process", since = "1.0.0")] diff --git a/src/test/compile-fail/feature-gate-unboxed-closures.rs b/src/test/compile-fail/feature-gate-unboxed-closures.rs new file mode 100644 index 0000000000000..4005021774443 --- /dev/null +++ b/src/test/compile-fail/feature-gate-unboxed-closures.rs @@ -0,0 +1,24 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Test; + +impl FnOnce<(u32, u32)> for Test { + type Output = u32; + + extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 { + a + b + } + //~^^^ ERROR rust-call ABI is subject to change (see issue #29625) +} + +fn main() { + assert_eq!(Test(1u32, 2u32), 3u32); +} diff --git a/src/test/rustdoc/issue-27759.rs b/src/test/rustdoc/issue-27759.rs index fe40ce2bd7ddb..e82e93230aa07 100644 --- a/src/test/rustdoc/issue-27759.rs +++ b/src/test/rustdoc/issue-27759.rs @@ -14,12 +14,12 @@ #![unstable(feature="test", issue="27759")] // @has issue_27759/unstable/index.html -// @has - 'test' +// @has - 'test ' // @has - '#27759' #[unstable(feature="test", issue="27759")] pub mod unstable { // @has issue_27759/unstable/fn.issue.html - // @has - 'test_function' + // @has - 'test_function ' // @has - '#1234567890' #[unstable(feature="test_function", issue="1234567890")] pub fn issue() {} diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 5cca370829201..6d1f8bc1cf9ba 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -18,10 +18,10 @@ // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' -// @has - 'test' +// @has - 'test ' // @has - '#32374' // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \ -// '🔬 This is a nightly-only experimental API. \(test #32374\)$' +// '🔬 This is a nightly-only experimental API. \(test #32374\)$' #[rustc_deprecated(since = "1.0.0", reason = "text")] #[unstable(feature = "test", issue = "32374")] pub struct T; @@ -29,11 +29,11 @@ pub struct T; // @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: deprecated' // @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' +// '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//details' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' +// '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//summary' \ -// '🔬 This is a nightly-only experimental API. (test #32374)' +// '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//details/p' \ // 'unstable' #[rustc_deprecated(since = "1.0.0", reason = "deprecated")] diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index c2c91487b0c17..d664a37576acb 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -45,6 +45,7 @@ static HOSTS: &'static [&'static str] = &[ 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 @@ static TARGETS: &'static [&'static str] = &[ "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", diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 2c81382bc9b08..c84fefd872e47 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -169,8 +169,8 @@ pub fn check(path: &Path, bad: &mut bool) { let whitelist = vec![ "abi_ptx", "simd", "cfg_target_has_atomic", - "unboxed_closures", "stmt_expr_attributes", - "cfg_target_thread_local", "unwind_attributes" + "stmt_expr_attributes", + "cfg_target_thread_local", "unwind_attributes", ]; // Only check the number of lang features.