Skip to content

Commit cf7e019

Browse files
committed
Auto merge of #67271 - Centril:rollup-i71iqkv, r=Centril
Rollup of 6 pull requests Successful merges: - #66341 (Match `VecDeque::extend` to `Vec::extend_desugared`) - #67243 (LinkedList: drop remaining items when drop panics) - #67247 (Don't suggest wrong snippet in closure) - #67250 (Remove the `DelimSpan` from `NamedMatch::MatchedSeq`.) - #67251 (Require `allow_internal_unstable` for stable min_const_fn using unsta…) - #67269 (parser: recover on `&'lifetime mut? $pat`.) Failed merges: r? @ghost
2 parents 3eeb8d4 + d25197c commit cf7e019

24 files changed

+287
-67
lines changed

src/liballoc/collections/linked_list.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,21 @@ impl<T> LinkedList<T> {
808808
#[stable(feature = "rust1", since = "1.0.0")]
809809
unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
810810
fn drop(&mut self) {
811-
while let Some(_) = self.pop_front_node() {}
811+
struct DropGuard<'a, T>(&'a mut LinkedList<T>);
812+
813+
impl<'a, T> Drop for DropGuard<'a, T> {
814+
fn drop(&mut self) {
815+
// Continue the same loop we do below. This only runs when a destructor has
816+
// panicked. If another one panics this will abort.
817+
while let Some(_) = self.0.pop_front_node() {}
818+
}
819+
}
820+
821+
while let Some(node) = self.pop_front_node() {
822+
let guard = DropGuard(self);
823+
drop(node);
824+
mem::forget(guard);
825+
}
812826
}
813827
}
814828

src/liballoc/collections/vec_deque.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -2809,7 +2809,22 @@ impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
28092809
#[stable(feature = "rust1", since = "1.0.0")]
28102810
impl<A> Extend<A> for VecDeque<A> {
28112811
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
2812-
iter.into_iter().for_each(move |elt| self.push_back(elt));
2812+
// This function should be the moral equivalent of:
2813+
//
2814+
// for item in iter.into_iter() {
2815+
// self.push_back(item);
2816+
// }
2817+
let mut iter = iter.into_iter();
2818+
while let Some(element) = iter.next() {
2819+
if self.len() == self.capacity() {
2820+
let (lower, _) = iter.size_hint();
2821+
self.reserve(lower.saturating_add(1));
2822+
}
2823+
2824+
let head = self.head;
2825+
self.head = self.wrap_add(self.head, 1);
2826+
unsafe { self.buffer_write(head, element); }
2827+
}
28132828
}
28142829
}
28152830

src/liballoc/tests/linked_list.rs

+107
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::LinkedList;
2+
use std::panic::catch_unwind;
23

34
#[test]
45
fn test_basic() {
@@ -529,3 +530,109 @@ fn drain_filter_complex() {
529530
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]);
530531
}
531532
}
533+
534+
535+
#[test]
536+
fn test_drop() {
537+
static mut DROPS: i32 = 0;
538+
struct Elem;
539+
impl Drop for Elem {
540+
fn drop(&mut self) {
541+
unsafe {
542+
DROPS += 1;
543+
}
544+
}
545+
}
546+
547+
let mut ring = LinkedList::new();
548+
ring.push_back(Elem);
549+
ring.push_front(Elem);
550+
ring.push_back(Elem);
551+
ring.push_front(Elem);
552+
drop(ring);
553+
554+
assert_eq!(unsafe { DROPS }, 4);
555+
}
556+
557+
#[test]
558+
fn test_drop_with_pop() {
559+
static mut DROPS: i32 = 0;
560+
struct Elem;
561+
impl Drop for Elem {
562+
fn drop(&mut self) {
563+
unsafe {
564+
DROPS += 1;
565+
}
566+
}
567+
}
568+
569+
let mut ring = LinkedList::new();
570+
ring.push_back(Elem);
571+
ring.push_front(Elem);
572+
ring.push_back(Elem);
573+
ring.push_front(Elem);
574+
575+
drop(ring.pop_back());
576+
drop(ring.pop_front());
577+
assert_eq!(unsafe { DROPS }, 2);
578+
579+
drop(ring);
580+
assert_eq!(unsafe { DROPS }, 4);
581+
}
582+
583+
#[test]
584+
fn test_drop_clear() {
585+
static mut DROPS: i32 = 0;
586+
struct Elem;
587+
impl Drop for Elem {
588+
fn drop(&mut self) {
589+
unsafe {
590+
DROPS += 1;
591+
}
592+
}
593+
}
594+
595+
let mut ring = LinkedList::new();
596+
ring.push_back(Elem);
597+
ring.push_front(Elem);
598+
ring.push_back(Elem);
599+
ring.push_front(Elem);
600+
ring.clear();
601+
assert_eq!(unsafe { DROPS }, 4);
602+
603+
drop(ring);
604+
assert_eq!(unsafe { DROPS }, 4);
605+
}
606+
607+
#[test]
608+
fn test_drop_panic() {
609+
static mut DROPS: i32 = 0;
610+
611+
struct D(bool);
612+
613+
impl Drop for D {
614+
fn drop(&mut self) {
615+
unsafe {
616+
DROPS += 1;
617+
}
618+
619+
if self.0 {
620+
panic!("panic in `drop`");
621+
}
622+
}
623+
}
624+
625+
let mut q = LinkedList::new();
626+
q.push_back(D(false));
627+
q.push_back(D(false));
628+
q.push_back(D(false));
629+
q.push_back(D(false));
630+
q.push_back(D(false));
631+
q.push_front(D(false));
632+
q.push_front(D(false));
633+
q.push_front(D(true));
634+
635+
catch_unwind(move || drop(q)).ok();
636+
637+
assert_eq!(unsafe { DROPS }, 8);
638+
}

src/librustc_mir/borrow_check/diagnostics/move_errors.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
223223

224224
fn report(&mut self, error: GroupedMoveError<'tcx>) {
225225
let (mut err, err_span) = {
226-
let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind<'_>) =
226+
let (span, use_spans, original_path, kind,):
227+
(
228+
Span,
229+
Option<UseSpans>,
230+
&Place<'tcx>,
231+
&IllegalMoveOriginKind<'_>,
232+
) =
227233
match error {
228234
GroupedMoveError::MovesFromPlace { span, ref original_path, ref kind, .. } |
229235
GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } => {
230-
(span, original_path, kind)
236+
(span, None, original_path, kind)
231237
}
232238
GroupedMoveError::OtherIllegalMove {
233239
use_spans,
234240
ref original_path,
235241
ref kind
236242
} => {
237-
(use_spans.args_or_use(), original_path, kind)
243+
(use_spans.args_or_use(), Some(use_spans), original_path, kind)
238244
},
239245
};
240246
debug!("report: original_path={:?} span={:?}, kind={:?} \
@@ -250,6 +256,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
250256
original_path,
251257
target_place,
252258
span,
259+
use_spans,
253260
)
254261
}
255262
IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
@@ -296,6 +303,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
296303
move_place: &Place<'tcx>,
297304
deref_target_place: &Place<'tcx>,
298305
span: Span,
306+
use_spans: Option<UseSpans>,
299307
) -> DiagnosticBuilder<'a> {
300308
// Inspect the type of the content behind the
301309
// borrow to provide feedback about why this
@@ -416,7 +424,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
416424
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
417425
let is_option = move_ty.starts_with("std::option::Option");
418426
let is_result = move_ty.starts_with("std::result::Result");
419-
if is_option || is_result {
427+
if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
420428
err.span_suggestion(
421429
span,
422430
&format!("consider borrowing the `{}`'s content", if is_option {

src/librustc_mir/transform/qualify_min_const_fn.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc
8080
for ty in ty.walk() {
8181
match ty.kind {
8282
ty::Ref(_, _, hir::Mutability::Mutable) => {
83-
if !tcx.features().const_mut_refs {
83+
if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
8484
return Err((
8585
span,
8686
"mutable references in const fn are unstable".into(),
@@ -220,7 +220,7 @@ fn check_statement(
220220
}
221221

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

@@ -329,7 +329,7 @@ fn check_terminator(
329329

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

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

346346
| TerminatorKind::Abort | TerminatorKind::Unreachable => {
347347
Err((span, "const fn with unreachable code is not stable".into()))

src/librustc_parse/parser/pat.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -459,16 +459,26 @@ impl<'a> Parser<'a> {
459459
/// Parse `&pat` / `&mut pat`.
460460
fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> {
461461
self.expect_and()?;
462+
self.recover_lifetime_in_deref_pat();
462463
let mutbl = self.parse_mutability();
464+
let subpat = self.parse_pat_with_range_pat(false, expected)?;
465+
Ok(PatKind::Ref(subpat, mutbl))
466+
}
463467

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

470-
let subpat = self.parse_pat_with_range_pat(false, expected)?;
471-
Ok(PatKind::Ref(subpat, mutbl))
472+
let span = self.prev_span;
473+
self.struct_span_err(span, &format!("unexpected lifetime `{}` in pattern", name))
474+
.span_suggestion(
475+
span,
476+
"remove the lifetime",
477+
String::new(),
478+
Applicability::MachineApplicable,
479+
)
480+
.emit();
481+
}
472482
}
473483

474484
/// Parse a tuple or parenthesis pattern.

src/libsyntax_expand/mbe/macro_parser.rs

+7-16
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ use syntax::print::pprust;
8383
use syntax::sess::ParseSess;
8484
use syntax::symbol::{kw, sym, Symbol};
8585
use syntax::token::{self, DocComment, Nonterminal, Token};
86-
use syntax::tokenstream::{DelimSpan, TokenStream};
86+
use syntax::tokenstream::TokenStream;
8787

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

167-
/// The first span of source that the beginning of this matcher corresponds to. In other
168-
/// words, the token in the source whose span is `sp_open` is matched against the first token of
169-
/// the matcher.
170-
sp_open: Span,
171-
172167
/// For each named metavar in the matcher, we keep track of token trees matched against the
173168
/// metavar by the black box parser. In particular, there may be more than one match per
174169
/// metavar if we are in a repetition (each repetition matches each of the variables).
@@ -307,17 +302,15 @@ fn create_matches(len: usize) -> Box<[Lrc<NamedMatchVec>]> {
307302
}
308303

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

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

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

504496
// Move the "dot" past the repetition in `up`
@@ -552,7 +544,7 @@ fn inner_parse_loop<'root, 'tt>(
552544
new_item.match_cur += seq.num_captures;
553545
new_item.idx += 1;
554546
for idx in item.match_cur..item.match_cur + seq.num_captures {
555-
new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![]), sp));
547+
new_item.push_match(idx, MatchedSeq(Lrc::new(smallvec![])));
556548
}
557549
cur_items.push(new_item);
558550
}
@@ -568,7 +560,6 @@ fn inner_parse_loop<'root, 'tt>(
568560
match_cur: item.match_cur,
569561
match_hi: item.match_cur + seq.num_captures,
570562
up: Some(item),
571-
sp_open: sp.open,
572563
top_elts: Tt(TokenTree::Sequence(sp, seq)),
573564
})));
574565
}
@@ -663,7 +654,7 @@ pub(super) fn parse(
663654
//
664655
// This MatcherPos instance is allocated on the stack. All others -- and
665656
// there are frequently *no* others! -- are allocated on the heap.
666-
let mut initial = initial_matcher_pos(ms, parser.token.span);
657+
let mut initial = initial_matcher_pos(ms);
667658
let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)];
668659
let mut next_items = Vec::new();
669660

src/libsyntax_expand/mbe/macro_rules.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ pub fn compile_declarative_macro(
379379

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

404404
let rhses = match argument_map[&rhs_nm] {
405-
MatchedSeq(ref s, _) => s
405+
MatchedSeq(ref s) => s
406406
.iter()
407407
.map(|m| {
408408
if let MatchedNonterminal(ref nt) = *m {

0 commit comments

Comments
 (0)