diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 429996126f92b..e9d8c84f40715 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -199,7 +199,7 @@ Some common invocations of `x.py` are: This is the fastest way to recompile after you changed only rustc source code. Note however that the resulting rustc binary won't have a stdlib to link against by default. You can build libstd once with `x.py build src/libstd`, - but it is is only guaranteed to work if recompiled, so if there are any issues + but it is only guaranteed to work if recompiled, so if there are any issues recompile it. - `x.py test` - build the full compiler & run all tests (takes a while). This is what gets run by the continuous integration system against your pull diff --git a/appveyor.yml b/appveyor.yml index 6b906fd9ab618..44791b033a641 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,17 +5,15 @@ environment: secure: 1UkmbiDd15tWtYbMm5O2Uqm0b0Ur8v1MoSlydxl4ojcroPeerRMlUges0l57py8c SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c matrix: - # 32/64 bit MSVC + # 32/64 bit MSVC tests - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended - SCRIPT: python x.py test && python x.py dist - DEPLOY: 1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + SCRIPT: python x.py test - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-extended - SCRIPT: python x.py test --host i686-pc-windows-msvc --target i686-pc-windows-msvc && python x.py dist - DEPLOY: 1 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc + SCRIPT: python x.py test --host i686-pc-windows-msvc --target i686-pc-windows-msvc - # MSVC cargotest + # MSVC aux tests - MSYS_BITS: 64 RUST_CHECK_TARGET: check-aux RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc @@ -44,16 +42,40 @@ environment: # And as a final point of note, the 32-bit MinGW build using the makefiles do # *not* use debug assertions and llvm assertions. This is because they take # too long on appveyor and this is tested by rustbuild below. + - MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: python x.py test + MINGW_URL: https://s3.amazonaws.com/rust-lang-ci + MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z + MINGW_DIR: mingw32 + - MSYS_BITS: 64 + SCRIPT: python x.py test + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3.amazonaws.com/rust-lang-ci + MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z + MINGW_DIR: mingw64 + + # 32/64 bit MSVC and GNU deployment + - RUST_CONFIGURE_ARGS: > + --build=x86_64-pc-windows-msvc + --enable-extended + SCRIPT: python x.py dist + DEPLOY: 1 + - RUST_CONFIGURE_ARGS: > + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc + --enable-extended + SCRIPT: python x.py dist + DEPLOY: 1 - MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended - SCRIPT: python x.py test && python x.py dist + SCRIPT: python x.py dist MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z MINGW_DIR: mingw32 DEPLOY: 1 - - MSYS_BITS: 64 - SCRIPT: python x.py test && python x.py dist + SCRIPT: python x.py dist RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended MINGW_URL: https://s3.amazonaws.com/rust-lang-ci MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z @@ -83,12 +105,15 @@ install: # file exists in there (which it doesn't by default). - if defined MINGW_URL appveyor DownloadFile %MINGW_URL%/%MINGW_ARCHIVE% - if defined MINGW_URL 7z x -y %MINGW_ARCHIVE% > nul - - if defined MINGW_URL set PATH=C:\Python27;%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH% - - if defined MINGW_URL copy C:\Python27\python.exe C:\Python27\python2.7.exe + - if defined MINGW_URL set PATH=%CD%\%MINGW_DIR%\bin;C:\msys64\usr\bin;%PATH% # Otherwise pull in the MinGW installed on appveyor - if NOT defined MINGW_URL set PATH=C:\msys64\mingw%MSYS_BITS%\bin;C:\msys64\usr\bin;%PATH% + # Prefer the "native" Python as LLVM has trouble building with MSYS sometimes + - copy C:\Python27\python.exe C:\Python27\python2.7.exe + - set PATH=C:\Python27;%PATH% + # Download and install sccache - appveyor DownloadFile https://api.pub.build.mozilla.org/tooltool/sha512/%SCCACHE_DIGEST% - mv %SCCACHE_DIGEST% sccache.tar.bz2 diff --git a/src/Cargo.lock b/src/Cargo.lock index 51d45c06fcb49..f17095f960920 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -8,10 +8,10 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -63,13 +63,13 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -77,7 +77,7 @@ dependencies = [ name = "build-manifest" version = "0.1.0" dependencies = [ - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -94,22 +94,22 @@ version = "0.1.0" [[package]] name = "clap" -version = "2.19.3" +version = "2.20.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cmake" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", @@ -139,20 +139,33 @@ dependencies = [ "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core" version = "0.0.0" +[[package]] +name = "dtoa" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "env_logger" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -164,7 +177,7 @@ name = "filetime" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -199,17 +212,23 @@ version = "0.0.0" [[package]] name = "handlebars" -version = "0.20.5" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itoa" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -221,7 +240,7 @@ dependencies = [ [[package]] name = "lazy_static" -version = "0.1.16" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -233,7 +252,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -251,33 +270,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mdbook" -version = "0.0.14" +version = "0.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "handlebars 0.20.5 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "handlebars 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "0.1.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "open" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "panic_abort" version = "0.0.0" @@ -348,27 +381,27 @@ dependencies = [ [[package]] name = "regex" -version = "0.1.80" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mdbook 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mdbook 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -401,7 +434,7 @@ dependencies = [ [[package]] name = "rustc-serialize" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -410,7 +443,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -553,7 +586,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -597,7 +630,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -689,7 +722,7 @@ version = "0.0.0" dependencies = [ "alloc_system 0.0.0", "build_helper 0.1.0", - "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -734,6 +767,22 @@ dependencies = [ "syntax_pos 0.0.0", ] +[[package]] +name = "serde" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_json" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serialize" version = "0.0.0" @@ -779,7 +828,7 @@ dependencies = [ [[package]] name = "strsim" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -819,11 +868,11 @@ version = "0.0.0" [[package]] name = "term_size" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -844,19 +893,20 @@ dependencies = [ [[package]] name = "thread-id" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" -version = "0.2.7" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -868,12 +918,20 @@ name = "toml" version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-segmentation" -version = "0.1.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -881,9 +939,17 @@ name = "unicode-width" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unreachable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" -version = "0.1.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -891,6 +957,11 @@ name = "vec_map" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -902,38 +973,48 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" +"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374" -"checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283" +"checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758" +"checksum cmake 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a3a6805df695087e7c1bcd9a82e03ad6fb864c8e67ac41b1348229ce5b7f0407" +"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" +"checksum env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" "checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" -"checksum handlebars 0.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "07f9c1d28bcfb97143c95ed0667141677b2b5675c7ba3d5b81459ad43b1073bd" +"checksum handlebars 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b930077f1422bf853008047b55896efc1409744bfc9903f1eec1a58fcc7edeff" +"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417" -"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" +"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" +"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" -"checksum mdbook 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a629cd0194bbd0340a70db83a94b27cf9881fac8c55e6a2db983addcb7114ee4" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum mdbook 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "14e8a6aca534ac51bad1c1886b10f6d6948a14fa70b1b20a1e41c9e5c0fe3019" +"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" +"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c" "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3" +"checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41" "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" -"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c" -"checksum term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7f5f3f71b0040cecc71af239414c23fd3c73570f5ff54cf50e03cef637f2a0" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" +"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" +"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" +"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" +"checksum serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0ed773960f90a78567fcfbe935284adf50c5d7cf119aa2cf43bb0b4afa69bb" +"checksum serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e095e4e94e7382b76f48e93bd845ffddda62df8dfd4c163b1bfa93d40e22e13a" +"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" +"checksum term_size 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71662702fe5cd2cf95edd4ad655eea42f24a87a0e44059cbaa4e55260b7bc331" +"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" +"checksum thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7793b722f0f77ce716e7f1acf416359ca32ff24d04ffbac4269f44a4a83be05d" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" -"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5" +"checksum toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08272367dd2e766db3fa38f068067d17aa6a9dfd7259af24b3927db92f1e0c2f" +"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" +"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 90fd31ecbdd73..62e476bd737d3 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -205,6 +205,11 @@ fn main() { } } } + + if target.contains("pc-windows-msvc") { + cmd.arg("-Z").arg("unstable-options"); + cmd.arg("-C").arg("target-feature=+crt-static"); + } } if verbose > 1 { diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index ee3f663dbd552..7ca7ef4bd720c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -173,6 +173,8 @@ def download_stage0(self): if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="rustc", verbose=self.verbose) + self.fix_executable(self.bin_root() + "/bin/rustc") + self.fix_executable(self.bin_root() + "/bin/rustdoc") with open(self.rustc_stamp(), 'w') as f: f.write(self.stage0_rustc_date()) @@ -185,9 +187,63 @@ def download_stage0(self): if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="cargo", verbose=self.verbose) + self.fix_executable(self.bin_root() + "/bin/cargo") with open(self.cargo_stamp(), 'w') as f: f.write(self.stage0_cargo_rev()) + def fix_executable(self, fname): + # If we're on NixOS we need to change the path to the dynamic loader + + default_encoding = sys.getdefaultencoding() + try: + ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding) + except (subprocess.CalledProcessError, WindowsError): + return + + if ostype != "Linux": + return + + if not os.path.exists("/etc/NIXOS"): + return + if os.path.exists("/lib"): + return + + # At this point we're pretty sure the user is running NixOS + print("info: you seem to be running NixOS. Attempting to patch " + fname) + + try: + interpreter = subprocess.check_output(["patchelf", "--print-interpreter", fname]) + interpreter = interpreter.strip().decode(default_encoding) + except subprocess.CalledProcessError as e: + print("warning: failed to call patchelf: %s" % e) + return + + loader = interpreter.split("/")[-1] + + try: + ldd_output = subprocess.check_output(['ldd', '/run/current-system/sw/bin/sh']) + ldd_output = ldd_output.strip().decode(default_encoding) + except subprocess.CalledProcessError as e: + print("warning: unable to call ldd: %s" % e) + return + + for line in ldd_output.splitlines(): + libname = line.split()[0] + if libname.endswith(loader): + loader_path = libname[:len(libname) - len(loader)] + break + else: + print("warning: unable to find the path to the dynamic linker") + return + + correct_interpreter = loader_path + loader + + try: + subprocess.check_output(["patchelf", "--set-interpreter", correct_interpreter, fname]) + except subprocess.CalledProcessError as e: + print("warning: failed to call patchelf: %s" % e) + return + def stage0_cargo_rev(self): return self._cargo_rev diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 74b13144f2ff0..f4a667141665b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -115,10 +115,6 @@ pub fn standalone(build: &Build, target: &str) { .arg("-o").arg(&out) .arg(&path); - if filename == "reference.md" { - cmd.arg("--html-in-header").arg(&full_toc); - } - if filename == "not_found.md" { cmd.arg("--markdown-no-toc") .arg("--markdown-css") diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 21fc61cc81484..f16fc2092f616 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -99,6 +99,12 @@ pub fn llvm(build: &Build, target: &str) { .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) .define("LLVM_DEFAULT_TARGET_TRIPLE", target); + if target.contains("msvc") { + cfg.define("LLVM_USE_CRT_DEBUG", "MT"); + cfg.define("LLVM_USE_CRT_RELEASE", "MT"); + cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT"); + } + if target.starts_with("i686") { cfg.define("LLVM_BUILD_32_BITS", "ON"); } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index ee5b61062fed8..36738b81c189e 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -568,6 +568,15 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { }) .default(build.config.docs) .run(move |s| doc::rustbook(build, s.target, "nomicon")); + rules.doc("doc-reference", "src/doc/reference") + .dep(move |s| { + s.name("tool-rustbook") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) + .default(build.config.docs) + .run(move |s| doc::rustbook(build, s.target, "reference")); rules.doc("doc-standalone", "src/doc") .dep(move |s| { s.name("rustc") diff --git a/src/doc/book/src/attributes.md b/src/doc/book/src/attributes.md index 9e3cdb7ec0978..103ec39aa38a5 100644 --- a/src/doc/book/src/attributes.md +++ b/src/doc/book/src/attributes.md @@ -67,4 +67,4 @@ Rust attributes are used for a number of different things. There is a full list of attributes [in the reference][reference]. Currently, you are not allowed to create your own attributes, the Rust compiler defines them. -[reference]: ../reference.html#attributes +[reference]: ../reference/attributes.html diff --git a/src/doc/book/src/casting-between-types.md b/src/doc/book/src/casting-between-types.md index 2f6730be6651f..853fb1ec25417 100644 --- a/src/doc/book/src/casting-between-types.md +++ b/src/doc/book/src/casting-between-types.md @@ -8,7 +8,7 @@ most dangerous features of Rust! # Coercion Coercion between types is implicit and has no syntax of its own, but can -be spelled out with [`as`](#Explicit%20coercions). +be spelled out with [`as`](#explicit-coercions). Coercion occurs in `let`, `const`, and `static` statements; in function call arguments; in field values in struct initialization; and in a diff --git a/src/doc/book/src/closures.md b/src/doc/book/src/closures.md index 2f6d5039f4d43..5426ed0ff4c9c 100644 --- a/src/doc/book/src/closures.md +++ b/src/doc/book/src/closures.md @@ -463,7 +463,7 @@ fn factory() -> &(Fn(i32) -> i32) { Right. Because we have a reference, we need to give it a lifetime. But our `factory()` function takes no arguments, so -[elision](lifetimes.html#Lifetime%20Elision) doesn’t kick in here. Then what +[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what choices do we have? Try `'static`: ```rust,ignore diff --git a/src/doc/book/src/compiler-plugins.md b/src/doc/book/src/compiler-plugins.md index 47c5e5c829155..c05d808a94740 100644 --- a/src/doc/book/src/compiler-plugins.md +++ b/src/doc/book/src/compiler-plugins.md @@ -119,7 +119,7 @@ The advantages over a simple `fn(&str) -> u32` are: a way to define new literal syntax for any data type. In addition to procedural macros, you can define new -[`derive`](../reference.html#derive)-like attributes and other kinds of +[`derive`](../reference/attributes.html#derive)-like attributes and other kinds of extensions. See `Registry::register_syntax_extension` and the `SyntaxExtension` enum. For a more involved macro example, see [`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs). @@ -127,7 +127,7 @@ enum. For a more involved macro example, see ## Tips and tricks -Some of the [macro debugging tips](macros.html#Debugging%20macro%20code) are applicable. +Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable. You can use `syntax::parse` to turn token trees into higher-level syntax elements like expressions: @@ -165,8 +165,8 @@ quasiquote as an ordinary plugin library. # Lint plugins Plugins can extend [Rust's lint -infrastructure](../reference.html#lint-check-attributes) with additional checks for -code style, safety, etc. Now let's write a plugin +infrastructure](../reference/attributes.html#lint-check-attributes) with +additional checks for code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs) that warns about any item named `lintme`. @@ -244,9 +244,10 @@ mostly use the same infrastructure as lint plugins, and provide examples of how to access type information. Lints defined by plugins are controlled by the usual [attributes and compiler -flags](../reference.html#lint-check-attributes), e.g. `#[allow(test_lint)]` or -`-A test-lint`. These identifiers are derived from the first argument to -`declare_lint!`, with appropriate case and punctuation conversion. +flags](../reference/attributes.html#lint-check-attributes), e.g. +`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the +first argument to `declare_lint!`, with appropriate case and punctuation +conversion. You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`, including those provided by plugins loaded by `foo.rs`. diff --git a/src/doc/book/src/concurrency.md b/src/doc/book/src/concurrency.md index e5bc7ecdd0b28..a64178c26f237 100644 --- a/src/doc/book/src/concurrency.md +++ b/src/doc/book/src/concurrency.md @@ -55,7 +55,7 @@ For sharing references across threads, Rust provides a wrapper type called `Arc`. `Arc` implements `Send` and `Sync` if and only if `T` implements both `Send` and `Sync`. For example, an object of type `Arc>` cannot be transferred across threads because -[`RefCell`](choosing-your-guarantees.html#RefCell%3CT%3E) does not implement +[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement `Sync`, consequently `Arc>` would not implement `Send`. These two traits allow you to use the type system to make strong guarantees @@ -126,7 +126,7 @@ closure only captures a _reference to `x`_. This is a problem, because the thread may outlive the scope of `x`, leading to a dangling pointer. To fix this, we use a `move` closure as mentioned in the error message. `move` -closures are explained in depth [here](closures.html#move%20closures); basically +closures are explained in depth [here](closures.html#move-closures); basically they move variables from their environment into themselves. ```rust diff --git a/src/doc/book/src/error-handling.md b/src/doc/book/src/error-handling.md index 1b0d2453275fc..c823c32a135bb 100644 --- a/src/doc/book/src/error-handling.md +++ b/src/doc/book/src/error-handling.md @@ -21,35 +21,35 @@ sum types and combinators, and try to motivate the way Rust does error handling incrementally. As such, programmers with experience in other expressive type systems may want to jump around. -* [The Basics](#The%20Basics) - * [Unwrapping explained](#Unwrapping%20explained) - * [The `Option` type](#The%20Option%20type) - * [Composing `Option` values](#Composing%20Option%3CT%3E%20values) - * [The `Result` type](#The%20Result%20type) - * [Parsing integers](#Parsing%20integers) - * [The `Result` type alias idiom](#The%20Result%20type%20alias%20idiom) - * [A brief interlude: unwrapping isn't evil](#A%20brief%20interlude:%20unwrapping%20isnt%20evil) -* [Working with multiple error types](#Working%20with%20multiple%20error%20types) - * [Composing `Option` and `Result`](#Composing%20Option%20and%20Result) - * [The limits of combinators](#The%20limits%20of%20combinators) - * [Early returns](#Early%20returns) - * [The `try!` macro](#The%20try%20macro) - * [Defining your own error type](#Defining%20your%20own%20error%20type) -* [Standard library traits used for error handling](#Standard%20library%20traits%20used%20for%20error%20handling) - * [The `Error` trait](#The%20Error%20trait) - * [The `From` trait](#The%20From%20trait) - * [The real `try!` macro](#The%20real%20try%20macro) - * [Composing custom error types](#Composing%20custom%20error%20types) - * [Advice for library writers](#Advice%20for%20library%20writers) -* [Case study: A program to read population data](#Case%20study:%20A%20program%20to%20read%20population%20data) - * [Initial setup](#Initial%20setup) - * [Argument parsing](#Argument%20parsing) - * [Writing the logic](#Writing%20the%20logic) - * [Error handling with `Box`](#Error%20handling%20with%20Box%3CError%3E) - * [Reading from stdin](#Reading%20from%20stdin) - * [Error handling with a custom type](#Error%20handling%20with%20a%20custom%20type) - * [Adding functionality](#Adding%20functionality) -* [The short story](#The%20short%20story) +* [The Basics](#the-basics) + * [Unwrapping explained](#unwrapping-explained) + * [The `Option` type](#the-option-type) + * [Composing `Option` values](#composing-optiont-values) + * [The `Result` type](#the-result-type) + * [Parsing integers](#parsing-integers) + * [The `Result` type alias idiom](#the-result-type-alias-idiom) + * [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil) +* [Working with multiple error types](#working-with-multiple-error-types) + * [Composing `Option` and `Result`](#composing-option-and-result) + * [The limits of combinators](#the-limits-of-combinators) + * [Early returns](#early-returns) + * [The `try!` macro](#the-try-macro) + * [Defining your own error type](#defining-your-own-error-type) +* [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling) + * [The `Error` trait](#the-error-trait) + * [The `From` trait](#the-from-trait) + * [The real `try!` macro](#the-real-try-macro) + * [Composing custom error types](#composing-custom-error-types) + * [Advice for library writers](#advice-for-library-writers) +* [Case study: A program to read population data](#case-study-a-program-to-read-population-data) + * [Initial setup](#initial-setup) + * [Argument parsing](#argument-parsing) + * [Writing the logic](#writing-the-logic) + * [Error handling with `Box`](#error-handling-with-boxerror) + * [Reading from stdin](#reading-from-stdin) + * [Error handling with a custom type](#error-handling-with-a-custom-type) + * [Adding functionality](#adding-functionality) +* [The short story](#the-short-story) # The Basics @@ -796,7 +796,7 @@ because of the return types of [`std::fs::File::open`](../std/fs/struct.File.html#method.open) and [`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string). (Note that they both use the [`Result` type alias -idiom](#The%20Result%20type%20alias%20idiom) described previously. If you +idiom](#the-result-type-alias-idiom) described previously. If you click on the `Result` type, you'll [see the type alias](../std/io/type.Result.html), and consequently, the underlying `io::Error` type.) The third problem is described by the @@ -1120,7 +1120,7 @@ returns an `&Error`, which is itself a trait object. We'll revisit the For now, it suffices to show an example implementing the `Error` trait. Let's use the error type we defined in the -[previous section](#Defining%20your%20own%20error%20type): +[previous section](#defining-your-own-error-type): ```rust use std::io; @@ -1493,19 +1493,19 @@ representation. But certainly, this will vary depending on use cases. At a minimum, you should probably implement the [`Error`](../std/error/trait.Error.html) trait. This will give users of your library some minimum flexibility for -[composing errors](#The%20real%20try%20macro). Implementing the `Error` trait also +[composing errors](#the-real-try-macro). Implementing the `Error` trait also means that users are guaranteed the ability to obtain a string representation of an error (because it requires impls for both `fmt::Debug` and `fmt::Display`). Beyond that, it can also be useful to provide implementations of `From` on your error types. This allows you (the library author) and your users to -[compose more detailed errors](#Composing%20custom%20error%20types). For example, +[compose more detailed errors](#composing-custom-error-types). For example, [`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html) provides `From` impls for both `io::Error` and `byteorder::Error`. Finally, depending on your tastes, you may also want to define a -[`Result` type alias](#The%20Result%20type%20alias%20idiom), particularly if your +[`Result` type alias](#the-result-type-alias-idiom), particularly if your library defines a single error type. This is used in the standard library for [`io::Result`](../std/io/type.Result.html) and [`fmt::Result`](../std/fmt/type.Result.html). @@ -1538,7 +1538,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates. We're not going to spend a lot of time on setting up a project with Cargo because it is already covered well in [the Cargo -section](getting-started.html#Hello%20Cargo) and [Cargo's documentation][14]. +section](getting-started.html#hello-cargo) and [Cargo's documentation][14]. To get started from scratch, run `cargo new --bin city-pop` and make sure your `Cargo.toml` looks something like this: @@ -1729,7 +1729,7 @@ error types and you don't need any `From` implementations. The downside is that since `Box` is a trait object, it *erases the type*, which means the compiler can no longer reason about its underlying type. -[Previously](#The%20limits%20of%20combinators) we started refactoring our code by +[Previously](#the-limits-of-combinators) we started refactoring our code by changing the type of our function from `T` to `Result`. In this case, `OurErrorType` is only `Box`. But what's `T`? And can we add a return type to `main`? diff --git a/src/doc/book/src/ffi.md b/src/doc/book/src/ffi.md index b2994d2a29cbb..cccefd8dfe73f 100644 --- a/src/doc/book/src/ffi.md +++ b/src/doc/book/src/ffi.md @@ -680,7 +680,7 @@ pub extern fn hello_rust() -> *const u8 { The `extern` makes this function adhere to the C calling convention, as discussed above in "[Foreign Calling -Conventions](ffi.html#Foreign%20calling%20conventions)". The `no_mangle` +Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle` attribute turns off Rust's name mangling, so that it is easier to link to. # FFI and panics diff --git a/src/doc/book/src/generics.md b/src/doc/book/src/generics.md index 56655ac41d0d3..d02cd776d00e3 100644 --- a/src/doc/book/src/generics.md +++ b/src/doc/book/src/generics.md @@ -140,5 +140,51 @@ container types like [`Vec`][Vec]. On the other hand, often you want to trade that flexibility for increased expressive power. Read about [trait bounds][traits] to see why and how. +## Resolving ambiguities + +Most of the time when generics are involved, the compiler can infer the +generic parameters automatically: + +```rust +// v must be a Vec but we don't know what T is yet +let mut v = Vec::new(); +// v just got a bool value, so T must be bool! +v.push(true); +// Debug-print v +println!("{:?}", v); +``` + +Sometimes though, the compiler needs a little help. For example, had we +omitted the last line, we would get a compile error: + +```rust,ignore +let v = Vec::new(); +// ^^^^^^^^ cannot infer type for `T` +// +// note: type annotations or generic parameter binding required +println!("{:?}", v); +``` + +We can solve this using either a type annotation: + +```rust +let v: Vec = Vec::new(); +println!("{:?}", v); +``` + +or by binding the generic parameter `T` via the so-called +[‘turbofish’][turbofish] `::<>` syntax: + +```rust +let v = Vec::::new(); +println!("{:?}", v); +``` + +The second approach is useful in situations where we don’t want to bind the +result to a variable. It can also be used to bind generic parameters in +functions or methods. See [Iterators § Consumers](iterators.html#consumers) +for an example. + [traits]: traits.html [Vec]: ../std/vec/struct.Vec.html +[turbofish]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect diff --git a/src/doc/book/src/getting-started.md b/src/doc/book/src/getting-started.md index 93846644c398e..6208b1f4c1234 100644 --- a/src/doc/book/src/getting-started.md +++ b/src/doc/book/src/getting-started.md @@ -236,7 +236,7 @@ language]*, which means that most things are expressions, rather than statements. The `;` indicates that this expression is over, and the next one is ready to begin. Most lines of Rust code end with a `;`. -[expression-oriented language]: glossary.html#Expression-Oriented%20Language +[expression-oriented language]: glossary.html#expression-oriented-language ## Compiling and Running Are Separate Steps diff --git a/src/doc/book/src/glossary.md b/src/doc/book/src/glossary.md index 49821d86a9200..b17b89633f356 100644 --- a/src/doc/book/src/glossary.md +++ b/src/doc/book/src/glossary.md @@ -56,7 +56,7 @@ They can be used to manage control flow in a modular fashion. A type without a statically known size or alignment. ([more info][link]) -[link]: ../nomicon/exotic-sizes.html#Dynamically%20Sized%20Types%20(DSTs) +[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts ### Expression @@ -76,8 +76,8 @@ In an expression-oriented language, (nearly) every statement is an expression and therefore returns a value. Consequently, these expression statements can themselves form part of larger expressions. -[expression]: glossary.html#Expression -[statement]: glossary.html#Statement +[expression]: glossary.html#expression +[statement]: glossary.html#statement ### Statement diff --git a/src/doc/book/src/guessing-game.md b/src/doc/book/src/guessing-game.md index 216db25cd9564..7368d2184e5c2 100644 --- a/src/doc/book/src/guessing-game.md +++ b/src/doc/book/src/guessing-game.md @@ -119,7 +119,7 @@ there are no arguments, and `{` starts the body of the function. Because we didn’t include a return type, it’s assumed to be `()`, an empty [tuple][tuples]. -[tuples]: primitive-types.html#Tuples +[tuples]: primitive-types.html#tuples ```rust,ignore println!("Guess the number!"); @@ -727,7 +727,7 @@ thirty-two bit integer. Rust has [a number of built-in number types][number], but we’ve chosen `u32`. It’s a good default choice for a small positive number. [parse]: ../std/primitive.str.html#method.parse -[number]: primitive-types.html#Numeric%20types +[number]: primitive-types.html#numeric-types Just like `read_line()`, our call to `parse()` could cause an error. What if our string contained `A👍%`? There’d be no way to convert that to a number. As diff --git a/src/doc/book/src/iterators.md b/src/doc/book/src/iterators.md index 1437c0f0b54c6..8ee6c0828ad6b 100644 --- a/src/doc/book/src/iterators.md +++ b/src/doc/book/src/iterators.md @@ -135,10 +135,10 @@ Here's the version that does compile: let one_to_one_hundred = (1..101).collect::>(); ``` -If you remember, the `::<>` syntax allows us to give a type hint, -and so we tell it that we want a vector of integers. You don't always -need to use the whole type, though. Using a `_` will let you provide -a partial hint: +If you remember, the [`::<>` syntax](generics.html#resolving-ambiguities) +allows us to give a type hint that tells the compiler we want a vector of +integers. You don't always need to use the whole type, though. Using a `_` +will let you provide a partial hint: ```rust let one_to_one_hundred = (1..101).collect::>(); diff --git a/src/doc/book/src/lifetimes.md b/src/doc/book/src/lifetimes.md index c00815f49c740..8bca13c28f0bd 100644 --- a/src/doc/book/src/lifetimes.md +++ b/src/doc/book/src/lifetimes.md @@ -139,7 +139,7 @@ associated with it, but the compiler lets you elide (i.e. omit, see ["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we get to that, though, let’s look at a short example with explicit lifetimes: -[lifetime-elision]: #Lifetime%20Elision +[lifetime-elision]: #lifetime-elision ```rust,ignore fn bar<'a>(...) diff --git a/src/doc/book/src/macros.md b/src/doc/book/src/macros.md index ae1e1c65dd225..93f63ddc0a562 100644 --- a/src/doc/book/src/macros.md +++ b/src/doc/book/src/macros.md @@ -101,7 +101,7 @@ trees, at compile time. The semicolon is optional on the last (here, only) case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’. These have [their own little grammar] within the language. -[their own little grammar]: ../reference.html#macros +[their own little grammar]: ../reference/macros.html The matcher `$x:expr` will match any Rust expression, binding that syntax tree to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’; @@ -363,7 +363,7 @@ fn main() { } ``` -[items]: ../reference.html#items +[items]: ../reference/items.html # Recursive macros @@ -430,7 +430,7 @@ Even when Rust code contains un-expanded macros, it can be parsed as a full tools that process code. It also has a few consequences for the design of Rust’s macro system. -[ast]: glossary.html#Abstract%20Syntax%20Tree +[ast]: glossary.html#abstract-syntax-tree One consequence is that Rust must determine, when it parses a macro invocation, whether the macro stands in for @@ -490,7 +490,7 @@ be forced to choose between parsing `$i` and parsing `$e`. Changing the invocation syntax to put a distinctive token in front can solve the problem. In this case, you can write `$(I $i:ident)* E $e:expr`. -[item]: ../reference.html#items +[item]: ../reference/items.html # Scoping and macro import/export @@ -565,7 +565,7 @@ When this library is loaded with `#[macro_use] extern crate`, only `m2` will be imported. The Rust Reference has a [listing of macro-related -attributes](../reference.html#macro-related-attributes). +attributes](../reference/attributes.html#macro-related-attributes). # The variable `$crate` diff --git a/src/doc/book/src/mutability.md b/src/doc/book/src/mutability.md index 7e96849220a95..fa7a259392a7e 100644 --- a/src/doc/book/src/mutability.md +++ b/src/doc/book/src/mutability.md @@ -89,7 +89,7 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the > * exactly one mutable reference (`&mut T`). [ownership]: ownership.html -[borrowing]: references-and-borrowing.html#Borrowing +[borrowing]: references-and-borrowing.html#borrowing So, that’s the real definition of ‘immutability’: is this safe to have two pointers to? In `Arc`’s case, yes: the mutation is entirely contained inside diff --git a/src/doc/book/src/ownership.md b/src/doc/book/src/ownership.md index e7bf3cec55e47..21ebd6333f710 100644 --- a/src/doc/book/src/ownership.md +++ b/src/doc/book/src/ownership.md @@ -65,10 +65,10 @@ elements onto them. Vectors have a [generic type][generics] `Vec`, so in this example `v` will have type `Vec`. We'll cover [generics] in detail in a later chapter. -[arrays]: primitive-types.html#Arrays +[arrays]: primitive-types.html#arrays [vectors]: vectors.html -[heap]: the-stack-and-the-heap.html#The%20Heap -[stack]: the-stack-and-the-heap.html#The%20Stack +[heap]: the-stack-and-the-heap.html#the-heap +[stack]: the-stack-and-the-heap.html#the-stack [bindings]: variable-bindings.html [generics]: generics.html @@ -136,7 +136,7 @@ Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit pattern representing the value of 10 to the allocated memory and binds the variable name x to this memory region for future reference. -[i32]: primitive-types.html#Numeric%20types +[i32]: primitive-types.html#numeric-types Now consider the following code fragment: diff --git a/src/doc/book/src/primitive-types.md b/src/doc/book/src/primitive-types.md index 67d71ceba0cc3..8fd3d17c15e57 100644 --- a/src/doc/book/src/primitive-types.md +++ b/src/doc/book/src/primitive-types.md @@ -232,7 +232,7 @@ soon. You can assign one tuple into another, if they have the same contained types and [arity]. Tuples have the same arity when they have the same length. -[arity]: glossary.html#Arity +[arity]: glossary.html#arity ```rust let mut x = (1, 2); // x: (i32, i32) diff --git a/src/doc/book/src/procedural-macros.md b/src/doc/book/src/procedural-macros.md index 6c4700f9305ca..079324d56d1e6 100644 --- a/src/doc/book/src/procedural-macros.md +++ b/src/doc/book/src/procedural-macros.md @@ -169,7 +169,7 @@ So this is where quotes comes in. The `ast` argument is a struct that gives us a representation of our type (which can be either a `struct` or an `enum`). Check out the [docs](https://docs.rs/syn/0.10.5/syn/struct.MacroInput.html), there is some useful information there. We are able to get the name of the -type using `ast.ident`. The `quote!` macro let's us write up the Rust code +type using `ast.ident`. The `quote!` macro lets us write up the Rust code that we wish to return and convert it into `Tokens`. `quote!` let's us use some really cool templating mechanics; we simply write `#name` and `quote!` will replace it with the variable named `name`. You can even do some repetition diff --git a/src/doc/book/src/structs.md b/src/doc/book/src/structs.md index 6423147e66e09..6b2a145c85e51 100644 --- a/src/doc/book/src/structs.md +++ b/src/doc/book/src/structs.md @@ -134,7 +134,7 @@ fn main() { let age = 27; let peter = Person { name, age }; - // Print debug struct + // Debug-print struct println!("{:?}", peter); } ``` diff --git a/src/doc/book/src/syntax-index.md b/src/doc/book/src/syntax-index.md index 1e1d811a1d8b1..a06520f4ac2f3 100644 --- a/src/doc/book/src/syntax-index.md +++ b/src/doc/book/src/syntax-index.md @@ -125,7 +125,7 @@ * `path<…>` (*e.g.* `Vec`): specifies parameters to generic type *in a type*. See [Generics]. -* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::()`): specifies parameters to generic type, function, or method *in an expression*. +* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::()`): specifies parameters to generic type, function, or method *in an expression*. See [Generics § Resolving ambiguities](generics.html#resolving-ambiguities). * `fn ident<…> …`: define generic function. See [Generics]. * `struct ident<…> …`: define generic structure. See [Generics]. * `enum ident<…> …`: define generic enumeration. See [Generics]. @@ -196,18 +196,18 @@ [Associated Types]: associated-types.html [Attributes]: attributes.html [Casting Between Types (`as`)]: casting-between-types.html#as -[Closures (`move` closures)]: closures.html#move%20closures +[Closures (`move` closures)]: closures.html#move-closures [Closures]: closures.html [Comments]: comments.html -[Crates and Modules (Defining Modules)]: crates-and-modules.html#Defining%20modules -[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#Exporting%20a%20public%20interface -[Crates and Modules (Importing External Crates)]: crates-and-modules.html#Importing%20external%20crates -[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#Importing%20modules%20with%20use -[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#Re-exporting%20with%20pub%20use -[Diverging Functions]: functions.html#Diverging%20functions +[Crates and Modules (Defining Modules)]: crates-and-modules.html#defining-modules +[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#exporting-a-public-interface +[Crates and Modules (Importing External Crates)]: crates-and-modules.html#importing-external-crates +[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#importing-modules-with-use +[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#re-exporting-with-pub-use +[Diverging Functions]: functions.html#diverging-functions [Enums]: enums.html [Foreign Function Interface]: ffi.html -[Functions (Early Returns)]: functions.html#Early%20returns +[Functions (Early Returns)]: functions.html#early-returns [Functions]: functions.html [Generics]: generics.html [Iterators]: iterators.html @@ -216,38 +216,38 @@ [Loops (`for`)]: loops.html#for [Loops (`loop`)]: loops.html#loop [Loops (`while`)]: loops.html#while -[Loops (Ending Iteration Early)]: loops.html#Ending%20iteration%20early -[Loops (Loops Labels)]: loops.html#Loop%20labels +[Loops (Ending Iteration Early)]: loops.html#ending-iteration-early +[Loops (Loops Labels)]: loops.html#loop-labels [Macros]: macros.html [Match]: match.html -[Method Syntax (Method Calls)]: method-syntax.html#Method%20calls +[Method Syntax (Method Calls)]: method-syntax.html#method-calls [Method Syntax]: method-syntax.html [Mutability]: mutability.html [Operators and Overloading]: operators-and-overloading.html -[Patterns (`ref` and `ref mut`)]: patterns.html#ref%20and%20ref%20mut -[Patterns (Bindings)]: patterns.html#Bindings -[Patterns (Ignoring bindings)]: patterns.html#Ignoring%20bindings -[Patterns (Multiple patterns)]: patterns.html#Multiple%20patterns -[Patterns (Ranges)]: patterns.html#Ranges +[Patterns (`ref` and `ref mut`)]: patterns.html#ref-and-ref-mut +[Patterns (Bindings)]: patterns.html#bindings +[Patterns (Ignoring bindings)]: patterns.html#ignoring-bindings +[Patterns (Multiple patterns)]: patterns.html#multiple-patterns +[Patterns (Ranges)]: patterns.html#ranges [Primitive Types (`char`)]: primitive-types.html#char -[Primitive Types (Arrays)]: primitive-types.html#Arrays -[Primitive Types (Booleans)]: primitive-types.html#Booleans -[Primitive Types (Tuple Indexing)]: primitive-types.html#Tuple%20indexing -[Primitive Types (Tuples)]: primitive-types.html#Tuples +[Primitive Types (Arrays)]: primitive-types.html#arrays +[Primitive Types (Booleans)]: primitive-types.html#booleans +[Primitive Types (Tuple Indexing)]: primitive-types.html#tuple-indexing +[Primitive Types (Tuples)]: primitive-types.html#tuples [Raw Pointers]: raw-pointers.html -[Reference (Byte String Literals)]: ../reference.html#byte-string-literals -[Reference (Integer literals)]: ../reference.html#integer-literals -[Reference (Raw Byte String Literals)]: ../reference.html#raw-byte-string-literals -[Reference (Raw String Literals)]: ../reference.html#raw-string-literals +[Reference (Byte String Literals)]: ../reference/tokens.html/#byte-string-literals +[Reference (Integer literals)]: ../reference/tokens.html#integer-literals +[Reference (Raw Byte String Literals)]: ../reference/tokens.html#raw-byte-string-literals +[Reference (Raw String Literals)]: ../reference/tokens.html#raw-string-literals [References and Borrowing]: references-and-borrowing.html [Strings]: strings.html -[Structs (Update syntax)]: structs.html#Update%20syntax +[Structs (Update syntax)]: structs.html#update-syntax [Structs]: structs.html -[Traits (`where` clause)]: traits.html#Where%20clause -[Traits (Multiple Trait Bounds)]: traits.html#Multiple%20trait%20bounds +[Traits (`where` clause)]: traits.html#where-clause +[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds [Traits]: traits.html [Universal Function Call Syntax]: ufcs.html -[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#Angle-bracket%20Form +[Universal Function Call Syntax (Angle-bracket Form)]: ufcs.html#angle-bracket-form [Unsafe]: unsafe.html -[Unsized Types (`?Sized`)]: unsized-types.html#Sized +[Unsized Types (`?Sized`)]: unsized-types.html#sized [Variable Bindings]: variable-bindings.html diff --git a/src/doc/book/src/traits.md b/src/doc/book/src/traits.md index a6d1c3d1d231d..19a133f84b0b6 100644 --- a/src/doc/book/src/traits.md +++ b/src/doc/book/src/traits.md @@ -81,7 +81,7 @@ Traits are useful because they allow a type to make certain promises about its behavior. Generic functions can exploit this to constrain, or [bound][bounds], the types they accept. Consider this function, which does not compile: -[bounds]: glossary.html#Bounds +[bounds]: glossary.html#bounds ```rust,ignore fn print_area(shape: T) { diff --git a/src/doc/book/src/type-aliases.md b/src/doc/book/src/type-aliases.md index b1ce068528381..1bd0f78e36853 100644 --- a/src/doc/book/src/type-aliases.md +++ b/src/doc/book/src/type-aliases.md @@ -55,7 +55,7 @@ if x == y { This compiles without error. Values of a `Num` type are the same as a value of type `i32`, in every way. You can use [tuple struct] to really get a new type. -[tuple struct]: structs.html#Tuple%20structs +[tuple struct]: structs.html#tuple-structs You can also use type aliases with generics: diff --git a/src/doc/book/src/variable-bindings.md b/src/doc/book/src/variable-bindings.md index 0c8324d83e073..d6aa8b1acb72f 100644 --- a/src/doc/book/src/variable-bindings.md +++ b/src/doc/book/src/variable-bindings.md @@ -181,7 +181,7 @@ print. # Scope and shadowing Let’s get back to bindings. Variable bindings have a scope - they are -constrained to live in a block they were defined in. A block is a collection +constrained to live in the block they were defined in. A block is a collection of statements enclosed by `{` and `}`. Function definitions are also blocks! In the following example we define two variable bindings, `x` and `y`, which live in different blocks. `x` can be accessed from inside the `fn main() {}` diff --git a/src/doc/book/src/vectors.md b/src/doc/book/src/vectors.md index 9b293880cdc03..aff078718dfb1 100644 --- a/src/doc/book/src/vectors.md +++ b/src/doc/book/src/vectors.md @@ -151,6 +151,6 @@ API documentation][vec]. [vec]: ../std/vec/index.html [box]: ../std/boxed/index.html [generic]: generics.html -[panic]: concurrency.html#Panics +[panic]: concurrency.html#panics [get]: ../std/vec/struct.Vec.html#method.get [get_mut]: ../std/vec/struct.Vec.html#method.get_mut diff --git a/src/doc/grammar.md b/src/doc/grammar.md index c81f2e2282b5e..8e803aff4d6fe 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -187,7 +187,7 @@ literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit | bool_ The optional `lit_suffix` production is only used for certain numeric literals, but is reserved for future extension. That is, the above gives the lexical grammar, but a Rust parser will reject everything but the 12 special cases -mentioned in [Number literals](reference.html#number-literals) in the +mentioned in [Number literals](reference/tokens.html#number-literals) in the reference. #### Character and string literals diff --git a/src/doc/index.md b/src/doc/index.md index 144b786f58d24..982e24ef69549 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -16,14 +16,6 @@ builds documentation for individual Rust packages. Rust provides a standard library with a number of features; [we host its documentation here][api]. -## Reference Documentation - -Rust does not yet have a formal specification, but we have [a reference document -][ref]. It is guaranteed to be accurate, but not complete. We now have a -policy that all new features must be included in the reference before -stabilization; however, we are still back-filling things that landed before -then. That work is being tracked [here][38643]. - ## Extended Error Documentation Many of Rust's errors come with error codes, and you can request extended @@ -37,11 +29,17 @@ nicknamed 'The Rust Bookshelf.' * [The Rust Programming Language][book] teaches you how to program in Rust. * [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust. +* [The Reference][ref] is not a formal spec, but is more detailed and comprehensive than the book. + +Another few words about the reference: it is guaranteed to be accurate, but not +complete. We now have a policy that all new features must be included in the +reference before stabilization; however, we are still back-filling things that +landed before then. That work is being tracked [here][38643]. [Rust Learning]: https://github.com/ctjhoa/rust-learning [Docs.rs]: https://docs.rs/ [api]: std/index.html -[ref]: reference.html +[ref]: reference/index.html [38643]: https://github.com/rust-lang/rust/issues/38643 [err]: error-index.html [book]: book/index.html diff --git a/src/doc/nomicon/src/drop-flags.md b/src/doc/nomicon/src/drop-flags.md index 51fa9d0a3c0f1..e69264f281c99 100644 --- a/src/doc/nomicon/src/drop-flags.md +++ b/src/doc/nomicon/src/drop-flags.md @@ -79,17 +79,5 @@ if condition { } ``` -As of Rust 1.0, the drop flags are actually not-so-secretly stashed in a hidden -field of any type that implements Drop. Rust sets the drop flag by overwriting -the entire value with a particular bit pattern. This is pretty obviously Not -The Fastest and causes a bunch of trouble with optimizing code. It's legacy from -a time when you could do much more complex conditional initialization. - -As such work is currently under way to move the flags out onto the stack frame -where they more reasonably belong. Unfortunately, this work will take some time -as it requires fairly substantial changes to the compiler. - -Regardless, Rust programs don't need to worry about uninitialized values on -the stack for correctness. Although they might care for performance. Thankfully, -Rust makes it easy to take control here! Uninitialized values are there, and -you can work with them in Safe Rust, but you're never in danger. +The drop flags are tracked on the stack and no longer stashed in types that +implement drop. diff --git a/src/doc/nomicon/src/lifetime-mismatch.md b/src/doc/nomicon/src/lifetime-mismatch.md index 08627130590c0..30b4f09f9032d 100644 --- a/src/doc/nomicon/src/lifetime-mismatch.md +++ b/src/doc/nomicon/src/lifetime-mismatch.md @@ -78,4 +78,4 @@ TODO: other common problems? SEME regions stuff, mostly? -[ex2]: lifetimes.html#Example%3A%20aliasing%20a%20mutable%20reference +[ex2]: lifetimes.html#example-aliasing-a-mutable-reference diff --git a/src/doc/nomicon/src/repr-rust.md b/src/doc/nomicon/src/repr-rust.md index 98411e041be07..c02cf44189f1a 100644 --- a/src/doc/nomicon/src/repr-rust.md +++ b/src/doc/nomicon/src/repr-rust.md @@ -151,4 +151,4 @@ use fairly elaborate algorithms to cache bits throughout nested types with special constrained representations. As such it is *especially* desirable that we leave enum layout unspecified today. -[dst]: exotic-sizes.html#Dynamically%20Sized%20Types%20(DSTs) +[dst]: exotic-sizes.html#dynamically-sized-types-dsts diff --git a/src/doc/reference.md b/src/doc/reference.md index f2be20d4a7516..fdeea17ed1124 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1,4411 +1,4 @@ -% The Rust Reference +% The Rust Reference has moved -# Introduction - -This document is the primary reference for the Rust programming language. It -provides three kinds of material: - - - Chapters that informally describe each language construct and their use. - - Chapters that informally describe the memory model, concurrency model, - runtime services, linkage model and debugging facilities. - - Appendix chapters providing rationale and references to languages that - influenced the design. - -This document does not serve as an introduction to the language. Background -familiarity with the language is assumed. A separate [book] is available to -help acquire such background familiarity. - -This document also does not serve as a reference to the [standard] library -included in the language distribution. Those libraries are documented -separately by extracting documentation attributes from their source code. Many -of the features that one might expect to be language features are library -features in Rust, so what you're looking for may be there, not here. - -Finally, this document is not normative. It may include details that are -specific to `rustc` itself, and should not be taken as a specification for -the Rust language. We intend to produce such a document someday, but this -is what we have for now. - -You may also be interested in the [grammar]. - -[book]: book/index.html -[standard]: std/index.html -[grammar]: grammar.html - -# Notation - -## Unicode productions - -A few productions in Rust's grammar permit Unicode code points outside the -ASCII range. We define these productions in terms of character properties -specified in the Unicode standard, rather than in terms of ASCII-range code -points. The grammar has a [Special Unicode Productions][unicodeproductions] -section that lists these productions. - -[unicodeproductions]: grammar.html#special-unicode-productions - -## String table productions - -Some rules in the grammar — notably [unary -operators](#unary-operator-expressions), [binary -operators](#binary-operator-expressions), and [keywords][keywords] — are -given in a simplified form: as a listing of a table of unquoted, printable -whitespace-separated strings. These cases form a subset of the rules regarding -the [token](#tokens) rule, and are assumed to be the result of a -lexical-analysis phase feeding the parser, driven by a DFA, operating over the -disjunction of all such string table entries. - -[keywords]: grammar.html#keywords - -When such a string enclosed in double-quotes (`"`) occurs inside the grammar, -it is an implicit reference to a single member of such a string table -production. See [tokens](#tokens) for more information. - -# Lexical structure - -## Input format - -Rust input is interpreted as a sequence of Unicode code points encoded in UTF-8. -Most Rust grammar rules are defined in terms of printable ASCII-range -code points, but a small number are defined in terms of Unicode properties or -explicit code point lists. [^inputformat] - -[^inputformat]: Substitute definitions for the special Unicode productions are - provided to the grammar verifier, restricted to ASCII range, when verifying the - grammar in this document. - -## Identifiers - -An identifier is any nonempty Unicode[^non_ascii_idents] string of the following form: - -[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature - gated. This is expected to improve soon. - -Either - - * The first character has property `XID_start` - * The remaining characters have property `XID_continue` - -Or - - * The first character is `_` - * The identifier is more than one character, `_` alone is not an identifier - * The remaining characters have property `XID_continue` - -that does _not_ occur in the set of [keywords][keywords]. - -> **Note**: `XID_start` and `XID_continue` as character properties cover the -> character ranges used to form the more familiar C and Java language-family -> identifiers. - -## Comments - -Comments in Rust code follow the general C++ style of line (`//`) and -block (`/* ... */`) comment forms. Nested block comments are supported. - -Line comments beginning with exactly _three_ slashes (`///`), and block -comments (`/** ... */`), are interpreted as a special syntax for `doc` -[attributes](#attributes). That is, they are equivalent to writing -`#[doc="..."]` around the body of the comment, i.e., `/// Foo` turns into -`#[doc="Foo"]`. - -Line comments beginning with `//!` and block comments `/*! ... */` are -doc comments that apply to the parent of the comment, rather than the item -that follows. That is, they are equivalent to writing `#![doc="..."]` around -the body of the comment. `//!` comments are usually used to document -modules that occupy a source file. - -Non-doc comments are interpreted as a form of whitespace. - -## Whitespace - -Whitespace is any non-empty string containing only characters that have the -`Pattern_White_Space` Unicode property, namely: - -- `U+0009` (horizontal tab, `'\t'`) -- `U+000A` (line feed, `'\n'`) -- `U+000B` (vertical tab) -- `U+000C` (form feed) -- `U+000D` (carriage return, `'\r'`) -- `U+0020` (space, `' '`) -- `U+0085` (next line) -- `U+200E` (left-to-right mark) -- `U+200F` (right-to-left mark) -- `U+2028` (line separator) -- `U+2029` (paragraph separator) - -Rust is a "free-form" language, meaning that all forms of whitespace serve only -to separate _tokens_ in the grammar, and have no semantic significance. - -A Rust program has identical meaning if each whitespace element is replaced -with any other legal whitespace element, such as a single space character. - -## Tokens - -Tokens are primitive productions in the grammar defined by regular -(non-recursive) languages. "Simple" tokens are given in [string table -production](#string-table-productions) form, and occur in the rest of the -grammar as double-quoted strings. Other tokens have exact rules given. - -### Literals - -A literal is an expression consisting of a single token, rather than a sequence -of tokens, that immediately and directly denotes the value it evaluates to, -rather than referring to it by name or some other evaluation rule. A literal is -a form of constant expression, so is evaluated (primarily) at compile time. - -#### Examples - -##### Characters and strings - -| | Example | `#` sets | Characters | Escapes | -|----------------------------------------------|-----------------|------------|-------------|---------------------| -| [Character](#character-literals) | `'H'` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | -| [String](#string-literals) | `"hello"` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | -| [Raw](#raw-string-literals) | `r#"hello"#` | `0...` | All Unicode | `N/A` | -| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | `0...` | All ASCII | `N/A` | - -##### Byte escapes - -| | Name | -|---|------| -| `\x7F` | 8-bit character code (exactly 2 digits) | -| `\n` | Newline | -| `\r` | Carriage return | -| `\t` | Tab | -| `\\` | Backslash | -| `\0` | Null | - -##### Unicode escapes -| | Name | -|---|------| -| `\u{7FFF}` | 24-bit Unicode character code (up to 6 digits) | - -##### Quote escapes -| | Name | -|---|------| -| `\'` | Single quote | -| `\"` | Double quote | - -##### Numbers - -| [Number literals](#number-literals)`*` | Example | Exponentiation | Suffixes | -|----------------------------------------|---------|----------------|----------| -| Decimal integer | `98_222` | `N/A` | Integer suffixes | -| Hex integer | `0xff` | `N/A` | Integer suffixes | -| Octal integer | `0o77` | `N/A` | Integer suffixes | -| Binary integer | `0b1111_0000` | `N/A` | Integer suffixes | -| Floating-point | `123.0E+77` | `Optional` | Floating-point suffixes | - -`*` All number literals allow `_` as a visual separator: `1_234.0E+18f64` - -##### Suffixes -| Integer | Floating-point | -|---------|----------------| -| `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `isize`, `usize` | `f32`, `f64` | - -#### Character and string literals - -##### Character literals - -A _character literal_ is a single Unicode character enclosed within two -`U+0027` (single-quote) characters, with the exception of `U+0027` itself, -which must be _escaped_ by a preceding `U+005C` character (`\`). - -##### String literals - -A _string literal_ is a sequence of any Unicode characters enclosed within two -`U+0022` (double-quote) characters, with the exception of `U+0022` itself, -which must be _escaped_ by a preceding `U+005C` character (`\`). - -Line-break characters are allowed in string literals. Normally they represent -themselves (i.e. no translation), but as a special exception, when an unescaped -`U+005C` character (`\`) occurs immediately before the newline (`U+000A`), the -`U+005C` character, the newline, and all whitespace at the beginning of the -next line are ignored. Thus `a` and `b` are equal: - -```rust -let a = "foobar"; -let b = "foo\ - bar"; - -assert_eq!(a,b); -``` - -##### Character escapes - -Some additional _escapes_ are available in either character or non-raw string -literals. An escape starts with a `U+005C` (`\`) and continues with one of the -following forms: - -* An _8-bit code point escape_ starts with `U+0078` (`x`) and is - followed by exactly two _hex digits_. It denotes the Unicode code point - equal to the provided hex value. -* A _24-bit code point escape_ starts with `U+0075` (`u`) and is followed - by up to six _hex digits_ surrounded by braces `U+007B` (`{`) and `U+007D` - (`}`). It denotes the Unicode code point equal to the provided hex value. -* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072` - (`r`), or `U+0074` (`t`), denoting the Unicode values `U+000A` (LF), - `U+000D` (CR) or `U+0009` (HT) respectively. -* The _null escape_ is the character `U+0030` (`0`) and denotes the Unicode - value `U+0000` (NUL). -* The _backslash escape_ is the character `U+005C` (`\`) which must be - escaped in order to denote *itself*. - -##### Raw string literals - -Raw string literals do not process any escapes. They start with the character -`U+0072` (`r`), followed by zero or more of the character `U+0023` (`#`) and a -`U+0022` (double-quote) character. The _raw string body_ can contain any sequence -of Unicode characters and is terminated only by another `U+0022` (double-quote) -character, followed by the same number of `U+0023` (`#`) characters that preceded -the opening `U+0022` (double-quote) character. - -All Unicode characters contained in the raw string body represent themselves, -the characters `U+0022` (double-quote) (except when followed by at least as -many `U+0023` (`#`) characters as were used to start the raw string literal) or -`U+005C` (`\`) do not have any special meaning. - -Examples for string literals: - -``` -"foo"; r"foo"; // foo -"\"foo\""; r#""foo""#; // "foo" - -"foo #\"# bar"; -r##"foo #"# bar"##; // foo #"# bar - -"\x52"; "R"; r"R"; // R -"\\x52"; r"\x52"; // \x52 -``` - -#### Byte and byte string literals - -##### Byte literals - -A _byte literal_ is a single ASCII character (in the `U+0000` to `U+007F` -range) or a single _escape_ preceded by the characters `U+0062` (`b`) and -`U+0027` (single-quote), and followed by the character `U+0027`. If the character -`U+0027` is present within the literal, it must be _escaped_ by a preceding -`U+005C` (`\`) character. It is equivalent to a `u8` unsigned 8-bit integer -_number literal_. - -##### Byte string literals - -A non-raw _byte string literal_ is a sequence of ASCII characters and _escapes_, -preceded by the characters `U+0062` (`b`) and `U+0022` (double-quote), and -followed by the character `U+0022`. If the character `U+0022` is present within -the literal, it must be _escaped_ by a preceding `U+005C` (`\`) character. -Alternatively, a byte string literal can be a _raw byte string literal_, defined -below. A byte string literal of length `n` is equivalent to a `&'static [u8; n]` borrowed fixed-sized array -of unsigned 8-bit integers. - -Some additional _escapes_ are available in either byte or non-raw byte string -literals. An escape starts with a `U+005C` (`\`) and continues with one of the -following forms: - -* A _byte escape_ escape starts with `U+0078` (`x`) and is - followed by exactly two _hex digits_. It denotes the byte - equal to the provided hex value. -* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072` - (`r`), or `U+0074` (`t`), denoting the bytes values `0x0A` (ASCII LF), - `0x0D` (ASCII CR) or `0x09` (ASCII HT) respectively. -* The _null escape_ is the character `U+0030` (`0`) and denotes the byte - value `0x00` (ASCII NUL). -* The _backslash escape_ is the character `U+005C` (`\`) which must be - escaped in order to denote its ASCII encoding `0x5C`. - -##### Raw byte string literals - -Raw byte string literals do not process any escapes. They start with the -character `U+0062` (`b`), followed by `U+0072` (`r`), followed by zero or more -of the character `U+0023` (`#`), and a `U+0022` (double-quote) character. The -_raw string body_ can contain any sequence of ASCII characters and is terminated -only by another `U+0022` (double-quote) character, followed by the same number of -`U+0023` (`#`) characters that preceded the opening `U+0022` (double-quote) -character. A raw byte string literal can not contain any non-ASCII byte. - -All characters contained in the raw string body represent their ASCII encoding, -the characters `U+0022` (double-quote) (except when followed by at least as -many `U+0023` (`#`) characters as were used to start the raw string literal) or -`U+005C` (`\`) do not have any special meaning. - -Examples for byte string literals: - -``` -b"foo"; br"foo"; // foo -b"\"foo\""; br#""foo""#; // "foo" - -b"foo #\"# bar"; -br##"foo #"# bar"##; // foo #"# bar - -b"\x52"; b"R"; br"R"; // R -b"\\x52"; br"\x52"; // \x52 -``` - -#### Number literals - -A _number literal_ is either an _integer literal_ or a _floating-point -literal_. The grammar for recognizing the two kinds of literals is mixed. - -##### Integer literals - -An _integer literal_ has one of four forms: - -* A _decimal literal_ starts with a *decimal digit* and continues with any - mixture of *decimal digits* and _underscores_. -* A _hex literal_ starts with the character sequence `U+0030` `U+0078` - (`0x`) and continues as any mixture of hex digits and underscores. -* An _octal literal_ starts with the character sequence `U+0030` `U+006F` - (`0o`) and continues as any mixture of octal digits and underscores. -* A _binary literal_ starts with the character sequence `U+0030` `U+0062` - (`0b`) and continues as any mixture of binary digits and underscores. - -Like any literal, an integer literal may be followed (immediately, -without any spaces) by an _integer suffix_, which forcibly sets the -type of the literal. The integer suffix must be the name of one of the -integral types: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, -`isize`, or `usize`. - -The type of an _unsuffixed_ integer literal is determined by type inference: - -* If an integer type can be _uniquely_ determined from the surrounding - program context, the unsuffixed integer literal has that type. - -* If the program context under-constrains the type, it defaults to the - signed 32-bit integer `i32`. - -* If the program context over-constrains the type, it is considered a - static type error. - -Examples of integer literals of various forms: - -``` -123i32; // type i32 -123u32; // type u32 -123_u32; // type u32 -0xff_u8; // type u8 -0o70_i16; // type i16 -0b1111_1111_1001_0000_i32; // type i32 -0usize; // type usize -``` - -Note that the Rust syntax considers `-1i8` as an application of the [unary minus -operator](#unary-operator-expressions) to an integer literal `1i8`, rather than -a single integer literal. - -##### Floating-point literals - -A _floating-point literal_ has one of two forms: - -* A _decimal literal_ followed by a period character `U+002E` (`.`). This is - optionally followed by another decimal literal, with an optional _exponent_. -* A single _decimal literal_ followed by an _exponent_. - -Like integer literals, a floating-point literal may be followed by a -suffix, so long as the pre-suffix part does not end with `U+002E` (`.`). -The suffix forcibly sets the type of the literal. There are two valid -_floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point -types), which explicitly determine the type of the literal. - -The type of an _unsuffixed_ floating-point literal is determined by -type inference: - -* If a floating-point type can be _uniquely_ determined from the - surrounding program context, the unsuffixed floating-point literal - has that type. - -* If the program context under-constrains the type, it defaults to `f64`. - -* If the program context over-constrains the type, it is considered a - static type error. - -Examples of floating-point literals of various forms: - -``` -123.0f64; // type f64 -0.1f64; // type f64 -0.1f32; // type f32 -12E+99_f64; // type f64 -let x: f64 = 2.; // type f64 -``` - -This last example is different because it is not possible to use the suffix -syntax with a floating point literal ending in a period. `2.f64` would attempt -to call a method named `f64` on `2`. - -The representation semantics of floating-point numbers are described in -["Machine Types"](#machine-types). - -#### Boolean literals - -The two values of the boolean type are written `true` and `false`. - -### Symbols - -Symbols are a general class of printable [tokens](#tokens) that play structural -roles in a variety of grammar productions. They are a -set of remaining miscellaneous printable tokens that do not -otherwise appear as [unary operators](#unary-operator-expressions), [binary -operators](#binary-operator-expressions), or [keywords][keywords]. -They are catalogued in [the Symbols section][symbols] of the Grammar document. - -[symbols]: grammar.html#symbols - - -## Paths - -A _path_ is a sequence of one or more path components _logically_ separated by -a namespace qualifier (`::`). If a path consists of only one component, it may -refer to either an [item](#items) or a [variable](#variables) in a local control -scope. If a path has multiple components, it refers to an item. - -Every item has a _canonical path_ within its crate, but the path naming an item -is only meaningful within a given crate. There is no global namespace across -crates; an item's canonical path merely identifies it within the crate. - -Two examples of simple paths consisting of only identifier components: - -```{.ignore} -x; -x::y::z; -``` - -Path components are usually [identifiers](#identifiers), but they may -also include angle-bracket-enclosed lists of type arguments. In -[expression](#expressions) context, the type argument list is given -after a `::` namespace qualifier in order to disambiguate it from a -relational expression involving the less-than symbol (`<`). In type -expression context, the final namespace qualifier is omitted. - -Two examples of paths with type arguments: - -``` -# struct HashMap(K,V); -# fn f() { -# fn id(t: T) -> T { t } -type T = HashMap; // Type arguments used in a type expression -let x = id::(10); // Type arguments used in a call expression -# } -``` - -Paths can be denoted with various leading qualifiers to change the meaning of -how it is resolved: - -* Paths starting with `::` are considered to be global paths where the - components of the path start being resolved from the crate root. Each - identifier in the path must resolve to an item. - -```rust -mod a { - pub fn foo() {} -} -mod b { - pub fn foo() { - ::a::foo(); // call a's foo function - } -} -# fn main() {} -``` - -* Paths starting with the keyword `super` begin resolution relative to the - parent module. Each further identifier must resolve to an item. - -```rust -mod a { - pub fn foo() {} -} -mod b { - pub fn foo() { - super::a::foo(); // call a's foo function - } -} -# fn main() {} -``` - -* Paths starting with the keyword `self` begin resolution relative to the - current module. Each further identifier must resolve to an item. - -```rust -fn foo() {} -fn bar() { - self::foo(); -} -# fn main() {} -``` - -Additionally keyword `super` may be repeated several times after the first -`super` or `self` to refer to ancestor modules. - -```rust -mod a { - fn foo() {} - - mod b { - mod c { - fn foo() { - super::super::foo(); // call a's foo function - self::super::super::foo(); // call a's foo function - } - } - } -} -# fn main() {} -``` - -# Macros - -A number of minor features of Rust are not central enough to have their own -syntax, and yet are not implementable as functions. Instead, they are given -names, and invoked through a consistent syntax: `some_extension!(...)`. - -Users of `rustc` can define new macros in two ways: - -* [Macros](book/macros.html) define new syntax in a higher-level, - declarative way. -* [Procedural Macros][procedural macros] can be used to implement custom derive. - -And one unstable way: [compiler plugins][plugin]. - -## Macros - -`macro_rules` allows users to define syntax extension in a declarative way. We -call such extensions "macros by example" or simply "macros". - -Currently, macros can expand to expressions, statements, items, or patterns. - -(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is -any token other than a delimiter or `$`.) - -The macro expander looks up macro invocations by name, and tries each macro -rule in turn. It transcribes the first successful match. Matching and -transcription are closely related to each other, and we will describe them -together. - -### Macro By Example - -The macro expander matches and transcribes every token that does not begin with -a `$` literally, including delimiters. For parsing reasons, delimiters must be -balanced, but they are otherwise not special. - -In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust -syntax named by _designator_. Valid designators are: - -* `item`: an [item](#items) -* `block`: a [block](#block-expressions) -* `stmt`: a [statement](#statements) -* `pat`: a [pattern](#match-expressions) -* `expr`: an [expression](#expressions) -* `ty`: a [type](#types) -* `ident`: an [identifier](#identifiers) -* `path`: a [path](#paths) -* `tt`: a token tree (a single [token](#tokens) or a sequence of token trees surrounded - by matching `()`, `[]`, or `{}`) -* `meta`: the contents of an [attribute](#attributes) - -In the transcriber, the -designator is already known, and so only the name of a matched nonterminal comes -after the dollar sign. - -In both the matcher and transcriber, the Kleene star-like operator indicates -repetition. The Kleene star operator consists of `$` and parentheses, optionally -followed by a separator token, followed by `*` or `+`. `*` means zero or more -repetitions, `+` means at least one repetition. The parentheses are not matched or -transcribed. On the matcher side, a name is bound to _all_ of the names it -matches, in a structure that mimics the structure of the repetition encountered -on a successful match. The job of the transcriber is to sort that structure -out. - -The rules for transcription of these repetitions are called "Macro By Example". -Essentially, one "layer" of repetition is discharged at a time, and all of them -must be discharged by the time a name is transcribed. Therefore, `( $( $i:ident -),* ) => ( $i )` is an invalid macro, but `( $( $i:ident ),* ) => ( $( $i:ident -),* )` is acceptable (if trivial). - -When Macro By Example encounters a repetition, it examines all of the `$` -_name_ s that occur in its body. At the "current layer", they all must repeat -the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $( -($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not -`(a,b,c ; d,e)`. The repetition walks through the choices at that layer in -lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`. - -Nested repetitions are allowed. - -### Parsing limitations - -The parser used by the macro system is reasonably powerful, but the parsing of -Rust syntax is restricted in two ways: - -1. Macro definitions are required to include suitable separators after parsing - expressions and other bits of the Rust grammar. This implies that - a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part - of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal, - however, because `,` and `;` are legal separators. See [RFC 550] for more information. -2. The parser must have eliminated all ambiguity by the time it reaches a `$` - _name_ `:` _designator_. This requirement most often affects name-designator - pairs when they occur at the beginning of, or immediately after, a `$(...)*`; - requiring a distinctive token in front can solve the problem. - -[RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md - -## Procedural Macros - -"Procedural macros" are the second way to implement a macro. For now, the only -thing they can be used for is to implement derive on your own types. See -[the book][procedural macros] for a tutorial. - -Procedural macros involve a few different parts of the language and its -standard libraries. First is the `proc_macro` crate, included with Rust, -that defines an interface for building a procedural macro. The -`#[proc_macro_derive(Foo)]` attribute is used to mark the deriving -function. This function must have the type signature: - -```rust,ignore -use proc_macro::TokenStream; - -#[proc_macro_derive(Hello)] -pub fn hello_world(input: TokenStream) -> TokenStream -``` - -Finally, procedural macros must be in their own crate, with the `proc-macro` -crate type. - -# Crates and source files - -Although Rust, like any other language, can be implemented by an interpreter as -well as a compiler, the only existing implementation is a compiler, -and the language has -always been designed to be compiled. For these reasons, this section assumes a -compiler. - -Rust's semantics obey a *phase distinction* between compile-time and -run-time.[^phase-distinction] Semantic rules that have a *static -interpretation* govern the success or failure of compilation, while -semantic rules -that have a *dynamic interpretation* govern the behavior of the program at -run-time. - -[^phase-distinction]: This distinction would also exist in an interpreter. - Static checks like syntactic analysis, type checking, and lints should - happen before the program is executed regardless of when it is executed. - -The compilation model centers on artifacts called _crates_. Each compilation -processes a single crate in source form, and if successful, produces a single -crate in binary form: either an executable or some sort of -library.[^cratesourcefile] - -[^cratesourcefile]: A crate is somewhat analogous to an *assembly* in the - ECMA-335 CLI model, a *library* in the SML/NJ Compilation Manager, a *unit* - in the Owens and Flatt module system, or a *configuration* in Mesa. - -A _crate_ is a unit of compilation and linking, as well as versioning, -distribution and runtime loading. A crate contains a _tree_ of nested -[module](#modules) scopes. The top level of this tree is a module that is -anonymous (from the point of view of paths within the module) and any item -within a crate has a canonical [module path](#paths) denoting its location -within the crate's module tree. - -The Rust compiler is always invoked with a single source file as input, and -always produces a single output crate. The processing of that source file may -result in other source files being loaded as modules. Source files have the -extension `.rs`. - -A Rust source file describes a module, the name and location of which — -in the module tree of the current crate — are defined from outside the -source file: either by an explicit `mod_item` in a referencing source file, or -by the name of the crate itself. Every source file is a module, but not every -module needs its own source file: [module definitions](#modules) can be nested -within one file. - -Each source file contains a sequence of zero or more `item` definitions, and -may optionally begin with any number of [attributes](#items-and-attributes) -that apply to the containing module, most of which influence the behavior of -the compiler. The anonymous crate module can have additional attributes that -apply to the crate as a whole. - -```no_run -// Specify the crate name. -#![crate_name = "projx"] - -// Specify the type of output artifact. -#![crate_type = "lib"] - -// Turn on a warning. -// This can be done in any module, not just the anonymous crate module. -#![warn(non_camel_case_types)] -``` - -A crate that contains a `main` function can be compiled to an executable. If a -`main` function is present, its return type must be `()` -("[unit](#tuple-types)") and it must take no arguments. - -# Items and attributes - -Crates contain [items](#items), each of which may have some number of -[attributes](#attributes) attached to it. - -## Items - -An _item_ is a component of a crate. Items are organized within a crate by a -nested set of [modules](#modules). Every crate has a single "outermost" -anonymous module; all further items within the crate have [paths](#paths) -within the module tree of the crate. - -Items are entirely determined at compile-time, generally remain fixed during -execution, and may reside in read-only memory. - -There are several kinds of item: - -* [`extern crate` declarations](#extern-crate-declarations) -* [`use` declarations](#use-declarations) -* [modules](#modules) -* [function definitions](#functions) -* [`extern` blocks](#external-blocks) -* [type definitions](grammar.html#type-definitions) -* [struct definitions](#structs) -* [enumeration definitions](#enumerations) -* [constant items](#constant-items) -* [static items](#static-items) -* [trait definitions](#traits) -* [implementations](#implementations) - -Some items form an implicit scope for the declaration of sub-items. In other -words, within a function or module, declarations of items can (in many cases) -be mixed with the statements, control blocks, and similar artifacts that -otherwise compose the item body. The meaning of these scoped items is the same -as if the item was declared outside the scope — it is still a static item -— except that the item's *path name* within the module namespace is -qualified by the name of the enclosing item, or is private to the enclosing -item (in the case of functions). The grammar specifies the exact locations in -which sub-item declarations may appear. - -### Type Parameters - -All items except modules, constants and statics may be *parameterized* by type. -Type parameters are given as a comma-separated list of identifiers enclosed in -angle brackets (`<...>`), after the name of the item and before its definition. -The type parameters of an item are considered "part of the name", not part of -the type of the item. A referencing [path](#paths) must (in principle) provide -type arguments as a list of comma-separated types enclosed within angle -brackets, in order to refer to the type-parameterized item. In practice, the -type-inference system can usually infer such argument types from context. There -are no general type-parametric types, only type-parametric items. That is, Rust -has no notion of type abstraction: there are no higher-ranked (or "forall") types -abstracted over other types, though higher-ranked types do exist for lifetimes. - -### Modules - -A module is a container for zero or more [items](#items). - -A _module item_ is a module, surrounded in braces, named, and prefixed with the -keyword `mod`. A module item introduces a new, named module into the tree of -modules making up a crate. Modules can nest arbitrarily. - -An example of a module: - -``` -mod math { - type Complex = (f64, f64); - fn sin(f: f64) -> f64 { - /* ... */ -# panic!(); - } - fn cos(f: f64) -> f64 { - /* ... */ -# panic!(); - } - fn tan(f: f64) -> f64 { - /* ... */ -# panic!(); - } -} -``` - -Modules and types share the same namespace. Declaring a named type with -the same name as a module in scope is forbidden: that is, a type definition, -trait, struct, enumeration, or type parameter can't shadow the name of a module -in scope, or vice versa. - -A module without a body is loaded from an external file, by default with the -same name as the module, plus the `.rs` extension. When a nested submodule is -loaded from an external file, it is loaded from a subdirectory path that -mirrors the module hierarchy. - -```{.ignore} -// Load the `vec` module from `vec.rs` -mod vec; - -mod thread { - // Load the `local_data` module from `thread/local_data.rs` - // or `thread/local_data/mod.rs`. - mod local_data; -} -``` - -The directories and files used for loading external file modules can be -influenced with the `path` attribute. - -```{.ignore} -#[path = "thread_files"] -mod thread { - // Load the `local_data` module from `thread_files/tls.rs` - #[path = "tls.rs"] - mod local_data; -} -``` - -#### Extern crate declarations - -An _`extern crate` declaration_ specifies a dependency on an external crate. -The external crate is then bound into the declaring scope as the `ident` -provided in the `extern_crate_decl`. - -The external crate is resolved to a specific `soname` at compile time, and a -runtime linkage requirement to that `soname` is passed to the linker for -loading at runtime. The `soname` is resolved at compile time by scanning the -compiler's library path and matching the optional `crateid` provided against -the `crateid` attributes that were declared on the external crate when it was -compiled. If no `crateid` is provided, a default `name` attribute is assumed, -equal to the `ident` given in the `extern_crate_decl`. - -Three examples of `extern crate` declarations: - -```{.ignore} -extern crate pcre; - -extern crate std; // equivalent to: extern crate std as std; - -extern crate std as ruststd; // linking to 'std' under another name -``` - -When naming Rust crates, hyphens are disallowed. However, Cargo packages may -make use of them. In such case, when `Cargo.toml` doesn't specify a crate name, -Cargo will transparently replace `-` with `_` (Refer to [RFC 940] for more -details). - -Here is an example: - -```{.ignore} -// Importing the Cargo package hello-world -extern crate hello_world; // hyphen replaced with an underscore -``` - -[RFC 940]: https://github.com/rust-lang/rfcs/blob/master/text/0940-hyphens-considered-harmful.md - -#### Use declarations - -A _use declaration_ creates one or more local name bindings synonymous with -some other [path](#paths). Usually a `use` declaration is used to shorten the -path required to refer to a module item. These declarations may appear in -[modules](#modules) and [blocks](grammar.html#block-expressions), usually at the top. - -> **Note**: Unlike in many languages, -> `use` declarations in Rust do *not* declare linkage dependency with external crates. -> Rather, [`extern crate` declarations](#extern-crate-declarations) declare linkage dependencies. - -Use declarations support a number of convenient shortcuts: - -* Rebinding the target name as a new local name, using the syntax `use p::q::r as x;` -* Simultaneously binding a list of paths differing only in their final element, - using the glob-like brace syntax `use a::b::{c,d,e,f};` -* Binding all paths matching a given prefix, using the asterisk wildcard syntax - `use a::b::*;` -* Simultaneously binding a list of paths differing only in their final element - and their immediate parent module, using the `self` keyword, such as - `use a::b::{self, c, d};` - -An example of `use` declarations: - -```rust -use std::option::Option::{Some, None}; -use std::collections::hash_map::{self, HashMap}; - -fn foo(_: T){} -fn bar(map1: HashMap, map2: hash_map::HashMap){} - -fn main() { - // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), - // std::option::Option::None]);' - foo(vec![Some(1.0f64), None]); - - // Both `hash_map` and `HashMap` are in scope. - let map1 = HashMap::new(); - let map2 = hash_map::HashMap::new(); - bar(map1, map2); -} -``` - -Like items, `use` declarations are private to the containing module, by -default. Also like items, a `use` declaration can be public, if qualified by -the `pub` keyword. Such a `use` declaration serves to _re-export_ a name. A -public `use` declaration can therefore _redirect_ some public name to a -different target definition: even a definition with a private canonical path, -inside a different module. If a sequence of such redirections form a cycle or -cannot be resolved unambiguously, they represent a compile-time error. - -An example of re-exporting: - -``` -# fn main() { } -mod quux { - pub use quux::foo::{bar, baz}; - - pub mod foo { - pub fn bar() { } - pub fn baz() { } - } -} -``` - -In this example, the module `quux` re-exports two public names defined in -`foo`. - -Also note that the paths contained in `use` items are relative to the crate -root. So, in the previous example, the `use` refers to `quux::foo::{bar, -baz}`, and not simply to `foo::{bar, baz}`. This also means that top-level -module declarations should be at the crate root if direct usage of the declared -modules within `use` items is desired. It is also possible to use `self` and -`super` at the beginning of a `use` item to refer to the current and direct -parent modules respectively. All rules regarding accessing declared modules in -`use` declarations apply to both module declarations and `extern crate` -declarations. - -An example of what will and will not work for `use` items: - -``` -# #![allow(unused_imports)] -use foo::baz::foobaz; // good: foo is at the root of the crate - -mod foo { - - mod example { - pub mod iter {} - } - - use foo::example::iter; // good: foo is at crate root -// use example::iter; // bad: example is not at the crate root - use self::baz::foobaz; // good: self refers to module 'foo' - use foo::bar::foobar; // good: foo is at crate root - - pub mod bar { - pub fn foobar() { } - } - - pub mod baz { - use super::bar::foobar; // good: super refers to module 'foo' - pub fn foobaz() { } - } -} - -fn main() {} -``` - -### Functions - -A _function item_ defines a sequence of [statements](#statements) and a -final [expression](#expressions), along with a name and a set of -parameters. Other than a name, all these are optional. -Functions are declared with the keyword `fn`. Functions may declare a -set of *input* [*variables*](#variables) as parameters, through which the caller -passes arguments into the function, and the *output* [*type*](#types) -of the value the function will return to its caller on completion. - -A function may also be copied into a first-class *value*, in which case the -value has the corresponding [*function type*](#function-types), and can be used -otherwise exactly as a function item (with a minor additional cost of calling -the function indirectly). - -Every control path in a function logically ends with a `return` expression or a -diverging expression. If the outermost block of a function has a -value-producing expression in its final-expression position, that expression is -interpreted as an implicit `return` expression applied to the final-expression. - -An example of a function: - -``` -fn add(x: i32, y: i32) -> i32 { - x + y -} -``` - -As with `let` bindings, function arguments are irrefutable patterns, so any -pattern that is valid in a let binding is also valid as an argument. - -``` -fn first((value, _): (i32, i32)) -> i32 { value } -``` - - -#### Generic functions - -A _generic function_ allows one or more _parameterized types_ to appear in its -signature. Each type parameter must be explicitly declared in an -angle-bracket-enclosed and comma-separated list, following the function name. - -```rust,ignore -// foo is generic over A and B - -fn foo(x: A, y: B) { -``` - -Inside the function signature and body, the name of the type parameter can be -used as a type name. [Trait](#traits) bounds can be specified for type parameters -to allow methods with that trait to be called on values of that type. This is -specified using the `where` syntax: - -```rust,ignore -fn foo(x: T) where T: Debug { -``` - -When a generic function is referenced, its type is instantiated based on the -context of the reference. For example, calling the `foo` function here: - -``` -use std::fmt::Debug; - -fn foo(x: &[T]) where T: Debug { - // details elided - # () -} - -foo(&[1, 2]); -``` - -will instantiate type parameter `T` with `i32`. - -The type parameters can also be explicitly supplied in a trailing -[path](#paths) component after the function name. This might be necessary if -there is not sufficient context to determine the type parameters. For example, -`mem::size_of::() == 4`. - -#### Diverging functions - -A special kind of function can be declared with a `!` character where the -output type would normally be. For example: - -``` -fn my_err(s: &str) -> ! { - println!("{}", s); - panic!(); -} -``` - -We call such functions "diverging" because they never return a value to the -caller. Every control path in a diverging function must end with a `panic!()` or -a call to another diverging function on every control path. The `!` annotation -does *not* denote a type. - -It might be necessary to declare a diverging function because as mentioned -previously, the typechecker checks that every control path in a function ends -with a [`return`](#return-expressions) or diverging expression. So, if `my_err` -were declared without the `!` annotation, the following code would not -typecheck: - -``` -# fn my_err(s: &str) -> ! { panic!() } - -fn f(i: i32) -> i32 { - if i == 42 { - return 42; - } - else { - my_err("Bad number!"); - } -} -``` - -This will not compile without the `!` annotation on `my_err`, since the `else` -branch of the conditional in `f` does not return an `i32`, as required by the -signature of `f`. Adding the `!` annotation to `my_err` informs the -typechecker that, should control ever enter `my_err`, no further type judgments -about `f` need to hold, since control will never resume in any context that -relies on those judgments. Thus the return type on `f` only needs to reflect -the `if` branch of the conditional. - -#### Extern functions - -Extern functions are part of Rust's foreign function interface, providing the -opposite functionality to [external blocks](#external-blocks). Whereas -external blocks allow Rust code to call foreign code, extern functions with -bodies defined in Rust code _can be called by foreign code_. They are defined -in the same way as any other Rust function, except that they have the `extern` -modifier. - -``` -// Declares an extern fn, the ABI defaults to "C" -extern fn new_i32() -> i32 { 0 } - -// Declares an extern fn with "stdcall" ABI -extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } -``` - -Unlike normal functions, extern fns have type `extern "ABI" fn()`. This is the -same type as the functions declared in an extern block. - -``` -# extern fn new_i32() -> i32 { 0 } -let fptr: extern "C" fn() -> i32 = new_i32; -``` - -Extern functions may be called directly from Rust code as Rust uses large, -contiguous stack segments like C. - -### Type aliases - -A _type alias_ defines a new name for an existing [type](#types). Type -aliases are declared with the keyword `type`. Every value has a single, -specific type, but may implement several different traits, or be compatible with -several different type constraints. - -For example, the following defines the type `Point` as a synonym for the type -`(u8, u8)`, the type of pairs of unsigned 8 bit integers: - -``` -type Point = (u8, u8); -let p: Point = (41, 68); -``` - -Currently a type alias to an enum type cannot be used to qualify the -constructors: - -``` -enum E { A } -type F = E; -let _: F = E::A; // OK -// let _: F = F::A; // Doesn't work -``` - -### Structs - -A _struct_ is a nominal [struct type](#struct-types) defined with the -keyword `struct`. - -An example of a `struct` item and its use: - -``` -struct Point {x: i32, y: i32} -let p = Point {x: 10, y: 11}; -let px: i32 = p.x; -``` - -A _tuple struct_ is a nominal [tuple type](#tuple-types), also defined with -the keyword `struct`. For example: - -``` -struct Point(i32, i32); -let p = Point(10, 11); -let px: i32 = match p { Point(x, _) => x }; -``` - -A _unit-like struct_ is a struct without any fields, defined by leaving off -the list of fields entirely. Such a struct implicitly defines a constant of -its type with the same name. For example: - -``` -struct Cookie; -let c = [Cookie, Cookie {}, Cookie, Cookie {}]; -``` - -is equivalent to - -``` -struct Cookie {} -const Cookie: Cookie = Cookie {}; -let c = [Cookie, Cookie {}, Cookie, Cookie {}]; -``` - -The precise memory layout of a struct is not specified. One can specify a -particular layout using the [`repr` attribute](#ffi-attributes). - -### Enumerations - -An _enumeration_ is a simultaneous definition of a nominal [enumerated -type](#enumerated-types) as well as a set of *constructors*, that can be used -to create or pattern-match values of the corresponding enumerated type. - -Enumerations are declared with the keyword `enum`. - -An example of an `enum` item and its use: - -``` -enum Animal { - Dog, - Cat, -} - -let mut a: Animal = Animal::Dog; -a = Animal::Cat; -``` - -Enumeration constructors can have either named or unnamed fields: - -```rust -enum Animal { - Dog (String, f64), - Cat { name: String, weight: f64 }, -} - -let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2); -a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; -``` - -In this example, `Cat` is a _struct-like enum variant_, -whereas `Dog` is simply called an enum variant. - -Each enum value has a _discriminant_ which is an integer associated to it. You -can specify it explicitly: - -``` -enum Foo { - Bar = 123, -} -``` - -The right hand side of the specification is interpreted as an `isize` value, -but the compiler is allowed to use a smaller type in the actual memory layout. -The [`repr` attribute](#ffi-attributes) can be added in order to change -the type of the right hand side and specify the memory layout. - -If a discriminant isn't specified, they start at zero, and add one for each -variant, in order. - -You can cast an enum to get its discriminant: - -``` -# enum Foo { Bar = 123 } -let x = Foo::Bar as u32; // x is now 123u32 -``` - -This only works as long as none of the variants have data attached. If -it were `Bar(i32)`, this is disallowed. - -### Constant items - -A *constant item* is a named _constant value_ which is not associated with a -specific memory location in the program. Constants are essentially inlined -wherever they are used, meaning that they are copied directly into the relevant -context when used. References to the same constant are not necessarily -guaranteed to refer to the same memory address. - -Constant values must not have destructors, and otherwise permit most forms of -data. Constants may refer to the address of other constants, in which case the -address will have elided lifetimes where applicable, otherwise – in most cases – -defaulting to the `static` lifetime. (See below on [static lifetime elision].) -The compiler is, however, still at liberty to translate the constant many times, -so the address referred to may not be stable. - -[static lifetime elision]: #static-lifetime-elision - -Constants must be explicitly typed. The type may be `bool`, `char`, a number, or -a type derived from those primitive types. The derived types are references with -the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs. - -```rust -const BIT1: u32 = 1 << 0; -const BIT2: u32 = 1 << 1; - -const BITS: [u32; 2] = [BIT1, BIT2]; -const STRING: &'static str = "bitstring"; - -struct BitsNStrings<'a> { - mybits: [u32; 2], - mystring: &'a str, -} - -const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { - mybits: BITS, - mystring: STRING, -}; -``` - - - -### Static items - -A *static item* is similar to a *constant*, except that it represents a precise -memory location in the program. A static is never "inlined" at the usage site, -and all references to it refer to the same memory location. Static items have -the `static` lifetime, which outlives all other lifetimes in a Rust program. -Static items may be placed in read-only memory if they do not contain any -interior mutability. - -Statics may contain interior mutability through the `UnsafeCell` language item. -All access to a static is safe, but there are a number of restrictions on -statics: - -* Statics may not contain any destructors. -* The types of static values must ascribe to `Sync` to allow thread-safe access. -* Statics may not refer to other statics by value, only by reference. -* Constants cannot refer to statics. - -Constants should in general be preferred over statics, unless large amounts of -data are being stored, or single-address and mutability properties are required. - -#### Mutable statics - -If a static item is declared with the `mut` keyword, then it is allowed to -be modified by the program. One of Rust's goals is to make concurrency bugs -hard to run into, and this is obviously a very large source of race conditions -or other bugs. For this reason, an `unsafe` block is required when either -reading or writing a mutable static variable. Care should be taken to ensure -that modifications to a mutable static are safe with respect to other threads -running in the same process. - -Mutable statics are still very useful, however. They can be used with C -libraries and can also be bound from C libraries (in an `extern` block). - -```rust -# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 } - -static mut LEVELS: u32 = 0; - -// This violates the idea of no shared state, and this doesn't internally -// protect against races, so this function is `unsafe` -unsafe fn bump_levels_unsafe1() -> u32 { - let ret = LEVELS; - LEVELS += 1; - return ret; -} - -// Assuming that we have an atomic_add function which returns the old value, -// this function is "safe" but the meaning of the return value may not be what -// callers expect, so it's still marked as `unsafe` -unsafe fn bump_levels_unsafe2() -> u32 { - return atomic_add(&mut LEVELS, 1); -} -``` - -Mutable statics have the same restrictions as normal statics, except that the -type of the value is not required to ascribe to `Sync`. - -#### `'static` lifetime elision - -[Unstable] Both constant and static declarations of reference types have -*implicit* `'static` lifetimes unless an explicit lifetime is specified. As -such, the constant declarations involving `'static` above may be written -without the lifetimes. Returning to our previous example: - -```rust -# #![feature(static_in_const)] -const BIT1: u32 = 1 << 0; -const BIT2: u32 = 1 << 1; - -const BITS: [u32; 2] = [BIT1, BIT2]; -const STRING: &str = "bitstring"; - -struct BitsNStrings<'a> { - mybits: [u32; 2], - mystring: &'a str, -} - -const BITS_N_STRINGS: BitsNStrings = BitsNStrings { - mybits: BITS, - mystring: STRING, -}; -``` - -Note that if the `static` or `const` items include function or closure -references, which themselves include references, the compiler will first try the -standard elision rules ([see discussion in the nomicon][elision-nomicon]). If it -is unable to resolve the lifetimes by its usual rules, it will default to using -the `'static` lifetime. By way of example: - -[elision-nomicon]: https://doc.rust-lang.org/nomicon/lifetime-elision.html - -```rust,ignore -// Resolved as `fn<'a>(&'a str) -> &'a str`. -const RESOLVED_SINGLE: fn(&str) -> &str = .. - -// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`. -const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = .. - -// There is insufficient information to bound the return reference lifetime -// relative to the argument lifetimes, so the signature is resolved as -// `Fn(&'static Foo, &'static Bar) -> &'static Baz`. -const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = .. -``` - -### Traits - -A _trait_ describes an abstract interface that types can -implement. This interface consists of associated items, which come in -three varieties: - -- functions -- constants -- types - -Associated functions whose first parameter is named `self` are called -methods and may be invoked using `.` notation (e.g., `x.foo()`). - -All traits define an implicit type parameter `Self` that refers to -"the type that is implementing this interface". Traits may also -contain additional type parameters. These type parameters (including -`Self`) may be constrained by other traits and so forth as usual. - -Trait bounds on `Self` are considered "supertraits". These are -required to be acyclic. Supertraits are somewhat different from other -constraints in that they affect what methods are available in the -vtable when the trait is used as a [trait object](#trait-objects). - -Traits are implemented for specific types through separate -[implementations](#implementations). - -Consider the following trait: - -``` -# type Surface = i32; -# type BoundingBox = i32; -trait Shape { - fn draw(&self, Surface); - fn bounding_box(&self) -> BoundingBox; -} -``` - -This defines a trait with two methods. All values that have -[implementations](#implementations) of this trait in scope can have their -`draw` and `bounding_box` methods called, using `value.bounding_box()` -[syntax](#method-call-expressions). - -Traits can include default implementations of methods, as in: - -``` -trait Foo { - fn bar(&self); - fn baz(&self) { println!("We called baz."); } -} -``` - -Here the `baz` method has a default implementation, so types that implement -`Foo` need only implement `bar`. It is also possible for implementing types -to override a method that has a default implementation. - -Type parameters can be specified for a trait to make it generic. These appear -after the trait name, using the same syntax used in [generic -functions](#generic-functions). - -``` -trait Seq { - fn len(&self) -> u32; - fn elt_at(&self, n: u32) -> T; - fn iter(&self, F) where F: Fn(T); -} -``` - -It is also possible to define associated types for a trait. Consider the -following example of a `Container` trait. Notice how the type is available -for use in the method signatures: - -``` -trait Container { - type E; - fn empty() -> Self; - fn insert(&mut self, Self::E); -} -``` - -In order for a type to implement this trait, it must not only provide -implementations for every method, but it must specify the type `E`. Here's -an implementation of `Container` for the standard library type `Vec`: - -``` -# trait Container { -# type E; -# fn empty() -> Self; -# fn insert(&mut self, Self::E); -# } -impl Container for Vec { - type E = T; - fn empty() -> Vec { Vec::new() } - fn insert(&mut self, x: T) { self.push(x); } -} -``` - -Generic functions may use traits as _bounds_ on their type parameters. This -will have two effects: - -- Only types that have the trait may instantiate the parameter. -- Within the generic function, the methods of the trait can be - called on values that have the parameter's type. - -For example: - -``` -# type Surface = i32; -# trait Shape { fn draw(&self, Surface); } -fn draw_twice(surface: Surface, sh: T) { - sh.draw(surface); - sh.draw(surface); -} -``` - -Traits also define a [trait object](#trait-objects) with the same -name as the trait. Values of this type are created by coercing from a -pointer of some specific type to a pointer of trait type. For example, -`&T` could be coerced to `&Shape` if `T: Shape` holds (and similarly -for `Box`). This coercion can either be implicit or -[explicit](#type-cast-expressions). Here is an example of an explicit -coercion: - -``` -trait Shape { } -impl Shape for i32 { } -let mycircle = 0i32; -let myshape: Box = Box::new(mycircle) as Box; -``` - -The resulting value is a box containing the value that was cast, along with -information that identifies the methods of the implementation that was used. -Values with a trait type can have [methods called](#method-call-expressions) on -them, for any method in the trait, and can be used to instantiate type -parameters that are bounded by the trait. - -Trait methods may be static, which means that they lack a `self` argument. -This means that they can only be called with function call syntax (`f(x)`) and -not method call syntax (`obj.f()`). The way to refer to the name of a static -method is to qualify it with the trait name, treating the trait name like a -module. For example: - -``` -trait Num { - fn from_i32(n: i32) -> Self; -} -impl Num for f64 { - fn from_i32(n: i32) -> f64 { n as f64 } -} -let x: f64 = Num::from_i32(42); -``` - -Traits may inherit from other traits. Consider the following example: - -``` -trait Shape { fn area(&self) -> f64; } -trait Circle : Shape { fn radius(&self) -> f64; } -``` - -The syntax `Circle : Shape` means that types that implement `Circle` must also -have an implementation for `Shape`. Multiple supertraits are separated by `+`, -`trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a -given type `T`, methods can refer to `Shape` methods, since the typechecker -checks that any type with an implementation of `Circle` also has an -implementation of `Shape`: - -```rust -struct Foo; - -trait Shape { fn area(&self) -> f64; } -trait Circle : Shape { fn radius(&self) -> f64; } -impl Shape for Foo { - fn area(&self) -> f64 { - 0.0 - } -} -impl Circle for Foo { - fn radius(&self) -> f64 { - println!("calling area: {}", self.area()); - - 0.0 - } -} - -let c = Foo; -c.radius(); -``` - -In type-parameterized functions, methods of the supertrait may be called on -values of subtrait-bound type parameters. Referring to the previous example of -`trait Circle : Shape`: - -``` -# trait Shape { fn area(&self) -> f64; } -# trait Circle : Shape { fn radius(&self) -> f64; } -fn radius_times_area(c: T) -> f64 { - // `c` is both a Circle and a Shape - c.radius() * c.area() -} -``` - -Likewise, supertrait methods may also be called on trait objects. - -```{.ignore} -# trait Shape { fn area(&self) -> f64; } -# trait Circle : Shape { fn radius(&self) -> f64; } -# impl Shape for i32 { fn area(&self) -> f64 { 0.0 } } -# impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } } -# let mycircle = 0i32; -let mycircle = Box::new(mycircle) as Box; -let nonsense = mycircle.radius() * mycircle.area(); -``` - -### Implementations - -An _implementation_ is an item that implements a [trait](#traits) for a -specific type. - -Implementations are defined with the keyword `impl`. - -``` -# #[derive(Copy, Clone)] -# struct Point {x: f64, y: f64}; -# type Surface = i32; -# struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; -# trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } -# fn do_draw_circle(s: Surface, c: Circle) { } -struct Circle { - radius: f64, - center: Point, -} - -impl Copy for Circle {} - -impl Clone for Circle { - fn clone(&self) -> Circle { *self } -} - -impl Shape for Circle { - fn draw(&self, s: Surface) { do_draw_circle(s, *self); } - fn bounding_box(&self) -> BoundingBox { - let r = self.radius; - BoundingBox { - x: self.center.x - r, - y: self.center.y - r, - width: 2.0 * r, - height: 2.0 * r, - } - } -} -``` - -It is possible to define an implementation without referring to a trait. The -methods in such an implementation can only be used as direct calls on the values -of the type that the implementation targets. In such an implementation, the -trait type and `for` after `impl` are omitted. Such implementations are limited -to nominal types (enums, structs, trait objects), and the implementation must -appear in the same crate as the `self` type: - -``` -struct Point {x: i32, y: i32} - -impl Point { - fn log(&self) { - println!("Point is at ({}, {})", self.x, self.y); - } -} - -let my_point = Point {x: 10, y:11}; -my_point.log(); -``` - -When a trait _is_ specified in an `impl`, all methods declared as part of the -trait must be implemented, with matching types and type parameter counts. - -An implementation can take type parameters, which can be different from the -type parameters taken by the trait it implements. Implementation parameters -are written after the `impl` keyword. - -``` -# trait Seq { fn dummy(&self, _: T) { } } -impl Seq for Vec { - /* ... */ -} -impl Seq for u32 { - /* Treat the integer as a sequence of bits */ -} -``` - -### External blocks - -External blocks form the basis for Rust's foreign function interface. -Declarations in an external block describe symbols in external, non-Rust -libraries. - -Functions within external blocks are declared in the same way as other Rust -functions, with the exception that they may not have a body and are instead -terminated by a semicolon. - -Functions within external blocks may be called by Rust code, just like -functions defined in Rust. The Rust compiler automatically translates between -the Rust ABI and the foreign ABI. - -Functions within external blocks may be variadic by specifying `...` after one -or more named arguments in the argument list: - -```ignore -extern { - fn foo(x: i32, ...); -} -``` - -A number of [attributes](#ffi-attributes) control the behavior of external blocks. - -By default external blocks assume that the library they are calling uses the -standard C ABI on the specific platform. Other ABIs may be specified using an -`abi` string, as shown here: - -```ignore -// Interface to the Windows API -extern "stdcall" { } -``` - -There are three ABI strings which are cross-platform, and which all compilers -are guaranteed to support: - -* `extern "Rust"` -- The default ABI when you write a normal `fn foo()` in any - Rust code. -* `extern "C"` -- This is the same as `extern fn foo()`; whatever the default - your C compiler supports. -* `extern "system"` -- Usually the same as `extern "C"`, except on Win32, in - which case it's `"stdcall"`, or what you should use to link to the Windows API - itself - -There are also some platform-specific ABI strings: - -* `extern "cdecl"` -- The default for x86\_32 C code. -* `extern "stdcall"` -- The default for the Win32 API on x86\_32. -* `extern "win64"` -- The default for C code on x86\_64 Windows. -* `extern "sysv64"` -- The default for C code on non-Windows x86\_64. -* `extern "aapcs"` -- The default for ARM. -* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's - `__fastcall` and GCC and clang's `__attribute__((fastcall))` -* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's - `__vectorcall` and clang's `__attribute__((vectorcall))` - -Finally, there are some rustc-specific ABI strings: - -* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics. -* `extern "rust-call"` -- The ABI of the Fn::call trait functions. -* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for - example, `sqrt` -- have this ABI. You should never have to deal with it. - -The `link` attribute allows the name of the library to be specified. When -specified the compiler will attempt to link against the native library of the -specified name. - -```{.ignore} -#[link(name = "crypto")] -extern { } -``` - -The type of a function declared in an extern block is `extern "abi" fn(A1, ..., -An) -> R`, where `A1...An` are the declared types of its arguments and `R` is -the declared return type. - -It is valid to add the `link` attribute on an empty extern block. You can use -this to satisfy the linking requirements of extern blocks elsewhere in your code -(including upstream crates) instead of adding the attribute to each extern block. - -## Visibility and Privacy - -These two terms are often used interchangeably, and what they are attempting to -convey is the answer to the question "Can this item be used at this location?" - -Rust's name resolution operates on a global hierarchy of namespaces. Each level -in the hierarchy can be thought of as some item. The items are one of those -mentioned above, but also include external crates. Declaring or defining a new -module can be thought of as inserting a new tree into the hierarchy at the -location of the definition. - -To control whether interfaces can be used across modules, Rust checks each use -of an item to see whether it should be allowed or not. This is where privacy -warnings are generated, or otherwise "you used a private item of another module -and weren't allowed to." - -By default, everything in Rust is *private*, with two exceptions: Associated -items in a `pub` Trait are public by default; Enum variants -in a `pub` enum are also public by default. When an item is declared as `pub`, -it can be thought of as being accessible to the outside world. For example: - -``` -# fn main() {} -// Declare a private struct -struct Foo; - -// Declare a public struct with a private field -pub struct Bar { - field: i32, -} - -// Declare a public enum with two public variants -pub enum State { - PubliclyAccessibleState, - PubliclyAccessibleState2, -} -``` - -With the notion of an item being either public or private, Rust allows item -accesses in two cases: - -1. If an item is public, then it can be used externally through any of its - public ancestors. -2. If an item is private, it may be accessed by the current module and its - descendants. - -These two cases are surprisingly powerful for creating module hierarchies -exposing public APIs while hiding internal implementation details. To help -explain, here's a few use cases and what they would entail: - -* A library developer needs to expose functionality to crates which link - against their library. As a consequence of the first case, this means that - anything which is usable externally must be `pub` from the root down to the - destination item. Any private item in the chain will disallow external - accesses. - -* A crate needs a global available "helper module" to itself, but it doesn't - want to expose the helper module as a public API. To accomplish this, the - root of the crate's hierarchy would have a private module which then - internally has a "public API". Because the entire crate is a descendant of - the root, then the entire local crate can access this private module through - the second case. - -* When writing unit tests for a module, it's often a common idiom to have an - immediate child of the module to-be-tested named `mod test`. This module - could access any items of the parent module through the second case, meaning - that internal implementation details could also be seamlessly tested from the - child module. - -In the second case, it mentions that a private item "can be accessed" by the -current module and its descendants, but the exact meaning of accessing an item -depends on what the item is. Accessing a module, for example, would mean -looking inside of it (to import more items). On the other hand, accessing a -function would mean that it is invoked. Additionally, path expressions and -import statements are considered to access an item in the sense that the -import/expression is only valid if the destination is in the current visibility -scope. - -Here's an example of a program which exemplifies the three cases outlined -above: - -``` -// This module is private, meaning that no external crate can access this -// module. Because it is private at the root of this current crate, however, any -// module in the crate may access any publicly visible item in this module. -mod crate_helper_module { - - // This function can be used by anything in the current crate - pub fn crate_helper() {} - - // This function *cannot* be used by anything else in the crate. It is not - // publicly visible outside of the `crate_helper_module`, so only this - // current module and its descendants may access it. - fn implementation_detail() {} -} - -// This function is "public to the root" meaning that it's available to external -// crates linking against this one. -pub fn public_api() {} - -// Similarly to 'public_api', this module is public so external crates may look -// inside of it. -pub mod submodule { - use crate_helper_module; - - pub fn my_method() { - // Any item in the local crate may invoke the helper module's public - // interface through a combination of the two rules above. - crate_helper_module::crate_helper(); - } - - // This function is hidden to any module which is not a descendant of - // `submodule` - fn my_implementation() {} - - #[cfg(test)] - mod test { - - #[test] - fn test_my_implementation() { - // Because this module is a descendant of `submodule`, it's allowed - // to access private items inside of `submodule` without a privacy - // violation. - super::my_implementation(); - } - } -} - -# fn main() {} -``` - -For a Rust program to pass the privacy checking pass, all paths must be valid -accesses given the two rules above. This includes all use statements, -expressions, types, etc. - -### Re-exporting and Visibility - -Rust allows publicly re-exporting items through a `pub use` directive. Because -this is a public directive, this allows the item to be used in the current -module through the rules above. It essentially allows public access into the -re-exported item. For example, this program is valid: - -``` -pub use self::implementation::api; - -mod implementation { - pub mod api { - pub fn f() {} - } -} - -# fn main() {} -``` - -This means that any external crate referencing `implementation::api::f` would -receive a privacy violation, while the path `api::f` would be allowed. - -When re-exporting a private item, it can be thought of as allowing the "privacy -chain" being short-circuited through the reexport instead of passing through -the namespace hierarchy as it normally would. - -## Attributes - -Any item declaration may have an _attribute_ applied to it. Attributes in Rust -are modeled on Attributes in ECMA-335, with the syntax coming from ECMA-334 -(C#). An attribute is a general, free-form metadatum that is interpreted -according to name, convention, and language and compiler version. Attributes -may appear as any of: - -* A single identifier, the attribute name -* An identifier followed by the equals sign '=' and a literal, providing a - key/value pair -* An identifier followed by a parenthesized list of sub-attribute arguments - -Attributes with a bang ("!") after the hash ("#") apply to the item that the -attribute is declared within. Attributes that do not have a bang after the hash -apply to the item that follows the attribute. - -An example of attributes: - -```{.rust} -// General metadata applied to the enclosing module or crate. -#![crate_type = "lib"] - -// A function marked as a unit test -#[test] -fn test_foo() { - /* ... */ -} - -// A conditionally-compiled module -#[cfg(target_os="linux")] -mod bar { - /* ... */ -} - -// A lint attribute used to suppress a warning/error -#[allow(non_camel_case_types)] -type int8_t = i8; -``` - -> **Note:** At some point in the future, the compiler will distinguish between -> language-reserved and user-available attributes. Until then, there is -> effectively no difference between an attribute handled by a loadable syntax -> extension and the compiler. - -### Crate-only attributes - -- `crate_name` - specify the crate's crate name. -- `crate_type` - see [linkage](#linkage). -- `feature` - see [compiler features](#compiler-features). -- `no_builtins` - disable optimizing certain code patterns to invocations of - library functions that are assumed to exist -- `no_main` - disable emitting the `main` symbol. Useful when some other - object being linked to defines `main`. -- `no_start` - disable linking to the `native` crate, which specifies the - "start" language item. -- `no_std` - disable linking to the `std` crate. -- `plugin` - load a list of named crates as compiler plugins, e.g. - `#![plugin(foo, bar)]`. Optional arguments for each plugin, - i.e. `#![plugin(foo(... args ...))]`, are provided to the plugin's - registrar function. The `plugin` feature gate is required to use - this attribute. -- `recursion_limit` - Sets the maximum depth for potentially - infinitely-recursive compile-time operations like - auto-dereference or macro expansion. The default is - `#![recursion_limit="64"]`. - -### Module-only attributes - -- `no_implicit_prelude` - disable injecting `use std::prelude::*` in this - module. -- `path` - specifies the file to load the module from. `#[path="foo.rs"] mod - bar;` is equivalent to `mod bar { /* contents of foo.rs */ }`. The path is - taken relative to the directory that the current module is in. - -### Function-only attributes - -- `main` - indicates that this function should be passed to the entry point, - rather than the function in the crate root named `main`. -- `plugin_registrar` - mark this function as the registration point for - [compiler plugins][plugin], such as loadable syntax extensions. -- `start` - indicates that this function should be used as the entry point, - overriding the "start" language item. See the "start" [language - item](#language-items) for more details. -- `test` - indicates that this function is a test function, to only be compiled - in case of `--test`. -- `should_panic` - indicates that this test function should panic, inverting the success condition. -- `cold` - The function is unlikely to be executed, so optimize it (and calls - to it) differently. -- `naked` - The function utilizes a custom ABI or custom inline ASM that requires - epilogue and prologue to be skipped. - -### Static-only attributes - -- `thread_local` - on a `static mut`, this signals that the value of this - static may change depending on the current thread. The exact consequences of - this are implementation-defined. - -### FFI attributes - -On an `extern` block, the following attributes are interpreted: - -- `link_args` - specify arguments to the linker, rather than just the library - name and type. This is feature gated and the exact behavior is - implementation-defined (due to variety of linker invocation syntax). -- `link` - indicate that a native library should be linked to for the - declarations in this block to be linked correctly. `link` supports an optional - `kind` key with three possible values: `dylib`, `static`, and `framework`. See - [external blocks](#external-blocks) for more about external blocks. Two - examples: `#[link(name = "readline")]` and - `#[link(name = "CoreFoundation", kind = "framework")]`. -- `linked_from` - indicates what native library this block of FFI items is - coming from. This attribute is of the form `#[linked_from = "foo"]` where - `foo` is the name of a library in either `#[link]` or a `-l` flag. This - attribute is currently required to export symbols from a Rust dynamic library - on Windows, and it is feature gated behind the `linked_from` feature. - -On declarations inside an `extern` block, the following attributes are -interpreted: - -- `link_name` - the name of the symbol that this function or static should be - imported as. -- `linkage` - on a static, this specifies the [linkage - type](http://llvm.org/docs/LangRef.html#linkage-types). - -On `enum`s: - -- `repr` - on C-like enums, this sets the underlying type used for - representation. Takes one argument, which is the primitive - type this enum should be represented for, or `C`, which specifies that it - should be the default `enum` size of the C ABI for that platform. Note that - enum representation in C is undefined, and this may be incorrect when the C - code is compiled with certain flags. - -On `struct`s: - -- `repr` - specifies the representation to use for this struct. Takes a list - of options. The currently accepted ones are `C` and `packed`, which may be - combined. `C` will use a C ABI compatible struct layout, and `packed` will - remove any padding between fields (note that this is very fragile and may - break platforms which require aligned access). - -### Macro-related attributes - -- `macro_use` on a `mod` — macros defined in this module will be visible in the - module's parent, after this module has been included. - -- `macro_use` on an `extern crate` — load macros from this crate. An optional - list of names `#[macro_use(foo, bar)]` restricts the import to just those - macros named. The `extern crate` must appear at the crate root, not inside - `mod`, which ensures proper function of the [`$crate` macro - variable](book/macros.html#The%20variable%20%24crate). - -- `macro_reexport` on an `extern crate` — re-export the named macros. - -- `macro_export` - export a macro for cross-crate usage. - -- `no_link` on an `extern crate` — even if we load this crate for macros, don't - link it into the output. - -See the [macros section of the -book](book/macros.html#Scoping%20and%20macro%20import%2Fexport) for more information on -macro scope. - - -### Miscellaneous attributes - -- `deprecated` - mark the item as deprecated; the full attribute is - `#[deprecated(since = "crate version", note = "...")`, where both arguments - are optional. -- `export_name` - on statics and functions, this determines the name of the - exported symbol. -- `link_section` - on statics and functions, this specifies the section of the - object file that this item's contents will be placed into. -- `no_mangle` - on any item, do not apply the standard name mangling. Set the - symbol for this item to its identifier. -- `simd` - on certain tuple structs, derive the arithmetic operators, which - lower to the target's SIMD instructions, if any; the `simd` feature gate - is necessary to use this attribute. -- `unsafe_destructor_blind_to_params` - on `Drop::drop` method, asserts that the - destructor code (and all potential specializations of that code) will - never attempt to read from nor write to any references with lifetimes - that come in via generic parameters. This is a constraint we cannot - currently express via the type system, and therefore we rely on the - programmer to assert that it holds. Adding this to a Drop impl causes - the associated destructor to be considered "uninteresting" by the - Drop-Check rule, and thus it can help sidestep data ordering - constraints that would otherwise be introduced by the Drop-Check - rule. Such sidestepping of the constraints, if done incorrectly, can - lead to undefined behavior (in the form of reading or writing to data - outside of its dynamic extent), and thus this attribute has the word - "unsafe" in its name. To use this, the - `unsafe_destructor_blind_to_params` feature gate must be enabled. -- `doc` - Doc comments such as `/// foo` are equivalent to `#[doc = "foo"]`. -- `rustc_on_unimplemented` - Write a custom note to be shown along with the error - when the trait is found to be unimplemented on a type. - You may use format arguments like `{T}`, `{A}` to correspond to the - types at the point of use corresponding to the type parameters of the - trait of the same name. `{Self}` will be replaced with the type that is supposed - to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate - must be enabled. -- `must_use` - on structs and enums, will warn if a value of this type isn't used or - assigned to a variable. You may also include an optional message by using - `#[must_use = "message"]` which will be given alongside the warning. - -### Conditional compilation - -Sometimes one wants to have different compiler outputs from the same code, -depending on build target, such as targeted operating system, or to enable -release builds. - -Configuration options are boolean (on or off) and are named either with a -single identifier (e.g. `foo`) or an identifier and a string (e.g. `foo = "bar"`; -the quotes are required and spaces around the `=` are unimportant). Note that -similarly-named options, such as `foo`, `foo="bar"` and `foo="baz"` may each be set -or unset independently. - -Configuration options are either provided by the compiler or passed in on the -command line using `--cfg` (e.g. `rustc main.rs --cfg foo --cfg 'bar="baz"'`). -Rust code then checks for their presence using the `#[cfg(...)]` attribute: - -``` -// The function is only included in the build when compiling for OSX -#[cfg(target_os = "macos")] -fn macos_only() { - // ... -} - -// This function is only included when either foo or bar is defined -#[cfg(any(foo, bar))] -fn needs_foo_or_bar() { - // ... -} - -// This function is only included when compiling for a unixish OS with a 32-bit -// architecture -#[cfg(all(unix, target_pointer_width = "32"))] -fn on_32bit_unix() { - // ... -} - -// This function is only included when foo is not defined -#[cfg(not(foo))] -fn needs_not_foo() { - // ... -} -``` - -This illustrates some conditional compilation can be achieved using the -`#[cfg(...)]` attribute. `any`, `all` and `not` can be used to assemble -arbitrarily complex configurations through nesting. - -The following configurations must be defined by the implementation: - -* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, - `"x86_64"` `"mips"`, `"powerpc"`, `"powerpc64"`, `"arm"`, or - `"aarch64"`. This value is closely related to the first element of - the platform target triple, though it is not identical. -* `target_os = "..."` - Operating system of the target, examples - include `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, - `"freebsd"`, `"dragonfly"`, `"bitrig"` , `"openbsd"` or - `"netbsd"`. This value is closely related to the second and third - element of the platform target triple, though it is not identical. -* `target_family = "..."` - Operating system family of the target, e. g. - `"unix"` or `"windows"`. The value of this configuration option is defined - as a configuration itself, like `unix` or `windows`. -* `unix` - See `target_family`. -* `windows` - See `target_family`. -* `target_env = ".."` - Further disambiguates the target platform with - information about the ABI/libc. Presently this value is either - `"gnu"`, `"msvc"`, `"musl"`, or the empty string. For historical - reasons this value has only been defined as non-empty when needed - for disambiguation. Thus on many GNU platforms this value will be - empty. This value is closely related to the fourth element of the - platform target triple, though it is not identical. For example, - embedded ABIs such as `gnueabihf` will simply define `target_env` as - `"gnu"`. -* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or - `"big"`. -* `target_pointer_width = "..."` - Target pointer width in bits. This is set - to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for - 64-bit pointers. -* `target_has_atomic = "..."` - Set of integer sizes on which the target can perform - atomic operations. Values are `"8"`, `"16"`, `"32"`, `"64"` and `"ptr"`. -* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or - simply `"unknown"`. -* `test` - Enabled when compiling the test harness (using the `--test` flag). -* `debug_assertions` - Enabled by default when compiling without optimizations. - This can be used to enable extra debugging code in development but not in - production. For example, it controls the behavior of the standard library's - `debug_assert!` macro. - -You can also set another attribute based on a `cfg` variable with `cfg_attr`: - -```rust,ignore -#[cfg_attr(a, b)] -``` - -This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise. - -Lastly, configuration options can be used in expressions by invoking the `cfg!` -macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise. - -### Lint check attributes - -A lint check names a potentially undesirable coding pattern, such as -unreachable code or omitted documentation, for the static entity to which the -attribute applies. - -For any lint check `C`: - -* `allow(C)` overrides the check for `C` so that violations will go - unreported, -* `deny(C)` signals an error after encountering a violation of `C`, -* `forbid(C)` is the same as `deny(C)`, but also forbids changing the lint - level afterwards, -* `warn(C)` warns about violations of `C` but continues compilation. - -The lint checks supported by the compiler can be found via `rustc -W help`, -along with their default settings. [Compiler -plugins](book/compiler-plugins.html#Lint%20plugins) can provide additional lint checks. - -```{.ignore} -pub mod m1 { - // Missing documentation is ignored here - #[allow(missing_docs)] - pub fn undocumented_one() -> i32 { 1 } - - // Missing documentation signals a warning here - #[warn(missing_docs)] - pub fn undocumented_too() -> i32 { 2 } - - // Missing documentation signals an error here - #[deny(missing_docs)] - pub fn undocumented_end() -> i32 { 3 } -} -``` - -This example shows how one can use `allow` and `warn` to toggle a particular -check on and off: - -```{.ignore} -#[warn(missing_docs)] -pub mod m2{ - #[allow(missing_docs)] - pub mod nested { - // Missing documentation is ignored here - pub fn undocumented_one() -> i32 { 1 } - - // Missing documentation signals a warning here, - // despite the allow above. - #[warn(missing_docs)] - pub fn undocumented_two() -> i32 { 2 } - } - - // Missing documentation signals a warning here - pub fn undocumented_too() -> i32 { 3 } -} -``` - -This example shows how one can use `forbid` to disallow uses of `allow` for -that lint check: - -```{.ignore} -#[forbid(missing_docs)] -pub mod m3 { - // Attempting to toggle warning signals an error here - #[allow(missing_docs)] - /// Returns 2. - pub fn undocumented_too() -> i32 { 2 } -} -``` - -### Language items - -Some primitive Rust operations are defined in Rust code, rather than being -implemented directly in C or assembly language. The definitions of these -operations have to be easy for the compiler to find. The `lang` attribute -makes it possible to declare these operations. For example, the `str` module -in the Rust standard library defines the string equality function: - -```{.ignore} -#[lang = "str_eq"] -pub fn eq_slice(a: &str, b: &str) -> bool { - // details elided -} -``` - -The name `str_eq` has a special meaning to the Rust compiler, and the presence -of this definition means that it will use this definition when generating calls -to the string equality function. - -The set of language items is currently considered unstable. A complete -list of the built-in language items will be added in the future. - -### Inline attributes - -The inline attribute suggests that the compiler should place a copy of -the function or static in the caller, rather than generating code to -call the function or access the static where it is defined. - -The compiler automatically inlines functions based on internal heuristics. -Incorrectly inlining functions can actually make the program slower, so it -should be used with care. - -`#[inline]` and `#[inline(always)]` always cause the function to be serialized -into the crate metadata to allow cross-crate inlining. - -There are three different types of inline attributes: - -* `#[inline]` hints the compiler to perform an inline expansion. -* `#[inline(always)]` asks the compiler to always perform an inline expansion. -* `#[inline(never)]` asks the compiler to never perform an inline expansion. - -### `derive` - -The `derive` attribute allows certain traits to be automatically implemented -for data structures. For example, the following will create an `impl` for the -`PartialEq` and `Clone` traits for `Foo`, the type parameter `T` will be given -the `PartialEq` or `Clone` constraints for the appropriate `impl`: - -``` -#[derive(PartialEq, Clone)] -struct Foo { - a: i32, - b: T, -} -``` - -The generated `impl` for `PartialEq` is equivalent to - -``` -# struct Foo { a: i32, b: T } -impl PartialEq for Foo { - fn eq(&self, other: &Foo) -> bool { - self.a == other.a && self.b == other.b - } - - fn ne(&self, other: &Foo) -> bool { - self.a != other.a || self.b != other.b - } -} -``` - -You can implement `derive` for your own type through [procedural -macros](#procedural-macros). - -### Compiler Features - -Certain aspects of Rust may be implemented in the compiler, but they're not -necessarily ready for every-day use. These features are often of "prototype -quality" or "almost production ready", but may not be stable enough to be -considered a full-fledged language feature. - -For this reason, Rust recognizes a special crate-level attribute of the form: - -```{.ignore} -#![feature(feature1, feature2, feature3)] -``` - -This directive informs the compiler that the feature list: `feature1`, -`feature2`, and `feature3` should all be enabled. This is only recognized at a -crate-level, not at a module-level. Without this directive, all features are -considered off, and using the features will result in a compiler error. - -The currently implemented features of the reference compiler are: - -* `advanced_slice_patterns` - See the [match expressions](#match-expressions) - section for discussion; the exact semantics of - slice patterns are subject to change, so some types - are still unstable. - -* `slice_patterns` - OK, actually, slice patterns are just scary and - completely unstable. - -* `asm` - The `asm!` macro provides a means for inline assembly. This is often - useful, but the exact syntax for this feature along with its - semantics are likely to change, so this macro usage must be opted - into. - -* `associated_consts` - Allows constants to be defined in `impl` and `trait` - blocks, so that they can be associated with a type or - trait in a similar manner to methods and associated - types. - -* `box_patterns` - Allows `box` patterns, the exact semantics of which - is subject to change. - -* `box_syntax` - Allows use of `box` expressions, the exact semantics of which - is subject to change. - -* `cfg_target_vendor` - Allows conditional compilation using the `target_vendor` - matcher which is subject to change. - -* `cfg_target_has_atomic` - Allows conditional compilation using the `target_has_atomic` - matcher which is subject to change. - -* `concat_idents` - Allows use of the `concat_idents` macro, which is in many - ways insufficient for concatenating identifiers, and may be - removed entirely for something more wholesome. - -* `custom_attribute` - Allows the usage of attributes unknown to the compiler - so that new attributes can be added in a backwards compatible - manner (RFC 572). - -* `custom_derive` - Allows the use of `#[derive(Foo,Bar)]` as sugar for - `#[derive_Foo] #[derive_Bar]`, which can be user-defined syntax - extensions. - -* `inclusive_range_syntax` - Allows use of the `a...b` and `...b` syntax for inclusive ranges. - -* `inclusive_range` - Allows use of the types that represent desugared inclusive ranges. - -* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics - are inherently unstable and no promise about them is made. - -* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`, - lang items are inherently unstable and no promise about them - is made. - -* `link_args` - This attribute is used to specify custom flags to the linker, - but usage is strongly discouraged. The compiler's usage of the - system linker is not guaranteed to continue in the future, and - if the system linker is not used then specifying custom flags - doesn't have much meaning. - -* `link_llvm_intrinsics` – Allows linking to LLVM intrinsics via - `#[link_name="llvm.*"]`. - -* `linkage` - Allows use of the `linkage` attribute, which is not portable. - -* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a - nasty hack that will certainly be removed. - -* `main` - Allows use of the `#[main]` attribute, which changes the entry point - into a Rust program. This capability is subject to change. - -* `macro_reexport` - Allows macros to be re-exported from one crate after being imported - from another. This feature was originally designed with the sole - use case of the Rust standard library in mind, and is subject to - change. - -* `non_ascii_idents` - The compiler supports the use of non-ascii identifiers, - but the implementation is a little rough around the - edges, so this can be seen as an experimental feature - for now until the specification of identifiers is fully - fleshed out. - -* `no_std` - Allows the `#![no_std]` crate attribute, which disables the implicit - `extern crate std`. This typically requires use of the unstable APIs - behind the libstd "facade", such as libcore and libcollections. It - may also cause problems when using syntax extensions, including - `#[derive]`. - -* `on_unimplemented` - Allows the `#[rustc_on_unimplemented]` attribute, which allows - trait definitions to add specialized notes to error messages - when an implementation was expected but not found. - -* `optin_builtin_traits` - Allows the definition of default and negative trait - implementations. Experimental. - -* `plugin` - Usage of [compiler plugins][plugin] for custom lints or syntax extensions. - These depend on compiler internals and are subject to change. - -* `plugin_registrar` - Indicates that a crate provides [compiler plugins][plugin]. - -* `quote` - Allows use of the `quote_*!` family of macros, which are - implemented very poorly and will likely change significantly - with a proper implementation. - -* `rustc_attrs` - Gates internal `#[rustc_*]` attributes which may be - for internal use only or have meaning added to them in the future. - -* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation - of rustc, not meant for mortals. - -* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and - not the SIMD interface we want to expose in the long term. - -* `simd_ffi` - Allows use of SIMD vectors in signatures for foreign functions. - The SIMD interface is subject to change. - -* `start` - Allows use of the `#[start]` attribute, which changes the entry point - into a Rust program. This capability, especially the signature for the - annotated function, is subject to change. - -* `thread_local` - The usage of the `#[thread_local]` attribute is experimental - and should be seen as unstable. This attribute is used to - declare a `static` as being unique per-thread leveraging - LLVM's implementation which works in concert with the kernel - loader and dynamic linker. This is not necessarily available - on all platforms, and usage of it is discouraged. - -* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty - hack that will certainly be removed. - -* `unboxed_closures` - Rust's new closure design, which is currently a work in - progress feature with many known bugs. - -* `allow_internal_unstable` - Allows `macro_rules!` macros to be tagged with the - `#[allow_internal_unstable]` attribute, designed - to allow `std` macros to call - `#[unstable]`/feature-gated functionality - internally without imposing on callers - (i.e. making them behave like function calls in - terms of encapsulation). - -* `default_type_parameter_fallback` - Allows type parameter defaults to - influence type inference. - -* `stmt_expr_attributes` - Allows attributes on expressions. - -* `type_ascription` - Allows type ascription expressions `expr: Type`. - -* `abi_vectorcall` - Allows the usage of the vectorcall calling convention - (e.g. `extern "vectorcall" func fn_();`) - -* `abi_sysv64` - Allows the usage of the system V AMD64 calling convention - (e.g. `extern "sysv64" func fn_();`) - -If a feature is promoted to a language feature, then all existing programs will -start to receive compilation warnings about `#![feature]` directives which enabled -the new feature (because the directive is no longer necessary). However, if a -feature is decided to be removed from the language, errors will be issued (if -there isn't a parser error first). The directive in this case is no longer -necessary, and it's likely that existing code will break if the feature isn't -removed. - -If an unknown feature is found in a directive, it results in a compiler error. -An unknown feature is one which has never been recognized by the compiler. - -# Statements and expressions - -Rust is _primarily_ an expression language. This means that most forms of -value-producing or effect-causing evaluation are directed by the uniform syntax -category of _expressions_. Each kind of expression can typically _nest_ within -each other kind of expression, and rules for evaluation of expressions involve -specifying both the value produced by the expression and the order in which its -sub-expressions are themselves evaluated. - -In contrast, statements in Rust serve _mostly_ to contain and explicitly -sequence expression evaluation. - -## Statements - -A _statement_ is a component of a block, which is in turn a component of an -outer [expression](#expressions) or [function](#functions). - -Rust has two kinds of statement: [declaration -statements](#declaration-statements) and [expression -statements](#expression-statements). - -### Declaration statements - -A _declaration statement_ is one that introduces one or more *names* into the -enclosing statement block. The declared names may denote new variables or new -items. - -#### Item declarations - -An _item declaration statement_ has a syntactic form identical to an -[item](#items) declaration within a module. Declaring an item — a -function, enumeration, struct, type, static, trait, implementation or module -— locally within a statement block is simply a way of restricting its -scope to a narrow region containing all of its uses; it is otherwise identical -in meaning to declaring the item outside the statement block. - -> **Note**: there is no implicit capture of the function's dynamic environment when -> declaring a function-local item. - -#### `let` statements - -A _`let` statement_ introduces a new set of variables, given by a pattern. The -pattern may be followed by a type annotation, and/or an initializer expression. -When no type annotation is given, the compiler will infer the type, or signal -an error if insufficient type information is available for definite inference. -Any variables introduced by a variable declaration are visible from the point of -declaration until the end of the enclosing block scope. - -### Expression statements - -An _expression statement_ is one that evaluates an [expression](#expressions) -and ignores its result. The type of an expression statement `e;` is always -`()`, regardless of the type of `e`. As a rule, an expression statement's -purpose is to trigger the effects of evaluating its expression. - -## Expressions - -An expression may have two roles: it always produces a *value*, and it may have -*effects* (otherwise known as "side effects"). An expression *evaluates to* a -value, and has effects during *evaluation*. Many expressions contain -sub-expressions (operands). The meaning of each kind of expression dictates -several things: - -* Whether or not to evaluate the sub-expressions when evaluating the expression -* The order in which to evaluate the sub-expressions -* How to combine the sub-expressions' values to obtain the value of the expression - -In this way, the structure of expressions dictates the structure of execution. -Blocks are just another kind of expression, so blocks, statements, expressions, -and blocks again can recursively nest inside each other to an arbitrary depth. - -#### Lvalues, rvalues and temporaries - -Expressions are divided into two main categories: _lvalues_ and _rvalues_. -Likewise within each expression, sub-expressions may occur in _lvalue context_ -or _rvalue context_. The evaluation of an expression depends both on its own -category and the context it occurs within. - -An lvalue is an expression that represents a memory location. These expressions -are [paths](#path-expressions) (which refer to local variables, function and -method arguments, or static variables), dereferences (`*expr`), [indexing -expressions](#index-expressions) (`expr[expr]`), and [field -references](#field-expressions) (`expr.f`). All other expressions are rvalues. - -The left operand of an [assignment](#assignment-expressions) or -[compound-assignment](#compound-assignment-expressions) expression is -an lvalue context, as is the single operand of a unary -[borrow](#unary-operator-expressions). The discriminant or subject of -a [match expression](#match-expressions) may be an lvalue context, if -ref bindings are made, but is otherwise an rvalue context. All other -expression contexts are rvalue contexts. - -When an lvalue is evaluated in an _lvalue context_, it denotes a memory -location; when evaluated in an _rvalue context_, it denotes the value held _in_ -that memory location. - -##### Temporary lifetimes - -When an rvalue is used in an lvalue context, a temporary un-named -lvalue is created and used instead. The lifetime of temporary values -is typically the innermost enclosing statement; the tail expression of -a block is considered part of the statement that encloses the block. - -When a temporary rvalue is being created that is assigned into a `let` -declaration, however, the temporary is created with the lifetime of -the enclosing block instead, as using the enclosing statement (the -`let` declaration) would be a guaranteed error (since a pointer to the -temporary would be stored into a variable, but the temporary would be -freed before the variable could be used). The compiler uses simple -syntactic rules to decide which values are being assigned into a `let` -binding, and therefore deserve a longer temporary lifetime. - -Here are some examples: - -- `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it - is being borrowed, a temporary is created which will be freed after - the innermost enclosing statement (the `let` declaration, in this case). -- `let x = temp().foo()`. This is the same as the previous example, - except that the value of `temp()` is being borrowed via autoref on a - method-call. Here we are assuming that `foo()` is an `&self` method - defined in some trait, say `Foo`. In other words, the expression - `temp().foo()` is equivalent to `Foo::foo(&temp())`. -- `let x = &temp()`. Here, the same temporary is being assigned into - `x`, rather than being passed as a parameter, and hence the - temporary's lifetime is considered to be the enclosing block. -- `let x = SomeStruct { foo: &temp() }`. As in the previous case, the - temporary is assigned into a struct which is then assigned into a - binding, and hence it is given the lifetime of the enclosing block. -- `let x = [ &temp() ]`. As in the previous case, the - temporary is assigned into an array which is then assigned into a - binding, and hence it is given the lifetime of the enclosing block. -- `let ref x = temp()`. In this case, the temporary is created using a ref binding, - but the result is the same: the lifetime is extended to the enclosing block. - -#### Moved and copied types - -When a [local variable](#variables) is used as an -[rvalue](#lvalues-rvalues-and-temporaries), the variable will be copied -if its type implements `Copy`. All others are moved. - -### Literal expressions - -A _literal expression_ consists of one of the [literal](#literals) forms -described earlier. It directly describes a number, character, string, boolean -value, or the unit value. - -```{.literals} -(); // unit type -"hello"; // string type -'5'; // character type -5; // integer type -``` - -### Path expressions - -A [path](#paths) used as an expression context denotes either a local variable -or an item. Path expressions are [lvalues](#lvalues-rvalues-and-temporaries). - -### Tuple expressions - -Tuples are written by enclosing zero or more comma-separated expressions in -parentheses. They are used to create [tuple-typed](#tuple-types) values. - -```{.tuple} -(0.0, 4.5); -("a", 4usize, true); -``` - -You can disambiguate a single-element tuple from a value in parentheses with a -comma: - -``` -(0,); // single-element tuple -(0); // zero in parentheses -``` - -### Struct expressions - -There are several forms of struct expressions. A _struct expression_ -consists of the [path](#paths) of a [struct item](#structs), followed by -a brace-enclosed list of zero or more comma-separated name-value pairs, -providing the field values of a new instance of the struct. A field name -can be any identifier, and is separated from its value expression by a colon. -The location denoted by a struct field is mutable if and only if the -enclosing struct is mutable. - -A _tuple struct expression_ consists of the [path](#paths) of a [struct -item](#structs), followed by a parenthesized list of one or more -comma-separated expressions (in other words, the path of a struct item -followed by a tuple expression). The struct item must be a tuple struct -item. - -A _unit-like struct expression_ consists only of the [path](#paths) of a -[struct item](#structs). - -The following are examples of struct expressions: - -``` -# struct Point { x: f64, y: f64 } -# struct NothingInMe { } -# struct TuplePoint(f64, f64); -# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } } -# struct Cookie; fn some_fn(t: T) {} -Point {x: 10.0, y: 20.0}; -NothingInMe {}; -TuplePoint(10.0, 20.0); -let u = game::User {name: "Joe", age: 35, score: 100_000}; -some_fn::(Cookie); -``` - -A struct expression forms a new value of the named struct type. Note -that for a given *unit-like* struct type, this will always be the same -value. - -A struct expression can terminate with the syntax `..` followed by an -expression to denote a functional update. The expression following `..` (the -base) must have the same struct type as the new struct type being formed. -The entire expression denotes the result of constructing a new struct (with -the same type as the base expression) with the given values for the fields that -were explicitly specified and the values in the base expression for all other -fields. - -``` -# struct Point3d { x: i32, y: i32, z: i32 } -let base = Point3d {x: 1, y: 2, z: 3}; -Point3d {y: 0, z: 10, .. base}; -``` - -#### Struct field init shorthand - -When initializing a data structure (struct, enum, union) with named fields, -it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. -This allows a compact syntax with less duplication. - -Example: - -``` -# struct Point3d { x: i32, y: i32, z: i32 } -# let x = 0; -# let y_value = 0; -# let z = 0; -Point3d { x: x, y: y_value, z: z }; -Point3d { x, y: y_value, z }; -``` - -### Block expressions - -A _block expression_ is similar to a module in terms of the declarations that -are possible. Each block conceptually introduces a new namespace scope. Use -items can bring new names into scopes and declared items are in scope for only -the block itself. - -A block will execute each statement sequentially, and then execute the -expression (if given). If the block ends in a statement, its value is `()`: - -``` -let x: () = { println!("Hello."); }; -``` - -If it ends in an expression, its value and type are that of the expression: - -``` -let x: i32 = { println!("Hello."); 5 }; - -assert_eq!(5, x); -``` - -### Method-call expressions - -A _method call_ consists of an expression followed by a single dot, an -identifier, and a parenthesized expression-list. Method calls are resolved to -methods on specific traits, either statically dispatching to a method if the -exact `self`-type of the left-hand-side is known, or dynamically dispatching if -the left-hand-side expression is an indirect [trait object](#trait-objects). - -### Field expressions - -A _field expression_ consists of an expression followed by a single dot and an -identifier, when not immediately followed by a parenthesized expression-list -(the latter is a [method call expression](#method-call-expressions)). A field -expression denotes a field of a [struct](#struct-types). - -```{.ignore .field} -mystruct.myfield; -foo().x; -(Struct {a: 10, b: 20}).a; -``` - -A field access is an [lvalue](#lvalues-rvalues-and-temporaries) referring to -the value of that field. When the type providing the field inherits mutability, -it can be [assigned](#assignment-expressions) to. - -Also, if the type of the expression to the left of the dot is a -pointer, it is automatically dereferenced as many times as necessary -to make the field access possible. In cases of ambiguity, we prefer -fewer autoderefs to more. - -### Array expressions - -An [array](#array-and-slice-types) _expression_ is written by enclosing zero -or more comma-separated expressions of uniform type in square brackets. - -In the `[expr ';' expr]` form, the expression after the `';'` must be a -constant expression that can be evaluated at compile time, such as a -[literal](#literals) or a [static item](#static-items). - -``` -[1, 2, 3, 4]; -["a", "b", "c", "d"]; -[0; 128]; // array with 128 zeros -[0u8, 0u8, 0u8, 0u8]; -``` - -### Index expressions - -[Array](#array-and-slice-types)-typed expressions can be indexed by -writing a square-bracket-enclosed expression (the index) after them. When the -array is mutable, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can -be assigned to. - -Indices are zero-based, and may be of any integral type. Vector access is -bounds-checked at compile-time for constant arrays being accessed with a constant index value. -Otherwise a check will be performed at run-time that will put the thread in a _panicked state_ if it fails. - -```{should-fail} -([1, 2, 3, 4])[0]; - -let x = (["a", "b"])[10]; // compiler error: const index-expr is out of bounds - -let n = 10; -let y = (["a", "b"])[n]; // panics - -let arr = ["a", "b"]; -arr[10]; // panics -``` - -Also, if the type of the expression to the left of the brackets is a -pointer, it is automatically dereferenced as many times as necessary -to make the indexing possible. In cases of ambiguity, we prefer fewer -autoderefs to more. - -### Range expressions - -The `..` operator will construct an object of one of the `std::ops::Range` variants. - -``` -1..2; // std::ops::Range -3..; // std::ops::RangeFrom -..4; // std::ops::RangeTo -..; // std::ops::RangeFull -``` - -The following expressions are equivalent. - -``` -let x = std::ops::Range {start: 0, end: 10}; -let y = 0..10; - -assert_eq!(x, y); -``` - -Similarly, the `...` operator will construct an object of one of the -`std::ops::RangeInclusive` variants. - -``` -# #![feature(inclusive_range_syntax)] -1...2; // std::ops::RangeInclusive -...4; // std::ops::RangeToInclusive -``` - -The following expressions are equivalent. - -``` -# #![feature(inclusive_range_syntax, inclusive_range)] -let x = std::ops::RangeInclusive::NonEmpty {start: 0, end: 10}; -let y = 0...10; - -assert_eq!(x, y); -``` - -### Unary operator expressions - -Rust defines the following unary operators. With the exception of `?`, they are -all written as prefix operators, before the expression they apply to. - -* `-` - : Negation. Signed integer types and floating-point types support negation. It - is an error to apply negation to unsigned types; for example, the compiler - rejects `-1u32`. -* `*` - : Dereference. When applied to a [pointer](#pointer-types) it denotes the - pointed-to location. For pointers to mutable locations, the resulting - [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to. - On non-pointer types, it calls the `deref` method of the `std::ops::Deref` - trait, or the `deref_mut` method of the `std::ops::DerefMut` trait (if - implemented by the type and required for an outer expression that will or - could mutate the dereference), and produces the result of dereferencing the - `&` or `&mut` borrowed pointer returned from the overload method. -* `!` - : Logical negation. On the boolean type, this flips between `true` and - `false`. On integer types, this inverts the individual bits in the - two's complement representation of the value. -* `&` and `&mut` - : Borrowing. When applied to an lvalue, these operators produce a - reference (pointer) to the lvalue. The lvalue is also placed into - a borrowed state for the duration of the reference. For a shared - borrow (`&`), this implies that the lvalue may not be mutated, but - it may be read or shared again. For a mutable borrow (`&mut`), the - lvalue may not be accessed in any way until the borrow expires. - If the `&` or `&mut` operators are applied to an rvalue, a - temporary value is created; the lifetime of this temporary value - is defined by [syntactic rules](#temporary-lifetimes). -* `?` - : Propagating errors if applied to `Err(_)` and unwrapping if - applied to `Ok(_)`. Only works on the `Result` type, - and written in postfix notation. - -### Binary operator expressions - -Binary operators expressions are given in terms of [operator -precedence](#operator-precedence). - -#### Arithmetic operators - -Binary arithmetic expressions are syntactic sugar for calls to built-in traits, -defined in the `std::ops` module of the `std` library. This means that -arithmetic operators can be overridden for user-defined types. The default -meaning of the operators on standard types is given here. - -* `+` - : Addition and array/string concatenation. - Calls the `add` method on the `std::ops::Add` trait. -* `-` - : Subtraction. - Calls the `sub` method on the `std::ops::Sub` trait. -* `*` - : Multiplication. - Calls the `mul` method on the `std::ops::Mul` trait. -* `/` - : Quotient. - Calls the `div` method on the `std::ops::Div` trait. -* `%` - : Remainder. - Calls the `rem` method on the `std::ops::Rem` trait. - -#### Bitwise operators - -Like the [arithmetic operators](#arithmetic-operators), bitwise operators are -syntactic sugar for calls to methods of built-in traits. This means that -bitwise operators can be overridden for user-defined types. The default -meaning of the operators on standard types is given here. Bitwise `&`, `|` and -`^` applied to boolean arguments are equivalent to logical `&&`, `||` and `!=` -evaluated in non-lazy fashion. - -* `&` - : Bitwise AND. - Calls the `bitand` method of the `std::ops::BitAnd` trait. -* `|` - : Bitwise inclusive OR. - Calls the `bitor` method of the `std::ops::BitOr` trait. -* `^` - : Bitwise exclusive OR. - Calls the `bitxor` method of the `std::ops::BitXor` trait. -* `<<` - : Left shift. - Calls the `shl` method of the `std::ops::Shl` trait. -* `>>` - : Right shift (arithmetic). - Calls the `shr` method of the `std::ops::Shr` trait. - -#### Lazy boolean operators - -The operators `||` and `&&` may be applied to operands of boolean type. The -`||` operator denotes logical 'or', and the `&&` operator denotes logical -'and'. They differ from `|` and `&` in that the right-hand operand is only -evaluated when the left-hand operand does not already determine the result of -the expression. That is, `||` only evaluates its right-hand operand when the -left-hand operand evaluates to `false`, and `&&` only when it evaluates to -`true`. - -#### Comparison operators - -Comparison operators are, like the [arithmetic -operators](#arithmetic-operators), and [bitwise operators](#bitwise-operators), -syntactic sugar for calls to built-in traits. This means that comparison -operators can be overridden for user-defined types. The default meaning of the -operators on standard types is given here. - -* `==` - : Equal to. - Calls the `eq` method on the `std::cmp::PartialEq` trait. -* `!=` - : Unequal to. - Calls the `ne` method on the `std::cmp::PartialEq` trait. -* `<` - : Less than. - Calls the `lt` method on the `std::cmp::PartialOrd` trait. -* `>` - : Greater than. - Calls the `gt` method on the `std::cmp::PartialOrd` trait. -* `<=` - : Less than or equal. - Calls the `le` method on the `std::cmp::PartialOrd` trait. -* `>=` - : Greater than or equal. - Calls the `ge` method on the `std::cmp::PartialOrd` trait. - -#### Type cast expressions - -A type cast expression is denoted with the binary operator `as`. - -Executing an `as` expression casts the value on the left-hand side to the type -on the right-hand side. - -An example of an `as` expression: - -``` -# fn sum(values: &[f64]) -> f64 { 0.0 } -# fn len(values: &[f64]) -> i32 { 0 } - -fn average(values: &[f64]) -> f64 { - let sum: f64 = sum(values); - let size: f64 = len(values) as f64; - sum / size -} -``` - -Some of the conversions which can be done through the `as` operator -can also be done implicitly at various points in the program, such as -argument passing and assignment to a `let` binding with an explicit -type. Implicit conversions are limited to "harmless" conversions that -do not lose information and which have minimal or no risk of -surprising side-effects on the dynamic execution semantics. - -#### Assignment expressions - -An _assignment expression_ consists of an -[lvalue](#lvalues-rvalues-and-temporaries) expression followed by an equals -sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression. - -Evaluating an assignment expression [either copies or -moves](#moved-and-copied-types) its right-hand operand to its left-hand -operand. - -``` -# let mut x = 0; -# let y = 0; -x = y; -``` - -#### Compound assignment expressions - -The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be -composed with the `=` operator. The expression `lval OP= val` is equivalent to -`lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. - -Any such expression always has the [`unit`](#tuple-types) type. - -#### Operator precedence - -The precedence of Rust binary operators is ordered as follows, going from -strong to weak: - -```{.text .precedence} -as : -* / % -+ - -<< >> -& -^ -| -== != < > <= >= -&& -|| -.. ... -<- -= -``` - -Operators at the same precedence level are evaluated left-to-right. [Unary -operators](#unary-operator-expressions) have the same precedence level and are -stronger than any of the binary operators. - -### Grouped expressions - -An expression enclosed in parentheses evaluates to the result of the enclosed -expression. Parentheses can be used to explicitly specify evaluation order -within an expression. - -An example of a parenthesized expression: - -``` -let x: i32 = (2 + 3) * 4; -``` - - -### Call expressions - -A _call expression_ invokes a function, providing zero or more input variables -and an optional location to move the function's output into. If the function -eventually returns, then the expression completes. - -Some examples of call expressions: - -``` -# fn add(x: i32, y: i32) -> i32 { 0 } - -let x: i32 = add(1i32, 2i32); -let pi: Result = "3.14".parse(); -``` - -### Lambda expressions - -A _lambda expression_ (sometimes called an "anonymous function expression") -defines a function and denotes it as a value, in a single expression. A lambda -expression is a pipe-symbol-delimited (`|`) list of identifiers followed by an -expression. - -A lambda expression denotes a function that maps a list of parameters -(`ident_list`) onto the expression that follows the `ident_list`. The -identifiers in the `ident_list` are the parameters to the function. These -parameters' types need not be specified, as the compiler infers them from -context. - -Lambda expressions are most useful when passing functions as arguments to other -functions, as an abbreviation for defining and capturing a separate function. - -Significantly, lambda expressions _capture their environment_, which regular -[function definitions](#functions) do not. The exact type of capture depends -on the [function type](#function-types) inferred for the lambda expression. In -the simplest and least-expensive form (analogous to a ```|| { }``` expression), -the lambda expression captures its environment by reference, effectively -borrowing pointers to all outer variables mentioned inside the function. -Alternately, the compiler may infer that a lambda expression should copy or -move values (depending on their type) from the environment into the lambda -expression's captured environment. A lambda can be forced to capture its -environment by moving values by prefixing it with the `move` keyword. - -In this example, we define a function `ten_times` that takes a higher-order -function argument, and we then call it with a lambda expression as an argument, -followed by a lambda expression that moves values from its environment. - -``` -fn ten_times(f: F) where F: Fn(i32) { - for index in 0..10 { - f(index); - } -} - -ten_times(|j| println!("hello, {}", j)); - -let word = "konnichiwa".to_owned(); -ten_times(move |j| println!("{}, {}", word, j)); -``` - -### Infinite loops - -A `loop` expression denotes an infinite loop. - -A `loop` expression may optionally have a _label_. The label is written as -a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a -label is present, then labeled `break` and `continue` expressions nested -within this loop may exit out of this loop or return control to its head. -See [break expressions](#break-expressions) and [continue -expressions](#continue-expressions). - -### `break` expressions - -A `break` expression has an optional _label_. If the label is absent, then -executing a `break` expression immediately terminates the innermost loop -enclosing it. It is only permitted in the body of a loop. If the label is -present, then `break 'foo` terminates the loop with label `'foo`, which need not -be the innermost label enclosing the `break` expression, but must enclose it. - -### `continue` expressions - -A `continue` expression has an optional _label_. If the label is absent, then -executing a `continue` expression immediately terminates the current iteration -of the innermost loop enclosing it, returning control to the loop *head*. In -the case of a `while` loop, the head is the conditional expression controlling -the loop. In the case of a `for` loop, the head is the call-expression -controlling the loop. If the label is present, then `continue 'foo` returns -control to the head of the loop with label `'foo`, which need not be the -innermost label enclosing the `continue` expression, but must enclose it. - -A `continue` expression is only permitted in the body of a loop. - -### `while` loops - -A `while` loop begins by evaluating the boolean loop conditional expression. -If the loop conditional expression evaluates to `true`, the loop body block -executes and control returns to the loop conditional expression. If the loop -conditional expression evaluates to `false`, the `while` expression completes. - -An example: - -``` -let mut i = 0; - -while i < 10 { - println!("hello"); - i = i + 1; -} -``` - -Like `loop` expressions, `while` loops can be controlled with `break` or -`continue`, and may optionally have a _label_. See [infinite -loops](#infinite-loops), [break expressions](#break-expressions), and -[continue expressions](#continue-expressions) for more information. - -### `for` expressions - -A `for` expression is a syntactic construct for looping over elements provided -by an implementation of `std::iter::IntoIterator`. - -An example of a `for` loop over the contents of an array: - -``` -# type Foo = i32; -# fn bar(f: &Foo) { } -# let a = 0; -# let b = 0; -# let c = 0; - -let v: &[Foo] = &[a, b, c]; - -for e in v { - bar(e); -} -``` - -An example of a for loop over a series of integers: - -``` -# fn bar(b:usize) { } -for i in 0..256 { - bar(i); -} -``` - -Like `loop` expressions, `for` loops can be controlled with `break` or -`continue`, and may optionally have a _label_. See [infinite -loops](#infinite-loops), [break expressions](#break-expressions), and -[continue expressions](#continue-expressions) for more information. - -### `if` expressions - -An `if` expression is a conditional branch in program control. The form of an -`if` expression is a condition expression, followed by a consequent block, any -number of `else if` conditions and blocks, and an optional trailing `else` -block. The condition expressions must have type `bool`. If a condition -expression evaluates to `true`, the consequent block is executed and any -subsequent `else if` or `else` block is skipped. If a condition expression -evaluates to `false`, the consequent block is skipped and any subsequent `else -if` condition is evaluated. If all `if` and `else if` conditions evaluate to -`false` then any `else` block is executed. - -### `match` expressions - -A `match` expression branches on a *pattern*. The exact form of matching that -occurs depends on the pattern. Patterns consist of some combination of -literals, destructured arrays or enum constructors, structs and tuples, -variable binding specifications, wildcards (`..`), and placeholders (`_`). A -`match` expression has a *head expression*, which is the value to compare to -the patterns. The type of the patterns must equal the type of the head -expression. - -In a pattern whose head expression has an `enum` type, a placeholder (`_`) -stands for a *single* data field, whereas a wildcard `..` stands for *all* the -fields of a particular variant. - -A `match` behaves differently depending on whether or not the head expression -is an [lvalue or an rvalue](#lvalues-rvalues-and-temporaries). If the head -expression is an rvalue, it is first evaluated into a temporary location, and -the resulting value is sequentially compared to the patterns in the arms until -a match is found. The first arm with a matching pattern is chosen as the branch -target of the `match`, any variables bound by the pattern are assigned to local -variables in the arm's block, and control enters the block. - -When the head expression is an lvalue, the match does not allocate a temporary -location (however, a by-value binding may copy or move from the lvalue). When -possible, it is preferable to match on lvalues, as the lifetime of these -matches inherits the lifetime of the lvalue, rather than being restricted to -the inside of the match. - -An example of a `match` expression: - -``` -let x = 1; - -match x { - 1 => println!("one"), - 2 => println!("two"), - 3 => println!("three"), - 4 => println!("four"), - 5 => println!("five"), - _ => println!("something else"), -} -``` - -Patterns that bind variables default to binding to a copy or move of the -matched value (depending on the matched value's type). This can be changed to -bind to a reference by using the `ref` keyword, or to a mutable reference using -`ref mut`. - -Subpatterns can also be bound to variables by the use of the syntax `variable @ -subpattern`. For example: - -``` -let x = 1; - -match x { - e @ 1 ... 5 => println!("got a range element {}", e), - _ => println!("anything"), -} -``` - -Patterns can also dereference pointers by using the `&`, `&mut` and `box` -symbols, as appropriate. For example, these two matches on `x: &i32` are -equivalent: - -``` -# let x = &3; -let y = match *x { 0 => "zero", _ => "some" }; -let z = match x { &0 => "zero", _ => "some" }; - -assert_eq!(y, z); -``` - -Multiple match patterns may be joined with the `|` operator. A range of values -may be specified with `...`. For example: - -``` -# let x = 2; - -let message = match x { - 0 | 1 => "not many", - 2 ... 9 => "a few", - _ => "lots" -}; -``` - -Range patterns only work on scalar types (like integers and characters; not -like arrays and structs, which have sub-components). A range pattern may not -be a sub-range of another range pattern inside the same `match`. - -Finally, match patterns can accept *pattern guards* to further refine the -criteria for matching a case. Pattern guards appear after the pattern and -consist of a bool-typed expression following the `if` keyword. A pattern guard -may refer to the variables bound within the pattern they follow. - -``` -# let maybe_digit = Some(0); -# fn process_digit(i: i32) { } -# fn process_other(i: i32) { } - -let message = match maybe_digit { - Some(x) if x < 10 => process_digit(x), - Some(x) => process_other(x), - None => panic!(), -}; -``` - -### `if let` expressions - -An `if let` expression is semantically identical to an `if` expression but in -place of a condition expression it expects a `let` statement with a refutable -pattern. If the value of the expression on the right hand side of the `let` -statement matches the pattern, the corresponding block will execute, otherwise -flow proceeds to the first `else` block that follows. - -``` -let dish = ("Ham", "Eggs"); - -// this body will be skipped because the pattern is refuted -if let ("Bacon", b) = dish { - println!("Bacon is served with {}", b); -} - -// this body will execute -if let ("Ham", b) = dish { - println!("Ham is served with {}", b); -} -``` - -### `while let` loops - -A `while let` loop is semantically identical to a `while` loop but in place of -a condition expression it expects `let` statement with a refutable pattern. If -the value of the expression on the right hand side of the `let` statement -matches the pattern, the loop body block executes and control returns to the -pattern matching statement. Otherwise, the while expression completes. - -### `return` expressions - -Return expressions are denoted with the keyword `return`. Evaluating a `return` -expression moves its argument into the designated output location for the -current function call, destroys the current function activation frame, and -transfers control to the caller frame. - -An example of a `return` expression: - -``` -fn max(a: i32, b: i32) -> i32 { - if a > b { - return a; - } - return b; -} -``` - -# Type system - -## Types - -Every variable, item and value in a Rust program has a type. The _type_ of a -*value* defines the interpretation of the memory holding it. - -Built-in types and type-constructors are tightly integrated into the language, -in nontrivial ways that are not possible to emulate in user-defined types. -User-defined types have limited capabilities. - -### Primitive types - -The primitive types are the following: - -* The boolean type `bool` with values `true` and `false`. -* The machine types (integer and floating-point). -* The machine-dependent integer types. -* Arrays -* Tuples -* Slices -* Function pointers - -#### Machine types - -The machine types are the following: - -* The unsigned word types `u8`, `u16`, `u32` and `u64`, with values drawn from - the integer intervals [0, 2^8 - 1], [0, 2^16 - 1], [0, 2^32 - 1] and - [0, 2^64 - 1] respectively. - -* The signed two's complement word types `i8`, `i16`, `i32` and `i64`, with - values drawn from the integer intervals [-(2^(7)), 2^7 - 1], - [-(2^(15)), 2^15 - 1], [-(2^(31)), 2^31 - 1], [-(2^(63)), 2^63 - 1] - respectively. - -* The IEEE 754-2008 `binary32` and `binary64` floating-point types: `f32` and - `f64`, respectively. - -#### Machine-dependent integer types - -The `usize` type is an unsigned integer type with the same number of bits as the -platform's pointer type. It can represent every memory address in the process. - -The `isize` type is a signed integer type with the same number of bits as the -platform's pointer type. The theoretical upper bound on object and array size -is the maximum `isize` value. This ensures that `isize` can be used to calculate -differences between pointers into an object or array and can address every byte -within an object along with one byte past the end. - -### Textual types - -The types `char` and `str` hold textual data. - -A value of type `char` is a [Unicode scalar value]( -http://www.unicode.org/glossary/#unicode_scalar_value) (i.e. a code point that -is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to -0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 / -UTF-32 string. - -A value of type `str` is a Unicode string, represented as an array of 8-bit -unsigned bytes holding a sequence of UTF-8 code points. Since `str` is of -unknown size, it is not a _first-class_ type, but can only be instantiated -through a pointer type, such as `&str`. - -### Tuple types - -A tuple *type* is a heterogeneous product of other types, called the *elements* -of the tuple. It has no nominal name and is instead structurally typed. - -Tuple types and values are denoted by listing the types or values of their -elements, respectively, in a parenthesized, comma-separated list. - -Because tuple elements don't have a name, they can only be accessed by -pattern-matching or by using `N` directly as a field to access the -`N`th element. - -An example of a tuple type and its use: - -``` -type Pair<'a> = (i32, &'a str); -let p: Pair<'static> = (10, "ten"); -let (a, b) = p; - -assert_eq!(a, 10); -assert_eq!(b, "ten"); -assert_eq!(p.0, 10); -assert_eq!(p.1, "ten"); -``` - -For historical reasons and convenience, the tuple type with no elements (`()`) -is often called ‘unit’ or ‘the unit type’. - -### Array, and Slice types - -Rust has two different types for a list of items: - -* `[T; N]`, an 'array' -* `&[T]`, a 'slice' - -An array has a fixed size, and can be allocated on either the stack or the -heap. - -A slice is a 'view' into an array. It doesn't own the data it points -to, it borrows it. - -Examples: - -```{rust} -// A stack-allocated array -let array: [i32; 3] = [1, 2, 3]; - -// A heap-allocated array -let vector: Vec = vec![1, 2, 3]; - -// A slice into an array -let slice: &[i32] = &vector[..]; -``` - -As you can see, the `vec!` macro allows you to create a `Vec` easily. The -`vec!` macro is also part of the standard library, rather than the language. - -All in-bounds elements of arrays and slices are always initialized, and access -to an array or slice is always bounds-checked. - -### Struct types - -A `struct` *type* is a heterogeneous product of other types, called the -*fields* of the type.[^structtype] - -[^structtype]: `struct` types are analogous to `struct` types in C, - the *record* types of the ML family, - or the *struct* types of the Lisp family. - -New instances of a `struct` can be constructed with a [struct -expression](#struct-expressions). - -The memory layout of a `struct` is undefined by default to allow for compiler -optimizations like field reordering, but it can be fixed with the -`#[repr(...)]` attribute. In either case, fields may be given in any order in -a corresponding struct *expression*; the resulting `struct` value will always -have the same memory layout. - -The fields of a `struct` may be qualified by [visibility -modifiers](#visibility-and-privacy), to allow access to data in a -struct outside a module. - -A _tuple struct_ type is just like a struct type, except that the fields are -anonymous. - -A _unit-like struct_ type is like a struct type, except that it has no -fields. The one value constructed by the associated [struct -expression](#struct-expressions) is the only value that inhabits such a -type. - -### Enumerated types - -An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted -by the name of an [`enum` item](#enumerations). [^enumtype] - -[^enumtype]: The `enum` type is analogous to a `data` constructor declaration in - ML, or a *pick ADT* in Limbo. - -An [`enum` item](#enumerations) declares both the type and a number of *variant -constructors*, each of which is independently named and takes an optional tuple -of arguments. - -New instances of an `enum` can be constructed by calling one of the variant -constructors, in a [call expression](#call-expressions). - -Any `enum` value consumes as much memory as the largest variant constructor for -its corresponding `enum` type. - -Enum types cannot be denoted *structurally* as types, but must be denoted by -named reference to an [`enum` item](#enumerations). - -### Recursive types - -Nominal types — [enumerations](#enumerated-types) and -[structs](#struct-types) — may be recursive. That is, each `enum` -constructor or `struct` field may refer, directly or indirectly, to the -enclosing `enum` or `struct` type itself. Such recursion has restrictions: - -* Recursive types must include a nominal type in the recursion - (not mere [type definitions](grammar.html#type-definitions), - or other structural types such as [arrays](#array-and-slice-types) or [tuples](#tuple-types)). -* A recursive `enum` item must have at least one non-recursive constructor - (in order to give the recursion a basis case). -* The size of a recursive type must be finite; - in other words the recursive fields of the type must be [pointer types](#pointer-types). -* Recursive type definitions can cross module boundaries, but not module *visibility* boundaries, - or crate boundaries (in order to simplify the module system and type checker). - -An example of a *recursive* type and its use: - -``` -enum List { - Nil, - Cons(T, Box>) -} - -let a: List = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil)))); -``` - -### Pointer types - -All pointers in Rust are explicit first-class values. They can be copied, -stored into data structs, and returned from functions. There are two -varieties of pointer in Rust: - -* References (`&`) - : These point to memory _owned by some other value_. - A reference type is written `&type`, - or `&'a type` when you need to specify an explicit lifetime. - Copying a reference is a "shallow" operation: - it involves only copying the pointer itself. - Releasing a reference has no effect on the value it points to, - but a reference of a temporary value will keep it alive during the scope - of the reference itself. - -* Raw pointers (`*`) - : Raw pointers are pointers without safety or liveness guarantees. - Raw pointers are written as `*const T` or `*mut T`, - for example `*const i32` means a raw pointer to a 32-bit integer. - Copying or dropping a raw pointer has no effect on the lifecycle of any - other value. Dereferencing a raw pointer or converting it to any other - pointer type is an [`unsafe` operation](#unsafe-functions). - Raw pointers are generally discouraged in Rust code; - they exist to support interoperability with foreign code, - and writing performance-critical or low-level functions. - -The standard library contains additional 'smart pointer' types beyond references -and raw pointers. - -### Function types - -The function type constructor `fn` forms new function types. A function type -consists of a possibly-empty set of function-type modifiers (such as `unsafe` -or `extern`), a sequence of input types and an output type. - -An example of a `fn` type: - -``` -fn add(x: i32, y: i32) -> i32 { - x + y -} - -let mut x = add(5,7); - -type Binop = fn(i32, i32) -> i32; -let bo: Binop = add; -x = bo(5,7); -``` - -#### Function types for specific items - -Internal to the compiler, there are also function types that are specific to a particular -function item. In the following snippet, for example, the internal types of the functions -`foo` and `bar` are different, despite the fact that they have the same signature: - -``` -fn foo() { } -fn bar() { } -``` - -The types of `foo` and `bar` can both be implicitly coerced to the fn -pointer type `fn()`. There is currently no syntax for unique fn types, -though the compiler will emit a type like `fn() {foo}` in error -messages to indicate "the unique fn type for the function `foo`". - -### Closure types - -A [lambda expression](#lambda-expressions) produces a closure value with -a unique, anonymous type that cannot be written out. - -Depending on the requirements of the closure, its type implements one or -more of the closure traits: - -* `FnOnce` - : The closure can be called once. A closure called as `FnOnce` - can move out values from its environment. - -* `FnMut` - : The closure can be called multiple times as mutable. A closure called as - `FnMut` can mutate values from its environment. `FnMut` inherits from - `FnOnce` (i.e. anything implementing `FnMut` also implements `FnOnce`). - -* `Fn` - : The closure can be called multiple times through a shared reference. - A closure called as `Fn` can neither move out from nor mutate values - from its environment. `Fn` inherits from `FnMut`, which itself - inherits from `FnOnce`. - - -### Trait objects - -In Rust, a type like `&SomeTrait` or `Box` is called a _trait object_. -Each instance of a trait object includes: - - - a pointer to an instance of a type `T` that implements `SomeTrait` - - a _virtual method table_, often just called a _vtable_, which contains, for - each method of `SomeTrait` that `T` implements, a pointer to `T`'s - implementation (i.e. a function pointer). - -The purpose of trait objects is to permit "late binding" of methods. Calling a -method on a trait object results in virtual dispatch at runtime: that is, a -function pointer is loaded from the trait object vtable and invoked indirectly. -The actual implementation for each vtable entry can vary on an object-by-object -basis. - -Note that for a trait object to be instantiated, the trait must be -_object-safe_. Object safety rules are defined in [RFC 255]. - -[RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md - -Given a pointer-typed expression `E` of type `&T` or `Box`, where `T` -implements trait `R`, casting `E` to the corresponding pointer type `&R` or -`Box` results in a value of the _trait object_ `R`. This result is -represented as a pair of pointers: the vtable pointer for the `T` -implementation of `R`, and the pointer value of `E`. - -An example of a trait object: - -``` -trait Printable { - fn stringify(&self) -> String; -} - -impl Printable for i32 { - fn stringify(&self) -> String { self.to_string() } -} - -fn print(a: Box) { - println!("{}", a.stringify()); -} - -fn main() { - print(Box::new(10) as Box); -} -``` - -In this example, the trait `Printable` occurs as a trait object in both the -type signature of `print`, and the cast expression in `main`. - -### Type parameters - -Within the body of an item that has type parameter declarations, the names of -its type parameters are types: - -```ignore -fn to_vec(xs: &[A]) -> Vec { - if xs.is_empty() { - return vec![]; - } - let first: A = xs[0].clone(); - let mut rest: Vec = to_vec(&xs[1..]); - rest.insert(0, first); - rest -} -``` - -Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and `rest` -has type `Vec`, a vector with element type `A`. - -### Self types - -The special type `Self` has a meaning within traits and impls. In a trait definition, it refers -to an implicit type parameter representing the "implementing" type. In an impl, -it is an alias for the implementing type. For example, in: - -``` -pub trait From { - fn from(T) -> Self; -} - -impl From for String { - fn from(x: i32) -> Self { - x.to_string() - } -} -``` - -The notation `Self` in the impl refers to the implementing type: `String`. In another -example: - -``` -trait Printable { - fn make_string(&self) -> String; -} - -impl Printable for String { - fn make_string(&self) -> String { - (*self).clone() - } -} -``` - -The notation `&self` is a shorthand for `self: &Self`. In this case, -in the impl, `Self` refers to the value of type `String` that is the -receiver for a call to the method `make_string`. - -## Subtyping - -Subtyping is implicit and can occur at any stage in type checking or -inference. Subtyping in Rust is very restricted and occurs only due to -variance with respect to lifetimes and between types with higher ranked -lifetimes. If we were to erase lifetimes from types, then the only subtyping -would be due to type equality. - -Consider the following example: string literals always have `'static` -lifetime. Nevertheless, we can assign `s` to `t`: - -``` -fn bar<'a>() { - let s: &'static str = "hi"; - let t: &'a str = s; -} -``` -Since `'static` "lives longer" than `'a`, `&'static str` is a subtype of -`&'a str`. - -## Type coercions - -Coercions are defined in [RFC 401]. A coercion is implicit and has no syntax. - -[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md - -### Coercion sites - -A coercion can only occur at certain coercion sites in a program; these are -typically places where the desired type is explicit or can be derived by -propagation from explicit types (without type inference). Possible coercion -sites are: - -* `let` statements where an explicit type is given. - - For example, `42` is coerced to have type `i8` in the following: - - ```rust - let _: i8 = 42; - ``` - -* `static` and `const` statements (similar to `let` statements). - -* Arguments for function calls - - The value being coerced is the actual parameter, and it is coerced to - the type of the formal parameter. - - For example, `42` is coerced to have type `i8` in the following: - - ```rust - fn bar(_: i8) { } - - fn main() { - bar(42); - } - ``` - -* Instantiations of struct or variant fields - - For example, `42` is coerced to have type `i8` in the following: - - ```rust - struct Foo { x: i8 } - - fn main() { - Foo { x: 42 }; - } - ``` - -* Function results, either the final line of a block if it is not - semicolon-terminated or any expression in a `return` statement - - For example, `42` is coerced to have type `i8` in the following: - - ```rust - fn foo() -> i8 { - 42 - } - ``` - -If the expression in one of these coercion sites is a coercion-propagating -expression, then the relevant sub-expressions in that expression are also -coercion sites. Propagation recurses from these new coercion sites. -Propagating expressions and their relevant sub-expressions are: - -* Array literals, where the array has type `[U; n]`. Each sub-expression in -the array literal is a coercion site for coercion to type `U`. - -* Array literals with repeating syntax, where the array has type `[U; n]`. The -repeated sub-expression is a coercion site for coercion to type `U`. - -* Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`. -Each sub-expression is a coercion site to the respective type, e.g. the -zeroth sub-expression is a coercion site to type `U_0`. - -* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then -the sub-expression is a coercion site to `U`. - -* Blocks: if a block has type `U`, then the last expression in the block (if -it is not semicolon-terminated) is a coercion site to `U`. This includes -blocks which are part of control flow statements, such as `if`/`else`, if -the block has a known type. - -### Coercion types - -Coercion is allowed between the following types: - -* `T` to `U` if `T` is a subtype of `U` (*reflexive case*) - -* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` -(*transitive case*) - - Note that this is not fully supported yet - -* `&mut T` to `&T` - -* `*mut T` to `*const T` - -* `&T` to `*const T` - -* `&mut T` to `*mut T` - -* `&T` to `&U` if `T` implements `Deref`. For example: - - ```rust - use std::ops::Deref; - - struct CharContainer { - value: char, - } - - impl Deref for CharContainer { - type Target = char; - - fn deref<'a>(&'a self) -> &'a char { - &self.value - } - } - - fn foo(arg: &char) {} - - fn main() { - let x = &mut CharContainer { value: 'y' }; - foo(x); //&mut CharContainer is coerced to &char. - } - ``` - -* `&mut T` to `&mut U` if `T` implements `DerefMut`. - -* TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of - - `&T` - - `&mut T` - - `*const T` - - `*mut T` - - `Box` - - and where - - coerce_inner(`[T, ..n]`) = `[T]` - - coerce_inner(`T`) = `U` where `T` is a concrete type which implements the - trait `U`. - - In the future, coerce_inner will be recursively extended to tuples and - structs. In addition, coercions from sub-traits to super-traits will be - added. See [RFC 401] for more details. - -# Special traits - -Several traits define special evaluation behavior. - -## The `Copy` trait - -The `Copy` trait changes the semantics of a type implementing it. Values whose -type implements `Copy` are copied rather than moved upon assignment. - -## The `Sized` trait - -The `Sized` trait indicates that the size of this type is known at compile-time. - -## The `Drop` trait - -The `Drop` trait provides a destructor, to be run whenever a value of this type -is to be destroyed. - -## The `Deref` trait - -The `Deref` trait allows a type to implicitly implement all the methods -of the type `U`. When attempting to resolve a method call, the compiler will search -the top-level type for the implementation of the called method. If no such method is -found, `.deref()` is called and the compiler continues to search for the method -implementation in the returned type `U`. - -## The `Send` trait - -The `Send` trait indicates that a value of this type is safe to send from one -thread to another. - -## The `Sync` trait - -The `Sync` trait indicates that a value of this type is safe to share between -multiple threads. - -# Memory model - -A Rust program's memory consists of a static set of *items* and a *heap*. -Immutable portions of the heap may be safely shared between threads, mutable -portions may not be safely shared, but several mechanisms for effectively-safe -sharing of mutable values, built on unsafe code but enforcing a safe locking -discipline, exist in the standard library. - -Allocations in the stack consist of *variables*, and allocations in the heap -consist of *boxes*. - -### Memory allocation and lifetime - -The _items_ of a program are those functions, modules and types that have their -value calculated at compile-time and stored uniquely in the memory image of the -rust process. Items are neither dynamically allocated nor freed. - -The _heap_ is a general term that describes boxes. The lifetime of an -allocation in the heap depends on the lifetime of the box values pointing to -it. Since box values may themselves be passed in and out of frames, or stored -in the heap, heap allocations may outlive the frame they are allocated within. -An allocation in the heap is guaranteed to reside at a single location in the -heap for the whole lifetime of the allocation - it will never be relocated as -a result of moving a box value. - -### Memory ownership - -When a stack frame is exited, its local allocations are all released, and its -references to boxes are dropped. - -### Variables - -A _variable_ is a component of a stack frame, either a named function parameter, -an anonymous [temporary](#lvalues-rvalues-and-temporaries), or a named local -variable. - -A _local variable_ (or *stack-local* allocation) holds a value directly, -allocated within the stack's memory. The value is a part of the stack frame. - -Local variables are immutable unless declared otherwise like: `let mut x = ...`. - -Function parameters are immutable unless declared with `mut`. The `mut` keyword -applies only to the following parameter (so `|mut x, y|` and `fn f(mut x: -Box, y: Box)` declare one mutable variable `x` and one immutable -variable `y`). - -Methods that take either `self` or `Box` can optionally place them in a -mutable variable by prefixing them with `mut` (similar to regular arguments): - -``` -trait Changer: Sized { - fn change(mut self) {} - fn modify(mut self: Box) {} -} -``` - -Local variables are not initialized when allocated; the entire frame worth of -local variables are allocated at once, on frame-entry, in an uninitialized -state. Subsequent statements within a function may or may not initialize the -local variables. Local variables can be used only after they have been -initialized; this is enforced by the compiler. - -# Linkage - -The Rust compiler supports various methods to link crates together both -statically and dynamically. This section will explore the various methods to -link Rust crates together, and more information about native libraries can be -found in the [FFI section of the book][ffi]. - -In one session of compilation, the compiler can generate multiple artifacts -through the usage of either command line flags or the `crate_type` attribute. -If one or more command line flags are specified, all `crate_type` attributes will -be ignored in favor of only building the artifacts specified by command line. - -* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be - produced. This requires that there is a `main` function in the crate which - will be run when the program begins executing. This will link in all Rust and - native dependencies, producing a distributable binary. - -* `--crate-type=lib`, `#[crate_type = "lib"]` - A Rust library will be produced. - This is an ambiguous concept as to what exactly is produced because a library - can manifest itself in several forms. The purpose of this generic `lib` option - is to generate the "compiler recommended" style of library. The output library - will always be usable by rustc, but the actual type of library may change from - time-to-time. The remaining output types are all different flavors of - libraries, and the `lib` type can be seen as an alias for one of them (but the - actual one is compiler-defined). - -* `--crate-type=dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will - be produced. This is different from the `lib` output type in that this forces - dynamic library generation. The resulting dynamic library can be used as a - dependency for other libraries and/or executables. This output type will - create `*.so` files on linux, `*.dylib` files on osx, and `*.dll` files on - windows. - -* `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system - library will be produced. This is different from other library outputs in that - the Rust compiler will never attempt to link to `staticlib` outputs. The - purpose of this output type is to create a static library containing all of - the local crate's code along with all upstream dependencies. The static - library is actually a `*.a` archive on linux and osx and a `*.lib` file on - windows. This format is recommended for use in situations such as linking - Rust code into an existing non-Rust application because it will not have - dynamic dependencies on other Rust code. - -* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system - library will be produced. This is used when compiling Rust code as - a dynamic library to be loaded from another language. This output type will - create `*.so` files on Linux, `*.dylib` files on OSX, and `*.dll` files on - Windows. - -* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be - produced. This is used as an intermediate artifact and can be thought of as a - "static Rust library". These `rlib` files, unlike `staticlib` files, are - interpreted by the Rust compiler in future linkage. This essentially means - that `rustc` will look for metadata in `rlib` files like it looks for metadata - in dynamic libraries. This form of output is used to produce statically linked - executables as well as `staticlib` outputs. - -* `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output - produced is not specified, but if a `-L` path is provided to it then the - compiler will recognize the output artifacts as a macro and it can be loaded - for a program. If a crate is compiled with the `proc-macro` crate type it - will forbid exporting any items in the crate other than those functions - tagged `#[proc_macro_derive]` and those functions must also be placed at the - crate root. Finally, the compiler will automatically set the - `cfg(proc_macro)` annotation whenever any crate type of a compilation is the - `proc-macro` crate type. - -Note that these outputs are stackable in the sense that if multiple are -specified, then the compiler will produce each form of output at once without -having to recompile. However, this only applies for outputs specified by the -same method. If only `crate_type` attributes are specified, then they will all -be built, but if one or more `--crate-type` command line flags are specified, -then only those outputs will be built. - -With all these different kinds of outputs, if crate A depends on crate B, then -the compiler could find B in various different forms throughout the system. The -only forms looked for by the compiler, however, are the `rlib` format and the -dynamic library format. With these two options for a dependent library, the -compiler must at some point make a choice between these two formats. With this -in mind, the compiler follows these rules when determining what format of -dependencies will be used: - -1. If a static library is being produced, all upstream dependencies are - required to be available in `rlib` formats. This requirement stems from the - reason that a dynamic library cannot be converted into a static format. - - Note that it is impossible to link in native dynamic dependencies to a static - library, and in this case warnings will be printed about all unlinked native - dynamic dependencies. - -2. If an `rlib` file is being produced, then there are no restrictions on what - format the upstream dependencies are available in. It is simply required that - all upstream dependencies be available for reading metadata from. - - The reason for this is that `rlib` files do not contain any of their upstream - dependencies. It wouldn't be very efficient for all `rlib` files to contain a - copy of `libstd.rlib`! - -3. If an executable is being produced and the `-C prefer-dynamic` flag is not - specified, then dependencies are first attempted to be found in the `rlib` - format. If some dependencies are not available in an rlib format, then - dynamic linking is attempted (see below). - -4. If a dynamic library or an executable that is being dynamically linked is - being produced, then the compiler will attempt to reconcile the available - dependencies in either the rlib or dylib format to create a final product. - - A major goal of the compiler is to ensure that a library never appears more - than once in any artifact. For example, if dynamic libraries B and C were - each statically linked to library A, then a crate could not link to B and C - together because there would be two copies of A. The compiler allows mixing - the rlib and dylib formats, but this restriction must be satisfied. - - The compiler currently implements no method of hinting what format a library - should be linked with. When dynamically linking, the compiler will attempt to - maximize dynamic dependencies while still allowing some dependencies to be - linked in via an rlib. - - For most situations, having all libraries available as a dylib is recommended - if dynamically linking. For other situations, the compiler will emit a - warning if it is unable to determine which formats to link each library with. - -In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for -all compilation needs, and the other options are just available if more -fine-grained control is desired over the output format of a Rust crate. - -# Unsafety - -Unsafe operations are those that potentially violate the memory-safety -guarantees of Rust's static semantics. - -The following language level features cannot be used in the safe subset of -Rust: - -- Dereferencing a [raw pointer](#pointer-types). -- Reading or writing a [mutable static variable](#mutable-statics). -- Calling an unsafe function (including an intrinsic or foreign function). - -## Unsafe functions - -Unsafe functions are functions that are not safe in all contexts and/or for all -possible inputs. Such a function must be prefixed with the keyword `unsafe` and -can only be called from an `unsafe` block or another `unsafe` function. - -## Unsafe blocks - -A block of code can be prefixed with the `unsafe` keyword, to permit calling -`unsafe` functions or dereferencing raw pointers within a safe function. - -When a programmer has sufficient conviction that a sequence of potentially -unsafe operations is actually safe, they can encapsulate that sequence (taken -as a whole) within an `unsafe` block. The compiler will consider uses of such -code safe, in the surrounding context. - -Unsafe blocks are used to wrap foreign libraries, make direct use of hardware -or implement features not directly present in the language. For example, Rust -provides the language features necessary to implement memory-safe concurrency -in the language but the implementation of threads and message passing is in the -standard library. - -Rust's type system is a conservative approximation of the dynamic safety -requirements, so in some cases there is a performance cost to using safe code. -For example, a doubly-linked list is not a tree structure and can only be -represented with reference-counted pointers in safe code. By using `unsafe` -blocks to represent the reverse links as raw pointers, it can be implemented -with only boxes. - -## Behavior considered undefined - -The following is a list of behavior which is forbidden in all Rust code, -including within `unsafe` blocks and `unsafe` functions. Type checking provides -the guarantee that these issues are never caused by safe code. - -* Data races -* Dereferencing a null/dangling raw pointer -* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values) - (uninitialized) memory -* Breaking the [pointer aliasing - rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules) - with raw pointers (a subset of the rules used by C) -* `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T` - contains an `UnsafeCell`. Unsafe code must not violate these aliasing - guarantees. -* Mutating non-mutable data (that is, data reached through a shared reference or - data owned by a `let` binding), unless that data is contained within an `UnsafeCell`. -* Invoking undefined behavior via compiler intrinsics: - * Indexing outside of the bounds of an object with `std::ptr::offset` - (`offset` intrinsic), with - the exception of one byte past the end which is permitted. - * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` - intrinsics) on overlapping buffers -* Invalid values in primitive types, even in private fields/locals: - * Dangling/null references or boxes - * A value other than `false` (0) or `true` (1) in a `bool` - * A discriminant in an `enum` not included in the type definition - * A value in a `char` which is a surrogate or above `char::MAX` - * Non-UTF-8 byte sequences in a `str` -* Unwinding into Rust from foreign code or unwinding from Rust into foreign - code. Rust's failure system is not compatible with exception handling in - other languages. Unwinding must be caught and handled at FFI boundaries. - -[noalias]: http://llvm.org/docs/LangRef.html#noalias - -## Behavior not considered unsafe - -This is a list of behavior not considered *unsafe* in Rust terms, but that may -be undesired. - -* Deadlocks -* Leaks of memory and other resources -* Exiting without calling destructors -* Integer overflow - - Overflow is considered "unexpected" behavior and is always user-error, - unless the `wrapping` primitives are used. In non-optimized builds, the compiler - will insert debug checks that panic on overflow, but in optimized builds overflow - instead results in wrapped values. See [RFC 560] for the rationale and more details. - -[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md - -# Appendix: Influences - -Rust is not a particularly original language, with design elements coming from -a wide range of sources. Some of these are listed below (including elements -that have since been removed): - -* SML, OCaml: algebraic data types, pattern matching, type inference, - semicolon statement separation -* C++: references, RAII, smart pointers, move semantics, monomorphization, - memory model -* ML Kit, Cyclone: region based memory management -* Haskell (GHC): typeclasses, type families -* Newsqueak, Alef, Limbo: channels, concurrency -* Erlang: message passing, thread failure, ~~linked thread failure~~, - ~~lightweight concurrency~~ -* Swift: optional bindings -* Scheme: hygienic macros -* C#: attributes -* Ruby: ~~block syntax~~ -* NIL, Hermes: ~~typestate~~ -* [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and - pattern syntax - -[ffi]: book/ffi.html -[plugin]: book/compiler-plugins.html -[procedural macros]: book/procedural-macros.html +We've split up the reference into chapters. Please find it at its new +home [here](reference/index.html). diff --git a/src/doc/reference/.gitignore b/src/doc/reference/.gitignore new file mode 100644 index 0000000000000..7585238efedfc --- /dev/null +++ b/src/doc/reference/.gitignore @@ -0,0 +1 @@ +book diff --git a/src/doc/reference/src/SUMMARY.md b/src/doc/reference/src/SUMMARY.md new file mode 100644 index 0000000000000..a07e195a7184f --- /dev/null +++ b/src/doc/reference/src/SUMMARY.md @@ -0,0 +1,58 @@ +# The Rust Reference + +[Introduction](introduction.md) + +- [Notation](notation.md) + - [Unicode productions](unicode-productions.md) + - [String table productions](string-table-productions.md) + +- [Lexical structure](lexical-structure.md) + - [Input format](input-format.md) + - [Identifiers](identifiers.md) + - [Comments](comments.md) + - [Whitespace](whitespace.md) + - [Tokens](tokens.md) + - [Paths](paths.md) + +- [Macros](macros.md) + - [Macros By Example](macros-by-example.md) + - [Procedrual Macros](procedural-macros.md) + +- [Crates and source files](crates-and-source-files.md) + +- [Items and attributes](items-and-attributes.md) + - [Items](items.md) + - [Visibility and Privacy](visibility-and-privacy.md) + - [Attributes](attributes.md) + +- [Statements and expressions](statements-and-expressions.md) + - [Statements](statements.md) + - [Expressions](expressions.md) + +- [Type system](type-system.md) + - [Types](types.md) + - [Subtyping](subtyping.md) + - [Type coercions](type-coercions.md) + +- [Special traits](special-traits.md) + - [The Copy trait](the-copy-trait.md) + - [The Sized trait](the-sized-trait.md) + - [The Drop trait](the-drop-trait.md) + - [The Deref trait](the-deref-trait.md) + - [The Send trait](the-send-trait.md) + - [The Sync trait](the-sync-trait.md) + +- [Memory model](memory-model.md) + - [Memory allocation and lifetime](memory-allocation-and-lifetime.md) + - [Memory ownership](memory-ownership.md) + - [Variables](variables.md) + +- [Linkage](linkage.md) + +- [Unsafety](unsafety.md) + - [Unsafe functions](unsafe-functions.md) + - [Unsafe blocks](unsafe-blocks.md) + - [Behavior considered undefined](behavior-considered-undefined.md) + - [Behavior not considered unsafe](behavior-not-considered-unsafe.md) + +[Appendix: Influences](influences.md) diff --git a/src/doc/reference/src/attributes.md b/src/doc/reference/src/attributes.md new file mode 100644 index 0000000000000..da43e1cc057eb --- /dev/null +++ b/src/doc/reference/src/attributes.md @@ -0,0 +1,630 @@ +# Attributes + +Any item declaration may have an _attribute_ applied to it. Attributes in Rust +are modeled on Attributes in ECMA-335, with the syntax coming from ECMA-334 +(C#). An attribute is a general, free-form metadatum that is interpreted +according to name, convention, and language and compiler version. Attributes +may appear as any of: + +* A single identifier, the attribute name +* An identifier followed by the equals sign '=' and a literal, providing a + key/value pair +* An identifier followed by a parenthesized list of sub-attribute arguments + +Attributes with a bang ("!") after the hash ("#") apply to the item that the +attribute is declared within. Attributes that do not have a bang after the hash +apply to the item that follows the attribute. + +An example of attributes: + +```{.rust} +// General metadata applied to the enclosing module or crate. +#![crate_type = "lib"] + +// A function marked as a unit test +#[test] +fn test_foo() { + /* ... */ +} + +// A conditionally-compiled module +#[cfg(target_os="linux")] +mod bar { + /* ... */ +} + +// A lint attribute used to suppress a warning/error +#[allow(non_camel_case_types)] +type int8_t = i8; +``` + +> **Note:** At some point in the future, the compiler will distinguish between +> language-reserved and user-available attributes. Until then, there is +> effectively no difference between an attribute handled by a loadable syntax +> extension and the compiler. + +## Crate-only attributes + +- `crate_name` - specify the crate's crate name. +- `crate_type` - see [linkage](linkage.html). +- `feature` - see [compiler features](#compiler-features). +- `no_builtins` - disable optimizing certain code patterns to invocations of + library functions that are assumed to exist +- `no_main` - disable emitting the `main` symbol. Useful when some other + object being linked to defines `main`. +- `no_start` - disable linking to the `native` crate, which specifies the + "start" language item. +- `no_std` - disable linking to the `std` crate. +- `plugin` - load a list of named crates as compiler plugins, e.g. + `#![plugin(foo, bar)]`. Optional arguments for each plugin, + i.e. `#![plugin(foo(... args ...))]`, are provided to the plugin's + registrar function. The `plugin` feature gate is required to use + this attribute. +- `recursion_limit` - Sets the maximum depth for potentially + infinitely-recursive compile-time operations like + auto-dereference or macro expansion. The default is + `#![recursion_limit="64"]`. + +### Module-only attributes + +- `no_implicit_prelude` - disable injecting `use std::prelude::*` in this + module. +- `path` - specifies the file to load the module from. `#[path="foo.rs"] mod + bar;` is equivalent to `mod bar { /* contents of foo.rs */ }`. The path is + taken relative to the directory that the current module is in. + +## Function-only attributes + +- `main` - indicates that this function should be passed to the entry point, + rather than the function in the crate root named `main`. +- `plugin_registrar` - mark this function as the registration point for + [compiler plugins][plugin], such as loadable syntax extensions. +- `start` - indicates that this function should be used as the entry point, + overriding the "start" language item. See the "start" [language + item](#language-items) for more details. +- `test` - indicates that this function is a test function, to only be compiled + in case of `--test`. +- `should_panic` - indicates that this test function should panic, inverting the success condition. +- `cold` - The function is unlikely to be executed, so optimize it (and calls + to it) differently. +- `naked` - The function utilizes a custom ABI or custom inline ASM that requires + epilogue and prologue to be skipped. + +## Static-only attributes + +- `thread_local` - on a `static mut`, this signals that the value of this + static may change depending on the current thread. The exact consequences of + this are implementation-defined. + +## FFI attributes + +On an `extern` block, the following attributes are interpreted: + +- `link_args` - specify arguments to the linker, rather than just the library + name and type. This is feature gated and the exact behavior is + implementation-defined (due to variety of linker invocation syntax). +- `link` - indicate that a native library should be linked to for the + declarations in this block to be linked correctly. `link` supports an optional + `kind` key with three possible values: `dylib`, `static`, and `framework`. See + [external blocks](items.html#external-blocks) for more about external blocks. Two + examples: `#[link(name = "readline")]` and + `#[link(name = "CoreFoundation", kind = "framework")]`. +- `linked_from` - indicates what native library this block of FFI items is + coming from. This attribute is of the form `#[linked_from = "foo"]` where + `foo` is the name of a library in either `#[link]` or a `-l` flag. This + attribute is currently required to export symbols from a Rust dynamic library + on Windows, and it is feature gated behind the `linked_from` feature. + +On declarations inside an `extern` block, the following attributes are +interpreted: + +- `link_name` - the name of the symbol that this function or static should be + imported as. +- `linkage` - on a static, this specifies the [linkage + type](http://llvm.org/docs/LangRef.html#linkage-types). + +On `enum`s: + +- `repr` - on C-like enums, this sets the underlying type used for + representation. Takes one argument, which is the primitive + type this enum should be represented for, or `C`, which specifies that it + should be the default `enum` size of the C ABI for that platform. Note that + enum representation in C is undefined, and this may be incorrect when the C + code is compiled with certain flags. + +On `struct`s: + +- `repr` - specifies the representation to use for this struct. Takes a list + of options. The currently accepted ones are `C` and `packed`, which may be + combined. `C` will use a C ABI compatible struct layout, and `packed` will + remove any padding between fields (note that this is very fragile and may + break platforms which require aligned access). + +## Macro-related attributes + +- `macro_use` on a `mod` — macros defined in this module will be visible in the + module's parent, after this module has been included. + +- `macro_use` on an `extern crate` — load macros from this crate. An optional + list of names `#[macro_use(foo, bar)]` restricts the import to just those + macros named. The `extern crate` must appear at the crate root, not inside + `mod`, which ensures proper function of the [`$crate` macro + variable](../book/macros.html#the-variable-crate). + +- `macro_reexport` on an `extern crate` — re-export the named macros. + +- `macro_export` - export a macro for cross-crate usage. + +- `no_link` on an `extern crate` — even if we load this crate for macros, don't + link it into the output. + +See the [macros section of the +book](../book/macros.html#scoping-and-macro-importexport) for more information on +macro scope. + +## Miscellaneous attributes + +- `deprecated` - mark the item as deprecated; the full attribute is + `#[deprecated(since = "crate version", note = "...")`, where both arguments + are optional. +- `export_name` - on statics and functions, this determines the name of the + exported symbol. +- `link_section` - on statics and functions, this specifies the section of the + object file that this item's contents will be placed into. +- `no_mangle` - on any item, do not apply the standard name mangling. Set the + symbol for this item to its identifier. +- `simd` - on certain tuple structs, derive the arithmetic operators, which + lower to the target's SIMD instructions, if any; the `simd` feature gate + is necessary to use this attribute. +- `unsafe_destructor_blind_to_params` - on `Drop::drop` method, asserts that the + destructor code (and all potential specializations of that code) will + never attempt to read from nor write to any references with lifetimes + that come in via generic parameters. This is a constraint we cannot + currently express via the type system, and therefore we rely on the + programmer to assert that it holds. Adding this to a Drop impl causes + the associated destructor to be considered "uninteresting" by the + Drop-Check rule, and thus it can help sidestep data ordering + constraints that would otherwise be introduced by the Drop-Check + rule. Such sidestepping of the constraints, if done incorrectly, can + lead to undefined behavior (in the form of reading or writing to data + outside of its dynamic extent), and thus this attribute has the word + "unsafe" in its name. To use this, the + `unsafe_destructor_blind_to_params` feature gate must be enabled. +- `doc` - Doc comments such as `/// foo` are equivalent to `#[doc = "foo"]`. +- `rustc_on_unimplemented` - Write a custom note to be shown along with the error + when the trait is found to be unimplemented on a type. + You may use format arguments like `{T}`, `{A}` to correspond to the + types at the point of use corresponding to the type parameters of the + trait of the same name. `{Self}` will be replaced with the type that is supposed + to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate + must be enabled. +- `must_use` - on structs and enums, will warn if a value of this type isn't used or + assigned to a variable. You may also include an optional message by using + `#[must_use = "message"]` which will be given alongside the warning. + +### Conditional compilation + +Sometimes one wants to have different compiler outputs from the same code, +depending on build target, such as targeted operating system, or to enable +release builds. + +Configuration options are boolean (on or off) and are named either with a +single identifier (e.g. `foo`) or an identifier and a string (e.g. `foo = "bar"`; +the quotes are required and spaces around the `=` are unimportant). Note that +similarly-named options, such as `foo`, `foo="bar"` and `foo="baz"` may each be set +or unset independently. + +Configuration options are either provided by the compiler or passed in on the +command line using `--cfg` (e.g. `rustc main.rs --cfg foo --cfg 'bar="baz"'`). +Rust code then checks for their presence using the `#[cfg(...)]` attribute: + +``` +// The function is only included in the build when compiling for OSX +#[cfg(target_os = "macos")] +fn macos_only() { + // ... +} + +// This function is only included when either foo or bar is defined +#[cfg(any(foo, bar))] +fn needs_foo_or_bar() { + // ... +} + +// This function is only included when compiling for a unixish OS with a 32-bit +// architecture +#[cfg(all(unix, target_pointer_width = "32"))] +fn on_32bit_unix() { + // ... +} + +// This function is only included when foo is not defined +#[cfg(not(foo))] +fn needs_not_foo() { + // ... +} +``` + +This illustrates some conditional compilation can be achieved using the +`#[cfg(...)]` attribute. `any`, `all` and `not` can be used to assemble +arbitrarily complex configurations through nesting. + +The following configurations must be defined by the implementation: + +* `target_arch = "..."` - Target CPU architecture, such as `"x86"`, + `"x86_64"` `"mips"`, `"powerpc"`, `"powerpc64"`, `"arm"`, or + `"aarch64"`. This value is closely related to the first element of + the platform target triple, though it is not identical. +* `target_os = "..."` - Operating system of the target, examples + include `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, + `"freebsd"`, `"dragonfly"`, `"bitrig"` , `"openbsd"` or + `"netbsd"`. This value is closely related to the second and third + element of the platform target triple, though it is not identical. +* `target_family = "..."` - Operating system family of the target, e. g. + `"unix"` or `"windows"`. The value of this configuration option is defined + as a configuration itself, like `unix` or `windows`. +* `unix` - See `target_family`. +* `windows` - See `target_family`. +* `target_env = ".."` - Further disambiguates the target platform with + information about the ABI/libc. Presently this value is either + `"gnu"`, `"msvc"`, `"musl"`, or the empty string. For historical + reasons this value has only been defined as non-empty when needed + for disambiguation. Thus on many GNU platforms this value will be + empty. This value is closely related to the fourth element of the + platform target triple, though it is not identical. For example, + embedded ABIs such as `gnueabihf` will simply define `target_env` as + `"gnu"`. +* `target_endian = "..."` - Endianness of the target CPU, either `"little"` or + `"big"`. +* `target_pointer_width = "..."` - Target pointer width in bits. This is set + to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for + 64-bit pointers. +* `target_has_atomic = "..."` - Set of integer sizes on which the target can perform + atomic operations. Values are `"8"`, `"16"`, `"32"`, `"64"` and `"ptr"`. +* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or + simply `"unknown"`. +* `test` - Enabled when compiling the test harness (using the `--test` flag). +* `debug_assertions` - Enabled by default when compiling without optimizations. + This can be used to enable extra debugging code in development but not in + production. For example, it controls the behavior of the standard library's + `debug_assert!` macro. + +You can also set another attribute based on a `cfg` variable with `cfg_attr`: + +```rust,ignore +#[cfg_attr(a, b)] +``` + +This is the same as `#[b]` if `a` is set by `cfg`, and nothing otherwise. + +Lastly, configuration options can be used in expressions by invoking the `cfg!` +macro: `cfg!(a)` evaluates to `true` if `a` is set, and `false` otherwise. + +### Lint check attributes + +A lint check names a potentially undesirable coding pattern, such as +unreachable code or omitted documentation, for the static entity to which the +attribute applies. + +For any lint check `C`: + +* `allow(C)` overrides the check for `C` so that violations will go + unreported, +* `deny(C)` signals an error after encountering a violation of `C`, +* `forbid(C)` is the same as `deny(C)`, but also forbids changing the lint + level afterwards, +* `warn(C)` warns about violations of `C` but continues compilation. + +The lint checks supported by the compiler can be found via `rustc -W help`, +along with their default settings. [Compiler +plugins](../book/compiler-plugins.html#lint-plugins) can provide additional +lint checks. + +```{.ignore} +pub mod m1 { + // Missing documentation is ignored here + #[allow(missing_docs)] + pub fn undocumented_one() -> i32 { 1 } + + // Missing documentation signals a warning here + #[warn(missing_docs)] + pub fn undocumented_too() -> i32 { 2 } + + // Missing documentation signals an error here + #[deny(missing_docs)] + pub fn undocumented_end() -> i32 { 3 } +} +``` + +This example shows how one can use `allow` and `warn` to toggle a particular +check on and off: + +```{.ignore} +#[warn(missing_docs)] +pub mod m2{ + #[allow(missing_docs)] + pub mod nested { + // Missing documentation is ignored here + pub fn undocumented_one() -> i32 { 1 } + + // Missing documentation signals a warning here, + // despite the allow above. + #[warn(missing_docs)] + pub fn undocumented_two() -> i32 { 2 } + } + + // Missing documentation signals a warning here + pub fn undocumented_too() -> i32 { 3 } +} +``` + +This example shows how one can use `forbid` to disallow uses of `allow` for +that lint check: + +```{.ignore} +#[forbid(missing_docs)] +pub mod m3 { + // Attempting to toggle warning signals an error here + #[allow(missing_docs)] + /// Returns 2. + pub fn undocumented_too() -> i32 { 2 } +} +``` + +### Language items + +Some primitive Rust operations are defined in Rust code, rather than being +implemented directly in C or assembly language. The definitions of these +operations have to be easy for the compiler to find. The `lang` attribute +makes it possible to declare these operations. For example, the `str` module +in the Rust standard library defines the string equality function: + +```{.ignore} +#[lang = "str_eq"] +pub fn eq_slice(a: &str, b: &str) -> bool { + // details elided +} +``` + +The name `str_eq` has a special meaning to the Rust compiler, and the presence +of this definition means that it will use this definition when generating calls +to the string equality function. + +The set of language items is currently considered unstable. A complete +list of the built-in language items will be added in the future. + +### Inline attributes + +The inline attribute suggests that the compiler should place a copy of +the function or static in the caller, rather than generating code to +call the function or access the static where it is defined. + +The compiler automatically inlines functions based on internal heuristics. +Incorrectly inlining functions can actually make the program slower, so it +should be used with care. + +`#[inline]` and `#[inline(always)]` always cause the function to be serialized +into the crate metadata to allow cross-crate inlining. + +There are three different types of inline attributes: + +* `#[inline]` hints the compiler to perform an inline expansion. +* `#[inline(always)]` asks the compiler to always perform an inline expansion. +* `#[inline(never)]` asks the compiler to never perform an inline expansion. + +### `derive` + +The `derive` attribute allows certain traits to be automatically implemented +for data structures. For example, the following will create an `impl` for the +`PartialEq` and `Clone` traits for `Foo`, the type parameter `T` will be given +the `PartialEq` or `Clone` constraints for the appropriate `impl`: + +``` +#[derive(PartialEq, Clone)] +struct Foo { + a: i32, + b: T, +} +``` + +The generated `impl` for `PartialEq` is equivalent to + +``` +# struct Foo { a: i32, b: T } +impl PartialEq for Foo { + fn eq(&self, other: &Foo) -> bool { + self.a == other.a && self.b == other.b + } + + fn ne(&self, other: &Foo) -> bool { + self.a != other.a || self.b != other.b + } +} +``` + +You can implement `derive` for your own type through [procedural +macros](procedural-macros.html). + +### Compiler Features + +Certain aspects of Rust may be implemented in the compiler, but they're not +necessarily ready for every-day use. These features are often of "prototype +quality" or "almost production ready", but may not be stable enough to be +considered a full-fledged language feature. + +For this reason, Rust recognizes a special crate-level attribute of the form: + +```{.ignore} +#![feature(feature1, feature2, feature3)] +``` + +This directive informs the compiler that the feature list: `feature1`, +`feature2`, and `feature3` should all be enabled. This is only recognized at a +crate-level, not at a module-level. Without this directive, all features are +considered off, and using the features will result in a compiler error. + +The currently implemented features of the reference compiler are: + +* `advanced_slice_patterns` - See the [match + expressions](expressions.html#match-expressions) + section for discussion; the exact semantics of +slice patterns are subject to change, so some types are still unstable. + +* `slice_patterns` - OK, actually, slice patterns are just scary and + completely unstable. + +* `asm` - The `asm!` macro provides a means for inline assembly. This is often + useful, but the exact syntax for this feature along with its + semantics are likely to change, so this macro usage must be opted + into. + +* `associated_consts` - Allows constants to be defined in `impl` and `trait` + blocks, so that they can be associated with a type or + trait in a similar manner to methods and associated + types. + +* `box_patterns` - Allows `box` patterns, the exact semantics of which + is subject to change. + +* `box_syntax` - Allows use of `box` expressions, the exact semantics of which + is subject to change. + +* `cfg_target_vendor` - Allows conditional compilation using the `target_vendor` + matcher which is subject to change. + +* `cfg_target_has_atomic` - Allows conditional compilation using the `target_has_atomic` + matcher which is subject to change. + +* `concat_idents` - Allows use of the `concat_idents` macro, which is in many + ways insufficient for concatenating identifiers, and may be + removed entirely for something more wholesome. + +* `custom_attribute` - Allows the usage of attributes unknown to the compiler + so that new attributes can be added in a backwards compatible + manner (RFC 572). + +* `custom_derive` - Allows the use of `#[derive(Foo,Bar)]` as sugar for + `#[derive_Foo] #[derive_Bar]`, which can be user-defined syntax + extensions. + +* `inclusive_range_syntax` - Allows use of the `a...b` and `...b` syntax for inclusive ranges. + +* `inclusive_range` - Allows use of the types that represent desugared inclusive ranges. + +* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics + are inherently unstable and no promise about them is made. + +* `lang_items` - Allows use of the `#[lang]` attribute. Like `intrinsics`, + lang items are inherently unstable and no promise about them + is made. + +* `link_args` - This attribute is used to specify custom flags to the linker, + but usage is strongly discouraged. The compiler's usage of the + system linker is not guaranteed to continue in the future, and + if the system linker is not used then specifying custom flags + doesn't have much meaning. + +* `link_llvm_intrinsics` - Allows linking to LLVM intrinsics via + `#[link_name="llvm.*"]`. + +* `linkage` - Allows use of the `linkage` attribute, which is not portable. + +* `log_syntax` - Allows use of the `log_syntax` macro attribute, which is a + nasty hack that will certainly be removed. + +* `main` - Allows use of the `#[main]` attribute, which changes the entry point + into a Rust program. This capability is subject to change. + +* `macro_reexport` - Allows macros to be re-exported from one crate after being imported + from another. This feature was originally designed with the sole + use case of the Rust standard library in mind, and is subject to + change. + +* `non_ascii_idents` - The compiler supports the use of non-ascii identifiers, + but the implementation is a little rough around the + edges, so this can be seen as an experimental feature + for now until the specification of identifiers is fully + fleshed out. + +* `no_std` - Allows the `#![no_std]` crate attribute, which disables the implicit + `extern crate std`. This typically requires use of the unstable APIs + behind the libstd "facade", such as libcore and libcollections. It + may also cause problems when using syntax extensions, including + `#[derive]`. + +* `on_unimplemented` - Allows the `#[rustc_on_unimplemented]` attribute, which allows + trait definitions to add specialized notes to error messages + when an implementation was expected but not found. + +* `optin_builtin_traits` - Allows the definition of default and negative trait + implementations. Experimental. + +* `plugin` - Usage of [compiler plugins][plugin] for custom lints or syntax extensions. + These depend on compiler internals and are subject to change. + +* `plugin_registrar` - Indicates that a crate provides [compiler plugins][plugin]. + +* `quote` - Allows use of the `quote_*!` family of macros, which are + implemented very poorly and will likely change significantly + with a proper implementation. + +* `rustc_attrs` - Gates internal `#[rustc_*]` attributes which may be + for internal use only or have meaning added to them in the future. + +* `rustc_diagnostic_macros`- A mysterious feature, used in the implementation + of rustc, not meant for mortals. + +* `simd` - Allows use of the `#[simd]` attribute, which is overly simple and + not the SIMD interface we want to expose in the long term. + +* `simd_ffi` - Allows use of SIMD vectors in signatures for foreign functions. + The SIMD interface is subject to change. + +* `start` - Allows use of the `#[start]` attribute, which changes the entry point + into a Rust program. This capability, especially the signature for the + annotated function, is subject to change. + +* `thread_local` - The usage of the `#[thread_local]` attribute is experimental + and should be seen as unstable. This attribute is used to + declare a `static` as being unique per-thread leveraging + LLVM's implementation which works in concert with the kernel + loader and dynamic linker. This is not necessarily available + on all platforms, and usage of it is discouraged. + +* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty + hack that will certainly be removed. + +* `unboxed_closures` - Rust's new closure design, which is currently a work in + progress feature with many known bugs. + +* `allow_internal_unstable` - Allows `macro_rules!` macros to be tagged with the + `#[allow_internal_unstable]` attribute, designed + to allow `std` macros to call + `#[unstable]`/feature-gated functionality + internally without imposing on callers + (i.e. making them behave like function calls in + terms of encapsulation). + +* `default_type_parameter_fallback` - Allows type parameter defaults to + influence type inference. + +* `stmt_expr_attributes` - Allows attributes on expressions. + +* `type_ascription` - Allows type ascription expressions `expr: Type`. + +* `abi_vectorcall` - Allows the usage of the vectorcall calling convention + (e.g. `extern "vectorcall" func fn_();`) + +* `abi_sysv64` - Allows the usage of the system V AMD64 calling convention + (e.g. `extern "sysv64" func fn_();`) + +If a feature is promoted to a language feature, then all existing programs will +start to receive compilation warnings about `#![feature]` directives which enabled +the new feature (because the directive is no longer necessary). However, if a +feature is decided to be removed from the language, errors will be issued (if +there isn't a parser error first). The directive in this case is no longer +necessary, and it's likely that existing code will break if the feature isn't +removed. + +If an unknown feature is found in a directive, it results in a compiler error. +An unknown feature is one which has never been recognized by the compiler. diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md new file mode 100644 index 0000000000000..b617ee3d78fa7 --- /dev/null +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -0,0 +1,35 @@ +## Behavior considered undefined + +The following is a list of behavior which is forbidden in all Rust code, +including within `unsafe` blocks and `unsafe` functions. Type checking provides +the guarantee that these issues are never caused by safe code. + +* Data races +* Dereferencing a null/dangling raw pointer +* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values) + (uninitialized) memory +* Breaking the [pointer aliasing + rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules) + with raw pointers (a subset of the rules used by C) +* `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T` + contains an `UnsafeCell`. Unsafe code must not violate these aliasing + guarantees. +* Mutating non-mutable data (that is, data reached through a shared reference or + data owned by a `let` binding), unless that data is contained within an `UnsafeCell`. +* Invoking undefined behavior via compiler intrinsics: + * Indexing outside of the bounds of an object with `std::ptr::offset` + (`offset` intrinsic), with + the exception of one byte past the end which is permitted. + * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` + intrinsics) on overlapping buffers +* Invalid values in primitive types, even in private fields/locals: + * Dangling/null references or boxes + * A value other than `false` (0) or `true` (1) in a `bool` + * A discriminant in an `enum` not included in the type definition + * A value in a `char` which is a surrogate or above `char::MAX` + * Non-UTF-8 byte sequences in a `str` +* Unwinding into Rust from foreign code or unwinding from Rust into foreign + code. Rust's failure system is not compatible with exception handling in + other languages. Unwinding must be caught and handled at FFI boundaries. + +[noalias]: http://llvm.org/docs/LangRef.html#noalias diff --git a/src/doc/reference/src/behavior-not-considered-unsafe.md b/src/doc/reference/src/behavior-not-considered-unsafe.md new file mode 100644 index 0000000000000..e16103372f552 --- /dev/null +++ b/src/doc/reference/src/behavior-not-considered-unsafe.md @@ -0,0 +1,15 @@ +## Behavior not considered unsafe + +This is a list of behavior not considered *unsafe* in Rust terms, but that may +be undesired. + +* Deadlocks +* Leaks of memory and other resources +* Exiting without calling destructors +* Integer overflow + - Overflow is considered "unexpected" behavior and is always user-error, + unless the `wrapping` primitives are used. In non-optimized builds, the compiler + will insert debug checks that panic on overflow, but in optimized builds overflow + instead results in wrapped values. See [RFC 560] for the rationale and more details. + +[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md diff --git a/src/doc/reference/src/comments.md b/src/doc/reference/src/comments.md new file mode 100644 index 0000000000000..784e19affd9da --- /dev/null +++ b/src/doc/reference/src/comments.md @@ -0,0 +1,20 @@ +# Comments + +Comments in Rust code follow the general C++ style of line (`//`) and +block (`/* ... */`) comment forms. Nested block comments are supported. + +Line comments beginning with exactly _three_ slashes (`///`), and block +comments (`/** ... */`), are interpreted as a special syntax for `doc` +[attributes]. That is, they are equivalent to writing +`#[doc="..."]` around the body of the comment, i.e., `/// Foo` turns into +`#[doc="Foo"]`. + +Line comments beginning with `//!` and block comments `/*! ... */` are +doc comments that apply to the parent of the comment, rather than the item +that follows. That is, they are equivalent to writing `#![doc="..."]` around +the body of the comment. `//!` comments are usually used to document +modules that occupy a source file. + +Non-doc comments are interpreted as a form of whitespace. + +[attributes]: attributes.html diff --git a/src/doc/reference/src/crates-and-source-files.md b/src/doc/reference/src/crates-and-source-files.md new file mode 100644 index 0000000000000..d41a8dc964095 --- /dev/null +++ b/src/doc/reference/src/crates-and-source-files.md @@ -0,0 +1,73 @@ +# Crates and source files + +Although Rust, like any other language, can be implemented by an interpreter as +well as a compiler, the only existing implementation is a compiler, +and the language has +always been designed to be compiled. For these reasons, this section assumes a +compiler. + +Rust's semantics obey a *phase distinction* between compile-time and +run-time.[^phase-distinction] Semantic rules that have a *static +interpretation* govern the success or failure of compilation, while +semantic rules +that have a *dynamic interpretation* govern the behavior of the program at +run-time. + +The compilation model centers on artifacts called _crates_. Each compilation +processes a single crate in source form, and if successful, produces a single +crate in binary form: either an executable or some sort of +library.[^cratesourcefile] + +A _crate_ is a unit of compilation and linking, as well as versioning, +distribution and runtime loading. A crate contains a _tree_ of nested +[module] scopes. The top level of this tree is a module that is +anonymous (from the point of view of paths within the module) and any item +within a crate has a canonical [module path] denoting its location +within the crate's module tree. + +The Rust compiler is always invoked with a single source file as input, and +always produces a single output crate. The processing of that source file may +result in other source files being loaded as modules. Source files have the +extension `.rs`. + +A Rust source file describes a module, the name and location of which — +in the module tree of the current crate — are defined from outside the +source file: either by an explicit `mod_item` in a referencing source file, or +by the name of the crate itself. Every source file is a module, but not every +module needs its own source file: [module definitions][module] can be nested +within one file. + +Each source file contains a sequence of zero or more `item` definitions, and +may optionally begin with any number of [attributes] +that apply to the containing module, most of which influence the behavior of +the compiler. The anonymous crate module can have additional attributes that +apply to the crate as a whole. + +```rust,no_run +// Specify the crate name. +#![crate_name = "projx"] + +// Specify the type of output artifact. +#![crate_type = "lib"] + +// Turn on a warning. +// This can be done in any module, not just the anonymous crate module. +#![warn(non_camel_case_types)] +``` + +A crate that contains a `main` function can be compiled to an executable. If a +`main` function is present, its return type must be `()` +("[unit]") and it must take no arguments. + +[^phase-distinction]: This distinction would also exist in an interpreter. + Static checks like syntactic analysis, type checking, and lints should + happen before the program is executed regardless of when it is executed. + +[^cratesourcefile]: A crate is somewhat analogous to an *assembly* in the + ECMA-335 CLI model, a *library* in the SML/NJ Compilation Manager, a *unit* + in the Owens and Flatt module system, or a *configuration* in Mesa. + +[module]: items.html#modules +[module path]: paths.html +[attributes]: items-and-attributes.html +[unit]: types.html#tuple-types \ No newline at end of file diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md new file mode 100644 index 0000000000000..c9c0496dac61c --- /dev/null +++ b/src/doc/reference/src/expressions.md @@ -0,0 +1,863 @@ +# Expressions + +An expression may have two roles: it always produces a *value*, and it may have +*effects* (otherwise known as "side effects"). An expression *evaluates to* a +value, and has effects during *evaluation*. Many expressions contain +sub-expressions (operands). The meaning of each kind of expression dictates +several things: + +* Whether or not to evaluate the sub-expressions when evaluating the expression +* The order in which to evaluate the sub-expressions +* How to combine the sub-expressions' values to obtain the value of the expression + +In this way, the structure of expressions dictates the structure of execution. +Blocks are just another kind of expression, so blocks, statements, expressions, +and blocks again can recursively nest inside each other to an arbitrary depth. + +### Lvalues, rvalues and temporaries + +Expressions are divided into two main categories: _lvalues_ and _rvalues_. +Likewise within each expression, sub-expressions may occur in _lvalue context_ +or _rvalue context_. The evaluation of an expression depends both on its own +category and the context it occurs within. + +An lvalue is an expression that represents a memory location. These expressions +are [paths](#path-expressions) (which refer to local variables, function and +method arguments, or static variables), dereferences (`*expr`), [indexing +expressions](#index-expressions) (`expr[expr]`), and [field +references](#field-expressions) (`expr.f`). All other expressions are rvalues. + +The left operand of an [assignment](#assignment-expressions) or +[compound-assignment](#compound-assignment-expressions) expression is +an lvalue context, as is the single operand of a unary +[borrow](#unary-operator-expressions). The discriminant or subject of +a [match expression](#match-expressions) may be an lvalue context, if +ref bindings are made, but is otherwise an rvalue context. All other +expression contexts are rvalue contexts. + +When an lvalue is evaluated in an _lvalue context_, it denotes a memory +location; when evaluated in an _rvalue context_, it denotes the value held _in_ +that memory location. + +#### Temporary lifetimes + +When an rvalue is used in an lvalue context, a temporary un-named +lvalue is created and used instead. The lifetime of temporary values +is typically the innermost enclosing statement; the tail expression of +a block is considered part of the statement that encloses the block. + +When a temporary rvalue is being created that is assigned into a `let` +declaration, however, the temporary is created with the lifetime of +the enclosing block instead, as using the enclosing statement (the +`let` declaration) would be a guaranteed error (since a pointer to the +temporary would be stored into a variable, but the temporary would be +freed before the variable could be used). The compiler uses simple +syntactic rules to decide which values are being assigned into a `let` +binding, and therefore deserve a longer temporary lifetime. + +Here are some examples: + +- `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it + is being borrowed, a temporary is created which will be freed after + the innermost enclosing statement (the `let` declaration, in this case). +- `let x = temp().foo()`. This is the same as the previous example, + except that the value of `temp()` is being borrowed via autoref on a + method-call. Here we are assuming that `foo()` is an `&self` method + defined in some trait, say `Foo`. In other words, the expression + `temp().foo()` is equivalent to `Foo::foo(&temp())`. +- `let x = &temp()`. Here, the same temporary is being assigned into + `x`, rather than being passed as a parameter, and hence the + temporary's lifetime is considered to be the enclosing block. +- `let x = SomeStruct { foo: &temp() }`. As in the previous case, the + temporary is assigned into a struct which is then assigned into a + binding, and hence it is given the lifetime of the enclosing block. +- `let x = [ &temp() ]`. As in the previous case, the + temporary is assigned into an array which is then assigned into a + binding, and hence it is given the lifetime of the enclosing block. +- `let ref x = temp()`. In this case, the temporary is created using a ref binding, + but the result is the same: the lifetime is extended to the enclosing block. + +### Moved and copied types + +When a [local variable](variables.html) is used as an +[rvalue](expressions.html#lvalues-rvalues-and-temporaries), the variable will +be copied if its type implements `Copy`. All others are moved. + +## Literal expressions + +A _literal expression_ consists of one of the [literal](tokens.html#literals) forms +described earlier. It directly describes a number, character, string, boolean +value, or the unit value. + +```text +(); // unit type +"hello"; // string type +'5'; // character type +5; // integer type +``` + +## Path expressions + +A [path](paths.html) used as an expression context denotes either a local +variable or an item. Path expressions are +[lvalues](expressions.html#lvalues-rvalues-and-temporaries). + +## Tuple expressions + +Tuples are written by enclosing zero or more comma-separated expressions in +parentheses. They are used to create [tuple-typed](types.html#tuple-types) +values. + +```{.tuple} +(0.0, 4.5); +("a", 4usize, true); +``` + +You can disambiguate a single-element tuple from a value in parentheses with a +comma: + +``` +(0,); // single-element tuple +(0); // zero in parentheses +``` + +## Struct expressions + +There are several forms of struct expressions. A _struct expression_ +consists of the [path](paths.html) of a [struct item](items.html#structs), followed +by a brace-enclosed list of zero or more comma-separated name-value pairs, +providing the field values of a new instance of the struct. A field name can be +any identifier, and is separated from its value expression by a colon. The +location denoted by a struct field is mutable if and only if the enclosing +struct is mutable. + +A _tuple struct expression_ consists of the [path](paths.html) of a [struct +item](items.html#structs), followed by a parenthesized list of one or more +comma-separated expressions (in other words, the path of a struct item followed +by a tuple expression). The struct item must be a tuple struct item. + +A _unit-like struct expression_ consists only of the [path](paths.html) of a +[struct item](items.html#structs). + +The following are examples of struct expressions: + +``` +# struct Point { x: f64, y: f64 } +# struct NothingInMe { } +# struct TuplePoint(f64, f64); +# mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } } +# struct Cookie; fn some_fn(t: T) {} +Point {x: 10.0, y: 20.0}; +NothingInMe {}; +TuplePoint(10.0, 20.0); +let u = game::User {name: "Joe", age: 35, score: 100_000}; +some_fn::(Cookie); +``` + +A struct expression forms a new value of the named struct type. Note +that for a given *unit-like* struct type, this will always be the same +value. + +A struct expression can terminate with the syntax `..` followed by an +expression to denote a functional update. The expression following `..` (the +base) must have the same struct type as the new struct type being formed. +The entire expression denotes the result of constructing a new struct (with +the same type as the base expression) with the given values for the fields that +were explicitly specified and the values in the base expression for all other +fields. + +``` +# struct Point3d { x: i32, y: i32, z: i32 } +let base = Point3d {x: 1, y: 2, z: 3}; +Point3d {y: 0, z: 10, .. base}; +``` + +#### Struct field init shorthand + +When initializing a data structure (struct, enum, union) with named fields, +it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. +This allows a compact syntax with less duplication. + +Example: + +``` +# struct Point3d { x: i32, y: i32, z: i32 } +# let x = 0; +# let y_value = 0; +# let z = 0; +Point3d { x: x, y: y_value, z: z }; +Point3d { x, y: y_value, z }; +``` + +## Block expressions + +A _block expression_ is similar to a module in terms of the declarations that +are possible. Each block conceptually introduces a new namespace scope. Use +items can bring new names into scopes and declared items are in scope for only +the block itself. + +A block will execute each statement sequentially, and then execute the +expression (if given). If the block ends in a statement, its value is `()`: + +``` +let x: () = { println!("Hello."); }; +``` + +If it ends in an expression, its value and type are that of the expression: + +``` +let x: i32 = { println!("Hello."); 5 }; + +assert_eq!(5, x); +``` + +## Method-call expressions + +A _method call_ consists of an expression followed by a single dot, an +identifier, and a parenthesized expression-list. Method calls are resolved to +methods on specific traits, either statically dispatching to a method if the +exact `self`-type of the left-hand-side is known, or dynamically dispatching if +the left-hand-side expression is an indirect [trait +object](types.html#trait-objects). + +## Field expressions + +A _field expression_ consists of an expression followed by a single dot and an +identifier, when not immediately followed by a parenthesized expression-list +(the latter is a [method call expression](#method-call-expressions)). A field +expression denotes a field of a [struct](types.html#struct-types). + +```{.ignore .field} +mystruct.myfield; +foo().x; +(Struct {a: 10, b: 20}).a; +``` + +A field access is an [lvalue](expressions.html#lvalues-rvalues-and-temporaries) +referring to the value of that field. When the type providing the field +inherits mutability, it can be [assigned](#assignment-expressions) to. + +Also, if the type of the expression to the left of the dot is a +pointer, it is automatically dereferenced as many times as necessary +to make the field access possible. In cases of ambiguity, we prefer +fewer autoderefs to more. + +## Array expressions + +An [array](types.html#array-and-slice-types) _expression_ is written by +enclosing zero or more comma-separated expressions of uniform type in square +brackets. + +In the `[expr ';' expr]` form, the expression after the `';'` must be a +constant expression that can be evaluated at compile time, such as a +[literal](tokens.html#literals) or a [static item](items.html#static-items). + +``` +[1, 2, 3, 4]; +["a", "b", "c", "d"]; +[0; 128]; // array with 128 zeros +[0u8, 0u8, 0u8, 0u8]; +``` + +## Index expressions + +[Array](types.html#array-and-slice-types)-typed expressions can be indexed by +writing a square-bracket-enclosed expression (the index) after them. When the +array is mutable, the resulting +[lvalue](expressions.html#lvalues-rvalues-and-temporaries) can be assigned to. + +Indices are zero-based, and may be of any integral type. Vector access is +bounds-checked at compile-time for constant arrays being accessed with a +constant index value. Otherwise a check will be performed at run-time that +will put the thread in a _panicked state_ if it fails. + +```{should-fail} +([1, 2, 3, 4])[0]; + +let x = (["a", "b"])[10]; // compiler error: const index-expr is out of bounds + +let n = 10; +let y = (["a", "b"])[n]; // panics + +let arr = ["a", "b"]; +arr[10]; // panics +``` + +Also, if the type of the expression to the left of the brackets is a +pointer, it is automatically dereferenced as many times as necessary +to make the indexing possible. In cases of ambiguity, we prefer fewer +autoderefs to more. + +## Range expressions + +The `..` operator will construct an object of one of the `std::ops::Range` variants. + +``` +1..2; // std::ops::Range +3..; // std::ops::RangeFrom +..4; // std::ops::RangeTo +..; // std::ops::RangeFull +``` + +The following expressions are equivalent. + +``` +let x = std::ops::Range {start: 0, end: 10}; +let y = 0..10; + +assert_eq!(x, y); +``` + +Similarly, the `...` operator will construct an object of one of the +`std::ops::RangeInclusive` variants. + +``` +# #![feature(inclusive_range_syntax)] +1...2; // std::ops::RangeInclusive +...4; // std::ops::RangeToInclusive +``` + +The following expressions are equivalent. + +``` +# #![feature(inclusive_range_syntax, inclusive_range)] +let x = std::ops::RangeInclusive::NonEmpty {start: 0, end: 10}; +let y = 0...10; + +assert_eq!(x, y); +``` + +## Unary operator expressions + +Rust defines the following unary operators. With the exception of `?`, they are +all written as prefix operators, before the expression they apply to. + +* `-` + : Negation. Signed integer types and floating-point types support negation. It + is an error to apply negation to unsigned types; for example, the compiler + rejects `-1u32`. +* `*` + : Dereference. When applied to a [pointer](types.html#pointer-types) it + denotes the pointed-to location. For pointers to mutable locations, the + resulting [lvalue](expressions.html#lvalues-rvalues-and-temporaries) can be + assigned to. On non-pointer types, it calls the `deref` method of the + `std::ops::Deref` trait, or the `deref_mut` method of the + `std::ops::DerefMut` trait (if implemented by the type and required for an + outer expression that will or could mutate the dereference), and produces + the result of dereferencing the `&` or `&mut` borrowed pointer returned + from the overload method. +* `!` + : Logical negation. On the boolean type, this flips between `true` and + `false`. On integer types, this inverts the individual bits in the + two's complement representation of the value. +* `&` and `&mut` + : Borrowing. When applied to an lvalue, these operators produce a + reference (pointer) to the lvalue. The lvalue is also placed into + a borrowed state for the duration of the reference. For a shared + borrow (`&`), this implies that the lvalue may not be mutated, but + it may be read or shared again. For a mutable borrow (`&mut`), the + lvalue may not be accessed in any way until the borrow expires. + If the `&` or `&mut` operators are applied to an rvalue, a + temporary value is created; the lifetime of this temporary value + is defined by [syntactic rules](#temporary-lifetimes). +* `?` + : Propagating errors if applied to `Err(_)` and unwrapping if + applied to `Ok(_)`. Only works on the `Result` type, + and written in postfix notation. + +## Binary operator expressions + +Binary operators expressions are given in terms of [operator +precedence](#operator-precedence). + +### Arithmetic operators + +Binary arithmetic expressions are syntactic sugar for calls to built-in traits, +defined in the `std::ops` module of the `std` library. This means that +arithmetic operators can be overridden for user-defined types. The default +meaning of the operators on standard types is given here. + +* `+` + : Addition and array/string concatenation. + Calls the `add` method on the `std::ops::Add` trait. +* `-` + : Subtraction. + Calls the `sub` method on the `std::ops::Sub` trait. +* `*` + : Multiplication. + Calls the `mul` method on the `std::ops::Mul` trait. +* `/` + : Quotient. + Calls the `div` method on the `std::ops::Div` trait. +* `%` + : Remainder. + Calls the `rem` method on the `std::ops::Rem` trait. + +### Bitwise operators + +Like the [arithmetic operators](#arithmetic-operators), bitwise operators are +syntactic sugar for calls to methods of built-in traits. This means that +bitwise operators can be overridden for user-defined types. The default +meaning of the operators on standard types is given here. Bitwise `&`, `|` and +`^` applied to boolean arguments are equivalent to logical `&&`, `||` and `!=` +evaluated in non-lazy fashion. + +* `&` + : Bitwise AND. + Calls the `bitand` method of the `std::ops::BitAnd` trait. +* `|` + : Bitwise inclusive OR. + Calls the `bitor` method of the `std::ops::BitOr` trait. +* `^` + : Bitwise exclusive OR. + Calls the `bitxor` method of the `std::ops::BitXor` trait. +* `<<` + : Left shift. + Calls the `shl` method of the `std::ops::Shl` trait. +* `>>` + : Right shift (arithmetic). + Calls the `shr` method of the `std::ops::Shr` trait. + +### Lazy boolean operators + +The operators `||` and `&&` may be applied to operands of boolean type. The +`||` operator denotes logical 'or', and the `&&` operator denotes logical +'and'. They differ from `|` and `&` in that the right-hand operand is only +evaluated when the left-hand operand does not already determine the result of +the expression. That is, `||` only evaluates its right-hand operand when the +left-hand operand evaluates to `false`, and `&&` only when it evaluates to +`true`. + +### Comparison operators + +Comparison operators are, like the [arithmetic +operators](#arithmetic-operators), and [bitwise operators](#bitwise-operators), +syntactic sugar for calls to built-in traits. This means that comparison +operators can be overridden for user-defined types. The default meaning of the +operators on standard types is given here. + +* `==` + : Equal to. + Calls the `eq` method on the `std::cmp::PartialEq` trait. +* `!=` + : Unequal to. + Calls the `ne` method on the `std::cmp::PartialEq` trait. +* `<` + : Less than. + Calls the `lt` method on the `std::cmp::PartialOrd` trait. +* `>` + : Greater than. + Calls the `gt` method on the `std::cmp::PartialOrd` trait. +* `<=` + : Less than or equal. + Calls the `le` method on the `std::cmp::PartialOrd` trait. +* `>=` + : Greater than or equal. + Calls the `ge` method on the `std::cmp::PartialOrd` trait. + +### Type cast expressions + +A type cast expression is denoted with the binary operator `as`. + +Executing an `as` expression casts the value on the left-hand side to the type +on the right-hand side. + +An example of an `as` expression: + +``` +# fn sum(values: &[f64]) -> f64 { 0.0 } +# fn len(values: &[f64]) -> i32 { 0 } + +fn average(values: &[f64]) -> f64 { + let sum: f64 = sum(values); + let size: f64 = len(values) as f64; + sum / size +} +``` + +Some of the conversions which can be done through the `as` operator +can also be done implicitly at various points in the program, such as +argument passing and assignment to a `let` binding with an explicit +type. Implicit conversions are limited to "harmless" conversions that +do not lose information and which have minimal or no risk of +surprising side-effects on the dynamic execution semantics. + +### Assignment expressions + +An _assignment expression_ consists of an +[lvalue](expressions.html#lvalues-rvalues-and-temporaries) expression followed +by an equals sign (`=`) and an +[rvalue](expressions.html#lvalues-rvalues-and-temporaries) expression. + +Evaluating an assignment expression [either copies or +moves](#moved-and-copied-types) its right-hand operand to its left-hand +operand. + +``` +# let mut x = 0; +# let y = 0; +x = y; +``` + +### Compound assignment expressions + +The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be +composed with the `=` operator. The expression `lval OP= val` is equivalent to +`lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. + +Any such expression always has the [`unit`](types.html#tuple-types) type. + +### Operator precedence + +The precedence of Rust binary operators is ordered as follows, going from +strong to weak: + +```{.text .precedence} +as : +* / % ++ - +<< >> +& +^ +| +== != < > <= >= +&& +|| +.. ... +<- += +``` + +Operators at the same precedence level are evaluated left-to-right. [Unary +operators](#unary-operator-expressions) have the same precedence level and are +stronger than any of the binary operators. + +## Grouped expressions + +An expression enclosed in parentheses evaluates to the result of the enclosed +expression. Parentheses can be used to explicitly specify evaluation order +within an expression. + +An example of a parenthesized expression: + +``` +let x: i32 = (2 + 3) * 4; +``` + + +## Call expressions + +A _call expression_ invokes a function, providing zero or more input variables +and an optional location to move the function's output into. If the function +eventually returns, then the expression completes. + +Some examples of call expressions: + +``` +# fn add(x: i32, y: i32) -> i32 { 0 } + +let x: i32 = add(1i32, 2i32); +let pi: Result = "3.14".parse(); +``` + +## Lambda expressions + +A _lambda expression_ (sometimes called an "anonymous function expression") +defines a function and denotes it as a value, in a single expression. A lambda +expression is a pipe-symbol-delimited (`|`) list of identifiers followed by an +expression. + +A lambda expression denotes a function that maps a list of parameters +(`ident_list`) onto the expression that follows the `ident_list`. The +identifiers in the `ident_list` are the parameters to the function. These +parameters' types need not be specified, as the compiler infers them from +context. + +Lambda expressions are most useful when passing functions as arguments to other +functions, as an abbreviation for defining and capturing a separate function. + +Significantly, lambda expressions _capture their environment_, which regular +[function definitions](items.html#functions) do not. The exact type of capture +depends on the [function type](types.html#function-types) inferred for the +lambda expression. In the simplest and least-expensive form (analogous to a +```|| { }``` expression), the lambda expression captures its environment by +reference, effectively borrowing pointers to all outer variables mentioned +inside the function. Alternately, the compiler may infer that a lambda +expression should copy or move values (depending on their type) from the +environment into the lambda expression's captured environment. A lambda can be +forced to capture its environment by moving values by prefixing it with the +`move` keyword. + +In this example, we define a function `ten_times` that takes a higher-order +function argument, and we then call it with a lambda expression as an argument, +followed by a lambda expression that moves values from its environment. + +``` +fn ten_times(f: F) where F: Fn(i32) { + for index in 0..10 { + f(index); + } +} + +ten_times(|j| println!("hello, {}", j)); + +let word = "konnichiwa".to_owned(); +ten_times(move |j| println!("{}, {}", word, j)); +``` + +## Infinite loops + +A `loop` expression denotes an infinite loop. + +A `loop` expression may optionally have a _label_. The label is written as +a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a +label is present, then labeled `break` and `continue` expressions nested +within this loop may exit out of this loop or return control to its head. +See [break expressions](#break-expressions) and [continue +expressions](#continue-expressions). + +## `break` expressions + +A `break` expression has an optional _label_. If the label is absent, then +executing a `break` expression immediately terminates the innermost loop +enclosing it. It is only permitted in the body of a loop. If the label is +present, then `break 'foo` terminates the loop with label `'foo`, which need not +be the innermost label enclosing the `break` expression, but must enclose it. + +## `continue` expressions + +A `continue` expression has an optional _label_. If the label is absent, then +executing a `continue` expression immediately terminates the current iteration +of the innermost loop enclosing it, returning control to the loop *head*. In +the case of a `while` loop, the head is the conditional expression controlling +the loop. In the case of a `for` loop, the head is the call-expression +controlling the loop. If the label is present, then `continue 'foo` returns +control to the head of the loop with label `'foo`, which need not be the +innermost label enclosing the `continue` expression, but must enclose it. + +A `continue` expression is only permitted in the body of a loop. + +## `while` loops + +A `while` loop begins by evaluating the boolean loop conditional expression. +If the loop conditional expression evaluates to `true`, the loop body block +executes and control returns to the loop conditional expression. If the loop +conditional expression evaluates to `false`, the `while` expression completes. + +An example: + +``` +let mut i = 0; + +while i < 10 { + println!("hello"); + i = i + 1; +} +``` + +Like `loop` expressions, `while` loops can be controlled with `break` or +`continue`, and may optionally have a _label_. See [infinite +loops](#infinite-loops), [break expressions](#break-expressions), and +[continue expressions](#continue-expressions) for more information. + +## `for` expressions + +A `for` expression is a syntactic construct for looping over elements provided +by an implementation of `std::iter::IntoIterator`. + +An example of a `for` loop over the contents of an array: + +``` +# type Foo = i32; +# fn bar(f: &Foo) { } +# let a = 0; +# let b = 0; +# let c = 0; + +let v: &[Foo] = &[a, b, c]; + +for e in v { + bar(e); +} +``` + +An example of a for loop over a series of integers: + +``` +# fn bar(b:usize) { } +for i in 0..256 { + bar(i); +} +``` + +Like `loop` expressions, `for` loops can be controlled with `break` or +`continue`, and may optionally have a _label_. See [infinite +loops](#infinite-loops), [break expressions](#break-expressions), and +[continue expressions](#continue-expressions) for more information. + +## `if` expressions + +An `if` expression is a conditional branch in program control. The form of an +`if` expression is a condition expression, followed by a consequent block, any +number of `else if` conditions and blocks, and an optional trailing `else` +block. The condition expressions must have type `bool`. If a condition +expression evaluates to `true`, the consequent block is executed and any +subsequent `else if` or `else` block is skipped. If a condition expression +evaluates to `false`, the consequent block is skipped and any subsequent `else +if` condition is evaluated. If all `if` and `else if` conditions evaluate to +`false` then any `else` block is executed. + +## `match` expressions + +A `match` expression branches on a *pattern*. The exact form of matching that +occurs depends on the pattern. Patterns consist of some combination of +literals, destructured arrays or enum constructors, structs and tuples, +variable binding specifications, wildcards (`..`), and placeholders (`_`). A +`match` expression has a *head expression*, which is the value to compare to +the patterns. The type of the patterns must equal the type of the head +expression. + +In a pattern whose head expression has an `enum` type, a placeholder (`_`) +stands for a *single* data field, whereas a wildcard `..` stands for *all* the +fields of a particular variant. + +A `match` behaves differently depending on whether or not the head expression +is an [lvalue or an rvalue](expressions.html#lvalues-rvalues-and-temporaries). +If the head expression is an rvalue, it is first evaluated into a temporary +location, and the resulting value is sequentially compared to the patterns in +the arms until a match is found. The first arm with a matching pattern is +chosen as the branch target of the `match`, any variables bound by the pattern +are assigned to local variables in the arm's block, and control enters the +block. + +When the head expression is an lvalue, the match does not allocate a temporary +location (however, a by-value binding may copy or move from the lvalue). When +possible, it is preferable to match on lvalues, as the lifetime of these +matches inherits the lifetime of the lvalue, rather than being restricted to +the inside of the match. + +An example of a `match` expression: + +``` +let x = 1; + +match x { + 1 => println!("one"), + 2 => println!("two"), + 3 => println!("three"), + 4 => println!("four"), + 5 => println!("five"), + _ => println!("something else"), +} +``` + +Patterns that bind variables default to binding to a copy or move of the +matched value (depending on the matched value's type). This can be changed to +bind to a reference by using the `ref` keyword, or to a mutable reference using +`ref mut`. + +Subpatterns can also be bound to variables by the use of the syntax `variable @ +subpattern`. For example: + +``` +let x = 1; + +match x { + e @ 1 ... 5 => println!("got a range element {}", e), + _ => println!("anything"), +} +``` + +Patterns can also dereference pointers by using the `&`, `&mut` and `box` +symbols, as appropriate. For example, these two matches on `x: &i32` are +equivalent: + +``` +# let x = &3; +let y = match *x { 0 => "zero", _ => "some" }; +let z = match x { &0 => "zero", _ => "some" }; + +assert_eq!(y, z); +``` + +Multiple match patterns may be joined with the `|` operator. A range of values +may be specified with `...`. For example: + +``` +# let x = 2; + +let message = match x { + 0 | 1 => "not many", + 2 ... 9 => "a few", + _ => "lots" +}; +``` + +Range patterns only work on scalar types (like integers and characters; not +like arrays and structs, which have sub-components). A range pattern may not +be a sub-range of another range pattern inside the same `match`. + +Finally, match patterns can accept *pattern guards* to further refine the +criteria for matching a case. Pattern guards appear after the pattern and +consist of a bool-typed expression following the `if` keyword. A pattern guard +may refer to the variables bound within the pattern they follow. + +``` +# let maybe_digit = Some(0); +# fn process_digit(i: i32) { } +# fn process_other(i: i32) { } + +let message = match maybe_digit { + Some(x) if x < 10 => process_digit(x), + Some(x) => process_other(x), + None => panic!(), +}; +``` + +## `if let` expressions + +An `if let` expression is semantically identical to an `if` expression but in +place of a condition expression it expects a `let` statement with a refutable +pattern. If the value of the expression on the right hand side of the `let` +statement matches the pattern, the corresponding block will execute, otherwise +flow proceeds to the first `else` block that follows. + +``` +let dish = ("Ham", "Eggs"); + +// this body will be skipped because the pattern is refuted +if let ("Bacon", b) = dish { + println!("Bacon is served with {}", b); +} + +// this body will execute +if let ("Ham", b) = dish { + println!("Ham is served with {}", b); +} +``` + +## `while let` loops + +A `while let` loop is semantically identical to a `while` loop but in place of +a condition expression it expects `let` statement with a refutable pattern. If +the value of the expression on the right hand side of the `let` statement +matches the pattern, the loop body block executes and control returns to the +pattern matching statement. Otherwise, the while expression completes. + +## `return` expressions + +Return expressions are denoted with the keyword `return`. Evaluating a `return` +expression moves its argument into the designated output location for the +current function call, destroys the current function activation frame, and +transfers control to the caller frame. + +An example of a `return` expression: + +``` +fn max(a: i32, b: i32) -> i32 { + if a > b { + return a; + } + return b; +} +``` diff --git a/src/doc/reference/src/identifiers.md b/src/doc/reference/src/identifiers.md new file mode 100644 index 0000000000000..de657e3e312d5 --- /dev/null +++ b/src/doc/reference/src/identifiers.md @@ -0,0 +1,24 @@ +# Identifiers + +An identifier is any nonempty Unicode[^non_ascii_idents] string of the following form: + +Either + + * The first character has property `XID_start` + * The remaining characters have property `XID_continue` + +Or + + * The first character is `_` + * The identifier is more than one character, `_` alone is not an identifier + * The remaining characters have property `XID_continue` + +that does _not_ occur in the set of [keywords]. + +> **Note**: `XID_start` and `XID_continue` as character properties cover the +> character ranges used to form the more familiar C and Java language-family +> identifiers. + +[keywords]: ../grammar.html#keywords +[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature + gated. This is expected to improve soon. diff --git a/src/doc/reference/src/influences.md b/src/doc/reference/src/influences.md new file mode 100644 index 0000000000000..46082bfc0b006 --- /dev/null +++ b/src/doc/reference/src/influences.md @@ -0,0 +1,22 @@ +# Influences + +Rust is not a particularly original language, with design elements coming from +a wide range of sources. Some of these are listed below (including elements +that have since been removed): + +* SML, OCaml: algebraic data types, pattern matching, type inference, + semicolon statement separation +* C++: references, RAII, smart pointers, move semantics, monomorphization, + memory model +* ML Kit, Cyclone: region based memory management +* Haskell (GHC): typeclasses, type families +* Newsqueak, Alef, Limbo: channels, concurrency +* Erlang: message passing, thread failure, linked thread failure, + lightweight concurrency +* Swift: optional bindings +* Scheme: hygienic macros +* C#: attributes +* Ruby: block syntax +* NIL, Hermes: typestate +* [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and + pattern syntax diff --git a/src/doc/reference/src/input-format.md b/src/doc/reference/src/input-format.md new file mode 100644 index 0000000000000..0dbba4be92a05 --- /dev/null +++ b/src/doc/reference/src/input-format.md @@ -0,0 +1,10 @@ +# Input format + +Rust input is interpreted as a sequence of Unicode code points encoded in UTF-8. +Most Rust grammar rules are defined in terms of printable ASCII-range +code points, but a small number are defined in terms of Unicode properties or +explicit code point lists. [^inputformat] + +[^inputformat]: Substitute definitions for the special Unicode productions are + provided to the grammar verifier, restricted to ASCII range, when verifying the + grammar in this document. diff --git a/src/doc/reference/src/introduction.md b/src/doc/reference/src/introduction.md new file mode 100644 index 0000000000000..3a00dfa4572bf --- /dev/null +++ b/src/doc/reference/src/introduction.md @@ -0,0 +1,31 @@ +# Introduction + +This document is the primary reference for the Rust programming language. It +provides three kinds of material: + + - Chapters that informally describe each language construct and their use. + - Chapters that informally describe the memory model, concurrency model, + runtime services, linkage model and debugging facilities. + - Appendix chapters providing rationale and references to languages that + influenced the design. + +This document does not serve as an introduction to the language. Background +familiarity with the language is assumed. A separate [book] is available to +help acquire such background familiarity. + +This document also does not serve as a reference to the [standard] library +included in the language distribution. Those libraries are documented +separately by extracting documentation attributes from their source code. Many +of the features that one might expect to be language features are library +features in Rust, so what you're looking for may be there, not here. + +Finally, this document is not normative. It may include details that are +specific to `rustc` itself, and should not be taken as a specification for +the Rust language. We intend to produce such a document someday, but this +is what we have for now. + +You may also be interested in the [grammar]. + +[book]: ../book/index.html +[standard]: ../std/index.html +[grammar]: ../grammar.html diff --git a/src/doc/reference/src/items-and-attributes.md b/src/doc/reference/src/items-and-attributes.md new file mode 100644 index 0000000000000..bd5018d69cc78 --- /dev/null +++ b/src/doc/reference/src/items-and-attributes.md @@ -0,0 +1,7 @@ +# Items and attributes + +Crates contain [items], each of which may have some number of +[attributes] attached to it. + +[items]: items.html +[attributes]: attributes.html diff --git a/src/doc/reference/src/items.md b/src/doc/reference/src/items.md new file mode 100644 index 0000000000000..ba3f4195ba62d --- /dev/null +++ b/src/doc/reference/src/items.md @@ -0,0 +1,1091 @@ +# Items + +An _item_ is a component of a crate. Items are organized within a crate by a +nested set of [modules]. Every crate has a single "outermost" +anonymous module; all further items within the crate have [paths] +within the module tree of the crate. + +[modules]: #modules +[paths]: paths.html + +Items are entirely determined at compile-time, generally remain fixed during +execution, and may reside in read-only memory. + +There are several kinds of item: + +* [`extern crate` declarations](#extern-crate-declarations) +* [`use` declarations](#use-declarations) +* [modules](#modules) +* [function definitions](#functions) +* [`extern` blocks](#external-blocks) +* [type definitions](../grammar.html#type-definitions) +* [struct definitions](#structs) +* [enumeration definitions](#enumerations) +* [constant items](#constant-items) +* [static items](#static-items) +* [trait definitions](#traits) +* [implementations](#implementations) + +Some items form an implicit scope for the declaration of sub-items. In other +words, within a function or module, declarations of items can (in many cases) +be mixed with the statements, control blocks, and similar artifacts that +otherwise compose the item body. The meaning of these scoped items is the same +as if the item was declared outside the scope — it is still a static item +— except that the item's *path name* within the module namespace is +qualified by the name of the enclosing item, or is private to the enclosing +item (in the case of functions). The grammar specifies the exact locations in +which sub-item declarations may appear. + +## Type Parameters + +All items except modules, constants and statics may be *parameterized* by type. +Type parameters are given as a comma-separated list of identifiers enclosed in +angle brackets (`<...>`), after the name of the item and before its definition. +The type parameters of an item are considered "part of the name", not part of +the type of the item. A referencing [path] must (in principle) provide +type arguments as a list of comma-separated types enclosed within angle +brackets, in order to refer to the type-parameterized item. In practice, the +type-inference system can usually infer such argument types from context. There +are no general type-parametric types, only type-parametric items. That is, Rust +has no notion of type abstraction: there are no higher-ranked (or "forall") types +abstracted over other types, though higher-ranked types do exist for lifetimes. + +[path]: paths.html + +## Modules + +A module is a container for zero or more [items]. + +[items]: items.html + +A _module item_ is a module, surrounded in braces, named, and prefixed with the +keyword `mod`. A module item introduces a new, named module into the tree of +modules making up a crate. Modules can nest arbitrarily. + +An example of a module: + +```rust +mod math { + type Complex = (f64, f64); + fn sin(f: f64) -> f64 { + /* ... */ +# panic!(); + } + fn cos(f: f64) -> f64 { + /* ... */ +# panic!(); + } + fn tan(f: f64) -> f64 { + /* ... */ +# panic!(); + } +} +``` + +Modules and types share the same namespace. Declaring a named type with +the same name as a module in scope is forbidden: that is, a type definition, +trait, struct, enumeration, or type parameter can't shadow the name of a module +in scope, or vice versa. + +A module without a body is loaded from an external file, by default with the +same name as the module, plus the `.rs` extension. When a nested submodule is +loaded from an external file, it is loaded from a subdirectory path that +mirrors the module hierarchy. + +```rust,ignore +// Load the `vec` module from `vec.rs` +mod vec; + +mod thread { + // Load the `local_data` module from `thread/local_data.rs` + // or `thread/local_data/mod.rs`. + mod local_data; +} +``` + +The directories and files used for loading external file modules can be +influenced with the `path` attribute. + +```rust,ignore +#[path = "thread_files"] +mod thread { + // Load the `local_data` module from `thread_files/tls.rs` + #[path = "tls.rs"] + mod local_data; +} +``` + +### Extern crate declarations + +An _`extern crate` declaration_ specifies a dependency on an external crate. +The external crate is then bound into the declaring scope as the `ident` +provided in the `extern_crate_decl`. + +The external crate is resolved to a specific `soname` at compile time, and a +runtime linkage requirement to that `soname` is passed to the linker for +loading at runtime. The `soname` is resolved at compile time by scanning the +compiler's library path and matching the optional `crateid` provided against +the `crateid` attributes that were declared on the external crate when it was +compiled. If no `crateid` is provided, a default `name` attribute is assumed, +equal to the `ident` given in the `extern_crate_decl`. + +Three examples of `extern crate` declarations: + +```rust,ignore +extern crate pcre; + +extern crate std; // equivalent to: extern crate std as std; + +extern crate std as ruststd; // linking to 'std' under another name +``` + +When naming Rust crates, hyphens are disallowed. However, Cargo packages may +make use of them. In such case, when `Cargo.toml` doesn't specify a crate name, +Cargo will transparently replace `-` with `_` (Refer to [RFC 940] for more +details). + +Here is an example: + +```rust,ignore +// Importing the Cargo package hello-world +extern crate hello_world; // hyphen replaced with an underscore +``` + +[RFC 940]: https://github.com/rust-lang/rfcs/blob/master/text/0940-hyphens-considered-harmful.md + +### Use declarations + +A _use declaration_ creates one or more local name bindings synonymous with +some other [path]. Usually a `use` declaration is used to shorten the +path required to refer to a module item. These declarations may appear in +[modules] and [blocks], usually at the top. + +[path]: paths.html +[modules]: #modules +[blocks]: ../grammar.html#block-expressions + +> **Note**: Unlike in many languages, +> `use` declarations in Rust do *not* declare linkage dependency with external crates. +> Rather, [`extern crate` declarations](#extern-crate-declarations) declare linkage dependencies. + +Use declarations support a number of convenient shortcuts: + +* Rebinding the target name as a new local name, using the syntax `use p::q::r as x;` +* Simultaneously binding a list of paths differing only in their final element, + using the glob-like brace syntax `use a::b::{c,d,e,f};` +* Binding all paths matching a given prefix, using the asterisk wildcard syntax + `use a::b::*;` +* Simultaneously binding a list of paths differing only in their final element + and their immediate parent module, using the `self` keyword, such as + `use a::b::{self, c, d};` + +An example of `use` declarations: + +```rust +use std::option::Option::{Some, None}; +use std::collections::hash_map::{self, HashMap}; + +fn foo(_: T){} +fn bar(map1: HashMap, map2: hash_map::HashMap){} + +fn main() { + // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), + // std::option::Option::None]);' + foo(vec![Some(1.0f64), None]); + + // Both `hash_map` and `HashMap` are in scope. + let map1 = HashMap::new(); + let map2 = hash_map::HashMap::new(); + bar(map1, map2); +} +``` + +Like items, `use` declarations are private to the containing module, by +default. Also like items, a `use` declaration can be public, if qualified by +the `pub` keyword. Such a `use` declaration serves to _re-export_ a name. A +public `use` declaration can therefore _redirect_ some public name to a +different target definition: even a definition with a private canonical path, +inside a different module. If a sequence of such redirections form a cycle or +cannot be resolved unambiguously, they represent a compile-time error. + +An example of re-exporting: + +```rust +# fn main() { } +mod quux { + pub use quux::foo::{bar, baz}; + + pub mod foo { + pub fn bar() { } + pub fn baz() { } + } +} +``` + +In this example, the module `quux` re-exports two public names defined in +`foo`. + +Also note that the paths contained in `use` items are relative to the crate +root. So, in the previous example, the `use` refers to `quux::foo::{bar, +baz}`, and not simply to `foo::{bar, baz}`. This also means that top-level +module declarations should be at the crate root if direct usage of the declared +modules within `use` items is desired. It is also possible to use `self` and +`super` at the beginning of a `use` item to refer to the current and direct +parent modules respectively. All rules regarding accessing declared modules in +`use` declarations apply to both module declarations and `extern crate` +declarations. + +An example of what will and will not work for `use` items: + +```rust +# #![allow(unused_imports)] +use foo::baz::foobaz; // good: foo is at the root of the crate + +mod foo { + + mod example { + pub mod iter {} + } + + use foo::example::iter; // good: foo is at crate root +// use example::iter; // bad: example is not at the crate root + use self::baz::foobaz; // good: self refers to module 'foo' + use foo::bar::foobar; // good: foo is at crate root + + pub mod bar { + pub fn foobar() { } + } + + pub mod baz { + use super::bar::foobar; // good: super refers to module 'foo' + pub fn foobaz() { } + } +} + +fn main() {} +``` + +## Functions + +A _function item_ defines a sequence of [statements] and a +final [expression], along with a name and a set of +parameters. Other than a name, all these are optional. +Functions are declared with the keyword `fn`. Functions may declare a +set of *input* [*variables*][variables] as parameters, through which the caller +passes arguments into the function, and the *output* [*type*][type] +of the value the function will return to its caller on completion. + +[statements]: statements.html +[expression]: expressions.html +[variables]: variables.html +[type]: types.html + +A function may also be copied into a first-class *value*, in which case the +value has the corresponding [*function type*][function type], and can be used +otherwise exactly as a function item (with a minor additional cost of calling +the function indirectly). + +[function type]: types.html#function-types + +Every control path in a function logically ends with a `return` expression or a +diverging expression. If the outermost block of a function has a +value-producing expression in its final-expression position, that expression is +interpreted as an implicit `return` expression applied to the final-expression. + +An example of a function: + +```rust +fn add(x: i32, y: i32) -> i32 { + x + y +} +``` + +As with `let` bindings, function arguments are irrefutable patterns, so any +pattern that is valid in a let binding is also valid as an argument. + +```rust +fn first((value, _): (i32, i32)) -> i32 { value } +``` + + +### Generic functions + +A _generic function_ allows one or more _parameterized types_ to appear in its +signature. Each type parameter must be explicitly declared in an +angle-bracket-enclosed and comma-separated list, following the function name. + +```rust,ignore +// foo is generic over A and B + +fn foo(x: A, y: B) { +``` + +Inside the function signature and body, the name of the type parameter can be +used as a type name. [Trait](#traits) bounds can be specified for type parameters +to allow methods with that trait to be called on values of that type. This is +specified using the `where` syntax: + +```rust,ignore +fn foo(x: T) where T: Debug { +``` + +When a generic function is referenced, its type is instantiated based on the +context of the reference. For example, calling the `foo` function here: + +```rust +use std::fmt::Debug; + +fn foo(x: &[T]) where T: Debug { + // details elided + # () +} + +foo(&[1, 2]); +``` + +will instantiate type parameter `T` with `i32`. + +The type parameters can also be explicitly supplied in a trailing +[path] component after the function name. This might be necessary if +there is not sufficient context to determine the type parameters. For example, +`mem::size_of::() == 4`. + +[path]: paths.html + +### Diverging functions + +A special kind of function can be declared with a `!` character where the +output type would normally be. For example: + +```rust +fn my_err(s: &str) -> ! { + println!("{}", s); + panic!(); +} +``` + +We call such functions "diverging" because they never return a value to the +caller. Every control path in a diverging function must end with a `panic!()` or +a call to another diverging function on every control path. The `!` annotation +does *not* denote a type. + +It might be necessary to declare a diverging function because as mentioned +previously, the typechecker checks that every control path in a function ends +with a [`return`] or diverging expression. So, if `my_err` +were declared without the `!` annotation, the following code would not +typecheck: + +[`return`]: expressions.html#return-expressions + +```rust +# fn my_err(s: &str) -> ! { panic!() } + +fn f(i: i32) -> i32 { + if i == 42 { + return 42; + } + else { + my_err("Bad number!"); + } +} +``` + +This will not compile without the `!` annotation on `my_err`, since the `else` +branch of the conditional in `f` does not return an `i32`, as required by the +signature of `f`. Adding the `!` annotation to `my_err` informs the +typechecker that, should control ever enter `my_err`, no further type judgments +about `f` need to hold, since control will never resume in any context that +relies on those judgments. Thus the return type on `f` only needs to reflect +the `if` branch of the conditional. + +### Extern functions + +Extern functions are part of Rust's foreign function interface, providing the +opposite functionality to [external blocks](#external-blocks). Whereas +external blocks allow Rust code to call foreign code, extern functions with +bodies defined in Rust code _can be called by foreign code_. They are defined +in the same way as any other Rust function, except that they have the `extern` +modifier. + +```rust +// Declares an extern fn, the ABI defaults to "C" +extern fn new_i32() -> i32 { 0 } + +// Declares an extern fn with "stdcall" ABI +extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } +``` + +Unlike normal functions, extern fns have type `extern "ABI" fn()`. This is the +same type as the functions declared in an extern block. + +```rust +# extern fn new_i32() -> i32 { 0 } +let fptr: extern "C" fn() -> i32 = new_i32; +``` + +Extern functions may be called directly from Rust code as Rust uses large, +contiguous stack segments like C. + +## Type aliases + +A _type alias_ defines a new name for an existing [type]. Type +aliases are declared with the keyword `type`. Every value has a single, +specific type, but may implement several different traits, or be compatible with +several different type constraints. + +[type]: types.html + +For example, the following defines the type `Point` as a synonym for the type +`(u8, u8)`, the type of pairs of unsigned 8 bit integers: + +```rust +type Point = (u8, u8); +let p: Point = (41, 68); +``` + +Currently a type alias to an enum type cannot be used to qualify the +constructors: + +```rust +enum E { A } +type F = E; +let _: F = E::A; // OK +// let _: F = F::A; // Doesn't work +``` + +## Structs + +A _struct_ is a nominal [struct type] defined with the +keyword `struct`. + +An example of a `struct` item and its use: + +```rust +struct Point {x: i32, y: i32} +let p = Point {x: 10, y: 11}; +let px: i32 = p.x; +``` + +A _tuple struct_ is a nominal [tuple type], also defined with +the keyword `struct`. For example: + +[struct type]: types.html#struct-types +[tuple type]: types.html#tuple-types + +```rust +struct Point(i32, i32); +let p = Point(10, 11); +let px: i32 = match p { Point(x, _) => x }; +``` + +A _unit-like struct_ is a struct without any fields, defined by leaving off +the list of fields entirely. Such a struct implicitly defines a constant of +its type with the same name. For example: + +```rust +struct Cookie; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +is equivalent to + +```rust +struct Cookie {} +const Cookie: Cookie = Cookie {}; +let c = [Cookie, Cookie {}, Cookie, Cookie {}]; +``` + +The precise memory layout of a struct is not specified. One can specify a +particular layout using the [`repr` attribute]. + +[`repr` attribute]: attributes.html#ffi-attributes + +## Enumerations + +An _enumeration_ is a simultaneous definition of a nominal [enumerated +type] as well as a set of *constructors*, that can be used +to create or pattern-match values of the corresponding enumerated type. + +[enumerated type]: types.html#enumerated-types + +Enumerations are declared with the keyword `enum`. + +An example of an `enum` item and its use: + +```rust +enum Animal { + Dog, + Cat, +} + +let mut a: Animal = Animal::Dog; +a = Animal::Cat; +``` + +Enumeration constructors can have either named or unnamed fields: + +```rust +enum Animal { + Dog (String, f64), + Cat { name: String, weight: f64 }, +} + +let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2); +a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; +``` + +In this example, `Cat` is a _struct-like enum variant_, +whereas `Dog` is simply called an enum variant. + +Each enum value has a _discriminant_ which is an integer associated to it. You +can specify it explicitly: + +```rust +enum Foo { + Bar = 123, +} +``` + +The right hand side of the specification is interpreted as an `isize` value, +but the compiler is allowed to use a smaller type in the actual memory layout. +The [`repr` attribute] can be added in order to change +the type of the right hand side and specify the memory layout. + +[`repr` attribute]: attributes.html#ffi-attributes + +If a discriminant isn't specified, they start at zero, and add one for each +variant, in order. + +You can cast an enum to get its discriminant: + +```rust +# enum Foo { Bar = 123 } +let x = Foo::Bar as u32; // x is now 123u32 +``` + +This only works as long as none of the variants have data attached. If +it were `Bar(i32)`, this is disallowed. + +## Constant items + +A *constant item* is a named _constant value_ which is not associated with a +specific memory location in the program. Constants are essentially inlined +wherever they are used, meaning that they are copied directly into the relevant +context when used. References to the same constant are not necessarily +guaranteed to refer to the same memory address. + +Constant values must not have destructors, and otherwise permit most forms of +data. Constants may refer to the address of other constants, in which case the +address will have elided lifetimes where applicable, otherwise – in most cases – +defaulting to the `static` lifetime. (See below on [static lifetime elision].) +The compiler is, however, still at liberty to translate the constant many times, +so the address referred to may not be stable. + +[static lifetime elision]: #static-lifetime-elision + +Constants must be explicitly typed. The type may be `bool`, `char`, a number, or +a type derived from those primitive types. The derived types are references with +the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs. + +```rust +const BIT1: u32 = 1 << 0; +const BIT2: u32 = 1 << 1; + +const BITS: [u32; 2] = [BIT1, BIT2]; +const STRING: &'static str = "bitstring"; + +struct BitsNStrings<'a> { + mybits: [u32; 2], + mystring: &'a str, +} + +const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { + mybits: BITS, + mystring: STRING, +}; +``` + +## Static items + +A *static item* is similar to a *constant*, except that it represents a precise +memory location in the program. A static is never "inlined" at the usage site, +and all references to it refer to the same memory location. Static items have +the `static` lifetime, which outlives all other lifetimes in a Rust program. +Static items may be placed in read-only memory if they do not contain any +interior mutability. + +Statics may contain interior mutability through the `UnsafeCell` language item. +All access to a static is safe, but there are a number of restrictions on +statics: + +* Statics may not contain any destructors. +* The types of static values must ascribe to `Sync` to allow thread-safe access. +* Statics may not refer to other statics by value, only by reference. +* Constants cannot refer to statics. + +Constants should in general be preferred over statics, unless large amounts of +data are being stored, or single-address and mutability properties are required. + +### Mutable statics + +If a static item is declared with the `mut` keyword, then it is allowed to +be modified by the program. One of Rust's goals is to make concurrency bugs +hard to run into, and this is obviously a very large source of race conditions +or other bugs. For this reason, an `unsafe` block is required when either +reading or writing a mutable static variable. Care should be taken to ensure +that modifications to a mutable static are safe with respect to other threads +running in the same process. + +Mutable statics are still very useful, however. They can be used with C +libraries and can also be bound from C libraries (in an `extern` block). + +```rust +# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 } + +static mut LEVELS: u32 = 0; + +// This violates the idea of no shared state, and this doesn't internally +// protect against races, so this function is `unsafe` +unsafe fn bump_levels_unsafe1() -> u32 { + let ret = LEVELS; + LEVELS += 1; + return ret; +} + +// Assuming that we have an atomic_add function which returns the old value, +// this function is "safe" but the meaning of the return value may not be what +// callers expect, so it's still marked as `unsafe` +unsafe fn bump_levels_unsafe2() -> u32 { + return atomic_add(&mut LEVELS, 1); +} +``` + +Mutable statics have the same restrictions as normal statics, except that the +type of the value is not required to ascribe to `Sync`. + +#### `'static` lifetime elision + +[Unstable] Both constant and static declarations of reference types have +*implicit* `'static` lifetimes unless an explicit lifetime is specified. As +such, the constant declarations involving `'static` above may be written +without the lifetimes. Returning to our previous example: + +```rust +# #![feature(static_in_const)] +const BIT1: u32 = 1 << 0; +const BIT2: u32 = 1 << 1; + +const BITS: [u32; 2] = [BIT1, BIT2]; +const STRING: &str = "bitstring"; + +struct BitsNStrings<'a> { + mybits: [u32; 2], + mystring: &'a str, +} + +const BITS_N_STRINGS: BitsNStrings = BitsNStrings { + mybits: BITS, + mystring: STRING, +}; +``` + +Note that if the `static` or `const` items include function or closure +references, which themselves include references, the compiler will first try the +standard elision rules ([see discussion in the nomicon][elision-nomicon]). If it +is unable to resolve the lifetimes by its usual rules, it will default to using +the `'static` lifetime. By way of example: + +[elision-nomicon]: ../nomicon/lifetime-elision.html + +```rust,ignore +// Resolved as `fn<'a>(&'a str) -> &'a str`. +const RESOLVED_SINGLE: fn(&str) -> &str = .. + +// Resolved as `Fn<'a, 'b, 'c>(&'a Foo, &'b Bar, &'c Baz) -> usize`. +const RESOLVED_MULTIPLE: Fn(&Foo, &Bar, &Baz) -> usize = .. + +// There is insufficient information to bound the return reference lifetime +// relative to the argument lifetimes, so the signature is resolved as +// `Fn(&'static Foo, &'static Bar) -> &'static Baz`. +const RESOLVED_STATIC: Fn(&Foo, &Bar) -> &Baz = .. +``` + +### Traits + +A _trait_ describes an abstract interface that types can +implement. This interface consists of associated items, which come in +three varieties: + +- functions +- constants +- types + +Associated functions whose first parameter is named `self` are called +methods and may be invoked using `.` notation (e.g., `x.foo()`). + +All traits define an implicit type parameter `Self` that refers to +"the type that is implementing this interface". Traits may also +contain additional type parameters. These type parameters (including +`Self`) may be constrained by other traits and so forth as usual. + +Trait bounds on `Self` are considered "supertraits". These are +required to be acyclic. Supertraits are somewhat different from other +constraints in that they affect what methods are available in the +vtable when the trait is used as a [trait object]. + +Traits are implemented for specific types through separate +[implementations]. + +Consider the following trait: + +```rust +# type Surface = i32; +# type BoundingBox = i32; +trait Shape { + fn draw(&self, Surface); + fn bounding_box(&self) -> BoundingBox; +} +``` + +This defines a trait with two methods. All values that have +[implementations] of this trait in scope can have their +`draw` and `bounding_box` methods called, using `value.bounding_box()` +[syntax]. + +[trait object]: types.html#trait-objects +[implementations]: #implementations +[syntax]: expressions.html#method-call-expressions + +Traits can include default implementations of methods, as in: + +```rust +trait Foo { + fn bar(&self); + fn baz(&self) { println!("We called baz."); } +} +``` + +Here the `baz` method has a default implementation, so types that implement +`Foo` need only implement `bar`. It is also possible for implementing types +to override a method that has a default implementation. + +Type parameters can be specified for a trait to make it generic. These appear +after the trait name, using the same syntax used in [generic +functions](#generic-functions). + +```rust +trait Seq { + fn len(&self) -> u32; + fn elt_at(&self, n: u32) -> T; + fn iter(&self, F) where F: Fn(T); +} +``` + +It is also possible to define associated types for a trait. Consider the +following example of a `Container` trait. Notice how the type is available +for use in the method signatures: + +```rust +trait Container { + type E; + fn empty() -> Self; + fn insert(&mut self, Self::E); +} +``` + +In order for a type to implement this trait, it must not only provide +implementations for every method, but it must specify the type `E`. Here's +an implementation of `Container` for the standard library type `Vec`: + +```rust +# trait Container { +# type E; +# fn empty() -> Self; +# fn insert(&mut self, Self::E); +# } +impl Container for Vec { + type E = T; + fn empty() -> Vec { Vec::new() } + fn insert(&mut self, x: T) { self.push(x); } +} +``` + +Generic functions may use traits as _bounds_ on their type parameters. This +will have two effects: + +- Only types that have the trait may instantiate the parameter. +- Within the generic function, the methods of the trait can be + called on values that have the parameter's type. + +For example: + +```rust +# type Surface = i32; +# trait Shape { fn draw(&self, Surface); } +fn draw_twice(surface: Surface, sh: T) { + sh.draw(surface); + sh.draw(surface); +} +``` + +Traits also define a [trait object] with the same +name as the trait. Values of this type are created by coercing from a +pointer of some specific type to a pointer of trait type. For example, +`&T` could be coerced to `&Shape` if `T: Shape` holds (and similarly +for `Box`). This coercion can either be implicit or +[explicit]. Here is an example of an explicit +coercion: + +[trait object]: types.html#trait-objects +[explicit]: expressions.html#type-cast-expressions + +```rust +trait Shape { } +impl Shape for i32 { } +let mycircle = 0i32; +let myshape: Box = Box::new(mycircle) as Box; +``` + +The resulting value is a box containing the value that was cast, along with +information that identifies the methods of the implementation that was used. +Values with a trait type can have [methods called] on +them, for any method in the trait, and can be used to instantiate type +parameters that are bounded by the trait. + +[methods called]: expressions.html#method-call-expressions + +Trait methods may be static, which means that they lack a `self` argument. +This means that they can only be called with function call syntax (`f(x)`) and +not method call syntax (`obj.f()`). The way to refer to the name of a static +method is to qualify it with the trait name, treating the trait name like a +module. For example: + +```rust +trait Num { + fn from_i32(n: i32) -> Self; +} +impl Num for f64 { + fn from_i32(n: i32) -> f64 { n as f64 } +} +let x: f64 = Num::from_i32(42); +``` + +Traits may inherit from other traits. Consider the following example: + +```rust +trait Shape { fn area(&self) -> f64; } +trait Circle : Shape { fn radius(&self) -> f64; } +``` + +The syntax `Circle : Shape` means that types that implement `Circle` must also +have an implementation for `Shape`. Multiple supertraits are separated by `+`, +`trait Circle : Shape + PartialEq { }`. In an implementation of `Circle` for a +given type `T`, methods can refer to `Shape` methods, since the typechecker +checks that any type with an implementation of `Circle` also has an +implementation of `Shape`: + +```rust +struct Foo; + +trait Shape { fn area(&self) -> f64; } +trait Circle : Shape { fn radius(&self) -> f64; } +impl Shape for Foo { + fn area(&self) -> f64 { + 0.0 + } +} +impl Circle for Foo { + fn radius(&self) -> f64 { + println!("calling area: {}", self.area()); + + 0.0 + } +} + +let c = Foo; +c.radius(); +``` + +In type-parameterized functions, methods of the supertrait may be called on +values of subtrait-bound type parameters. Referring to the previous example of +`trait Circle : Shape`: + +```rust +# trait Shape { fn area(&self) -> f64; } +# trait Circle : Shape { fn radius(&self) -> f64; } +fn radius_times_area(c: T) -> f64 { + // `c` is both a Circle and a Shape + c.radius() * c.area() +} +``` + +Likewise, supertrait methods may also be called on trait objects. + +```rust,ignore +# trait Shape { fn area(&self) -> f64; } +# trait Circle : Shape { fn radius(&self) -> f64; } +# impl Shape for i32 { fn area(&self) -> f64 { 0.0 } } +# impl Circle for i32 { fn radius(&self) -> f64 { 0.0 } } +# let mycircle = 0i32; +let mycircle = Box::new(mycircle) as Box; +let nonsense = mycircle.radius() * mycircle.area(); +``` + +### Implementations + +An _implementation_ is an item that implements a [trait](#traits) for a +specific type. + +Implementations are defined with the keyword `impl`. + +```rust +# #[derive(Copy, Clone)] +# struct Point {x: f64, y: f64}; +# type Surface = i32; +# struct BoundingBox {x: f64, y: f64, width: f64, height: f64}; +# trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; } +# fn do_draw_circle(s: Surface, c: Circle) { } +struct Circle { + radius: f64, + center: Point, +} + +impl Copy for Circle {} + +impl Clone for Circle { + fn clone(&self) -> Circle { *self } +} + +impl Shape for Circle { + fn draw(&self, s: Surface) { do_draw_circle(s, *self); } + fn bounding_box(&self) -> BoundingBox { + let r = self.radius; + BoundingBox { + x: self.center.x - r, + y: self.center.y - r, + width: 2.0 * r, + height: 2.0 * r, + } + } +} +``` + +It is possible to define an implementation without referring to a trait. The +methods in such an implementation can only be used as direct calls on the values +of the type that the implementation targets. In such an implementation, the +trait type and `for` after `impl` are omitted. Such implementations are limited +to nominal types (enums, structs, trait objects), and the implementation must +appear in the same crate as the `self` type: + +```rust +struct Point {x: i32, y: i32} + +impl Point { + fn log(&self) { + println!("Point is at ({}, {})", self.x, self.y); + } +} + +let my_point = Point {x: 10, y:11}; +my_point.log(); +``` + +When a trait _is_ specified in an `impl`, all methods declared as part of the +trait must be implemented, with matching types and type parameter counts. + +An implementation can take type parameters, which can be different from the +type parameters taken by the trait it implements. Implementation parameters +are written after the `impl` keyword. + +```rust +# trait Seq { fn dummy(&self, _: T) { } } +impl Seq for Vec { + /* ... */ +} +impl Seq for u32 { + /* Treat the integer as a sequence of bits */ +} +``` + +### External blocks + +External blocks form the basis for Rust's foreign function interface. +Declarations in an external block describe symbols in external, non-Rust +libraries. + +Functions within external blocks are declared in the same way as other Rust +functions, with the exception that they may not have a body and are instead +terminated by a semicolon. + +Functions within external blocks may be called by Rust code, just like +functions defined in Rust. The Rust compiler automatically translates between +the Rust ABI and the foreign ABI. + +Functions within external blocks may be variadic by specifying `...` after one +or more named arguments in the argument list: + +```rust,ignore +extern { + fn foo(x: i32, ...); +} +``` + +A number of [attributes] control the behavior of external blocks. + +[attributes]: attributes.html#ffi-attributes + +By default external blocks assume that the library they are calling uses the +standard C ABI on the specific platform. Other ABIs may be specified using an +`abi` string, as shown here: + +```rust,ignore +// Interface to the Windows API +extern "stdcall" { } +``` + +There are three ABI strings which are cross-platform, and which all compilers +are guaranteed to support: + +* `extern "Rust"` -- The default ABI when you write a normal `fn foo()` in any + Rust code. +* `extern "C"` -- This is the same as `extern fn foo()`; whatever the default + your C compiler supports. +* `extern "system"` -- Usually the same as `extern "C"`, except on Win32, in + which case it's `"stdcall"`, or what you should use to link to the Windows API + itself + +There are also some platform-specific ABI strings: + +* `extern "cdecl"` -- The default for x86\_32 C code. +* `extern "stdcall"` -- The default for the Win32 API on x86\_32. +* `extern "win64"` -- The default for C code on x86\_64 Windows. +* `extern "sysv64"` -- The default for C code on non-Windows x86\_64. +* `extern "aapcs"` -- The default for ARM. +* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's + `__fastcall` and GCC and clang's `__attribute__((fastcall))` +* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's + `__vectorcall` and clang's `__attribute__((vectorcall))` + +Finally, there are some rustc-specific ABI strings: + +* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics. +* `extern "rust-call"` -- The ABI of the Fn::call trait functions. +* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for + example, `sqrt` -- have this ABI. You should never have to deal with it. + +The `link` attribute allows the name of the library to be specified. When +specified the compiler will attempt to link against the native library of the +specified name. + +```rust,ignore +#[link(name = "crypto")] +extern { } +``` + +The type of a function declared in an extern block is `extern "abi" fn(A1, ..., +An) -> R`, where `A1...An` are the declared types of its arguments and `R` is +the declared return type. + +It is valid to add the `link` attribute on an empty extern block. You can use +this to satisfy the linking requirements of extern blocks elsewhere in your code +(including upstream crates) instead of adding the attribute to each extern block. diff --git a/src/doc/reference/src/lexical-structure.md b/src/doc/reference/src/lexical-structure.md new file mode 100644 index 0000000000000..5e1388e0d5a2b --- /dev/null +++ b/src/doc/reference/src/lexical-structure.md @@ -0,0 +1 @@ +# Lexical structure diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md new file mode 100644 index 0000000000000..4755e4be8b685 --- /dev/null +++ b/src/doc/reference/src/linkage.md @@ -0,0 +1,127 @@ +# Linkage + +The Rust compiler supports various methods to link crates together both +statically and dynamically. This section will explore the various methods to +link Rust crates together, and more information about native libraries can be +found in the [FFI section of the book][ffi]. + +[ffi]: ../book/ffi.html + +In one session of compilation, the compiler can generate multiple artifacts +through the usage of either command line flags or the `crate_type` attribute. +If one or more command line flags are specified, all `crate_type` attributes will +be ignored in favor of only building the artifacts specified by command line. + +* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be + produced. This requires that there is a `main` function in the crate which + will be run when the program begins executing. This will link in all Rust and + native dependencies, producing a distributable binary. + +* `--crate-type=lib`, `#[crate_type = "lib"]` - A Rust library will be produced. + This is an ambiguous concept as to what exactly is produced because a library + can manifest itself in several forms. The purpose of this generic `lib` option + is to generate the "compiler recommended" style of library. The output library + will always be usable by rustc, but the actual type of library may change from + time-to-time. The remaining output types are all different flavors of + libraries, and the `lib` type can be seen as an alias for one of them (but the + actual one is compiler-defined). + +* `--crate-type=dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will + be produced. This is different from the `lib` output type in that this forces + dynamic library generation. The resulting dynamic library can be used as a + dependency for other libraries and/or executables. This output type will + create `*.so` files on linux, `*.dylib` files on osx, and `*.dll` files on + windows. + +* `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system + library will be produced. This is different from other library outputs in that + the Rust compiler will never attempt to link to `staticlib` outputs. The + purpose of this output type is to create a static library containing all of + the local crate's code along with all upstream dependencies. The static + library is actually a `*.a` archive on linux and osx and a `*.lib` file on + windows. This format is recommended for use in situations such as linking + Rust code into an existing non-Rust application because it will not have + dynamic dependencies on other Rust code. + +* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system + library will be produced. This is used when compiling Rust code as + a dynamic library to be loaded from another language. This output type will + create `*.so` files on Linux, `*.dylib` files on OSX, and `*.dll` files on + Windows. + +* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be + produced. This is used as an intermediate artifact and can be thought of as a + "static Rust library". These `rlib` files, unlike `staticlib` files, are + interpreted by the Rust compiler in future linkage. This essentially means + that `rustc` will look for metadata in `rlib` files like it looks for metadata + in dynamic libraries. This form of output is used to produce statically linked + executables as well as `staticlib` outputs. + +* `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output + produced is not specified, but if a `-L` path is provided to it then the + compiler will recognize the output artifacts as a macro and it can be loaded + for a program. If a crate is compiled with the `proc-macro` crate type it + will forbid exporting any items in the crate other than those functions + tagged `#[proc_macro_derive]` and those functions must also be placed at the + crate root. Finally, the compiler will automatically set the + `cfg(proc_macro)` annotation whenever any crate type of a compilation is the + `proc-macro` crate type. + +Note that these outputs are stackable in the sense that if multiple are +specified, then the compiler will produce each form of output at once without +having to recompile. However, this only applies for outputs specified by the +same method. If only `crate_type` attributes are specified, then they will all +be built, but if one or more `--crate-type` command line flags are specified, +then only those outputs will be built. + +With all these different kinds of outputs, if crate A depends on crate B, then +the compiler could find B in various different forms throughout the system. The +only forms looked for by the compiler, however, are the `rlib` format and the +dynamic library format. With these two options for a dependent library, the +compiler must at some point make a choice between these two formats. With this +in mind, the compiler follows these rules when determining what format of +dependencies will be used: + +1. If a static library is being produced, all upstream dependencies are + required to be available in `rlib` formats. This requirement stems from the + reason that a dynamic library cannot be converted into a static format. + + Note that it is impossible to link in native dynamic dependencies to a static + library, and in this case warnings will be printed about all unlinked native + dynamic dependencies. + +2. If an `rlib` file is being produced, then there are no restrictions on what + format the upstream dependencies are available in. It is simply required that + all upstream dependencies be available for reading metadata from. + + The reason for this is that `rlib` files do not contain any of their upstream + dependencies. It wouldn't be very efficient for all `rlib` files to contain a + copy of `libstd.rlib`! + +3. If an executable is being produced and the `-C prefer-dynamic` flag is not + specified, then dependencies are first attempted to be found in the `rlib` + format. If some dependencies are not available in an rlib format, then + dynamic linking is attempted (see below). + +4. If a dynamic library or an executable that is being dynamically linked is + being produced, then the compiler will attempt to reconcile the available + dependencies in either the rlib or dylib format to create a final product. + + A major goal of the compiler is to ensure that a library never appears more + than once in any artifact. For example, if dynamic libraries B and C were + each statically linked to library A, then a crate could not link to B and C + together because there would be two copies of A. The compiler allows mixing + the rlib and dylib formats, but this restriction must be satisfied. + + The compiler currently implements no method of hinting what format a library + should be linked with. When dynamically linking, the compiler will attempt to + maximize dynamic dependencies while still allowing some dependencies to be + linked in via an rlib. + + For most situations, having all libraries available as a dylib is recommended + if dynamically linking. For other situations, the compiler will emit a + warning if it is unable to determine which formats to link each library with. + +In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for +all compilation needs, and the other options are just available if more +fine-grained control is desired over the output format of a Rust crate. diff --git a/src/doc/reference/src/macros-by-example.md b/src/doc/reference/src/macros-by-example.md new file mode 100644 index 0000000000000..a007b232e4c97 --- /dev/null +++ b/src/doc/reference/src/macros-by-example.md @@ -0,0 +1,88 @@ +# Macros By Example + +`macro_rules` allows users to define syntax extension in a declarative way. We +call such extensions "macros by example" or simply "macros". + +Currently, macros can expand to expressions, statements, items, or patterns. + +(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is +any token other than a delimiter or `$`.) + +The macro expander looks up macro invocations by name, and tries each macro +rule in turn. It transcribes the first successful match. Matching and +transcription are closely related to each other, and we will describe them +together. + +The macro expander matches and transcribes every token that does not begin with +a `$` literally, including delimiters. For parsing reasons, delimiters must be +balanced, but they are otherwise not special. + +In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust +syntax named by _designator_. Valid designators are: + +* `item`: an [item] +* `block`: a [block] +* `stmt`: a [statement] +* `pat`: a [pattern] +* `expr`: an [expression] +* `ty`: a [type] +* `ident`: an [identifier] +* `path`: a [path] +* `tt`: a token tree (a single [token] by matching `()`, `[]`, or `{}`) +* `meta`: the contents of an [attribute] + +[item]: items.html +[block]: expressions.html#block-expressions +[statement]: statements.html +[pattern]: expressions.html#match-expressions +[expression]: expressions.html +[type]: types.html +[identifier]: identifiers.html +[path]: paths.html +[token]: tokens.html +[attribute]: attributes.html + +In the transcriber, the +designator is already known, and so only the name of a matched nonterminal comes +after the dollar sign. + +In both the matcher and transcriber, the Kleene star-like operator indicates +repetition. The Kleene star operator consists of `$` and parentheses, optionally +followed by a separator token, followed by `*` or `+`. `*` means zero or more +repetitions, `+` means at least one repetition. The parentheses are not matched or +transcribed. On the matcher side, a name is bound to _all_ of the names it +matches, in a structure that mimics the structure of the repetition encountered +on a successful match. The job of the transcriber is to sort that structure +out. + +The rules for transcription of these repetitions are called "Macro By Example". +Essentially, one "layer" of repetition is discharged at a time, and all of them +must be discharged by the time a name is transcribed. Therefore, `( $( $i:ident +),* ) => ( $i )` is an invalid macro, but `( $( $i:ident ),* ) => ( $( $i:ident +),* )` is acceptable (if trivial). + +When Macro By Example encounters a repetition, it examines all of the `$` +_name_ s that occur in its body. At the "current layer", they all must repeat +the same number of times, so ` ( $( $i:ident ),* ; $( $j:ident ),* ) => ( $( +($i,$j) ),* )` is valid if given the argument `(a,b,c ; d,e,f)`, but not +`(a,b,c ; d,e)`. The repetition walks through the choices at that layer in +lockstep, so the former input transcribes to `(a,d), (b,e), (c,f)`. + +Nested repetitions are allowed. + +### Parsing limitations + +The parser used by the macro system is reasonably powerful, but the parsing of +Rust syntax is restricted in two ways: + +1. Macro definitions are required to include suitable separators after parsing + expressions and other bits of the Rust grammar. This implies that + a macro definition like `$i:expr [ , ]` is not legal, because `[` could be part + of an expression. A macro definition like `$i:expr,` or `$i:expr;` would be legal, + however, because `,` and `;` are legal separators. See [RFC 550] for more information. +2. The parser must have eliminated all ambiguity by the time it reaches a `$` + _name_ `:` _designator_. This requirement most often affects name-designator + pairs when they occur at the beginning of, or immediately after, a `$(...)*`; + requiring a distinctive token in front can solve the problem. + +[RFC 550]: https://github.com/rust-lang/rfcs/blob/master/text/0550-macro-future-proofing.md diff --git a/src/doc/reference/src/macros.md b/src/doc/reference/src/macros.md new file mode 100644 index 0000000000000..9ec5f2d6945e5 --- /dev/null +++ b/src/doc/reference/src/macros.md @@ -0,0 +1,17 @@ +# Macros + +A number of minor features of Rust are not central enough to have their own +syntax, and yet are not implementable as functions. Instead, they are given +names, and invoked through a consistent syntax: `some_extension!(...)`. + +Users of `rustc` can define new macros in two ways: + +* [Macros] define new syntax in a higher-level, + declarative way. +* [Procedural Macros] can be used to implement custom derive. + +And one unstable way: [compiler plugins]. + +[Macros]: ../book/macros.html +[Procedural Macros]: ../book/procedural-macros.html +[compiler plugins]: ../book/compiler-plugins.html diff --git a/src/doc/reference/src/memory-allocation-and-lifetime.md b/src/doc/reference/src/memory-allocation-and-lifetime.md new file mode 100644 index 0000000000000..24addb1dd39d4 --- /dev/null +++ b/src/doc/reference/src/memory-allocation-and-lifetime.md @@ -0,0 +1,13 @@ +# Memory allocation and lifetime + +The _items_ of a program are those functions, modules and types that have their +value calculated at compile-time and stored uniquely in the memory image of the +rust process. Items are neither dynamically allocated nor freed. + +The _heap_ is a general term that describes boxes. The lifetime of an +allocation in the heap depends on the lifetime of the box values pointing to +it. Since box values may themselves be passed in and out of frames, or stored +in the heap, heap allocations may outlive the frame they are allocated within. +An allocation in the heap is guaranteed to reside at a single location in the +heap for the whole lifetime of the allocation - it will never be relocated as +a result of moving a box value. diff --git a/src/doc/reference/src/memory-model.md b/src/doc/reference/src/memory-model.md new file mode 100644 index 0000000000000..aa57ae6ae9bea --- /dev/null +++ b/src/doc/reference/src/memory-model.md @@ -0,0 +1,10 @@ +# Memory model + +A Rust program's memory consists of a static set of *items* and a *heap*. +Immutable portions of the heap may be safely shared between threads, mutable +portions may not be safely shared, but several mechanisms for effectively-safe +sharing of mutable values, built on unsafe code but enforcing a safe locking +discipline, exist in the standard library. + +Allocations in the stack consist of *variables*, and allocations in the heap +consist of *boxes*. diff --git a/src/doc/reference/src/memory-ownership.md b/src/doc/reference/src/memory-ownership.md new file mode 100644 index 0000000000000..aed07ef2961a5 --- /dev/null +++ b/src/doc/reference/src/memory-ownership.md @@ -0,0 +1,4 @@ +## Memory ownership + +When a stack frame is exited, its local allocations are all released, and its +references to boxes are dropped. diff --git a/src/doc/reference/src/notation.md b/src/doc/reference/src/notation.md new file mode 100644 index 0000000000000..642bff440ad93 --- /dev/null +++ b/src/doc/reference/src/notation.md @@ -0,0 +1 @@ +# Notation diff --git a/src/doc/reference/src/paths.md b/src/doc/reference/src/paths.md new file mode 100644 index 0000000000000..e9fd07e5664b9 --- /dev/null +++ b/src/doc/reference/src/paths.md @@ -0,0 +1,105 @@ +# Paths + +A _path_ is a sequence of one or more path components _logically_ separated by +a namespace qualifier (`::`). If a path consists of only one component, it may +refer to either an [item] or a [variable] in a local control +scope. If a path has multiple components, it refers to an item. + +[item]: items.html +[variable]: variables.html + +Every item has a _canonical path_ within its crate, but the path naming an item +is only meaningful within a given crate. There is no global namespace across +crates; an item's canonical path merely identifies it within the crate. + +Two examples of simple paths consisting of only identifier components: + +```{.ignore} +x; +x::y::z; +``` + +Path components are usually [identifiers], but they may +also include angle-bracket-enclosed lists of type arguments. In +[expression] context, the type argument list is given +after a `::` namespace qualifier in order to disambiguate it from a +relational expression involving the less-than symbol (`<`). In type +expression context, the final namespace qualifier is omitted. + +[identifiers]: identifiers.html +[expression]: expressions.html + +Two examples of paths with type arguments: + +```rust +# struct HashMap(K,V); +# fn f() { +# fn id(t: T) -> T { t } +type T = HashMap; // Type arguments used in a type expression +let x = id::(10); // Type arguments used in a call expression +# } +``` + +Paths can be denoted with various leading qualifiers to change the meaning of +how it is resolved: + +* Paths starting with `::` are considered to be global paths where the + components of the path start being resolved from the crate root. Each + identifier in the path must resolve to an item. + +```rust +mod a { + pub fn foo() {} +} +mod b { + pub fn foo() { + ::a::foo(); // call a's foo function + } +} +# fn main() {} +``` + +* Paths starting with the keyword `super` begin resolution relative to the + parent module. Each further identifier must resolve to an item. + +```rust +mod a { + pub fn foo() {} +} +mod b { + pub fn foo() { + super::a::foo(); // call a's foo function + } +} +# fn main() {} +``` + +* Paths starting with the keyword `self` begin resolution relative to the + current module. Each further identifier must resolve to an item. + +```rust +fn foo() {} +fn bar() { + self::foo(); +} +# fn main() {} +``` + +Additionally keyword `super` may be repeated several times after the first +`super` or `self` to refer to ancestor modules. + +```rust +mod a { + fn foo() {} + + mod b { + mod c { + fn foo() { + super::super::foo(); // call a's foo function + self::super::super::foo(); // call a's foo function + } + } + } +} +# fn main() {} +``` diff --git a/src/doc/reference/src/procedural-macros.md b/src/doc/reference/src/procedural-macros.md new file mode 100644 index 0000000000000..b1fd35653d9e7 --- /dev/null +++ b/src/doc/reference/src/procedural-macros.md @@ -0,0 +1,23 @@ +## Procedural Macros + +"Procedural macros" are the second way to implement a macro. For now, the only +thing they can be used for is to implement derive on your own types. See +[the book][procedural macros] for a tutorial. + +[procedural macros]: ../book/procedural-macros.html + +Procedural macros involve a few different parts of the language and its +standard libraries. First is the `proc_macro` crate, included with Rust, +that defines an interface for building a procedural macro. The +`#[proc_macro_derive(Foo)]` attribute is used to mark the deriving +function. This function must have the type signature: + +```rust,ignore +use proc_macro::TokenStream; + +#[proc_macro_derive(Hello)] +pub fn hello_world(input: TokenStream) -> TokenStream +``` + +Finally, procedural macros must be in their own crate, with the `proc-macro` +crate type. diff --git a/src/doc/reference/src/special-traits.md b/src/doc/reference/src/special-traits.md new file mode 100644 index 0000000000000..ae3eebe392d1d --- /dev/null +++ b/src/doc/reference/src/special-traits.md @@ -0,0 +1,3 @@ +# Special traits + +Several traits define special evaluation behavior. diff --git a/src/doc/reference/src/statements-and-expressions.md b/src/doc/reference/src/statements-and-expressions.md new file mode 100644 index 0000000000000..bb59108f17f32 --- /dev/null +++ b/src/doc/reference/src/statements-and-expressions.md @@ -0,0 +1,11 @@ +# Statements and expressions + +Rust is _primarily_ an expression language. This means that most forms of +value-producing or effect-causing evaluation are directed by the uniform syntax +category of _expressions_. Each kind of expression can typically _nest_ within +each other kind of expression, and rules for evaluation of expressions involve +specifying both the value produced by the expression and the order in which its +sub-expressions are themselves evaluated. + +In contrast, statements in Rust serve _mostly_ to contain and explicitly +sequence expression evaluation. diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md new file mode 100644 index 0000000000000..ebb7d8bfa7cd0 --- /dev/null +++ b/src/doc/reference/src/statements.md @@ -0,0 +1,42 @@ +# Statements + +A _statement_ is a component of a block, which is in turn a component of an +outer [expression](expressions.html) or [function](items.html#functions). + +Rust has two kinds of statement: [declaration +statements](#declaration-statements) and [expression +statements](#expression-statements). + +## Declaration statements + +A _declaration statement_ is one that introduces one or more *names* into the +enclosing statement block. The declared names may denote new variables or new +items. + +### Item declarations + +An _item declaration statement_ has a syntactic form identical to an +[item](items.html) declaration within a module. Declaring an item — a +function, enumeration, struct, type, static, trait, implementation or module +— locally within a statement block is simply a way of restricting its +scope to a narrow region containing all of its uses; it is otherwise identical +in meaning to declaring the item outside the statement block. + +> **Note**: there is no implicit capture of the function's dynamic environment when +> declaring a function-local item. + +### `let` statements + +A _`let` statement_ introduces a new set of variables, given by a pattern. The +pattern may be followed by a type annotation, and/or an initializer expression. +When no type annotation is given, the compiler will infer the type, or signal +an error if insufficient type information is available for definite inference. +Any variables introduced by a variable declaration are visible from the point of +declaration until the end of the enclosing block scope. + +## Expression statements + +An _expression statement_ is one that evaluates an [expression](expressions.html) +and ignores its result. The type of an expression statement `e;` is always +`()`, regardless of the type of `e`. As a rule, an expression statement's +purpose is to trigger the effects of evaluating its expression. diff --git a/src/doc/reference/src/string-table-productions.md b/src/doc/reference/src/string-table-productions.md new file mode 100644 index 0000000000000..4e9742e3bbb80 --- /dev/null +++ b/src/doc/reference/src/string-table-productions.md @@ -0,0 +1,18 @@ +# String table productions + +Some rules in the grammar — notably [unary +operators], [binary operators], and [keywords][keywords] — are +given in a simplified form: as a listing of a table of unquoted, printable +whitespace-separated strings. These cases form a subset of the rules regarding +the [token][tokens] rule, and are assumed to be the result of a +lexical-analysis phase feeding the parser, driven by a DFA, operating over the +disjunction of all such string table entries. + +When such a string enclosed in double-quotes (`"`) occurs inside the grammar, +it is an implicit reference to a single member of such a string table +production. See [tokens] for more information. + +[binary operators]: expressions.html#binary-operator-expressions +[keywords]: ../grammar.html#keywords +[tokens]: tokens.html +[unary operators]: expressions.html#unary-operator-expressions \ No newline at end of file diff --git a/src/doc/reference/src/subtyping.md b/src/doc/reference/src/subtyping.md new file mode 100644 index 0000000000000..a43b041a69338 --- /dev/null +++ b/src/doc/reference/src/subtyping.md @@ -0,0 +1,19 @@ +# Subtyping + +Subtyping is implicit and can occur at any stage in type checking or +inference. Subtyping in Rust is very restricted and occurs only due to +variance with respect to lifetimes and between types with higher ranked +lifetimes. If we were to erase lifetimes from types, then the only subtyping +would be due to type equality. + +Consider the following example: string literals always have `'static` +lifetime. Nevertheless, we can assign `s` to `t`: + +``` +fn bar<'a>() { + let s: &'static str = "hi"; + let t: &'a str = s; +} +``` +Since `'static` "lives longer" than `'a`, `&'static str` is a subtype of +`&'a str`. diff --git a/src/doc/reference/src/the-copy-trait.md b/src/doc/reference/src/the-copy-trait.md new file mode 100644 index 0000000000000..d593165e48d58 --- /dev/null +++ b/src/doc/reference/src/the-copy-trait.md @@ -0,0 +1,4 @@ +# The `Copy` trait + +The `Copy` trait changes the semantics of a type implementing it. Values whose +type implements `Copy` are copied rather than moved upon assignment. diff --git a/src/doc/reference/src/the-deref-trait.md b/src/doc/reference/src/the-deref-trait.md new file mode 100644 index 0000000000000..a4d84ab83ea67 --- /dev/null +++ b/src/doc/reference/src/the-deref-trait.md @@ -0,0 +1,7 @@ +# The `Deref` trait + +The `Deref` trait allows a type to implicitly implement all the methods +of the type `U`. When attempting to resolve a method call, the compiler will search +the top-level type for the implementation of the called method. If no such method is +found, `.deref()` is called and the compiler continues to search for the method +implementation in the returned type `U`. diff --git a/src/doc/reference/src/the-drop-trait.md b/src/doc/reference/src/the-drop-trait.md new file mode 100644 index 0000000000000..42bf6eb0f2014 --- /dev/null +++ b/src/doc/reference/src/the-drop-trait.md @@ -0,0 +1,4 @@ +# The `Drop` trait + +The `Drop` trait provides a destructor, to be run whenever a value of this type +is to be destroyed. diff --git a/src/doc/reference/src/the-send-trait.md b/src/doc/reference/src/the-send-trait.md new file mode 100644 index 0000000000000..9ec669289a567 --- /dev/null +++ b/src/doc/reference/src/the-send-trait.md @@ -0,0 +1,4 @@ +# The `Send` trait + +The `Send` trait indicates that a value of this type is safe to send from one +thread to another. diff --git a/src/doc/reference/src/the-sized-trait.md b/src/doc/reference/src/the-sized-trait.md new file mode 100644 index 0000000000000..a2aa17c95f295 --- /dev/null +++ b/src/doc/reference/src/the-sized-trait.md @@ -0,0 +1,3 @@ +# The `Sized` trait + +The `Sized` trait indicates that the size of this type is known at compile-time. diff --git a/src/doc/reference/src/the-sync-trait.md b/src/doc/reference/src/the-sync-trait.md new file mode 100644 index 0000000000000..fd9365134b292 --- /dev/null +++ b/src/doc/reference/src/the-sync-trait.md @@ -0,0 +1,4 @@ +# The `Sync` trait + +The `Sync` trait indicates that a value of this type is safe to share between +multiple threads. diff --git a/src/doc/reference/src/theme/book.css b/src/doc/reference/src/theme/book.css new file mode 100644 index 0000000000000..ee92e2f8710a9 --- /dev/null +++ b/src/doc/reference/src/theme/book.css @@ -0,0 +1,798 @@ +html, +body { + font-family: "Open Sans", sans-serif; + color: #333; +} +.left { + float: left; +} +.right { + float: right; +} +.hidden { + display: none; +} +h2, +h3 { + margin-top: 2.5em; +} +h4, +h5 { + margin-top: 2em; +} +.header + .header h3, +.header + .header h4, +.header + .header h5 { + margin-top: 1em; +} +table { + margin: 0 auto; + border-collapse: collapse; +} +table td { + padding: 3px 20px; + border: 1px solid; +} +table thead td { + font-weight: 700; +} +.sidebar { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 300px; + overflow-y: auto; + padding: 10px 10px; + font-size: 0.875em; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + -webkit-transition: left 0.5s; + -moz-transition: left 0.5s; + -o-transition: left 0.5s; + -ms-transition: left 0.5s; + transition: left 0.5s; +} +@media only screen and (max-width: 1060px) { + .sidebar { + left: -300px; + } +} +.sidebar code { + line-height: 2em; +} +.sidebar-hidden .sidebar { + left: -300px; +} +.sidebar-visible .sidebar { + left: 0; +} +.chapter { + list-style: none outside none; + padding-left: 0; + line-height: 1.9em; +} +.chapter li a { + padding: 5px 0; + text-decoration: none; +} +.chapter li a:hover { + text-decoration: none; +} +.chapter .spacer { + width: 100%; + height: 3px; + margin: 10px 0px; +} +.section { + list-style: none outside none; + padding-left: 20px; + line-height: 2.5em; +} +.section li { + -o-text-overflow: ellipsis; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} +.page-wrapper { + position: absolute; + overflow-y: auto; + left: 315px; + right: 0; + top: 0; + bottom: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + min-height: 100%; + -webkit-transition: left 0.5s; + -moz-transition: left 0.5s; + -o-transition: left 0.5s; + -ms-transition: left 0.5s; + transition: left 0.5s; +} +@media only screen and (max-width: 1060px) { + .page-wrapper { + left: 15px; + padding-right: 15px; + } +} +.sidebar-hidden .page-wrapper { + left: 15px; +} +.sidebar-visible .page-wrapper { + left: 315px; +} +.page { + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + padding-right: 15px; + overflow-y: auto; +} +.content { + margin-left: auto; + margin-right: auto; + max-width: 750px; + padding-bottom: 50px; +} +.content a { + text-decoration: none; +} +.content a:hover { + text-decoration: underline; +} +.content img { + max-width: 100%; +} +.menu-bar { + position: relative; + height: 50px; +} +.menu-bar i { + position: relative; + margin: 0 10px; + z-index: 10; + line-height: 50px; + -webkit-transition: color 0.5s; + -moz-transition: color 0.5s; + -o-transition: color 0.5s; + -ms-transition: color 0.5s; + transition: color 0.5s; +} +.menu-bar i:hover { + cursor: pointer; +} +.menu-bar .left-buttons { + float: left; +} +.menu-bar .right-buttons { + float: right; +} +.menu-title { + display: inline-block; + font-weight: 200; + font-size: 20px; + line-height: 50px; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + text-align: center; + margin: 0; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + -webkit-transition: opacity 0.5s ease-in-out; + -moz-transition: opacity 0.5s ease-in-out; + -o-transition: opacity 0.5s ease-in-out; + -ms-transition: opacity 0.5s ease-in-out; + transition: opacity 0.5s ease-in-out; +} +.menu-bar:hover .menu-title { + opacity: 1; + -ms-filter: none; + filter: none; +} +.nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + position: absolute; + top: 50px /* Height of menu-bar */; + bottom: 0; + margin: 0; + max-width: 150px; + min-width: 90px; + display: -webkit-box; + display: -moz-box; + display: -webkit-flex; + display: -ms-flexbox; + display: box; + display: flex; + -webkit-box-pack: center; + -moz-box-pack: center; + -o-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -ms-flex-line-pack: center; + -webkit-align-content: center; + align-content: center; + -webkit-box-orient: vertical; + -moz-box-orient: vertical; + -o-box-orient: vertical; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-transition: color 0.5s; + -moz-transition: color 0.5s; + -o-transition: color 0.5s; + -ms-transition: color 0.5s; + transition: color 0.5s; +} +.mobile-nav-chapters { + display: none; +} +.nav-chapters:hover { + text-decoration: none; +} +.previous { + left: 0; +} +.next { + right: 15px; +} +.theme-popup { + position: relative; + left: 10px; + z-index: 1000; + -webkit-border-radius: 4px; + border-radius: 4px; + font-size: 0.7em; +} +.theme-popup .theme { + margin: 0; + padding: 2px 10px; + line-height: 25px; + white-space: nowrap; +} +.theme-popup .theme:hover:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} +.theme-popup .theme:hover:last-child { + border-bottom-left-radius: inherit; + border-bottom-right-radius: inherit; +} + +@media only screen and (max-width: 1250px) { + .nav-chapters { + display: none; + } + .mobile-nav-chapters { + font-size: 2.5em; + text-align: center; + text-decoration: none; + max-width: 150px; + min-width: 90px; + -webkit-box-pack: center; + -moz-box-pack: center; + -o-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -ms-flex-line-pack: center; + -webkit-align-content: center; + align-content: center; + position: relative; + display: inline-block; + margin-bottom: 50px; + -webkit-border-radius: 5px; + border-radius: 5px; + } + .next { + float: right; + } + .previous { + float: left; + } +} +.light { + color: #333; + background-color: #fff; +/* Inline code */ +} +.light .content .header:link, +.light .content .header:visited { + color: #333; + pointer: cursor; +} +.light .content .header:link:hover, +.light .content .header:visited:hover { + text-decoration: none; +} +.light .sidebar { + background-color: #fafafa; + color: #364149; +} +.light .chapter li { + color: #aaa; +} +.light .chapter li a { + color: #364149; +} +.light .chapter li .active, +.light .chapter li a:hover { +/* Animate color change */ + color: #008cff; +} +.light .chapter .spacer { + background-color: #f4f4f4; +} +.light .menu-bar, +.light .menu-bar:visited, +.light .nav-chapters, +.light .nav-chapters:visited, +.light .mobile-nav-chapters, +.light .mobile-nav-chapters:visited { + color: #ccc; +} +.light .menu-bar i:hover, +.light .nav-chapters:hover, +.light .mobile-nav-chapters i:hover { + color: #333; +} +.light .mobile-nav-chapters i:hover { + color: #364149; +} +.light .mobile-nav-chapters { + background-color: #fafafa; +} +.light .content a:link, +.light a:visited { + color: #4183c4; +} +.light .theme-popup { + color: #333; + background: #fafafa; + border: 1px solid #ccc; +} +.light .theme-popup .theme:hover { + background-color: #e6e6e6; +} +.light .theme-popup .default { + color: #ccc; +} +.light blockquote { + margin: 20px 0; + padding: 0 20px; + color: #333; + background-color: #f2f7f9; + border-top: 0.1em solid #e1edf1; + border-bottom: 0.1em solid #e1edf1; +} +.light table td { + border-color: #f2f2f2; +} +.light table tbody tr:nth-child(2n) { + background: #f7f7f7; +} +.light table thead { + background: #ccc; +} +.light table thead td { + border: none; +} +.light table thead tr { + border: 1px #ccc solid; +} +.light :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.light pre { + position: relative; +} +.light pre > .buttons { + position: absolute; + right: 5px; + top: 5px; + color: #364149; + cursor: pointer; +} +.light pre > .buttons :hover { + color: #008cff; +} +.light pre > .buttons i { + margin-left: 8px; +} +.light pre > .result { + margin-top: 10px; +} +.coal { + color: #98a3ad; + background-color: #141617; +/* Inline code */ +} +.coal .content .header:link, +.coal .content .header:visited { + color: #98a3ad; + pointer: cursor; +} +.coal .content .header:link:hover, +.coal .content .header:visited:hover { + text-decoration: none; +} +.coal .sidebar { + background-color: #292c2f; + color: #a1adb8; +} +.coal .chapter li { + color: #505254; +} +.coal .chapter li a { + color: #a1adb8; +} +.coal .chapter li .active, +.coal .chapter li a:hover { +/* Animate color change */ + color: #3473ad; +} +.coal .chapter .spacer { + background-color: #393939; +} +.coal .menu-bar, +.coal .menu-bar:visited, +.coal .nav-chapters, +.coal .nav-chapters:visited, +.coal .mobile-nav-chapters, +.coal .mobile-nav-chapters:visited { + color: #43484d; +} +.coal .menu-bar i:hover, +.coal .nav-chapters:hover, +.coal .mobile-nav-chapters i:hover { + color: #b3c0cc; +} +.coal .mobile-nav-chapters i:hover { + color: #a1adb8; +} +.coal .mobile-nav-chapters { + background-color: #292c2f; +} +.coal .content a:link, +.coal a:visited { + color: #2b79a2; +} +.coal .theme-popup { + color: #98a3ad; + background: #141617; + border: 1px solid #43484d; +} +.coal .theme-popup .theme:hover { + background-color: #1f2124; +} +.coal .theme-popup .default { + color: #43484d; +} +.coal blockquote { + margin: 20px 0; + padding: 0 20px; + color: #98a3ad; + background-color: #242637; + border-top: 0.1em solid #2c2f44; + border-bottom: 0.1em solid #2c2f44; +} +.coal table td { + border-color: #1f2223; +} +.coal table tbody tr:nth-child(2n) { + background: #1b1d1e; +} +.coal table thead { + background: #3f4649; +} +.coal table thead td { + border: none; +} +.coal table thead tr { + border: 1px #3f4649 solid; +} +.coal :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.coal pre { + position: relative; +} +.coal pre > .buttons { + position: absolute; + right: 5px; + top: 5px; + color: #a1adb8; + cursor: pointer; +} +.coal pre > .buttons :hover { + color: #3473ad; +} +.coal pre > .buttons i { + margin-left: 8px; +} +.coal pre > .result { + margin-top: 10px; +} +.navy { + color: #bcbdd0; + background-color: #161923; +/* Inline code */ +} +.navy .content .header:link, +.navy .content .header:visited { + color: #bcbdd0; + pointer: cursor; +} +.navy .content .header:link:hover, +.navy .content .header:visited:hover { + text-decoration: none; +} +.navy .sidebar { + background-color: #282d3f; + color: #c8c9db; +} +.navy .chapter li { + color: #505274; +} +.navy .chapter li a { + color: #c8c9db; +} +.navy .chapter li .active, +.navy .chapter li a:hover { +/* Animate color change */ + color: #2b79a2; +} +.navy .chapter .spacer { + background-color: #2d334f; +} +.navy .menu-bar, +.navy .menu-bar:visited, +.navy .nav-chapters, +.navy .nav-chapters:visited, +.navy .mobile-nav-chapters, +.navy .mobile-nav-chapters:visited { + color: #737480; +} +.navy .menu-bar i:hover, +.navy .nav-chapters:hover, +.navy .mobile-nav-chapters i:hover { + color: #b7b9cc; +} +.navy .mobile-nav-chapters i:hover { + color: #c8c9db; +} +.navy .mobile-nav-chapters { + background-color: #282d3f; +} +.navy .content a:link, +.navy a:visited { + color: #2b79a2; +} +.navy .theme-popup { + color: #bcbdd0; + background: #161923; + border: 1px solid #737480; +} +.navy .theme-popup .theme:hover { + background-color: #282e40; +} +.navy .theme-popup .default { + color: #737480; +} +.navy blockquote { + margin: 20px 0; + padding: 0 20px; + color: #bcbdd0; + background-color: #262933; + border-top: 0.1em solid #2f333f; + border-bottom: 0.1em solid #2f333f; +} +.navy table td { + border-color: #1f2331; +} +.navy table tbody tr:nth-child(2n) { + background: #1b1f2b; +} +.navy table thead { + background: #39415b; +} +.navy table thead td { + border: none; +} +.navy table thead tr { + border: 1px #39415b solid; +} +.navy :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.navy pre { + position: relative; +} +.navy pre > .buttons { + position: absolute; + right: 5px; + top: 5px; + color: #c8c9db; + cursor: pointer; +} +.navy pre > .buttons :hover { + color: #2b79a2; +} +.navy pre > .buttons i { + margin-left: 8px; +} +.navy pre > .result { + margin-top: 10px; +} +.rust { + color: #262625; + background-color: #e1e1db; +/* Inline code */ +} +.rust .content .header:link, +.rust .content .header:visited { + color: #262625; + pointer: cursor; +} +.rust .content .header:link:hover, +.rust .content .header:visited:hover { + text-decoration: none; +} +.rust .sidebar { + background-color: #3b2e2a; + color: #c8c9db; +} +.rust .chapter li { + color: #505254; +} +.rust .chapter li a { + color: #c8c9db; +} +.rust .chapter li .active, +.rust .chapter li a:hover { +/* Animate color change */ + color: #e69f67; +} +.rust .chapter .spacer { + background-color: #45373a; +} +.rust .menu-bar, +.rust .menu-bar:visited, +.rust .nav-chapters, +.rust .nav-chapters:visited, +.rust .mobile-nav-chapters, +.rust .mobile-nav-chapters:visited { + color: #737480; +} +.rust .menu-bar i:hover, +.rust .nav-chapters:hover, +.rust .mobile-nav-chapters i:hover { + color: #262625; +} +.rust .mobile-nav-chapters i:hover { + color: #c8c9db; +} +.rust .mobile-nav-chapters { + background-color: #3b2e2a; +} +.rust .content a:link, +.rust a:visited { + color: #2b79a2; +} +.rust .theme-popup { + color: #262625; + background: #e1e1db; + border: 1px solid #b38f6b; +} +.rust .theme-popup .theme:hover { + background-color: #99908a; +} +.rust .theme-popup .default { + color: #737480; +} +.rust blockquote { + margin: 20px 0; + padding: 0 20px; + color: #262625; + background-color: #c1c1bb; + border-top: 0.1em solid #b8b8b1; + border-bottom: 0.1em solid #b8b8b1; +} +.rust table td { + border-color: #d7d7cf; +} +.rust table tbody tr:nth-child(2n) { + background: #dbdbd4; +} +.rust table thead { + background: #b3a497; +} +.rust table thead td { + border: none; +} +.rust table thead tr { + border: 1px #b3a497 solid; +} +.rust :not(pre) > .hljs { + display: inline-block; + vertical-align: middle; + padding: 0.1em 0.3em; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.rust pre { + position: relative; +} +.rust pre > .buttons { + position: absolute; + right: 5px; + top: 5px; + color: #c8c9db; + cursor: pointer; +} +.rust pre > .buttons :hover { + color: #e69f67; +} +.rust pre > .buttons i { + margin-left: 8px; +} +.rust pre > .result { + margin-top: 10px; +} + +@media print { + #sidebar { + display: none; + } + #page-wrapper { + left: 0; + overflow-y: initial; + } + #content { + max-width: none; + margin: 0; + padding: 0; + } + #menu-bar { + display: none; + } + .page { + overflow-y: initial; + } + .nav-chapters { + display: none; + } + .mobile-nav-chapters { + display: none; + } +} + +div.footnote-definition p { + display: inline; +} diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md new file mode 100644 index 0000000000000..ca6cde8bd2855 --- /dev/null +++ b/src/doc/reference/src/tokens.md @@ -0,0 +1,326 @@ +# Tokens + +Tokens are primitive productions in the grammar defined by regular +(non-recursive) languages. "Simple" tokens are given in [string table +production] form, and occur in the rest of the +grammar as double-quoted strings. Other tokens have exact rules given. + +[string table production]: string-table-productions.html + +## Literals + +A literal is an expression consisting of a single token, rather than a sequence +of tokens, that immediately and directly denotes the value it evaluates to, +rather than referring to it by name or some other evaluation rule. A literal is +a form of constant expression, so is evaluated (primarily) at compile time. + +### Examples + +#### Characters and strings + +| | Example | `#` sets | Characters | Escapes | +|----------------------------------------------|-----------------|------------|-------------|---------------------| +| [Character](#character-literals) | `'H'` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | +| [String](#string-literals) | `"hello"` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | +| [Raw](#raw-string-literals) | `r#"hello"#` | `0...` | All Unicode | `N/A` | +| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | `0...` | All ASCII | `N/A` | + +#### Byte escapes + +| | Name | +|---|------| +| `\x7F` | 8-bit character code (exactly 2 digits) | +| `\n` | Newline | +| `\r` | Carriage return | +| `\t` | Tab | +| `\\` | Backslash | +| `\0` | Null | + +#### Unicode escapes + +| | Name | +|---|------| +| `\u{7FFF}` | 24-bit Unicode character code (up to 6 digits) | + +#### Quote escapes + +| | Name | +|---|------| +| `\'` | Single quote | +| `\"` | Double quote | + +#### Numbers + +| [Number literals](#number-literals)`*` | Example | Exponentiation | Suffixes | +|----------------------------------------|---------|----------------|----------| +| Decimal integer | `98_222` | `N/A` | Integer suffixes | +| Hex integer | `0xff` | `N/A` | Integer suffixes | +| Octal integer | `0o77` | `N/A` | Integer suffixes | +| Binary integer | `0b1111_0000` | `N/A` | Integer suffixes | +| Floating-point | `123.0E+77` | `Optional` | Floating-point suffixes | + +`*` All number literals allow `_` as a visual separator: `1_234.0E+18f64` + +#### Suffixes + +| Integer | Floating-point | +|---------|----------------| +| `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `isize`, `usize` | `f32`, `f64` | + +### Character and string literals + +#### Character literals + +A _character literal_ is a single Unicode character enclosed within two +`U+0027` (single-quote) characters, with the exception of `U+0027` itself, +which must be _escaped_ by a preceding `U+005C` character (`\`). + +#### String literals + +A _string literal_ is a sequence of any Unicode characters enclosed within two +`U+0022` (double-quote) characters, with the exception of `U+0022` itself, +which must be _escaped_ by a preceding `U+005C` character (`\`). + +Line-break characters are allowed in string literals. Normally they represent +themselves (i.e. no translation), but as a special exception, when an unescaped +`U+005C` character (`\`) occurs immediately before the newline (`U+000A`), the +`U+005C` character, the newline, and all whitespace at the beginning of the +next line are ignored. Thus `a` and `b` are equal: + +```rust +let a = "foobar"; +let b = "foo\ + bar"; + +assert_eq!(a,b); +``` + +#### Character escapes + +Some additional _escapes_ are available in either character or non-raw string +literals. An escape starts with a `U+005C` (`\`) and continues with one of the +following forms: + +* An _8-bit code point escape_ starts with `U+0078` (`x`) and is + followed by exactly two _hex digits_. It denotes the Unicode code point + equal to the provided hex value. +* A _24-bit code point escape_ starts with `U+0075` (`u`) and is followed + by up to six _hex digits_ surrounded by braces `U+007B` (`{`) and `U+007D` + (`}`). It denotes the Unicode code point equal to the provided hex value. +* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072` + (`r`), or `U+0074` (`t`), denoting the Unicode values `U+000A` (LF), + `U+000D` (CR) or `U+0009` (HT) respectively. +* The _null escape_ is the character `U+0030` (`0`) and denotes the Unicode + value `U+0000` (NUL). +* The _backslash escape_ is the character `U+005C` (`\`) which must be + escaped in order to denote *itself*. + +#### Raw string literals + +Raw string literals do not process any escapes. They start with the character +`U+0072` (`r`), followed by zero or more of the character `U+0023` (`#`) and a +`U+0022` (double-quote) character. The _raw string body_ can contain any sequence +of Unicode characters and is terminated only by another `U+0022` (double-quote) +character, followed by the same number of `U+0023` (`#`) characters that preceded +the opening `U+0022` (double-quote) character. + +All Unicode characters contained in the raw string body represent themselves, +the characters `U+0022` (double-quote) (except when followed by at least as +many `U+0023` (`#`) characters as were used to start the raw string literal) or +`U+005C` (`\`) do not have any special meaning. + +Examples for string literals: + +``` +"foo"; r"foo"; // foo +"\"foo\""; r#""foo""#; // "foo" + +"foo #\"# bar"; +r##"foo #"# bar"##; // foo #"# bar + +"\x52"; "R"; r"R"; // R +"\\x52"; r"\x52"; // \x52 +``` + +### Byte and byte string literals + +#### Byte literals + +A _byte literal_ is a single ASCII character (in the `U+0000` to `U+007F` +range) or a single _escape_ preceded by the characters `U+0062` (`b`) and +`U+0027` (single-quote), and followed by the character `U+0027`. If the character +`U+0027` is present within the literal, it must be _escaped_ by a preceding +`U+005C` (`\`) character. It is equivalent to a `u8` unsigned 8-bit integer +_number literal_. + +#### Byte string literals + +A non-raw _byte string literal_ is a sequence of ASCII characters and _escapes_, +preceded by the characters `U+0062` (`b`) and `U+0022` (double-quote), and +followed by the character `U+0022`. If the character `U+0022` is present within +the literal, it must be _escaped_ by a preceding `U+005C` (`\`) character. +Alternatively, a byte string literal can be a _raw byte string literal_, defined +below. A byte string literal of length `n` is equivalent to a `&'static [u8; n]` borrowed fixed-sized array +of unsigned 8-bit integers. + +Some additional _escapes_ are available in either byte or non-raw byte string +literals. An escape starts with a `U+005C` (`\`) and continues with one of the +following forms: + +* A _byte escape_ escape starts with `U+0078` (`x`) and is + followed by exactly two _hex digits_. It denotes the byte + equal to the provided hex value. +* A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072` + (`r`), or `U+0074` (`t`), denoting the bytes values `0x0A` (ASCII LF), + `0x0D` (ASCII CR) or `0x09` (ASCII HT) respectively. +* The _null escape_ is the character `U+0030` (`0`) and denotes the byte + value `0x00` (ASCII NUL). +* The _backslash escape_ is the character `U+005C` (`\`) which must be + escaped in order to denote its ASCII encoding `0x5C`. + +#### Raw byte string literals + +Raw byte string literals do not process any escapes. They start with the +character `U+0062` (`b`), followed by `U+0072` (`r`), followed by zero or more +of the character `U+0023` (`#`), and a `U+0022` (double-quote) character. The +_raw string body_ can contain any sequence of ASCII characters and is terminated +only by another `U+0022` (double-quote) character, followed by the same number of +`U+0023` (`#`) characters that preceded the opening `U+0022` (double-quote) +character. A raw byte string literal can not contain any non-ASCII byte. + +All characters contained in the raw string body represent their ASCII encoding, +the characters `U+0022` (double-quote) (except when followed by at least as +many `U+0023` (`#`) characters as were used to start the raw string literal) or +`U+005C` (`\`) do not have any special meaning. + +Examples for byte string literals: + +``` +b"foo"; br"foo"; // foo +b"\"foo\""; br#""foo""#; // "foo" + +b"foo #\"# bar"; +br##"foo #"# bar"##; // foo #"# bar + +b"\x52"; b"R"; br"R"; // R +b"\\x52"; br"\x52"; // \x52 +``` + +### Number literals + +A _number literal_ is either an _integer literal_ or a _floating-point +literal_. The grammar for recognizing the two kinds of literals is mixed. + +#### Integer literals + +An _integer literal_ has one of four forms: + +* A _decimal literal_ starts with a *decimal digit* and continues with any + mixture of *decimal digits* and _underscores_. +* A _hex literal_ starts with the character sequence `U+0030` `U+0078` + (`0x`) and continues as any mixture of hex digits and underscores. +* An _octal literal_ starts with the character sequence `U+0030` `U+006F` + (`0o`) and continues as any mixture of octal digits and underscores. +* A _binary literal_ starts with the character sequence `U+0030` `U+0062` + (`0b`) and continues as any mixture of binary digits and underscores. + +Like any literal, an integer literal may be followed (immediately, +without any spaces) by an _integer suffix_, which forcibly sets the +type of the literal. The integer suffix must be the name of one of the +integral types: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, +`isize`, or `usize`. + +The type of an _unsuffixed_ integer literal is determined by type inference: + +* If an integer type can be _uniquely_ determined from the surrounding + program context, the unsuffixed integer literal has that type. + +* If the program context under-constrains the type, it defaults to the + signed 32-bit integer `i32`. + +* If the program context over-constrains the type, it is considered a + static type error. + +Examples of integer literals of various forms: + +``` +123i32; // type i32 +123u32; // type u32 +123_u32; // type u32 +0xff_u8; // type u8 +0o70_i16; // type i16 +0b1111_1111_1001_0000_i32; // type i32 +0usize; // type usize +``` + +Note that the Rust syntax considers `-1i8` as an application of the [unary minus +operator] to an integer literal `1i8`, rather than +a single integer literal. + +[unary minus operator]: expressions.html#unary-operator-expressions + +#### Floating-point literals + +A _floating-point literal_ has one of two forms: + +* A _decimal literal_ followed by a period character `U+002E` (`.`). This is + optionally followed by another decimal literal, with an optional _exponent_. +* A single _decimal literal_ followed by an _exponent_. + +Like integer literals, a floating-point literal may be followed by a +suffix, so long as the pre-suffix part does not end with `U+002E` (`.`). +The suffix forcibly sets the type of the literal. There are two valid +_floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point +types), which explicitly determine the type of the literal. + +The type of an _unsuffixed_ floating-point literal is determined by +type inference: + +* If a floating-point type can be _uniquely_ determined from the + surrounding program context, the unsuffixed floating-point literal + has that type. + +* If the program context under-constrains the type, it defaults to `f64`. + +* If the program context over-constrains the type, it is considered a + static type error. + +Examples of floating-point literals of various forms: + +``` +123.0f64; // type f64 +0.1f64; // type f64 +0.1f32; // type f32 +12E+99_f64; // type f64 +let x: f64 = 2.; // type f64 +``` + +This last example is different because it is not possible to use the suffix +syntax with a floating point literal ending in a period. `2.f64` would attempt +to call a method named `f64` on `2`. + +The representation semantics of floating-point numbers are described in +["Machine Types"]. + +["Machine Types"]: types.html#machine-types + +### Boolean literals + +The two values of the boolean type are written `true` and `false`. + +## Symbols + +Symbols are a general class of printable [tokens] that play structural +roles in a variety of grammar productions. They are a +set of remaining miscellaneous printable tokens that do not +otherwise appear as [unary operators], [binary +operators], or [keywords]. +They are catalogued in [the Symbols section][symbols] of the Grammar document. + +[unary operators]: expressions.html#unary-operator-expressions +[binary operators]: expressions.html#binary-operator-expressions +[tokens]: #tokens +[symbols]: ../grammar.html#symbols +[keywords]: ../grammar.html#keywords \ No newline at end of file diff --git a/src/doc/reference/src/type-coercions.md b/src/doc/reference/src/type-coercions.md new file mode 100644 index 0000000000000..6301e5e83d748 --- /dev/null +++ b/src/doc/reference/src/type-coercions.md @@ -0,0 +1,145 @@ +# Type coercions + +Coercions are defined in [RFC 401]. A coercion is implicit and has no syntax. + +[RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md + +## Coercion sites + +A coercion can only occur at certain coercion sites in a program; these are +typically places where the desired type is explicit or can be derived by +propagation from explicit types (without type inference). Possible coercion +sites are: + +* `let` statements where an explicit type is given. + + For example, `42` is coerced to have type `i8` in the following: + + ```rust + let _: i8 = 42; + ``` + +* `static` and `const` statements (similar to `let` statements). + +* Arguments for function calls + + The value being coerced is the actual parameter, and it is coerced to + the type of the formal parameter. + + For example, `42` is coerced to have type `i8` in the following: + + ```rust + fn bar(_: i8) { } + + fn main() { + bar(42); + } + ``` + +* Instantiations of struct or variant fields + + For example, `42` is coerced to have type `i8` in the following: + + ```rust + struct Foo { x: i8 } + + fn main() { + Foo { x: 42 }; + } + ``` + +* Function results, either the final line of a block if it is not + semicolon-terminated or any expression in a `return` statement + + For example, `42` is coerced to have type `i8` in the following: + + ```rust + fn foo() -> i8 { + 42 + } + ``` + +If the expression in one of these coercion sites is a coercion-propagating +expression, then the relevant sub-expressions in that expression are also +coercion sites. Propagation recurses from these new coercion sites. +Propagating expressions and their relevant sub-expressions are: + +* Array literals, where the array has type `[U; n]`. Each sub-expression in +the array literal is a coercion site for coercion to type `U`. + +* Array literals with repeating syntax, where the array has type `[U; n]`. The +repeated sub-expression is a coercion site for coercion to type `U`. + +* Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`. +Each sub-expression is a coercion site to the respective type, e.g. the +zeroth sub-expression is a coercion site to type `U_0`. + +* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then +the sub-expression is a coercion site to `U`. + +* Blocks: if a block has type `U`, then the last expression in the block (if +it is not semicolon-terminated) is a coercion site to `U`. This includes +blocks which are part of control flow statements, such as `if`/`else`, if +the block has a known type. + +## Coercion types + +Coercion is allowed between the following types: + +* `T` to `U` if `T` is a subtype of `U` (*reflexive case*) + +* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` +(*transitive case*) + + Note that this is not fully supported yet + +* `&mut T` to `&T` + +* `*mut T` to `*const T` + +* `&T` to `*const T` + +* `&mut T` to `*mut T` + +* `&T` to `&U` if `T` implements `Deref`. For example: + + ```rust + use std::ops::Deref; + + struct CharContainer { + value: char, + } + + impl Deref for CharContainer { + type Target = char; + + fn deref<'a>(&'a self) -> &'a char { + &self.value + } + } + + fn foo(arg: &char) {} + + fn main() { + let x = &mut CharContainer { value: 'y' }; + foo(x); //&mut CharContainer is coerced to &char. + } + ``` + +* `&mut T` to `&mut U` if `T` implements `DerefMut`. + +* TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of + - `&T` + - `&mut T` + - `*const T` + - `*mut T` + - `Box` + + and where + - coerce_inner(`[T, ..n]`) = `[T]` + - coerce_inner(`T`) = `U` where `T` is a concrete type which implements the + trait `U`. + + In the future, coerce_inner will be recursively extended to tuples and + structs. In addition, coercions from sub-traits to super-traits will be + added. See [RFC 401] for more details. diff --git a/src/doc/reference/src/type-system.md b/src/doc/reference/src/type-system.md new file mode 100644 index 0000000000000..bed7f128e5704 --- /dev/null +++ b/src/doc/reference/src/type-system.md @@ -0,0 +1 @@ +# Type system diff --git a/src/doc/reference/src/types.md b/src/doc/reference/src/types.md new file mode 100644 index 0000000000000..2ddcba177e35d --- /dev/null +++ b/src/doc/reference/src/types.md @@ -0,0 +1,398 @@ +# Types + +Every variable, item and value in a Rust program has a type. The _type_ of a +*value* defines the interpretation of the memory holding it. + +Built-in types and type-constructors are tightly integrated into the language, +in nontrivial ways that are not possible to emulate in user-defined types. +User-defined types have limited capabilities. + +## Primitive types + +The primitive types are the following: + +* The boolean type `bool` with values `true` and `false`. +* The machine types (integer and floating-point). +* The machine-dependent integer types. +* Arrays +* Tuples +* Slices +* Function pointers + +### Machine types + +The machine types are the following: + +* The unsigned word types `u8`, `u16`, `u32` and `u64`, with values drawn from + the integer intervals [0, 2^8 - 1], [0, 2^16 - 1], [0, 2^32 - 1] and + [0, 2^64 - 1] respectively. + +* The signed two's complement word types `i8`, `i16`, `i32` and `i64`, with + values drawn from the integer intervals [-(2^(7)), 2^7 - 1], + [-(2^(15)), 2^15 - 1], [-(2^(31)), 2^31 - 1], [-(2^(63)), 2^63 - 1] + respectively. + +* The IEEE 754-2008 `binary32` and `binary64` floating-point types: `f32` and + `f64`, respectively. + +### Machine-dependent integer types + +The `usize` type is an unsigned integer type with the same number of bits as the +platform's pointer type. It can represent every memory address in the process. + +The `isize` type is a signed integer type with the same number of bits as the +platform's pointer type. The theoretical upper bound on object and array size +is the maximum `isize` value. This ensures that `isize` can be used to calculate +differences between pointers into an object or array and can address every byte +within an object along with one byte past the end. + +## Textual types + +The types `char` and `str` hold textual data. + +A value of type `char` is a [Unicode scalar value]( +http://www.unicode.org/glossary/#unicode_scalar_value) (i.e. a code point that +is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to +0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 / +UTF-32 string. + +A value of type `str` is a Unicode string, represented as an array of 8-bit +unsigned bytes holding a sequence of UTF-8 code points. Since `str` is of +unknown size, it is not a _first-class_ type, but can only be instantiated +through a pointer type, such as `&str`. + +## Tuple types + +A tuple *type* is a heterogeneous product of other types, called the *elements* +of the tuple. It has no nominal name and is instead structurally typed. + +Tuple types and values are denoted by listing the types or values of their +elements, respectively, in a parenthesized, comma-separated list. + +Because tuple elements don't have a name, they can only be accessed by +pattern-matching or by using `N` directly as a field to access the +`N`th element. + +An example of a tuple type and its use: + +``` +type Pair<'a> = (i32, &'a str); +let p: Pair<'static> = (10, "ten"); +let (a, b) = p; + +assert_eq!(a, 10); +assert_eq!(b, "ten"); +assert_eq!(p.0, 10); +assert_eq!(p.1, "ten"); +``` + +For historical reasons and convenience, the tuple type with no elements (`()`) +is often called ‘unit’ or ‘the unit type’. + +## Array, and Slice types + +Rust has two different types for a list of items: + +* `[T; N]`, an 'array' +* `&[T]`, a 'slice' + +An array has a fixed size, and can be allocated on either the stack or the +heap. + +A slice is a 'view' into an array. It doesn't own the data it points +to, it borrows it. + +Examples: + +```{rust} +// A stack-allocated array +let array: [i32; 3] = [1, 2, 3]; + +// A heap-allocated array +let vector: Vec = vec![1, 2, 3]; + +// A slice into an array +let slice: &[i32] = &vector[..]; +``` + +As you can see, the `vec!` macro allows you to create a `Vec` easily. The +`vec!` macro is also part of the standard library, rather than the language. + +All in-bounds elements of arrays and slices are always initialized, and access +to an array or slice is always bounds-checked. + +## Struct types + +A `struct` *type* is a heterogeneous product of other types, called the +*fields* of the type.[^structtype] + +[^structtype]: `struct` types are analogous to `struct` types in C, + the *record* types of the ML family, + or the *struct* types of the Lisp family. + +New instances of a `struct` can be constructed with a [struct +expression](expressions.html#struct-expressions). + +The memory layout of a `struct` is undefined by default to allow for compiler +optimizations like field reordering, but it can be fixed with the +`#[repr(...)]` attribute. In either case, fields may be given in any order in +a corresponding struct *expression*; the resulting `struct` value will always +have the same memory layout. + +The fields of a `struct` may be qualified by [visibility +modifiers](visibility-and-privacy.html), to allow access to data in a +struct outside a module. + +A _tuple struct_ type is just like a struct type, except that the fields are +anonymous. + +A _unit-like struct_ type is like a struct type, except that it has no +fields. The one value constructed by the associated [struct +expression](expressions.html#struct-expressions) is the only value that inhabits such a +type. + +## Enumerated types + +An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted +by the name of an [`enum` item](items.html#enumerations). [^enumtype] + +[^enumtype]: The `enum` type is analogous to a `data` constructor declaration in + ML, or a *pick ADT* in Limbo. + +An [`enum` item](items.html#enumerations) declares both the type and a number of *variant +constructors*, each of which is independently named and takes an optional tuple +of arguments. + +New instances of an `enum` can be constructed by calling one of the variant +constructors, in a [call expression](expressions.html#call-expressions). + +Any `enum` value consumes as much memory as the largest variant constructor for +its corresponding `enum` type. + +Enum types cannot be denoted *structurally* as types, but must be denoted by +named reference to an [`enum` item](items.html#enumerations). + +## Recursive types + +Nominal types — [enumerations](#enumerated-types) and +[structs](#struct-types) — may be recursive. That is, each `enum` +constructor or `struct` field may refer, directly or indirectly, to the +enclosing `enum` or `struct` type itself. Such recursion has restrictions: + +* Recursive types must include a nominal type in the recursion + (not mere [type definitions](../grammar.html#type-definitions), + or other structural types such as [arrays](#array-and-slice-types) or [tuples](#tuple-types)). +* A recursive `enum` item must have at least one non-recursive constructor + (in order to give the recursion a basis case). +* The size of a recursive type must be finite; + in other words the recursive fields of the type must be [pointer types](#pointer-types). +* Recursive type definitions can cross module boundaries, but not module *visibility* boundaries, + or crate boundaries (in order to simplify the module system and type checker). + +An example of a *recursive* type and its use: + +``` +enum List { + Nil, + Cons(T, Box>) +} + +let a: List = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil)))); +``` + +## Pointer types + +All pointers in Rust are explicit first-class values. They can be copied, +stored into data structs, and returned from functions. There are two +varieties of pointer in Rust: + +* References (`&`) + : These point to memory _owned by some other value_. + A reference type is written `&type`, + or `&'a type` when you need to specify an explicit lifetime. + Copying a reference is a "shallow" operation: + it involves only copying the pointer itself. + Releasing a reference has no effect on the value it points to, + but a reference of a temporary value will keep it alive during the scope + of the reference itself. + +* Raw pointers (`*`) + : Raw pointers are pointers without safety or liveness guarantees. + Raw pointers are written as `*const T` or `*mut T`, + for example `*const i32` means a raw pointer to a 32-bit integer. + Copying or dropping a raw pointer has no effect on the lifecycle of any + other value. Dereferencing a raw pointer or converting it to any other + pointer type is an [`unsafe` operation](unsafe-functions.html). + Raw pointers are generally discouraged in Rust code; + they exist to support interoperability with foreign code, + and writing performance-critical or low-level functions. + +The standard library contains additional 'smart pointer' types beyond references +and raw pointers. + +## Function types + +The function type constructor `fn` forms new function types. A function type +consists of a possibly-empty set of function-type modifiers (such as `unsafe` +or `extern`), a sequence of input types and an output type. + +An example of a `fn` type: + +``` +fn add(x: i32, y: i32) -> i32 { + x + y +} + +let mut x = add(5,7); + +type Binop = fn(i32, i32) -> i32; +let bo: Binop = add; +x = bo(5,7); +``` + +### Function types for specific items + +Internal to the compiler, there are also function types that are specific to a particular +function item. In the following snippet, for example, the internal types of the functions +`foo` and `bar` are different, despite the fact that they have the same signature: + +``` +fn foo() { } +fn bar() { } +``` + +The types of `foo` and `bar` can both be implicitly coerced to the fn +pointer type `fn()`. There is currently no syntax for unique fn types, +though the compiler will emit a type like `fn() {foo}` in error +messages to indicate "the unique fn type for the function `foo`". + +## Closure types + +A [lambda expression](expressions.html#lambda-expressions) produces a closure +value with a unique, anonymous type that cannot be written out. + +Depending on the requirements of the closure, its type implements one or +more of the closure traits: + +* `FnOnce` + : The closure can be called once. A closure called as `FnOnce` + can move out values from its environment. + +* `FnMut` + : The closure can be called multiple times as mutable. A closure called as + `FnMut` can mutate values from its environment. `FnMut` inherits from + `FnOnce` (i.e. anything implementing `FnMut` also implements `FnOnce`). + +* `Fn` + : The closure can be called multiple times through a shared reference. + A closure called as `Fn` can neither move out from nor mutate values + from its environment. `Fn` inherits from `FnMut`, which itself + inherits from `FnOnce`. + + +## Trait objects + +In Rust, a type like `&SomeTrait` or `Box` is called a _trait object_. +Each instance of a trait object includes: + + - a pointer to an instance of a type `T` that implements `SomeTrait` + - a _virtual method table_, often just called a _vtable_, which contains, for + each method of `SomeTrait` that `T` implements, a pointer to `T`'s + implementation (i.e. a function pointer). + +The purpose of trait objects is to permit "late binding" of methods. Calling a +method on a trait object results in virtual dispatch at runtime: that is, a +function pointer is loaded from the trait object vtable and invoked indirectly. +The actual implementation for each vtable entry can vary on an object-by-object +basis. + +Note that for a trait object to be instantiated, the trait must be +_object-safe_. Object safety rules are defined in [RFC 255]. + +[RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md + +Given a pointer-typed expression `E` of type `&T` or `Box`, where `T` +implements trait `R`, casting `E` to the corresponding pointer type `&R` or +`Box` results in a value of the _trait object_ `R`. This result is +represented as a pair of pointers: the vtable pointer for the `T` +implementation of `R`, and the pointer value of `E`. + +An example of a trait object: + +``` +trait Printable { + fn stringify(&self) -> String; +} + +impl Printable for i32 { + fn stringify(&self) -> String { self.to_string() } +} + +fn print(a: Box) { + println!("{}", a.stringify()); +} + +fn main() { + print(Box::new(10) as Box); +} +``` + +In this example, the trait `Printable` occurs as a trait object in both the +type signature of `print`, and the cast expression in `main`. + +### Type parameters + +Within the body of an item that has type parameter declarations, the names of +its type parameters are types: + +```ignore +fn to_vec(xs: &[A]) -> Vec { + if xs.is_empty() { + return vec![]; + } + let first: A = xs[0].clone(); + let mut rest: Vec = to_vec(&xs[1..]); + rest.insert(0, first); + rest +} +``` + +Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and `rest` +has type `Vec`, a vector with element type `A`. + +## Self types + +The special type `Self` has a meaning within traits and impls. In a trait definition, it refers +to an implicit type parameter representing the "implementing" type. In an impl, +it is an alias for the implementing type. For example, in: + +``` +pub trait From { + fn from(T) -> Self; +} + +impl From for String { + fn from(x: i32) -> Self { + x.to_string() + } +} +``` + +The notation `Self` in the impl refers to the implementing type: `String`. In another +example: + +``` +trait Printable { + fn make_string(&self) -> String; +} + +impl Printable for String { + fn make_string(&self) -> String { + (*self).clone() + } +} +``` + +The notation `&self` is a shorthand for `self: &Self`. In this case, +in the impl, `Self` refers to the value of type `String` that is the +receiver for a call to the method `make_string`. diff --git a/src/doc/reference/src/unicode-productions.md b/src/doc/reference/src/unicode-productions.md new file mode 100644 index 0000000000000..f9d6d1d59732d --- /dev/null +++ b/src/doc/reference/src/unicode-productions.md @@ -0,0 +1,9 @@ +# Unicode productions + +A few productions in Rust's grammar permit Unicode code points outside the +ASCII range. We define these productions in terms of character properties +specified in the Unicode standard, rather than in terms of ASCII-range code +points. The grammar has a [Special Unicode Productions][unicodeproductions] +section that lists these productions. + +[unicodeproductions]: ../grammar.html#special-unicode-productions diff --git a/src/doc/reference/src/unsafe-blocks.md b/src/doc/reference/src/unsafe-blocks.md new file mode 100644 index 0000000000000..754278445d51e --- /dev/null +++ b/src/doc/reference/src/unsafe-blocks.md @@ -0,0 +1,22 @@ +# Unsafe blocks + +A block of code can be prefixed with the `unsafe` keyword, to permit calling +`unsafe` functions or dereferencing raw pointers within a safe function. + +When a programmer has sufficient conviction that a sequence of potentially +unsafe operations is actually safe, they can encapsulate that sequence (taken +as a whole) within an `unsafe` block. The compiler will consider uses of such +code safe, in the surrounding context. + +Unsafe blocks are used to wrap foreign libraries, make direct use of hardware +or implement features not directly present in the language. For example, Rust +provides the language features necessary to implement memory-safe concurrency +in the language but the implementation of threads and message passing is in the +standard library. + +Rust's type system is a conservative approximation of the dynamic safety +requirements, so in some cases there is a performance cost to using safe code. +For example, a doubly-linked list is not a tree structure and can only be +represented with reference-counted pointers in safe code. By using `unsafe` +blocks to represent the reverse links as raw pointers, it can be implemented +with only boxes. diff --git a/src/doc/reference/src/unsafe-functions.md b/src/doc/reference/src/unsafe-functions.md new file mode 100644 index 0000000000000..7a5064c08f41a --- /dev/null +++ b/src/doc/reference/src/unsafe-functions.md @@ -0,0 +1,5 @@ +# Unsafe functions + +Unsafe functions are functions that are not safe in all contexts and/or for all +possible inputs. Such a function must be prefixed with the keyword `unsafe` and +can only be called from an `unsafe` block or another `unsafe` function. diff --git a/src/doc/reference/src/unsafety.md b/src/doc/reference/src/unsafety.md new file mode 100644 index 0000000000000..abb7a9eec5848 --- /dev/null +++ b/src/doc/reference/src/unsafety.md @@ -0,0 +1,11 @@ +# Unsafety + +Unsafe operations are those that potentially violate the memory-safety +guarantees of Rust's static semantics. + +The following language level features cannot be used in the safe subset of +Rust: + +- Dereferencing a [raw pointer](types.html#pointer-types). +- Reading or writing a [mutable static variable](items.html#mutable-statics). +- Calling an unsafe function (including an intrinsic or foreign function). diff --git a/src/doc/reference/src/variables.md b/src/doc/reference/src/variables.md new file mode 100644 index 0000000000000..ce3d226d0238b --- /dev/null +++ b/src/doc/reference/src/variables.md @@ -0,0 +1,31 @@ +# Variables + +A _variable_ is a component of a stack frame, either a named function parameter, +an anonymous [temporary](expressions.html#lvalues-rvalues-and-temporaries), or a named local +variable. + +A _local variable_ (or *stack-local* allocation) holds a value directly, +allocated within the stack's memory. The value is a part of the stack frame. + +Local variables are immutable unless declared otherwise like: `let mut x = ...`. + +Function parameters are immutable unless declared with `mut`. The `mut` keyword +applies only to the following parameter (so `|mut x, y|` and `fn f(mut x: +Box, y: Box)` declare one mutable variable `x` and one immutable +variable `y`). + +Methods that take either `self` or `Box` can optionally place them in a +mutable variable by prefixing them with `mut` (similar to regular arguments): + +``` +trait Changer: Sized { + fn change(mut self) {} + fn modify(mut self: Box) {} +} +``` + +Local variables are not initialized when allocated; the entire frame worth of +local variables are allocated at once, on frame-entry, in an uninitialized +state. Subsequent statements within a function may or may not initialize the +local variables. Local variables can be used only after they have been +initialized; this is enforced by the compiler. diff --git a/src/doc/reference/src/visibility-and-privacy.md b/src/doc/reference/src/visibility-and-privacy.md new file mode 100644 index 0000000000000..50d3e7507d0ed --- /dev/null +++ b/src/doc/reference/src/visibility-and-privacy.md @@ -0,0 +1,160 @@ +# Visibility and Privacy + +These two terms are often used interchangeably, and what they are attempting to +convey is the answer to the question "Can this item be used at this location?" + +Rust's name resolution operates on a global hierarchy of namespaces. Each level +in the hierarchy can be thought of as some item. The items are one of those +mentioned above, but also include external crates. Declaring or defining a new +module can be thought of as inserting a new tree into the hierarchy at the +location of the definition. + +To control whether interfaces can be used across modules, Rust checks each use +of an item to see whether it should be allowed or not. This is where privacy +warnings are generated, or otherwise "you used a private item of another module +and weren't allowed to." + +By default, everything in Rust is *private*, with two exceptions: Associated +items in a `pub` Trait are public by default; Enum variants +in a `pub` enum are also public by default. When an item is declared as `pub`, +it can be thought of as being accessible to the outside world. For example: + +``` +# fn main() {} +// Declare a private struct +struct Foo; + +// Declare a public struct with a private field +pub struct Bar { + field: i32, +} + +// Declare a public enum with two public variants +pub enum State { + PubliclyAccessibleState, + PubliclyAccessibleState2, +} +``` + +With the notion of an item being either public or private, Rust allows item +accesses in two cases: + +1. If an item is public, then it can be used externally through any of its + public ancestors. +2. If an item is private, it may be accessed by the current module and its + descendants. + +These two cases are surprisingly powerful for creating module hierarchies +exposing public APIs while hiding internal implementation details. To help +explain, here's a few use cases and what they would entail: + +* A library developer needs to expose functionality to crates which link + against their library. As a consequence of the first case, this means that + anything which is usable externally must be `pub` from the root down to the + destination item. Any private item in the chain will disallow external + accesses. + +* A crate needs a global available "helper module" to itself, but it doesn't + want to expose the helper module as a public API. To accomplish this, the + root of the crate's hierarchy would have a private module which then + internally has a "public API". Because the entire crate is a descendant of + the root, then the entire local crate can access this private module through + the second case. + +* When writing unit tests for a module, it's often a common idiom to have an + immediate child of the module to-be-tested named `mod test`. This module + could access any items of the parent module through the second case, meaning + that internal implementation details could also be seamlessly tested from the + child module. + +In the second case, it mentions that a private item "can be accessed" by the +current module and its descendants, but the exact meaning of accessing an item +depends on what the item is. Accessing a module, for example, would mean +looking inside of it (to import more items). On the other hand, accessing a +function would mean that it is invoked. Additionally, path expressions and +import statements are considered to access an item in the sense that the +import/expression is only valid if the destination is in the current visibility +scope. + +Here's an example of a program which exemplifies the three cases outlined +above: + +``` +// This module is private, meaning that no external crate can access this +// module. Because it is private at the root of this current crate, however, any +// module in the crate may access any publicly visible item in this module. +mod crate_helper_module { + + // This function can be used by anything in the current crate + pub fn crate_helper() {} + + // This function *cannot* be used by anything else in the crate. It is not + // publicly visible outside of the `crate_helper_module`, so only this + // current module and its descendants may access it. + fn implementation_detail() {} +} + +// This function is "public to the root" meaning that it's available to external +// crates linking against this one. +pub fn public_api() {} + +// Similarly to 'public_api', this module is public so external crates may look +// inside of it. +pub mod submodule { + use crate_helper_module; + + pub fn my_method() { + // Any item in the local crate may invoke the helper module's public + // interface through a combination of the two rules above. + crate_helper_module::crate_helper(); + } + + // This function is hidden to any module which is not a descendant of + // `submodule` + fn my_implementation() {} + + #[cfg(test)] + mod test { + + #[test] + fn test_my_implementation() { + // Because this module is a descendant of `submodule`, it's allowed + // to access private items inside of `submodule` without a privacy + // violation. + super::my_implementation(); + } + } +} + +# fn main() {} +``` + +For a Rust program to pass the privacy checking pass, all paths must be valid +accesses given the two rules above. This includes all use statements, +expressions, types, etc. + +## Re-exporting and Visibility + +Rust allows publicly re-exporting items through a `pub use` directive. Because +this is a public directive, this allows the item to be used in the current +module through the rules above. It essentially allows public access into the +re-exported item. For example, this program is valid: + +``` +pub use self::implementation::api; + +mod implementation { + pub mod api { + pub fn f() {} + } +} + +# fn main() {} +``` + +This means that any external crate referencing `implementation::api::f` would +receive a privacy violation, while the path `api::f` would be allowed. + +When re-exporting a private item, it can be thought of as allowing the "privacy +chain" being short-circuited through the reexport instead of passing through +the namespace hierarchy as it normally would. diff --git a/src/doc/reference/src/whitespace.md b/src/doc/reference/src/whitespace.md new file mode 100644 index 0000000000000..2fd162bcb2da8 --- /dev/null +++ b/src/doc/reference/src/whitespace.md @@ -0,0 +1,22 @@ +# Whitespace + +Whitespace is any non-empty string containing only characters that have the +`Pattern_White_Space` Unicode property, namely: + +- `U+0009` (horizontal tab, `'\t'`) +- `U+000A` (line feed, `'\n'`) +- `U+000B` (vertical tab) +- `U+000C` (form feed) +- `U+000D` (carriage return, `'\r'`) +- `U+0020` (space, `' '`) +- `U+0085` (next line) +- `U+200E` (left-to-right mark) +- `U+200F` (right-to-left mark) +- `U+2028` (line separator) +- `U+2029` (paragraph separator) + +Rust is a "free-form" language, meaning that all forms of whitespace serve only +to separate _tokens_ in the grammar, and have no semantic significance. + +A Rust program has identical meaning if each whitespace element is replaced +with any other legal whitespace element, such as a single space character. diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 210917b68a2aa..38d843263ffda 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -102,7 +102,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// [downgrade]: struct.Arc.html#method.downgrade /// [upgrade]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html#variant.None -/// [assoc]: ../../book/method-syntax.html#Associated%20functions +/// [assoc]: ../../book/method-syntax.html#associated-functions /// /// # Examples /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a874e938a40cd..6108a06634bb8 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -215,7 +215,7 @@ //! [downgrade]: struct.Rc.html#method.downgrade //! [upgrade]: struct.Weak.html#method.upgrade //! [`None`]: ../../std/option/enum.Option.html#variant.None -//! [assoc]: ../../book/method-syntax.html#Associated%20functions +//! [assoc]: ../../book/method-syntax.html#associated-functions //! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 4c82e2e2e7e35..e92eb4ff7bdd4 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1250,17 +1250,17 @@ impl String { self.len() == 0 } - /// Divide one string into two at an index. + /// Splits the string into two at the given index. /// - /// The argument, `mid`, should be a byte offset from the start of the string. It must also - /// be on the boundary of a UTF-8 code point. + /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and + /// the returned `String` contains bytes `[at, len)`. `at` must be on the + /// boundary of a UTF-8 code point. /// - /// The two strings returned go from the start of the string to `mid`, and from `mid` to the end - /// of the string. + /// Note that the capacity of `self` does not change. /// /// # Panics /// - /// Panics if `mid` is not on a `UTF-8` code point boundary, or if it is beyond the last + /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last /// code point of the string. /// /// # Examples @@ -1275,9 +1275,9 @@ impl String { /// ``` #[inline] #[stable(feature = "string_split_off", since = "1.16.0")] - pub fn split_off(&mut self, mid: usize) -> String { - assert!(self.is_char_boundary(mid)); - let other = self.vec.split_off(mid); + pub fn split_off(&mut self, at: usize) -> String { + assert!(self.is_char_boundary(at)); + let other = self.vec.split_off(at); unsafe { String::from_utf8_unchecked(other) } } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 31a0cc6884184..12410c08f399b 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -687,7 +687,7 @@ extern "rust-intrinsic" { /// The [nomicon](../../nomicon/transmutes.html) has additional /// documentation. /// - /// [ub]: ../../reference.html#behavior-considered-undefined + /// [ub]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index d41767cce18fe..0f47378aebb7c 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1603,12 +1603,12 @@ pub trait Iterator { let mut i = self.len(); while let Some(v) = self.next_back() { - if predicate(v) { - return Some(i - 1); - } // No need for an overflow check here, because `ExactSizeIterator` // implies that the number of elements fits into a `usize`. i -= 1; + if predicate(v) { + return Some(i); + } } None } @@ -1616,7 +1616,9 @@ pub trait Iterator { /// Returns the maximum element of an iterator. /// /// If several elements are equally maximum, the last element is - /// returned. + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -1624,8 +1626,10 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; + /// let b: Vec = Vec::new(); /// /// assert_eq!(a.iter().max(), Some(&3)); + /// assert_eq!(b.iter().max(), None); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1642,7 +1646,9 @@ pub trait Iterator { /// Returns the minimum element of an iterator. /// /// If several elements are equally minimum, the first element is - /// returned. + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -1650,8 +1656,10 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3]; + /// let b: Vec = Vec::new(); /// /// assert_eq!(a.iter().min(), Some(&1)); + /// assert_eq!(b.iter().min(), None); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -1669,7 +1677,9 @@ pub trait Iterator { /// specified function. /// /// If several elements are equally maximum, the last element is - /// returned. + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -1694,7 +1704,9 @@ pub trait Iterator { /// specified comparison function. /// /// If several elements are equally maximum, the last element is - /// returned. + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -1719,7 +1731,9 @@ pub trait Iterator { /// specified function. /// /// If several elements are equally minimum, the first element is - /// returned. + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -1743,7 +1757,9 @@ pub trait Iterator { /// specified comparison function. /// /// If several elements are equally minimum, the first element is - /// returned. + /// returned. If the iterator is empty, [`None`] is returned. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index ede22ccddc62f..1e9eaaf5f3223 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -36,7 +36,7 @@ use hash::Hasher; /// /// [`Rc`]: ../../std/rc/struct.Rc.html /// [arc]: ../../std/sync/struct.Arc.html -/// [ub]: ../../reference.html#behavior-considered-undefined +/// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] #[lang = "send"] #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] @@ -338,7 +338,7 @@ pub trait Copy : Clone { /// [mutex]: ../../std/sync/struct.Mutex.html /// [rwlock]: ../../std/sync/struct.RwLock.html /// [unsafecell]: ../cell/struct.UnsafeCell.html -/// [ub]: ../../reference.html#behavior-considered-undefined +/// [ub]: ../../reference/behavior-considered-undefined.html /// [transmute]: ../../std/mem/fn.transmute.html #[stable(feature = "rust1", since = "1.0.0")] #[lang = "sync"] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 5655fd066047c..f4ce4697d7cf4 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -167,7 +167,7 @@ pub use intrinsics::transmute; /// [FFI]: ../../book/ffi.html /// [box]: ../../std/boxed/struct.Box.html /// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw -/// [ub]: ../../reference.html#behavior-considered-undefined +/// [ub]: ../../reference/behavior-considered-undefined.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn forget(t: T) { @@ -318,7 +318,7 @@ pub fn align_of_val(val: &T) -> usize { /// /// [uninit]: fn.uninitialized.html /// [FFI]: ../../book/ffi.html -/// [ub]: ../../reference.html#behavior-considered-undefined +/// [ub]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// @@ -417,7 +417,7 @@ pub unsafe fn zeroed() -> T { /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html -/// [ub]: ../../reference.html#behavior-considered-undefined +/// [ub]: ../../reference/behavior-considered-undefined.html /// [write]: ../ptr/fn.write.html /// [copy]: ../intrinsics/fn.copy.html /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html @@ -525,7 +525,7 @@ pub fn replace(dest: &mut T, mut src: T) -> T { /// it will not release any borrows, as borrows are based on lexical scope. /// /// This effectively does nothing for -/// [types which implement `Copy`](../../book/ownership.html#Copy%20types), +/// [types which implement `Copy`](../../book/ownership.html#copy-types), /// e.g. integers. Such values are copied and _then_ moved into the function, /// so the value persists after this function call. /// @@ -626,7 +626,7 @@ pub fn drop(_x: T) { } /// same size. This function triggers [undefined behavior][ub] if `U` is larger than /// `T`. /// -/// [ub]: ../../reference.html#behavior-considered-undefined +/// [ub]: ../../reference/behavior-considered-undefined.html /// [size_of]: fn.size_of.html /// /// # Examples diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index 652b139f1e608..a7d0d3899b181 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -25,7 +25,7 @@ /// Book][moreinfo] contains more details about the precise nature of /// these internals. /// -/// [moreinfo]: ../../book/trait-objects.html#Representation +/// [moreinfo]: ../../book/trait-objects.html#representation /// /// `TraitObject` is guaranteed to match layouts, but it is not the /// type of trait objects (e.g. the fields are not directly accessible diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 006de1c06e2d9..96d1a925425e8 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -131,7 +131,37 @@ pub enum DepNode { // which would yield an overly conservative dep-graph. TraitItems(D), ReprHints(D), - TraitSelect(Vec), + + // Trait selection cache is a little funny. Given a trait + // reference like `Foo: SomeTrait`, there could be + // arbitrarily many def-ids to map on in there (e.g., `Foo`, + // `SomeTrait`, `Bar`). We could have a vector of them, but it + // requires heap-allocation, and trait sel in general can be a + // surprisingly hot path. So instead we pick two def-ids: the + // trait def-id, and the first def-id in the input types. If there + // is no def-id in the input types, then we use the trait def-id + // again. So for example: + // + // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }` + // - `Vec: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }` + // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }` + // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `Foo: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // - `i32: Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }` + // + // You can see that we map many trait refs to the same + // trait-select node. This is not a problem, it just means + // imprecision in our dep-graph tracking. The important thing is + // that for any given trait-ref, we always map to the **same** + // trait-select node. + TraitSelect { trait_def_id: D, input_def_id: D }, + + // For proj. cache, we just keep a list of all def-ids, since it is + // not a hotspot. + ProjectionCache { def_ids: Vec }, } impl DepNode { @@ -236,9 +266,17 @@ impl DepNode { TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), - TraitSelect(ref type_ds) => { - let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect()); - Some(TraitSelect(type_ds)) + TraitSelect { ref trait_def_id, ref input_def_id } => { + op(trait_def_id).and_then(|trait_def_id| { + op(input_def_id).and_then(|input_def_id| { + Some(TraitSelect { trait_def_id: trait_def_id, + input_def_id: input_def_id }) + }) + }) + } + ProjectionCache { ref def_ids } => { + let def_ids: Option> = def_ids.iter().map(op).collect(); + def_ids.map(|d| ProjectionCache { def_ids: d }) } } } diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index b6fce2d6ca0be..53b7be74f8503 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -59,32 +59,45 @@ pub enum Def { Err, } -/// The result of resolving a path. -/// Before type checking completes, `depth` represents the number of -/// trailing segments which are yet unresolved. Afterwards, if there -/// were no errors, all paths should be fully resolved, with `depth` -/// set to `0` and `base_def` representing the final resolution. -/// +/// The result of resolving a path before lowering to HIR. +/// `base_def` is definition of resolved part of the +/// path, `unresolved_segments` is the number of unresolved +/// segments. /// module::Type::AssocX::AssocY::MethodOrAssocType /// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_def depth = 3 +/// base_def unresolved_segments = 3 /// /// ::AssocX::AssocY::MethodOrAssocType /// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~ -/// base_def depth = 2 +/// base_def unresolved_segments = 2 #[derive(Copy, Clone, Debug)] pub struct PathResolution { - pub base_def: Def, - pub depth: usize + base_def: Def, + unresolved_segments: usize, } impl PathResolution { - pub fn new(def: Def) -> PathResolution { - PathResolution { base_def: def, depth: 0 } + pub fn new(def: Def) -> Self { + PathResolution { base_def: def, unresolved_segments: 0 } + } + + pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self { + if def == Def::Err { unresolved_segments = 0 } + PathResolution { base_def: def, unresolved_segments: unresolved_segments } + } + + #[inline] + pub fn base_def(&self) -> Def { + self.base_def + } + + #[inline] + pub fn unresolved_segments(&self) -> usize { + self.unresolved_segments } pub fn kind_name(&self) -> &'static str { - if self.depth != 0 { + if self.unresolved_segments != 0 { "associated item" } else { self.base_def.kind_name() diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8a4acb3d03880..c87ce6505fcd5 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -217,10 +217,10 @@ impl<'a> LoweringContext<'a> { fn expect_full_def(&mut self, id: NodeId) -> Def { self.resolver.get_resolution(id).map_or(Def::Err, |pr| { - if pr.depth != 0 { + if pr.unresolved_segments() != 0 { bug!("path not fully resolved: {:?}", pr); } - pr.base_def + pr.base_def() }) } @@ -421,9 +421,9 @@ impl<'a> LoweringContext<'a> { let resolution = self.resolver.get_resolution(id) .unwrap_or(PathResolution::new(Def::Err)); - let proj_start = p.segments.len() - resolution.depth; + let proj_start = p.segments.len() - resolution.unresolved_segments(); let path = P(hir::Path { - def: resolution.base_def, + def: resolution.base_def(), segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| { let param_mode = match (qself_position, param_mode) { (Some(j), ParamMode::Optional) if i < j => { @@ -443,7 +443,7 @@ impl<'a> LoweringContext<'a> { index: this.def_key(def_id).parent.expect("missing parent") } }; - let type_def_id = match resolution.base_def { + let type_def_id = match resolution.base_def() { Def::AssociatedTy(def_id) if i + 2 == proj_start => { Some(parent_def_id(self, def_id)) } @@ -474,7 +474,7 @@ impl<'a> LoweringContext<'a> { // Simple case, either no projections, or only fully-qualified. // E.g. `std::mem::size_of` or `::Item`. - if resolution.depth == 0 { + if resolution.unresolved_segments() == 0 { return hir::QPath::Resolved(qself, path); } @@ -749,7 +749,7 @@ impl<'a> LoweringContext<'a> { bound_pred.bound_lifetimes.is_empty() => { if let Some(Def::TyParam(def_id)) = self.resolver.get_resolution(bound_pred.bounded_ty.id) - .map(|d| d.base_def) { + .map(|d| d.base_def()) { if let Some(node_id) = self.resolver.definitions().as_local_node_id(def_id) { for ty_param in &g.ty_params { @@ -1295,7 +1295,7 @@ impl<'a> LoweringContext<'a> { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, pth1, ref sub) => { self.with_parent_def(p.id, |this| { - match this.resolver.get_resolution(p.id).map(|d| d.base_def) { + match this.resolver.get_resolution(p.id).map(|d| d.base_def()) { // `None` can occur in body-less function signatures def @ None | def @ Some(Def::Local(_)) => { let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| { diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 939f214407ef7..9295fb2ee327b 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -65,9 +65,6 @@ use super::region_inference::ConcreteFailure; use super::region_inference::SubSupConflict; use super::region_inference::GenericBoundFailure; use super::region_inference::GenericKind; -use super::region_inference::ProcessedErrors; -use super::region_inference::ProcessedErrorOrigin; -use super::region_inference::SameRegions; use hir::map as hir_map; use hir; @@ -77,11 +74,10 @@ use infer; use middle::region; use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, TyCtxt, TypeFoldable}; -use ty::{Region, ReFree, Issue32330}; +use ty::{Region, Issue32330}; use ty::error::TypeError; use std::fmt; -use syntax::ast; use syntax_pos::{Pos, Span}; use errors::DiagnosticBuilder; @@ -255,8 +251,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // try to pre-process the errors, which will group some of them // together into a `ProcessedErrors` group: - let processed_errors = self.process_errors(errors); - let errors = processed_errors.as_ref().unwrap_or(errors); + let errors = self.process_errors(errors); debug!("report_region_errors: {} errors after preprocessing", errors.len()); @@ -278,13 +273,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sub_origin, sub_r, sup_origin, sup_r); } - - ProcessedErrors(ref origins, - ref same_regions) => { - if !same_regions.is_empty() { - self.report_processed_errors(origins); - } - } } } } @@ -300,202 +288,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // duplicates that will be unhelpful to the end-user. But // obviously it never weeds out ALL errors. fn process_errors(&self, errors: &Vec>) - -> Option>> { + -> Vec> { debug!("process_errors()"); - let mut origins = Vec::new(); - - // we collect up ConcreteFailures and SubSupConflicts that are - // relating free-regions bound on the fn-header and group them - // together into this vector - let mut same_regions = Vec::new(); - - // here we put errors that we will not be able to process nicely - let mut other_errors = Vec::new(); - - // we collect up GenericBoundFailures in here. - let mut bound_failures = Vec::new(); - - for error in errors { - // Check whether we can process this error into some other - // form; if not, fall through. - match *error { - ConcreteFailure(ref origin, sub, sup) => { - debug!("processing ConcreteFailure"); - if let SubregionOrigin::CompareImplMethodObligation { .. } = *origin { - // When comparing an impl method against a - // trait method, it is not helpful to suggest - // changes to the impl method. This is - // because the impl method signature is being - // checked using the trait's environment, so - // usually the changes we suggest would - // actually have to be applied to the *trait* - // method (and it's not clear that the trait - // method is even under the user's control). - } else if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) { - origins.push( - ProcessedErrorOrigin::ConcreteFailure( - origin.clone(), - sub, - sup)); - append_to_same_regions(&mut same_regions, &same_frs); - continue; - } - } - SubSupConflict(ref var_origin, ref sub_origin, sub, ref sup_origin, sup) => { - debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub, sup); - match (sub_origin, sup_origin) { - (&SubregionOrigin::CompareImplMethodObligation { .. }, _) => { - // As above, when comparing an impl method - // against a trait method, it is not helpful - // to suggest changes to the impl method. - } - (_, &SubregionOrigin::CompareImplMethodObligation { .. }) => { - // See above. - } - _ => { - if let Some(same_frs) = free_regions_from_same_fn(self.tcx, sub, sup) { - origins.push( - ProcessedErrorOrigin::VariableFailure( - var_origin.clone())); - append_to_same_regions(&mut same_regions, &same_frs); - continue; - } - } - } - } - GenericBoundFailure(ref origin, ref kind, region) => { - bound_failures.push((origin.clone(), kind.clone(), region)); - continue; - } - ProcessedErrors(..) => { - bug!("should not encounter a `ProcessedErrors` yet: {:?}", error) - } - } - - // No changes to this error. - other_errors.push(error.clone()); - } - - // ok, let's pull together the errors, sorted in an order that - // we think will help user the best - let mut processed_errors = vec![]; - - // first, put the processed errors, if any - if !same_regions.is_empty() { - let common_scope_id = same_regions[0].scope_id; - for sr in &same_regions { - // Since ProcessedErrors is used to reconstruct the function - // declaration, we want to make sure that they are, in fact, - // from the same scope - if sr.scope_id != common_scope_id { - debug!("returning empty result from process_errors because - {} != {}", sr.scope_id, common_scope_id); - return None; - } - } - assert!(origins.len() > 0); - let pe = ProcessedErrors(origins, same_regions); - debug!("errors processed: {:?}", pe); - processed_errors.push(pe); - } - - // next, put the other misc errors - processed_errors.extend(other_errors); - - // finally, put the `T: 'a` errors, but only if there were no - // other errors. otherwise, these have a very high rate of - // being unhelpful in practice. This is because they are - // basically secondary checks that test the state of the - // region graph after the rest of inference is done, and the - // other kinds of errors indicate that the region constraint - // graph is internally inconsistent, so these test results are - // likely to be meaningless. - if processed_errors.is_empty() { - for (origin, kind, region) in bound_failures { - processed_errors.push(GenericBoundFailure(origin, kind, region)); - } - } - // we should always wind up with SOME errors, unless there were no - // errors to start - assert!(if errors.len() > 0 {processed_errors.len() > 0} else {true}); - - return Some(processed_errors); - - #[derive(Debug)] - struct FreeRegionsFromSameFn { - sub_fr: ty::FreeRegion, - sup_fr: ty::FreeRegion, - scope_id: ast::NodeId - } - - impl FreeRegionsFromSameFn { - fn new(sub_fr: ty::FreeRegion, - sup_fr: ty::FreeRegion, - scope_id: ast::NodeId) - -> FreeRegionsFromSameFn { - FreeRegionsFromSameFn { - sub_fr: sub_fr, - sup_fr: sup_fr, - scope_id: scope_id - } - } - } - - fn free_regions_from_same_fn<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - sub: &'tcx Region, - sup: &'tcx Region) - -> Option { - debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup); - let (scope_id, fr1, fr2) = match (sub, sup) { - (&ReFree(fr1), &ReFree(fr2)) => { - if fr1.scope != fr2.scope { - return None - } - assert!(fr1.scope == fr2.scope); - (fr1.scope.node_id(&tcx.region_maps), fr1, fr2) - }, - _ => return None - }; - let parent = tcx.hir.get_parent(scope_id); - let parent_node = tcx.hir.find(parent); - match parent_node { - Some(node) => match node { - hir_map::NodeItem(item) => match item.node { - hir::ItemFn(..) => { - Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id)) - }, - _ => None - }, - hir_map::NodeImplItem(..) | - hir_map::NodeTraitItem(..) => { - Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id)) - }, - _ => None - }, - None => { - debug!("no parent node of scope_id {}", scope_id); - None - } - } - } + // We want to avoid reporting generic-bound failures if we can + // avoid it: these have a very high rate of being unhelpful in + // practice. This is because they are basically secondary + // checks that test the state of the region graph after the + // rest of inference is done, and the other kinds of errors + // indicate that the region constraint graph is internally + // inconsistent, so these test results are likely to be + // meaningless. + // + // Therefore, we filter them out of the list unless they are + // the only thing in the list. + + let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e { + ConcreteFailure(..) => false, + SubSupConflict(..) => false, + GenericBoundFailure(..) => true, + }; - fn append_to_same_regions(same_regions: &mut Vec, - same_frs: &FreeRegionsFromSameFn) { - debug!("append_to_same_regions(same_regions={:?}, same_frs={:?})", - same_regions, same_frs); - let scope_id = same_frs.scope_id; - let (sub_fr, sup_fr) = (same_frs.sub_fr, same_frs.sup_fr); - for sr in same_regions.iter_mut() { - if sr.contains(&sup_fr.bound_region) && scope_id == sr.scope_id { - sr.push(sub_fr.bound_region); - return - } - } - same_regions.push(SameRegions { - scope_id: scope_id, - regions: vec![sub_fr.bound_region, sup_fr.bound_region] - }) + if errors.iter().all(|e| is_bound_failure(e)) { + errors.clone() + } else { + errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect() } } @@ -1072,20 +889,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.note_region_origin(&mut err, &sub_origin); err.emit(); } - - fn report_processed_errors(&self, - origins: &[ProcessedErrorOrigin<'tcx>]) { - for origin in origins.iter() { - let mut err = match *origin { - ProcessedErrorOrigin::VariableFailure(ref var_origin) => - self.report_inference_failure(var_origin.clone()), - ProcessedErrorOrigin::ConcreteFailure(ref sr_origin, sub, sup) => - self.report_concrete_failure(sr_origin.clone(), sub, sup), - }; - - err.emit(); - } - } } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index af6f2c50e72fc..0bb9e2c7fa15c 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -24,7 +24,7 @@ use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING}; use rustc_data_structures::unify::{self, UnificationTable}; use middle::free_region::FreeRegionMap; use ty::{self, Ty, TyCtxt}; -use ty::{BoundRegion, Region, RegionVid}; +use ty::{Region, RegionVid}; use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased}; use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh}; @@ -171,13 +171,6 @@ pub enum RegionResolutionError<'tcx> { &'tcx Region, SubregionOrigin<'tcx>, &'tcx Region), - - /// For subsets of `ConcreteFailure` and `SubSupConflict`, we can derive - /// more specific errors message by suggesting to the user where they - /// should put a lifetime. In those cases we process and put those errors - /// into `ProcessedErrors` before we do any reporting. - ProcessedErrors(Vec>, - Vec), } #[derive(Clone, Debug)] @@ -186,33 +179,6 @@ pub enum ProcessedErrorOrigin<'tcx> { VariableFailure(RegionVariableOrigin), } -/// SameRegions is used to group regions that we think are the same and would -/// like to indicate so to the user. -/// For example, the following function -/// ``` -/// struct Foo { bar: i32 } -/// fn foo2<'a, 'b>(x: &'a Foo) -> &'b i32 { -/// &x.bar -/// } -/// ``` -/// would report an error because we expect 'a and 'b to match, and so we group -/// 'a and 'b together inside a SameRegions struct -#[derive(Clone, Debug)] -pub struct SameRegions { - pub scope_id: ast::NodeId, - pub regions: Vec, -} - -impl SameRegions { - pub fn contains(&self, other: &BoundRegion) -> bool { - self.regions.contains(other) - } - - pub fn push(&mut self, other: BoundRegion) { - self.regions.push(other); - } -} - pub type CombineMap<'tcx> = FxHashMap, RegionVid>; pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d8212807eb277..3403cf0477450 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -777,6 +777,12 @@ pub enum StatementKind<'tcx> { /// End the current live range for the storage of the local. StorageDead(Lvalue<'tcx>), + InlineAsm { + asm: InlineAsm, + outputs: Vec>, + inputs: Vec> + }, + /// No-op. Useful for deleting instructions without affecting statement indices. Nop, } @@ -790,7 +796,10 @@ impl<'tcx> Debug for Statement<'tcx> { StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv), SetDiscriminant{lvalue: ref lv, variant_index: index} => { write!(fmt, "discriminant({:?}) = {:?}", lv, index) - } + }, + InlineAsm { ref asm, ref outputs, ref inputs } => { + write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs) + }, Nop => write!(fmt, "nop"), } } @@ -1004,12 +1013,6 @@ pub enum Rvalue<'tcx> { /// that `Foo` has a destructor. These rvalues can be optimized /// away after type-checking and before lowering. Aggregate(AggregateKind<'tcx>, Vec>), - - InlineAsm { - asm: InlineAsm, - outputs: Vec>, - inputs: Vec> - } } #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] @@ -1111,10 +1114,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a), Discriminant(ref lval) => write!(fmt, "discriminant({:?})", lval), Box(ref t) => write!(fmt, "Box({:?})", t), - InlineAsm { ref asm, ref outputs, ref inputs } => { - write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs) - } - Ref(_, borrow_kind, ref lv) => { let kind_str = match borrow_kind { BorrowKind::Shared => "", diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 7b0863b4c42bc..5c8d031caf60d 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -207,7 +207,6 @@ impl<'tcx> Rvalue<'tcx> { } } } - Rvalue::InlineAsm { .. } => None } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index be3c43db7badd..7cdbd5cae061f 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -333,6 +333,16 @@ macro_rules! make_mir_visitor { StatementKind::StorageDead(ref $($mutability)* lvalue) => { self.visit_lvalue(lvalue, LvalueContext::StorageDead, location); } + StatementKind::InlineAsm { ref $($mutability)* outputs, + ref $($mutability)* inputs, + asm: _ } => { + for output in & $($mutability)* outputs[..] { + self.visit_lvalue(output, LvalueContext::Store, location); + } + for input in & $($mutability)* inputs[..] { + self.visit_operand(input, location); + } + } StatementKind::Nop => {} } } @@ -526,17 +536,6 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); } } - - Rvalue::InlineAsm { ref $($mutability)* outputs, - ref $($mutability)* inputs, - asm: _ } => { - for output in & $($mutability)* outputs[..] { - self.visit_lvalue(output, LvalueContext::Store, location); - } - for input in & $($mutability)* inputs[..] { - self.visit_operand(input, location); - } - } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 4893e24091127..58ab713ef2730 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -628,6 +628,11 @@ pub fn get_vtable_methods<'a, 'tcx>( |_, _| tcx.mk_region(ty::ReErased), |def, _| trait_ref.substs().type_for_def(def)); + // the trait type may have higher-ranked lifetimes in it; + // so erase them if they appear, so that we get the type + // at some particular call site + let substs = tcx.erase_late_bound_regions_and_normalize(&ty::Binder(substs)); + // It's possible that the method relies on where clauses that // do not hold for this particular set of type parameters. // Note that this method could then never be called, so we diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 41f3f825c3d19..40c62762c3cf3 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2547,7 +2547,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // TyError and ensure they do not affect any other fields. // This could be checked after type collection for any struct // with a potentially unsized trailing field. - let params = substs_a.params().iter().enumerate().map(|(i, &k)| { + let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { Kind::from(tcx.types.err) } else { @@ -2567,7 +2567,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check that the source structure with the target's // type parameters is a subtype of the target. - let params = substs_a.params().iter().enumerate().map(|(i, &k)| { + let params = substs_a.iter().enumerate().map(|(i, &k)| { if ty_params.contains(i) { Kind::from(substs_b.type_at(i)) } else { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 411e14531fab3..7937d2ccfe46d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -34,7 +34,6 @@ use serialize::{self, Encodable, Encoder}; use std::borrow::Cow; use std::cell::{Cell, RefCell, Ref}; use std::hash::{Hash, Hasher}; -use std::iter; use std::ops::Deref; use std::rc::Rc; use std::slice; @@ -843,27 +842,22 @@ impl<'tcx> TraitPredicate<'tcx> { /// Creates the dep-node for selecting/evaluating this trait reference. fn dep_node(&self) -> DepNode { - // Ideally, the dep-node would just have all the input types - // in it. But they are limited to including def-ids. So as an - // approximation we include the def-ids for all nominal types - // found somewhere. This means that we will e.g. conflate the - // dep-nodes for `u32: SomeTrait` and `u64: SomeTrait`, but we - // would have distinct dep-nodes for `Vec: SomeTrait`, - // `Rc: SomeTrait`, and `(Vec, Rc): SomeTrait`. - // Note that it's always sound to conflate dep-nodes, it just - // leads to more recompilation. - let def_ids: Vec<_> = + // Extact the trait-def and first def-id from inputs. See the + // docs for `DepNode::TraitSelect` for more information. + let trait_def_id = self.def_id(); + let input_def_id = self.input_types() .flat_map(|t| t.walk()) .filter_map(|t| match t.sty { - ty::TyAdt(adt_def, _) => - Some(adt_def.did), - _ => - None + ty::TyAdt(adt_def, _) => Some(adt_def.did), + _ => None }) - .chain(iter::once(self.def_id())) - .collect(); - DepNode::TraitSelect(def_ids) + .next() + .unwrap_or(trait_def_id); + DepNode::TraitSelect { + trait_def_id: trait_def_id, + input_def_id: input_def_id + } } pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index adedf78bba7c0..2e3009b4ed6db 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -143,7 +143,7 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, { let tcx = relation.tcx(); - let params = a_subst.params().iter().zip(b_subst.params()).enumerate().map(|(i, (a, b))| { + let params = a_subst.iter().zip(b_subst).enumerate().map(|(i, (a, b))| { let variance = variances.map_or(ty::Invariant, |v| v[i]); if let (Some(a_ty), Some(b_ty)) = (a.as_type(), b.as_type()) { Ok(Kind::from(relation.relate_with_variance(variance, &a_ty, &b_ty)?)) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index d6f61a12a3c6e..c0a529b936b0f 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -254,12 +254,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { self.is_empty() } - #[inline] - pub fn params(&self) -> &[Kind<'tcx>] { - // FIXME (dikaiosune) this should be removed, and corresponding compilation errors fixed - self - } - #[inline] pub fn types(&'a self) -> impl DoubleEndedIterator> + 'a { self.iter().filter_map(|k| k.as_type()) diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs index 1fa4da94dd6bf..7888a56d39dfb 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs @@ -473,6 +473,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => {} } } diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index ea6ef423c92ce..940dd5433a0d9 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -104,6 +104,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => continue, mir::StatementKind::SetDiscriminant{ .. } => span_bug!(stmt.source_info.span, diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs index 0c7e922c48ab4..35ace6628cfed 100644 --- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs @@ -412,6 +412,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { span_bug!(stmt.source_info.span, "SetDiscriminant should not exist during borrowck"); } + StatementKind::InlineAsm { .. } | StatementKind::Nop => {} } } @@ -436,8 +437,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { } Rvalue::Ref(..) | Rvalue::Discriminant(..) | - Rvalue::Len(..) | - Rvalue::InlineAsm { .. } => {} + Rvalue::Len(..) => {} Rvalue::Box(..) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index a0c36139ddcd2..d9283e7037f50 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -378,6 +378,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>( } mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::Nop => {} }, None => { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4fe3730bbe249..de789d5686fcf 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -726,6 +726,8 @@ pub fn phase_2_configure_and_expand(sess: &Session, }); } + after_expand(&krate)?; + if sess.opts.debugging_opts.input_stats { println!("Post-expansion node count: {}", count_nodes(&krate)); } @@ -751,14 +753,14 @@ pub fn phase_2_configure_and_expand(sess: &Session, || ast_validation::check_crate(sess, &krate)); time(time_passes, "name resolution", || -> CompileResult { - // Since import resolution will eventually happen in expansion, - // don't perform `after_expand` until after import resolution. - after_expand(&krate)?; - resolver.resolve_crate(&krate); Ok(()) })?; + if resolver.found_unresolved_macro { + sess.parse_sess.span_diagnostic.abort_if_errors(); + } + // Needs to go *after* expansion to be able to check the results of macro expansion. time(time_passes, "complete gated feature checking", || { sess.track_errors(|| { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index dad1d713168cd..7adcc0e730b15 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -49,21 +49,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Scope { extent, value } => { this.in_scope(extent, block, |this| this.as_rvalue(block, value)) } - ExprKind::InlineAsm { asm, outputs, inputs } => { - let outputs = outputs.into_iter().map(|output| { - unpack!(block = this.as_lvalue(block, output)) - }).collect(); - - let inputs = inputs.into_iter().map(|input| { - unpack!(block = this.as_operand(block, input)) - }).collect(); - - block.and(Rvalue::InlineAsm { - asm: asm.clone(), - outputs: outputs, - inputs: inputs - }) - } ExprKind::Repeat { value, count } => { let value_operand = unpack!(block = this.as_operand(block, value)); block.and(Rvalue::Repeat(value_operand, count)) @@ -238,6 +223,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } | + ExprKind::InlineAsm { .. } | ExprKind::StaticRef { .. } => { // these do not have corresponding `Rvalue` variants, // so make an operand and then return that diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 35841c2cbdf01..e66f2b4e2bfc0 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -232,6 +232,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::AssignOp { .. } | ExprKind::Continue { .. } | ExprKind::Break { .. } | + ExprKind::InlineAsm { .. } | ExprKind::Return {.. } => { this.stmt_expr(block, expr) } @@ -257,7 +258,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Literal { .. } | - ExprKind::InlineAsm { .. } | ExprKind::Field { .. } => { debug_assert!(match Category::of(&expr.kind).unwrap() { Category::Rvalue(RvalueFunc::Into) => false, diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index f04d630379a35..c577aab40dbeb 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -117,6 +117,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.exit_scope(expr_span, extent, block, return_block); this.cfg.start_new_block().unit() } + ExprKind::InlineAsm { asm, outputs, inputs } => { + let outputs = outputs.into_iter().map(|output| { + unpack!(block = this.as_lvalue(block, output)) + }).collect(); + let inputs = inputs.into_iter().map(|input| { + unpack!(block = this.as_operand(block, input)) + }).collect(); + this.cfg.push(block, Statement { + source_info: source_info, + kind: StatementKind::InlineAsm { + asm: asm.clone(), + outputs: outputs, + inputs: inputs + }, + }); + block.unit() + } _ => { let expr_ty = expr.ty; let temp = this.temp(expr.ty.clone()); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 922521726c626..4459142cfb274 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -774,10 +774,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } } - - Rvalue::InlineAsm {..} => { - self.not_const(); - } } } @@ -933,6 +929,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | + StatementKind::InlineAsm {..} | StatementKind::Nop => {} } }); diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 8ede7aaab5f68..8d108815e0f3c 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -361,9 +361,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}", lv_ty, rv_ty, terr); } - // FIXME: rvalue with undeterminable type - e.g. inline - // asm. } + // FIXME: rvalue with undeterminable type - e.g. AggregateKind::Array branch that + // returns `None`. } StatementKind::SetDiscriminant{ ref lvalue, variant_index } => { let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx); @@ -392,6 +392,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } } + StatementKind::InlineAsm { .. } | StatementKind::Nop => {} } } diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 517a472056334..33b7089c38214 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -128,6 +128,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", StatementKind::StorageLive(..) => "StatementKind::StorageLive", StatementKind::StorageDead(..) => "StatementKind::StorageDead", + StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm", StatementKind::Nop => "StatementKind::Nop", }, &statement.kind); self.super_statement(block, statement, location); @@ -198,7 +199,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { "Rvalue::Aggregate" } - Rvalue::InlineAsm { .. } => "Rvalue::InlineAsm", }; self.record(rvalue_kind, rvalue); self.super_rvalue(rvalue, location); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 676ff98e602d6..c9e870188aaec 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -51,6 +51,7 @@ use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::{Determined, Undetermined}; +use syntax::ext::base::MacroKind; use syntax::symbol::{Symbol, keywords}; use syntax::util::lev_distance::find_best_match_for_name; @@ -785,7 +786,7 @@ pub struct ModuleData<'a> { normal_ancestor_id: DefId, resolutions: RefCell>>>, - legacy_macro_resolutions: RefCell>, + legacy_macro_resolutions: RefCell>, macro_resolutions: RefCell, Span)>>, // Macro invocations that can expand into items in this module. @@ -1117,6 +1118,7 @@ pub struct Resolver<'a> { macro_map: FxHashMap>, macro_exports: Vec, pub whitelisted_legacy_custom_derives: Vec, + pub found_unresolved_macro: bool, // Maps the `Mark` of an expansion to its containing module or block. invocations: FxHashMap>, @@ -1193,7 +1195,8 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect(); match self.resolve_path(&path, Some(namespace), Some(span)) { PathResult::Module(module) => *def = module.def().unwrap(), - PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def, + PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => + *def = path_res.base_def(), PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) { PathResult::Failed(msg, _) => { resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); @@ -1315,6 +1318,7 @@ impl<'a> Resolver<'a> { warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), struct_constructors: DefIdMap(), + found_unresolved_macro: false, } } @@ -1715,7 +1719,7 @@ impl<'a> Resolver<'a> { let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { let def = self.smart_resolve_path(trait_ref.ref_id, None, - &trait_ref.path, PathSource::Trait).base_def; + &trait_ref.path, PathSource::Trait).base_def(); if def != Def::Err { new_val = Some((def.def_id(), trait_ref.clone())); new_id = Some(def.def_id()); @@ -1846,8 +1850,8 @@ impl<'a> Resolver<'a> { pat.walk(&mut |pat| { if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { - if sub_pat.is_some() || match self.def_map.get(&pat.id) { - Some(&PathResolution { base_def: Def::Local(..), .. }) => true, + if sub_pat.is_some() || match self.def_map.get(&pat.id).map(|res| res.base_def()) { + Some(Def::Local(..)) => true, _ => false, } { let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode }; @@ -2245,14 +2249,14 @@ impl<'a> Resolver<'a> { let resolution = match self.resolve_qpath_anywhere(id, qself, path, ns, span, source.defer_to_typeck(), source.global_by_default()) { - Some(resolution) if resolution.depth == 0 => { - if is_expected(resolution.base_def) || resolution.base_def == Def::Err { + Some(resolution) if resolution.unresolved_segments() == 0 => { + if is_expected(resolution.base_def()) || resolution.base_def() == Def::Err { resolution } else { // Add a temporary hack to smooth the transition to new struct ctor // visibility rules. See #38932 for more details. let mut res = None; - if let Def::Struct(def_id) = resolution.base_def { + if let Def::Struct(def_id) = resolution.base_def() { if let Some((ctor_def, ctor_vis)) = self.struct_constructors.get(&def_id).cloned() { if is_expected(ctor_def) && self.is_accessible(ctor_vis) { @@ -2265,7 +2269,7 @@ impl<'a> Resolver<'a> { } } - res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def))) + res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def()))) } } Some(resolution) if source.defer_to_typeck() => { @@ -2318,7 +2322,8 @@ impl<'a> Resolver<'a> { match self.resolve_qpath(id, qself, path, ns, span, global_by_default) { // If defer_to_typeck, then resolution > no resolution, // otherwise full resolution > partial resolution > no resolution. - Some(res) if res.depth == 0 || defer_to_typeck => return Some(res), + Some(res) if res.unresolved_segments() == 0 || defer_to_typeck => + return Some(res), res => if fin_res.is_none() { fin_res = res }, }; } @@ -2343,19 +2348,17 @@ impl<'a> Resolver<'a> { if let Some(qself) = qself { if qself.position == 0 { // FIXME: Create some fake resolution that can't possibly be a type. - return Some(PathResolution { - base_def: Def::Mod(DefId::local(CRATE_DEF_INDEX)), - depth: path.len(), - }); + return Some(PathResolution::with_unresolved_segments( + Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len() + )); } // Make sure `A::B` in `::B::C` is a trait item. let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; - let mut res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], - span, PathSource::TraitItem(ns)); - if res.base_def != Def::Err { - res.depth += path.len() - qself.position - 1; - } - return Some(res); + let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1], + span, PathSource::TraitItem(ns)); + return Some(PathResolution::with_unresolved_segments( + res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1 + )); } let result = match self.resolve_path(&path, Some(ns), Some(span)) { @@ -2390,10 +2393,7 @@ impl<'a> Resolver<'a> { } _ => {} } - PathResolution { - base_def: Def::PrimTy(prim), - depth: path.len() - 1, - } + PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(module) => PathResolution::new(module.def().unwrap()), PathResult::Failed(msg, false) => { @@ -2404,16 +2404,16 @@ impl<'a> Resolver<'a> { PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), }; - if path.len() > 1 && !global_by_default && result.base_def != Def::Err && + if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" { let unqualified_result = { match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { - PathResult::NonModule(path_res) => path_res.base_def, + PathResult::NonModule(path_res) => path_res.base_def(), PathResult::Module(module) => module.def().unwrap(), _ => return Some(result), } }; - if result.base_def == unqualified_result { + if result.base_def() == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; self.session.add_lint(lint, id, span, "unnecessary qualification".to_string()); } @@ -2467,10 +2467,9 @@ impl<'a> Resolver<'a> { Some(LexicalScopeBinding::Item(binding)) => Ok(binding), Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { - return PathResult::NonModule(PathResolution { - base_def: def, - depth: path.len() - 1, - }); + return PathResult::NonModule(PathResolution::with_unresolved_segments( + def, path.len() - 1 + )); } _ => Err(if record_used.is_some() { Determined } else { Undetermined }), } @@ -2485,10 +2484,9 @@ impl<'a> Resolver<'a> { } else if def == Def::Err { return PathResult::NonModule(err_path_resolution()); } else if opt_ns.is_some() && (is_last || maybe_assoc) { - return PathResult::NonModule(PathResolution { - base_def: def, - depth: path.len() - i - 1, - }); + return PathResult::NonModule(PathResolution::with_unresolved_segments( + def, path.len() - i - 1 + )); } else { return PathResult::Failed(format!("Not a module `{}`", ident), is_last); } @@ -2497,10 +2495,9 @@ impl<'a> Resolver<'a> { Err(Determined) => { if let Some(module) = module { if opt_ns.is_some() && !module.is_normal() { - return PathResult::NonModule(PathResolution { - base_def: module.def().unwrap(), - depth: path.len() - i, - }); + return PathResult::NonModule(PathResolution::with_unresolved_segments( + module.def().unwrap(), path.len() - i + )); } } let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { @@ -2669,8 +2666,9 @@ impl<'a> Resolver<'a> { if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) { // Look for a field with the same name in the current self_type. if let Some(resolution) = self.def_map.get(&node_id) { - match resolution.base_def { - Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => { + match resolution.base_def() { + Def::Struct(did) | Def::Union(did) + if resolution.unresolved_segments() == 0 => { if let Some(field_names) = self.field_names.get(&did) { if field_names.iter().any(|&field_name| name == field_name) { return Some(AssocSuggestion::Field); @@ -3054,7 +3052,6 @@ impl<'a> Resolver<'a> { fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { debug!("(recording def) recording {:?} for {}", resolution, node_id); - assert!(resolution.depth == 0 || resolution.base_def != Def::Err); if let Some(prev_res) = self.def_map.insert(node_id, resolution) { panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution); } @@ -3068,7 +3065,8 @@ impl<'a> Resolver<'a> { ty::Visibility::Restricted(self.current_module.normal_ancestor_id) } ast::Visibility::Restricted { ref path, id } => { - let def = self.smart_resolve_path(id, None, path, PathSource::Visibility).base_def; + let def = self.smart_resolve_path(id, None, path, + PathSource::Visibility).base_def(); if def == Def::Err { ty::Visibility::Public } else { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 97d3e6c9e43d9..8d563d20549c3 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -24,6 +24,7 @@ use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator}; use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension}; +use syntax::ext::base::MacroKind; use syntax::ext::expand::{Expansion, mark_tts}; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; @@ -236,8 +237,8 @@ impl<'a> base::Resolver for Resolver<'a> { None } - fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) - -> Result, Determinacy> { + fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, + force: bool) -> Result, Determinacy> { let ast::Path { ref segments, span } = *path; if segments.iter().any(|segment| segment.parameters.is_some()) { let kind = @@ -256,17 +257,21 @@ impl<'a> base::Resolver for Resolver<'a> { let msg = "non-ident macro paths are experimental"; let feature = "use_extern_macros"; emit_feature_err(&self.session.parse_sess, feature, span, GateIssue::Language, msg); + self.found_unresolved_macro = true; return Err(Determinacy::Determined); } let ext = match self.resolve_path(&path, Some(MacroNS), None) { - PathResult::NonModule(path_res) => match path_res.base_def { + PathResult::NonModule(path_res) => match path_res.base_def() { Def::Err => Err(Determinacy::Determined), def @ _ => Ok(self.get_macro(def)), }, PathResult::Module(..) => unreachable!(), PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), - _ => Err(Determinacy::Determined), + _ => { + self.found_unresolved_macro = true; + Err(Determinacy::Determined) + }, }; self.current_module.macro_resolutions.borrow_mut() .push((path.into_boxed_slice(), span)); @@ -279,40 +284,19 @@ impl<'a> base::Resolver for Resolver<'a> { Some(MacroBinding::Modern(binding)) => Ok(binding.get_macro(self)), None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) { Ok(binding) => Ok(binding.get_macro(self)), - Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined), - _ => { - let msg = format!("macro undefined: `{}`", name); - let mut err = self.session.struct_span_err(span, &msg); - self.suggest_macro_name(&name.as_str(), &mut err); - err.emit(); - return Err(Determinacy::Determined); - }, + Err(Determinacy::Undetermined) if !force => + return Err(Determinacy::Undetermined), + Err(_) => { + self.found_unresolved_macro = true; + Err(Determinacy::Determined) + } }, }; - if self.use_extern_macros { - self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, path[0], span)); - } - result - } + self.current_module.legacy_macro_resolutions.borrow_mut() + .push((scope, path[0], span, kind)); - fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) - -> Result, Determinacy> { - let ast::Path { span, .. } = *path; - match self.resolve_macro(scope, path, false) { - Ok(ext) => match *ext { - SyntaxExtension::BuiltinDerive(..) | - SyntaxExtension::ProcMacroDerive(..) => Ok(ext), - _ => Err(Determinacy::Determined), - }, - Err(Determinacy::Undetermined) if force => { - let msg = format!("cannot find derive macro `{}` in this scope", path); - let mut err = self.session.struct_span_err(span, &msg); - err.emit(); - Err(Determinacy::Determined) - }, - Err(err) => Err(err), - } + result } } @@ -438,37 +422,74 @@ impl<'a> Resolver<'a> { } } - for &(mark, ident, span) in module.legacy_macro_resolutions.borrow().iter() { + for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() { let legacy_scope = &self.invocations[&mark].legacy_scope; let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true); let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span)); - let (legacy_resolution, resolution) = match (legacy_resolution, resolution) { - (Some(legacy_resolution), Ok(resolution)) => (legacy_resolution, resolution), + match (legacy_resolution, resolution) { + (Some(legacy_resolution), Ok(resolution)) => { + let (legacy_span, participle) = match legacy_resolution { + MacroBinding::Modern(binding) + if binding.def() == resolution.def() => continue, + MacroBinding::Modern(binding) => (binding.span, "imported"), + MacroBinding::Legacy(binding) => (binding.span, "defined"), + }; + let msg1 = format!("`{}` could refer to the macro {} here", ident, participle); + let msg2 = format!("`{}` could also refer to the macro imported here", ident); + self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident)) + .span_note(legacy_span, &msg1) + .span_note(resolution.span, &msg2) + .emit(); + }, (Some(MacroBinding::Modern(binding)), Err(_)) => { self.record_use(ident, MacroNS, binding, span); self.err_if_macro_use_proc_macro(ident.name, span, binding); - continue }, - _ => continue, - }; - let (legacy_span, participle) = match legacy_resolution { - MacroBinding::Modern(binding) if binding.def() == resolution.def() => continue, - MacroBinding::Modern(binding) => (binding.span, "imported"), - MacroBinding::Legacy(binding) => (binding.span, "defined"), + (None, Err(_)) => { + let msg = match kind { + MacroKind::Bang => + format!("cannot find macro `{}!` in this scope", ident), + MacroKind::Attr => + format!("cannot find attribute macro `{}` in this scope", ident), + MacroKind::Derive => + format!("cannot find derive macro `{}` in this scope", ident), + }; + let mut err = self.session.struct_span_err(span, &msg); + self.suggest_macro_name(&ident.name.as_str(), kind, &mut err); + err.emit(); + }, + _ => {}, }; - let msg1 = format!("`{}` could refer to the macro {} here", ident, participle); - let msg2 = format!("`{}` could also refer to the macro imported here", ident); - self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident)) - .span_note(legacy_span, &msg1) - .span_note(resolution.span, &msg2) - .emit(); } } - fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) { - if let Some(suggestion) = find_best_match_for_name(self.macro_names.iter(), name, None) { + fn suggest_macro_name(&mut self, name: &str, kind: MacroKind, + err: &mut DiagnosticBuilder<'a>) { + let suggestion = match kind { + MacroKind::Bang => + find_best_match_for_name(self.macro_names.iter(), name, None), + MacroKind::Attr | + MacroKind::Derive => { + // Find a suggestion from the legacy namespace. + // FIXME: get_macro needs an &mut Resolver, can we do it without cloning? + let builtin_macros = self.builtin_macros.clone(); + let names = builtin_macros.iter().filter_map(|(name, binding)| { + if binding.get_macro(self).kind() == kind { + Some(name) + } else { + None + } + }); + find_best_match_for_name(names, name, None) + } + }; + if let Some(suggestion) = suggestion { if suggestion != name { - err.help(&format!("did you mean `{}!`?", suggestion)); + if let MacroKind::Bang = kind { + err.help(&format!("did you mean `{}!`?", suggestion)); + } else { + err.help(&format!("did you mean `{}`?", suggestion)); + } } else { err.help(&format!("have you added the `#[macro_use]` on the module/import?")); } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index b717254ef0d25..40a69721495b8 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -315,11 +315,15 @@ impl ModuleConfig { // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. Otherwise configure other optimization aspects // of this pass manager builder. + // Turn off vectorization for emscripten, as it's not very well supported. self.vectorize_loop = !sess.opts.cg.no_vectorize_loops && (sess.opts.optimize == config::OptLevel::Default || - sess.opts.optimize == config::OptLevel::Aggressive); + sess.opts.optimize == config::OptLevel::Aggressive) && + !sess.target.target.options.is_like_emscripten; + self.vectorize_slp = !sess.opts.cg.no_vectorize_slp && - sess.opts.optimize == config::OptLevel::Aggressive; + sess.opts.optimize == config::OptLevel::Aggressive && + !sess.target.target.options.is_like_emscripten; self.merge_functions = sess.opts.optimize == config::OptLevel::Default || sess.opts.optimize == config::OptLevel::Aggressive; diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 89f5c00e9c11a..b5f948442b774 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1090,13 +1090,16 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, trait_ty: ty::Ty<'tcx>, impl_ty: ty::Ty<'tcx>, output: &mut Vec>) { - assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst()); + assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() && + !impl_ty.needs_subst() && !impl_ty.has_escaping_regions()); if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty { if let Some(principal) = trait_ty.principal() { let poly_trait_ref = principal.with_self_ty(scx.tcx(), impl_ty); let param_substs = scx.tcx().intern_substs(&[]); + assert!(!poly_trait_ref.has_escaping_regions()); + // Walk all methods of the trait, including those of its supertraits let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref); let methods = methods.filter_map(|method| method) diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 5efdd129a32b8..799f502aadbfa 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -208,7 +208,8 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> { _ => None, }) .collect(); - DepNode::TraitSelect(def_ids) + + DepNode::ProjectionCache { def_ids: def_ids } } } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 19139301bb0c4..7e17ae5f1d389 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -287,8 +287,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::Nop => {} + mir::StatementKind::InlineAsm { .. } | mir::StatementKind::SetDiscriminant{ .. } => { - span_bug!(span, "SetDiscriminant should not appear in constants?"); + span_bug!(span, "{:?} should not appear in constants?", statement.kind); } } } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 38ee67796c6de..7d4f542addbb1 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -16,7 +16,6 @@ use rustc::mir::tcx::LvalueTy; use rustc::mir; use middle::lang_items::ExchangeMallocFnLangItem; -use asm; use base; use builder::Builder; use callee::Callee; @@ -156,20 +155,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { bcx } - mir::Rvalue::InlineAsm { ref asm, ref outputs, ref inputs } => { - let outputs = outputs.iter().map(|output| { - let lvalue = self.trans_lvalue(&bcx, output); - (lvalue.llval, lvalue.ty.to_ty(bcx.tcx())) - }).collect(); - - let input_vals = inputs.iter().map(|input| { - self.trans_operand(&bcx, input).immediate() - }).collect(); - - asm::trans_inline_asm(&bcx, asm, outputs, input_vals); - bcx - } - _ => { assert!(rvalue_creates_operand(rvalue)); let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue); @@ -468,8 +453,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { (bcx, operand) } mir::Rvalue::Repeat(..) | - mir::Rvalue::Aggregate(..) | - mir::Rvalue::InlineAsm { .. } => { + mir::Rvalue::Aggregate(..) => { bug!("cannot generate operand from rvalue {:?}", rvalue); } @@ -669,8 +653,7 @@ pub fn rvalue_creates_operand(rvalue: &mir::Rvalue) -> bool { mir::Rvalue::Use(..) => true, mir::Rvalue::Repeat(..) | - mir::Rvalue::Aggregate(..) | - mir::Rvalue::InlineAsm { .. } => + mir::Rvalue::Aggregate(..) => false, } diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 48fc9720e4b83..29a0648c8f8f8 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -11,6 +11,7 @@ use rustc::mir; use base; +use asm; use common; use builder::Builder; @@ -73,6 +74,19 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { mir::StatementKind::StorageDead(ref lvalue) => { self.trans_storage_liveness(bcx, lvalue, base::Lifetime::End) } + mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { + let outputs = outputs.iter().map(|output| { + let lvalue = self.trans_lvalue(&bcx, output); + (lvalue.llval, lvalue.ty.to_ty(bcx.tcx())) + }).collect(); + + let input_vals = inputs.iter().map(|input| { + self.trans_operand(&bcx, input).immediate() + }).collect(); + + asm::trans_inline_asm(&bcx, asm, outputs, input_vals); + bcx + } mir::StatementKind::Nop => bcx, } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index fb6d28448a0c5..ab1897101eb6f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -918,7 +918,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { (_, Def::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait - we have a concrete self type and a // trait reference. - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + // FIXME: Self type is not always computed when we are here because type parameter + // bounds may affect Self type and have to be converted before it. + let trait_ref = if impl_def_id.is_local() { + tcx.impl_trait_refs.borrow().get(&impl_def_id).cloned().and_then(|x| x) + } else { + tcx.impl_trait_ref(impl_def_id) + }; + let trait_ref = if let Some(trait_ref) = trait_ref { + trait_ref + } else { + tcx.sess.span_err(span, "`Self` type is used before it's determined"); + return (tcx.types.err, Def::Err); + }; let trait_ref = if let Some(free_substs) = self.get_free_substs() { trait_ref.subst(tcx, free_substs) } else { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index ff9eaa012ba41..2d90394025d21 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -309,17 +309,17 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - let supplied_start = substs.params().len() + method_generics.regions.len(); + let supplied_start = substs.len() + method_generics.regions.len(); Substs::for_item(self.tcx, pick.item.def_id, |def, _| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.region_at(i) } else { self.region_var_for_def(self.span, def) } }, |def, cur_substs| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.type_at(i) } else if supplied_method_types.is_empty() { self.type_var_for_def(self.span, def, cur_substs) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 201a223c15f15..fd29ff0be43b4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1326,7 +1326,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } else { let substs = Substs::for_item(self.tcx, method, |def, _| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.region_at(i) } else { // In general, during probe we erase regions. See @@ -1335,7 +1335,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } }, |def, cur_substs| { let i = def.index as usize; - if i < substs.params().len() { + if i < substs.len() { substs.type_at(i) } else { self.type_var_for_def(self.span, def, cur_substs) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4b36e682f1e82..9d963226caf4b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4156,17 +4156,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; if self.diverges.get().always() { - if let ExpectHasType(ety) = expected { - // Avoid forcing a type (only `!` for now) in unreachable code. - // FIXME(aburka) do we need this special case? and should it be is_uninhabited? - if !ety.is_never() { - if let Some(ref e) = blk.expr { - // Coerce the tail expression to the right type. - self.demand_coerce(e, ty, ety); - } - } - } - ty = self.next_diverging_ty_var(TypeVariableOrigin::DivergingBlockExpr(blk.span)); } else if let ExpectHasType(ety) = expected { if let Some(ref e) = blk.expr { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 28156dd616b3a..a292227058379 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let gcx = fcx.tcx.global_tcx(); let free_substs = fcx.parameter_environment.free_substs; - for (i, k) in free_substs.params().iter().enumerate() { + for (i, k) in free_substs.iter().enumerate() { let r = if let Some(r) = k.as_region() { r } else { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 079dbd667d65b..fd5827b4c0753 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -182,15 +182,15 @@ impl DefaultResizePolicy { // ---------------------- // To protect against degenerate performance scenarios (including DOS attacks), // the implementation includes an adaptive behavior that can resize the map -// early (before it's capacity is exceeded) when suspiciously long probe or -// foward shifts sequences are encounted. +// early (before its capacity is exceeded) when suspiciously long probe or +// forward shifts sequences are encountered. // // With this algorithm in place it would be possible to turn a CPU attack into -// a memory attack due to the agressive resizing. To prevent that the +// a memory attack due to the aggressive resizing. To prevent that the // adaptive behavior only triggers when the map occupancy is half the maximum occupancy. -// This reduces the effectivenes of the algorithm but also makes it completelly safe. +// This reduces the effectiveness of the algorithm but also makes it completely safe. // -// The previous safety measure that also prevents degenerate iteractions with +// The previous safety measure also prevents degenerate interactions with // really bad quality hash algorithms that can make normal inputs look like a // DOS attack. // diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 1ef2cb4ed153c..dd4f1ff4f5ed7 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -96,7 +96,9 @@ pub struct VarsOs { inner: os_imp::Env } /// /// While iterating, the returned iterator will panic if any key or value in the /// environment is not valid unicode. If this is not desired, consider using the -/// `env::vars_os` function. +/// [`env::vars_os`] function. +/// +/// [`env::vars_os`]: fn.vars_os.html /// /// # Examples /// @@ -171,9 +173,12 @@ impl fmt::Debug for VarsOs { /// Fetches the environment variable `key` from the current process. /// -/// The returned result is `Ok(s)` if the environment variable is present and is +/// The returned result is [`Ok(s)`] if the environment variable is present and is /// valid unicode. If the environment variable is not present, or it is not -/// valid unicode, then `Err` will be returned. +/// valid unicode, then [`Err`] will be returned. +/// +/// [`Ok(s)`]: ../result/enum.Result.html#variant.Ok +/// [`Err`]: ../result/enum.Result.html#variant.Err /// /// # Examples /// @@ -199,7 +204,9 @@ fn _var(key: &OsStr) -> Result { } /// Fetches the environment variable `key` from the current process, returning -/// `None` if the variable isn't set. +/// [`None`] if the variable isn't set. +/// +/// [`None`]: ../option/enum.Option.html#variant.None /// /// # Examples /// diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 7a676c041ad89..544f4f9ddbed3 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -264,7 +264,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` - /// [floating-point]: ../reference.html#machine-types + /// [floating-point]: ../reference/types.html#machine-types #[unstable(feature = "float_extras", reason = "signature is undecided", issue = "27752")] #[rustc_deprecated(since = "1.11.0", diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 67a1c302483d2..dd4bc253bed4b 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -206,7 +206,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` - /// [floating-point]: ../reference.html#machine-types + /// [floating-point]: ../reference/types.html#machine-types #[unstable(feature = "float_extras", reason = "signature is undecided", issue = "27752")] #[rustc_deprecated(since = "1.11.0", diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 0cff8661d8871..60767ea478661 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -200,18 +200,20 @@ impl Cursor { #[stable(feature = "rust1", since = "1.0.0")] impl io::Seek for Cursor where T: AsRef<[u8]> { fn seek(&mut self, style: SeekFrom) -> io::Result { - let pos = match style { - SeekFrom::Start(n) => { self.pos = n; return Ok(n) } - SeekFrom::End(n) => self.inner.as_ref().len() as i64 + n, - SeekFrom::Current(n) => self.pos as i64 + n, + let (base_pos, offset) = match style { + SeekFrom::Start(n) => { self.pos = n; return Ok(n); } + SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), + SeekFrom::Current(n) => (self.pos, n), }; - - if pos < 0 { - Err(Error::new(ErrorKind::InvalidInput, - "invalid seek to a negative position")) + let new_pos = if offset >= 0 { + base_pos.checked_add(offset as u64) } else { - self.pos = pos as u64; - Ok(self.pos) + base_pos.checked_sub((offset.wrapping_neg()) as u64) + }; + match new_pos { + Some(n) => {self.pos = n; Ok(self.pos)} + None => Err(Error::new(ErrorKind::InvalidInput, + "invalid seek to a negative or overflowing position")) } } } @@ -526,6 +528,43 @@ mod tests { assert_eq!(r.write(&[3]).unwrap(), 0); } + #[test] + fn seek_past_i64() { + let buf = [0xff]; + let mut r = Cursor::new(&buf[..]); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + + let mut r = Cursor::new(vec![10]); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + + let mut buf = [0]; + let mut r = Cursor::new(&mut buf[..]); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + + let mut r = Cursor::new(vec![10].into_boxed_slice()); + assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6); + assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6); + assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006); + assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006); + assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err()); + assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6); + } + #[test] fn seek_before_0() { let buf = [0xff]; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 88c2310a86e22..070690773b6c4 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -189,8 +189,8 @@ //! [`sync`]: sync/index.html //! [`thread`]: thread/index.html //! [`use std::env`]: env/index.html -//! [`use`]: ../book/crates-and-modules.html#Importing%20Modules%20with%20use -//! [crate root]: ../book/crates-and-modules.html#Basic%20terminology%3A%20Crates%20and%20Modules +//! [`use`]: ../book/crates-and-modules.html#importing-modules-with-use +//! [crate root]: ../book/crates-and-modules.html#basic-terminology-crates-and-modules //! [crates.io]: https://crates.io //! [deref coercions]: ../book/deref-coercions.html //! [files]: fs/struct.File.html diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d79a9a202d9e4..a1f092621cb44 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -441,7 +441,7 @@ pub mod builtin { /// leads to less duplicated code. /// /// The syntax given to this macro is the same syntax as [the `cfg` - /// attribute](../reference.html#conditional-compilation). + /// attribute](../book/conditional-compilation.html). /// /// # Examples /// diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 1b3e17c300e4d..11197db98a396 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -490,7 +490,7 @@ mod prim_str { } /// assert_eq!(tuple.2, 'c'); /// ``` /// -/// For more about tuples, see [the book](../book/primitive-types.html#Tuples). +/// For more about tuples, see [the book](../book/primitive-types.html#tuples). /// /// # Trait implementations /// diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index ba99375139139..1e7394c0b09e7 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -316,7 +316,7 @@ impl Once { } // Once we've enqueued ourselves, wait in a loop. - // Aftewards reload the state and continue with what we + // Afterwards reload the state and continue with what we // were doing from before. while !node.signaled.load(Ordering::SeqCst) { thread::park(); diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 6dc85840a6343..36928696c4059 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -483,41 +483,21 @@ pub fn home_dir() -> Option { target_os = "nacl", target_os = "emscripten")))] unsafe fn fallback() -> Option { - #[cfg(not(target_os = "solaris"))] - unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd, - buf: &mut Vec) -> Option<()> { - let mut result = ptr::null_mut(); - match libc::getpwuid_r(me, passwd, buf.as_mut_ptr(), - buf.capacity(), - &mut result) { - 0 if !result.is_null() => Some(()), - _ => None - } - } - - #[cfg(target_os = "solaris")] - unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd, - buf: &mut Vec) -> Option<()> { - // getpwuid_r semantics is different on Illumos/Solaris: - // http://illumos.org/man/3c/getpwuid_r - let result = libc::getpwuid_r(me, passwd, buf.as_mut_ptr(), - buf.capacity()); - if result.is_null() { None } else { Some(()) } - } - let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { n if n < 0 => 512 as usize, n => n as usize, }; let mut buf = Vec::with_capacity(amt); let mut passwd: libc::passwd = mem::zeroed(); - - if getpwduid_r(libc::getuid(), &mut passwd, &mut buf).is_some() { - let ptr = passwd.pw_dir as *const _; - let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); - Some(OsStringExt::from_vec(bytes)) - } else { - None + let mut result = ptr::null_mut(); + match libc::getpwuid_r(libc::getuid(), &mut passwd, buf.as_mut_ptr(), + buf.capacity(), &mut result) { + 0 if !result.is_null() => { + let ptr = passwd.pw_dir as *const _; + let bytes = CStr::from_ptr(ptr).to_bytes().to_vec(); + Some(OsStringExt::from_vec(bytes)) + }, + _ => None, } } } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 5166ddf8a21b6..66f09a7069c13 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -28,8 +28,8 @@ use mem; /// # Initialization and Destruction /// /// Initialization is dynamically performed on the first call to `with()` -/// within a thread, and values support destructors which will be run when a -/// thread exits. +/// within a thread, and values that implement `Drop` get destructed when a +/// thread exits. Some caveats apply, which are explained below. /// /// # Examples /// diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index 2b4d13375046e..2d59051ec4a53 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -201,6 +201,74 @@ where appropriate is ongoing. Try using an unquoted name instead: pub fn something() {} ``` "##, + +E0583: r##" +A file wasn't found for an out-of-line module. + +Erroneous code example: + +```compile_fail,E0583 +mod file_that_doesnt_exist; // error: file not found for module + +fn main() {} +``` + +Please be sure that a file corresponding to the module exists. If you +want to use a module named `file_that_doesnt_exist`, you need to have a file +named `file_that_doesnt_exist.rs` or `file_that_doesnt_exist/mod.rs` in the +same directory. +"##, + +E0585: r##" +A documentation comment that doesn't document anything was found. + +Erroneous code example: + +```compile_fail,E0585 +fn main() { + // The following doc comment will fail: + /// This is a useless doc comment! +} +``` + +Documentation comments need to be followed by items, including functions, +types, modules, etc. Examples: + +``` +/// I'm documenting the following struct: +struct Foo; + +/// I'm documenting the following function: +fn foo() {} +``` +"##, + +E0586: r##" +An inclusive range was used with no end. + +Erroneous code example: + +```compile_fail,E0586 +let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; +let x = &tmp[1...]; // error: inclusive range was used with no end +``` + +An inclusive range needs an end in order to *include* it. If you just need a +start and no end, use a non-inclusive range (with `..`): + +``` +let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; +let x = &tmp[1..]; // ok! +``` + +Or put an end to your inclusive range: + +``` +let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; +let x = &tmp[1...3]; // ok! +``` +"##, + } register_diagnostics! { @@ -224,4 +292,5 @@ register_diagnostics! { E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word E0557, // feature has been removed + E0584, // file for module `..` found at both .. and .. } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b5afd0c453a1e..b61ab74687bb7 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -474,6 +474,17 @@ impl MacResult for DummyResult { pub type BuiltinDeriveFn = for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable)); +/// Represents different kinds of macro invocations that can be resolved. +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum MacroKind { + /// A bang macro - foo!() + Bang, + /// An attribute macro - #[foo] + Attr, + /// A derive attribute macro - #[derive(Foo)] + Derive, +} + /// An enum representing the different kinds of syntax extensions. pub enum SyntaxExtension { /// A syntax extension that is attached to an item and creates new items @@ -520,6 +531,25 @@ pub enum SyntaxExtension { BuiltinDerive(BuiltinDeriveFn), } +impl SyntaxExtension { + /// Return which kind of macro calls this syntax extension. + pub fn kind(&self) -> MacroKind { + match *self { + SyntaxExtension::NormalTT(..) | + SyntaxExtension::IdentTT(..) | + SyntaxExtension::ProcMacro(..) => + MacroKind::Bang, + SyntaxExtension::MultiDecorator(..) | + SyntaxExtension::MultiModifier(..) | + SyntaxExtension::AttrProcMacro(..) => + MacroKind::Attr, + SyntaxExtension::ProcMacroDerive(..) | + SyntaxExtension::BuiltinDerive(..) => + MacroKind::Derive, + } + } +} + pub type NamedSyntaxExtension = (Name, SyntaxExtension); pub trait Resolver { @@ -535,10 +565,8 @@ pub trait Resolver { fn resolve_imports(&mut self); // Resolves attribute and derive legacy macros from `#![plugin(..)]`. fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec) -> Option; - fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) - -> Result, Determinacy>; - fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) - -> Result, Determinacy>; + fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, + force: bool) -> Result, Determinacy>; } #[derive(Copy, Clone, Debug)] @@ -561,12 +589,8 @@ impl Resolver for DummyResolver { fn resolve_imports(&mut self) {} fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } - fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) - -> Result, Determinacy> { - Err(Determinacy::Determined) - } - fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) - -> Result, Determinacy> { + fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind, + _force: bool) -> Result, Determinacy> { Err(Determinacy::Determined) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d011d7c2a1c44..38494378f72ad 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -282,8 +282,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mark = Mark::fresh(); derives.push(mark); let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); - let item = match self.cx.resolver - .resolve_macro(Mark::root(), &path, false) { + let item = match self.cx.resolver.resolve_macro( + Mark::root(), &path, MacroKind::Derive, false) { Ok(ext) => match *ext { SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(), _ => item.clone(), @@ -369,12 +369,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { -> Result>, Determinacy> { let (attr, traits, item) = match invoc.kind { InvocationKind::Bang { ref mac, .. } => { - return self.cx.resolver.resolve_macro(scope, &mac.node.path, force).map(Some); + return self.cx.resolver.resolve_macro(scope, &mac.node.path, + MacroKind::Bang, force).map(Some); } InvocationKind::Attr { attr: None, .. } => return Ok(None), InvocationKind::Derive { name, span, .. } => { let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); - return self.cx.resolver.resolve_derive_macro(scope, &path, force).map(Some); + return self.cx.resolver.resolve_macro(scope, &path, + MacroKind::Derive, force).map(Some) } InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item), }; @@ -385,7 +387,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; let mut determined = true; - match self.cx.resolver.resolve_macro(scope, &path, force) { + match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Attr, force) { Ok(ext) => return Ok(Some(ext)), Err(Determinacy::Undetermined) => determined = false, Err(Determinacy::Determined) if force => return Err(Determinacy::Determined), @@ -394,7 +396,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { for &(name, span) in traits { let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name)); - match self.cx.resolver.resolve_macro(scope, &path, force) { + match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Derive, force) { Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext { if inert_attrs.contains(&attr_name) { // FIXME(jseyfried) Avoid `mem::replace` here. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2c4fa8e15edf2..b5b8a6bc0ef64 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -219,7 +219,7 @@ fn is_ident_or_underscore(t: &token::Token) -> bool { pub struct ModulePath { pub name: String, pub path_exists: bool, - pub result: Result, + pub result: Result, } pub struct ModulePathSuccess { @@ -233,6 +233,63 @@ pub struct ModulePathError { pub help_msg: String, } +pub enum Error { + FileNotFoundForModule { + mod_name: String, + default_path: String, + secondary_path: String, + dir_path: String, + }, + DuplicatePaths { + mod_name: String, + default_path: String, + secondary_path: String, + }, + UselessDocComment, + InclusiveRangeWithNoEnd, +} + +impl Error { + pub fn span_err<'a>(self, sp: Span, handler: &'a errors::Handler) -> DiagnosticBuilder<'a> { + match self { + Error::FileNotFoundForModule { ref mod_name, + ref default_path, + ref secondary_path, + ref dir_path } => { + let mut err = struct_span_err!(handler, sp, E0583, + "file not found for module `{}`", mod_name); + err.help(&format!("name the file either {} or {} inside the directory {:?}", + default_path, + secondary_path, + dir_path)); + err + } + Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { + let mut err = struct_span_err!(handler, sp, E0584, + "file for module `{}` found at both {} and {}", + mod_name, + default_path, + secondary_path); + err.help("delete or rename one of them to remove the ambiguity"); + err + } + Error::UselessDocComment => { + let mut err = struct_span_err!(handler, sp, E0585, + "found a documentation comment that doesn't document anything"); + err.help("doc comments must come before what they document, maybe a comment was \ + intended with `//`?"); + err + } + Error::InclusiveRangeWithNoEnd => { + let mut err = struct_span_err!(handler, sp, E0586, + "inclusive range with no end"); + err.help("inclusive ranges must be bounded at the end (`...b` or `a...b`)"); + err + } + } + } +} + pub enum LhsExpr { NotYetParsed, AttributesParsed(ThinVec), @@ -461,10 +518,7 @@ impl<'a> Parser<'a> { } _ => { Err(if self.prev_token_kind == PrevTokenKind::DocComment { - self.span_fatal_help(self.prev_span, - "found a documentation comment that doesn't document anything", - "doc comments must come before what they document, maybe a comment was \ - intended with `//`?") + self.span_fatal_err(self.prev_span, Error::UselessDocComment) } else { let mut err = self.fatal(&format!("expected identifier, found `{}`", self.this_token_to_string())); @@ -955,6 +1009,9 @@ impl<'a> Parser<'a> { pub fn span_fatal(&self, sp: Span, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(sp, m) } + pub fn span_fatal_err(&self, sp: Span, err: Error) -> DiagnosticBuilder<'a> { + err.span_err(sp, self.diagnostic()) + } pub fn span_fatal_help(&self, sp: Span, m: &str, help: &str) -> DiagnosticBuilder<'a> { let mut err = self.sess.span_diagnostic.struct_span_fatal(sp, m); err.help(help); @@ -1944,10 +2001,7 @@ impl<'a> Parser<'a> { limits: RangeLimits) -> PResult<'a, ast::ExprKind> { if end.is_none() && limits == RangeLimits::Closed { - Err(self.span_fatal_help(self.span, - "inclusive range with no end", - "inclusive ranges must be bounded at the end \ - (`...b` or `a...b`)")) + Err(self.span_fatal_err(self.span, Error::InclusiveRangeWithNoEnd)) } else { Ok(ExprKind::Range(start, end, limits)) } @@ -3862,10 +3916,7 @@ impl<'a> Parser<'a> { let unused_attrs = |attrs: &[_], s: &mut Self| { if attrs.len() > 0 { if s.prev_token_kind == PrevTokenKind::DocComment { - s.span_err_help(s.prev_span, - "found a documentation comment that doesn't document anything", - "doc comments must come before what they document, maybe a \ - comment was intended with `//`?"); + s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit(); } else { s.span_err(s.span, "expected statement after outer attribute"); } @@ -4998,10 +5049,8 @@ impl<'a> Parser<'a> { self.bump(); } token::CloseDelim(token::Brace) => {} - token::DocComment(_) => return Err(self.span_fatal_help(self.span, - "found a documentation comment that doesn't document anything", - "doc comments must come before what they document, maybe a comment was \ - intended with `//`?")), + token::DocComment(_) => return Err(self.span_fatal_err(self.span, + Error::UselessDocComment)), _ => return Err(self.span_fatal_help(self.span, &format!("expected `,`, or `}}`, found `{}`", self.this_token_to_string()), "struct fields should be separated by commas")), @@ -5162,8 +5211,7 @@ impl<'a> Parser<'a> { } /// Returns either a path to a module, or . - pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -> ModulePath - { + pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -> ModulePath { let mod_name = id.to_string(); let default_path_str = format!("{}.rs", mod_name); let secondary_path_str = format!("{}/mod.rs", mod_name); @@ -5183,19 +5231,16 @@ impl<'a> Parser<'a> { directory_ownership: DirectoryOwnership::Owned, warn: false, }), - (false, false) => Err(ModulePathError { - err_msg: format!("file not found for module `{}`", mod_name), - help_msg: format!("name the file either {} or {} inside the directory {:?}", - default_path_str, - secondary_path_str, - dir_path.display()), + (false, false) => Err(Error::FileNotFoundForModule { + mod_name: mod_name.clone(), + default_path: default_path_str, + secondary_path: secondary_path_str, + dir_path: format!("{}", dir_path.display()), }), - (true, true) => Err(ModulePathError { - err_msg: format!("file for module `{}` found at both {} and {}", - mod_name, - default_path_str, - secondary_path_str), - help_msg: "delete or rename one of them to remove the ambiguity".to_owned(), + (true, true) => Err(Error::DuplicatePaths { + mod_name: mod_name.clone(), + default_path: default_path_str, + secondary_path: secondary_path_str, }), }; @@ -5232,7 +5277,7 @@ impl<'a> Parser<'a> { paths.name); err.span_note(id_sp, &msg); } - return Err(err); + Err(err) } else if let DirectoryOwnership::UnownedViaMod(warn) = self.directory.ownership { if warn { if let Ok(result) = paths.result { @@ -5254,15 +5299,12 @@ impl<'a> Parser<'a> { &format!("... or maybe `use` the module `{}` instead \ of possibly redeclaring it", paths.name)); - return Err(err); + Err(err) } else { - return Err(err); - }; - } - - match paths.result { - Ok(succ) => Ok(succ), - Err(err) => Err(self.span_fatal_help(id_sp, &err.err_msg, &err.help_msg)), + Err(err) + } + } else { + paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) } } diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index b74f491385820..ab36e9a2c2b20 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be forcibly cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2016-12-19 +2017-02-15 diff --git a/src/test/compile-fail-fulldeps/gated-quote.rs b/src/test/compile-fail-fulldeps/gated-quote.rs index 3480bd895bf1c..726af9864b482 100644 --- a/src/test/compile-fail-fulldeps/gated-quote.rs +++ b/src/test/compile-fail-fulldeps/gated-quote.rs @@ -25,32 +25,45 @@ extern crate syntax; use syntax::ast; use syntax::parse; -use syntax_pos::Span; struct ParseSess; impl ParseSess { fn cfg(&self) -> ast::CrateConfig { loop { } } fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { loop { } } - fn call_site(&self) -> Span { loop { } } + fn call_site(&self) -> () { loop { } } fn ident_of(&self, st: &str) -> ast::Ident { loop { } } fn name_of(&self, st: &str) -> ast::Name { loop { } } } pub fn main() { let ecx = &ParseSess; - let x = quote_tokens!(ecx, 3); //~ ERROR macro undefined: `quote_tokens` - let x = quote_expr!(ecx, 3); //~ ERROR macro undefined: `quote_expr` - let x = quote_ty!(ecx, 3); //~ ERROR macro undefined: `quote_ty` - let x = quote_method!(ecx, 3); //~ ERROR macro undefined: `quote_method` - let x = quote_item!(ecx, 3); //~ ERROR macro undefined: `quote_item` - let x = quote_pat!(ecx, 3); //~ ERROR macro undefined: `quote_pat` - let x = quote_arm!(ecx, 3); //~ ERROR macro undefined: `quote_arm` - let x = quote_stmt!(ecx, 3); //~ ERROR macro undefined: `quote_stmt` - let x = quote_matcher!(ecx, 3); //~ ERROR macro undefined: `quote_matcher` - let x = quote_attr!(ecx, 3); //~ ERROR macro undefined: `quote_attr` - let x = quote_arg!(ecx, 3); //~ ERROR macro undefined: `quote_arg` - let x = quote_block!(ecx, 3); //~ ERROR macro undefined: `quote_block` - let x = quote_meta_item!(ecx, 3); //~ ERROR macro undefined: `quote_meta_item` - let x = quote_path!(ecx, 3); //~ ERROR macro undefined: `quote_path` + let x = quote_tokens!(ecx, 3); + //~^ ERROR cannot find macro `quote_tokens!` in this scope + let x = quote_expr!(ecx, 3); + //~^ ERROR cannot find macro `quote_expr!` in this scope + let x = quote_ty!(ecx, 3); + //~^ ERROR cannot find macro `quote_ty!` in this scope + let x = quote_method!(ecx, 3); + //~^ ERROR cannot find macro `quote_method!` in this scope + let x = quote_item!(ecx, 3); + //~^ ERROR cannot find macro `quote_item!` in this scope + let x = quote_pat!(ecx, 3); + //~^ ERROR cannot find macro `quote_pat!` in this scope + let x = quote_arm!(ecx, 3); + //~^ ERROR cannot find macro `quote_arm!` in this scope + let x = quote_stmt!(ecx, 3); + //~^ ERROR cannot find macro `quote_stmt!` in this scope + let x = quote_matcher!(ecx, 3); + //~^ ERROR cannot find macro `quote_matcher!` in this scope + let x = quote_attr!(ecx, 3); + //~^ ERROR cannot find macro `quote_attr!` in this scope + let x = quote_arg!(ecx, 3); + //~^ ERROR cannot find macro `quote_arg!` in this scope + let x = quote_block!(ecx, 3); + //~^ ERROR cannot find macro `quote_block!` in this scope + let x = quote_meta_item!(ecx, 3); + //~^ ERROR cannot find macro `quote_meta_item!` in this scope + let x = quote_path!(ecx, 3); + //~^ ERROR cannot find macro `quote_path!` in this scope } diff --git a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs index d5d8d7b6ef85a..886b6247c0a3d 100644 --- a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs +++ b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs @@ -14,5 +14,6 @@ extern crate macro_crate_test; fn main() { - assert_eq!(3, unexported_macro!()); //~ ERROR macro undefined: `unexported_macro` + unexported_macro!(); + //~^ ERROR cannot find macro `unexported_macro!` in this scope } diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs new file mode 100644 index 0000000000000..719fbdb15ef2a --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs @@ -0,0 +1,23 @@ +// 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Clona)] +pub fn derive_clonea(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs new file mode 100644 index 0000000000000..64dcf72ba2029 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs @@ -0,0 +1,23 @@ +// 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. + +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(FooWithLongName)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs b/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs new file mode 100644 index 0000000000000..c9a36920a19e4 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs @@ -0,0 +1,44 @@ +// 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. + +// aux-build:derive-foo.rs +// aux-build:derive-clona.rs +// aux-build:attr_proc_macro.rs + +#![feature(proc_macro)] + +#[macro_use] +extern crate derive_foo; +#[macro_use] +extern crate derive_clona; +extern crate attr_proc_macro; + +use attr_proc_macro::attr_proc_macro; + +#[derive(FooWithLongNam)] +//~^ ERROR cannot find derive macro `FooWithLongNam` in this scope +//~^^ HELP did you mean `FooWithLongName`? +struct Foo; + +#[attr_proc_macra] +//~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope +struct Bar; + +#[derive(Dlone)] +//~^ ERROR cannot find derive macro `Dlone` in this scope +//~^^ HELP did you mean `Clone`? +struct A; + +#[derive(Dlona)] +//~^ ERROR cannot find derive macro `Dlona` in this scope +//~^^ HELP did you mean `Clona`? +struct B; + +fn main() {} diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/compile-fail/E0583.rs similarity index 67% rename from src/test/compile-fail/issue-5500.rs rename to src/test/compile-fail/E0583.rs index 1cbb7588e17df..3a5255d0f5fe3 100644 --- a/src/test/compile-fail/issue-5500.rs +++ b/src/test/compile-fail/E0583.rs @@ -1,4 +1,4 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +mod module_that_doesnt_exist; //~ ERROR E0583 + fn main() { - &panic!() - //~^ ERROR mismatched types - //~| expected type `()` - //~| found type `&_` - //~| expected (), found reference } diff --git a/src/test/compile-fail/E0585.rs b/src/test/compile-fail/E0585.rs new file mode 100644 index 0000000000000..1acaf8c0b78b6 --- /dev/null +++ b/src/test/compile-fail/E0585.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + /// Hello! I'm useless... + //~^ ERROR E0585 +} diff --git a/src/test/compile-fail/E0586.rs b/src/test/compile-fail/E0586.rs new file mode 100644 index 0000000000000..0b063569abc17 --- /dev/null +++ b/src/test/compile-fail/E0586.rs @@ -0,0 +1,14 @@ +// 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. + +fn main() { + let tmp = vec![0, 1, 2, 3, 4, 4, 3, 3, 2, 1]; + let x = &tmp[1...]; //~ ERROR E0586 +} diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs index 97a39a46c19a8..04fdee5e3edf6 100644 --- a/src/test/compile-fail/deriving-primitive.rs +++ b/src/test/compile-fail/deriving-primitive.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(FromPrimitive)] //~ERROR cannot find derive macro `FromPrimitive` in this scope +#[derive(FromPrimitive)] //~ ERROR cannot find derive macro `FromPrimitive` in this scope enum Foo {} fn main() {} diff --git a/src/test/compile-fail/empty-macro-use.rs b/src/test/compile-fail/empty-macro-use.rs index d8cf23d1ff0bb..823a7426079aa 100644 --- a/src/test/compile-fail/empty-macro-use.rs +++ b/src/test/compile-fail/empty-macro-use.rs @@ -14,5 +14,6 @@ extern crate two_macros; pub fn main() { - macro_two!(); //~ ERROR macro undefined + macro_two!(); + //~^ ERROR cannot find macro } diff --git a/src/test/compile-fail/ext-nonexistent.rs b/src/test/compile-fail/ext-nonexistent.rs index 3727d91d5ead4..a5bf796062487 100644 --- a/src/test/compile-fail/ext-nonexistent.rs +++ b/src/test/compile-fail/ext-nonexistent.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:macro undefined +// error-pattern:cannot find macro fn main() { iamnotanextensionthatexists!(""); } diff --git a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs b/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs index 03c3960a1efe2..bbdf248780f33 100644 --- a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs +++ b/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs @@ -12,12 +12,12 @@ // gate __register_diagnostic!(E0001); -//~^ ERROR macro undefined: `__register_diagnostic` +//~^ ERROR cannot find macro `__register_diagnostic!` in this scope fn main() { __diagnostic_used!(E0001); - //~^ ERROR macro undefined: `__diagnostic_used` + //~^ ERROR cannot find macro `__diagnostic_used!` in this scope } __build_diagnostic_array!(DIAGNOSTICS); -//~^ ERROR macro undefined: `__build_diagnostic_array` +//~^ ERROR cannot find macro `__build_diagnostic_array!` in this scope diff --git a/src/test/compile-fail/issue-11692-1.rs b/src/test/compile-fail/issue-11692-1.rs new file mode 100644 index 0000000000000..f577aad04e620 --- /dev/null +++ b/src/test/compile-fail/issue-11692-1.rs @@ -0,0 +1,14 @@ +// Copyright 2014 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. + +fn main() { + print!(test!()); + //~^ ERROR: format argument must be a string literal +} diff --git a/src/test/compile-fail/issue-11692.rs b/src/test/compile-fail/issue-11692-2.rs similarity index 75% rename from src/test/compile-fail/issue-11692.rs rename to src/test/compile-fail/issue-11692-2.rs index 7819fd4c1abc7..acac2d151fe9a 100644 --- a/src/test/compile-fail/issue-11692.rs +++ b/src/test/compile-fail/issue-11692-2.rs @@ -9,10 +9,6 @@ // except according to those terms. fn main() { - print!(test!()); - //~^ ERROR: macro undefined: `test` - //~^^ ERROR: format argument must be a string literal - concat!(test!()); - //~^ ERROR: macro undefined: `test` + //~^ ERROR cannot find macro `test!` in this scope } diff --git a/src/test/compile-fail/issue-17728.rs b/src/test/compile-fail/issue-17728.rs index f508d7123d88f..9724d17bef1ea 100644 --- a/src/test/compile-fail/issue-17728.rs +++ b/src/test/compile-fail/issue-17728.rs @@ -108,9 +108,6 @@ impl Debug for Player { fn str_to_direction(to_parse: &str) -> RoomDirection { match to_parse { //~ ERROR match arms have incompatible types - //~^ expected enum `RoomDirection`, found enum `std::option::Option` - //~| expected type `RoomDirection` - //~| found type `std::option::Option<_>` "w" | "west" => RoomDirection::West, "e" | "east" => RoomDirection::East, "n" | "north" => RoomDirection::North, @@ -119,7 +116,7 @@ fn str_to_direction(to_parse: &str) -> RoomDirection { "out" => RoomDirection::Out, "up" => RoomDirection::Up, "down" => RoomDirection::Down, - _ => None //~ NOTE match arm with an incompatible type + _ => None } } diff --git a/src/test/compile-fail/issue-19734.rs b/src/test/compile-fail/issue-19734.rs index fe0648c3713ff..a3820d20aac5b 100644 --- a/src/test/compile-fail/issue-19734.rs +++ b/src/test/compile-fail/issue-19734.rs @@ -10,6 +10,9 @@ fn main() {} +struct Type; + impl Type { - undef!(); //~ ERROR macro undefined: `undef` + undef!(); + //~^ ERROR cannot find macro `undef!` in this scope } diff --git a/src/test/compile-fail/issue-39559.rs b/src/test/compile-fail/issue-39559.rs new file mode 100644 index 0000000000000..a56a5e8548944 --- /dev/null +++ b/src/test/compile-fail/issue-39559.rs @@ -0,0 +1,31 @@ +// 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. + +trait Dim { + fn dim() -> usize; +} + +enum Dim3 {} + +impl Dim for Dim3 { + fn dim() -> usize { + 3 + } +} + +pub struct Vector { + entries: [T; D::dim()] + //~^ ERROR cannot use an outer type parameter in this context + //~| ERROR constant evaluation error +} + +fn main() { + let array: [usize; Dim3::dim()] = [0; Dim3::dim()]; +} diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs index 3512b21961a14..78f95e365c44b 100644 --- a/src/test/compile-fail/macro-error.rs +++ b/src/test/compile-fail/macro-error.rs @@ -16,5 +16,4 @@ fn main() { foo!(0); // Check that we report errors at macro definition, not expansion. let _: cfg!(foo) = (); //~ ERROR non-type macro in type position - derive!(); //~ ERROR macro undefined: `derive` } diff --git a/src/test/compile-fail/macro-expansion-tests.rs b/src/test/compile-fail/macro-expansion-tests.rs index a064e69bc6d59..ada06b0b3f452 100644 --- a/src/test/compile-fail/macro-expansion-tests.rs +++ b/src/test/compile-fail/macro-expansion-tests.rs @@ -12,14 +12,16 @@ mod macros_cant_escape_fns { fn f() { macro_rules! m { () => { 3 + 4 } } } - fn g() -> i32 { m!() } //~ ERROR macro undefined + fn g() -> i32 { m!() } + //~^ ERROR cannot find macro } mod macros_cant_escape_mods { mod f { macro_rules! m { () => { 3 + 4 } } } - fn g() -> i32 { m!() } //~ ERROR macro undefined + fn g() -> i32 { m!() } + //~^ ERROR cannot find macro } mod macros_can_escape_flattened_mods_test { diff --git a/src/test/compile-fail/macro-name-typo.rs b/src/test/compile-fail/macro-name-typo.rs index e1f7d9b65d116..4840205fee4c3 100644 --- a/src/test/compile-fail/macro-name-typo.rs +++ b/src/test/compile-fail/macro-name-typo.rs @@ -9,6 +9,7 @@ // except according to those terms. fn main() { - printlx!("oh noes!"); //~ ERROR macro undefined - //~^ HELP did you mean `println!`? + printlx!("oh noes!"); + //~^ ERROR cannot find macro + //~^^ HELP did you mean `println!`? } diff --git a/src/test/compile-fail/macro-no-implicit-reexport.rs b/src/test/compile-fail/macro-no-implicit-reexport.rs index cd6640f8b6dda..07467e06eb2df 100644 --- a/src/test/compile-fail/macro-no-implicit-reexport.rs +++ b/src/test/compile-fail/macro-no-implicit-reexport.rs @@ -15,5 +15,6 @@ extern crate macro_non_reexport_2; fn main() { - assert_eq!(reexported!(), 3); //~ ERROR macro undefined + assert_eq!(reexported!(), 3); + //~^ ERROR cannot find macro `reexported!` in this scope } diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-reexport-not-locally-visible.rs index ca334d9fd2d78..54a74b0e13431 100644 --- a/src/test/compile-fail/macro-reexport-not-locally-visible.rs +++ b/src/test/compile-fail/macro-reexport-not-locally-visible.rs @@ -17,5 +17,6 @@ extern crate macro_reexport_1; fn main() { - assert_eq!(reexported!(), 3); //~ ERROR macro undefined + assert_eq!(reexported!(), 3); + //~^ ERROR cannot find macro } diff --git a/src/test/compile-fail/macro-use-wrong-name.rs b/src/test/compile-fail/macro-use-wrong-name.rs index 4dc65434dc7e1..143ecb4ce5e0a 100644 --- a/src/test/compile-fail/macro-use-wrong-name.rs +++ b/src/test/compile-fail/macro-use-wrong-name.rs @@ -14,5 +14,6 @@ extern crate two_macros; pub fn main() { - macro_two!(); //~ ERROR macro undefined + macro_two!(); + //~^ ERROR cannot find macro } diff --git a/src/test/compile-fail/macro_undefined.rs b/src/test/compile-fail/macro_undefined.rs index d35428efaccb3..00c8d44f30602 100644 --- a/src/test/compile-fail/macro_undefined.rs +++ b/src/test/compile-fail/macro_undefined.rs @@ -18,8 +18,10 @@ mod m { } fn main() { - k!(); //~ ERROR macro undefined: `k` - //~^ HELP did you mean `kl!`? - kl!(); //~ ERROR macro undefined: `kl` - //~^ HELP have you added the `#[macro_use]` on the module/import? + k!(); + //~^ ERROR cannot find macro `k!` in this scope + //~^^ HELP did you mean `kl!`? + kl!(); + //~^ ERROR cannot find macro `kl!` in this scope + //~^^ HELP have you added the `#[macro_use]` on the module/import? } diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs index 3f710af8ac9a8..7046ee12b50e5 100644 --- a/src/test/compile-fail/macros-nonfatal-errors.rs +++ b/src/test/compile-fail/macros-nonfatal-errors.rs @@ -14,15 +14,10 @@ #![feature(asm)] #![feature(trace_macros, concat_idents)] -#[derive(Zero)] //~ ERROR -struct CantDeriveThis; - #[derive(Default)] //~ ERROR enum OrDeriveThis {} fn main() { - doesnt_exist!(); //~ ERROR - asm!(invalid); //~ ERROR concat_idents!("not", "idents"); //~ ERROR diff --git a/src/test/compile-fail/missing-macro-use.rs b/src/test/compile-fail/missing-macro-use.rs index bbce9c2128757..bfe49ea000972 100644 --- a/src/test/compile-fail/missing-macro-use.rs +++ b/src/test/compile-fail/missing-macro-use.rs @@ -13,5 +13,6 @@ extern crate two_macros; pub fn main() { - macro_two!(); //~ ERROR macro undefined + macro_two!(); + //~^ ERROR cannot find macro `macro_two!` in this scope } diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs index 82037b6c9ed02..04f98c7ab329f 100644 --- a/src/test/compile-fail/resolve-self-in-impl.rs +++ b/src/test/compile-fail/resolve-self-in-impl.rs @@ -18,9 +18,12 @@ impl> Tr for S {} //~ ERROR `Self` type is used before it's deter impl Tr for S {} //~ ERROR `Self` type is used before it's determined impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined impl Tr for S where S: Copy {} //~ ERROR `Self` type is used before it's determined +impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined + //~^ ERROR `Self` type is used before it's determined impl Tr for Self {} //~ ERROR `Self` type is used before it's determined impl Tr for S {} //~ ERROR `Self` type is used before it's determined impl Self {} //~ ERROR `Self` type is used before it's determined impl S {} //~ ERROR `Self` type is used before it's determined +impl Tr for S {} //~ ERROR `Self` type is used before it's determined fn main() {} diff --git a/src/test/compile-fail/self_type_keyword.rs b/src/test/compile-fail/self_type_keyword.rs index b3ab96b79c492..20d2e2ca9cfa1 100644 --- a/src/test/compile-fail/self_type_keyword.rs +++ b/src/test/compile-fail/self_type_keyword.rs @@ -10,12 +10,16 @@ // compile-flags: -Z continue-parse-after-error -struct Self; -//~^ ERROR expected identifier, found keyword `Self` +mod foo { + struct Self; + //~^ ERROR expected identifier, found keyword `Self` +} struct Bar<'Self>; //~^ ERROR lifetimes cannot use keyword names +struct Foo; + pub fn main() { match 15 { ref Self => (), @@ -25,7 +29,7 @@ pub fn main() { ref mut Self => (), //~^ ERROR expected identifier, found keyword `Self` Self!() => (), - //~^ ERROR macro undefined: `Self` + //~^ ERROR cannot find macro `Self!` in this scope Foo { Self } => (), //~^ ERROR expected identifier, found keyword `Self` } diff --git a/src/test/run-pass/const-enum-vec-index.rs b/src/test/run-pass/const-enum-vec-index.rs index 4af6a6d10d5bf..9c1a4dbdffa84 100644 --- a/src/test/run-pass/const-enum-vec-index.rs +++ b/src/test/run-pass/const-enum-vec-index.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[derive(Copy, Clone)] enum E { V1(isize), V0 } + const C: &'static [E] = &[E::V0, E::V1(0xDEADBEE)]; static C0: E = C[0]; static C1: E = C[1]; diff --git a/src/test/compile-fail/issue-10176.rs b/src/test/run-pass/inference-changes-39485.rs similarity index 82% rename from src/test/compile-fail/issue-10176.rs rename to src/test/run-pass/inference-changes-39485.rs index 434b795ff31f5..193c66b2a2afd 100644 --- a/src/test/compile-fail/issue-10176.rs +++ b/src/test/run-pass/inference-changes-39485.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn g() { + &panic!() +} + fn f() -> isize { (return 1, return 2) -//~^ ERROR mismatched types -//~| expected type `isize` -//~| found type `(_, _)` -//~| expected isize, found tuple } fn main() {} diff --git a/src/test/run-pass/issue-15763.rs b/src/test/run-pass/issue-15763.rs index 0baaaac267685..f77888c29554d 100644 --- a/src/test/run-pass/issue-15763.rs +++ b/src/test/run-pass/issue-15763.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] +#![allow(unused_features)] +#![allow(unreachable_code)] #![feature(box_syntax)] #[derive(PartialEq, Debug)] @@ -28,14 +29,14 @@ struct Foo { } fn foo() -> Result { - return Ok(Foo { + return Ok::(Foo { x: Bar { x: 22 }, a: return Err(32) }); } fn baz() -> Result { - Ok(Foo { + Ok::(Foo { x: Bar { x: 22 }, a: return Err(32) }) diff --git a/src/test/run-pass/issue-39292.rs b/src/test/run-pass/issue-39292.rs new file mode 100644 index 0000000000000..dc2b21f3470e8 --- /dev/null +++ b/src/test/run-pass/issue-39292.rs @@ -0,0 +1,26 @@ +// 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. + +// Regression test for issue #39292. The object vtable was being +// incorrectly left with a null pointer. + +trait Foo { + fn print<'a>(&'a self) where T: 'a { println!("foo"); } +} + +impl<'a> Foo<&'a ()> for () { } + +trait Bar: for<'a> Foo<&'a ()> { } + +impl Bar for () {} + +fn main() { + (&() as &Bar).print(); // Segfault +} diff --git a/src/test/run-pass/project-defer-unification.rs b/src/test/run-pass/project-defer-unification.rs index 9a6ea2272fea7..8e008c639b30e 100644 --- a/src/test/run-pass/project-defer-unification.rs +++ b/src/test/run-pass/project-defer-unification.rs @@ -11,6 +11,8 @@ // A regression test extracted from image-0.3.11. The point of // failure was in `index_colors` below. +#![allow(unused)] + use std::ops::{Deref, DerefMut}; #[derive(Copy, Clone)] @@ -92,7 +94,7 @@ pub fn index_colors(image: &ImageBuffer>) -> ImageBuffer, Vec> where Pix: Pixel + 'static, { - let mut indices: ImageBuffer<_,Vec<_>> = loop { }; + let mut indices: ImageBuffer, Vec> = loop { }; for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) { // failured occurred here ^^ because we were requiring that we // could project Pixel or Subpixel from `T_indices` (type of diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.rs new file mode 100644 index 0000000000000..30239f4c0946c --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.rs @@ -0,0 +1,15 @@ +// 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. + +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + if x > y { x } else { y } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr new file mode 100644 index 0000000000000..85e05422ab3b2 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr @@ -0,0 +1,25 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27 + | +12 | if x > y { x } else { y } + | ^ + | +note: ...the reference is valid for the lifetime 'a as defined on the body at 11:43... + --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44 + | +11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + | ____________________________________________^ starting here... +12 | | if x > y { x } else { y } +13 | | } + | |_^ ...ending here +note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the body at 11:43 + --> $DIR/ex1-return-one-existing-name-if-else.rs:11:44 + | +11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { + | ____________________________________________^ starting here... +12 | | if x > y { x } else { y } +13 | | } + | |_^ ...ending here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.rs b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.rs new file mode 100644 index 0000000000000..098950e13b315 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.rs @@ -0,0 +1,15 @@ +// 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. + +fn foo(x: &i32, y: &i32) -> &i32 { + if x > y { x } else { y } +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr new file mode 100644 index 0000000000000..fccc44caac81a --- /dev/null +++ b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -0,0 +1,10 @@ +error[E0106]: missing lifetime specifier + --> $DIR/ex1b-return-no-names-if-else.rs:11:29 + | +11 | fn foo(x: &i32, y: &i32) -> &i32 { + | ^ expected lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.rs new file mode 100644 index 0000000000000..71a1c865e0995 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.rs @@ -0,0 +1,19 @@ +// 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 Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a>(x: &mut Vec>, y: Ref) { + x.push(y); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr new file mode 100644 index 0000000000000..6f42a9f679a6a --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/ex2a-push-one-existing-name.rs:16:12 + | +16 | x.push(y); + | ^ lifetime mismatch + | + = note: expected type `Ref<'a, i32>` + found type `Ref<'_, i32>` +note: the anonymous lifetime #2 defined on the body at 15:51... + --> $DIR/ex2a-push-one-existing-name.rs:15:52 + | +15 | fn foo<'a>(x: &mut Vec>, y: Ref) { + | ____________________________________________________^ starting here... +16 | | x.push(y); +17 | | } + | |_^ ...ending here +note: ...does not necessarily outlive the lifetime 'a as defined on the body at 15:51 + --> $DIR/ex2a-push-one-existing-name.rs:15:52 + | +15 | fn foo<'a>(x: &mut Vec>, y: Ref) { + | ____________________________________________________^ starting here... +16 | | x.push(y); +17 | | } + | |_^ ...ending here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.rs b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.rs new file mode 100644 index 0000000000000..09038d8ce9027 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.rs @@ -0,0 +1,19 @@ +// 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 Ref<'a, T: 'a> { + data: &'a T +} + +fn foo(x: &mut Vec>, y: Ref) { + x.push(y); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr new file mode 100644 index 0000000000000..edc1c2362de57 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/ex2b-push-no-existing-names.rs:16:12 + | +16 | x.push(y); + | ^ lifetime mismatch + | + = note: expected type `Ref<'_, i32>` + found type `Ref<'_, i32>` +note: the anonymous lifetime #3 defined on the body at 15:43... + --> $DIR/ex2b-push-no-existing-names.rs:15:44 + | +15 | fn foo(x: &mut Vec>, y: Ref) { + | ____________________________________________^ starting here... +16 | | x.push(y); +17 | | } + | |_^ ...ending here +note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 15:43 + --> $DIR/ex2b-push-no-existing-names.rs:15:44 + | +15 | fn foo(x: &mut Vec>, y: Ref) { + | ____________________________________________^ starting here... +16 | | x.push(y); +17 | | } + | |_^ ...ending here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.rs b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.rs new file mode 100644 index 0000000000000..cb083f778deeb --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.rs @@ -0,0 +1,20 @@ +// 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 Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + let z = Ref { data: y.data }; + x.push(z); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr new file mode 100644 index 0000000000000..755b71d4a1d9e --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr @@ -0,0 +1,37 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/ex2c-push-inference-variable.rs:16:13 + | +16 | let z = Ref { data: y.data }; + | ^^^ + | +note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66... + --> $DIR/ex2c-push-inference-variable.rs:15:67 + | +15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | ___________________________________________________________________^ starting here... +16 | | let z = Ref { data: y.data }; +17 | | x.push(z); +18 | | } + | |_^ ...ending here +note: ...so that reference does not outlive borrowed content + --> $DIR/ex2c-push-inference-variable.rs:16:25 + | +16 | let z = Ref { data: y.data }; + | ^^^^^^ +note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66... + --> $DIR/ex2c-push-inference-variable.rs:15:67 + | +15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | ___________________________________________________________________^ starting here... +16 | | let z = Ref { data: y.data }; +17 | | x.push(z); +18 | | } + | |_^ ...ending here +note: ...so that expression is assignable (expected Ref<'b, i32>, found Ref<'_, i32>) + --> $DIR/ex2c-push-inference-variable.rs:17:12 + | +17 | x.push(z); + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.rs b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.rs new file mode 100644 index 0000000000000..bcb7583beefcf --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.rs @@ -0,0 +1,21 @@ +// 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 Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + let a: &mut Vec> = x; + let b = Ref { data: y.data }; + a.push(b); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr new file mode 100644 index 0000000000000..daa6ea2d91aa3 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -0,0 +1,39 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/ex2d-push-inference-variable-2.rs:17:13 + | +17 | let b = Ref { data: y.data }; + | ^^^ + | +note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66... + --> $DIR/ex2d-push-inference-variable-2.rs:15:67 + | +15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | ___________________________________________________________________^ starting here... +16 | | let a: &mut Vec> = x; +17 | | let b = Ref { data: y.data }; +18 | | a.push(b); +19 | | } + | |_^ ...ending here +note: ...so that reference does not outlive borrowed content + --> $DIR/ex2d-push-inference-variable-2.rs:17:25 + | +17 | let b = Ref { data: y.data }; + | ^^^^^^ +note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66... + --> $DIR/ex2d-push-inference-variable-2.rs:15:67 + | +15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | ___________________________________________________________________^ starting here... +16 | | let a: &mut Vec> = x; +17 | | let b = Ref { data: y.data }; +18 | | a.push(b); +19 | | } + | |_^ ...ending here +note: ...so that expression is assignable (expected &mut std::vec::Vec>, found &mut std::vec::Vec>) + --> $DIR/ex2d-push-inference-variable-2.rs:16:33 + | +16 | let a: &mut Vec> = x; + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.rs b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.rs new file mode 100644 index 0000000000000..2d05adb7ecd37 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.rs @@ -0,0 +1,21 @@ +// 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 Ref<'a, T: 'a> { + data: &'a T +} + +fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + let a: &mut Vec> = x; + let b = Ref { data: y.data }; + Vec::push(a, b); +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr new file mode 100644 index 0000000000000..b679532a4d910 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -0,0 +1,39 @@ +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/ex2e-push-inference-variable-3.rs:17:13 + | +17 | let b = Ref { data: y.data }; + | ^^^ + | +note: first, the lifetime cannot outlive the lifetime 'c as defined on the body at 15:66... + --> $DIR/ex2e-push-inference-variable-3.rs:15:67 + | +15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | ___________________________________________________________________^ starting here... +16 | | let a: &mut Vec> = x; +17 | | let b = Ref { data: y.data }; +18 | | Vec::push(a, b); +19 | | } + | |_^ ...ending here +note: ...so that reference does not outlive borrowed content + --> $DIR/ex2e-push-inference-variable-3.rs:17:25 + | +17 | let b = Ref { data: y.data }; + | ^^^^^^ +note: but, the lifetime must be valid for the lifetime 'b as defined on the body at 15:66... + --> $DIR/ex2e-push-inference-variable-3.rs:15:67 + | +15 | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { + | ___________________________________________________________________^ starting here... +16 | | let a: &mut Vec> = x; +17 | | let b = Ref { data: y.data }; +18 | | Vec::push(a, b); +19 | | } + | |_^ ...ending here +note: ...so that expression is assignable (expected &mut std::vec::Vec>, found &mut std::vec::Vec>) + --> $DIR/ex2e-push-inference-variable-3.rs:16:33 + | +16 | let a: &mut Vec> = x; + | ^ + +error: aborting due to previous error + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index d0aba8a0b0a7e..c9bdcd408ead7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -13,6 +13,7 @@ use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits}; use common::{Incremental, RunMake, Ui, MirOpt}; use errors::{self, ErrorKind, Error}; +use filetime::FileTime; use json; use header::TestProps; use header; @@ -2457,12 +2458,25 @@ actual:\n\ } } + fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) { + let t = |file| FileTime::from_last_modification_time(&fs::metadata(file).unwrap()); + let source_file = &self.testpaths.file; + let output_time = t(output_file); + let source_time = t(source_file); + if source_time > output_time { + debug!("source file time: {:?} output file time: {:?}", source_time, output_time); + panic!("test source file `{}` is newer than potentially stale output file `{}`.", + source_file.display(), test_name); + } + } + fn compare_mir_test_output(&self, test_name: &str, expected_content: &Vec<&str>) { let mut output_file = PathBuf::new(); output_file.push(self.get_mir_dump_dir()); output_file.push(test_name); debug!("comparing the contests of: {:?}", output_file); debug!("with: {:?}", expected_content); + self.check_mir_test_timestamp(test_name, &output_file); let mut dumped_file = fs::File::open(output_file.clone()).unwrap(); let mut dumped_string = String::new(); diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 304c722bbe5da..ba5ca44526b86 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -65,6 +65,7 @@ enum Redirect { struct FileEntry { source: String, ids: HashSet, + names: HashSet, } type Cache = HashMap; @@ -81,6 +82,15 @@ impl FileEntry { }); } } + + fn parse_names(&mut self, contents: &str) { + if self.names.is_empty() { + with_attrs_in_source(contents, " name", |fragment, _| { + let frag = fragment.trim_left_matches("#").to_owned(); + self.names.insert(frag); + }); + } + } } fn walk(cache: &mut Cache, root: &Path, dir: &Path, errors: &mut bool) { @@ -139,6 +149,9 @@ fn check(cache: &mut Cache, cache.get_mut(&pretty_file) .unwrap() .parse_ids(&pretty_file, &contents, errors); + cache.get_mut(&pretty_file) + .unwrap() + .parse_names(&contents); } // Search for anything that's the regex 'href[ ]*=[ ]*".*?"' @@ -209,13 +222,6 @@ fn check(cache: &mut Cache, Err(LoadError::IsRedirect) => unreachable!(), }; - // we don't check the book for fragments because they're added via JS - for book in ["book/", "nomicon/"].iter() { - if !pretty_path.to_str().unwrap().starts_with(book) { - return; - } - } - if let Some(ref fragment) = fragment { // Fragments like `#1-6` are most likely line numbers to be // interpreted by javascript, so we're ignoring these @@ -226,8 +232,9 @@ fn check(cache: &mut Cache, let entry = &mut cache.get_mut(&pretty_path).unwrap(); entry.parse_ids(&pretty_path, &contents, errors); + entry.parse_names(&contents); - if !entry.ids.contains(*fragment) { + if !(entry.ids.contains(*fragment) || entry.names.contains(*fragment)) { *errors = true; print!("{}:{}: broken link fragment ", pretty_file.display(), @@ -277,6 +284,7 @@ fn load_file(cache: &mut Cache, entry.insert(FileEntry { source: contents.clone(), ids: HashSet::new(), + names: HashSet::new(), }); } maybe diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 25c310aa8774a..f7a452d9f7bd7 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT/Apache-2.0" clap = "2.19.3" [dependencies.mdbook] -version = "0.0.14" +version = "0.0.16" default-features = false