Skip to content

Rollup of 9 pull requests #70931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1ce9257
ci: move /var/lib/docker to /mnt on GHA
pietroalbini Apr 6, 2020
bdbe56e
BTreeMap first/last: simplify implementations
ssomers Apr 4, 2020
c23ee76
BTreeMap first/last: make examples more to the point
ssomers Apr 6, 2020
8212b97
BTreeMap first/last: add pop methods
ssomers Apr 5, 2020
a90661a
Use a `SmallVec` for `Cache::predecessors`.
nnethercote Apr 7, 2020
6569a2e
Clean up E0507 explanation
GuillaumeGomez Apr 7, 2020
ab4178b
wf: refactor `compute_trait_ref`
lcnr Apr 7, 2020
817f059
remove false positives of unused_braces
lcnr Apr 4, 2020
d55c399
Corrects a typo in rustdoc documentation.
tsandstr Apr 7, 2020
4cdb206
Remove unnecessary TypeFlags::NOMINAL_FLAGS
tsandstr Apr 8, 2020
80e3126
Clean up E0510 explanation
GuillaumeGomez Apr 8, 2020
956e50b
Rollup merge of #70789 - lcnr:macros, r=varkor
Dylan-DPC Apr 8, 2020
54abd4f
Rollup merge of #70847 - pietroalbini:ci-move-docker-lib, r=Mark-Simu…
Dylan-DPC Apr 8, 2020
b9bb126
Rollup merge of #70850 - ssomers:btreemap_first_last, r=Amanieu
Dylan-DPC Apr 8, 2020
e97a6e7
Rollup merge of #70876 - nnethercote:smallvec-predecessors, r=estebank
Dylan-DPC Apr 8, 2020
6696666
Rollup merge of #70883 - GuillaumeGomez:cleanup-e0507, r=Dylan-DPC
Dylan-DPC Apr 8, 2020
e3346e5
Rollup merge of #70892 - lcnr:interators_are_nice, r=nikomatsakis
Dylan-DPC Apr 8, 2020
9a84771
Rollup merge of #70914 - tsandstr:typo1, r=Dylan-DPC
Dylan-DPC Apr 8, 2020
bad8f0b
Rollup merge of #70915 - tsandstr:remove-nominal-flags, r=eddyb
Dylan-DPC Apr 8, 2020
1498da8
Rollup merge of #70927 - GuillaumeGomez:cleanup-e0510, r=Dylan-DPC
Dylan-DPC Apr 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/ci/scripts/symlink-build-dir.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,10 @@ elif isLinux && isGitHubActions; then
mv "${current_dir}" /mnt/more-space/workspace
ln -s /mnt/more-space/workspace "${current_dir}"
cd "${current_dir}"

# Move the Docker data directory to /mnt
sudo systemctl stop docker.service
sudo mv /var/lib/docker /mnt/docker
sudo ln -s /mnt/docker /var/lib/docker
sudo systemctl start docker.service
fi
6 changes: 3 additions & 3 deletions src/doc/rustdoc/src/documentation-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,9 @@ are added.
/// ```
```

`edition2018` tells `rustdoc` that the code sample should be compiled the 2018
edition of Rust. Similarly, you can specify `edition2015` to compile the code
with the 2015 edition.
`edition2018` tells `rustdoc` that the code sample should be compiled using
the 2018 edition of Rust. Similarly, you can specify `edition2015` to compile
the code with the 2015 edition.

## Syntax reference

Expand Down
124 changes: 76 additions & 48 deletions src/liballoc/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,11 +653,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.first_key_value(), Some((&1, &"b")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_key_value(&self) -> Option<(&K, &V)> {
let front = self.root.as_ref()?.as_ref().first_leaf_edge();
front.right_kv().ok().map(Handle::into_kv)
}
Expand All @@ -667,36 +663,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.first_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.first_entry() {
/// if *entry.key() > 0 {
/// entry.insert("first");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "first");
/// assert_eq!(*map.get(&2).unwrap(), "b");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let front = self.root.as_mut()?.as_mut().first_leaf_edge();
if let Ok(kv) = front.right_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = front.right_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the first element in the map.
/// The key of this element is the minimum key that was in the map.
///
/// # Examples
///
/// Draining elements in ascending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_first() {
/// assert!(map.iter().all(|(k, _v)| *k > key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_first(&mut self) -> Option<(K, V)> {
self.first_entry().map(|entry| entry.remove_entry())
}

/// Returns the last key-value pair in the map.
Expand All @@ -716,11 +730,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.last_key_value(), Some((&2, &"a")));
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_key_value<T: ?Sized>(&self) -> Option<(&K, &V)>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_key_value(&self) -> Option<(&K, &V)> {
let back = self.root.as_ref()?.as_ref().last_leaf_edge();
back.left_kv().ok().map(Handle::into_kv)
}
Expand All @@ -730,36 +740,54 @@ impl<K: Ord, V> BTreeMap<K, V> {
///
/// # Examples
///
/// Contrived way to `clear` a map:
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some(entry) = map.last_entry() {
/// let (key, val) = entry.remove_entry();
/// assert!(!map.contains_key(&key));
/// if let Some(mut entry) = map.last_entry() {
/// if *entry.key() > 0 {
/// entry.insert("last");
/// }
/// }
/// assert_eq!(*map.get(&1).unwrap(), "a");
/// assert_eq!(*map.get(&2).unwrap(), "last");
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_entry<T: ?Sized>(&mut self) -> Option<OccupiedEntry<'_, K, V>>
where
T: Ord,
K: Borrow<T>,
{
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let back = self.root.as_mut()?.as_mut().last_leaf_edge();
if let Ok(kv) = back.left_kv() {
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
} else {
None
}
let kv = back.left_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
_marker: PhantomData,
})
}

/// Removes and returns the last element in the map.
/// The key of this element is the maximum key that was in the map.
///
/// # Examples
///
/// Draining elements in descending order, while keeping a usable map each iteration.
///
/// ```
/// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// while let Some((key, _val)) = map.pop_last() {
/// assert!(map.iter().all(|(k, _v)| *k < key));
/// }
/// assert!(map.is_empty());
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn pop_last(&mut self) -> Option<(K, V)> {
self.last_entry().map(|entry| entry.remove_entry())
}

/// Returns `true` if the map contains a value for the specified key.
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_error_codes/error_codes/E0507.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
You tried to move out of a value which was borrowed.

This can also happen when using a type implementing `Fn` or `FnMut`, as neither
allows moving out of them (they usually represent closures which can be called
more than once). Much of the text following applies equally well to non-`FnOnce`
closure bodies.
A borrowed value was moved out.

Erroneous code example:

Expand Down Expand Up @@ -32,6 +27,11 @@ you have three choices:
* Somehow reclaim the ownership.
* Implement the `Copy` trait on the type.

This can also happen when using a type implementing `Fn` or `FnMut`, as neither
allows moving out of them (they usually represent closures which can be called
more than once). Much of the text following applies equally well to non-`FnOnce`
closure bodies.

Examples:

```
Expand Down
27 changes: 20 additions & 7 deletions src/librustc_error_codes/error_codes/E0510.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
Cannot mutate place in this match guard.
The matched value was assigned in a match guard.

When matching on a variable it cannot be mutated in the match guards, as this
could cause the match to be non-exhaustive:
Erroneous code example:

```compile_fail,E0510
let mut x = Some(0);
match x {
None => (),
Some(_) if { x = None; false } => (),
Some(v) => (), // No longer matches
None => {}
Some(_) if { x = None; false } => {} // error!
Some(_) => {}
}
```

When matching on a variable it cannot be mutated in the match guards, as this
could cause the match to be non-exhaustive.

Here executing `x = None` would modify the value being matched and require us
to go "back in time" to the `None` arm.
to go "back in time" to the `None` arm. To fix it, change the value in the match
arm:

```
let mut x = Some(0);
match x {
None => {}
Some(_) => {
x = None; // ok!
}
}
```
26 changes: 23 additions & 3 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,19 @@ impl From<UnusedDelimsCtx> for &'static str {
trait UnusedDelimLint {
const DELIM_STR: &'static str;

/// Due to `ref` pattern, there can be a difference between using
/// `{ expr }` and `expr` in pattern-matching contexts. This means
/// that we should only lint `unused_parens` and not `unused_braces`
/// in this case.
///
/// ```rust
/// let mut a = 7;
/// let ref b = { a }; // We actually borrow a copy of `a` here.
/// a += 1; // By mutating `a` we invalidate any borrows of `a`.
/// assert_eq!(b + 1, a); // `b` does not borrow `a`, so we can still use it here.
/// ```
const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool;

// this cannot be a constant is it refers to a static.
fn lint(&self) -> &'static Lint;

Expand Down Expand Up @@ -454,7 +467,10 @@ trait UnusedDelimLint {
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
use rustc_ast::ast::ExprKind::*;
let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
If(ref cond, ref block, ..) => {
// Do not lint `unused_braces` in `if let` expressions.
If(ref cond, ref block, ..)
if !matches!(cond.kind, Let(_, _)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
{
let left = e.span.lo() + rustc_span::BytePos(2);
let right = block.span.lo();
(cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right))
Expand All @@ -470,7 +486,7 @@ trait UnusedDelimLint {
(cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()))
}

Match(ref head, _) => {
Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
let left = e.span.lo() + rustc_span::BytePos(5);
(head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None)
}
Expand Down Expand Up @@ -512,7 +528,7 @@ trait UnusedDelimLint {

fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
match s.kind {
StmtKind::Local(ref local) => {
StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
if let Some(ref value) = local.init {
self.check_unused_delims_expr(
cx,
Expand Down Expand Up @@ -565,6 +581,8 @@ declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
impl UnusedDelimLint for UnusedParens {
const DELIM_STR: &'static str = "parentheses";

const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;

fn lint(&self) -> &'static Lint {
UNUSED_PARENS
}
Expand Down Expand Up @@ -736,6 +754,8 @@ declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
impl UnusedDelimLint for UnusedBraces {
const DELIM_STR: &'static str = "braces";

const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;

fn lint(&self) -> &'static Lint {
UNUSED_BRACES
}
Expand Down
16 changes: 11 additions & 5 deletions src/librustc_middle/mir/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_index::vec::IndexVec;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use smallvec::SmallVec;
use std::iter;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::vec::IntoIter;

#[derive(Clone, Debug)]
pub struct Cache {
predecessors: Option<IndexVec<BasicBlock, Vec<BasicBlock>>>,
// Typically 95%+ of the inner vectors have 4 or fewer elements.
predecessors: Option<IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>>,
}

impl rustc_serialize::Encodable for Cache {
Expand Down Expand Up @@ -44,7 +46,7 @@ impl Cache {

pub fn ensure_predecessors(&mut self, body: &Body<'_>) {
if self.predecessors.is_none() {
let mut result = IndexVec::from_elem(vec![], body.basic_blocks());
let mut result = IndexVec::from_elem(smallvec![], body.basic_blocks());
for (bb, data) in body.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
for &tgt in term.successors() {
Expand All @@ -58,7 +60,11 @@ impl Cache {
}

/// This will recompute the predecessors cache if it is not available
fn predecessors(&mut self, body: &Body<'_>) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
// njn: typedef?
fn predecessors(
&mut self,
body: &Body<'_>,
) -> &IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>> {
self.ensure_predecessors(body);
self.predecessors.as_ref().unwrap()
}
Expand Down Expand Up @@ -137,7 +143,7 @@ impl BodyAndCache<'tcx> {
self.cache.ensure_predecessors(&self.body);
}

pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
pub fn predecessors(&mut self) -> &IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>> {
self.cache.predecessors(&self.body)
}

Expand Down Expand Up @@ -199,7 +205,7 @@ impl ReadOnlyBodyAndCache<'a, 'tcx> {
Self { body, cache }
}

pub fn predecessors(&self) -> &IndexVec<BasicBlock, Vec<BasicBlock>> {
pub fn predecessors(&self) -> &IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>> {
self.cache.predecessors.as_ref().unwrap()
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl FlagComputation {
}

fn add_flags(&mut self, flags: TypeFlags) {
self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
self.flags = self.flags | flags;
}

/// indicates that `self` refers to something at binding level `binder`
Expand Down
Loading