Skip to content
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

Rollup of 6 pull requests #67271

Merged
merged 12 commits into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 15 additions & 1 deletion src/liballoc/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,21 @@ impl<T> LinkedList<T> {
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
fn drop(&mut self) {
while let Some(_) = self.pop_front_node() {}
struct DropGuard<'a, T>(&'a mut LinkedList<T>);

impl<'a, T> Drop for DropGuard<'a, T> {
fn drop(&mut self) {
// Continue the same loop we do below. This only runs when a destructor has
// panicked. If another one panics this will abort.
while let Some(_) = self.0.pop_front_node() {}
}
}

while let Some(node) = self.pop_front_node() {
let guard = DropGuard(self);
drop(node);
mem::forget(guard);
}
}
}

Expand Down
17 changes: 16 additions & 1 deletion src/liballoc/collections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2809,7 +2809,22 @@ impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> Extend<A> for VecDeque<A> {
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
iter.into_iter().for_each(move |elt| self.push_back(elt));
// This function should be the moral equivalent of:
//
// for item in iter.into_iter() {
// self.push_back(item);
// }
let mut iter = iter.into_iter();
while let Some(element) = iter.next() {
if self.len() == self.capacity() {
let (lower, _) = iter.size_hint();
self.reserve(lower.saturating_add(1));
}

let head = self.head;
self.head = self.wrap_add(self.head, 1);
unsafe { self.buffer_write(head, element); }
}
}
}

Expand Down
107 changes: 107 additions & 0 deletions src/liballoc/tests/linked_list.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::collections::LinkedList;
use std::panic::catch_unwind;

#[test]
fn test_basic() {
Expand Down Expand Up @@ -529,3 +530,109 @@ fn drain_filter_complex() {
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
}
}


#[test]
fn test_drop() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}

let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
drop(ring);

assert_eq!(unsafe { DROPS }, 4);
}

#[test]
fn test_drop_with_pop() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}

let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);

drop(ring.pop_back());
drop(ring.pop_front());
assert_eq!(unsafe { DROPS }, 2);

drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}

#[test]
fn test_drop_clear() {
static mut DROPS: i32 = 0;
struct Elem;
impl Drop for Elem {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}
}
}

let mut ring = LinkedList::new();
ring.push_back(Elem);
ring.push_front(Elem);
ring.push_back(Elem);
ring.push_front(Elem);
ring.clear();
assert_eq!(unsafe { DROPS }, 4);

drop(ring);
assert_eq!(unsafe { DROPS }, 4);
}

#[test]
fn test_drop_panic() {
static mut DROPS: i32 = 0;

struct D(bool);

impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}

if self.0 {
panic!("panic in `drop`");
}
}
}

let mut q = LinkedList::new();
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_front(D(false));
q.push_front(D(false));
q.push_front(D(true));

catch_unwind(move || drop(q)).ok();

assert_eq!(unsafe { DROPS }, 8);
}
16 changes: 12 additions & 4 deletions src/librustc_mir/borrow_check/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,18 +223,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {

fn report(&mut self, error: GroupedMoveError<'tcx>) {
let (mut err, err_span) = {
let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind<'_>) =
let (span, use_spans, original_path, kind,):
(
Span,
Option<UseSpans>,
&Place<'tcx>,
&IllegalMoveOriginKind<'_>,
) =
match error {
GroupedMoveError::MovesFromPlace { span, ref original_path, ref kind, .. } |
GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } => {
(span, original_path, kind)
(span, None, original_path, kind)
}
GroupedMoveError::OtherIllegalMove {
use_spans,
ref original_path,
ref kind
} => {
(use_spans.args_or_use(), original_path, kind)
(use_spans.args_or_use(), Some(use_spans), original_path, kind)
},
};
debug!("report: original_path={:?} span={:?}, kind={:?} \
Expand All @@ -250,6 +256,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
original_path,
target_place,
span,
use_spans,
)
}
IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
Expand Down Expand Up @@ -296,6 +303,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
move_place: &Place<'tcx>,
deref_target_place: &Place<'tcx>,
span: Span,
use_spans: Option<UseSpans>,
) -> DiagnosticBuilder<'a> {
// Inspect the type of the content behind the
// borrow to provide feedback about why this
Expand Down Expand Up @@ -416,7 +424,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
let is_option = move_ty.starts_with("std::option::Option");
let is_result = move_ty.starts_with("std::result::Result");
if is_option || is_result {
if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
err.span_suggestion(
span,
&format!("consider borrowing the `{}`'s content", if is_option {
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_mir/transform/qualify_min_const_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc
for ty in ty.walk() {
match ty.kind {
ty::Ref(_, _, hir::Mutability::Mutable) => {
if !tcx.features().const_mut_refs {
if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
return Err((
span,
"mutable references in const fn are unstable".into(),
Expand Down Expand Up @@ -220,7 +220,7 @@ fn check_statement(
}

| StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _)
if !tcx.features().const_if_match
if !feature_allowed(tcx, def_id, sym::const_if_match)
=> {
Err((span, "loops and conditional expressions are not stable in const fn".into()))
}
Expand Down Expand Up @@ -272,7 +272,7 @@ fn check_place(
while let &[ref proj_base @ .., elem] = cursor {
cursor = proj_base;
match elem {
ProjectionElem::Downcast(..) if !tcx.features().const_if_match
ProjectionElem::Downcast(..) if !feature_allowed(tcx, def_id, sym::const_if_match)
=> return Err((span, "`match` or `if let` in `const fn` is unstable".into())),
ProjectionElem::Downcast(_symbol, _variant_index) => {}

Expand Down Expand Up @@ -329,7 +329,7 @@ fn check_terminator(

| TerminatorKind::FalseEdges { .. }
| TerminatorKind::SwitchInt { .. }
if !tcx.features().const_if_match
if !feature_allowed(tcx, def_id, sym::const_if_match)
=> Err((
span,
"loops and conditional expressions are not stable in const fn".into(),
Expand All @@ -341,7 +341,7 @@ fn check_terminator(
}

// FIXME(ecstaticmorse): We probably want to allow `Unreachable` unconditionally.
TerminatorKind::Unreachable if tcx.features().const_if_match => Ok(()),
TerminatorKind::Unreachable if feature_allowed(tcx, def_id, sym::const_if_match) => Ok(()),

| TerminatorKind::Abort | TerminatorKind::Unreachable => {
Err((span, "const fn with unreachable code is not stable".into()))
Expand Down
22 changes: 16 additions & 6 deletions src/librustc_parse/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,16 +459,26 @@ impl<'a> Parser<'a> {
/// Parse `&pat` / `&mut pat`.
fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> {
self.expect_and()?;
self.recover_lifetime_in_deref_pat();
let mutbl = self.parse_mutability();
let subpat = self.parse_pat_with_range_pat(false, expected)?;
Ok(PatKind::Ref(subpat, mutbl))
}

fn recover_lifetime_in_deref_pat(&mut self) {
if let token::Lifetime(name) = self.token.kind {
let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name));
err.span_label(self.token.span, "unexpected lifetime");
return Err(err);
}
self.bump(); // `'a`

let subpat = self.parse_pat_with_range_pat(false, expected)?;
Ok(PatKind::Ref(subpat, mutbl))
let span = self.prev_span;
self.struct_span_err(span, &format!("unexpected lifetime `{}` in pattern", name))
.span_suggestion(
span,
"remove the lifetime",
String::new(),
Applicability::MachineApplicable,
)
.emit();
}
}

/// Parse a tuple or parenthesis pattern.
Expand Down
23 changes: 7 additions & 16 deletions src/libsyntax_expand/mbe/macro_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ use syntax::print::pprust;
use syntax::sess::ParseSess;
use syntax::symbol::{kw, sym, Symbol};
use syntax::token::{self, DocComment, Nonterminal, Token};
use syntax::tokenstream::{DelimSpan, TokenStream};
use syntax::tokenstream::TokenStream;

use errors::{PResult, FatalError};
use smallvec::{smallvec, SmallVec};
Expand Down Expand Up @@ -164,11 +164,6 @@ struct MatcherPos<'root, 'tt> {
/// The position of the "dot" in this matcher
idx: usize,

/// The first span of source that the beginning of this matcher corresponds to. In other
/// words, the token in the source whose span is `sp_open` is matched against the first token of
/// the matcher.
sp_open: Span,

/// For each named metavar in the matcher, we keep track of token trees matched against the
/// metavar by the black box parser. In particular, there may be more than one match per
/// metavar if we are in a repetition (each repetition matches each of the variables).
Expand Down Expand Up @@ -307,17 +302,15 @@ fn create_matches(len: usize) -> Box<[Lrc<NamedMatchVec>]> {
}

/// Generates the top-level matcher position in which the "dot" is before the first token of the
/// matcher `ms` and we are going to start matching at the span `open` in the source.
fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree], open: Span) -> MatcherPos<'root, 'tt> {
/// matcher `ms`.
fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree]) -> MatcherPos<'root, 'tt> {
let match_idx_hi = count_names(ms);
let matches = create_matches(match_idx_hi);
MatcherPos {
// Start with the top level matcher given to us
top_elts: TtSeq(ms), // "elts" is an abbr. for "elements"
// The "dot" is before the first token of the matcher
idx: 0,
// We start matching at the span `open` in the source code
sp_open: open,

// Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`.
// `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since
Expand Down Expand Up @@ -355,7 +348,7 @@ fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree], open: Span) -> MatcherP
/// token tree it was derived from.
#[derive(Debug, Clone)]
crate enum NamedMatch {
MatchedSeq(Lrc<NamedMatchVec>, DelimSpan),
MatchedSeq(Lrc<NamedMatchVec>),
MatchedNonterminal(Lrc<Nonterminal>),
}

Expand Down Expand Up @@ -497,8 +490,7 @@ fn inner_parse_loop<'root, 'tt>(
// Add matches from this repetition to the `matches` of `up`
for idx in item.match_lo..item.match_hi {
let sub = item.matches[idx].clone();
let span = DelimSpan::from_pair(item.sp_open, token.span);
new_pos.push_match(idx, MatchedSeq(sub, span));
new_pos.push_match(idx, MatchedSeq(sub));
}

// Move the "dot" past the repetition in `up`
Expand Down Expand Up @@ -552,7 +544,7 @@ fn inner_parse_loop<'root, 'tt>(
new_item.match_cur += seq.num_captures;
new_item.idx += 1;
for idx in item.match_cur..item.match_cur + seq.num_captures {
new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![]), sp));
new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![])));
}
cur_items.push(new_item);
}
Expand All @@ -568,7 +560,6 @@ fn inner_parse_loop<'root, 'tt>(
match_cur: item.match_cur,
match_hi: item.match_cur + seq.num_captures,
up: Some(item),
sp_open: sp.open,
top_elts: Tt(TokenTree::Sequence(sp, seq)),
})));
}
Expand Down Expand Up @@ -663,7 +654,7 @@ pub(super) fn parse(
//
// This MatcherPos instance is allocated on the stack. All others -- and
// there are frequently *no* others! -- are allocated on the heap.
let mut initial = initial_matcher_pos(ms, parser.token.span);
let mut initial = initial_matcher_pos(ms);
let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
let mut next_items = Vec::new();

Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax_expand/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ pub fn compile_declarative_macro(

// Extract the arguments:
let lhses = match argument_map[&lhs_nm] {
MatchedSeq(ref s, _) => s
MatchedSeq(ref s) => s
.iter()
.map(|m| {
if let MatchedNonterminal(ref nt) = *m {
Expand All @@ -402,7 +402,7 @@ pub fn compile_declarative_macro(
};

let rhses = match argument_map[&rhs_nm] {
MatchedSeq(ref s, _) => s
MatchedSeq(ref s) => s
.iter()
.map(|m| {
if let MatchedNonterminal(ref nt) = *m {
Expand Down
Loading