Skip to content
Merged
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
@@ -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);
}
}
}

17 changes: 16 additions & 1 deletion src/liballoc/collections/vec_deque.rs
Original file line number Diff line number Diff line change
@@ -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); }
}
}
}

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() {
@@ -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
@@ -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={:?} \
@@ -250,6 +256,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
original_path,
target_place,
span,
use_spans,
)
}
IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
@@ -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
@@ -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 {
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
@@ -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(),
@@ -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()))
}
@@ -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) => {}

@@ -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(),
@@ -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()))
22 changes: 16 additions & 6 deletions src/librustc_parse/parser/pat.rs
Original file line number Diff line number Diff line change
@@ -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.
23 changes: 7 additions & 16 deletions src/libsyntax_expand/mbe/macro_parser.rs
Original file line number Diff line number Diff line change
@@ -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};
@@ -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).
@@ -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
@@ -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>),
}

@@ -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`
@@ -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);
}
@@ -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)),
})));
}
@@ -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();

4 changes: 2 additions & 2 deletions src/libsyntax_expand/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
@@ -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 {
@@ -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 {
4 changes: 2 additions & 2 deletions src/libsyntax_expand/mbe/transcribe.rs
Original file line number Diff line number Diff line change
@@ -299,7 +299,7 @@ fn lookup_cur_matched<'a>(
for &(idx, _) in repeats {
match matched {
MatchedNonterminal(_) => break,
MatchedSeq(ref ads, _) => matched = ads.get(idx).unwrap(),
MatchedSeq(ref ads) => matched = ads.get(idx).unwrap(),
}
}

@@ -382,7 +382,7 @@ fn lockstep_iter_size(
match lookup_cur_matched(name, interpolations, repeats) {
Some(matched) => match matched {
MatchedNonterminal(_) => LockstepIterSize::Unconstrained,
MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name),
MatchedSeq(ref ads) => LockstepIterSize::Constraint(ads.len(), name),
},
_ => LockstepIterSize::Unconstrained,
}
1 change: 1 addition & 0 deletions src/test/ui/consts/const-mut-refs/const_mut_refs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// run-pass

#![feature(const_mut_refs)]
#![feature(const_fn)]

struct Foo {
x: usize
1 change: 1 addition & 0 deletions src/test/ui/consts/control-flow/basics.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@

#![feature(const_panic)]
#![feature(const_if_match)]
#![feature(const_fn)]

const X: u32 = 4;
const Y: u32 = 5;
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
// check-pass

#![feature(const_if_match)]
#![feature(const_fn)]

enum E {
A,
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/feature-gate-const-if-match.rs:108:1
--> $DIR/feature-gate-const-if-match.rs:109:1
|
LL | / fn main() {
LL | | let _ = [0; {
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@

#![feature(rustc_attrs)]
#![cfg_attr(if_match, feature(const_if_match))]
#![feature(const_fn)]

const _: i32 = if true { //[stock]~ ERROR `if` is not allowed in a `const`
5
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:10:16
--> $DIR/feature-gate-const-if-match.rs:11:16
|
LL | const _: i32 = if true {
| ________________^
@@ -13,7 +13,7 @@ LL | | };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:16:16
--> $DIR/feature-gate-const-if-match.rs:17:16
|
LL | const _: i32 = if let Some(true) = Some(false) {
| ________________^
@@ -27,7 +27,7 @@ LL | | };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:22:16
--> $DIR/feature-gate-const-if-match.rs:23:16
|
LL | const _: i32 = match 1 {
| ________________^
@@ -41,7 +41,7 @@ LL | | };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `static`
--> $DIR/feature-gate-const-if-match.rs:29:13
--> $DIR/feature-gate-const-if-match.rs:30:13
|
LL | let x = if true { 0 } else { 1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +50,7 @@ LL | let x = if true { 0 } else { 1 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `static`
--> $DIR/feature-gate-const-if-match.rs:31:13
--> $DIR/feature-gate-const-if-match.rs:32:13
|
LL | let x = match x { 0 => 1, _ => 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@ LL | let x = match x { 0 => 1, _ => 0 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `static`
--> $DIR/feature-gate-const-if-match.rs:33:5
--> $DIR/feature-gate-const-if-match.rs:34:5
|
LL | if let Some(x) = Some(x) { x } else { 1 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -68,7 +68,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 }
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `static mut`
--> $DIR/feature-gate-const-if-match.rs:38:13
--> $DIR/feature-gate-const-if-match.rs:39:13
|
LL | let x = if true { 0 } else { 1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL | let x = if true { 0 } else { 1 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `static mut`
--> $DIR/feature-gate-const-if-match.rs:40:13
--> $DIR/feature-gate-const-if-match.rs:41:13
|
LL | let x = match x { 0 => 1, _ => 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -86,7 +86,7 @@ LL | let x = match x { 0 => 1, _ => 0 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `static mut`
--> $DIR/feature-gate-const-if-match.rs:42:5
--> $DIR/feature-gate-const-if-match.rs:43:5
|
LL | if let Some(x) = Some(x) { x } else { 1 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,7 +95,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 }
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const fn`
--> $DIR/feature-gate-const-if-match.rs:47:5
--> $DIR/feature-gate-const-if-match.rs:48:5
|
LL | if true { 5 } else { 6 }
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -104,7 +104,7 @@ LL | if true { 5 } else { 6 }
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const fn`
--> $DIR/feature-gate-const-if-match.rs:51:5
--> $DIR/feature-gate-const-if-match.rs:52:5
|
LL | / if let Some(true) = a {
LL | | 0
@@ -117,7 +117,7 @@ LL | | }
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `const fn`
--> $DIR/feature-gate-const-if-match.rs:59:5
--> $DIR/feature-gate-const-if-match.rs:60:5
|
LL | / match i {
LL | | i if i > 10 => i,
@@ -130,7 +130,7 @@ LL | | }
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const fn`
--> $DIR/feature-gate-const-if-match.rs:90:17
--> $DIR/feature-gate-const-if-match.rs:91:17
|
LL | let x = if y { 0 } else { 1 };
| ^^^^^^^^^^^^^^^^^^^^^
@@ -139,7 +139,7 @@ LL | let x = if y { 0 } else { 1 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `const fn`
--> $DIR/feature-gate-const-if-match.rs:92:17
--> $DIR/feature-gate-const-if-match.rs:93:17
|
LL | let x = match x { 0 => 1, _ => 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +148,7 @@ LL | let x = match x { 0 => 1, _ => 0 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const fn`
--> $DIR/feature-gate-const-if-match.rs:94:9
--> $DIR/feature-gate-const-if-match.rs:95:9
|
LL | if let Some(x) = Some(x) { x } else { 1 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -157,7 +157,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 }
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:110:17
--> $DIR/feature-gate-const-if-match.rs:111:17
|
LL | let x = if false { 0 } else { 1 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,7 +166,7 @@ LL | let x = if false { 0 } else { 1 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:112:17
--> $DIR/feature-gate-const-if-match.rs:113:17
|
LL | let x = match x { 0 => 1, _ => 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -175,7 +175,7 @@ LL | let x = match x { 0 => 1, _ => 0 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:114:9
--> $DIR/feature-gate-const-if-match.rs:115:9
|
LL | if let Some(x) = Some(x) { x } else { 1 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +184,7 @@ LL | if let Some(x) = Some(x) { x } else { 1 }
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:67:21
--> $DIR/feature-gate-const-if-match.rs:68:21
|
LL | const IF: i32 = if true { 5 } else { 6 };
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +193,7 @@ LL | const IF: i32 = if true { 5 } else { 6 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:70:25
--> $DIR/feature-gate-const-if-match.rs:71:25
|
LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -202,7 +202,7 @@ LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:73:24
--> $DIR/feature-gate-const-if-match.rs:74:24
|
LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -211,7 +211,7 @@ LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:78:21
--> $DIR/feature-gate-const-if-match.rs:79:21
|
LL | const IF: i32 = if true { 5 } else { 6 };
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +220,7 @@ LL | const IF: i32 = if true { 5 } else { 6 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `if` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:81:25
--> $DIR/feature-gate-const-if-match.rs:82:25
|
LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,7 +229,7 @@ LL | const IF_LET: i32 = if let Some(true) = None { 5 } else { 6 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0658]: `match` is not allowed in a `const`
--> $DIR/feature-gate-const-if-match.rs:84:24
--> $DIR/feature-gate-const-if-match.rs:85:24
|
LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -238,7 +238,7 @@ LL | const MATCH: i32 = match 0 { 1 => 2, _ => 0 };
= help: add `#![feature(const_if_match)]` to the crate attributes to enable

error[E0019]: constant contains unimplemented expression type
--> $DIR/feature-gate-const-if-match.rs:114:21
--> $DIR/feature-gate-const-if-match.rs:115:21
|
LL | if let Some(x) = Some(x) { x } else { 1 }
| ^
1 change: 1 addition & 0 deletions src/test/ui/consts/control-flow/short-circuit-let.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@

#![feature(const_if_match)]
#![feature(const_panic)]
#![feature(const_fn)]

const X: i32 = {
let mut x = 0;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// check-pass

#![feature(const_if_match)]
#![feature(const_if_match, const_fn)]

enum Foo {
Prob,
6 changes: 6 additions & 0 deletions src/test/ui/parser/lifetime-in-pattern-recover.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
let &'a x = &0; //~ ERROR unexpected lifetime `'a` in pattern
let &'a mut y = &mut 0; //~ ERROR unexpected lifetime `'a` in pattern

let _recovery_witness: () = 0; //~ ERROR mismatched types
}
23 changes: 23 additions & 0 deletions src/test/ui/parser/lifetime-in-pattern-recover.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
error: unexpected lifetime `'a` in pattern
--> $DIR/lifetime-in-pattern-recover.rs:2:10
|
LL | let &'a x = &0;
| ^^ help: remove the lifetime

error: unexpected lifetime `'a` in pattern
--> $DIR/lifetime-in-pattern-recover.rs:3:10
|
LL | let &'a mut y = &mut 0;
| ^^ help: remove the lifetime

error[E0308]: mismatched types
--> $DIR/lifetime-in-pattern-recover.rs:5:33
|
LL | let _recovery_witness: () = 0;
| -- ^ expected `()`, found integer
| |
| expected due to this

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0308`.
1 change: 1 addition & 0 deletions src/test/ui/parser/lifetime-in-pattern.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fn test(&'a str) {
//~^ ERROR unexpected lifetime `'a` in pattern
//~| ERROR expected one of `:`, `@`, or `|`, found `)`
}

fn main() {
10 changes: 8 additions & 2 deletions src/test/ui/parser/lifetime-in-pattern.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,13 @@ error: unexpected lifetime `'a` in pattern
--> $DIR/lifetime-in-pattern.rs:1:10
|
LL | fn test(&'a str) {
| ^^ unexpected lifetime
| ^^ help: remove the lifetime

error: aborting due to previous error
error: expected one of `:`, `@`, or `|`, found `)`
--> $DIR/lifetime-in-pattern.rs:1:16
|
LL | fn test(&'a str) {
| ^ expected one of `:`, `@`, or `|`

error: aborting due to 2 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/self/self-vs-path-ambiguity.stderr
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ error: unexpected lifetime `'a` in pattern
--> $DIR/self-vs-path-ambiguity.rs:9:11
|
LL | fn i(&'a self::S: &S) {}
| ^^ unexpected lifetime
| ^^ help: remove the lifetime

error: aborting due to previous error

16 changes: 16 additions & 0 deletions src/test/ui/suggestions/option-content-move2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
struct NotCopyable;

fn func<F: FnMut() -> H, H: FnMut()>(_: F) {}

fn parse() {
let mut var = None;
func(|| {
// Shouldn't suggest `move ||.as_ref()` here
move || {
//~^ ERROR: cannot move out of `var`
var = Some(NotCopyable);
}
});
}

fn main() {}
18 changes: 18 additions & 0 deletions src/test/ui/suggestions/option-content-move2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
--> $DIR/option-content-move2.rs:9:9
|
LL | let mut var = None;
| ------- captured outer variable
...
LL | move || {
| ^^^^^^^ move out of `var` occurs here
LL |
LL | var = Some(NotCopyable);
| ---
| |
| move occurs because `var` has type `std::option::Option<NotCopyable>`, which does not implement the `Copy` trait
| move occurs due to use in closure

error: aborting due to previous error

For more information about this error, try `rustc --explain E0507`.