]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #76758 - adamlesinski:clone_clock, r=tmandry
authorTyler Mandry <tmandry@gmail.com>
Wed, 16 Sep 2020 19:24:19 +0000 (12:24 -0700)
committerGitHub <noreply@github.com>
Wed, 16 Sep 2020 19:24:19 +0000 (12:24 -0700)
[fuchsia] Propagate the userspace UTC clock

On Fuchsia, spawning a subprocess does not automatically
clone all of the parent process' capabilities. UTC time on
Fuchsia is managed by a top-level userspace clock capability
that is cloned and passed to subprocesses.

This change ensures that any Rust subprocess gets access to the
UTC clock, if the parent had access to it. This is critical for
tests, which on Fuchsia, use panic=abort and spawn subprocesses
per test.

162 files changed:
.github/workflows/ci.yml
Cargo.lock
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs
compiler/rustc_middle/src/infer/unify_key.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/ty/adjustment.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/diagnostics.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
compiler/rustc_mir/src/borrow_check/mod.rs
compiler/rustc_mir/src/monomorphize/partitioning/default.rs
compiler/rustc_mir/src/monomorphize/partitioning/merging.rs
compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
compiler/rustc_mir/src/transform/check_const_item_mutation.rs
compiler/rustc_mir/src/transform/instcombine.rs
compiler/rustc_mir/src/util/find_self_call.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/autoderef.rs
compiler/rustc_trait_selection/src/traits/coherence.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_traits/src/chalk/db.rs
compiler/rustc_typeck/src/check/_match.rs
compiler/rustc_typeck/src/check/autoderef.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/method/confirm.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check/place_op.rs
config.toml.example
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/vec_deque.rs
library/alloc/src/lib.rs
library/alloc/src/slice.rs
library/alloc/src/string.rs
library/alloc/src/vec.rs
library/alloc/tests/lib.rs
library/alloc/tests/str.rs
library/alloc/tests/string.rs
library/alloc/tests/vec.rs
library/alloc/tests/vec_deque.rs
library/core/src/cmp.rs
library/core/src/hint.rs
library/core/src/iter/adapters/flatten.rs
library/core/src/mem/mod.rs
library/core/src/num/dec2flt/algorithm.rs
library/core/src/num/dec2flt/mod.rs
library/core/src/num/mod.rs
library/core/src/ops/deref.rs
library/core/src/slice/index.rs
library/core/src/slice/iter.rs
library/core/src/slice/mod.rs
library/core/src/task/poll.rs
library/core/src/time.rs
library/core/tests/cmp.rs
library/core/tests/lib.rs
library/core/tests/num/i32.rs
library/core/tests/slice.rs
library/core/tests/time.rs
library/std/src/process.rs
library/std/src/sys/sgx/fs.rs [deleted file]
library/std/src/sys/sgx/io.rs [deleted file]
library/std/src/sys/sgx/mod.rs
library/std/src/sys/sgx/pipe.rs [deleted file]
library/std/src/sys/sgx/process.rs [deleted file]
library/std/src/sys/unix/alloc.rs
library/std/src/sys/unsupported/fs.rs
library/std/src/sys/unsupported/mod.rs
library/std/src/sys/unsupported/path.rs [deleted file]
library/std/src/sys/unsupported/process.rs
library/std/src/sys/wasi/alloc.rs [deleted file]
library/std/src/sys/wasi/mod.rs
library/std/src/sys/wasi/path.rs [deleted file]
library/std/src/sys/wasi/pipe.rs [deleted file]
library/std/src/sys/wasi/process.rs [deleted file]
library/std/src/sys/wasm/mod.rs
library/std/src/thread/local.rs
library/stdarch
src/bootstrap/README.md
src/bootstrap/builder.rs
src/bootstrap/builder/tests.rs
src/bootstrap/config.rs
src/bootstrap/doc.rs
src/bootstrap/format.rs
src/bootstrap/sanity.rs
src/bootstrap/test.rs
src/ci/docker/host-x86_64/dist-x86_64-linux/build-git.sh [deleted file]
src/ci/docker/host-x86_64/dist-x86_64-linux/build-headers.sh [deleted file]
src/ci/docker/host-x86_64/dist-x86_64-linux/build-perl.sh [deleted file]
src/ci/github-actions/ci.yml
src/doc/rustc/src/platform-support.md
src/doc/unstable-book/src/library-features/asm.md
src/doc/unstable-book/src/library-features/llvm-asm.md
src/librustdoc/Cargo.toml
src/librustdoc/clean/mod.rs
src/librustdoc/html/markdown.rs
src/librustdoc/lib.rs
src/librustdoc/passes/doc_test_lints.rs
src/test/codegen/issue-73396-bounds-check-after-position.rs [new file with mode: 0644]
src/test/rustdoc-ui/coverage/doc-examples.stdout
src/test/rustdoc-ui/intra-link-double-anchor.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-link-double-anchor.stderr [new file with mode: 0644]
src/test/rustdoc-ui/private-doc-test.rs [new file with mode: 0644]
src/test/ui/const-generics/cannot-infer-const-args.full.stderr [deleted file]
src/test/ui/const-generics/cannot-infer-const-args.min.stderr [deleted file]
src/test/ui/const-generics/cannot-infer-const-args.rs [deleted file]
src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/cannot-infer-const-args.rs [new file with mode: 0644]
src/test/ui/const-generics/infer/method-chain.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/method-chain.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/method-chain.rs [new file with mode: 0644]
src/test/ui/const-generics/infer/uninferred-consts.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/uninferred-consts.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/uninferred-consts.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-64494.min.stderr
src/test/ui/const-generics/issues/issue-67739.min.stderr
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs [new file with mode: 0644]
src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
src/test/ui/const-generics/type-dependent/issue-61936.rs
src/test/ui/const-generics/uninferred-consts.full.stderr [deleted file]
src/test/ui/const-generics/uninferred-consts.min.stderr [deleted file]
src/test/ui/const-generics/uninferred-consts.rs [deleted file]
src/test/ui/consts/duration-consts-2.rs [deleted file]
src/test/ui/lint/lint-unconditional-recursion.stderr
src/test/ui/moves/move-deref-coercion.rs [new file with mode: 0644]
src/test/ui/moves/move-deref-coercion.stderr [new file with mode: 0644]
src/test/ui/no-capture-arc.stderr
src/test/ui/no-reuse-move-arc.stderr
src/test/ui/numbers-arithmetic/arith-0.rs [deleted file]
src/test/ui/numbers-arithmetic/arith-1.rs [deleted file]
src/test/ui/numbers-arithmetic/arith-2.rs [deleted file]
src/test/ui/parser/issue-73568-lifetime-after-mut.rs [new file with mode: 0644]
src/test/ui/parser/issue-73568-lifetime-after-mut.stderr [new file with mode: 0644]
src/test/ui/str-multiline.rs [deleted file]
src/test/ui/string-escapes.rs [deleted file]
src/test/ui/trait-impl-bound-suggestions.fixed [new file with mode: 0644]
src/test/ui/trait-impl-bound-suggestions.rs [new file with mode: 0644]
src/test/ui/trait-impl-bound-suggestions.stderr [new file with mode: 0644]
src/test/ui/type/type-check-defaults.stderr
src/tools/cargo
src/tools/lint-docs/src/lib.rs
src/tools/rust-analyzer

index 8b6828fd49d27d3df552c38029fd966a3d2c524d..50ae8c313d6fcb152fb0e3f600296f23062050a2 100644 (file)
@@ -76,7 +76,7 @@ jobs:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
+        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
         if: success() && !env.SKIP_JOB
@@ -180,7 +180,7 @@ jobs:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
+        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
         if: success() && !env.SKIP_JOB
@@ -375,6 +375,64 @@ jobs:
             env:
               DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
             os: ubuntu-latest-xl
+          - name: dist-x86_64-apple
+            env:
+              SCRIPT: "./x.py dist"
+              RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+              DIST_REQUIRE_ALL_TOOLS: 1
+            os: macos-latest
+          - name: dist-x86_64-apple-alt
+            env:
+              SCRIPT: "./x.py dist"
+              RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            os: macos-latest
+          - name: x86_64-apple
+            env:
+              SCRIPT: "./x.py --stage 2 test"
+              RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.8
+              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            os: macos-latest
+          - name: dist-x86_64-apple
+            env:
+              SCRIPT: "./x.py dist"
+              RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+              DIST_REQUIRE_ALL_TOOLS: 1
+            os: macos-latest
+          - name: dist-x86_64-apple-alt
+            env:
+              SCRIPT: "./x.py dist"
+              RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            os: macos-latest
+          - name: x86_64-apple
+            env:
+              SCRIPT: "./x.py --stage 2 test"
+              RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.8
+              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            os: macos-latest
           - name: x86_64-msvc-1
             env:
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
@@ -499,7 +557,7 @@ jobs:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
+        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
         if: success() && !env.SKIP_JOB
@@ -580,38 +638,6 @@ jobs:
               - self-hosted
               - ARM64
               - linux
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: "./x.py dist"
-              RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-              RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
-            os: macos-latest
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: "./x.py dist"
-              RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
-            os: macos-latest
-          - name: x86_64-apple
-            env:
-              SCRIPT: "./x.py --stage 2 test"
-              RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.8
-              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
-            os: macos-latest
     timeout-minutes: 600
     runs-on: "${{ matrix.os }}"
     steps:
@@ -638,7 +664,7 @@ jobs:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
+        if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
       - name: collect CPU statistics
         run: src/ci/scripts/collect-cpu-stats.sh
         if: success() && !env.SKIP_JOB
index 9b5a4c24d25ed9017174803806241911b1b9740a..d3f777bc663ddd250b9d13cf6f2ea5d0bbf33a0c 100644 (file)
@@ -534,7 +534,7 @@ dependencies = [
  "if_chain",
  "itertools 0.9.0",
  "lazy_static",
- "pulldown-cmark",
+ "pulldown-cmark 0.7.2",
  "quine-mc_cluskey",
  "quote",
  "regex-syntax",
@@ -1853,7 +1853,7 @@ dependencies = [
  "log",
  "memchr",
  "open",
- "pulldown-cmark",
+ "pulldown-cmark 0.7.2",
  "regex",
  "serde",
  "serde_derive",
@@ -2511,6 +2511,17 @@ dependencies = [
  "unicase",
 ]
 
+[[package]]
+name = "pulldown-cmark"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8"
+dependencies = [
+ "bitflags",
+ "memchr",
+ "unicase",
+]
+
 [[package]]
 name = "punycode"
 version = "0.4.1"
@@ -4122,7 +4133,7 @@ dependencies = [
  "expect-test",
  "itertools 0.9.0",
  "minifier",
- "pulldown-cmark",
+ "pulldown-cmark 0.8.0",
  "rustc-rayon",
  "serde",
  "serde_json",
index ec41fd7a3eebe90132d9982db5b8c74f34b21b38..4cfb188783ba110c42165132188d698c3a535152 100644 (file)
@@ -584,12 +584,12 @@ fn subspan(
 
         let start = match start {
             Bound::Included(lo) => lo,
-            Bound::Excluded(lo) => lo + 1,
+            Bound::Excluded(lo) => lo.checked_add(1)?,
             Bound::Unbounded => 0,
         };
 
         let end = match end {
-            Bound::Included(hi) => hi + 1,
+            Bound::Included(hi) => hi.checked_add(1)?,
             Bound::Excluded(hi) => hi,
             Bound::Unbounded => length,
         };
index 4de84e5ba399c2dd243a9c90040049933ebc01c7..f87406c2ce469c97f15da28c3d9950abb90942d6 100644 (file)
@@ -6,9 +6,10 @@
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
 use rustc_middle::hir::map::Map;
+use rustc_middle::infer::unify_key::ConstVariableOriginKind;
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_middle::ty::{self, DefIdTree, InferConst, Ty};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
@@ -569,14 +570,26 @@ pub fn need_type_info_err_const(
             local_visitor.visit_expr(expr);
         }
 
+        let mut param_name = None;
+        let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
+            let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
+            if let ConstVariableOriginKind::ConstParameterDefinition(param) = origin.kind {
+                param_name = Some(param);
+            }
+            origin.span
+        } else {
+            local_visitor.target_span
+        };
+
         let error_code = error_code.into();
-        let mut err = self.tcx.sess.struct_span_err_with_code(
-            local_visitor.target_span,
-            "type annotations needed",
-            error_code,
-        );
+        let mut err =
+            self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code);
 
-        err.note("unable to infer the value of a const parameter");
+        if let Some(param_name) = param_name {
+            err.note(&format!("cannot infer the value of the const parameter `{}`", param_name));
+        } else {
+            err.note("unable to infer the value of a const parameter");
+        }
 
         err
     }
index 89142edb2dc61dc58e738062c517b888eb78aae1..e3c613b1d6a12876cf5066a97d9ec09a7e8d90de 100644 (file)
@@ -85,7 +85,7 @@ pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<
 
                 debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
                 if sub == &ty::ReStatic
-                    && v.0.into_iter().find(|t| t.span.desugaring_kind().is_none()).is_some()
+                    && v.0.into_iter().any(|t| t.span.desugaring_kind().is_none())
                 {
                     // If the failure is due to a `'static` requirement coming from a `dyn` or
                     // `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case
index 2580ac6bebd86cbfa437c0671aaf433c9b6b46ba..a60a17befeffdce2b344112e4508b5910445d03e 100644 (file)
@@ -124,6 +124,7 @@ pub struct ConstVariableOrigin {
 pub enum ConstVariableOriginKind {
     MiscVariable,
     ConstInference,
+    // FIXME(const_generics): Consider storing the `DefId` of the param here.
     ConstParameterDefinition(Symbol),
     SubstitutionPlaceholder,
 }
index d32a7a4062e27502e10fd91121a985e7b2e5536f..29daf7e9309aa36716a15ad9e430b5e5f3926580 100644 (file)
@@ -2285,8 +2285,8 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 /// Constants
 ///
 /// Two constants are equal if they are the same constant. Note that
-/// this does not necessarily mean that they are "==" in Rust -- in
-/// particular one must be wary of `NaN`!
+/// this does not necessarily mean that they are `==` in Rust -- in
+/// particular, one must be wary of `NaN`!
 
 #[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub struct Constant<'tcx> {
index 6a9bb8d6c284fc31d09a89c1e12ac8cd283cbfae..46ef5ff7dd8c5c97e71278b3df39e44040ef2716 100644 (file)
@@ -4,6 +4,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_macros::HashStable;
+use rustc_span::Span;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum PointerCast {
@@ -113,6 +114,9 @@ pub enum Adjust<'tcx> {
 pub struct OverloadedDeref<'tcx> {
     pub region: ty::Region<'tcx>,
     pub mutbl: hir::Mutability,
+    /// The `Span` associated with the field access or method call
+    /// that triggered this overloaded deref.
+    pub span: Span,
 }
 
 impl<'tcx> OverloadedDeref<'tcx> {
index aacf61e5b425a28852d05b70b928ed7a160c026a..56746666e2f1fea12c9e2e1171b8a08201c08068 100644 (file)
@@ -66,8 +66,8 @@
 use std::ops::{Bound, Deref};
 use std::sync::Arc;
 
-/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
-/// except through `tcx.err*()`, which are in this module.
+/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
+/// except through the error-reporting functions on a [`tcx`][TyCtxt].
 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
 #[derive(TyEncodable, TyDecodable, HashStable)]
 pub struct DelaySpanBugEmitted(());
index bc51c8b6cd41c6e1b3f9054678d9987d29f7d471..715319747e3900adf34732b690bc1e93a05ee94c 100644 (file)
@@ -202,33 +202,59 @@ pub fn suggest_constraining_type_param(
         //    Suggestion:
         //      fn foo<T>(t: T) where T: Foo, T: Bar {... }
         //                                          - insert: `, T: Zar`
+        //
+        // Additionally, there may be no `where` clause whatsoever in the case that this was
+        // reached because the generic parameter has a default:
+        //
+        //    Message:
+        //      trait Foo<T=()> {... }
+        //             - help: consider further restricting this type parameter with `where T: Zar`
+        //
+        //    Suggestion:
+        //      trait Foo<T=()> where T: Zar {... }
+        //                     - insert: `where T: Zar`
 
-        let mut param_spans = Vec::new();
+        if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
+            && generics.where_clause.predicates.len() == 0
+        {
+            // Suggest a bound, but there is no existing `where` clause *and* the type param has a
+            // default (`<T=Foo>`), so we suggest adding `where T: Bar`.
+            err.span_suggestion_verbose(
+                generics.where_clause.tail_span_for_suggestion(),
+                &msg_restrict_type_further,
+                format!(" where {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            let mut param_spans = Vec::new();
 
-        for predicate in generics.where_clause.predicates {
-            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
-                span, bounded_ty, ..
-            }) = predicate
-            {
-                if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
-                    if let Some(segment) = path.segments.first() {
-                        if segment.ident.to_string() == param_name {
-                            param_spans.push(span);
+            for predicate in generics.where_clause.predicates {
+                if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+                    span,
+                    bounded_ty,
+                    ..
+                }) = predicate
+                {
+                    if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
+                        if let Some(segment) = path.segments.first() {
+                            if segment.ident.to_string() == param_name {
+                                param_spans.push(span);
+                            }
                         }
                     }
                 }
             }
-        }
 
-        match &param_spans[..] {
-            &[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
-            _ => {
-                err.span_suggestion_verbose(
-                    generics.where_clause.tail_span_for_suggestion(),
-                    &msg_restrict_type_further,
-                    format!(", {}: {}", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
+            match &param_spans[..] {
+                &[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
+                _ => {
+                    err.span_suggestion_verbose(
+                        generics.where_clause.tail_span_for_suggestion(),
+                        &msg_restrict_type_further,
+                        format!(", {}: {}", param_name, constraint),
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
         }
 
index 9562d43791493691c2e9ea47aa1d466d8b352af7..4b2e9a16d4a07ec6398ea08f705dc49e53c7a4ab 100644 (file)
@@ -273,10 +273,10 @@ fn try_print_trimmed_def_path(
         }
 
         match self.tcx().trimmed_def_paths(LOCAL_CRATE).get(&def_id) {
-            None => return Ok((self, false)),
+            None => Ok((self, false)),
             Some(symbol) => {
                 self.write_str(&symbol.as_str())?;
-                return Ok((self, true));
+                Ok((self, true))
             }
         }
     }
index afbf805975ce76e8f5875b5be86177c39a479255..6d9d23836fc69d920284317bde8689d07d6f887f 100644 (file)
@@ -612,8 +612,11 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::OverloadedDeref<'a> {
     type Lifted = ty::adjustment::OverloadedDeref<'tcx>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-        tcx.lift(&self.region)
-            .map(|region| ty::adjustment::OverloadedDeref { region, mutbl: self.mutbl })
+        tcx.lift(&self.region).map(|region| ty::adjustment::OverloadedDeref {
+            region,
+            mutbl: self.mutbl,
+            span: self.span,
+        })
     }
 }
 
index 9f5fc5a2d3fbccc428e429954403ada0e344e791..d4c8ba082751e89a13abeb1a95c9fc7e0ce6239e 100644 (file)
@@ -1233,13 +1233,13 @@ pub fn to_const(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx>
     /// particular, imagine a type like this:
     ///
     ///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
-    ///     ^          ^            |        |         |
-    ///     |          |            |        |         |
-    ///     |          +------------+ 0      |         |
-    ///     |                                |         |
-    ///     +--------------------------------+ 1       |
-    ///     |                                          |
-    ///     +------------------------------------------+ 0
+    ///     ^          ^            |          |           |
+    ///     |          |            |          |           |
+    ///     |          +------------+ 0        |           |
+    ///     |                                  |           |
+    ///     +----------------------------------+ 1         |
+    ///     |                                              |
+    ///     +----------------------------------------------+ 0
     ///
     /// In this type, there are two binders (the outer fn and the inner
     /// fn). We need to be able to determine, for any given region, which
@@ -2280,6 +2280,12 @@ pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
     ///
     /// Returning true means the type is known to be sized. Returning
     /// `false` means nothing -- could be sized, might not be.
+    ///
+    /// Note that we could never rely on the fact that a type such as `[_]` is
+    /// trivially `!Sized` because we could be in a type environment with a
+    /// bound such as `[_]: Copy`. A function with such a bound obviously never
+    /// can be called, but that doesn't mean it shouldn't typecheck. This is why
+    /// this method doesn't return `Option<bool>`.
     pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
         match self.kind() {
             ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
index 676065007b7ef5cf107c8771e929e33306812359..11122b195c0c4bf2c7fe4173688afe12753fd3b5 100644 (file)
@@ -66,7 +66,10 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
         let span = use_spans.args_or_use();
 
         let move_site_vec = self.get_moved_indexes(location, mpi);
-        debug!("report_use_of_moved_or_uninitialized: move_site_vec={:?}", move_site_vec);
+        debug!(
+            "report_use_of_moved_or_uninitialized: move_site_vec={:?} use_spans={:?}",
+            move_site_vec, use_spans
+        );
         let move_out_indices: Vec<_> =
             move_site_vec.iter().map(|move_site| move_site.moi).collect();
 
@@ -229,6 +232,8 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                                     );
                                 }
                             }
+                            // Deref::deref takes &self, which cannot cause a move
+                            FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
                         }
                     } else {
                         err.span_label(
@@ -355,6 +360,20 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
                 self.note_type_does_not_implement_copy(&mut err, &note_msg, ty, span, partial_str);
             }
 
+            if let UseSpans::FnSelfUse {
+                kind: FnSelfUseKind::DerefCoercion { deref_target, deref_target_ty },
+                ..
+            } = use_spans
+            {
+                err.note(&format!(
+                    "{} occurs due to deref coercion to `{}`",
+                    desired_action.as_noun(),
+                    deref_target_ty
+                ));
+
+                err.span_note(deref_target, "deref defined here");
+            }
+
             if let Some((_, mut old_err)) =
                 self.move_error_reported.insert(move_out_indices, (used_place, err))
             {
@@ -945,7 +964,7 @@ fn report_local_value_does_not_live_long_enough(
         name: &str,
         borrow: &BorrowData<'tcx>,
         drop_span: Span,
-        borrow_spans: UseSpans,
+        borrow_spans: UseSpans<'tcx>,
         explanation: BorrowExplanation,
     ) -> DiagnosticBuilder<'cx> {
         debug!(
@@ -1146,7 +1165,7 @@ fn report_temporary_value_does_not_live_long_enough(
         location: Location,
         borrow: &BorrowData<'tcx>,
         drop_span: Span,
-        borrow_spans: UseSpans,
+        borrow_spans: UseSpans<'tcx>,
         proper_span: Span,
         explanation: BorrowExplanation,
     ) -> DiagnosticBuilder<'cx> {
@@ -1274,7 +1293,7 @@ fn try_report_cannot_return_reference_to_local(
 
     fn report_escaping_closure_capture(
         &mut self,
-        use_span: UseSpans,
+        use_span: UseSpans<'tcx>,
         var_span: Span,
         fr_name: &RegionName,
         category: ConstraintCategory,
index eaaf202f3bd13484a1bc7b3459d1c34189e79485..eccb6168229c29f5949ef6f468ff03bd6cfb1175 100644 (file)
@@ -501,7 +501,7 @@ fn is_back_edge(&self, source: Location, target: Location) -> bool {
     fn later_use_kind(
         &self,
         borrow: &BorrowData<'tcx>,
-        use_spans: UseSpans,
+        use_spans: UseSpans<'tcx>,
         location: Location,
     ) -> (LaterUseKind, Span) {
         match use_spans {
index 3cee32834beb7579b54382b5a14d19929d6b837a..4256f6e39d5e863234dcefda647b0994c5fc4bc2 100644 (file)
@@ -11,7 +11,7 @@
     PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::print::Print;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
 use rustc_span::{
     hygiene::{DesugaringKind, ForLoopLoc},
     symbol::sym,
@@ -538,7 +538,7 @@ pub(super) fn get_region_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> Str
 
 /// The span(s) associated to a use of a place.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub(super) enum UseSpans {
+pub(super) enum UseSpans<'tcx> {
     /// The access is caused by capturing a variable for a closure.
     ClosureUse {
         /// This is true if the captured variable was from a generator.
@@ -558,7 +558,7 @@ pub(super) enum UseSpans {
         fn_call_span: Span,
         /// The definition span of the method being called
         fn_span: Span,
-        kind: FnSelfUseKind,
+        kind: FnSelfUseKind<'tcx>,
     },
     /// This access is caused by a `match` or `if let` pattern.
     PatUse(Span),
@@ -567,22 +567,32 @@ pub(super) enum UseSpans {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub(super) enum FnSelfUseKind {
+pub(super) enum FnSelfUseKind<'tcx> {
     /// A normal method call of the form `receiver.foo(a, b, c)`
     Normal { self_arg: Ident, implicit_into_iter: bool },
     /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
     FnOnceCall,
     /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
     Operator { self_arg: Ident },
+    DerefCoercion {
+        /// The `Span` of the `Target` associated type
+        /// in the `Deref` impl we are using.
+        deref_target: Span,
+        /// The type `T::Deref` we are dereferencing to
+        deref_target_ty: Ty<'tcx>,
+    },
 }
 
-impl UseSpans {
+impl UseSpans<'_> {
     pub(super) fn args_or_use(self) -> Span {
         match self {
             UseSpans::ClosureUse { args_span: span, .. }
             | UseSpans::PatUse(span)
-            | UseSpans::FnSelfUse { var_span: span, .. }
             | UseSpans::OtherUse(span) => span,
+            UseSpans::FnSelfUse {
+                fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
+            } => fn_call_span,
+            UseSpans::FnSelfUse { var_span, .. } => var_span,
         }
     }
 
@@ -590,8 +600,11 @@ pub(super) fn var_or_use(self) -> Span {
         match self {
             UseSpans::ClosureUse { var_span: span, .. }
             | UseSpans::PatUse(span)
-            | UseSpans::FnSelfUse { var_span: span, .. }
             | UseSpans::OtherUse(span) => span,
+            UseSpans::FnSelfUse {
+                fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
+            } => fn_call_span,
+            UseSpans::FnSelfUse { var_span, .. } => var_span,
         }
     }
 
@@ -754,7 +767,7 @@ pub(super) fn move_spans(
         &self,
         moved_place: PlaceRef<'tcx>, // Could also be an upvar.
         location: Location,
-    ) -> UseSpans {
+    ) -> UseSpans<'tcx> {
         use self::UseSpans::*;
 
         let stmt = match self.body[location.block].statements.get(location.statement_index) {
@@ -809,36 +822,64 @@ pub(super) fn move_spans(
             kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
         }) = &self.body[location.block].terminator
         {
-            let method_did = if let Some(method_did) =
+            let (method_did, method_substs) = if let Some(info) =
                 crate::util::find_self_call(self.infcx.tcx, &self.body, target_temp, location.block)
             {
-                method_did
+                info
             } else {
                 return normal_ret;
             };
 
             let tcx = self.infcx.tcx;
-
             let parent = tcx.parent(method_did);
             let is_fn_once = parent == tcx.lang_items().fn_once_trait();
             let is_operator = !from_hir_call
                 && parent.map_or(false, |p| tcx.lang_items().group(LangItemGroup::Op).contains(&p));
+            let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
             let fn_call_span = *fn_span;
 
             let self_arg = tcx.fn_arg_names(method_did)[0];
 
+            debug!(
+                "terminator = {:?} from_hir_call={:?}",
+                self.body[location.block].terminator, from_hir_call
+            );
+
+            // Check for a 'special' use of 'self' -
+            // an FnOnce call, an operator (e.g. `<<`), or a
+            // deref coercion.
             let kind = if is_fn_once {
-                FnSelfUseKind::FnOnceCall
+                Some(FnSelfUseKind::FnOnceCall)
             } else if is_operator {
-                FnSelfUseKind::Operator { self_arg }
+                Some(FnSelfUseKind::Operator { self_arg })
+            } else if is_deref {
+                let deref_target =
+                    tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
+                        Instance::resolve(tcx, self.param_env, deref_target, method_substs)
+                            .transpose()
+                    });
+                if let Some(Ok(instance)) = deref_target {
+                    let deref_target_ty = instance.ty(tcx, self.param_env);
+                    Some(FnSelfUseKind::DerefCoercion {
+                        deref_target: tcx.def_span(instance.def_id()),
+                        deref_target_ty,
+                    })
+                } else {
+                    None
+                }
             } else {
+                None
+            };
+
+            let kind = kind.unwrap_or_else(|| {
+                // This isn't a 'special' use of `self`
                 debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
                 let implicit_into_iter = matches!(
                     fn_call_span.desugaring_kind(),
                     Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
                 );
                 FnSelfUseKind::Normal { self_arg, implicit_into_iter }
-            };
+            });
 
             return FnSelfUse {
                 var_span: stmt.source_info.span,
@@ -859,7 +900,7 @@ pub(super) fn move_spans(
     /// and its usage of the local assigned at `location`.
     /// This is done by searching in statements succeeding `location`
     /// and originating from `maybe_closure_span`.
-    pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans {
+    pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans<'tcx> {
         use self::UseSpans::*;
         debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
 
@@ -963,7 +1004,7 @@ fn closure_span(
 
     /// Helper to retrieve span(s) of given borrow from the current MIR
     /// representation
-    pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans {
+    pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData<'_>) -> UseSpans<'tcx> {
         let span = self.body.source_info(borrow.reserve_location).span;
         self.borrow_spans(span, borrow.reserve_location)
     }
index 6cf1cf20b5afd0f3a5183950d9a44e0acf564a36..e256fb55b124b70a2d3eec66140982b394056a05 100644 (file)
@@ -47,7 +47,7 @@ enum GroupedMoveError<'tcx> {
     // Everything that isn't from pattern matching.
     OtherIllegalMove {
         original_path: Place<'tcx>,
-        use_spans: UseSpans,
+        use_spans: UseSpans<'tcx>,
         kind: IllegalMoveOriginKind<'tcx>,
     },
 }
@@ -222,7 +222,7 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
         let (mut err, err_span) = {
             let (span, use_spans, original_path, kind): (
                 Span,
-                Option<UseSpans>,
+                Option<UseSpans<'tcx>>,
                 Place<'tcx>,
                 &IllegalMoveOriginKind<'_>,
             ) = match error {
@@ -291,7 +291,7 @@ fn report_cannot_move_from_borrowed_content(
         move_place: Place<'tcx>,
         deref_target_place: Place<'tcx>,
         span: Span,
-        use_spans: Option<UseSpans>,
+        use_spans: Option<UseSpans<'tcx>>,
     ) -> DiagnosticBuilder<'a> {
         // Inspect the type of the content behind the
         // borrow to provide feedback about why this
index 639428ff07d9deb2d136a9aab4a3d5e2c7e62252..eb1f70099fc89059ecf603f1da07cc0258e2565f 100644 (file)
@@ -387,7 +387,7 @@ fn report_fnmut_error(
         if let ReturnConstraint::ClosureUpvar(upvar) = kind {
             let def_id = match self.regioncx.universal_regions().defining_ty {
                 DefiningTy::Closure(def_id, _) => def_id,
-                ty @ _ => bug!("unexpected DefiningTy {:?}", ty),
+                ty => bug!("unexpected DefiningTy {:?}", ty),
             };
 
             let upvar_def_span = self.infcx.tcx.hir().span(upvar);
index acd9e3dcf3fcd44a40343908ad7d71c80c192482..64ad0627720aa0286b26af7ab2a6bccfb4269ba4 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
 use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, InstanceDef, RegionVid, TyCtxt};
+use rustc_middle::ty::{self, InstanceDef, ParamEnv, RegionVid, TyCtxt};
 use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
 use rustc_span::{Span, Symbol, DUMMY_SP};
 
@@ -287,6 +287,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         if let Err((move_data, move_errors)) = move_data_results {
             let mut promoted_mbcx = MirBorrowckCtxt {
                 infcx,
+                param_env,
                 body: promoted_body,
                 mir_def_id: def.did,
                 move_data: &move_data,
@@ -320,6 +321,7 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     let mut mbcx = MirBorrowckCtxt {
         infcx,
+        param_env,
         body,
         mir_def_id: def.did,
         move_data: &mdpe.move_data,
@@ -473,6 +475,7 @@ fn do_mir_borrowck<'a, 'tcx>(
 
 crate struct MirBorrowckCtxt<'cx, 'tcx> {
     crate infcx: &'cx InferCtxt<'cx, 'tcx>,
+    param_env: ParamEnv<'tcx>,
     body: &'cx Body<'tcx>,
     mir_def_id: LocalDefId,
     move_data: &'cx MoveData<'tcx>,
index b48bae837877979462f3da9ce6b2d998df8d1da1..827d037f3198888888f36188d4470fbb122b2544 100644 (file)
@@ -11,6 +11,7 @@
 use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
 use rustc_span::symbol::Symbol;
 
+use super::PartitioningCx;
 use crate::monomorphize::collector::InliningMap;
 use crate::monomorphize::partitioning::merging;
 use crate::monomorphize::partitioning::{
 impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
     fn place_root_mono_items(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
     ) -> PreInliningPartitioning<'tcx> {
         let mut roots = FxHashSet::default();
         let mut codegen_units = FxHashMap::default();
-        let is_incremental_build = tcx.sess.opts.incremental.is_some();
+        let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
         let mut internalization_candidates = FxHashSet::default();
 
         // Determine if monomorphizations instantiated in this crate will be made
         // available to downstream crates. This depends on whether we are in
         // share-generics mode and whether the current crate can even have
         // downstream crates.
-        let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics();
+        let export_generics =
+            cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
 
-        let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
+        let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
         let cgu_name_cache = &mut FxHashMap::default();
 
         for mono_item in mono_items {
-            match mono_item.instantiation_mode(tcx) {
+            match mono_item.instantiation_mode(cx.tcx) {
                 InstantiationMode::GloballyShared { .. } => {}
                 InstantiationMode::LocalCopy => continue,
             }
 
-            let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item);
+            let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
             let is_volatile = is_incremental_build && mono_item.is_generic_fn();
 
             let codegen_unit_name = match characteristic_def_id {
                 Some(def_id) => compute_codegen_unit_name(
-                    tcx,
+                    cx.tcx,
                     cgu_name_builder,
                     def_id,
                     is_volatile,
@@ -65,7 +67,7 @@ fn place_root_mono_items(
 
             let mut can_be_internalized = true;
             let (linkage, visibility) = mono_item_linkage_and_visibility(
-                tcx,
+                cx.tcx,
                 &mono_item,
                 &mut can_be_internalized,
                 export_generics,
@@ -97,17 +99,16 @@ fn place_root_mono_items(
 
     fn merge_codegen_units(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-        target_cgu_count: usize,
     ) {
-        merging::merge_codegen_units(tcx, initial_partitioning, target_cgu_count);
+        merging::merge_codegen_units(cx, initial_partitioning);
     }
 
     fn place_inlined_mono_items(
         &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: PreInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     ) -> PostInliningPartitioning<'tcx> {
         let mut new_partitioning = Vec::new();
         let mut mono_item_placements = FxHashMap::default();
@@ -124,7 +125,7 @@ fn place_inlined_mono_items(
             // Collect all items that need to be available in this codegen unit.
             let mut reachable = FxHashSet::default();
             for root in old_codegen_unit.items().keys() {
-                follow_inlining(*root, inlining_map, &mut reachable);
+                follow_inlining(*root, cx.inlining_map, &mut reachable);
             }
 
             let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
@@ -198,9 +199,8 @@ fn follow_inlining<'tcx>(
 
     fn internalize_symbols(
         &mut self,
-        _tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         partitioning: &mut PostInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     ) {
         if partitioning.codegen_units.len() == 1 {
             // Fast path for when there is only one codegen unit. In this case we
@@ -218,7 +218,7 @@ fn internalize_symbols(
         // Build a map from every monomorphization to all the monomorphizations that
         // reference it.
         let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
-        inlining_map.iter_accesses(|accessor, accessees| {
+        cx.inlining_map.iter_accesses(|accessor, accessees| {
             for accessee in accessees {
                 accessor_map.entry(*accessee).or_default().push(accessor);
             }
index d92f1367e7d679208175d98b6a2c3e93389fa28f..5107e6972632c2d2a295c6e4e8a2608697bacd97 100644 (file)
@@ -3,17 +3,16 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
-use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{Symbol, SymbolStr};
 
+use super::PartitioningCx;
 use crate::monomorphize::partitioning::PreInliningPartitioning;
 
 pub fn merge_codegen_units<'tcx>(
-    tcx: TyCtxt<'tcx>,
+    cx: &PartitioningCx<'_, 'tcx>,
     initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-    target_cgu_count: usize,
 ) {
-    assert!(target_cgu_count >= 1);
+    assert!(cx.target_cgu_count >= 1);
     let codegen_units = &mut initial_partitioning.codegen_units;
 
     // Note that at this point in time the `codegen_units` here may not be in a
@@ -32,7 +31,7 @@ pub fn merge_codegen_units<'tcx>(
         codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name().as_str()])).collect();
 
     // Merge the two smallest codegen units until the target size is reached.
-    while codegen_units.len() > target_cgu_count {
+    while codegen_units.len() > cx.target_cgu_count {
         // Sort small cgus to the back
         codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
         let mut smallest = codegen_units.pop().unwrap();
@@ -56,9 +55,9 @@ pub fn merge_codegen_units<'tcx>(
         );
     }
 
-    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
+    let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
 
-    if tcx.sess.opts.incremental.is_some() {
+    if cx.tcx.sess.opts.incremental.is_some() {
         // If we are doing incremental compilation, we want CGU names to
         // reflect the path of the source level module they correspond to.
         // For CGUs that contain the code of multiple modules because of the
@@ -84,7 +83,7 @@ pub fn merge_codegen_units<'tcx>(
 
         for cgu in codegen_units.iter_mut() {
             if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
-                if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
+                if cx.tcx.sess.opts.debugging_opts.human_readable_cgu_names {
                     cgu.set_name(Symbol::intern(&new_cgu_name));
                 } else {
                     // If we don't require CGU names to be human-readable, we
index 0f6f078d9686f07e6163c8cd6175120353a21159..b60beca688068c8494e5e4211e92bcfd01543463 100644 (file)
 use crate::monomorphize::collector::InliningMap;
 use crate::monomorphize::collector::{self, MonoItemCollectionMode};
 
+pub struct PartitioningCx<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    target_cgu_count: usize,
+    inlining_map: &'a InliningMap<'tcx>,
+}
+
 trait Partitioner<'tcx> {
     fn place_root_mono_items(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
     ) -> PreInliningPartitioning<'tcx>;
 
     fn merge_codegen_units(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-        target_cgu_count: usize,
     );
 
     fn place_inlined_mono_items(
         &mut self,
+        cx: &PartitioningCx<'_, 'tcx>,
         initial_partitioning: PreInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     ) -> PostInliningPartitioning<'tcx>;
 
     fn internalize_symbols(
         &mut self,
-        tcx: TyCtxt<'tcx>,
+        cx: &PartitioningCx<'_, 'tcx>,
         partitioning: &mut PostInliningPartitioning<'tcx>,
-        inlining_map: &InliningMap<'tcx>,
     );
 }
 
@@ -157,12 +161,13 @@ pub fn partition<'tcx>(
     let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
 
     let mut partitioner = get_partitioner(tcx);
+    let cx = &PartitioningCx { tcx, target_cgu_count: max_cgu_count, inlining_map };
     // In the first step, we place all regular monomorphizations into their
     // respective 'home' codegen unit. Regular monomorphizations are all
     // functions and statics defined in the local crate.
     let mut initial_partitioning = {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
-        partitioner.place_root_mono_items(tcx, mono_items)
+        partitioner.place_root_mono_items(cx, mono_items)
     };
 
     initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
@@ -172,7 +177,7 @@ pub fn partition<'tcx>(
     // Merge until we have at most `max_cgu_count` codegen units.
     {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
-        partitioner.merge_codegen_units(tcx, &mut initial_partitioning, max_cgu_count);
+        partitioner.merge_codegen_units(cx, &mut initial_partitioning);
         debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
     }
 
@@ -182,7 +187,7 @@ pub fn partition<'tcx>(
     // local functions the definition of which is marked with `#[inline]`.
     let mut post_inlining = {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
-        partitioner.place_inlined_mono_items(initial_partitioning, inlining_map)
+        partitioner.place_inlined_mono_items(cx, initial_partitioning)
     };
 
     post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
@@ -193,7 +198,7 @@ pub fn partition<'tcx>(
     // more freedom to optimize.
     if !tcx.sess.link_dead_code() {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
-        partitioner.internalize_symbols(tcx, &mut post_inlining, inlining_map);
+        partitioner.internalize_symbols(cx, &mut post_inlining);
     }
 
     // Finally, sort by codegen unit name, so that we get deterministic results.
index 589268e39bda9146e9ed1e2d86d8457b7f13db4f..70c1aed0957f8554279a33ca93924c8c1f7c800f 100644 (file)
@@ -101,7 +101,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, loc: Location) {
                         .note("each usage of a `const` item creates a new temporary")
                         .note("the mutable reference will refer to this temporary, not the original `const` item");
 
-                    if let Some(method_did) = method_did {
+                    if let Some((method_did, _substs)) = method_did {
                         lint.span_note(self.tcx.def_span(method_did), "mutable reference created due to call to this method");
                     }
 
index c4924cf16ab647e0249dcc58297915a9edddb3d7..b224df92e9da0245381866a22a51439066b2d6a2 100644 (file)
@@ -126,7 +126,7 @@ fn find_operand_in_equality_comparison_pattern(
             }
         }
 
-        return None;
+        None
     }
 }
 
index 049b5f01214cf49a8ccb76de10bd7202936994f0..5b146eeb87c044956846f6f5c4a33e7e9ad1a5cc 100644 (file)
@@ -1,30 +1,31 @@
 use rustc_middle::mir::*;
+use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 
 /// Checks if the specified `local` is used as the `self` prameter of a method call
 /// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
 /// returned.
-pub fn find_self_call(
-    tcx: TyCtxt<'_>,
-    body: &Body<'_>,
+pub fn find_self_call<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &Body<'tcx>,
     local: Local,
     block: BasicBlock,
-) -> Option<DefId> {
+) -> Option<(DefId, SubstsRef<'tcx>)> {
     debug!("find_self_call(local={:?}): terminator={:?}", local, &body[block].terminator);
     if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
         &body[block].terminator
     {
         debug!("find_self_call: func={:?}", func);
         if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
-            if let ty::FnDef(def_id, _) = *ty.kind() {
+            if let ty::FnDef(def_id, substs) = *ty.kind() {
                 if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
                     tcx.opt_associated_item(def_id)
                 {
                     debug!("find_self_call: args={:?}", args);
                     if let [Operand::Move(self_place) | Operand::Copy(self_place), ..] = **args {
                         if self_place.as_local() == Some(local) {
-                            return Some(def_id);
+                            return Some((def_id, substs));
                         }
                     }
                 }
index 70c7abc2654927519d18758b8b8fbf1682b24d57..13e69474cfb965b706f45ff1d4ce092803a8b2f1 100644 (file)
@@ -117,7 +117,14 @@ fn apply_adjustment<'a, 'tcx>(
                 },
             };
 
-            overloaded_place(cx, hir_expr, adjustment.target, Some(call), vec![expr.to_ref()])
+            overloaded_place(
+                cx,
+                hir_expr,
+                adjustment.target,
+                Some(call),
+                vec![expr.to_ref()],
+                deref.span,
+            )
         }
         Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
             ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: expr.to_ref() }
@@ -277,7 +284,14 @@ fn make_mirror_unadjusted<'a, 'tcx>(
 
         hir::ExprKind::Index(ref lhs, ref index) => {
             if cx.typeck_results().is_method_call(expr) {
-                overloaded_place(cx, expr, expr_ty, None, vec![lhs.to_ref(), index.to_ref()])
+                overloaded_place(
+                    cx,
+                    expr,
+                    expr_ty,
+                    None,
+                    vec![lhs.to_ref(), index.to_ref()],
+                    expr.span,
+                )
             } else {
                 ExprKind::Index { lhs: lhs.to_ref(), index: index.to_ref() }
             }
@@ -285,7 +299,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
 
         hir::ExprKind::Unary(hir::UnOp::UnDeref, ref arg) => {
             if cx.typeck_results().is_method_call(expr) {
-                overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()])
+                overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()], expr.span)
             } else {
                 ExprKind::Deref { arg: arg.to_ref() }
             }
@@ -1025,6 +1039,7 @@ fn overloaded_place<'a, 'tcx>(
     place_ty: Ty<'tcx>,
     overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
     args: Vec<ExprRef<'tcx>>,
+    span: Span,
 ) -> ExprKind<'tcx> {
     // For an overloaded *x or x[y] expression of type T, the method
     // call returns an &T and we must add the deref so that the types
@@ -1040,24 +1055,24 @@ fn overloaded_place<'a, 'tcx>(
     // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
     let (region, mutbl) = match *recv_ty.kind() {
         ty::Ref(region, _, mutbl) => (region, mutbl),
-        _ => span_bug!(expr.span, "overloaded_place: receiver is not a reference"),
+        _ => span_bug!(span, "overloaded_place: receiver is not a reference"),
     };
     let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl });
 
     // construct the complete expression `foo()` for the overloaded call,
     // which will yield the &T type
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-    let fun = method_callee(cx, expr, expr.span, overloaded_callee);
+    let fun = method_callee(cx, expr, span, overloaded_callee);
     let ref_expr = Expr {
         temp_lifetime,
         ty: ref_ty,
-        span: expr.span,
+        span,
         kind: ExprKind::Call {
             ty: fun.ty,
             fun: fun.to_ref(),
             args,
             from_hir_call: false,
-            fn_span: expr.span,
+            fn_span: span,
         },
     };
 
index 259764a317df808aea6dddfde6b50d43ad88f431..fc4c62ccbd90e7b4865827d2bc3997b2360ce012 100644 (file)
@@ -276,8 +276,34 @@ fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> {
     }
 
     fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
-        let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
+        let and_span = self.prev_token.span;
+        let mut opt_lifetime =
+            if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
         let mutbl = self.parse_mutability();
+        if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
+            // A lifetime is invalid here: it would be part of a bare trait bound, which requires
+            // it to be followed by a plus, but we disallow plus in the pointee type.
+            // So we can handle this case as an error here, and suggest `'a mut`.
+            // If there *is* a plus next though, handling the error later provides better suggestions
+            // (like adding parentheses)
+            if !self.look_ahead(1, |t| t.is_like_plus()) {
+                let lifetime_span = self.token.span;
+                let span = and_span.to(lifetime_span);
+
+                let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
+                if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
+                    err.span_suggestion(
+                        span,
+                        "place the lifetime before `mut`",
+                        format!("&{} mut", lifetime_src),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                err.emit();
+
+                opt_lifetime = Some(self.expect_lifetime());
+            }
+        }
         let ty = self.parse_ty_no_plus()?;
         Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
     }
index b80da64149150e0f67a759b441aec7355d5c98c4..612bc3e74911c44d788189c4398b2cf2b50936c9 100644 (file)
@@ -466,7 +466,7 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
-            ResolutionError::ParamInNonTrivialAnonConst(name) => {
+            ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
                 let mut err = self.session.struct_span_err(
                     span,
                     "generic parameters must not be used inside of non trivial constant values",
@@ -478,9 +478,17 @@ impl<'a> Resolver<'a> {
                         name
                     ),
                 );
-                err.help(
-                    &format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants", name)
-                );
+
+                if is_type {
+                    err.note("type parameters are currently not permitted in anonymous constants");
+                } else {
+                    err.help(
+                        &format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants",
+                                 name
+                        )
+                    );
+                }
+
                 err
             }
             ResolutionError::SelfInTyParamDefault => {
index 9b5650c260c220949b45b32ff0a5f3ebf9b657c6..2cc87dc637566fafa9cec8a914790039f02b2b3e 100644 (file)
@@ -1534,7 +1534,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
             }
         };
 
-        let lifetime_names: Vec<_> = lifetime_names.into_iter().collect();
+        let lifetime_names: Vec<_> = lifetime_names.iter().collect();
         match (&lifetime_names[..], snippet.as_deref()) {
             ([name], Some("&")) => {
                 suggest_existing(err, &name.as_str()[..], &|name| format!("&{} ", name));
index 00a37d908cd07ee600d3eaf92e8e8e84531f9588..85ddc5f55d110b389f288f839c35e2eb50417831 100644 (file)
@@ -221,7 +221,7 @@ enum ResolutionError<'a> {
     /// generic parameters must not be used inside of non trivial constant values.
     ///
     /// This error is only emitted when using `min_const_generics`.
-    ParamInNonTrivialAnonConst(Symbol),
+    ParamInNonTrivialAnonConst { name: Symbol, is_type: bool },
     /// Error E0735: type parameters with a default cannot use `Self`
     SelfInTyParamDefault,
     /// Error E0767: use of unreachable label
@@ -2638,9 +2638,10 @@ fn validate_res_from_ribs(
                                     if record_used {
                                         self.report_error(
                                             span,
-                                            ResolutionError::ParamInNonTrivialAnonConst(
-                                                rib_ident.name,
-                                            ),
+                                            ResolutionError::ParamInNonTrivialAnonConst {
+                                                name: rib_ident.name,
+                                                is_type: true,
+                                            },
                                         );
                                     }
                                     return Res::Err;
@@ -2718,7 +2719,10 @@ fn validate_res_from_ribs(
                                 if record_used {
                                     self.report_error(
                                         span,
-                                        ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
+                                        ResolutionError::ParamInNonTrivialAnonConst {
+                                            name: rib_ident.name,
+                                            is_type: false,
+                                        },
                                     );
                                 }
                                 return Res::Err;
index 407663e57577affefe9243c00389a46861ee339d..94f795b11ea4d3047b72efdb3d93c8eec1c8a46f 100644 (file)
         deny,
         deprecated,
         deref,
+        deref_method,
         deref_mut,
+        deref_target,
         derive,
         diagnostic,
         direct,
index d6e8b304380ca51a383dc927839164bedb20239f..f1e8330425e25c099c5e3669e6c64dfa57045939 100644 (file)
@@ -654,6 +654,7 @@ fn $module() {
     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
+    ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
     ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
     ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
     ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
diff --git a/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/riscv32gc_unknown_linux_gnu.rs
new file mode 100644 (file)
index 0000000..28710c6
--- /dev/null
@@ -0,0 +1,25 @@
+use crate::spec::{CodeModel, LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "riscv32-unknown-linux-gnu".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_env: "gnu".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        arch: "riscv32".to_string(),
+        target_os: "linux".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions {
+            unsupported_abis: super::riscv_base::unsupported_abis(),
+            code_model: Some(CodeModel::Medium),
+            cpu: "generic-rv32".to_string(),
+            features: "+m,+a,+f,+d,+c".to_string(),
+            llvm_abiname: "ilp32d".to_string(),
+            max_atomic_width: Some(32),
+            ..super::linux_base::opts()
+        },
+    })
+}
index 02eefe5622384a8e4319a99c196466b2027f7897..b9c5123e49a0ea3b35f3aa7c18e260647cce8f96 100644 (file)
@@ -27,6 +27,7 @@ pub struct Autoderef<'a, 'tcx> {
     // Meta infos:
     infcx: &'a InferCtxt<'a, 'tcx>,
     span: Span,
+    overloaded_span: Span,
     body_id: hir::HirId,
     param_env: ty::ParamEnv<'tcx>,
 
@@ -98,10 +99,12 @@ pub fn new(
         body_id: hir::HirId,
         span: Span,
         base_ty: Ty<'tcx>,
+        overloaded_span: Span,
     ) -> Autoderef<'a, 'tcx> {
         Autoderef {
             infcx,
             span,
+            overloaded_span,
             body_id,
             param_env,
             state: AutoderefSnapshot {
@@ -190,6 +193,10 @@ pub fn span(&self) -> Span {
         self.span
     }
 
+    pub fn overloaded_span(&self) -> Span {
+        self.overloaded_span
+    }
+
     pub fn reached_recursion_limit(&self) -> bool {
         self.state.reached_recursion_limit
     }
index c27d2fcc14998d8e4ccf24c82d8d8c02b237c456..c53c65c00b769919864947f9c0a84f3f5e56de7f 100644 (file)
@@ -182,7 +182,7 @@ fn overlap_within_probe(
     }
 
     if !skip_leak_check.is_yes() {
-        if let Err(_) = infcx.leak_check(true, snapshot) {
+        if infcx.leak_check(true, snapshot).is_err() {
             debug!("overlap: leak check failed");
             return None;
         }
index a9651144e597adad3c9a66dc5ba66c1315cb1ae4..bda4351b2f2d8437623583a2d208eae41526a296 100644 (file)
@@ -1512,12 +1512,7 @@ fn maybe_report_ambiguity(
                 // avoid inundating the user with unnecessary errors, but we now
                 // check upstream for type errors and don't add the obligations to
                 // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
+                if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
                     self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
                     return;
                 }
index 82e809d014dd06050a1a750e107d9d81c1414b82..90a8d9634ae1e183907226e7831c6bf12ec9a3ba 100644 (file)
@@ -483,7 +483,7 @@ fn suggest_dereferences(
         };
 
         if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() {
-            let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty);
+            let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span);
             if let Some(steps) = autoderef.find_map(|(ty, steps)| {
                 // Re-add the `&`
                 let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
index 7cc567dabb28f7f59daaaab5a96670b1428a54f5..2fad54013ad5bebc5d836fb7963b129f98f8658d 100644 (file)
@@ -110,25 +110,15 @@ fn trait_datum(
             .map(|i| chalk_ir::AssocTypeId(i.def_id))
             .collect();
 
-        let well_known = if self
-            .interner
-            .tcx
-            .lang_items()
-            .sized_trait()
-            .map(|t| def_id == t)
-            .unwrap_or(false)
-        {
+        let well_known = if self.interner.tcx.lang_items().sized_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Sized)
-        } else if self.interner.tcx.lang_items().copy_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().copy_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Copy)
-        } else if self.interner.tcx.lang_items().clone_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().clone_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Clone)
-        } else if self.interner.tcx.lang_items().drop_trait().map(|t| def_id == t).unwrap_or(false)
-        {
+        } else if self.interner.tcx.lang_items().drop_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Drop)
-        } else if self.interner.tcx.lang_items().fn_trait().map(|t| def_id == t).unwrap_or(false) {
+        } else if self.interner.tcx.lang_items().fn_trait() == Some(def_id) {
             Some(chalk_solve::rust_ir::WellKnownTrait::Fn)
         } else if self
             .interner
index 836a4ff78c79e1705c48a0b8cd19a7466564cb61..7cb23dc05379503399de89b96a2b516f5ac61961 100644 (file)
@@ -164,7 +164,7 @@ pub fn check_match(
                     }
                     // If all the obligations hold (or there are no obligations) the tail expression
                     // we can suggest to return a boxed trait object instead of an opaque type.
-                    if suggest_box { self.ret_type_span.clone() } else { None }
+                    if suggest_box { self.ret_type_span } else { None }
                 }
                 _ => None,
             };
index 17364897bde13a75671d4c7f5ba33add21174ecf..59c366ad7d776cb41868bc18140e042f70ccab60 100644 (file)
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
-        Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
+        Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
+    }
+
+    /// Like `autoderef`, but provides a custom `Span` to use for calls to
+    /// an overloaded `Deref` operator
+    pub fn autoderef_overloaded_span(
+        &'a self,
+        span: Span,
+        base_ty: Ty<'tcx>,
+        overloaded_span: Span,
+    ) -> Autoderef<'a, 'tcx> {
+        Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
     }
 
     pub fn try_overloaded_deref(
@@ -44,7 +55,11 @@ pub fn adjust_steps_as_infer_ok(
                         |InferOk { value: method, obligations: o }| {
                             obligations.extend(o);
                             if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
-                                Some(OverloadedDeref { region, mutbl })
+                                Some(OverloadedDeref {
+                                    region,
+                                    mutbl,
+                                    span: autoderef.overloaded_span(),
+                                })
                             } else {
                                 None
                             }
index dba46f35dca925643b36c860a55d04473b409db7..d5563cdac02de090cdb78efc989e0dfc404e55c5 100644 (file)
@@ -1243,10 +1243,9 @@ fn check_expr_struct_fields(
         } else if check_completeness && !error_happened && !remaining_fields.is_empty() {
             let no_accessible_remaining_fields = remaining_fields
                 .iter()
-                .filter(|(_, (_, field))| {
+                .find(|(_, (_, field))| {
                     field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx)
                 })
-                .next()
                 .is_none();
 
             if no_accessible_remaining_fields {
index ae338cccf797791ab1e77e881f37d0f279557a17..fd2700b85e2790a7721e523f4e0a272880babb21 100644 (file)
@@ -137,7 +137,8 @@ fn adjust_self_ty(
     ) -> Ty<'tcx> {
         // Commit the autoderefs by calling `autoderef` again, but this
         // time writing the results into the various typeck results.
-        let mut autoderef = self.autoderef(self.span, unadjusted_self_ty);
+        let mut autoderef =
+            self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span);
         let (_, n) = match autoderef.nth(pick.autoderefs) {
             Some(n) => n,
             None => {
index ebe71b86c9221f52de120bd9adfa3a01024fe2b2..8a62031ec887caed2885f04f843ec053dfcc8701 100644 (file)
@@ -446,9 +446,10 @@ fn method_autoderef_steps<'tcx>(
     tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &goal, |ref infcx, goal, inference_vars| {
         let ParamEnvAnd { param_env, value: self_ty } = goal;
 
-        let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty)
-            .include_raw_pointers()
-            .silence_errors();
+        let mut autoderef =
+            Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP)
+                .include_raw_pointers()
+                .silence_errors();
         let mut reached_raw_pointer = false;
         let mut steps: Vec<_> = autoderef
             .by_ref()
index 6be2fdf9f19047c0cd8c9580c317ec159bc7ebef..54b0671fab5a7f1f9b927ce3b441dbb283a527b2 100644 (file)
@@ -1141,10 +1141,9 @@ fn check_struct_pat_fields(
         } else if !etc && !unmentioned_fields.is_empty() {
             let no_accessible_unmentioned_fields = unmentioned_fields
                 .iter()
-                .filter(|(field, _)| {
+                .find(|(field, _)| {
                     field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
                 })
-                .next()
                 .is_none();
 
             if no_accessible_unmentioned_fields {
index aed2af20e5271f192dea23e913402bb52bc9c3f2..502cb562385e0de9432f10d4ab88b95ff4e51955 100644 (file)
@@ -242,7 +242,7 @@ pub fn convert_place_derefs_to_mutable(&self, expr: &hir::Expr<'_>) {
                         ) {
                             let method = self.register_infer_ok_obligations(ok);
                             if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
-                                *deref = OverloadedDeref { region, mutbl };
+                                *deref = OverloadedDeref { region, mutbl, span: deref.span };
                             }
                             // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
                             // This helps avoid accidental drops.
index 9135843045a2b465aa8f13300e7c95981da826f0..99e6f9dceb41c8de420983db2d795980d27c575b 100644 (file)
 # General build configuration options
 # =============================================================================
 [build]
+# The default stage to use for the `doc` subcommand
+#doc-stage = 0
+
+# The default stage to use for the `build` subcommand
+#build-stage = 1
+
+# The default stage to use for the `test` subcommand
+#test-stage = 1
+
+# The default stage to use for the `dist` subcommand
+#dist-stage = 2
+
+# The default stage to use for the `install` subcommand
+#install-stage = 2
+
+# The default stage to use for the `bench` subcommand
+#bench-stage = 2
 
 # Build triple for the original snapshot compiler. This must be a compiler that
 # nightlies are already produced for. The current platform must be able to run
index 40aa4d850f59ddc0798b156ae97f67a8e5c6a006..24d17fdd880ba8bc9585f93ce7c4e08dbaf7b59e 100644 (file)
@@ -1343,6 +1343,10 @@ fn from(vec: Vec<T>) -> BinaryHeap<T> {
 
 #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
 impl<T> From<BinaryHeap<T>> for Vec<T> {
+    /// Converts a `BinaryHeap<T>` into a `Vec<T>`.
+    ///
+    /// This conversion requires no data movement or allocation, and has
+    /// constant time complexity.
     fn from(heap: BinaryHeap<T>) -> Vec<T> {
         heap.data
     }
index 253a3e9f2bea91e130c29c3a5ca49d51dc861240..65cfe9a9b49965c3b1576952c64f977c312b0ca4 100644 (file)
@@ -1089,11 +1089,7 @@ fn range_tail_head<R>(&self, range: R) -> (usize, usize)
     where
         R: RangeBounds<usize>,
     {
-        // SAFETY: This buffer is only used to check the range. It might be partially
-        // uninitialized, but `check_range` needs a contiguous slice.
-        // https://github.com/rust-lang/rust/pull/75207#discussion_r471193682
-        let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) };
-        let Range { start, end } = buffer.check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         let tail = self.wrap_add(self.tail, start);
         let head = self.wrap_add(self.tail, end);
         (tail, head)
index 5774ebb9b195ab5c0c66c91da96d458f007051e2..7881c101f9f60f496f1b6f62b525c7cb330a2a2b 100644 (file)
@@ -76,6 +76,7 @@
 #![cfg_attr(test, feature(test))]
 #![feature(allocator_api)]
 #![feature(array_chunks)]
+#![feature(array_windows)]
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
index 677bfdd2349ec4c17f2a492a93408b0db0913cfa..79403cf86873ed28c13cb3a9f19b9892ed669c8f 100644 (file)
 use crate::boxed::Box;
 use crate::vec::Vec;
 
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub use core::slice::check_range;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunks;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunksMut;
+#[unstable(feature = "array_windows", issue = "75027")]
+pub use core::slice::ArrayWindows;
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use core::slice::SliceIndex;
 #[stable(feature = "from_ref", since = "1.28.0")]
index e1724bf3c9a90ce4c67f688784de874384ce1fff..2b0ce5ede56308b1a907def495bc12d5215b0d27 100644 (file)
@@ -49,6 +49,7 @@
 use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
 use core::ptr;
+use core::slice;
 use core::str::{lossy, pattern::Pattern};
 
 use crate::borrow::{Cow, ToOwned};
@@ -1506,7 +1507,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<'_>
         // of the vector version. The data is just plain bytes.
         // Because the range removal happens in Drop, if the Drain iterator is leaked,
         // the removal will not happen.
-        let Range { start, end } = self.as_bytes().check_range(range);
+        let Range { start, end } = slice::check_range(self.len(), range);
         assert!(self.is_char_boundary(start));
         assert!(self.is_char_boundary(end));
 
index cb4c1c20abcf6a7426597ef385c856f525e0261f..9dbea0dc9e68b9296d8d2dbdaebdb48635cb07d4 100644 (file)
 ///
 /// // ... and that's all!
 /// // you can also do it like this:
-/// let x : &[usize] = &v;
+/// let u: &[usize] = &v;
+/// // or like this:
+/// let u: &[_] = &v;
 /// ```
 ///
 /// In Rust, it's more common to pass slices as arguments rather than vectors
@@ -1310,7 +1312,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
         // the hole, and the vector length is restored to the new length.
         //
         let len = self.len();
-        let Range { start, end } = self.check_range(range);
+        let Range { start, end } = slice::check_range(len, range);
 
         unsafe {
             // set self.vec length's to start, to be safe in case Drain is leaked
@@ -3037,6 +3039,7 @@ fn as_into_iter(&mut self) -> &mut IntoIter<Self::Item> {
 /// A draining iterator for `Vec<T>`.
 ///
 /// This `struct` is created by [`Vec::drain`].
+/// See its documentation for more.
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, T: 'a> {
     /// Index of tail to preserve
index 590639d983481bdc0b3f0518ff820941d5fbf0cc..03737e1ef1f4dcd4d8be3439edffbd365ea8741f 100644 (file)
@@ -15,6 +15,7 @@
 #![feature(slice_ptr_get)]
 #![feature(split_inclusive)]
 #![feature(binary_heap_retain)]
+#![feature(deque_range)]
 #![feature(inplace_iteration)]
 #![feature(iter_map_while)]
 
index b20cf076aca3cac5dacea42cfc143ea5525b93fd..ed8ee2d8823c022449bdbf27caf8b4269fc140df 100644 (file)
@@ -1921,3 +1921,24 @@ fn foo<'a, P>(p: P)
 
     foo::<&str>("x");
 }
+
+#[test]
+fn test_str_multiline() {
+    let a: String = "this \
+is a test"
+        .to_string();
+    let b: String = "this \
+              is \
+              another \
+              test"
+        .to_string();
+    assert_eq!(a, "this is a test".to_string());
+    assert_eq!(b, "this is another test".to_string());
+}
+
+#[test]
+fn test_str_escapes() {
+    let x = "\\\\\
+    ";
+    assert_eq!(x, r"\\"); // extraneous whitespace stripped
+}
index f7f78046d089b09479a2c7067c06e7de70115d76..4e6043541226f77310e96628c9b23a7a5026354e 100644 (file)
@@ -1,6 +1,7 @@
 use std::borrow::Cow;
 use std::collections::TryReserveError::*;
 use std::mem::size_of;
+use std::ops::Bound::*;
 
 pub trait IntoCow<'a, B: ?Sized>
 where
@@ -271,8 +272,8 @@ fn test_split_off_past_end() {
 #[test]
 #[should_panic]
 fn test_split_off_mid_char() {
-    let mut orig = String::from("å±±");
-    let _ = orig.split_off(1);
+    let mut shan = String::from("å±±");
+    let _broken_mountain = shan.split_off(1);
 }
 
 #[test]
@@ -467,6 +468,20 @@ fn test_drain() {
     assert_eq!(t, "");
 }
 
+#[test]
+#[should_panic]
+fn test_drain_start_overflow() {
+    let mut s = String::from("abc");
+    s.drain((Excluded(usize::MAX), Included(0)));
+}
+
+#[test]
+#[should_panic]
+fn test_drain_end_overflow() {
+    let mut s = String::from("abc");
+    s.drain((Included(0), Included(usize::MAX)));
+}
+
 #[test]
 fn test_replace_range() {
     let mut s = "Hello, world!".to_owned();
@@ -504,6 +519,20 @@ fn test_replace_range_inclusive_out_of_bounds() {
     s.replace_range(5..=5, "789");
 }
 
+#[test]
+#[should_panic]
+fn test_replace_range_start_overflow() {
+    let mut s = String::from("123");
+    s.replace_range((Excluded(usize::MAX), Included(0)), "");
+}
+
+#[test]
+#[should_panic]
+fn test_replace_range_end_overflow() {
+    let mut s = String::from("456");
+    s.replace_range((Included(0), Included(usize::MAX)), "");
+}
+
 #[test]
 fn test_replace_range_empty() {
     let mut s = String::from("12345");
index 608a3c9bdf7624627dae134ee7d07f5c981a29ef..368ca4c543219a50d0d8e8a601185eeea7d4c5da 100644 (file)
@@ -3,6 +3,7 @@
 use std::fmt::Debug;
 use std::iter::InPlaceIterable;
 use std::mem::size_of;
+use std::ops::Bound::*;
 use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::rc::Rc;
 use std::vec::{Drain, IntoIter};
@@ -645,6 +646,16 @@ fn test_drain_max_vec_size() {
     assert_eq!(v.len(), usize::MAX - 1);
 }
 
+#[test]
+#[should_panic]
+fn test_drain_index_overflow() {
+    let mut v = Vec::<()>::with_capacity(usize::MAX);
+    unsafe {
+        v.set_len(usize::MAX);
+    }
+    v.drain(0..=usize::MAX);
+}
+
 #[test]
 #[should_panic]
 fn test_drain_inclusive_out_of_bounds() {
@@ -652,6 +663,20 @@ fn test_drain_inclusive_out_of_bounds() {
     v.drain(5..=5);
 }
 
+#[test]
+#[should_panic]
+fn test_drain_start_overflow() {
+    let mut v = vec![1, 2, 3];
+    v.drain((Excluded(usize::MAX), Included(0)));
+}
+
+#[test]
+#[should_panic]
+fn test_drain_end_overflow() {
+    let mut v = vec![1, 2, 3];
+    v.drain((Included(0), Included(usize::MAX)));
+}
+
 #[test]
 fn test_drain_leak() {
     static mut DROPS: i32 = 0;
@@ -894,7 +919,7 @@ fn test_from_iter_partially_drained_in_place_specialization() {
 #[test]
 fn test_from_iter_specialization_with_iterator_adapters() {
     fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
-    let src: Vec<usize> = vec![0usize; 65535];
+    let src: Vec<usize> = vec![0usize; 256];
     let srcptr = src.as_ptr();
     let iter = src
         .into_iter()
index 762dc4be44d6208950d4bd03e2fba8de66c45fcc..46d8a3c4cb4931126d578fd51d675e3f8758ff79 100644 (file)
@@ -2,6 +2,7 @@
 use std::collections::{vec_deque::Drain, VecDeque};
 use std::fmt::Debug;
 use std::mem::size_of;
+use std::ops::Bound::*;
 use std::panic::{catch_unwind, AssertUnwindSafe};
 
 use crate::hash;
@@ -115,6 +116,20 @@ fn test_index_out_of_bounds() {
     deq[3];
 }
 
+#[test]
+#[should_panic]
+fn test_range_start_overflow() {
+    let deq = VecDeque::from(vec![1, 2, 3]);
+    deq.range((Included(0), Included(usize::MAX)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_end_overflow() {
+    let deq = VecDeque::from(vec![1, 2, 3]);
+    deq.range((Excluded(usize::MAX), Included(0)));
+}
+
 #[derive(Clone, PartialEq, Debug)]
 enum Taggy {
     One(i32),
index 3953c73319fe419e5b33d735e68020a2cad20c85..dde442aa7b52de84c2a3810c6627c70fb99f6295 100644 (file)
@@ -356,8 +356,9 @@ impl Ordering {
     /// ```
     #[inline]
     #[must_use]
+    #[rustc_const_stable(feature = "const_ordering", since = "1.48.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn reverse(self) -> Ordering {
+    pub const fn reverse(self) -> Ordering {
         match self {
             Less => Greater,
             Equal => Equal,
@@ -394,8 +395,9 @@ pub fn reverse(self) -> Ordering {
     /// ```
     #[inline]
     #[must_use]
+    #[rustc_const_stable(feature = "const_ordering", since = "1.48.0")]
     #[stable(feature = "ordering_chaining", since = "1.17.0")]
-    pub fn then(self, other: Ordering) -> Ordering {
+    pub const fn then(self, other: Ordering) -> Ordering {
         match self {
             Equal => other,
             _ => self,
index d40a3802867624dd8d3dcd425ff2eaf3662f7956..1192b9e164a1450efb5ec71bf4bf59798f5649dd 100644 (file)
@@ -111,7 +111,7 @@ pub fn spin_loop() {
 #[inline]
 #[unstable(feature = "test", issue = "50297")]
 #[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
-pub fn black_box<T>(dummy: T) -> T {
+pub fn black_box<T>(mut dummy: T) -> T {
     // We need to "use" the argument in some way LLVM can't introspect, and on
     // targets that support it we can typically leverage inline assembly to do
     // this. LLVM's interpretation of inline assembly is that it's, well, a black
@@ -121,7 +121,8 @@ pub fn black_box<T>(dummy: T) -> T {
     #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
     // SAFETY: the inline assembly is a no-op.
     unsafe {
-        llvm_asm!("" : : "r"(&dummy));
+        // FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
+        llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
     }
 
     dummy
index 4202e52448dcfc358a865fb4cb9fe58d404a870e..ddb1aaebc1f3ecd3fd1869e9360badc273fe4845 100644 (file)
@@ -7,11 +7,8 @@
 /// An iterator that maps each element to an iterator, and yields the elements
 /// of the produced iterators.
 ///
-/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
-/// documentation for more.
-///
-/// [`flat_map`]: trait.Iterator.html#method.flat_map
-/// [`Iterator`]: trait.Iterator.html
+/// This `struct` is created by [`Iterator::flat_map`]. See its documentation
+/// for more.
 #[must_use = "iterators are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct FlatMap<I, U: IntoIterator, F> {
index 6d8ed2f4ffb1a158e9e62f845259d185e57f11d5..aa1b5529df22247a777697edb846a25c2f5194de 100644 (file)
 /// forever in an unreachable state. However, it does not guarantee that pointers
 /// to this memory will remain valid.
 ///
-/// * If you want to leak memory, see [`Box::leak`][leak].
-/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`][into_raw].
+/// * If you want to leak memory, see [`Box::leak`].
+/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`].
 /// * If you want to dispose of a value properly, running its destructor, see
-/// [`mem::drop`][drop].
+/// [`mem::drop`].
 ///
 /// # Safety
 ///
 /// ownership to `s` â€” the final step of interacting with `v` to dispose of it without
 /// running its destructor is entirely avoided.
 ///
-/// [drop]: fn.drop.html
-/// [uninit]: fn.uninitialized.html
-/// [clone]: ../clone/trait.Clone.html
-/// [swap]: fn.swap.html
-/// [box]: ../../std/boxed/struct.Box.html
-/// [leak]: ../../std/boxed/struct.Box.html#method.leak
-/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
+/// [`Box`]: ../../std/boxed/struct.Box.html
+/// [`Box::leak`]: ../../std/boxed/struct.Box.html#method.leak
+/// [`Box::into_raw`]: ../../std/boxed/struct.Box.html#method.into_raw
+/// [`mem::drop`]: drop
 /// [ub]: ../../reference/behavior-considered-undefined.html
-/// [`ManuallyDrop`]: struct.ManuallyDrop.html
 #[inline]
 #[rustc_const_stable(feature = "const_forget", since = "1.46.0")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -152,8 +148,6 @@ pub const fn forget<T>(t: T) {
 ///
 /// This function is just a shim intended to be removed when the `unsized_locals` feature gets
 /// stabilized.
-///
-/// [`forget`]: fn.forget.html
 #[inline]
 #[unstable(feature = "forget_unsized", issue = "none")]
 pub fn forget_unsized<T: ?Sized>(t: T) {
@@ -301,7 +295,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) {
 /// assert_eq!(2, mem::size_of::<ExampleUnion>());
 /// ```
 ///
-/// [alignment]: ./fn.align_of.html
+/// [alignment]: align_of
 #[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
@@ -365,7 +359,6 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
 /// [slice]: ../../std/primitive.slice.html
 /// [trait object]: ../../book/ch17-02-trait-objects.html
 /// [extern type]: ../../unstable-book/language-features/extern-types.html
-/// [`size_of_val`]: ../../core/mem/fn.size_of_val.html
 ///
 /// # Examples
 ///
@@ -501,7 +494,6 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
 /// [slice]: ../../std/primitive.slice.html
 /// [trait object]: ../../book/ch17-02-trait-objects.html
 /// [extern type]: ../../unstable-book/language-features/extern-types.html
-/// [`align_of_val`]: ../../core/mem/fn.align_of_val.html
 ///
 /// # Examples
 ///
@@ -540,7 +532,7 @@ pub unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
 /// `needs_drop` explicitly. Types like [`HashMap`], on the other hand, have to drop
 /// values one at a time and should use this API.
 ///
-/// [`drop_in_place`]: ../ptr/fn.drop_in_place.html
+/// [`drop_in_place`]: crate::ptr::drop_in_place
 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
 ///
 /// # Examples
@@ -595,9 +587,9 @@ pub const fn needs_drop<T>() -> bool {
 /// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
 /// It is useful for FFI sometimes, but should generally be avoided.
 ///
-/// [zeroed]: union.MaybeUninit.html#method.zeroed
+/// [zeroed]: MaybeUninit::zeroed
 /// [ub]: ../../reference/behavior-considered-undefined.html
-/// [inv]: union.MaybeUninit.html#initialization-invariant
+/// [inv]: MaybeUninit#initialization-invariant
 ///
 /// # Examples
 ///
@@ -650,10 +642,10 @@ pub unsafe fn zeroed<T>() -> T {
 /// (Notice that the rules around uninitialized integers are not finalized yet, but
 /// until they are, it is advisable to avoid them.)
 ///
-/// [`MaybeUninit<T>`]: union.MaybeUninit.html
-/// [uninit]: union.MaybeUninit.html#method.uninit
-/// [assume_init]: union.MaybeUninit.html#method.assume_init
-/// [inv]: union.MaybeUninit.html#initialization-invariant
+/// [`MaybeUninit<T>`]: MaybeUninit
+/// [uninit]: MaybeUninit::uninit
+/// [assume_init]: MaybeUninit::assume_init
+/// [inv]: MaybeUninit#initialization-invariant
 #[inline(always)]
 #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -686,9 +678,6 @@ pub unsafe fn uninitialized<T>() -> T {
 /// assert_eq!(42, x);
 /// assert_eq!(5, y);
 /// ```
-///
-/// [`replace`]: fn.replace.html
-/// [`take`]: fn.take.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn swap<T>(x: &mut T, y: &mut T) {
@@ -754,10 +743,6 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 /// assert_eq!(buffer.get_and_reset(), vec![0, 1]);
 /// assert_eq!(buffer.buf.len(), 0);
 /// ```
-///
-/// [`Clone`]: ../../std/clone/trait.Clone.html
-/// [`replace`]: fn.replace.html
-/// [`swap`]: fn.swap.html
 #[inline]
 #[stable(feature = "mem_take", since = "1.40.0")]
 pub fn take<T: Default>(dest: &mut T) -> T {
@@ -822,10 +807,6 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 /// assert_eq!(buffer.replace_index(0, 2), 0);
 /// assert_eq!(buffer.buf[0], 2);
 /// ```
-///
-/// [`Clone`]: ../../std/clone/trait.Clone.html
-/// [`swap`]: fn.swap.html
-/// [`take`]: fn.take.html
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_use = "if you don't need the old value, you can just assign the new value directly"]
@@ -851,7 +832,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// Because `_x` is moved into the function, it is automatically dropped before
 /// the function returns.
 ///
-/// [drop]: ../ops/trait.Drop.html
+/// [drop]: Drop
 ///
 /// # Examples
 ///
@@ -894,8 +875,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// println!("x: {}, y: {}", x, y.0); // still available
 /// ```
 ///
-/// [`RefCell`]: ../../std/cell/struct.RefCell.html
-/// [`Copy`]: ../../std/marker/trait.Copy.html
+/// [`RefCell`]: crate::cell::RefCell
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn drop<T>(_x: T) {}
@@ -914,7 +894,6 @@ pub fn drop<T>(_x: T) {}
 /// `T`.
 ///
 /// [ub]: ../../reference/behavior-considered-undefined.html
-/// [size_of]: fn.size_of.html
 ///
 /// # Examples
 ///
@@ -960,8 +939,6 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
 /// Opaque type representing the discriminant of an enum.
 ///
 /// See the [`discriminant`] function in this module for more information.
-///
-/// [`discriminant`]: fn.discriminant.html
 #[stable(feature = "discriminant_value", since = "1.21.0")]
 pub struct Discriminant<T>(<T as DiscriminantKind>::Discriminant);
 
index aaeb4d8a22c297eee22fb9514d1fe85ee60e6ad6..a5fbdc6ee2d4802528349acde70af9ff94e994f3 100644 (file)
@@ -60,12 +60,19 @@ mod fpu_precision {
     fn set_cw(cw: u16) {
         // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
         // any `u16`
-        unsafe { llvm_asm!("fldcw $0" :: "m" (cw) :: "volatile") }
+        unsafe {
+            asm!(
+                "fldcw ({})",
+                in(reg) &cw,
+                // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
+                options(att_syntax, nostack),
+            )
+        }
     }
 
     /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`.
     pub fn set_precision<T>() -> FPUControlWord {
-        let cw = 0u16;
+        let mut cw = 0_u16;
 
         // Compute the value for the Precision Control field that is appropriate for `T`.
         let cw_precision = match size_of::<T>() {
@@ -78,7 +85,14 @@ pub fn set_precision<T>() -> FPUControlWord {
         // `FPUControlWord` structure is dropped
         // SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
         // any `u16`
-        unsafe { llvm_asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") }
+        unsafe {
+            asm!(
+                "fnstcw ({})",
+                in(reg) &mut cw,
+                // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
+                options(att_syntax, nostack),
+            )
+        }
 
         // Set the control word to the desired precision. This is achieved by masking away the old
         // precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above.
index ed6202bb82f0fc45e7c4a9605353f7436f2e7a13..6f3a3a867450db0d9e3cf6ee1e9c3127bed0cd22 100644 (file)
@@ -166,6 +166,16 @@ fn from_str(src: &str) -> Result<Self, ParseFloatError> {
 ///
 /// This error is used as the error type for the [`FromStr`] implementation
 /// for [`f32`] and [`f64`].
+///
+/// # Example
+///
+/// ```
+/// use std::str::FromStr;
+///
+/// if let Err(e) = f64::from_str("a.12") {
+///     println!("Failed conversion to f64: {}", e);
+/// }
+/// ```
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseFloatError {
index 2a936c1867da00e63c50e5a07429dba4b84986bd..050c187e55576b5009becf286bd3c3576b780322 100644 (file)
@@ -5286,6 +5286,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
 ///
 /// [`str.trim()`]: ../../std/primitive.str.html#method.trim
 /// [`i8::from_str_radix`]: ../../std/primitive.i8.html#method.from_str_radix
+///
+/// # Example
+///
+/// ```
+/// if let Err(e) = i32::from_str_radix("a12", 10) {
+///     println!("Failed conversion to i32: {}", e);
+/// }
+/// ```
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseIntError {
@@ -5293,6 +5301,18 @@ pub struct ParseIntError {
 }
 
 /// Enum to store the various types of errors that can cause parsing an integer to fail.
+///
+/// # Example
+///
+/// ```
+/// #![feature(int_error_matching)]
+///
+/// # fn main() {
+/// if let Err(e) = i32::from_str_radix("a12", 10) {
+///     println!("Failed conversion to i32: {:?}", e.kind());
+/// }
+/// # }
+/// ```
 #[unstable(
     feature = "int_error_matching",
     reason = "it can be useful to match errors when making error messages \
index d6c097eee17bf96ff18540667972043d8b1e86c8..245152e5490d8c5e87c35f1479463985d428cce4 100644 (file)
 pub trait Deref {
     /// The resulting type after dereferencing.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "deref_target"]
     type Target: ?Sized;
 
     /// Dereferences the value.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_diagnostic_item = "deref_method"]
     fn deref(&self) -> &Self::Target;
 }
 
index d67e0ae536d9f9bc52f0c1482a88b3f7d566d4f8..16fcb6231dc0981834e67af5d2a769f21421e746 100644 (file)
@@ -1,6 +1,6 @@
 //! Indexing implementations for `[T]`.
 
-use crate::ops;
+use crate::ops::{self, Bound, Range, RangeBounds};
 use crate::ptr;
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -62,6 +62,79 @@ pub(super) fn slice_end_index_overflow_fail() -> ! {
     panic!("attempted to index slice up to maximum usize");
 }
 
+/// Performs bounds-checking of the given range.
+/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
+/// for slices of the given length.
+///
+/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
+/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
+///
+/// # Panics
+///
+/// Panics if the range is out of bounds.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(slice_check_range)]
+/// use std::slice;
+///
+/// let v = [10, 40, 30];
+/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
+/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
+/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
+/// ```
+///
+/// Panics when [`Index::index`] would panic:
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 2..1);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..4);
+/// ```
+///
+/// ```should_panic
+/// #![feature(slice_check_range)]
+///
+/// std::slice::check_range(3, 1..=usize::MAX);
+/// ```
+///
+/// [`Index::index`]: ops::Index::index
+#[track_caller]
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
+    let start = match range.start_bound() {
+        Bound::Included(&start) => start,
+        Bound::Excluded(start) => {
+            start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
+        }
+        Bound::Unbounded => 0,
+    };
+
+    let end = match range.end_bound() {
+        Bound::Included(end) => {
+            end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
+        }
+        Bound::Excluded(&end) => end,
+        Bound::Unbounded => len,
+    };
+
+    if start > end {
+        slice_index_order_fail(start, end);
+    }
+    if end > len {
+        slice_end_index_len_fail(end, len);
+    }
+
+    Range { start, end }
+}
+
 mod private_slice_index {
     use super::ops;
     #[stable(feature = "slice_get_slice", since = "1.28.0")]
index 2e8c3cd43e99998f26b98805264a9c1561a34f79..84fa34c75e3a2ed3219d3daea51151bc34a946e0 100644 (file)
@@ -1687,6 +1687,106 @@ fn may_have_side_effect() -> bool {
     }
 }
 
+/// A windowed iterator over a slice in overlapping chunks (`N` elements at a
+/// time), starting at the beginning of the slice
+///
+/// This struct is created by the [`array_windows`] method on [slices].
+///
+/// [`array_windows`]: ../../std/primitive.slice.html#method.array_windows
+/// [slices]: ../../std/primitive.slice.html
+#[derive(Debug, Clone, Copy)]
+#[unstable(feature = "array_windows", issue = "75027")]
+pub struct ArrayWindows<'a, T: 'a, const N: usize> {
+    pub(crate) slice_head: *const T,
+    pub(crate) num: usize,
+    pub(crate) marker: marker::PhantomData<&'a [T; N]>,
+}
+
+#[unstable(feature = "array_windows", issue = "75027")]
+impl<'a, T, const N: usize> Iterator for ArrayWindows<'a, T, N> {
+    type Item = &'a [T; N];
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.num == 0 {
+            return None;
+        }
+        // SAFETY:
+        // This is safe because it's indexing into a slice guaranteed to be length > N.
+        let ret = unsafe { &*self.slice_head.cast::<[T; N]>() };
+        // SAFETY: Guaranteed that there are at least 1 item remaining otherwise
+        // earlier branch would've been hit
+        self.slice_head = unsafe { self.slice_head.add(1) };
+
+        self.num -= 1;
+        Some(ret)
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.num, Some(self.num))
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.num
+    }
+
+    #[inline]
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        if self.num <= n {
+            self.num = 0;
+            return None;
+        }
+        // SAFETY:
+        // This is safe because it's indexing into a slice guaranteed to be length > N.
+        let ret = unsafe { &*self.slice_head.add(n).cast::<[T; N]>() };
+        // SAFETY: Guaranteed that there are at least n items remaining
+        self.slice_head = unsafe { self.slice_head.add(n + 1) };
+
+        self.num -= n + 1;
+        Some(ret)
+    }
+
+    #[inline]
+    fn last(mut self) -> Option<Self::Item> {
+        self.nth(self.num.checked_sub(1)?)
+    }
+}
+
+#[unstable(feature = "array_windows", issue = "75027")]
+impl<'a, T, const N: usize> DoubleEndedIterator for ArrayWindows<'a, T, N> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a [T; N]> {
+        if self.num == 0 {
+            return None;
+        }
+        // SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
+        let ret = unsafe { &*self.slice_head.add(self.num - 1).cast::<[T; N]>() };
+        self.num -= 1;
+        Some(ret)
+    }
+
+    #[inline]
+    fn nth_back(&mut self, n: usize) -> Option<&'a [T; N]> {
+        if self.num <= n {
+            self.num = 0;
+            return None;
+        }
+        // SAFETY: Guaranteed that there are n items remaining, n-1 for 0-indexing.
+        let ret = unsafe { &*self.slice_head.add(self.num - (n + 1)).cast::<[T; N]>() };
+        self.num -= n + 1;
+        Some(ret)
+    }
+}
+
+#[unstable(feature = "array_windows", issue = "75027")]
+impl<T, const N: usize> ExactSizeIterator for ArrayWindows<'_, T, N> {
+    fn is_empty(&self) -> bool {
+        self.num == 0
+    }
+}
+
 /// An iterator over a slice in (non-overlapping) chunks (`N` elements at a
 /// time), starting at the beginning of the slice.
 ///
index 64a707c39f07670930d16c91c948f6fff44a7724..8e9d1eb98a86b08130ea21fc972cf63d719c8f73 100644 (file)
@@ -12,7 +12,7 @@
 use crate::intrinsics::assume;
 use crate::marker::{self, Copy};
 use crate::mem;
-use crate::ops::{Bound, FnMut, Range, RangeBounds};
+use crate::ops::{FnMut, Range, RangeBounds};
 use crate::option::Option;
 use crate::option::Option::{None, Some};
 use crate::ptr::{self, NonNull};
@@ -56,6 +56,9 @@
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use iter::{ArrayChunks, ArrayChunksMut};
 
+#[unstable(feature = "array_windows", issue = "75027")]
+pub use iter::ArrayWindows;
+
 #[unstable(feature = "split_inclusive", issue = "72360")]
 pub use iter::{SplitInclusive, SplitInclusiveMut};
 
@@ -72,8 +75,8 @@
 #[stable(feature = "slice_get_slice", since = "1.28.0")]
 pub use index::SliceIndex;
 
-use index::{slice_end_index_len_fail, slice_index_order_fail};
-use index::{slice_end_index_overflow_fail, slice_start_index_overflow_fail};
+#[unstable(feature = "slice_check_range", issue = "76393")]
+pub use index::check_range;
 
 #[lang = "slice"]
 #[cfg(not(test))]
@@ -378,79 +381,6 @@ pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
         unsafe { &mut *index.get_unchecked_mut(self) }
     }
 
-    /// Converts a range over this slice to [`Range`].
-    ///
-    /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
-    ///
-    /// [`get_unchecked`]: #method.get_unchecked
-    /// [`get_unchecked_mut`]: #method.get_unchecked_mut
-    ///
-    /// # Panics
-    ///
-    /// Panics if the range is out of bounds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(slice_check_range)]
-    ///
-    /// let v = [10, 40, 30];
-    /// assert_eq!(1..2, v.check_range(1..2));
-    /// assert_eq!(0..2, v.check_range(..2));
-    /// assert_eq!(1..3, v.check_range(1..));
-    /// ```
-    ///
-    /// Panics when [`Index::index`] would panic:
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(2..1);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..4);
-    /// ```
-    ///
-    /// ```should_panic
-    /// #![feature(slice_check_range)]
-    ///
-    /// [10, 40, 30].check_range(1..=usize::MAX);
-    /// ```
-    ///
-    /// [`Index::index`]: crate::ops::Index::index
-    #[track_caller]
-    #[unstable(feature = "slice_check_range", issue = "76393")]
-    pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
-        let start = match range.start_bound() {
-            Bound::Included(&start) => start,
-            Bound::Excluded(start) => {
-                start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
-            }
-            Bound::Unbounded => 0,
-        };
-
-        let len = self.len();
-        let end = match range.end_bound() {
-            Bound::Included(end) => {
-                end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
-            }
-            Bound::Excluded(&end) => end,
-            Bound::Unbounded => len,
-        };
-
-        if start > end {
-            slice_index_order_fail(start, end);
-        }
-        if end > len {
-            slice_end_index_len_fail(end, len);
-        }
-
-        Range { start, end }
-    }
-
     /// Returns a raw pointer to the slice's buffer.
     ///
     /// The caller must ensure that the slice outlives the pointer this
@@ -1099,6 +1029,40 @@ pub fn array_chunks_mut<const N: usize>(&mut self) -> ArrayChunksMut<'_, T, N> {
         }
     }
 
+    /// Returns an iterator over overlapping windows of `N` elements of  a slice,
+    /// starting at the beginning of the slice.
+    ///
+    /// This is the const generic equivalent of [`windows`].
+    ///
+    /// If `N` is smaller than the size of the array, it will return no windows.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `N` is 0. This check will most probably get changed to a compile time
+    /// error before this method gets stabilized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(array_windows)]
+    /// let slice = [0, 1, 2, 3];
+    /// let mut iter = slice.array_windows();
+    /// assert_eq!(iter.next().unwrap(), &[0, 1]);
+    /// assert_eq!(iter.next().unwrap(), &[1, 2]);
+    /// assert_eq!(iter.next().unwrap(), &[2, 3]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// [`windows`]: #method.windows
+    #[unstable(feature = "array_windows", issue = "75027")]
+    #[inline]
+    pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
+        assert_ne!(N, 0);
+
+        let num_windows = self.len().saturating_sub(N - 1);
+        ArrayWindows { slice_head: self.as_ptr(), num: num_windows, marker: marker::PhantomData }
+    }
+
     /// Returns an iterator over `chunk_size` elements of the slice at a time, starting at the end
     /// of the slice.
     ///
@@ -2794,7 +2758,7 @@ pub fn copy_within<R: RangeBounds<usize>>(&mut self, src: R, dest: usize)
     where
         T: Copy,
     {
-        let Range { start: src_start, end: src_end } = self.check_range(src);
+        let Range { start: src_start, end: src_end } = check_range(self.len(), src);
         let count = src_end - src_start;
         assert!(dest <= self.len() - count, "dest is out of bounds");
         // SAFETY: the conditions for `ptr::copy` have all been checked above,
index 9383e7c45fa55b6c29b1ebd56346842b4b844b09..4e987a53b2cb236f12fd3618c80c579431bc56b5 100644 (file)
@@ -112,6 +112,14 @@ pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
 
 #[stable(feature = "futures_api", since = "1.36.0")]
 impl<T> From<T> for Poll<T> {
+    /// Convert to a `Ready` variant.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use core::task::Poll;
+    /// assert_eq!(Poll::from(true), Poll::Ready(true));
+    /// ```
     fn from(t: T) -> Poll<T> {
         Poll::Ready(t)
     }
index f39781788d7c04e09a5da36744a9ab77e5b37553..6dc542dee58e65ff280a4c0b343aaea322457413 100644 (file)
@@ -693,7 +693,8 @@ pub const fn as_secs_f32(&self) -> f32 {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn from_secs_f64(secs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn from_secs_f64(secs: f64) -> Duration {
         const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64;
         let nanos = secs * (NANOS_PER_SEC as f64);
         if !nanos.is_finite() {
@@ -727,7 +728,8 @@ pub fn from_secs_f64(secs: f64) -> Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn from_secs_f32(secs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn from_secs_f32(secs: f32) -> Duration {
         const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32;
         let nanos = secs * (NANOS_PER_SEC as f32);
         if !nanos.is_finite() {
@@ -761,7 +763,8 @@ pub fn from_secs_f32(secs: f32) -> Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn mul_f64(self, rhs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn mul_f64(self, rhs: f64) -> Duration {
         Duration::from_secs_f64(rhs * self.as_secs_f64())
     }
 
@@ -782,7 +785,8 @@ pub fn mul_f64(self, rhs: f64) -> Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn mul_f32(self, rhs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn mul_f32(self, rhs: f32) -> Duration {
         Duration::from_secs_f32(rhs * self.as_secs_f32())
     }
 
@@ -802,7 +806,8 @@ pub fn mul_f32(self, rhs: f32) -> Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn div_f64(self, rhs: f64) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn div_f64(self, rhs: f64) -> Duration {
         Duration::from_secs_f64(self.as_secs_f64() / rhs)
     }
 
@@ -824,7 +829,8 @@ pub fn div_f64(self, rhs: f64) -> Duration {
     /// ```
     #[stable(feature = "duration_float", since = "1.38.0")]
     #[inline]
-    pub fn div_f32(self, rhs: f32) -> Duration {
+    #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
+    pub const fn div_f32(self, rhs: f32) -> Duration {
         Duration::from_secs_f32(self.as_secs_f32() / rhs)
     }
 
index 4086917780fa4ae46ac17834567e5e34f6571fab..835289daf715adf936723f10b62f145248491640 100644 (file)
@@ -1,4 +1,7 @@
-use core::cmp::{self, Ordering::*};
+use core::cmp::{
+    self,
+    Ordering::{self, *},
+};
 
 #[test]
 fn test_int_totalord() {
@@ -116,3 +119,16 @@ fn eq(&self, other: &SketchyNum) -> bool {
     assert!(SketchyNum { num: 37 } == SketchyNum { num: 34 });
     assert!(SketchyNum { num: 25 } != SketchyNum { num: 57 });
 }
+
+#[test]
+fn ordering_const() {
+    // test that the methods of `Ordering` are usable in a const context
+
+    const ORDERING: Ordering = Greater;
+
+    const REVERSE: Ordering = ORDERING.reverse();
+    assert_eq!(REVERSE, Less);
+
+    const THEN: Ordering = Equal.then(ORDERING);
+    assert_eq!(THEN, Greater);
+}
index a2e294ace1860f2226350fb80c1df9fd2c647e82..a5b1b51e06c64ebea26e19a3d3b54a486d7579ac 100644 (file)
@@ -2,6 +2,7 @@
 #![feature(array_chunks)]
 #![feature(array_methods)]
 #![feature(array_map)]
+#![feature(array_windows)]
 #![feature(bool_to_option)]
 #![feature(bound_cloned)]
 #![feature(box_syntax)]
 #![feature(core_private_diy_float)]
 #![feature(debug_non_exhaustive)]
 #![feature(dec2flt)]
+#![feature(div_duration)]
+#![feature(duration_consts_2)]
 #![feature(duration_constants)]
 #![feature(duration_saturating_ops)]
+#![feature(duration_zero)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
 #![feature(flt2dec)]
index 39250ee84bce6d1f28485c052048f7d316205586..4acc760ffac9907e0d22509c140a679a82009572 100644 (file)
@@ -1 +1,30 @@
 int_module!(i32, i32);
+
+#[test]
+fn test_arith_operation() {
+    let a: isize = 10;
+    assert_eq!(a * (a - 1), 90);
+    let i32_a: isize = 10;
+    assert_eq!(i32_a, 10);
+    assert_eq!(i32_a - 10, 0);
+    assert_eq!(i32_a / 10, 1);
+    assert_eq!(i32_a - 20, -10);
+    assert_eq!(i32_a << 10, 10240);
+    assert_eq!(i32_a << 16, 655360);
+    assert_eq!(i32_a * 16, 160);
+    assert_eq!(i32_a * i32_a * i32_a, 1000);
+    assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000);
+    assert_eq!(i32_a * i32_a / i32_a * i32_a, 100);
+    assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640);
+    let i32_b: isize = 0x10101010;
+    assert_eq!(i32_b + 1 - 1, i32_b);
+    assert_eq!(i32_b << 1, i32_b << 1);
+    assert_eq!(i32_b >> 1, i32_b >> 1);
+    assert_eq!(i32_b & i32_b << 1, 0);
+    assert_eq!(i32_b | i32_b << 1, 0x30303030);
+    let i32_c: isize = 0x10101010;
+    assert_eq!(
+        i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3),
+        i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3)
+    );
+}
index 9b31e532a6a9fc2f6d8f41d7f070faf0757c2463..9556d43f9d78b3e9864ca1a6d78d4479ff7fb318 100644 (file)
@@ -657,6 +657,55 @@ fn test_array_chunks_mut_zip() {
     assert_eq!(v1, [13, 14, 19, 20, 4]);
 }
 
+#[test]
+fn test_array_windows_infer() {
+    let v: &[i32] = &[0, 1, 0, 1];
+    assert_eq!(v.array_windows::<2>().count(), 3);
+    let c = v.array_windows();
+    for &[a, b] in c {
+        assert_eq!(a + b, 1);
+    }
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
+    let total = v2.array_windows().map(|&[a, b, c]| a + b + c).sum::<i32>();
+    assert_eq!(total, 3 + 6 + 9 + 12 + 15);
+}
+
+#[test]
+fn test_array_windows_count() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let c = v.array_windows::<3>();
+    assert_eq!(c.count(), 4);
+
+    let v2: &[i32] = &[0, 1, 2, 3, 4];
+    let c2 = v2.array_windows::<6>();
+    assert_eq!(c2.count(), 0);
+
+    let v3: &[i32] = &[];
+    let c3 = v3.array_windows::<2>();
+    assert_eq!(c3.count(), 0);
+}
+
+#[test]
+fn test_array_windows_nth() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let snd = v.array_windows::<4>().nth(1);
+    assert_eq!(snd, Some(&[1, 2, 3, 4]));
+    let mut arr_windows = v.array_windows::<2>();
+    assert_ne!(arr_windows.nth(0), arr_windows.nth(0));
+    let last = v.array_windows::<3>().last();
+    assert_eq!(last, Some(&[3, 4, 5]));
+}
+
+#[test]
+fn test_array_windows_nth_back() {
+    let v: &[i32] = &[0, 1, 2, 3, 4, 5];
+    let snd = v.array_windows::<4>().nth_back(1);
+    assert_eq!(snd, Some(&[1, 2, 3, 4]));
+    let mut arr_windows = v.array_windows::<2>();
+    assert_ne!(arr_windows.nth_back(0), arr_windows.nth_back(0));
+}
+
 #[test]
 fn test_rchunks_count() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
index 4f90eb63b0472393c2d8e7beeaef66b9f56d0cdb..7c43885040b3e3fde6fdad5eca2dca12eb6d2189 100644 (file)
@@ -321,3 +321,104 @@ fn debug_formatting_precision_high() {
     assert_eq!(format!("{:.10?}", Duration::new(4, 001_000_000)), "4.0010000000s");
     assert_eq!(format!("{:.20?}", Duration::new(4, 001_000_000)), "4.00100000000000000000s");
 }
+
+#[test]
+fn duration_const() {
+    // test that the methods of `Duration` are usable in a const context
+
+    const DURATION: Duration = Duration::new(0, 123_456_789);
+
+    const SUB_SEC_MILLIS: u32 = DURATION.subsec_millis();
+    assert_eq!(SUB_SEC_MILLIS, 123);
+
+    const SUB_SEC_MICROS: u32 = DURATION.subsec_micros();
+    assert_eq!(SUB_SEC_MICROS, 123_456);
+
+    const SUB_SEC_NANOS: u32 = DURATION.subsec_nanos();
+    assert_eq!(SUB_SEC_NANOS, 123_456_789);
+
+    const ZERO: Duration = Duration::zero();
+    assert_eq!(ZERO, Duration::new(0, 0));
+
+    const IS_ZERO: bool = ZERO.is_zero();
+    assert!(IS_ZERO);
+
+    const ONE: Duration = Duration::new(1, 0);
+
+    const SECONDS: u64 = ONE.as_secs();
+    assert_eq!(SECONDS, 1);
+
+    const FROM_SECONDS: Duration = Duration::from_secs(1);
+    assert_eq!(FROM_SECONDS, ONE);
+
+    const SECONDS_F32: f32 = ONE.as_secs_f32();
+    assert_eq!(SECONDS_F32, 1.0);
+
+    const FROM_SECONDS_F32: Duration = Duration::from_secs_f32(1.0);
+    assert_eq!(FROM_SECONDS_F32, ONE);
+
+    const SECONDS_F64: f64 = ONE.as_secs_f64();
+    assert_eq!(SECONDS_F64, 1.0);
+
+    const FROM_SECONDS_F64: Duration = Duration::from_secs_f64(1.0);
+    assert_eq!(FROM_SECONDS_F64, ONE);
+
+    const MILLIS: u128 = ONE.as_millis();
+    assert_eq!(MILLIS, 1_000);
+
+    const FROM_MILLIS: Duration = Duration::from_millis(1_000);
+    assert_eq!(FROM_MILLIS, ONE);
+
+    const MICROS: u128 = ONE.as_micros();
+    assert_eq!(MICROS, 1_000_000);
+
+    const FROM_MICROS: Duration = Duration::from_micros(1_000_000);
+    assert_eq!(FROM_MICROS, ONE);
+
+    const NANOS: u128 = ONE.as_nanos();
+    assert_eq!(NANOS, 1_000_000_000);
+
+    const FROM_NANOS: Duration = Duration::from_nanos(1_000_000_000);
+    assert_eq!(FROM_NANOS, ONE);
+
+    const MAX: Duration = Duration::new(u64::MAX, 999_999_999);
+
+    const CHECKED_ADD: Option<Duration> = MAX.checked_add(ONE);
+    assert_eq!(CHECKED_ADD, None);
+
+    const CHECKED_SUB: Option<Duration> = ZERO.checked_sub(ONE);
+    assert_eq!(CHECKED_SUB, None);
+
+    const CHECKED_MUL: Option<Duration> = ONE.checked_mul(1);
+    assert_eq!(CHECKED_MUL, Some(ONE));
+
+    const MUL_F32: Duration = ONE.mul_f32(1.0);
+    assert_eq!(MUL_F32, ONE);
+
+    const MUL_F64: Duration = ONE.mul_f64(1.0);
+    assert_eq!(MUL_F64, ONE);
+
+    const CHECKED_DIV: Option<Duration> = ONE.checked_div(1);
+    assert_eq!(CHECKED_DIV, Some(ONE));
+
+    const DIV_F32: Duration = ONE.div_f32(1.0);
+    assert_eq!(DIV_F32, ONE);
+
+    const DIV_F64: Duration = ONE.div_f64(1.0);
+    assert_eq!(DIV_F64, ONE);
+
+    const DIV_DURATION_F32: f32 = ONE.div_duration_f32(ONE);
+    assert_eq!(DIV_DURATION_F32, 1.0);
+
+    const DIV_DURATION_F64: f64 = ONE.div_duration_f64(ONE);
+    assert_eq!(DIV_DURATION_F64, 1.0);
+
+    const SATURATING_ADD: Duration = MAX.saturating_add(ONE);
+    assert_eq!(SATURATING_ADD, MAX);
+
+    const SATURATING_SUB: Duration = ZERO.saturating_sub(ONE);
+    assert_eq!(SATURATING_SUB, ZERO);
+
+    const SATURATING_MUL: Duration = MAX.saturating_mul(2);
+    assert_eq!(SATURATING_MUL, MAX);
+}
index d1960a049d9062cb01e32b642b2a88e66cfda7fb..00e2dbc9c1dbf33e5d3c7c94c36edf4b6635f762 100644 (file)
@@ -95,6 +95,7 @@
 //! [`Read`]: io::Read
 
 #![stable(feature = "process", since = "1.0.0")]
+#![deny(unsafe_op_in_unsafe_fn)]
 
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
@@ -321,7 +322,8 @@ fn is_read_vectored(&self) -> bool {
 
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
+        // SAFETY: Read is guaranteed to work on uninitialized memory
+        unsafe { Initializer::nop() }
     }
 }
 
@@ -381,7 +383,8 @@ fn is_read_vectored(&self) -> bool {
 
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
+        // SAFETY: Read is guaranteed to work on uninitialized memory
+        unsafe { Initializer::nop() }
     }
 }
 
diff --git a/library/std/src/sys/sgx/fs.rs b/library/std/src/sys/sgx/fs.rs
deleted file mode 100644 (file)
index ecb5b51..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-use crate::ffi::OsString;
-use crate::fmt;
-use crate::hash::{Hash, Hasher};
-use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
-use crate::path::{Path, PathBuf};
-use crate::sys::time::SystemTime;
-use crate::sys::{unsupported, Void};
-
-pub struct File(Void);
-
-pub struct FileAttr(Void);
-
-pub struct ReadDir(Void);
-
-pub struct DirEntry(Void);
-
-#[derive(Clone, Debug)]
-pub struct OpenOptions {}
-
-pub struct FilePermissions(Void);
-
-pub struct FileType(Void);
-
-#[derive(Debug)]
-pub struct DirBuilder {}
-
-impl FileAttr {
-    pub fn size(&self) -> u64 {
-        match self.0 {}
-    }
-
-    pub fn perm(&self) -> FilePermissions {
-        match self.0 {}
-    }
-
-    pub fn file_type(&self) -> FileType {
-        match self.0 {}
-    }
-
-    pub fn modified(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-
-    pub fn accessed(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-
-    pub fn created(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-}
-
-impl Clone for FileAttr {
-    fn clone(&self) -> FileAttr {
-        match self.0 {}
-    }
-}
-
-impl FilePermissions {
-    pub fn readonly(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn set_readonly(&mut self, _readonly: bool) {
-        match self.0 {}
-    }
-}
-
-impl Clone for FilePermissions {
-    fn clone(&self) -> FilePermissions {
-        match self.0 {}
-    }
-}
-
-impl PartialEq for FilePermissions {
-    fn eq(&self, _other: &FilePermissions) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for FilePermissions {}
-
-impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl FileType {
-    pub fn is_dir(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn is_file(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn is_symlink(&self) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Clone for FileType {
-    fn clone(&self) -> FileType {
-        match self.0 {}
-    }
-}
-
-impl Copy for FileType {}
-
-impl PartialEq for FileType {
-    fn eq(&self, _other: &FileType) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for FileType {}
-
-impl Hash for FileType {
-    fn hash<H: Hasher>(&self, _h: &mut H) {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl Iterator for ReadDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        match self.0 {}
-    }
-}
-
-impl DirEntry {
-    pub fn path(&self) -> PathBuf {
-        match self.0 {}
-    }
-
-    pub fn file_name(&self) -> OsString {
-        match self.0 {}
-    }
-
-    pub fn metadata(&self) -> io::Result<FileAttr> {
-        match self.0 {}
-    }
-
-    pub fn file_type(&self) -> io::Result<FileType> {
-        match self.0 {}
-    }
-}
-
-impl OpenOptions {
-    pub fn new() -> OpenOptions {
-        OpenOptions {}
-    }
-
-    pub fn read(&mut self, _read: bool) {}
-    pub fn write(&mut self, _write: bool) {}
-    pub fn append(&mut self, _append: bool) {}
-    pub fn truncate(&mut self, _truncate: bool) {}
-    pub fn create(&mut self, _create: bool) {}
-    pub fn create_new(&mut self, _create_new: bool) {}
-}
-
-impl File {
-    pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
-        unsupported()
-    }
-
-    pub fn file_attr(&self) -> io::Result<FileAttr> {
-        match self.0 {}
-    }
-
-    pub fn fsync(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn datasync(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn truncate(&self, _size: u64) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn flush(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<File> {
-        match self.0 {}
-    }
-
-    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-impl DirBuilder {
-    pub fn new() -> DirBuilder {
-        DirBuilder {}
-    }
-
-    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
-        unsupported()
-    }
-}
-
-impl fmt::Debug for File {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
-    unsupported()
-}
-
-pub fn unlink(_p: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
-    match perm.0 {}
-}
-
-pub fn rmdir(_p: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn stat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
-}
-
-pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
-}
-
-pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
-    unsupported()
-}
diff --git a/library/std/src/sys/sgx/io.rs b/library/std/src/sys/sgx/io.rs
deleted file mode 100644 (file)
index d5f475b..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::mem;
-
-#[derive(Copy, Clone)]
-pub struct IoSlice<'a>(&'a [u8]);
-
-impl<'a> IoSlice<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        IoSlice(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.0 = &self.0[n..]
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-}
-
-pub struct IoSliceMut<'a>(&'a mut [u8]);
-
-impl<'a> IoSliceMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        IoSliceMut(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        let slice = mem::replace(&mut self.0, &mut []);
-        let (_, remaining) = slice.split_at_mut(n);
-        self.0 = remaining;
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        self.0
-    }
-}
index 1d32eb25424345578d63d378ad1fa3c9d463f4db..1abd91e75e8c40d9e3a472efce09e3e075b01367 100644 (file)
 pub mod env;
 pub mod ext;
 pub mod fd;
+#[path = "../unsupported/fs.rs"]
 pub mod fs;
+#[path = "../unsupported/io.rs"]
 pub mod io;
 pub mod memchr;
 pub mod mutex;
 pub mod net;
 pub mod os;
 pub mod path;
+#[path = "../unsupported/pipe.rs"]
 pub mod pipe;
+#[path = "../unsupported/process.rs"]
 pub mod process;
 pub mod rwlock;
 pub mod stack_overflow;
diff --git a/library/std/src/sys/sgx/pipe.rs b/library/std/src/sys/sgx/pipe.rs
deleted file mode 100644 (file)
index 10d0925..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-use crate::io::{self, IoSlice, IoSliceMut};
-use crate::sys::Void;
-
-pub struct AnonPipe(Void);
-
-impl AnonPipe {
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
-    match p1.0 {}
-}
diff --git a/library/std/src/sys/sgx/process.rs b/library/std/src/sys/sgx/process.rs
deleted file mode 100644 (file)
index 4702e5c..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io;
-use crate::sys::fs::File;
-use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
-
-pub use crate::ffi::OsString as EnvKey;
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    env: CommandEnv,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-}
-
-impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
-    }
-
-    pub fn arg(&mut self, _arg: &OsStr) {}
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, _dir: &OsStr) {}
-
-    pub fn stdin(&mut self, _stdin: Stdio) {}
-
-    pub fn stdout(&mut self, _stdout: Stdio) {}
-
-    pub fn stderr(&mut self, _stderr: Stdio) {}
-
-    pub fn spawn(
-        &mut self,
-        _default: Stdio,
-        _needs_stdin: bool,
-    ) -> io::Result<(Process, StdioPipes)> {
-        unsupported()
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        pipe.diverge()
-    }
-}
-
-impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-pub struct ExitStatus(Void);
-
-impl ExitStatus {
-    pub fn success(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        match self.0 {}
-    }
-}
-
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        match self.0 {}
-    }
-}
-
-impl Copy for ExitStatus {}
-
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for ExitStatus {}
-
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-pub struct Process(Void);
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        match self.0 {}
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
-    }
-}
index 8e193935460eb1f450ccb1cd9fd9ffcfb9ac66f3..964abe8b8c9ea86ffe714811e897110ab488c083 100644 (file)
@@ -52,46 +52,48 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
     }
 }
 
-#[cfg(any(
-    target_os = "android",
-    target_os = "illumos",
-    target_os = "redox",
-    target_os = "solaris"
-))]
-#[inline]
-unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-    // On android we currently target API level 9 which unfortunately
-    // doesn't have the `posix_memalign` API used below. Instead we use
-    // `memalign`, but this unfortunately has the property on some systems
-    // where the memory returned cannot be deallocated by `free`!
-    //
-    // Upon closer inspection, however, this appears to work just fine with
-    // Android, so for this platform we should be fine to call `memalign`
-    // (which is present in API level 9). Some helpful references could
-    // possibly be chromium using memalign [1], attempts at documenting that
-    // memalign + free is ok [2] [3], or the current source of chromium
-    // which still uses memalign on android [4].
-    //
-    // [1]: https://codereview.chromium.org/10796020/
-    // [2]: https://code.google.com/p/android/issues/detail?id=35391
-    // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
-    // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
-    //                                       /memory/aligned_memory.cc
-    libc::memalign(layout.align(), layout.size()) as *mut u8
-}
-
-#[cfg(not(any(
-    target_os = "android",
-    target_os = "illumos",
-    target_os = "redox",
-    target_os = "solaris"
-)))]
-#[inline]
-unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-    let mut out = ptr::null_mut();
-    // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
-    // Since these are all powers of 2, we can just use max.
-    let align = layout.align().max(crate::mem::size_of::<usize>());
-    let ret = libc::posix_memalign(&mut out, align, layout.size());
-    if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
+cfg_if::cfg_if! {
+    if #[cfg(any(
+        target_os = "android",
+        target_os = "illumos",
+        target_os = "redox",
+        target_os = "solaris"
+    ))] {
+        #[inline]
+        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+            // On android we currently target API level 9 which unfortunately
+            // doesn't have the `posix_memalign` API used below. Instead we use
+            // `memalign`, but this unfortunately has the property on some systems
+            // where the memory returned cannot be deallocated by `free`!
+            //
+            // Upon closer inspection, however, this appears to work just fine with
+            // Android, so for this platform we should be fine to call `memalign`
+            // (which is present in API level 9). Some helpful references could
+            // possibly be chromium using memalign [1], attempts at documenting that
+            // memalign + free is ok [2] [3], or the current source of chromium
+            // which still uses memalign on android [4].
+            //
+            // [1]: https://codereview.chromium.org/10796020/
+            // [2]: https://code.google.com/p/android/issues/detail?id=35391
+            // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
+            // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
+            //                                       /memory/aligned_memory.cc
+            libc::memalign(layout.align(), layout.size()) as *mut u8
+        }
+    } else if #[cfg(target_os = "wasi")] {
+        #[inline]
+        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+            libc::aligned_alloc(layout.align(), layout.size()) as *mut u8
+        }
+    } else {
+        #[inline]
+        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+            let mut out = ptr::null_mut();
+            // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
+            // Since these are all powers of 2, we can just use max.
+            let align = layout.align().max(crate::mem::size_of::<usize>());
+            let ret = libc::posix_memalign(&mut out, align, layout.size());
+            if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
+        }
+    }
 }
index ecb5b51cccdcd965d85e9ee8e22ecb878d876719..faa53b6a74422ddff884dec7a850c37252798d58 100644 (file)
@@ -233,10 +233,6 @@ pub fn duplicate(&self) -> io::Result<File> {
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
         match self.0 {}
     }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
 }
 
 impl DirBuilder {
index 87f655eecd54e74a33bde42e0b88d1a85a144d19..8ba870c5dbc14cecba6f52158fae1d49a799ea8e 100644 (file)
@@ -8,6 +8,7 @@
 pub mod mutex;
 pub mod net;
 pub mod os;
+#[path = "../unix/path.rs"]
 pub mod path;
 pub mod pipe;
 pub mod process;
diff --git a/library/std/src/sys/unsupported/path.rs b/library/std/src/sys/unsupported/path.rs
deleted file mode 100644 (file)
index 840a7ae..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::ffi::OsStr;
-use crate::path::Prefix;
-
-#[inline]
-pub fn is_sep_byte(b: u8) -> bool {
-    b == b'/'
-}
-
-#[inline]
-pub fn is_verbatim_sep(b: u8) -> bool {
-    b == b'/'
-}
-
-pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
-    None
-}
-
-pub const MAIN_SEP_STR: &str = "/";
-pub const MAIN_SEP: char = '/';
index 4702e5c549228ea27e5c59777cb707b34ea5d248..7156c9ab92f2b6af3da9699a3618f76275280af1 100644 (file)
@@ -65,8 +65,8 @@ fn from(pipe: AnonPipe) -> Stdio {
 }
 
 impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
+    fn from(_file: File) -> Stdio {
+        panic!("unsupported")
     }
 }
 
diff --git a/library/std/src/sys/wasi/alloc.rs b/library/std/src/sys/wasi/alloc.rs
deleted file mode 100644 (file)
index 4d0afe2..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::alloc::{GlobalAlloc, Layout, System};
-use crate::ptr;
-use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
-
-// SAFETY: All methods implemented follow the contract rules defined
-// in `GlobalAlloc`.
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
-    #[inline]
-    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-            // SAFETY: `libc::malloc` is guaranteed to be safe, it will allocate
-            // `layout.size()` bytes of memory and return a pointer to it
-            unsafe { libc::malloc(layout.size()) as *mut u8 }
-        } else {
-            // SAFETY: `libc::aligned_alloc` is guaranteed to be safe if
-            // `layout.size()` is a multiple of `layout.align()`. This
-            // constraint can be satisfied if `pad_to_align` is called,
-            // which creates a layout by rounding the size of this layout up
-            // to a multiple of the layout's alignment
-            let aligned_layout = layout.pad_to_align();
-            unsafe { libc::aligned_alloc(aligned_layout.align(), aligned_layout.size()) as *mut u8 }
-        }
-    }
-
-    #[inline]
-    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-            // SAFETY: `libc::calloc` is safe as long that `layout.size() * 1`
-            // would not result in integer overflow which cannot happen,
-            // multiplying by one never overflows
-            unsafe { libc::calloc(layout.size(), 1) as *mut u8 }
-        } else {
-            // SAFETY: The safety contract for `alloc` must be upheld by the caller
-            let ptr = unsafe { self.alloc(layout.clone()) };
-            if !ptr.is_null() {
-                // SAFETY: in the case of the `ptr` being not null
-                // it will be properly aligned and a valid ptr
-                // which satisfies `ptr::write_bytes` safety constrains
-                unsafe { ptr::write_bytes(ptr, 0, layout.size()) };
-            }
-            ptr
-        }
-    }
-
-    #[inline]
-    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
-        // SAFETY: `libc::free` is guaranteed to be safe if `ptr` is allocated
-        // by this allocator or if `ptr` is NULL
-        unsafe { libc::free(ptr as *mut libc::c_void) }
-    }
-
-    #[inline]
-    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
-        if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
-            // SAFETY: `libc::realloc` is safe if `ptr` is allocated by this
-            // allocator or NULL
-            // - If `new_size` is 0 and `ptr` is not NULL, it will act as `libc::free`
-            // - If `new_size` is not 0 and `ptr` is NULL, it will act as `libc::malloc`
-            // - Else, it will resize the block accordingly
-            unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
-        } else {
-            // SAFETY: The safety contract for `realloc_fallback` must be upheld by the caller
-            unsafe { realloc_fallback(self, ptr, layout, new_size) }
-        }
-    }
-}
index 2704ff484f9911c920329e86ebdb21dbeaf9372e..a7a4407ac38e281fb4ac716d2f8e75679c0d26af 100644 (file)
@@ -17,6 +17,7 @@
 use crate::io as std_io;
 use crate::mem;
 
+#[path = "../unix/alloc.rs"]
 pub mod alloc;
 pub mod args;
 #[path = "../unsupported/cmath.rs"]
 pub mod os;
 pub use crate::sys_common::os_str_bytes as os_str;
 pub mod ext;
+#[path = "../unix/path.rs"]
 pub mod path;
+#[path = "../unsupported/pipe.rs"]
 pub mod pipe;
+#[path = "../unsupported/process.rs"]
 pub mod process;
 #[path = "../unsupported/rwlock.rs"]
 pub mod rwlock;
diff --git a/library/std/src/sys/wasi/path.rs b/library/std/src/sys/wasi/path.rs
deleted file mode 100644 (file)
index 840a7ae..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::ffi::OsStr;
-use crate::path::Prefix;
-
-#[inline]
-pub fn is_sep_byte(b: u8) -> bool {
-    b == b'/'
-}
-
-#[inline]
-pub fn is_verbatim_sep(b: u8) -> bool {
-    b == b'/'
-}
-
-pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
-    None
-}
-
-pub const MAIN_SEP_STR: &str = "/";
-pub const MAIN_SEP: char = '/';
diff --git a/library/std/src/sys/wasi/pipe.rs b/library/std/src/sys/wasi/pipe.rs
deleted file mode 100644 (file)
index 180fc11..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::io::{self, IoSlice, IoSliceMut};
-use crate::sys::Void;
-
-pub struct AnonPipe(Void);
-
-impl AnonPipe {
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
-    match p1.0 {}
-}
diff --git a/library/std/src/sys/wasi/process.rs b/library/std/src/sys/wasi/process.rs
deleted file mode 100644 (file)
index c69d637..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io;
-use crate::sys::fs::File;
-use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
-
-pub use crate::ffi::OsString as EnvKey;
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    env: CommandEnv,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-}
-
-impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
-    }
-
-    pub fn arg(&mut self, _arg: &OsStr) {}
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, _dir: &OsStr) {}
-
-    pub fn stdin(&mut self, _stdin: Stdio) {}
-
-    pub fn stdout(&mut self, _stdout: Stdio) {}
-
-    pub fn stderr(&mut self, _stderr: Stdio) {}
-
-    pub fn spawn(
-        &mut self,
-        _default: Stdio,
-        _needs_stdin: bool,
-    ) -> io::Result<(Process, StdioPipes)> {
-        unsupported()
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        pipe.diverge()
-    }
-}
-
-impl From<File> for Stdio {
-    fn from(_file: File) -> Stdio {
-        panic!("unsupported")
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-pub struct ExitStatus(Void);
-
-impl ExitStatus {
-    pub fn success(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        match self.0 {}
-    }
-}
-
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        match self.0 {}
-    }
-}
-
-impl Copy for ExitStatus {}
-
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for ExitStatus {}
-
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-pub struct Process(Void);
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        match self.0 {}
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
-    }
-}
index 3de58904043573d4d4020021156e98c8d0383c12..2934ea59ab5ff687081f502df9e48417f7edea9d 100644 (file)
@@ -27,7 +27,7 @@
 pub mod net;
 #[path = "../unsupported/os.rs"]
 pub mod os;
-#[path = "../unsupported/path.rs"]
+#[path = "../unix/path.rs"]
 pub mod path;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
index 9d8c6f1815eeb38963decadd4bbb98d13a23a821..60a05dc5d545b74ea168a0a3c9d2b54251ead303 100644 (file)
@@ -424,10 +424,9 @@ pub unsafe fn get<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
         // thread_local's, or it is being recursively initialized.
         //
         // Macos: Inlining this function can cause two `tlv_get_addr` calls to
-        // be performed for every call to `Key::get`. The #[cold] hint makes
-        // that less likely.
+        // be performed for every call to `Key::get`.
         // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
-        #[cold]
+        #[inline(never)]
         unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
             if !mem::needs_drop::<T>() || self.try_register_dtor() {
                 Some(self.inner.initialize(init))
index 78891cdf292c23278ca8723bd543100249159604..718175b34a39e4e3d59b40e35930326edc515b87 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 78891cdf292c23278ca8723bd543100249159604
+Subproject commit 718175b34a39e4e3d59b40e35930326edc515b87
index 975b8be02c89831687ce21cad716007139ce5fcd..a69bd1cc3bc530f3d7f230d8232cfa2c51cd9837 100644 (file)
@@ -26,10 +26,10 @@ The script accepts commands, flags, and arguments to determine what to do:
 
   ```
   # build the whole compiler
-  ./x.py build
+  ./x.py build --stage 2
 
   # build the stage1 compiler
-  ./x.py build --stage 1
+  ./x.py build
 
   # build stage0 libstd
   ./x.py build --stage 0 library/std
@@ -43,8 +43,8 @@ The script accepts commands, flags, and arguments to determine what to do:
   that belong to stage n or earlier:
 
   ```
-  # keep old build products for stage 0 and build stage 1
-  ./x.py build --keep-stage 0 --stage 1
+  # build stage 1, keeping old build products for stage 0
+  ./x.py build --keep-stage 0
   ```
 
 * `test` - a command for executing unit tests. Like the `build` command this
@@ -123,24 +123,8 @@ that (b) leverage Rust as much as possible!
 
 ## Incremental builds
 
-You can configure rustbuild to use incremental compilation. Because
-incremental is new and evolving rapidly, if you want to use it, it is
-recommended that you replace the snapshot with a locally installed
-nightly build of rustc. You will want to keep this up to date.
-
-To follow this course of action, first thing you will want to do is to
-install a nightly, presumably using `rustup`. You will then want to
-configure your directory to use this build, like so:
-
-```sh
-# configure to use local rust instead of downloading a beta.
-# `--local-rust-root` is optional here. If elided, we will
-# use whatever rustc we find on your PATH.
-$ ./configure --local-rust-root=~/.cargo/ --enable-local-rebuild
-```
-
-After that, you can use the `--incremental` flag to actually do
-incremental builds:
+You can configure rustbuild to use incremental compilation with the
+`--incremental` flag:
 
 ```sh
 $ ./x.py build --incremental
@@ -150,9 +134,7 @@ The `--incremental` flag will store incremental compilation artifacts
 in `build/<host>/stage0-incremental`. Note that we only use incremental
 compilation for the stage0 -> stage1 compilation -- this is because
 the stage1 compiler is changing, and we don't try to cache and reuse
-incremental artifacts across different versions of the compiler. For
-this reason, `--incremental` defaults to `--stage 1` (though you can
-manually select a higher stage, if you prefer).
+incremental artifacts across different versions of the compiler.
 
 You can always drop the `--incremental` to build as normal (but you
 will still be using the local nightly as your bootstrap).
@@ -331,8 +313,8 @@ are:
   `Config` struct.
 * Adding a sanity check? Take a look at `bootstrap/sanity.rs`.
 
-If you have any questions feel free to reach out on `#infra` channel in the
-[Rust Discord server][rust-discord] or ask on internals.rust-lang.org. When
+If you have any questions feel free to reach out on the `#t-infra` channel in
+the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When
 you encounter bugs, please file issues on the rust-lang/rust issue tracker.
 
-[rust-discord]: https://discord.gg/rust-lang
+[rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra
index 0f18660c0e1092fd85876d89d4c1cbe23f64e262..d2537d65e67f50fe6dcf32977689b69d52511764 100644 (file)
@@ -526,23 +526,9 @@ pub fn get_help(build: &Build, subcommand: &str) -> Option<String> {
     }
 
     fn new_internal(build: &Build, kind: Kind, paths: Vec<PathBuf>) -> Builder<'_> {
-        let top_stage = if let Some(explicit_stage) = build.config.stage {
-            explicit_stage
-        } else {
-            // See https://github.com/rust-lang/compiler-team/issues/326
-            match kind {
-                Kind::Doc => 0,
-                Kind::Build | Kind::Test => 1,
-                Kind::Bench | Kind::Dist | Kind::Install => 2,
-                // These are all bootstrap tools, which don't depend on the compiler.
-                // The stage we pass shouldn't matter, but use 0 just in case.
-                Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => 0,
-            }
-        };
-
         Builder {
             build,
-            top_stage,
+            top_stage: build.config.stage,
             kind,
             cache: Cache::new(),
             stack: RefCell::new(Vec::new()),
@@ -566,20 +552,7 @@ pub fn new(build: &Build) -> Builder<'_> {
             Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
         };
 
-        let this = Self::new_internal(build, kind, paths.to_owned());
-
-        // CI should always run stage 2 builds, unless it specifically states otherwise
-        #[cfg(not(test))]
-        if build.config.stage.is_none() && build.ci_env != crate::CiEnv::None {
-            match kind {
-                Kind::Test | Kind::Doc | Kind::Build | Kind::Bench | Kind::Dist | Kind::Install => {
-                    assert_eq!(this.top_stage, 2)
-                }
-                Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => {}
-            }
-        }
-
-        this
+        Self::new_internal(build, kind, paths.to_owned())
     }
 
     pub fn execute_cli(&self) {
@@ -710,7 +683,7 @@ pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
 
     /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic
     /// library lookup path.
-    pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Cargo) {
+    pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) {
         // Windows doesn't need dylib path munging because the dlls for the
         // compiler live next to the compiler and the system will find them
         // automatically.
@@ -718,7 +691,7 @@ pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Cargo) {
             return;
         }
 
-        add_dylib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command);
+        add_dylib_path(vec![self.rustc_libdir(compiler)], cmd);
     }
 
     /// Gets a path to the compiler specified.
@@ -1236,7 +1209,7 @@ pub fn cargo(
             cargo.env(format!("CC_{}", target.triple), &cc);
 
             let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
-            cargo.env(format!("CFLAGS_{}", target.triple), cflags.clone());
+            cargo.env(format!("CFLAGS_{}", target.triple), &cflags);
 
             if let Some(ar) = self.ar(target) {
                 let ranlib = format!("{} s", ar.display());
@@ -1421,7 +1394,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
             (out, dur - deps)
         };
 
-        if self.config.print_step_timings {
+        if self.config.print_step_timings && !self.config.dry_run {
             println!("[TIMING] {:?} -- {}.{:03}", step, dur.as_secs(), dur.subsec_millis());
         }
 
@@ -1515,6 +1488,10 @@ pub fn env(&mut self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut
         self.command.env(key.as_ref(), value.as_ref());
         self
     }
+
+    pub fn add_rustc_lib_path(&mut self, builder: &Builder<'_>, compiler: Compiler) {
+        builder.add_rustc_lib_path(compiler, &mut self.command);
+    }
 }
 
 impl From<Cargo> for Command {
index c6eac95c34507bcb8954be882db0060df40a2439..f96925f927086ad1e64c3902e7427288ccef655c 100644 (file)
@@ -2,8 +2,8 @@
 use crate::config::{Config, TargetSelection};
 use std::thread;
 
-fn configure(host: &[&str], target: &[&str]) -> Config {
-    let mut config = Config::default_opts();
+fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
+    let mut config = Config::parse(&[cmd.to_owned()]);
     // don't save toolstates
     config.save_toolstates = None;
     config.skip_only_host_steps = false;
@@ -42,7 +42,7 @@ mod defaults {
 
     #[test]
     fn build_default() {
-        let build = Build::new(configure(&[], &[]));
+        let build = Build::new(configure("build", &[], &[]));
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
 
@@ -70,7 +70,7 @@ fn build_default() {
 
     #[test]
     fn build_stage_0() {
-        let config = Config { stage: Some(0), ..configure(&[], &[]) };
+        let config = Config { stage: 0, ..configure("build", &[], &[]) };
         let build = Build::new(config);
         let mut builder = Builder::new(&build);
         builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
@@ -92,7 +92,7 @@ fn build_stage_0() {
 
     #[test]
     fn doc_default() {
-        let mut config = configure(&[], &[]);
+        let mut config = configure("doc", &[], &[]);
         config.compiler_docs = true;
         config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
         let build = Build::new(config);
@@ -126,7 +126,7 @@ mod dist {
     use pretty_assertions::assert_eq;
 
     fn configure(host: &[&str], target: &[&str]) -> Config {
-        Config { stage: Some(2), ..super::configure(host, target) }
+        Config { stage: 2, ..super::configure("dist", host, target) }
     }
 
     #[test]
@@ -455,7 +455,7 @@ fn build_with_target_flag() {
     #[test]
     fn test_with_no_doc_stage0() {
         let mut config = configure(&[], &[]);
-        config.stage = Some(0);
+        config.stage = 0;
         config.cmd = Subcommand::Test {
             paths: vec!["library/std".into()],
             test_args: vec![],
index 7c8c729b5bfab56021247432c4dc0a1efd6280e3..7e2cb7721865e512034a64f6fc6725a62639e391 100644 (file)
@@ -10,7 +10,6 @@
 use std::fmt;
 use std::fs;
 use std::path::{Path, PathBuf};
-use std::process;
 
 use crate::cache::{Interned, INTERNER};
 use crate::flags::Flags;
@@ -68,7 +67,7 @@ pub struct Config {
     pub skip_only_host_steps: bool,
 
     pub on_fail: Option<String>,
-    pub stage: Option<u32>,
+    pub stage: u32,
     pub keep_stage: Vec<u32>,
     pub src: PathBuf,
     pub jobs: Option<u32>,
@@ -313,6 +312,12 @@ struct Build {
     configure_args: Option<Vec<String>>,
     local_rebuild: Option<bool>,
     print_step_timings: Option<bool>,
+    doc_stage: Option<u32>,
+    build_stage: Option<u32>,
+    test_stage: Option<u32>,
+    install_stage: Option<u32>,
+    dist_stage: Option<u32>,
+    bench_stage: Option<u32>,
 }
 
 /// TOML representation of various global install decisions.
@@ -495,13 +500,12 @@ pub fn default_opts() -> Config {
 
     pub fn parse(args: &[String]) -> Config {
         let flags = Flags::parse(&args);
-        let file = flags.config.clone();
+
         let mut config = Config::default_opts();
         config.exclude = flags.exclude;
         config.rustc_error_format = flags.rustc_error_format;
         config.json_output = flags.json_output;
         config.on_fail = flags.on_fail;
-        config.stage = flags.stage;
         config.jobs = flags.jobs.map(threads_from_config);
         config.cmd = flags.cmd;
         config.incremental = flags.incremental;
@@ -518,8 +522,14 @@ pub fn parse(args: &[String]) -> Config {
             config.out = dir;
         }
 
-        let toml = file
+        #[cfg(test)]
+        let toml = TomlConfig::default();
+        #[cfg(not(test))]
+        let toml = flags
+            .config
             .map(|file| {
+                use std::process;
+
                 let contents = t!(fs::read_to_string(&file));
                 match toml::from_str(&contents) {
                     Ok(table) => table,
@@ -535,21 +545,21 @@ pub fn parse(args: &[String]) -> Config {
             })
             .unwrap_or_else(TomlConfig::default);
 
-        let build = toml.build.clone().unwrap_or_default();
+        let build = toml.build.unwrap_or_default();
 
         // If --target was specified but --host wasn't specified, don't run any host-only tests.
         let has_hosts = build.host.is_some() || flags.host.is_some();
         let has_targets = build.target.is_some() || flags.target.is_some();
         config.skip_only_host_steps = !has_hosts && has_targets;
 
-        config.hosts = if let Some(arg_host) = flags.host.clone() {
+        config.hosts = if let Some(arg_host) = flags.host {
             arg_host
         } else if let Some(file_host) = build.host {
             file_host.iter().map(|h| TargetSelection::from_user(h)).collect()
         } else {
             vec![config.build]
         };
-        config.targets = if let Some(arg_target) = flags.target.clone() {
+        config.targets = if let Some(arg_target) = flags.target {
             arg_target
         } else if let Some(file_target) = build.target {
             file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
@@ -579,16 +589,54 @@ pub fn parse(args: &[String]) -> Config {
         set(&mut config.configure_args, build.configure_args);
         set(&mut config.local_rebuild, build.local_rebuild);
         set(&mut config.print_step_timings, build.print_step_timings);
+
+        // See https://github.com/rust-lang/compiler-team/issues/326
+        config.stage = match config.cmd {
+            Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0),
+            Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1),
+            Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1),
+            Subcommand::Bench { .. } => flags.stage.or(build.bench_stage).unwrap_or(2),
+            Subcommand::Dist { .. } => flags.stage.or(build.dist_stage).unwrap_or(2),
+            Subcommand::Install { .. } => flags.stage.or(build.install_stage).unwrap_or(2),
+            // These are all bootstrap tools, which don't depend on the compiler.
+            // The stage we pass shouldn't matter, but use 0 just in case.
+            Subcommand::Clean { .. }
+            | Subcommand::Check { .. }
+            | Subcommand::Clippy { .. }
+            | Subcommand::Fix { .. }
+            | Subcommand::Run { .. }
+            | Subcommand::Format { .. } => flags.stage.unwrap_or(0),
+        };
+
+        // CI should always run stage 2 builds, unless it specifically states otherwise
+        #[cfg(not(test))]
+        if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None {
+            match config.cmd {
+                Subcommand::Test { .. }
+                | Subcommand::Doc { .. }
+                | Subcommand::Build { .. }
+                | Subcommand::Bench { .. }
+                | Subcommand::Dist { .. }
+                | Subcommand::Install { .. } => assert_eq!(config.stage, 2),
+                Subcommand::Clean { .. }
+                | Subcommand::Check { .. }
+                | Subcommand::Clippy { .. }
+                | Subcommand::Fix { .. }
+                | Subcommand::Run { .. }
+                | Subcommand::Format { .. } => {}
+            }
+        }
+
         config.verbose = cmp::max(config.verbose, flags.verbose);
 
-        if let Some(ref install) = toml.install {
-            config.prefix = install.prefix.clone().map(PathBuf::from);
-            config.sysconfdir = install.sysconfdir.clone().map(PathBuf::from);
-            config.datadir = install.datadir.clone().map(PathBuf::from);
-            config.docdir = install.docdir.clone().map(PathBuf::from);
-            set(&mut config.bindir, install.bindir.clone().map(PathBuf::from));
-            config.libdir = install.libdir.clone().map(PathBuf::from);
-            config.mandir = install.mandir.clone().map(PathBuf::from);
+        if let Some(install) = toml.install {
+            config.prefix = install.prefix.map(PathBuf::from);
+            config.sysconfdir = install.sysconfdir.map(PathBuf::from);
+            config.datadir = install.datadir.map(PathBuf::from);
+            config.docdir = install.docdir.map(PathBuf::from);
+            set(&mut config.bindir, install.bindir.map(PathBuf::from));
+            config.libdir = install.libdir.map(PathBuf::from);
+            config.mandir = install.mandir.map(PathBuf::from);
         }
 
         // We want the llvm-skip-rebuild flag to take precedence over the
@@ -611,7 +659,7 @@ pub fn parse(args: &[String]) -> Config {
         let mut optimize = None;
         let mut ignore_git = None;
 
-        if let Some(ref llvm) = toml.llvm {
+        if let Some(llvm) = toml.llvm {
             match llvm.ccache {
                 Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
                 Some(StringOrBool::Bool(true)) => {
@@ -679,7 +727,7 @@ pub fn parse(args: &[String]) -> Config {
             }
         }
 
-        if let Some(ref rust) = toml.rust {
+        if let Some(rust) = toml.rust {
             debug = rust.debug;
             debug_assertions = rust.debug_assertions;
             debug_assertions_std = rust.debug_assertions_std;
@@ -699,7 +747,7 @@ pub fn parse(args: &[String]) -> Config {
             set(&mut config.test_compare_mode, rust.test_compare_mode);
             set(&mut config.llvm_libunwind, rust.llvm_libunwind);
             set(&mut config.backtrace, rust.backtrace);
-            set(&mut config.channel, rust.channel.clone());
+            set(&mut config.channel, rust.channel);
             set(&mut config.rust_dist_src, rust.dist_src);
             set(&mut config.verbose_tests, rust.verbose_tests);
             // in the case "false" is set explicitly, do not overwrite the command line args
@@ -710,9 +758,9 @@ pub fn parse(args: &[String]) -> Config {
             set(&mut config.lld_enabled, rust.lld);
             set(&mut config.llvm_tools_enabled, rust.llvm_tools);
             config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
-            config.rustc_default_linker = rust.default_linker.clone();
-            config.musl_root = rust.musl_root.clone().map(PathBuf::from);
-            config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
+            config.rustc_default_linker = rust.default_linker;
+            config.musl_root = rust.musl_root.map(PathBuf::from);
+            config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
             set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
             set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
             set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
@@ -729,9 +777,9 @@ pub fn parse(args: &[String]) -> Config {
             config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
         }
 
-        if let Some(ref t) = toml.target {
+        if let Some(t) = toml.target {
             for (triple, cfg) in t {
-                let mut target = Target::from_triple(triple);
+                let mut target = Target::from_triple(&triple);
 
                 if let Some(ref s) = cfg.llvm_config {
                     target.llvm_config = Some(config.src.join(s));
@@ -745,18 +793,18 @@ pub fn parse(args: &[String]) -> Config {
                 if let Some(s) = cfg.no_std {
                     target.no_std = s;
                 }
-                target.cc = cfg.cc.clone().map(PathBuf::from);
-                target.cxx = cfg.cxx.clone().map(PathBuf::from);
-                target.ar = cfg.ar.clone().map(PathBuf::from);
-                target.ranlib = cfg.ranlib.clone().map(PathBuf::from);
-                target.linker = cfg.linker.clone().map(PathBuf::from);
+                target.cc = cfg.cc.map(PathBuf::from);
+                target.cxx = cfg.cxx.map(PathBuf::from);
+                target.ar = cfg.ar.map(PathBuf::from);
+                target.ranlib = cfg.ranlib.map(PathBuf::from);
+                target.linker = cfg.linker.map(PathBuf::from);
                 target.crt_static = cfg.crt_static;
-                target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
-                target.musl_libdir = cfg.musl_libdir.clone().map(PathBuf::from);
-                target.wasi_root = cfg.wasi_root.clone().map(PathBuf::from);
-                target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
+                target.musl_root = cfg.musl_root.map(PathBuf::from);
+                target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
+                target.wasi_root = cfg.wasi_root.map(PathBuf::from);
+                target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
 
-                config.target_config.insert(TargetSelection::from_user(triple), target);
+                config.target_config.insert(TargetSelection::from_user(&triple), target);
             }
         }
 
@@ -774,10 +822,10 @@ pub fn parse(args: &[String]) -> Config {
             build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build)));
         }
 
-        if let Some(ref t) = toml.dist {
-            config.dist_sign_folder = t.sign_folder.clone().map(PathBuf::from);
-            config.dist_gpg_password_file = t.gpg_password_file.clone().map(PathBuf::from);
-            config.dist_upload_addr = t.upload_addr.clone();
+        if let Some(t) = toml.dist {
+            config.dist_sign_folder = t.sign_folder.map(PathBuf::from);
+            config.dist_gpg_password_file = t.gpg_password_file.map(PathBuf::from);
+            config.dist_upload_addr = t.upload_addr;
             set(&mut config.rust_dist_src, t.src_tarball);
             set(&mut config.missing_tools, t.missing_tools);
         }
index 98a0119e4df12f8daf4dd2c4c3a6e10c0528ed06..f90e76a4f4ea68f8a8ee331a125bc9c5c0f56f3c 100644 (file)
@@ -766,6 +766,10 @@ fn run(self, builder: &Builder<'_>) {
         if builder.config.verbose() {
             cmd.arg("--verbose");
         }
+        // If the lib directories are in an unusual location (changed in
+        // config.toml), then this needs to explicitly update the dylib search
+        // path.
+        builder.add_rustc_lib_path(self.compiler, &mut cmd);
         builder.run(&mut cmd);
         // Run rustbook/mdbook to generate the HTML pages.
         builder.ensure(RustbookSrc {
index 6f93082e6752f01c559b572dcf85ff95873e8270..0ae9f9712d569bb2dc55e65462c7d437ddf1552e 100644 (file)
@@ -105,15 +105,13 @@ pub fn format(build: &Build, check: bool) {
         eprintln!("./x.py fmt is not supported on this channel");
         std::process::exit(1);
     });
-    let src = build.src.clone();
-    let walker = WalkBuilder::new(&build.src).types(matcher).overrides(ignore_fmt).build_parallel();
+    let src = &build.src;
+    let walker = WalkBuilder::new(src).types(matcher).overrides(ignore_fmt).build_parallel();
     walker.run(|| {
-        let src = src.clone();
-        let rustfmt_path = rustfmt_path.clone();
         Box::new(move |entry| {
             let entry = t!(entry);
             if entry.file_type().map_or(false, |t| t.is_file()) {
-                rustfmt(&src, &rustfmt_path, &entry.path(), check);
+                rustfmt(src, &rustfmt_path, &entry.path(), check);
             }
             ignore::WalkState::Continue
         })
index 4d6612a376a34993abd26f523228961663371d04..6826d177a4adeac4e73d74db025b48919240fc38 100644 (file)
@@ -30,8 +30,8 @@ pub fn new() -> Self {
         Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() }
     }
 
-    pub fn maybe_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> Option<PathBuf> {
-        let cmd: OsString = cmd.as_ref().into();
+    pub fn maybe_have<S: Into<OsString>>(&mut self, cmd: S) -> Option<PathBuf> {
+        let cmd: OsString = cmd.into();
         let path = &self.path;
         self.cache
             .entry(cmd.clone())
index 045dda2d4cb4cbbc5da6631bda9dc4616e9c670f..ba5f75c49ac7769e2de63b3686afc88ec98ee89e 100644 (file)
@@ -270,7 +270,7 @@ fn run(self, builder: &Builder<'_>) {
             &[],
         );
 
-        builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.add_rustc_lib_path(builder, compiler);
         cargo.arg("--").args(builder.config.cmd.test_args());
 
         if try_run(builder, &mut cargo.into()) {
@@ -328,7 +328,7 @@ fn run(self, builder: &Builder<'_>) {
         t!(fs::create_dir_all(&dir));
         cargo.env("RUSTFMT_TEST_DIR", dir);
 
-        builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.add_rustc_lib_path(builder, compiler);
 
         if try_run(builder, &mut cargo.into()) {
             builder.save_toolstate("rustfmt", ToolState::TestPass);
@@ -449,7 +449,7 @@ fn run(self, builder: &Builder<'_>) {
 
             cargo.arg("--").args(builder.config.cmd.test_args());
 
-            builder.add_rustc_lib_path(compiler, &mut cargo);
+            cargo.add_rustc_lib_path(builder, compiler);
 
             if !try_run(builder, &mut cargo.into()) {
                 return;
@@ -554,7 +554,7 @@ fn run(self, builder: &Builder<'_>) {
 
         cargo.arg("--").args(builder.config.cmd.test_args());
 
-        builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.add_rustc_lib_path(builder, compiler);
 
         builder.run(&mut cargo.into());
     }
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-git.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-git.sh
deleted file mode 100755 (executable)
index 38fea2a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-source shared.sh
-
-curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
-
-cd git-2.10.0
-make configure
-hide_output ./configure --prefix=/rustroot
-hide_output make -j10
-hide_output make install
-
-cd ..
-rm -rf git-2.10.0
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-headers.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-headers.sh
deleted file mode 100755 (executable)
index b623e53..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-source shared.sh
-
-curl https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.2.84.tar.xz | unxz | tar x
-
-cd linux-3.2.84
-hide_output make mrproper
-hide_output make INSTALL_HDR_PATH=dest headers_install
-
-find dest/include \( -name .install -o -name ..install.cmd \) -delete
-yes | cp -fr dest/include/* /usr/include
-
-cd ..
-rm -rf linux-3.2.84
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-perl.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-perl.sh
deleted file mode 100755 (executable)
index a678d35..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-source shared.sh
-
-curl https://www.cpan.org/src/5.0/perl-5.28.0.tar.gz | \
-  tar xzf -
-
-cd perl-5.28.0
-
-# Gotta do some hackery to tell python about our custom OpenSSL build, but other
-# than that fairly normal.
-CC=gcc \
-CFLAGS='-I /rustroot/include -fgnu89-inline' \
-LDFLAGS='-L /rustroot/lib -L /rustroot/lib64' \
-    hide_output ./configure.gnu
-hide_output make -j10
-hide_output make install
-
-cd ..
-rm -rf perl-5.28.0
index 2109cdf4e86b7f42f58352957955897baceede46..f8d3bc8e8e5881be92e5346c6a682cfe260db10e 100644 (file)
@@ -130,9 +130,7 @@ x--expand-yaml-anchors--remove:
         uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
         with:
           github_token: "${{ secrets.github_token }}"
-        # TODO: remove the condition on RUST_CI_TEMP_SKIP_CANCEL_OUTDATED once
-        # we remove the `auto-fallible` job.
-        if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED
+        if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'
         <<: *step
 
       - name: collect CPU statistics
@@ -434,6 +432,78 @@ jobs:
               DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
             <<: *job-linux-xl
 
+          ####################
+          #  macOS Builders  #
+          ####################
+
+          - name: dist-x86_64-apple
+            env:
+              SCRIPT: ./x.py dist
+              RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+              DIST_REQUIRE_ALL_TOOLS: 1
+            <<: *job-macos-xl
+
+          - name: dist-x86_64-apple-alt
+            env:
+              SCRIPT: ./x.py dist
+              RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            <<: *job-macos-xl
+
+          - name: x86_64-apple
+            env:
+              SCRIPT: ./x.py --stage 2 test
+              RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.8
+              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            <<: *job-macos-xl
+
+          ####################
+          #  macOS Builders  #
+          ####################
+
+          - name: dist-x86_64-apple
+            env:
+              SCRIPT: ./x.py dist
+              RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+              DIST_REQUIRE_ALL_TOOLS: 1
+            <<: *job-macos-xl
+
+          - name: dist-x86_64-apple-alt
+            env:
+              SCRIPT: ./x.py dist
+              RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            <<: *job-macos-xl
+
+          - name: x86_64-apple
+            env:
+              SCRIPT: ./x.py --stage 2 test
+              RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
+              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+              MACOSX_DEPLOYMENT_TARGET: 10.8
+              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
+              NO_LLVM_ASSERTIONS: 1
+              NO_DEBUG_ASSERTIONS: 1
+            <<: *job-macos-xl
+
           ######################
           #  Windows Builders  #
           ######################
@@ -600,54 +670,6 @@ jobs:
           - name: aarch64-gnu
             <<: *job-aarch64-linux
 
-          ####################
-          #  macOS Builders  #
-          ####################
-
-          - name: dist-x86_64-apple
-            env:
-              SCRIPT: ./x.py dist
-              RUST_CONFIGURE_ARGS: --host=x86_64-apple-darwin --target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              DIST_REQUIRE_ALL_TOOLS: 1
-
-              # TODO: remove once we move this job away from auto-fallible.
-              # Also, remove the variable from the cancel-outdated-builds step
-              RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
-            <<: *job-macos-xl
-
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: ./x.py dist
-              RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-
-              # TODO: remove once we move this job away from auto-fallible.
-              # Also, remove the variable from the cancel-outdated-builds step
-              RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
-            <<: *job-macos-xl
-
-          - name: x86_64-apple
-            env:
-              SCRIPT: ./x.py --stage 2 test
-              RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.8
-              MACOSX_STD_DEPLOYMENT_TARGET: 10.7
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-
-              # TODO: remove once we move this job away from auto-fallible.
-              # Also, remove the variable from the cancel-outdated-builds step
-              RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
-            <<: *job-macos-xl
-
   master:
     name: master
     runs-on: ubuntu-latest
index 794eeafbbbff988c3053ca302d210f2b873c1db6..da27d2fbf99a3675c39b732e8462e03c85b5c51e 100644 (file)
@@ -195,6 +195,7 @@ target | std | host | notes
 `powerpc64-unknown-linux-musl` | ? |  |
 `powerpc64-wrs-vxworks` | ? |  |
 `powerpc64le-unknown-linux-musl` | ? |  |
+`riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
 `sparc-unknown-linux-gnu` | âœ“ |  | 32-bit SPARC Linux
 `sparc64-unknown-netbsd` | âœ“ | âœ“ | NetBSD/sparc64
 `sparc64-unknown-openbsd` | ? |  |
index 28a5fe31fc4b5f328e0be7dc72cf3a7e09a54d80..df113f0f1613c3fd33d37a13ae1fa9fb992350b7 100644 (file)
@@ -345,6 +345,25 @@ The `h` modifier will emit the register name for the high byte of that register
 
 If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.
 
+## Memory address operands
+
+Sometimes assembly instructions require operands passed via memory addresses/memory locations.
+You have to manually use the memory address syntax specified by the respectively architectures.
+For example, in x86/x86_64 and intel assembly syntax, you should wrap inputs/outputs in `[]`
+to indicate they are memory operands:
+
+```rust,allow_fail
+# #![feature(asm, llvm_asm)]
+# fn load_fpu_control_word(control: u16) {
+unsafe {
+    asm!("fldcw [{}]", in(reg) &control, options(nostack));
+
+    // Previously this would have been written with the deprecated `llvm_asm!` like this
+    llvm_asm!("fldcw $0" :: "m" (control) :: "volatile");
+}
+# }
+```
+
 ## Options
 
 By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.
index da01d9228f14e0ff12177e7694205a4f9a6ed095..a2f029db2916551e68afe12b388612747ce573b0 100644 (file)
@@ -159,12 +159,12 @@ specify some extra info about the inline assembly:
 
 Current valid options are:
 
-1. *volatile* - specifying this is analogous to
+1. `volatile` - specifying this is analogous to
    `__asm__ __volatile__ (...)` in gcc/clang.
-2. *alignstack* - certain instructions expect the stack to be
+2. `alignstack` - certain instructions expect the stack to be
    aligned a certain way (i.e. SSE) and specifying this indicates to
    the compiler to insert its usual stack alignment code
-3. *intel* - use intel syntax instead of the default AT&T.
+3. `intel` - use intel syntax instead of the default AT&T.
 
 ```rust
 # #![feature(llvm_asm)]
index 90d2a18ea58198a7bb15231ff64f154c56e78230..a40a44fe27da3edb9aace137a22d08ed93c4239a 100644 (file)
@@ -8,7 +8,7 @@ edition = "2018"
 path = "lib.rs"
 
 [dependencies]
-pulldown-cmark = { version = "0.7", default-features = false }
+pulldown-cmark = { version = "0.8", default-features = false }
 minifier = "0.0.33"
 rayon = { version = "0.3.0", package = "rustc-rayon" }
 serde = { version = "1.0", features = ["derive"] }
index 6a75a9bfb74d7d5a3999a0ebc69703feef4ee159..46ba14aa67e60d7fb35ffd59ce961ec71d569451 100644 (file)
@@ -840,7 +840,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Generics {
         let mut where_predicates =
             where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
 
-        // Type parameters and have a Sized bound by default unless removed with
+        // Type parameters have a Sized bound by default unless removed with
         // ?Sized. Scan through the predicates and mark any type parameter with
         // a Sized bound, removing the bounds as we find them.
         //
index a8c60e4a76df4d8d38c315eb0c7e51af64ad1ff1..6c0f1c02ac6da77d48c602932c30957d4742b8ff 100644 (file)
@@ -27,7 +27,6 @@
 use rustc_span::edition::Edition;
 use rustc_span::Span;
 use std::borrow::Cow;
-use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt::Write;
@@ -39,7 +38,7 @@
 use crate::html::highlight;
 use crate::html::toc::TocBuilder;
 
-use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
+use pulldown_cmark::{html, BrokenLink, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
 
 #[cfg(test)]
 mod tests;
@@ -931,15 +930,17 @@ pub fn into_string(self) -> String {
         if md.is_empty() {
             return String::new();
         }
-        let replacer = |_: &str, s: &str| {
-            if let Some(link) = links.iter().find(|link| &*link.original_text == s) {
-                Some((link.href.clone(), link.new_text.clone()))
+        let mut replacer = |broken_link: BrokenLink<'_>| {
+            if let Some(link) =
+                links.iter().find(|link| &*link.original_text == broken_link.reference)
+            {
+                Some((link.href.as_str().into(), link.new_text.as_str().into()))
             } else {
                 None
             }
         };
 
-        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&replacer));
+        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
@@ -1009,9 +1010,11 @@ pub fn into_string(self) -> String {
             return String::new();
         }
 
-        let replacer = |_: &str, s: &str| {
-            if let Some(link) = links.iter().find(|link| &*link.original_text == s) {
-                Some((link.href.clone(), link.new_text.clone()))
+        let mut replacer = |broken_link: BrokenLink<'_>| {
+            if let Some(link) =
+                links.iter().find(|link| &*link.original_text == broken_link.reference)
+            {
+                Some((link.href.as_str().into(), link.new_text.as_str().into()))
             } else {
                 None
             }
@@ -1020,7 +1023,7 @@ pub fn into_string(self) -> String {
         let p = Parser::new_with_broken_link_callback(
             md,
             Options::ENABLE_STRIKETHROUGH,
-            Some(&replacer),
+            Some(&mut replacer),
         );
 
         let mut s = String::new();
@@ -1067,7 +1070,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
     }
 
     let mut links = vec![];
-    let shortcut_links = RefCell::new(vec![]);
+    let mut shortcut_links = vec![];
 
     {
         let locate = |s: &str| unsafe {
@@ -1084,11 +1087,13 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
             }
         };
 
-        let push = |_: &str, s: &str| {
-            shortcut_links.borrow_mut().push((s.to_owned(), locate(s)));
+        let mut push = |link: BrokenLink<'_>| {
+            // FIXME: use `link.span` instead of `locate`
+            // (doing it now includes the `[]` as well as the text)
+            shortcut_links.push((link.reference.to_owned(), locate(link.reference)));
             None
         };
-        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&push));
+        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push));
 
         // There's no need to thread an IdMap through to here because
         // the IDs generated aren't going to be emitted anywhere.
@@ -1106,8 +1111,7 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
         }
     }
 
-    let mut shortcut_links = shortcut_links.into_inner();
-    links.extend(shortcut_links.drain(..));
+    links.append(&mut shortcut_links);
 
     links
 }
index 73a783d54060c4722f8668a398f1f8d9cd0d2026..7762e8f8d4fb181fac97fd8c406b453f4c64b92d 100644 (file)
 
 #[macro_use]
 extern crate lazy_static;
+#[macro_use]
+extern crate tracing;
+
+// N.B. these need `extern crate` even in 2018 edition
+// because they're loaded implicitly from the sysroot.
+// The reason they're loaded from the sysroot is because
+// the rustdoc artifacts aren't stored in rustc's cargo target directory.
+// So if `rustc` was specified in Cargo.toml, this would spuriously rebuild crates.
+//
+// Dependencies listed in Cargo.toml do not need `extern crate`.
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
@@ -42,8 +52,6 @@
 extern crate rustc_trait_selection;
 extern crate rustc_typeck;
 extern crate test as testing;
-#[macro_use]
-extern crate tracing;
 
 use std::default::Default;
 use std::env;
index cbbe86dc433f33456a7343750e21f044bbf51eda..78af9f9b8561a646ef1af4a7d2cbcf3b4e8a17bd 100644 (file)
@@ -8,7 +8,7 @@
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::{find_testable_code, ErrorCodes, LangString};
+use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
 use rustc_session::lint;
 
 pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
@@ -48,15 +48,11 @@ pub(crate) struct Tests {
     pub(crate) found_tests: usize,
 }
 
-impl Tests {
-    pub(crate) fn new() -> Tests {
-        Tests { found_tests: 0 }
-    }
-}
-
 impl crate::doctest::Tester for Tests {
-    fn add_test(&mut self, _: String, _: LangString, _: usize) {
-        self.found_tests += 1;
+    fn add_test(&mut self, _: String, config: LangString, _: usize) {
+        if config.rust && config.ignore == Ignore::None {
+            self.found_tests += 1;
+        }
     }
 }
 
@@ -85,7 +81,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
         }
     };
 
-    let mut tests = Tests::new();
+    let mut tests = Tests { found_tests: 0 };
 
     find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
 
diff --git a/src/test/codegen/issue-73396-bounds-check-after-position.rs b/src/test/codegen/issue-73396-bounds-check-after-position.rs
new file mode 100644 (file)
index 0000000..e5f3ae4
--- /dev/null
@@ -0,0 +1,78 @@
+// min-llvm-version: 11.0.0
+// compile-flags: -O
+// ignore-debug: the debug assertions get in the way
+#![crate_type = "lib"]
+
+// Make sure no bounds checks are emitted when slicing or indexing
+// with an index from `position()` or `rposition()`.
+
+// CHECK-LABEL: @position_slice_to_no_bounds_check
+#[no_mangle]
+pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+        &s[..idx]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @position_slice_from_no_bounds_check
+#[no_mangle]
+pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+        &s[idx..]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @position_index_no_bounds_check
+#[no_mangle]
+pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().position(|b| *b == b'\\') {
+        s[idx]
+    } else {
+        42
+    }
+}
+// CHECK-LABEL: @rposition_slice_to_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+        &s[..idx]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @rposition_slice_from_no_bounds_check
+#[no_mangle]
+pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+        &s[idx..]
+    } else {
+        s
+    }
+}
+
+// CHECK-LABEL: @rposition_index_no_bounds_check
+#[no_mangle]
+pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
+    // CHECK-NOT: panic
+    // CHECK-NOT: slice_index_len_fail
+    if let Some(idx) = s.iter().rposition(|b| *b == b'\\') {
+        s[idx]
+    } else {
+        42
+    }
+}
index 10ed13c9ff566c76d169649cc58949d7031dd442..8188740f8739bde325aea289b9119bcac222c35a 100644 (file)
@@ -1,7 +1,7 @@
 +-------------------------------------+------------+------------+------------+------------+
 | File                                | Documented | Percentage |   Examples | Percentage |
 +-------------------------------------+------------+------------+------------+------------+
-| ...tdoc-ui/coverage/doc-examples.rs |          4 |     100.0% |          2 |      50.0% |
+| ...tdoc-ui/coverage/doc-examples.rs |          4 |     100.0% |          1 |      25.0% |
 +-------------------------------------+------------+------------+------------+------------+
-| Total                               |          4 |     100.0% |          2 |      50.0% |
+| Total                               |          4 |     100.0% |          1 |      25.0% |
 +-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/intra-link-double-anchor.rs b/src/test/rustdoc-ui/intra-link-double-anchor.rs
new file mode 100644 (file)
index 0000000..a01211c
--- /dev/null
@@ -0,0 +1,7 @@
+// check-pass
+
+// regression test for #73264
+// should only give one error
+/// docs [label][with#anchor#error]
+//~^ WARNING multiple anchors
+pub struct S;
diff --git a/src/test/rustdoc-ui/intra-link-double-anchor.stderr b/src/test/rustdoc-ui/intra-link-double-anchor.stderr
new file mode 100644 (file)
index 0000000..3282ec8
--- /dev/null
@@ -0,0 +1,10 @@
+warning: `with#anchor#error` contains multiple anchors
+  --> $DIR/intra-link-double-anchor.rs:5:18
+   |
+LL | /// docs [label][with#anchor#error]
+   |                  ^^^^^^^^^^^^^^^^^ contains invalid anchor
+   |
+   = note: `#[warn(broken_intra_doc_links)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/private-doc-test.rs b/src/test/rustdoc-ui/private-doc-test.rs
new file mode 100644 (file)
index 0000000..379fa45
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![deny(private_doc_tests)]
+
+mod foo {
+    /// private doc test
+    ///
+    /// ```ignore (used for testing ignored doc tests)
+    /// assert!(false);
+    /// ```
+    fn bar() {}
+}
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/cannot-infer-const-args.full.stderr
deleted file mode 100644 (file)
index 0531397..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-const-args.rs:12:5
-   |
-LL |     foo();
-   |     ^^^
-   |
-   = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/cannot-infer-const-args.min.stderr
deleted file mode 100644 (file)
index 0531397..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-const-args.rs:12:5
-   |
-LL |     foo();
-   |     ^^^
-   |
-   = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.rs b/src/test/ui/const-generics/cannot-infer-const-args.rs
deleted file mode 100644 (file)
index 2d74b47..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(min, feature(min_const_generics))]
-
-fn foo<const X: usize>() -> usize {
-    0
-}
-
-fn main() {
-    foo(); //~ ERROR type annotations needed
-}
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
new file mode 100644 (file)
index 0000000..84e75cc
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-const-args.rs:12:5
+   |
+LL |     foo();
+   |     ^^^
+   |
+   = note: cannot infer the value of the const parameter `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
new file mode 100644 (file)
index 0000000..84e75cc
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-const-args.rs:12:5
+   |
+LL |     foo();
+   |     ^^^
+   |
+   = note: cannot infer the value of the const parameter `X`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.rs b/src/test/ui/const-generics/infer/cannot-infer-const-args.rs
new file mode 100644 (file)
index 0000000..2d74b47
--- /dev/null
@@ -0,0 +1,13 @@
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+fn foo<const X: usize>() -> usize {
+    0
+}
+
+fn main() {
+    foo(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr
new file mode 100644 (file)
index 0000000..e65bc3f
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-chain.rs:21:33
+   |
+LL |     Foo.bar().bar().bar().bar().baz();
+   |                                 ^^^
+   |
+   = note: cannot infer the value of the const parameter `N`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr
new file mode 100644 (file)
index 0000000..e65bc3f
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-chain.rs:21:33
+   |
+LL |     Foo.bar().bar().bar().bar().baz();
+   |                                 ^^^
+   |
+   = note: cannot infer the value of the const parameter `N`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.rs b/src/test/ui/const-generics/infer/method-chain.rs
new file mode 100644 (file)
index 0000000..9389ca2
--- /dev/null
@@ -0,0 +1,22 @@
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+struct Foo;
+
+impl Foo {
+    fn bar(self) -> Foo {
+        Foo
+    }
+
+    fn baz<const N: usize>(self) -> Foo {
+        println!("baz: {}", N);
+        Foo
+    }
+}
+
+fn main() {
+    Foo.bar().bar().bar().bar().baz(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
new file mode 100644 (file)
index 0000000..e47b6bd
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/uninferred-consts.rs:14:9
+   |
+LL |     Foo.foo();
+   |         ^^^
+   |
+   = note: cannot infer the value of the const parameter `N`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
new file mode 100644 (file)
index 0000000..e47b6bd
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/uninferred-consts.rs:14:9
+   |
+LL |     Foo.foo();
+   |         ^^^
+   |
+   = note: cannot infer the value of the const parameter `N`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.rs b/src/test/ui/const-generics/infer/uninferred-consts.rs
new file mode 100644 (file)
index 0000000..ec5b3ff
--- /dev/null
@@ -0,0 +1,16 @@
+// Test that we emit an error if we cannot properly infer a constant.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
+struct Foo;
+impl Foo {
+    fn foo<const N: usize>(self) {}
+}
+fn main() {
+    Foo.foo();
+    //~^ ERROR type annotations needed
+}
index 69fe0974a791a166040d65a526d756fad617d37c..07822f86f524b621e6c60f28ef5de0d35a88486e 100644 (file)
@@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
    |                                      ^^^^^^ non-trivial anonymous constants must not depend on the parameter `T`
    |
-   = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: generic parameters must not be used inside of non trivial constant values
   --> $DIR/issue-64494.rs:19:38
@@ -12,7 +12,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
    |                                      ^^^^^^ non-trivial anonymous constants must not depend on the parameter `T`
    |
-   = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error[E0119]: conflicting implementations of trait `MyTrait`:
   --> $DIR/issue-64494.rs:19:1
index 1254ee7239dc78877e4e205ad0a717ba89b0b270..68f1733decb93e03d1a455db3cae59714d522a8c 100644 (file)
@@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL |         [0u8; mem::size_of::<Self::Associated>()];
    |                              ^^^^^^^^^^^^^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
    |
-   = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr
new file mode 100644 (file)
index 0000000..089937e
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-76701-ty-param-in-const.rs:6:21
+   |
+LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-76701-ty-param-in-const.rs:12:37
+   |
+LL | fn const_param<const N: usize>() -> [u8; N + 1] {
+   |                                     ^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr
new file mode 100644 (file)
index 0000000..a39495e
--- /dev/null
@@ -0,0 +1,18 @@
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/issue-76701-ty-param-in-const.rs:6:46
+   |
+LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
+   |                                              ^ non-trivial anonymous constants must not depend on the parameter `T`
+   |
+   = note: type parameters are currently not permitted in anonymous constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/issue-76701-ty-param-in-const.rs:12:42
+   |
+LL | fn const_param<const N: usize>() -> [u8; N + 1] {
+   |                                          ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs
new file mode 100644 (file)
index 0000000..9252b59
--- /dev/null
@@ -0,0 +1,18 @@
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
+    //[full]~^ ERROR constant expression depends on a generic parameter
+    //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
+    todo!()
+}
+
+fn const_param<const N: usize>() -> [u8; N + 1] {
+    //[full]~^ ERROR constant expression depends on a generic parameter
+    //[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
+    todo!()
+}
+
+fn main() {}
index 89ce58564e465d04d6b5d7380acafb784b999dd6..edb77a87430611c09c59161cba91d0a556f12f36 100644 (file)
@@ -4,7 +4,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL |     fn t1() -> [u8; std::mem::size_of::<Self>()];
    |                                         ^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
    |
-   = help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: generic `Self` types are currently not permitted in anonymous constants
   --> $DIR/self-ty-in-const-1.rs:14:41
index 461822a96083b187a6fb2d7cd4abfbfeb2e277c2..e545ae8571f67d7ee7780bd20ddea1a02629f093 100644 (file)
@@ -12,7 +12,7 @@ error: generic parameters must not be used inside of non trivial constant values
 LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ non-trivial anonymous constants must not depend on the parameter `T`
    |
-   = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+   = note: type parameters are currently not permitted in anonymous constants
 
 error: constant values inside of type parameter defaults must not depend on generic parameters
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21
index 1d42afa3f8461de59044ed35380182c730f91b0a..f3b19109a7c80e14cd49faf608ae1cb7966f8802 100644 (file)
@@ -5,21 +5,21 @@
 #![cfg_attr(min, feature(min_const_generics))]
 
 trait SliceExt<T: Clone> {
-    fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N>;
+    fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N>;
 }
 
 impl <T: Clone> SliceExt<T> for [T] {
-   fn array_windows<'a, const N: usize>(&'a self) -> ArrayWindows<'a, T, N> {
-       ArrayWindows{ idx: 0, slice: &self }
+   fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N> {
+       ArrayWindowsExample{ idx: 0, slice: &self }
    }
 }
 
-struct ArrayWindows<'a, T, const N: usize> {
+struct ArrayWindowsExample<'a, T, const N: usize> {
     slice: &'a [T],
     idx: usize,
 }
 
-impl <'a, T: Clone, const N: usize> Iterator for ArrayWindows<'a, T, N> {
+impl <'a, T: Clone, const N: usize> Iterator for ArrayWindowsExample<'a, T, N> {
     type Item = [T; N];
     fn next(&mut self) -> Option<Self::Item> {
         // Note: this is unsound for some `T` and not meant as an example
@@ -45,7 +45,7 @@ fn next(&mut self) -> Option<Self::Item> {
 fn main() {
     let v: Vec<usize> = vec![0; 100];
 
-    for array in v.as_slice().array_windows::<FOUR>() {
+    for array in v.as_slice().array_windows_example::<FOUR>() {
         assert_eq!(array, [0, 0, 0, 0])
     }
 }
diff --git a/src/test/ui/const-generics/uninferred-consts.full.stderr b/src/test/ui/const-generics/uninferred-consts.full.stderr
deleted file mode 100644 (file)
index 2c5af9e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:14:5
-   |
-LL |     Foo.foo();
-   |     ^^^^^^^^^
-   |
-   = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/uninferred-consts.min.stderr b/src/test/ui/const-generics/uninferred-consts.min.stderr
deleted file mode 100644 (file)
index 2c5af9e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:14:5
-   |
-LL |     Foo.foo();
-   |     ^^^^^^^^^
-   |
-   = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/uninferred-consts.rs b/src/test/ui/const-generics/uninferred-consts.rs
deleted file mode 100644 (file)
index ec5b3ff..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Test that we emit an error if we cannot properly infer a constant.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(min, feature(min_const_generics))]
-
-// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
-struct Foo;
-impl Foo {
-    fn foo<const N: usize>(self) {}
-}
-fn main() {
-    Foo.foo();
-    //~^ ERROR type annotations needed
-}
diff --git a/src/test/ui/consts/duration-consts-2.rs b/src/test/ui/consts/duration-consts-2.rs
deleted file mode 100644 (file)
index bc0969e..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// run-pass
-
-#![feature(const_panic)]
-#![feature(duration_consts_2)]
-#![feature(div_duration)]
-#![feature(duration_saturating_ops)]
-
-use std::time::Duration;
-
-fn duration() {
-    const ZERO : Duration = Duration::new(0, 0);
-    assert_eq!(ZERO, Duration::from_secs(0));
-
-    const ONE : Duration = Duration::new(0, 1);
-    assert_eq!(ONE, Duration::from_nanos(1));
-
-    const MAX : Duration = Duration::new(u64::MAX, 1_000_000_000 - 1);
-
-    const MAX_CHECKED_ADD_ZERO : Option<Duration> = MAX.checked_add(ZERO);
-    assert_eq!(MAX_CHECKED_ADD_ZERO, Some(MAX));
-
-    const MAX_CHECKED_ADD_ONE : Option<Duration> = MAX.checked_add(ONE);
-    assert_eq!(MAX_CHECKED_ADD_ONE, None);
-
-    const ONE_CHECKED_SUB_ONE : Option<Duration> = ONE.checked_sub(ONE);
-    assert_eq!(ONE_CHECKED_SUB_ONE, Some(ZERO));
-
-    const ZERO_CHECKED_SUB_ONE : Option<Duration> = ZERO.checked_sub(ONE);
-    assert_eq!(ZERO_CHECKED_SUB_ONE, None);
-
-    const ONE_CHECKED_MUL_ONE : Option<Duration> = ONE.checked_mul(1);
-    assert_eq!(ONE_CHECKED_MUL_ONE, Some(ONE));
-
-    const MAX_CHECKED_MUL_TWO : Option<Duration> = MAX.checked_mul(2);
-    assert_eq!(MAX_CHECKED_MUL_TWO, None);
-
-    const ONE_CHECKED_DIV_ONE : Option<Duration> = ONE.checked_div(1);
-    assert_eq!(ONE_CHECKED_DIV_ONE, Some(ONE));
-
-    const ONE_CHECKED_DIV_ZERO : Option<Duration> = ONE.checked_div(0);
-    assert_eq!(ONE_CHECKED_DIV_ZERO, None);
-
-    const MAX_AS_F32 : f32 = MAX.as_secs_f32();
-    assert_eq!(MAX_AS_F32, 18446744000000000000.0_f32);
-
-    const MAX_AS_F64 : f64 = MAX.as_secs_f64();
-    assert_eq!(MAX_AS_F64, 18446744073709552000.0_f64);
-
-    const ONE_AS_F32 : f32 = ONE.div_duration_f32(ONE);
-    assert_eq!(ONE_AS_F32, 1.0_f32);
-
-    const ONE_AS_F64 : f64 = ONE.div_duration_f64(ONE);
-    assert_eq!(ONE_AS_F64, 1.0_f64);
-
-    const MAX_SATURATING_ADD_ONE : Duration = MAX.saturating_add(ONE);
-    assert_eq!(MAX_SATURATING_ADD_ONE, MAX);
-
-    const ZERO_SATURATING_SUB_ONE : Duration = ZERO.saturating_sub(ONE);
-    assert_eq!(ZERO_SATURATING_SUB_ONE, ZERO);
-
-    const MAX_SATURATING_MUL_TWO : Duration = MAX.saturating_mul(2);
-    assert_eq!(MAX_SATURATING_MUL_TWO, MAX);
-}
-
-fn main() {
-    duration();
-}
index 1770d71e2e2fe6f12d2921aa17ce029995aa2e87..fb884e3129999c3246f085522ebc6e553705c25a 100644 (file)
@@ -149,7 +149,7 @@ error: function cannot return without recursing
 LL |     fn deref(&self) -> &Baz {
    |     ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
 LL |         self.as_ref()
-   |         ---- recursive call site
+   |         ------------- recursive call site
    |
    = help: a `loop` may express intention better if this is on purpose
 
diff --git a/src/test/ui/moves/move-deref-coercion.rs b/src/test/ui/moves/move-deref-coercion.rs
new file mode 100644 (file)
index 0000000..4115438
--- /dev/null
@@ -0,0 +1,33 @@
+use std::ops::Deref;
+
+struct NotCopy {
+    inner: bool
+}
+
+impl NotCopy {
+    fn inner_method(&self) {}
+}
+
+struct Foo {
+    first: NotCopy,
+    second: NotCopy
+}
+
+impl Deref for Foo {
+    type Target = NotCopy;
+    fn deref(&self) -> &NotCopy {
+        &self.second
+    }
+}
+
+fn use_field(val: Foo) {
+    let _val = val.first;
+    val.inner; //~ ERROR borrow of
+}
+
+fn use_method(val: Foo) {
+    let _val = val.first;
+    val.inner_method(); //~ ERROR borrow of
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/move-deref-coercion.stderr b/src/test/ui/moves/move-deref-coercion.stderr
new file mode 100644 (file)
index 0000000..e3bdf6d
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0382]: borrow of partially moved value: `val`
+  --> $DIR/move-deref-coercion.rs:25:5
+   |
+LL |     let _val = val.first;
+   |                --------- value partially moved here
+LL |     val.inner;
+   |     ^^^^^^^^^ value borrowed here after partial move
+   |
+   = note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait
+   = note: borrow occurs due to deref coercion to `NotCopy`
+note: deref defined here
+  --> $DIR/move-deref-coercion.rs:17:5
+   |
+LL |     type Target = NotCopy;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0382]: borrow of partially moved value: `val`
+  --> $DIR/move-deref-coercion.rs:30:5
+   |
+LL |     let _val = val.first;
+   |                --------- value partially moved here
+LL |     val.inner_method();
+   |     ^^^^^^^^^^^^^^^^^^ value borrowed here after partial move
+   |
+   = note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait
+   = note: borrow occurs due to deref coercion to `NotCopy`
+note: deref defined here
+  --> $DIR/move-deref-coercion.rs:17:5
+   |
+LL |     type Target = NotCopy;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
index 0081841fec0907c669f6840c513ed1790d17aa8d..37032e73f1900c2a21bdfc55821ea77ed476fb52 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `arc_v`
-  --> $DIR/no-capture-arc.rs:14:18
+  --> $DIR/no-capture-arc.rs:14:16
    |
 LL |     let arc_v = Arc::new(v);
    |         ----- move occurs because `arc_v` has type `Arc<Vec<i32>>`, which does not implement the `Copy` trait
@@ -10,7 +10,14 @@ LL |         assert_eq!((*arc_v)[3], 4);
    |                      ----- variable moved due to use in closure
 ...
 LL |     assert_eq!((*arc_v)[2], 3);
-   |                  ^^^^^ value borrowed here after move
+   |                ^^^^^^^^ value borrowed here after move
+   |
+   = note: borrow occurs due to deref coercion to `Vec<i32>`
+note: deref defined here
+  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
+   |
+LL |     type Target = T;
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index bb4e0871224a283bd8cc0ec38fdd92274686eade..6f37d4c9d869125a8ea59a314edebf5f1577efae 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `arc_v`
-  --> $DIR/no-reuse-move-arc.rs:12:18
+  --> $DIR/no-reuse-move-arc.rs:12:16
    |
 LL |     let arc_v = Arc::new(v);
    |         ----- move occurs because `arc_v` has type `Arc<Vec<i32>>`, which does not implement the `Copy` trait
@@ -10,7 +10,14 @@ LL |         assert_eq!((*arc_v)[3], 4);
    |                      ----- variable moved due to use in closure
 ...
 LL |     assert_eq!((*arc_v)[2], 3);
-   |                  ^^^^^ value borrowed here after move
+   |                ^^^^^^^^ value borrowed here after move
+   |
+   = note: borrow occurs due to deref coercion to `Vec<i32>`
+note: deref defined here
+  --> $SRC_DIR/alloc/src/sync.rs:LL:COL
+   |
+LL |     type Target = T;
+   |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/numbers-arithmetic/arith-0.rs b/src/test/ui/numbers-arithmetic/arith-0.rs
deleted file mode 100644 (file)
index 7943cb9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// run-pass
-
-
-pub fn main() {
-    let a: isize = 10;
-    println!("{}", a);
-    assert_eq!(a * (a - 1), 90);
-}
diff --git a/src/test/ui/numbers-arithmetic/arith-1.rs b/src/test/ui/numbers-arithmetic/arith-1.rs
deleted file mode 100644 (file)
index c13c8d8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-
-
-pub fn main() {
-    let i32_a: isize = 10;
-    assert_eq!(i32_a, 10);
-    assert_eq!(i32_a - 10, 0);
-    assert_eq!(i32_a / 10, 1);
-    assert_eq!(i32_a - 20, -10);
-    assert_eq!(i32_a << 10, 10240);
-    assert_eq!(i32_a << 16, 655360);
-    assert_eq!(i32_a * 16, 160);
-    assert_eq!(i32_a * i32_a * i32_a, 1000);
-    assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000);
-    assert_eq!(i32_a * i32_a / i32_a * i32_a, 100);
-    assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640);
-    let i32_b: isize = 0x10101010;
-    assert_eq!(i32_b + 1 - 1, i32_b);
-    assert_eq!(i32_b << 1, i32_b << 1);
-    assert_eq!(i32_b >> 1, i32_b >> 1);
-    assert_eq!(i32_b & i32_b << 1, 0);
-    println!("{}", i32_b | i32_b << 1);
-    assert_eq!(i32_b | i32_b << 1, 0x30303030);
-}
diff --git a/src/test/ui/numbers-arithmetic/arith-2.rs b/src/test/ui/numbers-arithmetic/arith-2.rs
deleted file mode 100644 (file)
index 46c2806..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-
-
-
-pub fn main() {
-    let i32_c: isize = 0x10101010;
-    assert_eq!(i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3),
-                 i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3));
-}
diff --git a/src/test/ui/parser/issue-73568-lifetime-after-mut.rs b/src/test/ui/parser/issue-73568-lifetime-after-mut.rs
new file mode 100644 (file)
index 0000000..0b10a5f
--- /dev/null
@@ -0,0 +1,21 @@
+#![crate_type="lib"]
+fn x<'a>(x: &mut 'a i32){} //~ ERROR lifetime must precede `mut`
+
+macro_rules! mac {
+    ($lt:lifetime) => {
+        fn w<$lt>(w: &mut $lt i32) {}
+        //~^ ERROR lifetime must precede `mut`
+    }
+}
+
+mac!('a);
+
+// avoid false positives
+fn y<'a>(y: &mut 'a + Send) {
+    //~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a`
+    //~| WARNING trait objects without an explicit `dyn` are deprecated
+    //~| ERROR at least one trait is required for an object type
+    let z = y as &mut 'a + Send;
+    //~^ ERROR expected value, found trait `Send`
+    //~| WARNING trait objects without an explicit `dyn` are deprecated
+}
diff --git a/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr b/src/test/ui/parser/issue-73568-lifetime-after-mut.stderr
new file mode 100644 (file)
index 0000000..abb64f7
--- /dev/null
@@ -0,0 +1,53 @@
+error: lifetime must precede `mut`
+  --> $DIR/issue-73568-lifetime-after-mut.rs:2:13
+   |
+LL | fn x<'a>(x: &mut 'a i32){}
+   |             ^^^^^^^ help: place the lifetime before `mut`: `&'a mut`
+
+error[E0178]: expected a path on the left-hand side of `+`, not `&mut 'a`
+  --> $DIR/issue-73568-lifetime-after-mut.rs:14:13
+   |
+LL | fn y<'a>(y: &mut 'a + Send) {
+   |             ^^^^^^^^^^^^^^ help: try adding parentheses: `&mut ('a + Send)`
+
+error: lifetime must precede `mut`
+  --> $DIR/issue-73568-lifetime-after-mut.rs:6:22
+   |
+LL |         fn w<$lt>(w: &mut $lt i32) {}
+   |                      ^^^^^^^^ help: place the lifetime before `mut`: `&$lt mut`
+...
+LL | mac!('a);
+   | --------- in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0423]: expected value, found trait `Send`
+  --> $DIR/issue-73568-lifetime-after-mut.rs:18:28
+   |
+LL |     let z = y as &mut 'a + Send;
+   |                            ^^^^ not a value
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/issue-73568-lifetime-after-mut.rs:14:18
+   |
+LL | fn y<'a>(y: &mut 'a + Send) {
+   |                  ^^ help: use `dyn`: `dyn 'a`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/issue-73568-lifetime-after-mut.rs:18:23
+   |
+LL |     let z = y as &mut 'a + Send;
+   |                       ^^ help: use `dyn`: `dyn 'a`
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/issue-73568-lifetime-after-mut.rs:14:18
+   |
+LL | fn y<'a>(y: &mut 'a + Send) {
+   |                  ^^
+
+error: aborting due to 5 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0178, E0224, E0423.
+For more information about an error, try `rustc --explain E0178`.
diff --git a/src/test/ui/str-multiline.rs b/src/test/ui/str-multiline.rs
deleted file mode 100644 (file)
index 2b2e001..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-
-pub fn main() {
-    let a: String = "this \
-is a test".to_string();
-    let b: String =
-        "this \
-              is \
-              another \
-              test".to_string();
-    assert_eq!(a, "this is a test".to_string());
-    assert_eq!(b, "this is another test".to_string());
-}
diff --git a/src/test/ui/string-escapes.rs b/src/test/ui/string-escapes.rs
deleted file mode 100644 (file)
index cee5e27..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// run-pass
-
-fn main() {
-    let x = "\\\\\
-    ";
-    assert_eq!(x, r"\\"); // extraneous whitespace stripped
-}
diff --git a/src/test/ui/trait-impl-bound-suggestions.fixed b/src/test/ui/trait-impl-bound-suggestions.fixed
new file mode 100644 (file)
index 0000000..db3a95f
--- /dev/null
@@ -0,0 +1,20 @@
+// run-rustfix
+
+#[allow(unused)]
+use std::fmt::Debug;
+// Rustfix should add this, or use `std::fmt::Debug` instead.
+
+#[allow(dead_code)]
+struct ConstrainedStruct<X: Copy> {
+    x: X
+}
+
+#[allow(dead_code)]
+trait InsufficientlyConstrainedGeneric<X=()> where X: Copy {
+    fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+        //~^ ERROR the trait bound `X: Copy` is not satisfied
+        ConstrainedStruct { x }
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/trait-impl-bound-suggestions.rs b/src/test/ui/trait-impl-bound-suggestions.rs
new file mode 100644 (file)
index 0000000..bf75175
--- /dev/null
@@ -0,0 +1,20 @@
+// run-rustfix
+
+#[allow(unused)]
+use std::fmt::Debug;
+// Rustfix should add this, or use `std::fmt::Debug` instead.
+
+#[allow(dead_code)]
+struct ConstrainedStruct<X: Copy> {
+    x: X
+}
+
+#[allow(dead_code)]
+trait InsufficientlyConstrainedGeneric<X=()> {
+    fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+        //~^ ERROR the trait bound `X: Copy` is not satisfied
+        ConstrainedStruct { x }
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/trait-impl-bound-suggestions.stderr b/src/test/ui/trait-impl-bound-suggestions.stderr
new file mode 100644 (file)
index 0000000..3a21e9c
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `X: Copy` is not satisfied
+  --> $DIR/trait-impl-bound-suggestions.rs:14:52
+   |
+LL | struct ConstrainedStruct<X: Copy> {
+   |                             ---- required by this bound in `ConstrainedStruct`
+...
+LL |     fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
+   |                                                    ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X`
+   |
+help: consider further restricting type parameter `X`
+   |
+LL | trait InsufficientlyConstrainedGeneric<X=()> where X: Copy {
+   |                                              ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index fa6f342241025b9e2a7cab7108a9039652a54972..d8c7f595e62efcdf03555cd975d71761e7a7e586 100644 (file)
@@ -56,8 +56,8 @@ LL | trait Base<T = String>: Super<T> { }
    |
 help: consider further restricting type parameter `T`
    |
-LL | trait Base<T = String>: Super<T>, T: Copy { }
-   |                                 ^^^^^^^^^
+LL | trait Base<T = String>: Super<T> where T: Copy { }
+   |                                  ^^^^^^^^^^^^^
 
 error[E0277]: cannot add `u8` to `i32`
   --> $DIR/type-check-defaults.rs:24:66
index 875e0123259b0b6299903fe4aea0a12ecde9324f..8777a6b1e8834899f51b7e09cc9b8d85b2417110 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 875e0123259b0b6299903fe4aea0a12ecde9324f
+Subproject commit 8777a6b1e8834899f51b7e09cc9b8d85b2417110
index 5323bc357c09dd5ffbce9480d6731ffceb56b980..92b3d186fa141a6294cf22f70a5a5649af9417ec 100644 (file)
@@ -402,9 +402,12 @@ fn generate_lint_output(
                 None => {
                     let rendered: Vec<&str> =
                         msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
+                    let non_json: Vec<&str> =
+                        stderr.lines().filter(|line| !line.starts_with('{')).collect();
                     Err(format!(
-                        "did not find lint `{}` in output of example, got:\n{}",
+                        "did not find lint `{}` in output of example, got:\n{}\n{}",
                         name,
+                        non_json.join("\n"),
                         rendered.join("\n")
                     )
                     .into())
index 0275b08d1521606fa733f76fe5d5707717456fb4..0d03fe6ef57d3956e92382e0e1f1a916015191cb 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0275b08d1521606fa733f76fe5d5707717456fb4
+Subproject commit 0d03fe6ef57d3956e92382e0e1f1a916015191cb