From 1975b8d21b21d5ede54494d0b7661d6ac14ec6a2 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 29 Aug 2018 17:20:17 +0200 Subject: [PATCH 01/24] Document that slices cannot be larger than `isize::MAX` bytes Fixes #53676. --- src/libcore/slice/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 62adaea168a3f..7f623486cdf08 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3851,6 +3851,9 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// them from other data. You can obtain a pointer that is usable as `data` /// for zero-length slices using [`NonNull::dangling()`]. /// +/// The total size of the slice must be no larger than `isize::MAX` **bytes** +/// in memory. See the safety documentation of [`pointer::offset`]. +/// /// # Caveat /// /// The lifetime for the returned slice is inferred from its usage. To @@ -3872,6 +3875,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// ``` /// /// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling +/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { From 7b77508e233c724bcaf9821f62dbe45dc4b4cdb3 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 4 Sep 2018 11:22:25 +0200 Subject: [PATCH 02/24] Add `debug_assert!`s to `slice::from_raw_parts` Copy the documentation over to `slice::from_raw_parts_mut`. --- src/libcore/slice/mod.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 7f623486cdf08..44d2243c2ccd5 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -34,6 +34,7 @@ use cmp::Ordering::{self, Less, Equal, Greater}; use cmp; use fmt; use intrinsics::assume; +use isize; use iter::*; use ops::{FnMut, Try, self}; use option::Option; @@ -3880,6 +3881,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); + debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3889,14 +3892,20 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// This function is unsafe for the same reasons as [`from_raw_parts`], as well /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length -/// slices as with [`from_raw_parts`]. See the documentation of -/// [`from_raw_parts`] for more details. +/// slices as with [`from_raw_parts`]. The total size of the slice must be no +/// larger than `isize::MAX` **bytes** in memory. See the safety documentation +/// of [`pointer::offset`]. +/// +/// See the documentation of [`from_raw_parts`] for more details. /// /// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html +/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); + debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len} }.rust_mut } From 1aac00fad391d7f714be1401992e95d5dffcb300 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 10 Sep 2018 07:53:42 +0200 Subject: [PATCH 03/24] A slice covering exactly half the address space is not OK --- src/libcore/slice/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 44d2243c2ccd5..7fd8e2599f988 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3852,8 +3852,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// them from other data. You can obtain a pointer that is usable as `data` /// for zero-length slices using [`NonNull::dangling()`]. /// -/// The total size of the slice must be no larger than `isize::MAX` **bytes** -/// in memory. See the safety documentation of [`pointer::offset`]. +/// The total size of the slice must lower than `isize::MAX` **bytes** in +/// memory. See the safety documentation of [`pointer::offset`]. /// /// # Caveat /// @@ -3881,7 +3881,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + debug_assert!(len * mem::size_of::() < isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3892,8 +3892,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// This function is unsafe for the same reasons as [`from_raw_parts`], as well /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length -/// slices as with [`from_raw_parts`]. The total size of the slice must be no -/// larger than `isize::MAX` **bytes** in memory. See the safety documentation +/// slices as with [`from_raw_parts`]. The total size of the slice must be +/// lower than `isize::MAX` **bytes** in memory. See the safety documentation /// of [`pointer::offset`]. /// /// See the documentation of [`from_raw_parts`] for more details. @@ -3904,7 +3904,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() <= isize::MAX as usize, + debug_assert!(len * mem::size_of::() < isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len} }.rust_mut } From 5d9086f12361fc1dc51d831497a9af68046eb2d1 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 11 Sep 2018 11:44:28 +0200 Subject: [PATCH 04/24] Fix overflow in `from_raw_parts` size check --- src/libcore/slice/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 7fd8e2599f988..e7e4789e09f49 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3881,7 +3881,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() < isize::MAX as usize, + let size = mem::size_of::(); + debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3904,9 +3905,10 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - debug_assert!(len * mem::size_of::() < isize::MAX as usize, + let size = mem::size_of::(); + debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, "attempt to create slice covering half the address space"); - Repr { raw: FatPtr { data, len} }.rust_mut + Repr { raw: FatPtr { data, len } }.rust_mut } /// Converts a reference to T into a slice of length 1 (without copying). From 11c631838067927cddb4c867089401ae7f9ffb8b Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 17 Sep 2018 18:09:04 +0200 Subject: [PATCH 05/24] Use more obvious calculation for slice size check --- src/libcore/slice/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index e7e4789e09f49..3f43da9b3b6fa 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3881,8 +3881,7 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - let size = mem::size_of::(); - debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, + debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust } @@ -3905,8 +3904,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); - let size = mem::size_of::(); - debug_assert!(size == 0 || len < (isize::MAX as usize + size - 1) / size, + debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); Repr { raw: FatPtr { data, len } }.rust_mut } From ebffb672950dbf6d2a19364269f95b4bc3e40dc4 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 17 Sep 2018 18:34:15 +0200 Subject: [PATCH 06/24] Adjust the docs of `from_raw_parts` to match the implementation --- src/libcore/slice/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 3f43da9b3b6fa..0a719792c7f85 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3852,8 +3852,8 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { /// them from other data. You can obtain a pointer that is usable as `data` /// for zero-length slices using [`NonNull::dangling()`]. /// -/// The total size of the slice must lower than `isize::MAX` **bytes** in -/// memory. See the safety documentation of [`pointer::offset`]. +/// The total size of the slice must be no larger than `isize::MAX` **bytes** +/// in memory. See the safety documentation of [`pointer::offset`]. /// /// # Caveat /// @@ -3892,8 +3892,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// This function is unsafe for the same reasons as [`from_raw_parts`], as well /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length -/// slices as with [`from_raw_parts`]. The total size of the slice must be -/// lower than `isize::MAX` **bytes** in memory. See the safety documentation +/// slices as with [`from_raw_parts`]. The total size of the slice must be no +/// larger than `isize::MAX` **bytes** in memory. See the safety documentation /// of [`pointer::offset`]. /// /// See the documentation of [`from_raw_parts`] for more details. From 7cbe0605fa6eacb13aa8d256b999c8424144a4e1 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 22 Sep 2018 13:51:29 -0700 Subject: [PATCH 07/24] in which we include attributes in unused `extern crate` suggestion spans Resolves #54400. --- src/librustc_typeck/check_unused.rs | 8 +++++- ...-54400-unused-extern-crate-attr-span.fixed | 24 ++++++++++++++++++ ...sue-54400-unused-extern-crate-attr-span.rs | 25 +++++++++++++++++++ ...54400-unused-extern-crate-attr-span.stderr | 18 +++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed create mode 100644 src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs create mode 100644 src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 5967bd1ba3eea..3dbd5f2017ee4 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -140,9 +140,15 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) { let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index); let id = tcx.hir.hir_to_node_id(hir_id); let msg = "unused extern crate"; + + // Removal suggestion span needs to include attributes (Issue #54400) + let span_with_attrs = tcx.get_attrs(extern_crate.def_id).iter() + .map(|attr| attr.span) + .fold(span, |acc, attr_span| acc.to(attr_span)); + tcx.struct_span_lint_node(lint, id, span, msg) .span_suggestion_short_with_applicability( - span, + span_with_attrs, "remove it", String::new(), Applicability::MachineApplicable) diff --git a/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed new file mode 100644 index 0000000000000..20ebe6bb54336 --- /dev/null +++ b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.fixed @@ -0,0 +1,24 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--extern edition_lint_paths --cfg blandiloquence +// edition:2018 + +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + +// The suggestion span should include the attribute. + + +//~^ ERROR unused extern crate + +fn main() {} diff --git a/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs new file mode 100644 index 0000000000000..11febe5e87d86 --- /dev/null +++ b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--extern edition_lint_paths --cfg blandiloquence +// edition:2018 + +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + +// The suggestion span should include the attribute. + +#[cfg(blandiloquence)] //~ HELP remove it +extern crate edition_lint_paths; +//~^ ERROR unused extern crate + +fn main() {} diff --git a/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr new file mode 100644 index 0000000000000..cb945ba1c78d1 --- /dev/null +++ b/src/test/ui/rust-2018/issue-54400-unused-extern-crate-attr-span.stderr @@ -0,0 +1,18 @@ +error: unused extern crate + --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:22:1 + | +LL | / #[cfg(blandiloquence)] //~ HELP remove it +LL | | extern crate edition_lint_paths; + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | |________________________________| + | help: remove it + | +note: lint level defined here + --> $DIR/issue-54400-unused-extern-crate-attr-span.rs:16:9 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^ + = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)] + +error: aborting due to previous error + From e370b1ccaed1f2775e2d944acc2898c98b415083 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Thu, 27 Sep 2018 09:49:12 +0200 Subject: [PATCH 08/24] Don't have two adjacent "see also" sentences --- src/libcore/slice/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 0a719792c7f85..a76b30260369d 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3893,13 +3893,11 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { /// as not being able to provide a non-aliasing guarantee of the returned /// mutable slice. `data` must be non-null and aligned even for zero-length /// slices as with [`from_raw_parts`]. The total size of the slice must be no -/// larger than `isize::MAX` **bytes** in memory. See the safety documentation -/// of [`pointer::offset`]. +/// larger than `isize::MAX` **bytes** in memory. /// /// See the documentation of [`from_raw_parts`] for more details. /// /// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html -/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { From f9ff7b7336fef738caba56f1eabe72a299f2e136 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 28 Sep 2018 15:38:42 +0200 Subject: [PATCH 09/24] Prefer `#![feature(bind_by_move_pattern_guards)]` over `-Z disable_ast_check_for_mutation_in_guard` --- src/librustc/session/config.rs | 2 -- src/librustc/ty/context.rs | 5 ----- .../issue-24535-allow-mutable-borrow-in-match-guard.rs | 7 +++---- .../ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs | 2 +- src/test/ui/nll/match-guards-partially-borrow.rs | 2 +- 5 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index eb779e6382f4b..8c7445d860f6c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1320,8 +1320,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, useful for profiling / PGO."), relro_level: Option = (None, parse_relro_level, [TRACKED], "choose which RELRO level to use"), - disable_ast_check_for_mutation_in_guard: bool = (false, parse_bool, [UNTRACKED], - "skip AST-based mutation-in-guard check (mir-borrowck provides more precise check)"), nll_subminimal_causes: bool = (false, parse_bool, [UNTRACKED], "when tracking region error causes, accept subminimal results for faster execution."), nll_facts: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 37ef408c6bdee..39a3e663a06c7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1465,11 +1465,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// If true, we should use a naive AST walk to determine if match /// guard could perform bad mutations (or mutable-borrows). pub fn check_for_mutation_in_guard_via_ast_walk(self) -> bool { - // If someone passes the `-Z` flag, they're asking for the footgun. - if self.sess.opts.debugging_opts.disable_ast_check_for_mutation_in_guard { - return false; - } - // If someone requests the feature, then be a little more // careful and ensure that MIR-borrowck is enabled (which can // happen via edition selection, via `feature(nll)`, or via an diff --git a/src/test/run-pass/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/run-pass/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs index 3f46b0e312d10..10a4678107e1c 100644 --- a/src/test/run-pass/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs +++ b/src/test/run-pass/issues/issue-24535-allow-mutable-borrow-in-match-guard.rs @@ -12,12 +12,11 @@ // This test illustrates that under NLL, we can remove our overly // conservative approach for disallowing mutations of match inputs. -// See further discussion on rust-lang/rust#24535 and -// rust-lang/rfcs#1006. - -// compile-flags: -Z disable-ast-check-for-mutation-in-guard +// See further discussion on rust-lang/rust#24535, +// rust-lang/rfcs#1006, and rust-lang/rfcs#107 #![feature(nll)] +#![feature(bind_by_move_pattern_guards)] fn main() { rust_issue_24535(); diff --git a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs index 39d54f6e7ae28..6cbd493b99182 100644 --- a/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs +++ b/src/test/ui/issues/issue-27282-reborrow-ref-mut-in-guard.rs @@ -15,8 +15,8 @@ // reject it. But I want to make sure that we continue to reject it // (under NLL) even when that conservaive check goes away. -// compile-flags: -Z disable-ast-check-for-mutation-in-guard +#![feature(bind_by_move_pattern_guards)] #![feature(nll)] fn main() { diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs index 49846f620f0c0..f359800812c87 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.rs +++ b/src/test/ui/nll/match-guards-partially-borrow.rs @@ -5,8 +5,8 @@ // Test that we don't allow mutating the value being matched on in a way that // changes which patterns it matches, until we have chosen an arm. -// compile-flags: -Zdisable-ast-check-for-mutation-in-guard +#![feature(bind_by_move_pattern_guards)] #![feature(nll)] fn ok_mutation_in_guard(mut q: i32) { From 8d10f965f4400e5d01c944b331285b8ea1488788 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 24 Sep 2018 21:55:54 -0400 Subject: [PATCH 10/24] Indicate how to move value out of Box in docs. Fixes https://github.com/rust-lang/rust/issues/53634. --- src/liballoc/boxed.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index d4cca387f0689..f989e701913a5 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -16,10 +16,18 @@ //! //! # Examples //! -//! Creating a box: +//! Move a value from the stack to the heap by creating a [`Box`]: //! //! ``` -//! let x = Box::new(5); +//! let val: u8 = 5; +//! let boxed: Box = Box::new(val); +//! ``` +//! +//! Move a value from a [`Box`] back to the stack by [dereferencing]: +//! +//! ``` +//! let boxed: Box = Box::new(5); +//! let val: u8 = *boxed; //! ``` //! //! Creating a recursive data structure: @@ -52,6 +60,9 @@ //! elements are in the list, and so we don't know how much memory to allocate //! for a `Cons`. By introducing a `Box`, which has a defined size, we know how //! big `Cons` needs to be. +//! +//! [dereferencing]: ../../std/ops/trait.Deref.html +//! [`Box`]: struct.Box.html #![stable(feature = "rust1", since = "1.0.0")] From 89cb4119434ec8b013b2240073276c9a42460e05 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 28 Sep 2018 17:20:37 +0200 Subject: [PATCH 11/24] rustc/infer: use unwrap_or(_else) where applicable --- src/librustc/infer/canonical/query_result.rs | 17 +++++------------ .../infer/lexical_region_resolve/graphviz.rs | 9 +++------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs index 65d42c0888d5d..810d3231acdcd 100644 --- a/src/librustc/infer/canonical/query_result.rs +++ b/src/librustc/infer/canonical/query_result.rs @@ -135,10 +135,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { ); // Select everything, returning errors. - let true_errors = match fulfill_cx.select_where_possible(self) { - Ok(()) => vec![], - Err(errors) => errors, - }; + let true_errors = fulfill_cx.select_where_possible(self).err().unwrap_or_else(Vec::new); debug!("true_errors = {:#?}", true_errors); if !true_errors.is_empty() { @@ -148,10 +145,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { } // Anything left unselected *now* must be an ambiguity. - let ambig_errors = match fulfill_cx.select_all_or_error(self) { - Ok(()) => vec![], - Err(errors) => errors, - }; + let ambig_errors = fulfill_cx.select_all_or_error(self).err().unwrap_or_else(Vec::new); debug!("ambig_errors = {:#?}", ambig_errors); let region_obligations = self.take_registered_region_obligations(); @@ -448,10 +442,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { .variables .iter() .enumerate() - .map(|(index, info)| match opt_values[CanonicalVar::new(index)] { - Some(k) => k, - None => self.fresh_inference_var_for_canonical_var(cause.span, *info), - }) + .map(|(index, info)| opt_values[CanonicalVar::new(index)].unwrap_or_else(|| + self.fresh_inference_var_for_canonical_var(cause.span, *info) + )) .collect(), }; diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs index bdd3f78aff3eb..f605da584b28f 100644 --- a/src/librustc/infer/lexical_region_resolve/graphviz.rs +++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs @@ -187,12 +187,9 @@ impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> { None => bug!("no node_id found for node: {:?}", n), }; let name = || format!("node_{}", node_id); - match dot::Id::new(name()) { - Ok(id) => id, - Err(_) => { - bug!("failed to create graphviz node identified by {}", name()); - } - } + + dot::Id::new(name()).unwrap_or_else(|_| + bug!("failed to create graphviz node identified by {}", name())) } fn node_label(&self, n: &Node) -> dot::LabelText { match *n { From 9fd6fad3208c5f3ad11c49b65eb89732ad911e81 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 28 Sep 2018 17:26:10 +0200 Subject: [PATCH 12/24] rustc/infer: convert single-branch matches to if-let --- src/librustc/infer/error_reporting/mod.rs | 9 +- .../nice_region_error/outlives_closure.rs | 53 +++++------ .../nice_region_error/static_impl_trait.rs | 94 +++++++++---------- .../error_reporting/nice_region_error/util.rs | 15 ++- .../infer/lexical_region_resolve/graphviz.rs | 9 +- src/librustc/infer/region_constraints/mod.rs | 5 +- src/librustc/infer/type_variable.rs | 7 +- 7 files changed, 88 insertions(+), 104 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index e3bbdab4fd965..a24eeb328427f 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -455,11 +455,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { TypeError::Sorts(ref exp_found) => { // if they are both "path types", there's a chance of ambiguity // due to different versions of the same crate - match (&exp_found.expected.sty, &exp_found.found.sty) { - (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) => { - report_path_match(err, exp_adt.did, found_adt.did); - } - _ => (), + if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) + = (&exp_found.expected.sty, &exp_found.found.sty) + { + report_path_match(err, exp_adt.did, found_adt.did); } } TypeError::Traits(ref exp_found) => { diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs index 5c27cdb6fb553..009a823568131 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -58,18 +58,17 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { &RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) { let hir = &self.tcx.hir; if let Some(node_id) = hir.as_local_node_id(free_region.scope) { - match hir.get(node_id) { - Node::Expr(Expr { - node: Closure(_, _, _, closure_span, None), - .. - }) => { - let sup_sp = sup_origin.span(); - let origin_sp = origin.span(); - let mut err = self.tcx.sess.struct_span_err( - sup_sp, - "borrowed data cannot be stored outside of its closure"); - err.span_label(sup_sp, "cannot be stored outside of its closure"); - if origin_sp == sup_sp || origin_sp.contains(sup_sp) { + if let Node::Expr(Expr { + node: Closure(_, _, _, closure_span, None), + .. + }) = hir.get(node_id) { + let sup_sp = sup_origin.span(); + let origin_sp = origin.span(); + let mut err = self.tcx.sess.struct_span_err( + sup_sp, + "borrowed data cannot be stored outside of its closure"); + err.span_label(sup_sp, "cannot be stored outside of its closure"); + if origin_sp == sup_sp || origin_sp.contains(sup_sp) { // // sup_sp == origin.span(): // // let mut x = None; @@ -87,11 +86,11 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { // ------------ ... because it cannot outlive this closure // f = Some(x); // ^ cannot be stored outside of its closure - err.span_label(*external_span, - "borrowed data cannot be stored into here..."); - err.span_label(*closure_span, - "...because it cannot outlive this closure"); - } else { + err.span_label(*external_span, + "borrowed data cannot be stored into here..."); + err.span_label(*closure_span, + "...because it cannot outlive this closure"); + } else { // FIXME: the wording for this case could be much improved // // let mut lines_to_use: Vec<&CrateId> = Vec::new(); @@ -102,18 +101,16 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { // ...so that variable is valid at time of its declaration // lines_to_use.push(installed_id); // ^^^^^^^^^^^^ cannot be stored outside of its closure - err.span_label(origin_sp, - "cannot infer an appropriate lifetime..."); - err.span_label(*external_span, - "...so that variable is valid at time of its \ - declaration"); - err.span_label(*closure_span, - "borrowed data cannot outlive this closure"); - } - err.emit(); - return Some(ErrorReported); + err.span_label(origin_sp, + "cannot infer an appropriate lifetime..."); + err.span_label(*external_span, + "...so that variable is valid at time of its \ + declaration"); + err.span_label(*closure_span, + "borrowed data cannot outlive this closure"); } - _ => {} + err.emit(); + return Some(ErrorReported); } } } diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index 3393eb65089c0..766173bf66283 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -20,64 +20,62 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { /// Print the error message for lifetime errors when the return type is a static impl Trait. pub(super) fn try_report_static_impl_trait(&self) -> Option { if let Some(ref error) = self.error { - match error.clone() { - RegionResolutionError::SubSupConflict( + if let RegionResolutionError::SubSupConflict( var_origin, sub_origin, sub_r, sup_origin, sup_r, - ) => { - let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?; - if sub_r == &RegionKind::ReStatic && - self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some() - { - let sp = var_origin.span(); - let return_sp = sub_origin.span(); - let mut err = self.tcx.sess.struct_span_err( - sp, - "cannot infer an appropriate lifetime", + ) = error.clone() + { + let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?; + if sub_r == &RegionKind::ReStatic && + self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some() + { + let sp = var_origin.span(); + let return_sp = sub_origin.span(); + let mut err = self.tcx.sess.struct_span_err( + sp, + "cannot infer an appropriate lifetime", + ); + err.span_label( + return_sp, + "this return type evaluates to the `'static` lifetime...", + ); + err.span_label( + sup_origin.span(), + "...but this borrow...", + ); + + let (lifetime, lt_sp_opt) = self.tcx.msg_span_from_free_region(sup_r); + if let Some(lifetime_sp) = lt_sp_opt { + err.span_note( + lifetime_sp, + &format!("...can't outlive {}", lifetime), ); - err.span_label( + } + + let lifetime_name = match sup_r { + RegionKind::ReFree(FreeRegion { + bound_region: BoundRegion::BrNamed(_, ref name), .. + }) => name.to_string(), + _ => "'_".to_owned(), + }; + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) { + err.span_suggestion_with_applicability( return_sp, - "this return type evaluates to the `'static` lifetime...", + &format!( + "you can add a constraint to the return type to make it last \ + less than `'static` and match {}", + lifetime, + ), + format!("{} + {}", snippet, lifetime_name), + Applicability::Unspecified, ); - err.span_label( - sup_origin.span(), - "...but this borrow...", - ); - - let (lifetime, lt_sp_opt) = self.tcx.msg_span_from_free_region(sup_r); - if let Some(lifetime_sp) = lt_sp_opt { - err.span_note( - lifetime_sp, - &format!("...can't outlive {}", lifetime), - ); - } - - let lifetime_name = match sup_r { - RegionKind::ReFree(FreeRegion { - bound_region: BoundRegion::BrNamed(_, ref name), .. - }) => name.to_string(), - _ => "'_".to_owned(), - }; - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) { - err.span_suggestion_with_applicability( - return_sp, - &format!( - "you can add a constraint to the return type to make it last \ - less than `'static` and match {}", - lifetime, - ), - format!("{} + {}", snippet, lifetime_name), - Applicability::Unspecified, - ); - } - err.emit(); - return Some(ErrorReported); } + err.emit(); + return Some(ErrorReported); } - _ => {} } } None diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index afc50fe115166..76a780a5a055a 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -119,16 +119,13 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { decl: &hir::FnDecl, ) -> Option { let ret_ty = self.tcx.type_of(scope_def_id); - match ret_ty.sty { - ty::FnDef(_, _) => { - let sig = ret_ty.fn_sig(self.tcx); - let late_bound_regions = self.tcx - .collect_referenced_late_bound_regions(&sig.output()); - if late_bound_regions.iter().any(|r| *r == br) { - return Some(decl.output.span()); - } + if let ty::FnDef(_, _) = ret_ty.sty { + let sig = ret_ty.fn_sig(self.tcx); + let late_bound_regions = self.tcx + .collect_referenced_late_bound_regions(&sig.output()); + if late_bound_regions.iter().any(|r| *r == br) { + return Some(decl.output.span()); } - _ => {} } None } diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs index f605da584b28f..e4705df2eea13 100644 --- a/src/librustc/infer/lexical_region_resolve/graphviz.rs +++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs @@ -112,12 +112,9 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>( } }; - match dump_region_data_to(region_rels, ®ion_data.constraints, &output_path) { - Ok(()) => {} - Err(e) => { - let msg = format!("io error dumping region constraints: {}", e); - tcx.sess.err(&msg) - } + if let Err(e) = dump_region_data_to(region_rels, ®ion_data.constraints, &output_path) { + let msg = format!("io error dumping region constraints: {}", e); + tcx.sess.err(&msg) } } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index bc9027a08258c..1a79ca211283b 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -661,11 +661,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> { debug!("RegionConstraintCollector: add_verify({:?})", verify); // skip no-op cases known to be satisfied - match verify.bound { - VerifyBound::AllBounds(ref bs) if bs.len() == 0 => { + if let VerifyBound::AllBounds(ref bs) = verify.bound { + if bs.len() == 0 { return; } - _ => {} } let index = self.data.verifys.len(); diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index b1e4fc7c7fc7b..970b6e096ffe4 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -273,11 +273,8 @@ impl<'tcx> TypeVariableTable<'tcx> { pub fn rollback_to(&mut self, s: Snapshot<'tcx>) { debug!("rollback_to{:?}", { for action in self.values.actions_since_snapshot(&s.snapshot) { - match *action { - sv::UndoLog::NewElem(index) => { - debug!("inference variable _#{}t popped", index) - } - _ => { } + if let sv::UndoLog::NewElem(index) = *action { + debug!("inference variable _#{}t popped", index) } } }); From 0e84647e18181ea9aa199d42b3da598eb59ab70c Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 28 Sep 2018 17:28:47 +0200 Subject: [PATCH 13/24] rustc/infer: use to_owned instead of to_string with string literals --- src/librustc/infer/error_reporting/need_type_info.rs | 8 ++++---- .../nice_region_error/different_lifetimes.rs | 10 +++++----- src/librustc/infer/lexical_region_resolve/graphviz.rs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 505b1bc032d20..efb316243fad0 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut labels = vec![( span, if &name == "_" { - "cannot infer type".to_string() + "cannot infer type".to_owned() } else { format!("cannot infer type for `{}`", name) }, @@ -138,7 +138,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // ``` labels.clear(); labels.push( - (pattern.span, "consider giving this closure parameter a type".to_string())); + (pattern.span, "consider giving this closure parameter a type".to_owned())); } else if let Some(pattern) = local_visitor.found_local_pattern { if let Some(simple_ident) = pattern.simple_ident() { match pattern.span.compiler_desugaring_kind() { @@ -146,12 +146,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { format!("consider giving `{}` a type", simple_ident))), Some(CompilerDesugaringKind::ForLoop) => labels.push(( pattern.span, - "the element type for this iterator is not specified".to_string(), + "the element type for this iterator is not specified".to_owned(), )), _ => {} } } else { - labels.push((pattern.span, "consider giving the pattern a type".to_string())); + labels.push((pattern.span, "consider giving the pattern a type".to_owned())); } } diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index 97b1978cb2eb2..1f84c73a71583 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -113,12 +113,12 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { (None, None) => { let (main_label_1, span_label_1) = if ty_sup.id == ty_sub.id { ( - "this type is declared with multiple lifetimes...".to_string(), - "...but data with one lifetime flows into the other here".to_string() + "this type is declared with multiple lifetimes...".to_owned(), + "...but data with one lifetime flows into the other here".to_owned() ) } else { ( - "these two types are declared with different lifetimes...".to_string(), + "these two types are declared with different lifetimes...".to_owned(), format!( "...but data{} flows{} here", span_label_var1, @@ -133,7 +133,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ty_sub.span, ret_span, "this parameter and the return type are declared \ - with different lifetimes...".to_string() + with different lifetimes...".to_owned() , format!("...but data{} is returned here", span_label_var1), ), @@ -141,7 +141,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ty_sup.span, ret_span, "this parameter and the return type are declared \ - with different lifetimes...".to_string() + with different lifetimes...".to_owned() , format!("...but data{} is returned here", span_label_var1), ), diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs index e4705df2eea13..48ec3210fe727 100644 --- a/src/librustc/infer/lexical_region_resolve/graphviz.rs +++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs @@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> { match *e { Edge::Constraint(ref c) => dot::LabelText::label(format!("{:?}", self.map.get(c).unwrap())), - Edge::EnclScope(..) => dot::LabelText::label("(enclosed)".to_string()), + Edge::EnclScope(..) => dot::LabelText::label("(enclosed)".to_owned()), } } } From 999d76812cc2403568a2c5740be3474d5f8fc36f Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 28 Sep 2018 17:32:22 +0200 Subject: [PATCH 14/24] rustc/infer: improve vector allocations --- src/librustc/infer/canonical/query_result.rs | 71 ++++++++++---------- src/librustc/infer/opaque_types/mod.rs | 1 + 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs index 810d3231acdcd..f70064e071629 100644 --- a/src/librustc/infer/canonical/query_result.rs +++ b/src/librustc/infer/canonical/query_result.rs @@ -310,16 +310,18 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { } // ...also include the other query region constraints from the query. - output_query_region_constraints.reserve(query_result.value.region_constraints.len()); - for r_c in query_result.value.region_constraints.iter() { - let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below - let k1 = substitute_value(self.tcx, &result_subst, &k1); - let r2 = substitute_value(self.tcx, &result_subst, &r2); - if k1 != r2.into() { - output_query_region_constraints - .push(ty::Binder::bind(ty::OutlivesPredicate(k1, r2))); - } - } + output_query_region_constraints.extend( + query_result.value.region_constraints.iter().filter_map(|r_c| { + let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below + let k1 = substitute_value(self.tcx, &result_subst, &k1); + let r2 = substitute_value(self.tcx, &result_subst, &r2); + if k1 != r2.into() { + Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2))) + } else { + None + } + }) + ); let user_result: R = query_result.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value); @@ -576,31 +578,30 @@ pub fn make_query_outlives<'tcx>( assert!(verifys.is_empty()); assert!(givens.is_empty()); - let mut outlives: Vec<_> = constraints - .into_iter() - .map(|(k, _)| match *k { - // Swap regions because we are going from sub (<=) to outlives - // (>=). - Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( - tcx.mk_region(ty::ReVar(v2)).into(), - tcx.mk_region(ty::ReVar(v1)), - ), - Constraint::VarSubReg(v1, r2) => { - ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1))) - } - Constraint::RegSubVar(r1, v2) => { - ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) - } - Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), - }) - .map(ty::Binder::dummy) // no bound regions in the code above - .collect(); - - outlives.extend( - outlives_obligations - .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r)) - .map(ty::Binder::dummy), // no bound regions in the code above - ); + let outlives: Vec<_> = constraints + .into_iter() + .map(|(k, _)| match *k { + // Swap regions because we are going from sub (<=) to outlives + // (>=). + Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( + tcx.mk_region(ty::ReVar(v2)).into(), + tcx.mk_region(ty::ReVar(v1)), + ), + Constraint::VarSubReg(v1, r2) => { + ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1))) + } + Constraint::RegSubVar(r1, v2) => { + ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1) + } + Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), + }) + .map(ty::Binder::dummy) // no bound regions in the code above + .chain( + outlives_obligations + .map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r)) + .map(ty::Binder::dummy), // no bound regions in the code above + ) + .collect(); outlives } diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 88d375742670d..d365992aef500 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -803,6 +803,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> { ); debug!("instantiate_opaque_types: ty_var={:?}", ty_var); + self.obligations.reserve(bounds.predicates.len()); for predicate in bounds.predicates { // Change the predicate to refer to the type variable, // which will be the concrete type instead of the opaque type. From 70eeb054410031a0f23516be51bddaed5fe77276 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 28 Sep 2018 17:35:31 +0200 Subject: [PATCH 15/24] rustc/infer: readability improvements --- src/librustc/infer/canonical/query_result.rs | 32 +++++++++---------- src/librustc/infer/equate.rs | 6 ++-- .../error_reporting/nice_region_error/util.rs | 4 +-- src/librustc/infer/resolve.rs | 4 +-- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs index f70064e071629..a327f1f5c9d50 100644 --- a/src/librustc/infer/canonical/query_result.rs +++ b/src/librustc/infer/canonical/query_result.rs @@ -499,24 +499,22 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below let k1 = substitute_value(self.tcx, result_subst, k1); let r2 = substitute_value(self.tcx, result_subst, r2); - match k1.unpack() { - UnpackedKind::Lifetime(r1) => Obligation::new( - cause.clone(), - param_env, - ty::Predicate::RegionOutlives(ty::Binder::dummy( - ty::OutlivesPredicate(r1, r2), + + Obligation::new( + cause.clone(), + param_env, + match k1.unpack() { + UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives( + ty::Binder::dummy( + ty::OutlivesPredicate(r1, r2) )), - ), - - UnpackedKind::Type(t1) => Obligation::new( - cause.clone(), - param_env, - ty::Predicate::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate( - t1, r2, - ))), - ), - } - }), + UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives( + ty::Binder::dummy(ty::OutlivesPredicate( + t1, r2 + ))) + } + ) + }) ) as Box> } diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 26eb2ffbf6aba..854960492c9bd 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -77,24 +77,22 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> match (&a.sty, &b.sty) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().equate(a_id, b_id); - Ok(a) } (&ty::Infer(TyVar(a_id)), _) => { self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?; - Ok(a) } (_, &ty::Infer(TyVar(b_id))) => { self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?; - Ok(a) } _ => { self.fields.infcx.super_combine_tys(self, a, b)?; - Ok(a) } } + + Ok(a) } fn regions(&mut self, a: ty::Region<'tcx>, b: ty::Region<'tcx>) diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 76a780a5a055a..300bc54d64e13 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -137,8 +137,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool { is_first && self.tcx - .opt_associated_item(scope_def_id) - .map(|i| i.method_has_self_argument) == Some(true) + .opt_associated_item(scope_def_id) + .map(|i| i.method_has_self_argument) == Some(true) } } diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index be13fb9a2a5eb..0ef9761857264 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -153,8 +153,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for FullTypeResolver<'a, 'gcx, 'tcx> fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if !t.needs_infer() && !ty::keep_local(&t) { t // micro-optimize -- if there is nothing in this type that this fold affects... - // ^ we need to have the `keep_local` check to un-default - // defaulted tuples. + // ^ we need to have the `keep_local` check to un-default + // defaulted tuples. } else { let t = self.infcx.shallow_resolve(t); match t.sty { From 52da88639e515dabe4927706025adf976d9cd2b7 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Fri, 28 Sep 2018 17:38:02 +0200 Subject: [PATCH 16/24] rustc/infer: miscellaneous minor code improvements --- src/librustc/infer/error_reporting/mod.rs | 8 ++++---- src/librustc/infer/lexical_region_resolve/mod.rs | 4 +--- src/librustc/infer/region_constraints/mod.rs | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a24eeb328427f..6b9bb852a54f2 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -406,10 +406,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { errors.clone() } else { errors - .iter() - .filter(|&e| !is_bound_failure(e)) - .cloned() - .collect() + .iter() + .filter(|&e| !is_bound_failure(e)) + .cloned() + .collect() }; // sort the errors by span, for better error message stability. diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index a8fbfc3b64dfd..c2e75bedf0aed 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -147,9 +147,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { fn construct_var_data(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> LexicalRegionResolutions<'tcx> { LexicalRegionResolutions { error_region: tcx.types.re_static, - values: (0..self.num_vars()) - .map(|_| VarValue::Value(tcx.types.re_empty)) - .collect(), + values: IndexVec::from_elem_n(VarValue::Value(tcx.types.re_empty), self.num_vars()) } } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 1a79ca211283b..f6192efb79ec1 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -443,7 +443,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.undo_log[snapshot.length] == OpenSnapshot); if snapshot.length == 0 { - self.undo_log.truncate(0); + self.undo_log.clear(); } else { (*self.undo_log)[snapshot.length] = CommitedSnapshot; } From 54b303ace4f005074f823105e4ffcabc914d3784 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Sep 2018 19:43:15 +0200 Subject: [PATCH 17/24] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 130d803b3243a..e8f6973e2d40a 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 130d803b3243a92f5c2d9230935cba7fa88e263e +Subproject commit e8f6973e2d40ab39e30cdbe0cf8e77a72c867d4f From 0390736dce86cb97880e3eb144de9ec5759bec14 Mon Sep 17 00:00:00 2001 From: Donato Sciarra Date: Mon, 17 Sep 2018 23:37:20 +0200 Subject: [PATCH 18/24] Improve ux when calling associated functions with dot notation Issue: 22692 --- src/librustc_resolve/lib.rs | 59 ++++++++++++++++++++------ src/test/ui/resolve/issue-22692.rs | 13 ++++++ src/test/ui/resolve/issue-22692.stderr | 11 +++++ 3 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/resolve/issue-22692.rs create mode 100644 src/test/ui/resolve/issue-22692.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5e3f747009911..0bccf5292d9de 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3160,11 +3160,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // parser issue where a struct literal is being used on an expression // where a brace being opened means a block is being started. Look // ahead for the next text to see if `span` is followed by a `{`. - let cm = this.session.source_map(); + let sm = this.session.source_map(); let mut sp = span; loop { - sp = cm.next_point(sp); - match cm.span_to_snippet(sp) { + sp = sm.next_point(sp); + match sm.span_to_snippet(sp) { Ok(ref snippet) => { if snippet.chars().any(|c| { !c.is_whitespace() }) { break; @@ -3173,20 +3173,51 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { _ => break, } } - let followed_by_brace = match cm.span_to_snippet(sp) { + let followed_by_brace = match sm.span_to_snippet(sp) { Ok(ref snippet) if snippet == "{" => true, _ => false, }; - if let (PathSource::Expr(None), true) = (source, followed_by_brace) { - err.span_label( - span, - format!("did you mean `({} {{ /* fields */ }})`?", path_str), - ); - } else { - err.span_label( - span, - format!("did you mean `{} {{ /* fields */ }}`?", path_str), - ); + match source { + PathSource::Expr(Some(parent)) => { + match parent.node { + ExprKind::MethodCall(ref path_assignment, _) => { + err.span_suggestion_with_applicability( + sm.start_point(parent.span) + .to(path_assignment.ident.span), + "use `::` to access an associated function", + format!("{}::{}", + path_str, + path_assignment.ident), + Applicability::MaybeIncorrect + ); + return (err, candidates); + }, + _ => { + err.span_label( + span, + format!("did you mean `{} {{ /* fields */ }}`?", + path_str), + ); + return (err, candidates); + }, + } + }, + PathSource::Expr(None) if followed_by_brace == true => { + err.span_label( + span, + format!("did you mean `({} {{ /* fields */ }})`?", + path_str), + ); + return (err, candidates); + }, + _ => { + err.span_label( + span, + format!("did you mean `{} {{ /* fields */ }}`?", + path_str), + ); + return (err, candidates); + }, } } return (err, candidates); diff --git a/src/test/ui/resolve/issue-22692.rs b/src/test/ui/resolve/issue-22692.rs new file mode 100644 index 0000000000000..06648c599534f --- /dev/null +++ b/src/test/ui/resolve/issue-22692.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _ = String.new(); +} diff --git a/src/test/ui/resolve/issue-22692.stderr b/src/test/ui/resolve/issue-22692.stderr new file mode 100644 index 0000000000000..ecdd4ff855fb9 --- /dev/null +++ b/src/test/ui/resolve/issue-22692.stderr @@ -0,0 +1,11 @@ +error[E0423]: expected value, found struct `String` + --> $DIR/issue-22692.rs:12:13 + | +LL | let _ = String.new(); + | ^^^^^^---- + | | + | help: use `::` to access an associated function: `String::new` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. From d654e3c69b127f274c6ef146bc27901086a1cd28 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 29 Sep 2018 08:04:34 +0200 Subject: [PATCH 19/24] Improve bug! message for impossible case in Relate Hitting this branch in Clippy and I think it makes sense to print both values here in case other people hit this branch, too. --- src/librustc/ty/relate.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 98042e18d32d9..547f7cecc4e06 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -702,7 +702,12 @@ impl<'tcx> Relate<'tcx> for Kind<'tcx> { (UnpackedKind::Type(a_ty), UnpackedKind::Type(b_ty)) => { Ok(relation.relate(&a_ty, &b_ty)?.into()) } - (UnpackedKind::Lifetime(_), _) | (UnpackedKind::Type(_), _) => bug!() + (UnpackedKind::Lifetime(unpacked), x) => { + bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) + } + (UnpackedKind::Type(unpacked), x) => { + bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x) + } } } } From b3157601b1dbb231b9725b17580f89475dde9b88 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 29 Sep 2018 12:37:12 -0700 Subject: [PATCH 20/24] Rename sanitizer runtime libraries on OSX Currently we ship sanitizer libraries as they're built, but these names unfortunately conflict with the names of the sanitizer libraries installed on the system. If a crate, for example, links in C code that wants to use the system sanitizer and the Rust code doesn't use sanitizers at all, then using `cargo` may accidentally pull in the Rust-installed sanitizer library due to a conflict in names. This change is intended to be entirely transparent for Rust users of sanitizers, it should only hopefully improve our story with other users! Closes #54134 --- src/bootstrap/compile.rs | 2 +- src/build_helper/lib.rs | 37 ++++++++++++++++++++++++++++++++++--- src/librustc_asan/build.rs | 1 + src/librustc_tsan/build.rs | 1 + 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 608f2c982c2a5..7d235743c2c46 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -249,7 +249,7 @@ impl Step for StdLink { fn copy_apple_sanitizer_dylibs(builder: &Builder, native_dir: &Path, platform: &str, into: &Path) { for &sanitizer in &["asan", "tsan"] { - let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform); + let filename = format!("lib__rustc__clang_rt.{}_{}_dynamic.dylib", sanitizer, platform); let mut src_path = native_dir.join(sanitizer); src_path.push("build"); src_path.push("lib"); diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 1cbb8e49bfa15..ec94f57861dbe 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -178,6 +178,37 @@ pub struct NativeLibBoilerplate { pub out_dir: PathBuf, } +impl NativeLibBoilerplate { + /// On OSX we don't want to ship the exact filename that compiler-rt builds. + /// This conflicts with the system and ours is likely a wildly different + /// version, so they can't be substituted. + /// + /// As a result, we rename it here but we need to also use + /// `install_name_tool` on OSX to rename the commands listed inside of it to + /// ensure it's linked against correctly. + pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) { + if env::var("TARGET").unwrap() != "x86_64-apple-darwin" { + return + } + + let dir = self.out_dir.join("build/lib/darwin"); + let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name); + let src = dir.join(&format!("lib{}.dylib", name)); + let new_name = format!("lib__rustc__{}.dylib", name); + let dst = dir.join(&new_name); + + println!("{} => {}", src.display(), dst.display()); + fs::rename(&src, &dst).unwrap(); + let status = Command::new("install_name_tool") + .arg("-id") + .arg(format!("@rpath/{}", new_name)) + .arg(&dst) + .status() + .expect("failed to execute `install_name_tool`"); + assert!(status.success()); + } +} + impl Drop for NativeLibBoilerplate { fn drop(&mut self) { if !thread::panicking() { @@ -229,7 +260,7 @@ pub fn native_lib_boilerplate( pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result<(NativeLibBoilerplate, String), ()> { - let (link_name, search_path, dynamic) = match &*env::var("TARGET").unwrap() { + let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() { "x86_64-unknown-linux-gnu" => ( format!("clang_rt.{}-x86_64", sanitizer_name), "build/lib/linux", @@ -242,8 +273,8 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) ), _ => return Err(()), }; - let to_link = if dynamic { - format!("dylib={}", link_name) + let to_link = if apple { + format!("dylib=__rustc__{}", link_name) } else { format!("static={}", link_name) }; diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs index b8614c520e7cf..a5905df57c8cf 100644 --- a/src/librustc_asan/build.rs +++ b/src/librustc_asan/build.rs @@ -31,6 +31,7 @@ fn main() { .out_dir(&native.out_dir) .build_target(&target) .build(); + native.fixup_sanitizer_lib_name("asan"); } println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs index 38595478c7433..d23c71e2c1286 100644 --- a/src/librustc_tsan/build.rs +++ b/src/librustc_tsan/build.rs @@ -31,6 +31,7 @@ fn main() { .out_dir(&native.out_dir) .build_target(&target) .build(); + native.fixup_sanitizer_lib_name("tsan"); } println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); } From af9eb4fc21bfeb7317446581194b659df2e73fa5 Mon Sep 17 00:00:00 2001 From: Niek Sanders Date: Sun, 30 Sep 2018 00:24:37 +0200 Subject: [PATCH 21/24] Correct doc for WorkQueue::pop(). --- src/librustc_data_structures/work_queue.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_data_structures/work_queue.rs b/src/librustc_data_structures/work_queue.rs index af9ed9306ebb2..eff80a98c9de9 100644 --- a/src/librustc_data_structures/work_queue.rs +++ b/src/librustc_data_structures/work_queue.rs @@ -53,7 +53,7 @@ impl WorkQueue { } } - /// Attempt to enqueue `element` in the work queue. Returns false if it was already present. + /// Attempt to pop an element from the work queue. #[inline] pub fn pop(&mut self) -> Option { if let Some(element) = self.deque.pop_front() { From 3e142b92bc84c48b2bccf8673b49b02e9b1f13c4 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 27 Sep 2018 22:34:19 +0100 Subject: [PATCH 22/24] Added help message for `impl_trait_in_bindings` feature gate. --- src/librustc/hir/lowering.rs | 138 +++++++++++------- ...feature-gate-impl_trait_in_bindings.stderr | 4 + src/test/ui/impl-trait/where-allowed.stderr | 2 + 3 files changed, 88 insertions(+), 56 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 62b06f54301f3..81d8a803c3958 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -54,6 +54,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::thin_vec::ThinVec; use session::Session; +use session::config::nightly_options; use util::common::FN_OUTPUT_NAME; use util::nodemap::{DefIdMap, NodeMap}; @@ -188,16 +189,28 @@ enum ImplTraitContext<'a> { Existential(Option), /// `impl Trait` is not accepted in this position. - Disallowed, + Disallowed(ImplTraitPosition), +} + +/// Position in which `impl Trait` is disallowed. Used for error reporting. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum ImplTraitPosition { + Binding, + Other, } impl<'a> ImplTraitContext<'a> { + #[inline] + fn disallowed() -> Self { + ImplTraitContext::Disallowed(ImplTraitPosition::Other) + } + fn reborrow(&'b mut self) -> ImplTraitContext<'b> { use self::ImplTraitContext::*; match self { Universal(params) => Universal(params), Existential(did) => Existential(*did), - Disallowed => Disallowed, + Disallowed(pos) => Disallowed(*pos), } } } @@ -1142,7 +1155,7 @@ impl<'a> LoweringContext<'a> { generic_params: this.lower_generic_params( &f.generic_params, &NodeMap(), - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ), unsafety: this.lower_unsafety(f.unsafety), abi: f.abi, @@ -1255,20 +1268,27 @@ impl<'a> LoweringContext<'a> { }), )) } - ImplTraitContext::Disallowed => { + ImplTraitContext::Disallowed(pos) => { let allowed_in = if self.sess.features_untracked() .impl_trait_in_bindings { "bindings or function and inherent method return types" } else { "function and inherent method return types" }; - span_err!( + let mut err = struct_span_err!( self.sess, t.span, E0562, "`impl Trait` not allowed outside of {}", allowed_in, ); + if pos == ImplTraitPosition::Binding && + nightly_options::is_nightly_build() { + help!(err, + "add #![feature(impl_trait_in_bindings)] to the crate attributes \ + to enable"); + } + err.emit(); hir::TyKind::Err } } @@ -1742,7 +1762,7 @@ impl<'a> LoweringContext<'a> { param_mode, 0, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ) }) .chain(ident.map(|ident| hir::PathSegment::from_ident(ident))) @@ -1872,9 +1892,11 @@ impl<'a> LoweringContext<'a> { self.with_anonymous_lifetime_mode( AnonymousLifetimeMode::PassThrough, |this| { - const DISALLOWED: ImplTraitContext<'_> = ImplTraitContext::Disallowed; let &ParenthesisedArgs { ref inputs, ref output, span } = data; - let inputs = inputs.iter().map(|ty| this.lower_ty_direct(ty, DISALLOWED)).collect(); + let inputs = inputs + .iter() + .map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())) + .collect(); let mk_tup = |this: &mut Self, tys, span| { let LoweredNodeId { node_id, hir_id } = this.next_id(); hir::Ty { node: hir::TyKind::Tup(tys), id: node_id, hir_id, span } @@ -1889,7 +1911,7 @@ impl<'a> LoweringContext<'a> { ident: Ident::from_str(FN_OUTPUT_NAME), ty: output .as_ref() - .map(|ty| this.lower_ty(&ty, DISALLOWED)) + .map(|ty| this.lower_ty(&ty, ImplTraitContext::disallowed())) .unwrap_or_else(|| P(mk_tup(this, hir::HirVec::new(), span))), span: output.as_ref().map_or(span, |ty| ty.span), } @@ -1921,7 +1943,7 @@ impl<'a> LoweringContext<'a> { if self.sess.features_untracked().impl_trait_in_bindings { ImplTraitContext::Existential(Some(parent_def_id)) } else { - ImplTraitContext::Disallowed + ImplTraitContext::Disallowed(ImplTraitPosition::Binding) } )), pat: self.lower_pat(&l.pat), @@ -1983,7 +2005,7 @@ impl<'a> LoweringContext<'a> { if let Some((_, ref mut ibty)) = in_band_ty_params { self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty)) } else { - self.lower_ty_direct(&arg.ty, ImplTraitContext::Disallowed) + self.lower_ty_direct(&arg.ty, ImplTraitContext::disallowed()) } }) .collect::>(); @@ -1999,9 +2021,12 @@ impl<'a> LoweringContext<'a> { match decl.output { FunctionRetTy::Ty(ref ty) => match in_band_ty_params { Some((def_id, _)) if impl_trait_return_allow => { - hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(Some(def_id)))) + hir::Return(self.lower_ty(ty, + ImplTraitContext::Existential(Some(def_id)))) + } + _ => { + hir::Return(self.lower_ty(ty, ImplTraitContext::disallowed())) } - _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)), }, FunctionRetTy::Default(span) => hir::DefaultReturn(span), } @@ -2369,7 +2394,7 @@ impl<'a> LoweringContext<'a> { span: ident.span, kind: hir::GenericParamKind::Type { default: default.as_ref().map(|x| { - self.lower_ty(x, ImplTraitContext::Disallowed) + self.lower_ty(x, ImplTraitContext::disallowed()) }), synthetic: param.attrs.iter() .filter(|attr| attr.check_name("rustc_synthetic")) @@ -2472,9 +2497,9 @@ impl<'a> LoweringContext<'a> { bound_generic_params: this.lower_generic_params( bound_generic_params, &NodeMap(), - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ), - bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::Disallowed), + bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()), bounds: bounds .iter() .filter_map(|bound| match *bound { @@ -2483,7 +2508,7 @@ impl<'a> LoweringContext<'a> { GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, _ => Some(this.lower_param_bound( bound, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), )), }) .collect(), @@ -2499,7 +2524,7 @@ impl<'a> LoweringContext<'a> { }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { span, lifetime: self.lower_lifetime(lifetime), - bounds: self.lower_param_bounds(bounds, ImplTraitContext::Disallowed), + bounds: self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), }), WherePredicate::EqPredicate(WhereEqPredicate { id, @@ -2508,8 +2533,8 @@ impl<'a> LoweringContext<'a> { span, }) => hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { id: self.lower_node_id(id).node_id, - lhs_ty: self.lower_ty(lhs_ty, ImplTraitContext::Disallowed), - rhs_ty: self.lower_ty(rhs_ty, ImplTraitContext::Disallowed), + lhs_ty: self.lower_ty(lhs_ty, ImplTraitContext::disallowed()), + rhs_ty: self.lower_ty(rhs_ty, ImplTraitContext::disallowed()), span, }), } @@ -2579,7 +2604,7 @@ impl<'a> LoweringContext<'a> { None => Ident::new(Symbol::intern(&index.to_string()), f.span), }, vis: self.lower_visibility(&f.vis, None), - ty: self.lower_ty(&f.ty, ImplTraitContext::Disallowed), + ty: self.lower_ty(&f.ty, ImplTraitContext::disallowed()), attrs: self.lower_attrs(&f.attrs), } } @@ -2686,7 +2711,7 @@ impl<'a> LoweringContext<'a> { if self.sess.features_untracked().impl_trait_in_bindings { ImplTraitContext::Existential(None) } else { - ImplTraitContext::Disallowed + ImplTraitContext::Disallowed(ImplTraitPosition::Binding) } ), self.lower_mutability(m), @@ -2701,7 +2726,7 @@ impl<'a> LoweringContext<'a> { if self.sess.features_untracked().impl_trait_in_bindings { ImplTraitContext::Existential(None) } else { - ImplTraitContext::Disallowed + ImplTraitContext::Disallowed(ImplTraitPosition::Binding) } ), value @@ -2740,12 +2765,12 @@ impl<'a> LoweringContext<'a> { ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)), ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)), ItemKind::Ty(ref t, ref generics) => hir::ItemKind::Ty( - self.lower_ty(t, ImplTraitContext::Disallowed), - self.lower_generics(generics, ImplTraitContext::Disallowed), + self.lower_ty(t, ImplTraitContext::disallowed()), + self.lower_generics(generics, ImplTraitContext::disallowed()), ), ItemKind::Existential(ref b, ref generics) => hir::ItemKind::Existential(hir::ExistTy { - generics: self.lower_generics(generics, ImplTraitContext::Disallowed), - bounds: self.lower_param_bounds(b, ImplTraitContext::Disallowed), + generics: self.lower_generics(generics, ImplTraitContext::disallowed()), + bounds: self.lower_param_bounds(b, ImplTraitContext::disallowed()), impl_trait_fn: None, }), ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum( @@ -2756,20 +2781,20 @@ impl<'a> LoweringContext<'a> { .map(|x| self.lower_variant(x)) .collect(), }, - self.lower_generics(generics, ImplTraitContext::Disallowed), + self.lower_generics(generics, ImplTraitContext::disallowed()), ), ItemKind::Struct(ref struct_def, ref generics) => { let struct_def = self.lower_variant_data(struct_def); hir::ItemKind::Struct( struct_def, - self.lower_generics(generics, ImplTraitContext::Disallowed), + self.lower_generics(generics, ImplTraitContext::disallowed()), ) } ItemKind::Union(ref vdata, ref generics) => { let vdata = self.lower_variant_data(vdata); hir::ItemKind::Union( vdata, - self.lower_generics(generics, ImplTraitContext::Disallowed), + self.lower_generics(generics, ImplTraitContext::disallowed()), ) } ItemKind::Impl( @@ -2802,7 +2827,7 @@ impl<'a> LoweringContext<'a> { AnonymousLifetimeMode::CreateParameter, |this, _| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { - this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed) + this.lower_trait_ref(trait_ref, ImplTraitContext::disallowed()) }); if let Some(ref trait_ref) = trait_ref { @@ -2811,7 +2836,7 @@ impl<'a> LoweringContext<'a> { } } - let lowered_ty = this.lower_ty(ty, ImplTraitContext::Disallowed); + let lowered_ty = this.lower_ty(ty, ImplTraitContext::disallowed()); (trait_ref, lowered_ty) }, @@ -2838,7 +2863,7 @@ impl<'a> LoweringContext<'a> { ) } ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => { - let bounds = self.lower_param_bounds(bounds, ImplTraitContext::Disallowed); + let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed()); let items = items .iter() .map(|item| self.lower_trait_item_ref(item)) @@ -2846,14 +2871,14 @@ impl<'a> LoweringContext<'a> { hir::ItemKind::Trait( self.lower_is_auto(is_auto), self.lower_unsafety(unsafety), - self.lower_generics(generics, ImplTraitContext::Disallowed), + self.lower_generics(generics, ImplTraitContext::disallowed()), bounds, items, ) } ItemKind::TraitAlias(ref generics, ref bounds) => hir::ItemKind::TraitAlias( - self.lower_generics(generics, ImplTraitContext::Disallowed), - self.lower_param_bounds(bounds, ImplTraitContext::Disallowed), + self.lower_generics(generics, ImplTraitContext::disallowed()), + self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), ), ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"), } @@ -3043,9 +3068,9 @@ impl<'a> LoweringContext<'a> { let (generics, node) = match i.node { TraitItemKind::Const(ref ty, ref default) => ( - self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::TraitItemKind::Const( - self.lower_ty(ty, ImplTraitContext::Disallowed), + self.lower_ty(ty, ImplTraitContext::disallowed()), default .as_ref() .map(|x| self.lower_body(None, |this| this.lower_expr(x))), @@ -3077,12 +3102,12 @@ impl<'a> LoweringContext<'a> { (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } TraitItemKind::Type(ref bounds, ref default) => ( - self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::TraitItemKind::Type( - self.lower_param_bounds(bounds, ImplTraitContext::Disallowed), + self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), default .as_ref() - .map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)), + .map(|x| self.lower_ty(x, ImplTraitContext::disallowed())), ), ), TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -3132,9 +3157,9 @@ impl<'a> LoweringContext<'a> { ImplItemKind::Const(ref ty, ref expr) => { let body_id = self.lower_body(None, |this| this.lower_expr(expr)); ( - self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::ImplItemKind::Const( - self.lower_ty(ty, ImplTraitContext::Disallowed), + self.lower_ty(ty, ImplTraitContext::disallowed()), body_id, ), ) @@ -3152,13 +3177,13 @@ impl<'a> LoweringContext<'a> { (generics, hir::ImplItemKind::Method(sig, body_id)) } ImplItemKind::Type(ref ty) => ( - self.lower_generics(&i.generics, ImplTraitContext::Disallowed), - hir::ImplItemKind::Type(self.lower_ty(ty, ImplTraitContext::Disallowed)), + self.lower_generics(&i.generics, ImplTraitContext::disallowed()), + hir::ImplItemKind::Type(self.lower_ty(ty, ImplTraitContext::disallowed())), ), ImplItemKind::Existential(ref bounds) => ( - self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + self.lower_generics(&i.generics, ImplTraitContext::disallowed()), hir::ImplItemKind::Existential( - self.lower_param_bounds(bounds, ImplTraitContext::Disallowed), + self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), ), ), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -3349,7 +3374,8 @@ impl<'a> LoweringContext<'a> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(ref t, m) => { - hir::ForeignItemKind::Static(self.lower_ty(t, ImplTraitContext::Disallowed), m) + hir::ForeignItemKind::Static( + self.lower_ty(t, ImplTraitContext::disallowed()), m) } ForeignItemKind::Ty => hir::ForeignItemKind::Type, ForeignItemKind::Macro(_) => panic!("shouldn't exist here"), @@ -3488,7 +3514,7 @@ impl<'a> LoweringContext<'a> { &None, path, ParamMode::Optional, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ); self.check_self_struct_ctor_feature(&qpath); hir::PatKind::TupleStruct( @@ -3503,7 +3529,7 @@ impl<'a> LoweringContext<'a> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ); self.check_self_struct_ctor_feature(&qpath); hir::PatKind::Path(qpath) @@ -3514,7 +3540,7 @@ impl<'a> LoweringContext<'a> { &None, path, ParamMode::Optional, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ); let fs = fields @@ -3608,7 +3634,7 @@ impl<'a> LoweringContext<'a> { ParamMode::Optional, 0, ParenthesizedGenericArgs::Err, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ); let args = args.iter().map(|x| self.lower_expr(x)).collect(); hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args) @@ -3627,11 +3653,11 @@ impl<'a> LoweringContext<'a> { ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((**l).clone())), ExprKind::Cast(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); - hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::Disallowed)) + hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) } ExprKind::Type(ref expr, ref ty) => { let expr = P(self.lower_expr(expr)); - hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::Disallowed)) + hir::ExprKind::Type(expr, self.lower_ty(ty, ImplTraitContext::disallowed())) } ExprKind::AddrOf(m, ref ohs) => { let m = self.lower_mutability(m); @@ -3900,7 +3926,7 @@ impl<'a> LoweringContext<'a> { qself, path, ParamMode::Optional, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ); self.check_self_struct_ctor_feature(&qpath); hir::ExprKind::Path(qpath) @@ -3965,7 +3991,7 @@ impl<'a> LoweringContext<'a> { &None, path, ParamMode::Optional, - ImplTraitContext::Disallowed, + ImplTraitContext::disallowed(), ), fields.iter().map(|x| self.lower_field(x)).collect(), maybe_expr.as_ref().map(|x| P(self.lower_expr(x))), diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr index 52c99a7b159e3..82bc6194483c0 100644 --- a/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr +++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_bindings.stderr @@ -9,12 +9,16 @@ error[E0562]: `impl Trait` not allowed outside of function and inherent method r | LL | const FOO: impl Copy = 42; | ^^^^^^^^^ + | + = help: add #![feature(impl_trait_in_bindings)] to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types --> $DIR/feature-gate-impl_trait_in_bindings.rs:13:13 | LL | static BAR: impl Copy = 42; | ^^^^^^^^^ + | + = help: add #![feature(impl_trait_in_bindings)] to the crate attributes to enable error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index b15893e7c28cf..c43271c7371d2 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -231,6 +231,8 @@ error[E0562]: `impl Trait` not allowed outside of function and inherent method r | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ + | + = help: add #![feature(impl_trait_in_bindings)] to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types --> $DIR/where-allowed.rs:232:46 From f9375674dfcdcbab13eb3329c6986302964ad31a Mon Sep 17 00:00:00 2001 From: Collins Abitekaniza Date: Mon, 1 Oct 2018 04:06:58 +0300 Subject: [PATCH 23/24] allow use of ./x.py help ... --- src/bootstrap/bootstrap.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d9c66ce2d7790..c27f4f056d747 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -844,6 +844,11 @@ def bootstrap(help_triggered): def main(): """Entry point for the bootstrap process""" start_time = time() + + # x.py help ... + if len(sys.argv) > 1 and sys.argv[1] == 'help': + sys.argv = sys.argv[:1] + [sys.argv[2], '-h'] + sys.argv[3:] + help_triggered = ( '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) try: From e68db042888f6b3cb6164a5cc5bfc3a79faa851c Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 1 Oct 2018 11:11:58 +0200 Subject: [PATCH 24/24] Add nightly check for tool_lints warning cc #54358 --- src/librustc/lint/levels.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 80365a5610212..87d33e473e7f6 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -18,7 +18,7 @@ use lint::context::CheckLintNameResult; use lint::{self, Lint, LintId, Level, LintSource}; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; -use session::Session; +use session::{config::nightly_options, Session}; use syntax::ast; use syntax::attr; use syntax::source_map::MultiSpan; @@ -299,7 +299,13 @@ impl<'a> LintLevelsBuilder<'a> { "change it to", new_lint_name.to_string(), Applicability::MachineApplicable, - ).emit(); + ); + + if nightly_options::is_nightly_build() { + err.emit(); + } else { + err.cancel(); + } let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span); for id in ids {