From: bors Date: Tue, 15 May 2018 23:03:04 +0000 (+0000) Subject: Auto merge of #48523 - varkor:generics-ty-generalisations, r=nikomatsakis X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=e44fc6c52d9674ed09958512e3bf09bc55bccecf;hp=5be2bdb498249d71a4a5671f73224727784a1203;p=rust.git Auto merge of #48523 - varkor:generics-ty-generalisations, r=nikomatsakis The Great Generics Generalisation: Ty Edition Part of the generic parameter refactoring effort, split off from https://github.com/rust-lang/rust/pull/48149. Contains the `ty`-relative refactoring. r? @eddyb --- diff --git a/.travis.yml b/.travis.yml index 23c47bc9f76..9e62b895ed2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -197,7 +197,7 @@ env: # AWS_SECRET_ACCESS_KEY=... - secure: "j96XxTVOSUf4s4r4htIxn/fvIa5DWbMgLqWl7r8z2QfgUwscmkMXAwXuFNc7s7bGTpV/+CgDiMFFM6BAFLGKutytIF6oA02s9b+usQYnM0th7YQ2AIgm9GtMTJCJp4AoyfFmh8F2faUICBZlfVLUJ34udHEe35vOklix+0k4WDo=" # TOOLSTATE_REPO_ACCESS_TOKEN=... - - secure: "cFh8thThqEJLC98XKI5pfqflUzOlxsYPRW20AWRaYOOgYHPTiGWypTXiPbGSKaeAXTZoOA+DpQtEmefc0U6lt9dHc7a/MIaK6isFurjlnKYiLOeTruzyu1z7PWCeZ/jKXsU2RK/88DBtlNwfMdaMIeuKj14IVfpepPPL71ETbuk=" + - secure: "ESfcXqv4N2VMhqi2iIyw6da9VrsA78I4iR1asouCaq4hzTTrkB4WNRrfURy6xg72gQ4nMhtRJbB0/2jmc9Cu1+g2CzXtyiL223aJ5CKrXdcvbitopQSDfp07dMWm+UED+hNFEanpErKAeU/6FM3A+J+60PMk8MCF1h9tqNRISJw=" before_install: # We'll use the AWS cli to download/upload cached docker layers, so install diff --git a/appveyor.yml b/appveyor.yml index 60f5b4be8de..b1e2e1545cf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ environment: secure: 7Y+JiquYedOAgnUU26uL0DPzrxmTtR+qIwG6rNKSuWDffqU3vVZxbGXim9QpTO80 SCCACHE_DIGEST: f808afabb4a4eb1d7112bcb3fa6be03b61e93412890c88e177c667eb37f46353d7ec294e559b16f9f4b5e894f2185fe7670a0df15fd064889ecbd80f0c34166c TOOLSTATE_REPO_ACCESS_TOKEN: - secure: PTZiSxJMVUZ0VnMR5i13E4OagbXfglj7pcskDQiKufVrDm13mLoI0vDJAEM35+bY + secure: gKGlVktr7iuqCoYSxHxDE9ltLOKU0nYDEuQxvWbNxUIW7ri5ppn8L06jQzN0GGzN # By default schannel checks revocation of certificates unlike some other SSL # backends, but we've historically had problems on CI where a revocation diff --git a/src/Cargo.lock b/src/Cargo.lock index 2f52c889558..ce9fc63230d 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -79,15 +79,15 @@ dependencies = [ [[package]] name = "assert_cli" -version = "0.5.6" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -183,6 +183,11 @@ dependencies = [ name = "build_helper" version = "0.1.0" +[[package]] +name = "bytecount" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.2" @@ -570,6 +575,11 @@ name = "diff" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "difference" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "difference" version = "2.0.0" @@ -1188,6 +1198,14 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "minifier" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miniz-sys" version = "0.1.10" @@ -1550,7 +1568,7 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1689,6 +1707,15 @@ dependencies = [ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rls-data" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rls-rustc" version = "0.2.2" @@ -2140,7 +2167,7 @@ name = "rustc_save_analysis" version = "0.0.0" dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2260,6 +2287,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ + "minifier 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2290,7 +2318,7 @@ dependencies = [ name = "rustfmt-nightly" version = "0.6.1" dependencies = [ - "assert_cli 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2417,6 +2445,21 @@ name = "siphasher" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "skeptic" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "smallvec" version = "0.6.0" @@ -2988,7 +3031,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" -"checksum assert_cli 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8ca6beaa44a3520407b28a4a779a19b1364fcadcb2f258c41a7baf3102ced0" +"checksum assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930" "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" "checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" @@ -2996,6 +3039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" +"checksum bytecount 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "882585cd7ec84e902472df34a5e01891202db3bf62614e1f0afe459c1afcf744" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3" "checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba" @@ -3020,6 +3064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" "checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" +"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" @@ -3083,6 +3128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum minifier 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "26f3e36a4db1981b16567e4abfd6ddc3641bc9b950bdc868701f656bf9b74bdd" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d" "checksum nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d77f3db4bce033f4d04db08079b2ef1c3d02b44e86f25d08886fafa7756ffa" @@ -3132,6 +3178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-analysis 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a41488cf5dc99d6ce383319d2978756567b70d4ed0539eb0d9ce07763e732e46" "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2" "checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510" +"checksum rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd20763e1c60ae8945384c8a8fa4ac44f8afa7b0a817511f5e8927e5d24f988" "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb" @@ -3162,6 +3209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9" "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" +"checksum skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4474d6da9593171bcb086890fc344a3a12783cb24e5b141f8a5d0e43561f4b6" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ff606e0486e88f5fc6cfeb3966e434fb409abbc7a3ab495238f70a1ca97f789d" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 220af6bd6e4..4b6e266f1e5 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -556,15 +556,6 @@ fn run(mut $sel, $builder: &Builder) -> Option { }; Miri, miri, "src/tools/miri", "miri", {}; Rls, rls, "src/tools/rls", "rls", { - let clippy = builder.ensure(Clippy { - compiler: self.compiler, - target: self.target, - extra_features: Vec::new(), - }); - let channel = &builder.config.channel; - if clippy.is_some() && channel != "stable" && channel != "beta" { - self.extra_features.push("clippy".to_owned()); - } builder.ensure(native::Openssl { target: self.target, }); diff --git a/src/ci/docker/disabled/dist-sparc64-linux/Dockerfile b/src/ci/docker/disabled/dist-sparc64-linux/Dockerfile new file mode 100644 index 00000000000..952c265a139 --- /dev/null +++ b/src/ci/docker/disabled/dist-sparc64-linux/Dockerfile @@ -0,0 +1,26 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + g++-sparc64-linux-gnu \ + libssl-dev \ + pkg-config + + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV HOSTS=sparc64-unknown-linux-gnu + +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs +ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/x86_64-gnu-tools/repo.sh b/src/ci/docker/x86_64-gnu-tools/repo.sh index c10afef753e..807e6fb7b64 100644 --- a/src/ci/docker/x86_64-gnu-tools/repo.sh +++ b/src/ci/docker/x86_64-gnu-tools/repo.sh @@ -60,7 +60,7 @@ commit_toolstate_change() { OLDFLAGS="$-" set -eu - git config --global user.email '34210020+rust-toolstate-update@users.noreply.github.com' + git config --global user.email '7378925+rust-toolstate-update@users.noreply.github.com' git config --global user.name 'Rust Toolstate Update' git config --global credential.helper store printf 'https://%s:x-oauth-basic@github.com\n' "$TOOLSTATE_REPO_ACCESS_TOKEN" \ diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1 index 39d10539959..8f611063dbe 100644 --- a/src/doc/man/rustc.1 +++ b/src/doc/man/rustc.1 @@ -55,7 +55,7 @@ Configure the output that \fBrustc\fR will produce. Each emission may also have an optional explicit output \fIPATH\fR specified for that particular emission kind. This path takes precedence over the \fB-o\fR option. .TP -\fB\-\-print\fR [crate\-name|file\-names|sysroot] +\fB\-\-print\fR [crate\-name|\:file\-names|\:sysroot|\:cfg|\:target\-list|\:target\-cpus|\:target\-features|\:relocation\-models|\:code\-models|\:tls\-models|\:target\-spec\-json|\:native\-static\-libs] Comma separated list of compiler information to print on stdout. .TP \fB\-g\fR diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index fb0d2d9c882..7d3e7af1a18 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -962,59 +962,122 @@ /// value is not necessarily valid to be used to actually access memory. pub fn arith_offset(dst: *const T, offset: isize) -> *const T; - /// Copies `count * size_of` bytes from `src` to `dst`. The source - /// and destination may *not* overlap. + /// Copies `count * size_of::()` bytes from `src` to `dst`. The source + /// and destination must *not* overlap. /// - /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. + /// For regions of memory which might overlap, use [`copy`] instead. + /// + /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`]. + /// + /// [`copy`]: ./fn.copy.html + /// [`memcpy`]: https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html#index-memcpy /// /// # Safety /// - /// Beyond requiring that the program must be allowed to access both regions - /// of memory, it is Undefined Behavior for source and destination to - /// overlap. Care must also be taken with the ownership of `src` and - /// `dst`. This method semantically moves the values of `src` into `dst`. - /// However it does not drop the contents of `dst`, or prevent the contents - /// of `src` from being dropped or used. + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * The region of memory which begins at `src` and has a length of + /// `count * size_of::()` bytes must be *both* valid and initialized. + /// + /// * The region of memory which begins at `dst` and has a length of + /// `count * size_of::()` bytes must be valid (but may or may not be + /// initialized). + /// + /// * The two regions of memory must *not* overlap. + /// + /// * `src` must be properly aligned. + /// + /// * `dst` must be properly aligned. + /// + /// Additionally, if `T` is not [`Copy`], only the region at `src` *or* the + /// region at `dst` can be used or dropped after calling + /// `copy_nonoverlapping`. `copy_nonoverlapping` creates bitwise copies of + /// `T`, regardless of whether `T: Copy`, which can result in undefined + /// behavior if both copies are used. + /// + /// [`Copy`]: ../marker/trait.Copy.html /// /// # Examples /// - /// A safe swap function: + /// Manually implement [`Vec::append`]: /// /// ``` - /// use std::mem; /// use std::ptr; /// - /// # #[allow(dead_code)] - /// fn swap(x: &mut T, y: &mut T) { + /// /// Moves all the elements of `src` into `dst`, leaving `src` empty. + /// fn append(dst: &mut Vec, src: &mut Vec) { + /// let src_len = src.len(); + /// let dst_len = dst.len(); + /// + /// // Ensure that `dst` has enough capacity to hold all of `src`. + /// dst.reserve(src_len); + /// /// unsafe { - /// // Give ourselves some scratch space to work with - /// let mut t: T = mem::uninitialized(); + /// // The call to offset is always safe because `Vec` will never + /// // allocate more than `isize::MAX` bytes. + /// let dst = dst.as_mut_ptr().offset(dst_len as isize); + /// let src = src.as_ptr(); + /// + /// // The two regions cannot overlap becuase mutable references do + /// // not alias, and two different vectors cannot own the same + /// // memory. + /// ptr::copy_nonoverlapping(src, dst, src_len); + /// } /// - /// // Perform the swap, `&mut` pointers never alias - /// ptr::copy_nonoverlapping(x, &mut t, 1); - /// ptr::copy_nonoverlapping(y, x, 1); - /// ptr::copy_nonoverlapping(&t, y, 1); + /// unsafe { + /// // Truncate `src` without dropping its contents. + /// src.set_len(0); /// - /// // y and t now point to the same thing, but we need to completely forget `t` - /// // because it's no longer relevant. - /// mem::forget(t); + /// // Notify `dst` that it now holds the contents of `src`. + /// dst.set_len(dst_len + src_len); /// } /// } + /// + /// let mut a = vec!['r']; + /// let mut b = vec!['u', 's', 't']; + /// + /// append(&mut a, &mut b); + /// + /// assert_eq!(a, &['r', 'u', 's', 't']); + /// assert!(b.is_empty()); /// ``` + /// + /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append #[stable(feature = "rust1", since = "1.0.0")] pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); - /// Copies `count * size_of` bytes from `src` to `dst`. The source + /// Copies `count * size_of::()` bytes from `src` to `dst`. The source /// and destination may overlap. /// - /// `copy` is semantically equivalent to C's `memmove`. + /// If the source and destination will *never* overlap, + /// [`copy_nonoverlapping`] can be used instead. + /// + /// `copy` is semantically equivalent to C's [`memmove`]. + /// + /// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html + /// [`memmove`]: https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html#index-memmove /// /// # Safety /// - /// Care must be taken with the ownership of `src` and `dst`. - /// This method semantically moves the values of `src` into `dst`. - /// However it does not drop the contents of `dst`, or prevent the contents of `src` - /// from being dropped or used. + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * The region of memory which begins at `src` and has a length of + /// `count * size_of::()` bytes must be *both* valid and initialized. + /// + /// * The region of memory which begins at `dst` and has a length of + /// `count * size_of::()` bytes must be valid (but may or may not be + /// initialized). + /// + /// * `src` must be properly aligned. + /// + /// * `dst` must be properly aligned. + /// + /// Additionally, if `T` is not [`Copy`], only the region at `src` *or* the + /// region at `dst` can be used or dropped after calling `copy`. `copy` + /// creates bitwise copies of `T`, regardless of whether `T: Copy`, which + /// can result in undefined behavior if both copies are used. + /// + /// [`Copy`]: ../marker/trait.Copy.html /// /// # Examples /// @@ -1031,15 +1094,34 @@ /// dst /// } /// ``` - /// #[stable(feature = "rust1", since = "1.0.0")] pub fn copy(src: *const T, dst: *mut T, count: usize); - /// Invokes memset on the specified pointer, setting `count * size_of::()` - /// bytes of memory starting at `dst` to `val`. + /// Sets `count * size_of::()` bytes of memory starting at `dst` to + /// `val`. + /// + /// `write_bytes` is semantically equivalent to C's [`memset`]. + /// + /// [`memset`]: https://www.gnu.org/software/libc/manual/html_node/Copying-Strings-and-Arrays.html#index-memset + /// + /// # Safety + /// + /// Behavior is undefined if any of the following conditions are violated: + /// + /// * The region of memory which begins at `dst` and has a length of + /// `count` bytes must be valid. + /// + /// * `dst` must be properly aligned. + /// + /// Additionally, the caller must ensure that writing `count` bytes to the + /// given region of memory results in a valid value of `T`. Creating an + /// invalid value of `T` can result in undefined behavior. An example is + /// provided below. /// /// # Examples /// + /// Basic usage: + /// /// ``` /// use std::ptr; /// @@ -1050,6 +1132,23 @@ /// } /// assert_eq!(vec, [b'a', b'a', 0, 0]); /// ``` + /// + /// Creating an invalid value: + /// + /// ```no_run + /// use std::{mem, ptr}; + /// + /// let mut v = Box::new(0i32); + /// + /// unsafe { + /// // Leaks the previously held value by overwriting the `Box` with + /// // a null pointer. + /// ptr::write_bytes(&mut v, 0, mem::size_of::>()); + /// } + /// + /// // At this point, using or dropping `v` results in undefined behavior. + /// // v = Box::new(0i32); // ERROR + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn write_bytes(dst: *mut T, val: u8, count: usize); diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index ddbb5998942..173dfc36f04 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -587,7 +587,7 @@ fn next_back(&mut self) -> Option { (**self).next_back() } /// that information can be useful. For example, if you want to iterate /// backwards, a good start is to know where the end is. /// -/// When implementing an `ExactSizeIterator`, You must also implement +/// When implementing an `ExactSizeIterator`, you must also implement /// [`Iterator`]. When doing so, the implementation of [`size_hint`] *must* /// return the exact size of the iterator. /// diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 5d0b675e8e4..83dfac7a3a2 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -10,7 +10,7 @@ // FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory -//! Raw, unsafe pointers, `*const T`, and `*mut T`. +//! Manually manage memory through raw pointers. //! //! *[See also the pointer primitive types](../../std/primitive.pointer.html).* @@ -38,21 +38,62 @@ /// Executes the destructor (if any) of the pointed-to value. /// -/// This has two use cases: +/// This is semantically equivalent to calling [`ptr::read`] and discarding +/// the result, but has the following advantages: /// /// * It is *required* to use `drop_in_place` to drop unsized types like /// trait objects, because they can't be read out onto the stack and /// dropped normally. /// -/// * It is friendlier to the optimizer to do this over `ptr::read` when +/// * It is friendlier to the optimizer to do this over [`ptr::read`] when /// dropping manually allocated memory (e.g. when writing Box/Rc/Vec), /// as the compiler doesn't need to prove that it's sound to elide the /// copy. /// +/// [`ptr::read`]: ../ptr/fn.read.html +/// /// # Safety /// -/// This has all the same safety problems as `ptr::read` with respect to -/// invalid pointers, types, and double drops. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `to_drop` must point to valid memory. +/// +/// * `to_drop` must be properly aligned. +/// +/// Additionally, if `T` is not [`Copy`], using the pointed-to value after +/// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop = +/// foo` counts as a use because it will cause the the value to be dropped +/// again. [`write`] can be used to overwrite data without causing it to be +/// dropped. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`write`]: ../ptr/fn.write.html +/// +/// # Examples +/// +/// Manually remove the last item from a vector: +/// +/// ``` +/// use std::ptr; +/// use std::rc::Rc; +/// +/// let last = Rc::new(1); +/// let weak = Rc::downgrade(&last); +/// +/// let mut v = vec![Rc::new(0), last]; +/// +/// unsafe { +/// // Without a call `drop_in_place`, the last item would never be dropped, +/// // and the memory it manages would be leaked. +/// ptr::drop_in_place(&mut v[1]); +/// v.set_len(1); +/// } +/// +/// assert_eq!(v, &[0.into()]); +/// +/// // Ensure that the last item was dropped. +/// assert!(weak.upgrade().is_none()); +/// ``` #[stable(feature = "drop_in_place", since = "1.8.0")] #[lang = "drop_in_place"] #[allow(unconditional_recursion)] @@ -93,17 +134,25 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } /// Swaps the values at two mutable locations of the same type, without /// deinitializing either. /// -/// The values pointed at by `x` and `y` may overlap, unlike `mem::swap` which -/// is otherwise equivalent. If the values do overlap, then the overlapping -/// region of memory from `x` will be used. This is demonstrated in the -/// examples section below. +/// But for the following two exceptions, this function is semantically +/// equivalent to [`mem::swap`]: +/// +/// * It operates on raw pointers instead of references. When references are +/// available, [`mem::swap`] should be preferred. +/// +/// * The two pointed-to values may overlap. If the values do overlap, then the +/// overlapping region of memory from `x` will be used. This is demonstrated +/// in the examples below. +/// +/// [`mem::swap`]: ../mem/fn.swap.html /// /// # Safety /// -/// This function copies the memory through the raw pointers passed to it -/// as arguments. +/// Behavior is undefined if any of the following conditions are violated: /// -/// Ensure that these pointers are valid before calling `swap`. +/// * `x` and `y` must point to valid, initialized memory. +/// +/// * `x` and `y` must be properly aligned. /// /// # Examples /// @@ -239,13 +288,39 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { } } -/// Replaces the value at `dest` with `src`, returning the old -/// value, without dropping either. +/// Replaces the value at `dest` with `src`, returning the old value, without +/// dropping either. +/// +/// This function is semantically equivalent to [`mem::replace`] except that it +/// operates on raw pointers instead of references. When references are +/// available, [`mem::replace`] should be preferred. +/// +/// [`mem::replace`]: ../mem/fn.replace.html /// /// # Safety /// -/// This is only unsafe because it accepts a raw pointer. -/// Otherwise, this operation is identical to `mem::replace`. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dest` must point to valid, initialized memory. +/// +/// * `dest` must be properly aligned. +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let mut rust = vec!['b', 'u', 's', 't']; +/// +/// // `mem::replace` would have the same effect without requiring the unsafe +/// // block. +/// let b = unsafe { +/// ptr::replace(&mut rust[0], 'r') +/// }; +/// +/// assert_eq!(b, 'b'); +/// assert_eq!(rust, &['r', 'u', 's', 't']); +/// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn replace(dest: *mut T, mut src: T) -> T { @@ -258,14 +333,23 @@ pub unsafe fn replace(dest: *mut T, mut src: T) -> T { /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// Behavior is undefined if any of the following conditions are violated: /// -/// The pointer must be aligned; use `read_unaligned` if that is not the case. +/// * `src` must point to valid, initialized memory. +/// +/// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the +/// case. +/// +/// Additionally, if `T` is not [`Copy`], only the returned value *or* the +/// pointed-to value can be used or dropped after calling `read`. `read` creates +/// a bitwise copy of `T`, regardless of whether `T: Copy`, which can result +/// in undefined behavior if both copies are used. Note that `*src = foo` counts +/// as a use because it will attempt to drop the value previously at `*src`. +/// [`write`] can be used to overwrite data without causing it to be dropped. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`read_unaligned`]: ./fn.read_unaligned.html +/// [`write`]: ./fn.write.html /// /// # Examples /// @@ -279,6 +363,44 @@ pub unsafe fn replace(dest: *mut T, mut src: T) -> T { /// assert_eq!(std::ptr::read(y), 12); /// } /// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap(a: &mut T, b: &mut T) { +/// unsafe { +/// // Create a bitwise copy of the value at `a` in `tmp`. +/// let tmp = ptr::read(a); +/// +/// // Exiting at this point (either by explicitly returning or by +/// // calling a function which panics) would cause the value in `tmp` to +/// // be dropped while the same value is still referenced by `a`. This +/// // could trigger undefined behavior if `T` is not `Copy`. +/// +/// // Create a bitwise copy of the value at `b` in `a`. +/// // This is safe because mutable references cannot alias. +/// ptr::copy_nonoverlapping(b, a, 1); +/// +/// // As above, exiting here could trigger undefined behavior because +/// // the same value is referenced by `a` and `b`. +/// +/// // Move `tmp` into `b`. +/// ptr::write(b, tmp); +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +/// +/// [`mem::swap`]: ../mem/fn.swap.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn read(src: *const T) -> T { @@ -290,28 +412,62 @@ pub unsafe fn read(src: *const T) -> T { /// Reads the value from `src` without moving it. This leaves the /// memory in `src` unchanged. /// -/// Unlike `read`, the pointer may be unaligned. +/// Unlike [`read`], `read_unaligned` works with unaligned pointers. +/// +/// [`read`]: ./fn.read.html /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must point to valid, initialized memory. +/// +/// Additionally, if `T` is not [`Copy`], only the returned value *or* the +/// pointed-to value can be used or dropped after calling `read_unaligned`. +/// `read_unaligned` creates a bitwise copy of `T`, regardless of whether `T: +/// Copy`, and this can result in undefined behavior if both copies are used. +/// Note that `*src = foo` counts as a use because it will attempt to drop the +/// value previously at `*src`. [`write_unaligned`] can be used to overwrite +/// data without causing it to be dropped. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`write_unaligned`]: ./fn.write_unaligned.html /// /// # Examples /// -/// Basic usage: +/// Access members of a packed struct by reference: /// /// ``` -/// let x = 12; -/// let y = &x as *const i32; +/// use std::ptr; /// -/// unsafe { -/// assert_eq!(std::ptr::read_unaligned(y), 12); +/// #[repr(packed, C)] +/// #[derive(Default)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, /// } +/// +/// let x = Packed { +/// _padding: 0x00, +/// unaligned: 0x01020304, +/// }; +/// +/// let v = unsafe { +/// // Take a reference to a 32-bit integer which is not aligned. +/// let unaligned = &x.unaligned; +/// +/// // Dereferencing normally will emit an unaligned load instruction, +/// // causing undefined behavior. +/// // let v = *unaligned; // ERROR +/// +/// // Instead, use `read_unaligned` to read improperly aligned values. +/// let v = ptr::read_unaligned(unaligned); +/// +/// v +/// }; +/// +/// // Accessing unaligned values directly is safe. +/// assert!(x.unaligned == v); /// ``` #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] @@ -326,11 +482,7 @@ pub unsafe fn read_unaligned(src: *const T) -> T { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// -/// # Safety -/// -/// This operation is marked unsafe because it accepts a raw pointer. -/// -/// It does not drop the contents of `dst`. This is safe, but it could leak +/// `write` does not drop the contents of `dst`. This is safe, but it could leak /// allocations or resources, so care must be taken not to overwrite an object /// that should be dropped. /// @@ -338,9 +490,20 @@ pub unsafe fn read_unaligned(src: *const T) -> T { /// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// memory that has previously been [`read`] from. +/// +/// [`read`]: ./fn.read.html +/// +/// # Safety /// -/// The pointer must be aligned; use `write_unaligned` if that is not the case. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must point to valid memory. +/// +/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the +/// case. +/// +/// [`write_unaligned`]: ./fn.write_unaligned.html /// /// # Examples /// @@ -356,6 +519,30 @@ pub unsafe fn read_unaligned(src: *const T) -> T { /// assert_eq!(std::ptr::read(y), 12); /// } /// ``` +/// +/// Manually implement [`mem::swap`]: +/// +/// ``` +/// use std::ptr; +/// +/// fn swap(a: &mut T, b: &mut T) { +/// unsafe { +/// let tmp = ptr::read(a); +/// ptr::copy_nonoverlapping(b, a, 1); +/// ptr::write(b, tmp); +/// } +/// } +/// +/// let mut foo = "foo".to_owned(); +/// let mut bar = "bar".to_owned(); +/// +/// swap(&mut foo, &mut bar); +/// +/// assert_eq!(foo, "bar"); +/// assert_eq!(bar, "foo"); +/// ``` +/// +/// [`mem::swap`]: ../mem/fn.swap.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn write(dst: *mut T, src: T) { @@ -365,36 +552,58 @@ pub unsafe fn write(dst: *mut T, src: T) { /// Overwrites a memory location with the given value without reading or /// dropping the old value. /// -/// Unlike `write`, the pointer may be unaligned. -/// -/// # Safety +/// Unlike [`write`], the pointer may be unaligned. /// -/// This operation is marked unsafe because it accepts a raw pointer. -/// -/// It does not drop the contents of `dst`. This is safe, but it could leak -/// allocations or resources, so care must be taken not to overwrite an object -/// that should be dropped. +/// `write_unaligned` does not drop the contents of `dst`. This is safe, but it +/// could leak allocations or resources, so care must be taken not to overwrite +/// an object that should be dropped. /// /// Additionally, it does not drop `src`. Semantically, `src` is moved into the /// location pointed to by `dst`. /// /// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// memory that has previously been read with [`read_unaligned`]. +/// +/// [`write`]: ./fn.write.html +/// [`read_unaligned`]: ./fn.read_unaligned.html +/// +/// # Safety +/// +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `dst` must point to valid memory. /// /// # Examples /// -/// Basic usage: +/// Access fields in a packed struct: /// /// ``` -/// let mut x = 0; -/// let y = &mut x as *mut i32; -/// let z = 12; +/// use std::{mem, ptr}; +/// +/// #[repr(packed, C)] +/// #[derive(Default)] +/// struct Packed { +/// _padding: u8, +/// unaligned: u32, +/// } +/// +/// let v = 0x01020304; +/// let mut x: Packed = unsafe { mem::zeroed() }; /// /// unsafe { -/// std::ptr::write_unaligned(y, z); -/// assert_eq!(std::ptr::read_unaligned(y), 12); +/// // Take a reference to a 32-bit integer which is not aligned. +/// let unaligned = &mut x.unaligned; +/// +/// // Dereferencing normally will emit an unaligned store instruction, +/// // causing undefined behavior. +/// // *unaligned = v; // ERROR +/// +/// // Instead, use `write_unaligned` to write improperly aligned values. +/// ptr::write_unaligned(unaligned, v); /// } -/// ``` +/// +/// // Accessing unaligned values directly is safe. +/// assert!(x.unaligned == v); #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn write_unaligned(dst: *mut T, src: T) { @@ -411,6 +620,11 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// to not be elided or reordered by the compiler across other volatile /// operations. /// +/// Memory read with `read_volatile` should almost always be written to using +/// [`write_volatile`]. +/// +/// [`write_volatile`]: ./fn.write_volatile.html +/// /// # Notes /// /// Rust does not currently have a rigorously and formally defined memory model, @@ -427,12 +641,19 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// /// # Safety /// -/// Beyond accepting a raw pointer, this is unsafe because it semantically -/// moves the value out of `src` without preventing further usage of `src`. -/// If `T` is not `Copy`, then care must be taken to ensure that the value at -/// `src` is not used before the data is overwritten again (e.g. with `write`, -/// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use -/// because it will attempt to drop the value previously at `*src`. +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * `src` must point to valid, initialized memory. +/// +/// * `src` must be properly aligned. +/// +/// Like [`read`], `read_volatile` creates a bitwise copy of the pointed-to +/// object, regardless of whether `T` is [`Copy`]. Using both values can cause +/// undefined behavior. However, storing non-[`Copy`] data in I/O memory is +/// almost certainly incorrect. +/// +/// [`Copy`]: ../marker/trait.Copy.html +/// [`read`]: ./fn.read.html /// /// # Examples /// @@ -459,6 +680,18 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// +/// Memory written with `write_volatile` should almost always be read from using +/// [`read_volatile`]. +/// +/// `write_volatile` does not drop the contents of `dst`. This is safe, but it +/// could leak allocations or resources, so care must be taken not to overwrite +/// an object that should be dropped. +/// +/// Additionally, it does not drop `src`. Semantically, `src` is moved into the +/// location pointed to by `dst`. +/// +/// [`read_volatile`]: ./fn.read_volatile.html +/// /// # Notes /// /// Rust does not currently have a rigorously and formally defined memory model, @@ -475,14 +708,11 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// /// # Safety /// -/// This operation is marked unsafe because it accepts a raw pointer. +/// Behavior is undefined if any of the following conditions are violated: /// -/// It does not drop the contents of `dst`. This is safe, but it could leak -/// allocations or resources, so care must be taken not to overwrite an object -/// that should be dropped. +/// * `dst` must point to valid memory. /// -/// This is appropriate for initializing uninitialized memory, or overwriting -/// memory that has previously been `read` from. +/// * `dst` must be properly aligned. /// /// # Examples /// diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index ea3c0a8ddb4..7352c14490d 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -14,6 +14,7 @@ use infer::type_variable::TypeVariableOrigin; use ty::{self, Ty, TyInfer, TyVar}; use syntax_pos::Span; +use errors::DiagnosticBuilder; struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, @@ -86,7 +87,11 @@ fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { } } - pub fn need_type_info(&self, body_id: Option, span: Span, ty: Ty<'tcx>) { + pub fn need_type_info_err(&self, + body_id: Option, + span: Span, + ty: Ty<'tcx>) + -> DiagnosticBuilder<'gcx> { let ty = self.resolve_type_vars_if_possible(&ty); let name = self.extract_type_name(&ty); @@ -142,6 +147,6 @@ pub fn need_type_info(&self, body_id: Option, span: Span, ty: Ty<'t err.span_label(target_span, label_message); } - err.emit(); + err } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 934069974be..3e7f3af0358 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1238,7 +1238,7 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, self.tcx.lang_items().sized_trait() .map_or(false, |sized_id| sized_id == trait_ref.def_id()) { - self.need_type_info(body_id, span, self_ty); + self.need_type_info_err(body_id, span, self_ty).emit(); } else { let mut err = struct_span_err!(self.tcx.sess, span, E0283, @@ -1255,7 +1255,7 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, // Same hacky approach as above to avoid deluging user // with error messages. if !ty.references_error() && !self.tcx.sess.has_errors() { - self.need_type_info(body_id, span, ty); + self.need_type_info_err(body_id, span, ty).emit(); } } @@ -1266,9 +1266,9 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); // both must be type variables, or the other would've been instantiated assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info(body_id, - obligation.cause.span, - a); + self.need_type_info_err(body_id, + obligation.cause.span, + a).emit(); } } diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 976614c9542..7b94170ef6d 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -16,7 +16,7 @@ rustc_target = { path = "../librustc_target" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rls-data = "0.15" +rls-data = "0.16" rls-span = "0.4" # FIXME(#40527) should move rustc serialize out of tree rustc-serialize = "0.3" diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index abaa02a856e..2ef294fe430 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -268,80 +268,6 @@ fn lookup_def_id(&self, ref_id: NodeId) -> Option { } } - fn process_def_kind( - &mut self, - ref_id: NodeId, - span: Span, - sub_span: Option, - def_id: DefId, - ) { - if self.span.filter_generated(sub_span, span) { - return; - } - - let def = self.save_ctxt.get_path_def(ref_id); - match def { - HirDef::Mod(_) => { - let span = self.span_from_span(sub_span.expect("No span found for mod ref")); - self.dumper.dump_ref(Ref { - kind: RefKind::Mod, - span, - ref_id: ::id_from_def_id(def_id), - }); - } - HirDef::Struct(..) | - HirDef::Variant(..) | - HirDef::Union(..) | - HirDef::Enum(..) | - HirDef::TyAlias(..) | - HirDef::TyForeign(..) | - HirDef::TraitAlias(..) | - HirDef::Trait(_) => { - let span = self.span_from_span(sub_span.expect("No span found for type ref")); - self.dumper.dump_ref(Ref { - kind: RefKind::Type, - span, - ref_id: ::id_from_def_id(def_id), - }); - } - HirDef::Static(..) | - HirDef::Const(..) | - HirDef::StructCtor(..) | - HirDef::VariantCtor(..) => { - let span = self.span_from_span(sub_span.expect("No span found for var ref")); - self.dumper.dump_ref(Ref { - kind: RefKind::Variable, - span, - ref_id: ::id_from_def_id(def_id), - }); - } - HirDef::Fn(..) => { - let span = self.span_from_span(sub_span.expect("No span found for fn ref")); - self.dumper.dump_ref(Ref { - kind: RefKind::Function, - span, - ref_id: ::id_from_def_id(def_id), - }); - } - // With macros 2.0, we can legitimately get a ref to a macro, but - // we don't handle it properly for now (FIXME). - HirDef::Macro(..) => {} - HirDef::Local(..) | - HirDef::Upvar(..) | - HirDef::SelfTy(..) | - HirDef::Label(_) | - HirDef::TyParam(..) | - HirDef::Method(..) | - HirDef::AssociatedTy(..) | - HirDef::AssociatedConst(..) | - HirDef::PrimTy(_) | - HirDef::GlobalAsm(_) | - HirDef::Err => { - span_bug!(span, "process_def_kind for unexpected item: {:?}", def); - } - } - } - fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) { for arg in formals { self.visit_pat(&arg.pat); @@ -1348,29 +1274,17 @@ fn process_use_tree(&mut self, }; let sub_span = self.span.span_for_last_ident(path.span); - let mod_id = match self.lookup_def_id(id) { - Some(def_id) => { - self.process_def_kind(id, path.span, sub_span, def_id); - Some(def_id) - } - None => None, - }; - - // 'use' always introduces an alias, if there is not an explicit - // one, there is an implicit one. - let sub_span = match self.span.sub_span_after_keyword(use_tree.span, - keywords::As) { - Some(sub_span) => Some(sub_span), - None => sub_span, - }; + let alias_span = self.span.sub_span_after_keyword(use_tree.span, keywords::As); + let ref_id = self.lookup_def_id(id); if !self.span.filter_generated(sub_span, path.span) { - let span = - self.span_from_span(sub_span.expect("No span found for use")); + let span = self.span_from_span(sub_span.expect("No span found for use")); + let alias_span = alias_span.map(|sp| self.span_from_span(sp)); self.dumper.import(&access, Import { kind: ImportKind::Use, - ref_id: mod_id.map(|id| ::id_from_def_id(id)), + ref_id: ref_id.map(|id| ::id_from_def_id(id)), span, + alias_span, name: ident.to_string(), value: String::new(), parent, @@ -1407,6 +1321,7 @@ fn process_use_tree(&mut self, kind: ImportKind::GlobUse, ref_id: None, span, + alias_span: None, name: "*".to_owned(), value: names.join(", "), parent, @@ -1500,6 +1415,7 @@ fn visit_item(&mut self, item: &'l ast::Item) { kind: ImportKind::ExternCrate, ref_id: None, span, + alias_span: None, name: item.ident.to_string(), value: String::new(), parent, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2e9f31dd15e..955dc6f5aac 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3061,7 +3061,7 @@ fn check_field(&self, base: &'gcx hir::Expr, field: &Spanned) -> Ty<'tcx> { let expr_t = self.check_expr_with_needs(base, needs); - let expr_t = self.structurally_resolved_type(expr.span, + let expr_t = self.structurally_resolved_type(base.span, expr_t); let mut private_candidate = None; let mut autoderef = self.autoderef(expr.span, expr_t); @@ -4080,7 +4080,7 @@ fn check_expr_kind(&self, } else if idx_t.references_error() { idx_t } else { - let base_t = self.structurally_resolved_type(expr.span, base_t); + let base_t = self.structurally_resolved_type(base.span, base_t); match self.lookup_indexing(expr, base, base_t, idx_t, needs) { Some((index_ty, element_ty)) => { // two-phase not needed because index_ty is never mutable @@ -5073,7 +5073,9 @@ pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.need_type_info((**self).body_id, sp, ty); + self.need_type_info_err((**self).body_id, sp, ty) + .note("type must be known at this point") + .emit(); } self.demand_suptype(sp, self.tcx.types.err, ty); self.tcx.types.err diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 57c1d33cb5d..b0ee1154e86 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -593,7 +593,7 @@ fn new( fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t); + .need_type_info_err(Some(self.body.id()), self.span.to_span(&self.tcx), t).emit(); } } } diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 3a376bb9aff..96a2194eeee 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,3 +10,4 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.1.2", default-features = false } tempdir = "0.3" +minifier = "0.0.11" diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 17f2c47562f..a1d77f4145b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -17,7 +17,7 @@ pub use self::TyParamBound::*; pub use self::SelfTy::*; pub use self::FunctionRetTy::*; -pub use self::Visibility::*; +pub use self::Visibility::{Public, Inherited}; use syntax; use rustc_target::spec::abi::Abi; @@ -2998,11 +2998,22 @@ fn clean(&self, cx: &DocContext) -> Item { pub enum Visibility { Public, Inherited, + Crate, + Restricted(DefId, Path), } impl Clean> for hir::Visibility { - fn clean(&self, _: &DocContext) -> Option { - Some(if *self == hir::Visibility::Public { Public } else { Inherited }) + fn clean(&self, cx: &DocContext) -> Option { + Some(match *self { + hir::Visibility::Public => Visibility::Public, + hir::Visibility::Inherited => Visibility::Inherited, + hir::Visibility::Crate => Visibility::Crate, + hir::Visibility::Restricted { ref path, .. } => { + let path = path.clean(cx); + let did = register_def(cx, path.def); + Visibility::Restricted(did, path) + } + }) } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0323e2b1f52..40dcd6e891f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -927,8 +927,19 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { impl<'a> fmt::Display for VisSpace<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self.get() { - Some(clean::Public) => write!(f, "pub "), - Some(clean::Inherited) | None => Ok(()) + Some(clean::Public) => f.write_str("pub "), + Some(clean::Inherited) | None => Ok(()), + Some(clean::Visibility::Crate) => write!(f, "pub(crate) "), + Some(clean::Visibility::Restricted(did, ref path)) => { + f.write_str("pub(")?; + if path.segments.len() != 1 + || (path.segments[0].name != "self" && path.segments[0].name != "super") + { + f.write_str("in ")?; + } + resolved_path(f, did, path, true, false)?; + f.write_str(") ") + } } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 21851e7b9dc..109765b6711 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -76,6 +76,8 @@ use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine}; use html::{highlight, layout}; +use minifier; + /// A pair of name and its optional document. pub type NameDoc = (String, Option); @@ -513,7 +515,8 @@ pub fn run(mut krate: clean::Crate, css_file_extension: Option, renderinfo: RenderInfo, sort_modules_alphabetically: bool, - themes: Vec) -> Result<(), Error> { + themes: Vec, + enable_minification: bool) -> Result<(), Error> { let src_root = match krate.src { FileName::Real(ref p) => match p.parent() { Some(p) => p.to_path_buf(), @@ -665,7 +668,7 @@ pub fn run(mut krate: clean::Crate, CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone()); CURRENT_LOCATION_KEY.with(|s| s.borrow_mut().clear()); - write_shared(&cx, &krate, &*cache, index)?; + write_shared(&cx, &krate, &*cache, index, enable_minification)?; // And finally render the whole crate's documentation cx.krate(krate) @@ -744,7 +747,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { fn write_shared(cx: &Context, krate: &clean::Crate, cache: &Cache, - search_index: String) -> Result<(), Error> { + search_index: String, + enable_minification: bool) -> Result<(), Error> { // Write out the shared files. Note that these are shared among all rustdoc // docs placed in the output directory, so this needs to be a synchronized // operation with respect to all other rustdocs running around. @@ -836,16 +840,20 @@ fn write_shared(cx: &Context, .join(",")).as_bytes(), )?; - write(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)), - include_bytes!("static/main.js"))?; - write(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)), - include_bytes!("static/settings.js"))?; + write_minify(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)), + include_str!("static/main.js"), + enable_minification)?; + write_minify(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)), + include_str!("static/settings.js"), + enable_minification)?; { let mut data = format!("var resourcesSuffix = \"{}\";\n", - cx.shared.resource_suffix).into_bytes(); - data.extend_from_slice(include_bytes!("static/storage.js")); - write(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)), &data)?; + cx.shared.resource_suffix); + data.push_str(include_str!("static/storage.js")); + write_minify(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)), + &data, + enable_minification)?; } if let Some(ref css) = cx.shared.css_file_extension { @@ -1042,6 +1050,14 @@ fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> { Ok(try_err!(fs::write(&dst, contents), &dst)) } +fn write_minify(dst: PathBuf, contents: &str, enable_minification: bool) -> Result<(), Error> { + if enable_minification { + write(dst, minifier::js::minify(contents).as_bytes()) + } else { + write(dst, contents.as_bytes()) + } +} + /// Takes a path to a source file and cleans the path to it. This canonicalizes /// things like ".." to components which preserve the "top down" hierarchy of a /// static HTML tree. Each component in the cleaned path will be passed as an diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 9224bd1c508..e0235bfc694 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -202,7 +202,7 @@ onEach(e.getElementsByTagName('span'), function(i_e) { removeClass(i_e, 'line-highlighted'); }); - }) + }); for (i = from; i <= to; ++i) { addClass(document.getElementById(i), 'line-highlighted'); } @@ -1972,7 +1972,7 @@ hasClass(next.nextElementSibling, 'docblock')))) { insertAfter(toggle.cloneNode(true), e.childNodes[e.childNodes.length - 1]); } - } + }; onEach(document.getElementsByClassName('method'), func); onEach(document.getElementsByClassName('impl'), func); onEach(document.getElementsByClassName('impl-items'), function(e) { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f2da09e1603..d4244bfdba0 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -48,6 +48,7 @@ extern crate rustc_errors as errors; extern crate pulldown_cmark; extern crate tempdir; +extern crate minifier; extern crate serialize as rustc_serialize; // used by deriving @@ -299,6 +300,11 @@ pub fn opts() -> Vec { "How errors and other messages are produced", "human|json|short") }), + unstable("disable-minification", |o| { + o.optflag("", + "disable-minification", + "Disable minification applied on JS files") + }), ] } @@ -480,6 +486,7 @@ pub fn main_args(args: &[String]) -> isize { let linker = matches.opt_str("linker").map(PathBuf::from); let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance"); let resource_suffix = matches.opt_str("resource-suffix"); + let enable_minification = !matches.opt_present("disable-minification"); let edition = matches.opt_str("edition").unwrap_or("2015".to_string()); let edition = match edition.parse() { @@ -523,7 +530,8 @@ pub fn main_args(args: &[String]) -> isize { css_file_extension, renderinfo, sort_modules_alphabetically, - themes) + themes, + enable_minification) .expect("failed to generate documentation"); 0 } diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index f849db4ec60..7314d32b020 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -49,6 +49,8 @@ impl f32 { /// Returns the largest integer less than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.99_f32; /// let g = 3.0_f32; @@ -80,6 +82,8 @@ pub fn floor(self) -> f32 { /// Returns the smallest integer greater than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.01_f32; /// let g = 4.0_f32; @@ -100,6 +104,8 @@ pub fn ceil(self) -> f32 { /// Returns the nearest integer to a number. Round half-way cases away from /// `0.0`. /// + /// # Examples + /// /// ``` /// let f = 3.3_f32; /// let g = -3.3_f32; @@ -115,6 +121,8 @@ pub fn round(self) -> f32 { /// Returns the integer part of a number. /// + /// # Examples + /// /// ``` /// let f = 3.3_f32; /// let g = -3.7_f32; @@ -130,6 +138,8 @@ pub fn trunc(self) -> f32 { /// Returns the fractional part of a number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -148,6 +158,8 @@ pub fn fract(self) -> f32 { self - self.trunc() } /// Computes the absolute value of `self`. Returns `NAN` if the /// number is `NAN`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -174,6 +186,8 @@ pub fn abs(self) -> f32 { /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` /// - `NAN` if the number is `NAN` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -200,6 +214,8 @@ pub fn signum(self) -> f32 { /// Using `mul_add` can be more performant than an unfused multiply-add if /// the target architecture has a dedicated `fma` CPU instruction. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -225,6 +241,8 @@ pub fn mul_add(self, a: f32, b: f32) -> f32 { /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f32 = 7.0; @@ -248,6 +266,8 @@ pub fn div_euc(self, rhs: f32) -> f32 { /// /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f32 = 7.0; @@ -273,6 +293,8 @@ pub fn mod_euc(self, rhs: f32) -> f32 { /// /// Using this function is generally faster than using `powf` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -289,6 +311,8 @@ pub fn powi(self, n: i32) -> f32 { /// Raises a number to a floating point power. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -311,6 +335,8 @@ pub fn powf(self, n: f32) -> f32 { /// /// Returns NaN if `self` is a negative number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -334,6 +360,8 @@ pub fn sqrt(self) -> f32 { /// Returns `e^(self)`, (the exponential function). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -358,6 +386,8 @@ pub fn exp(self) -> f32 { /// Returns `2^(self)`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -376,6 +406,8 @@ pub fn exp2(self) -> f32 { /// Returns the natural logarithm of the number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -404,6 +436,8 @@ pub fn ln(self) -> f32 { /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -420,6 +454,8 @@ pub fn log(self, base: f32) -> f32 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -441,6 +477,8 @@ pub fn log2(self) -> f32 { /// Returns the base 10 logarithm of the number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -466,6 +504,8 @@ pub fn log10(self) -> f32 { /// * If `self <= other`: `0:0` /// * Else: `self - other` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -493,6 +533,8 @@ pub fn abs_sub(self, other: f32) -> f32 { /// Takes the cubic root of a number. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -512,6 +554,8 @@ pub fn cbrt(self) -> f32 { /// Calculates the length of the hypotenuse of a right-angle triangle given /// legs of length `x` and `y`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -531,6 +575,8 @@ pub fn hypot(self, other: f32) -> f32 { /// Computes the sine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -552,6 +598,8 @@ pub fn sin(self) -> f32 { /// Computes the cosine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -573,6 +621,8 @@ pub fn cos(self) -> f32 { /// Computes the tangent of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -591,6 +641,8 @@ pub fn tan(self) -> f32 { /// the range [-pi/2, pi/2] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -611,6 +663,8 @@ pub fn asin(self) -> f32 { /// the range [0, pi] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -630,6 +684,8 @@ pub fn acos(self) -> f32 { /// Computes the arctangent of a number. Return value is in radians in the /// range [-pi/2, pi/2]; /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -653,6 +709,8 @@ pub fn atan(self) -> f32 { /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -682,6 +740,8 @@ pub fn atan2(self, other: f32) -> f32 { /// Simultaneously computes the sine and cosine of the number, `x`. Returns /// `(sin(x), cos(x))`. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -703,6 +763,8 @@ pub fn sin_cos(self) -> (f32, f32) { /// Returns `e^(self) - 1` in a way that is accurate even if the /// number is close to zero. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -722,6 +784,8 @@ pub fn exp_m1(self) -> f32 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -740,6 +804,8 @@ pub fn ln_1p(self) -> f32 { /// Hyperbolic sine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -761,6 +827,8 @@ pub fn sinh(self) -> f32 { /// Hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -782,6 +850,8 @@ pub fn cosh(self) -> f32 { /// Hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -803,6 +873,8 @@ pub fn tanh(self) -> f32 { /// Inverse hyperbolic sine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -825,6 +897,8 @@ pub fn asinh(self) -> f32 { /// Inverse hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// use std::f32; /// @@ -846,6 +920,8 @@ pub fn acosh(self) -> f32 { /// Inverse hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f32; /// diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 40c3f4d0ef7..75edba8979f 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -49,6 +49,8 @@ impl f64 { /// Returns the largest integer less than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.99_f64; /// let g = 3.0_f64; @@ -64,6 +66,8 @@ pub fn floor(self) -> f64 { /// Returns the smallest integer greater than or equal to a number. /// + /// # Examples + /// /// ``` /// let f = 3.01_f64; /// let g = 4.0_f64; @@ -80,6 +84,8 @@ pub fn ceil(self) -> f64 { /// Returns the nearest integer to a number. Round half-way cases away from /// `0.0`. /// + /// # Examples + /// /// ``` /// let f = 3.3_f64; /// let g = -3.3_f64; @@ -95,6 +101,8 @@ pub fn round(self) -> f64 { /// Returns the integer part of a number. /// + /// # Examples + /// /// ``` /// let f = 3.3_f64; /// let g = -3.7_f64; @@ -110,6 +118,8 @@ pub fn trunc(self) -> f64 { /// Returns the fractional part of a number. /// + /// # Examples + /// /// ``` /// let x = 3.5_f64; /// let y = -3.5_f64; @@ -126,6 +136,8 @@ pub fn fract(self) -> f64 { self - self.trunc() } /// Computes the absolute value of `self`. Returns `NAN` if the /// number is `NAN`. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -152,6 +164,8 @@ pub fn abs(self) -> f64 { /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` /// - `NAN` if the number is `NAN` /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -178,6 +192,8 @@ pub fn signum(self) -> f64 { /// Using `mul_add` can be more performant than an unfused multiply-add if /// the target architecture has a dedicated `fma` CPU instruction. /// + /// # Examples + /// /// ``` /// let m = 10.0_f64; /// let x = 4.0_f64; @@ -201,6 +217,8 @@ pub fn mul_add(self, a: f64, b: f64) -> f64 { /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f64 = 7.0; @@ -224,6 +242,8 @@ pub fn div_euc(self, rhs: f64) -> f64 { /// /// In particular, the result `n` satisfies `0 <= n < rhs.abs()`. /// + /// # Examples + /// /// ``` /// #![feature(euclidean_division)] /// let a: f64 = 7.0; @@ -248,6 +268,8 @@ pub fn mod_euc(self, rhs: f64) -> f64 { /// /// Using this function is generally faster than using `powf` /// + /// # Examples + /// /// ``` /// let x = 2.0_f64; /// let abs_difference = (x.powi(2) - x*x).abs(); @@ -262,6 +284,8 @@ pub fn powi(self, n: i32) -> f64 { /// Raises a number to a floating point power. /// + /// # Examples + /// /// ``` /// let x = 2.0_f64; /// let abs_difference = (x.powf(2.0) - x*x).abs(); @@ -278,6 +302,8 @@ pub fn powf(self, n: f64) -> f64 { /// /// Returns NaN if `self` is a negative number. /// + /// # Examples + /// /// ``` /// let positive = 4.0_f64; /// let negative = -4.0_f64; @@ -299,6 +325,8 @@ pub fn sqrt(self) -> f64 { /// Returns `e^(self)`, (the exponential function). /// + /// # Examples + /// /// ``` /// let one = 1.0_f64; /// // e^1 @@ -317,6 +345,8 @@ pub fn exp(self) -> f64 { /// Returns `2^(self)`. /// + /// # Examples + /// /// ``` /// let f = 2.0_f64; /// @@ -333,6 +363,8 @@ pub fn exp2(self) -> f64 { /// Returns the natural logarithm of the number. /// + /// # Examples + /// /// ``` /// let one = 1.0_f64; /// // e^1 @@ -355,6 +387,8 @@ pub fn ln(self) -> f64 { /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. /// + /// # Examples + /// /// ``` /// let five = 5.0_f64; /// @@ -369,6 +403,8 @@ pub fn log(self, base: f64) -> f64 { self.ln() / base.ln() } /// Returns the base 2 logarithm of the number. /// + /// # Examples + /// /// ``` /// let two = 2.0_f64; /// @@ -390,6 +426,8 @@ pub fn log2(self) -> f64 { /// Returns the base 10 logarithm of the number. /// + /// # Examples + /// /// ``` /// let ten = 10.0_f64; /// @@ -409,6 +447,8 @@ pub fn log10(self) -> f64 { /// * If `self <= other`: `0:0` /// * Else: `self - other` /// + /// # Examples + /// /// ``` /// let x = 3.0_f64; /// let y = -3.0_f64; @@ -434,6 +474,8 @@ pub fn abs_sub(self, other: f64) -> f64 { /// Takes the cubic root of a number. /// + /// # Examples + /// /// ``` /// let x = 8.0_f64; /// @@ -451,6 +493,8 @@ pub fn cbrt(self) -> f64 { /// Calculates the length of the hypotenuse of a right-angle triangle given /// legs of length `x` and `y`. /// + /// # Examples + /// /// ``` /// let x = 2.0_f64; /// let y = 3.0_f64; @@ -468,6 +512,8 @@ pub fn hypot(self, other: f64) -> f64 { /// Computes the sine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -485,6 +531,8 @@ pub fn sin(self) -> f64 { /// Computes the cosine of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -502,6 +550,8 @@ pub fn cos(self) -> f64 { /// Computes the tangent of a number (in radians). /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -520,6 +570,8 @@ pub fn tan(self) -> f64 { /// the range [-pi/2, pi/2] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -540,6 +592,8 @@ pub fn asin(self) -> f64 { /// the range [0, pi] or NaN if the number is outside the range /// [-1, 1]. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -559,6 +613,8 @@ pub fn acos(self) -> f64 { /// Computes the arctangent of a number. Return value is in radians in the /// range [-pi/2, pi/2]; /// + /// # Examples + /// /// ``` /// let f = 1.0_f64; /// @@ -580,6 +636,8 @@ pub fn atan(self) -> f64 { /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]` /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)` /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -609,6 +667,8 @@ pub fn atan2(self, other: f64) -> f64 { /// Simultaneously computes the sine and cosine of the number, `x`. Returns /// `(sin(x), cos(x))`. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -630,6 +690,8 @@ pub fn sin_cos(self) -> (f64, f64) { /// Returns `e^(self) - 1` in a way that is accurate even if the /// number is close to zero. /// + /// # Examples + /// /// ``` /// let x = 7.0_f64; /// @@ -647,6 +709,8 @@ pub fn exp_m1(self) -> f64 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -665,6 +729,8 @@ pub fn ln_1p(self) -> f64 { /// Hyperbolic sine function. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -686,6 +752,8 @@ pub fn sinh(self) -> f64 { /// Hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -707,6 +775,8 @@ pub fn cosh(self) -> f64 { /// Hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f64; /// @@ -728,6 +798,8 @@ pub fn tanh(self) -> f64 { /// Inverse hyperbolic sine function. /// + /// # Examples + /// /// ``` /// let x = 1.0_f64; /// let f = x.sinh().asinh(); @@ -748,6 +820,8 @@ pub fn asinh(self) -> f64 { /// Inverse hyperbolic cosine function. /// + /// # Examples + /// /// ``` /// let x = 1.0_f64; /// let f = x.cosh().acosh(); @@ -767,6 +841,8 @@ pub fn acosh(self) -> f64 { /// Inverse hyperbolic tangent function. /// + /// # Examples + /// /// ``` /// use std::f64; /// diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 658408519b9..be031ea98c9 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -13,7 +13,7 @@ //! `[1]` Matthew Flatt, Ryan Culpepper, David Darais, and Robert Bruce Findler. 2012. //! *Macros that work together: Compile-time bindings, partial expansion, //! and definition contexts*. J. Funct. Program. 22, 2 (March 2012), 181-216. -//! DOI=10.1017/S0956796812000093 +//! DOI=10.1017/S0956796812000093 use GLOBALS; use Span; diff --git a/src/test/rustdoc/pub-restricted.rs b/src/test/rustdoc/pub-restricted.rs new file mode 100644 index 00000000000..cc8f628cad4 --- /dev/null +++ b/src/test/rustdoc/pub-restricted.rs @@ -0,0 +1,44 @@ +// Copyright 2018 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. + +// ignore-tidy-linelength + +// compile-flags: --document-private-items + +#![feature(crate_visibility_modifier)] + +#![crate_name = "foo"] + +// @has 'foo/struct.FooPublic.html' '//pre' 'pub struct FooPublic' +pub struct FooPublic; +// @has 'foo/struct.FooJustCrate.html' '//pre' 'pub(crate) struct FooJustCrate' +crate struct FooJustCrate; +// @has 'foo/struct.FooPubCrate.html' '//pre' 'pub(crate) struct FooPubCrate' +pub(crate) struct FooPubCrate; +// @has 'foo/struct.FooSelf.html' '//pre' 'pub(self) struct FooSelf' +pub(self) struct FooSelf; +// @has 'foo/struct.FooInSelf.html' '//pre' 'pub(self) struct FooInSelf' +pub(in self) struct FooInSelf; +mod a { + // @has 'foo/a/struct.FooSuper.html' '//pre' 'pub(super) struct FooSuper' + pub(super) struct FooSuper; + // @has 'foo/a/struct.FooInSuper.html' '//pre' 'pub(super) struct FooInSuper' + pub(in super) struct FooInSuper; + // @has 'foo/a/struct.FooInA.html' '//pre' 'pub(in a) struct FooInA' + pub(in a) struct FooInA; + mod b { + // @has 'foo/a/b/struct.FooInSelfSuperB.html' '//pre' 'pub(in self::super::b) struct FooInSelfSuperB' + pub(in self::super::b) struct FooInSelfSuperB; + // @has 'foo/a/b/struct.FooInSuperSuper.html' '//pre' 'pub(in super::super) struct FooInSuperSuper' + pub(in super::super) struct FooInSuperSuper; + // @has 'foo/a/b/struct.FooInAB.html' '//pre' 'pub(in a::b) struct FooInAB' + pub(in a::b) struct FooInAB; + } +} diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index 23315e3b76a..e1e13e9256d 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -5,6 +5,8 @@ LL | let x: Option<_> = None; | - consider giving `x` a type LL | x.unwrap().method_that_could_exist_on_some_type(); | ^^^^^^^^^^ cannot infer type for `T` + | + = note: type must be known at this point error[E0282]: type annotations needed --> $DIR/issue-42234-unknown-receiver-type.rs:22:5 @@ -12,6 +14,8 @@ error[E0282]: type annotations needed LL | / data.iter() //~ ERROR 22:5: 23:20: type annotations needed LL | | .sum::<_>() | |___________________^ cannot infer type for `_` + | + = note: type must be known at this point error: aborting due to 2 previous errors diff --git a/src/test/ui/span/method-and-field-eager-resolution.rs b/src/test/ui/span/method-and-field-eager-resolution.rs new file mode 100644 index 00000000000..29011abb460 --- /dev/null +++ b/src/test/ui/span/method-and-field-eager-resolution.rs @@ -0,0 +1,25 @@ +// Copyright 2018 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. + +// Test that spans get only base in eager type resolution (structurally_resolve_type). + +fn main() { + let mut x = Default::default(); + x.0; + //~^ ERROR type annotations needed + x = 1; +} + +fn foo() { + let mut x = Default::default(); + x[0]; + //~^ ERROR type annotations needed + x = 1; +} diff --git a/src/test/ui/span/method-and-field-eager-resolution.stderr b/src/test/ui/span/method-and-field-eager-resolution.stderr new file mode 100644 index 00000000000..21e19828a99 --- /dev/null +++ b/src/test/ui/span/method-and-field-eager-resolution.stderr @@ -0,0 +1,23 @@ +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:15:5 + | +LL | let mut x = Default::default(); + | ----- consider giving `x` a type +LL | x.0; + | ^ cannot infer type for `_` + | + = note: type must be known at this point + +error[E0282]: type annotations needed + --> $DIR/method-and-field-eager-resolution.rs:22:5 + | +LL | let mut x = Default::default(); + | ----- consider giving `x` a type +LL | x[0]; + | ^ cannot infer type for `_` + | + = note: type must be known at this point + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 47667d93cb7..bc4503903d6 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -12,73 +12,148 @@ const fs = require('fs'); const TEST_FOLDER = 'src/test/rustdoc-js/'; +function getNextStep(content, pos, stop) { + while (pos < content.length && content[pos] !== stop && + (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) { + pos += 1; + } + if (pos >= content.length) { + return null; + } + if (content[pos] !== stop) { + return pos * -1; + } + return pos; +} + // Stupid function extractor based on indent. function extractFunction(content, functionName) { - var x = content.split('\n'); - var in_func = false; var indent = 0; - var lines = []; - - for (var i = 0; i < x.length; ++i) { - if (in_func === false) { - var splitter = "function " + functionName + "("; - if (x[i].trim().startsWith(splitter)) { - in_func = true; - indent = x[i].split(splitter)[0].length; - lines.push(x[i]); - } - } else { - lines.push(x[i]); - if (x[i].trim() === "}" && x[i].split("}")[0].length === indent) { - return lines.join("\n"); + var splitter = "function " + functionName + "("; + + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = start; + while (pos < content.length && content[pos] !== ')') { + pos += 1; + } + if (pos >= content.length) { + break; + } + pos = getNextStep(content, pos + 1, '{'); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + if (content[pos] === '"' || content[pos] === "'") { + var stop = content[pos]; + var is_escaped = false; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + } else if (content[pos] === '{') { + indent += 1; + } else if (content[pos] === '}') { + indent -= 1; + if (indent === 0) { + return content.slice(start, pos + 1); + } } + pos += 1; } + content = content.slice(start + 1); } return null; } // Stupid function extractor for array. function extractArrayVariable(content, arrayName) { - var x = content.split('\n'); - var found_var = false; - var lines = []; - - for (var i = 0; i < x.length; ++i) { - if (found_var === false) { - var splitter = "var " + arrayName + " = ["; - if (x[i].trim().startsWith(splitter)) { - found_var = true; - i -= 1; - } - } else { - lines.push(x[i]); - if (x[i].endsWith('];')) { - return lines.join("\n"); + var splitter = "var " + arrayName; + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = getNextStep(content, start, '='); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + pos = getNextStep(content, pos, '['); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + if (content[pos] === '"' || content[pos] === "'") { + var stop = content[pos]; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + } else if (content[pos] === ']' && + pos + 1 < content.length && + content[pos + 1] === ';') { + return content.slice(start, pos + 2); } + pos += 1; } + content = content.slice(start + 1); } return null; } // Stupid function extractor for variable. function extractVariable(content, varName) { - var x = content.split('\n'); - var found_var = false; - var lines = []; - - for (var i = 0; i < x.length; ++i) { - if (found_var === false) { - var splitter = "var " + varName + " = "; - if (x[i].trim().startsWith(splitter)) { - found_var = true; - i -= 1; - } - } else { - lines.push(x[i]); - if (x[i].endsWith(';')) { - return lines.join("\n"); + var splitter = "var " + varName; + while (true) { + var start = content.indexOf(splitter); + if (start === -1) { + break; + } + var pos = getNextStep(content, start, '='); + if (pos === null) { + break; + } else if (pos < 0) { + content = content.slice(-pos); + continue; + } + while (pos < content.length) { + if (content[pos] === '"' || content[pos] === "'") { + var stop = content[pos]; + do { + if (content[pos] === '\\') { + pos += 2; + } else { + pos += 1; + } + } while (pos < content.length && + (content[pos] !== stop || content[pos - 1] === '\\')); + } else if (content[pos] === ';') { + return content.slice(start, pos + 1); } + pos += 1; } + content = content.slice(start + 1); } return null; } @@ -101,7 +176,7 @@ function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) { for (var i = 0; i < thingsToLoad.length; ++i) { var tmp = funcToCall(fileContent, thingsToLoad[i]); if (tmp === null) { - console.error('enable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); + console.error('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); process.exit(1); } content += tmp;