Auto merge of #45956 - kennytm:rollup, r=kennytm
Rollup of 9 pull requests - Successful merges: #45828, #45892, #45893, #45914, #45917, #45927, #45933, #45952, #45954 - Failed merges:
This commit is contained in:
commit
e312c8a8c3
|
@ -634,17 +634,13 @@ impl<T> Option<T> {
|
|||
#[inline]
|
||||
#[unstable(feature = "option_filter", issue = "45860")]
|
||||
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
|
||||
match self {
|
||||
Some(x) => {
|
||||
if let Some(x) = self {
|
||||
if predicate(&x) {
|
||||
Some(x)
|
||||
} else {
|
||||
return Some(x)
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the option if it contains a value, otherwise returns `optb`.
|
||||
///
|
||||
|
|
|
@ -1949,7 +1949,7 @@ impl ForeignItem_ {
|
|||
}
|
||||
|
||||
/// A free variable referred to in a function.
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct Freevar {
|
||||
/// The variable being accessed free.
|
||||
pub def: Def,
|
||||
|
|
|
@ -267,10 +267,10 @@ impl<'tcx> Mir<'tcx> {
|
|||
let block = &self[location.block];
|
||||
let stmts = &block.statements;
|
||||
let idx = location.statement_index;
|
||||
if location.statement_index < stmts.len() {
|
||||
if idx < stmts.len() {
|
||||
&stmts[idx].source_info
|
||||
} else {
|
||||
assert!(location.statement_index == stmts.len());
|
||||
assert!(idx == stmts.len());
|
||||
&block.terminator().source_info
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,11 +164,13 @@ enum DiagnosticBuilderMethod {
|
|||
// add more variants as needed to support one-time diagnostics
|
||||
}
|
||||
|
||||
/// Diagnostic message id - used in order to avoid emitting the same message more than once
|
||||
/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid
|
||||
/// emitting the same message more than once
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum DiagnosticMessageId {
|
||||
ErrorId(u16), // EXXXX error code as integer
|
||||
LintId(lint::LintId),
|
||||
StabilityId(u32)
|
||||
StabilityId(u32) // issue number
|
||||
}
|
||||
|
||||
impl Session {
|
||||
|
|
|
@ -36,6 +36,7 @@ use middle::const_val;
|
|||
use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
|
||||
use std::fmt;
|
||||
use syntax::ast;
|
||||
use session::DiagnosticMessageId;
|
||||
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::error::ExpectedFound;
|
||||
use ty::fast_reject;
|
||||
|
@ -219,6 +220,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let msg = format!("type mismatch resolving `{}`", predicate);
|
||||
let error_id = (DiagnosticMessageId::ErrorId(271),
|
||||
Some(obligation.cause.span), msg.clone());
|
||||
let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
if fresh {
|
||||
let mut diag = struct_span_err!(
|
||||
self.tcx.sess, obligation.cause.span, E0271,
|
||||
"type mismatch resolving `{}`", predicate
|
||||
|
@ -226,6 +232,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.note_type_err(&mut diag, &obligation.cause, None, values, err);
|
||||
self.note_obligation_cause(&mut diag, obligation);
|
||||
diag.emit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1169,8 +1169,72 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
|||
err.emit();
|
||||
}
|
||||
|
||||
/// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of
|
||||
/// the local assigned at `location`.
|
||||
/// This is done by searching in statements succeeding `location`
|
||||
/// and originating from `maybe_closure_span`.
|
||||
fn find_closure_span(
|
||||
&self,
|
||||
maybe_closure_span: Span,
|
||||
location: Location,
|
||||
) -> Option<(Span, Span)> {
|
||||
use rustc::hir::ExprClosure;
|
||||
use rustc::mir::AggregateKind;
|
||||
|
||||
let local = if let StatementKind::Assign(Lvalue::Local(local), _) =
|
||||
self.mir[location.block].statements[location.statement_index].kind
|
||||
{
|
||||
local
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
for stmt in &self.mir[location.block].statements[location.statement_index + 1..] {
|
||||
if maybe_closure_span != stmt.source_info.span {
|
||||
break;
|
||||
}
|
||||
|
||||
if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref lvs)) = stmt.kind {
|
||||
if let AggregateKind::Closure(def_id, _) = **kind {
|
||||
debug!("find_closure_span: found closure {:?}", lvs);
|
||||
|
||||
return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
|
||||
let args_span = if let ExprClosure(_, _, _, span, _) =
|
||||
self.tcx.hir.expect_expr(node_id).node
|
||||
{
|
||||
span
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
self.tcx
|
||||
.with_freevars(node_id, |freevars| {
|
||||
for (v, lv) in freevars.iter().zip(lvs) {
|
||||
if let Operand::Consume(Lvalue::Local(l)) = *lv {
|
||||
if local == l {
|
||||
debug!(
|
||||
"find_closure_span: found captured local {:?}",
|
||||
l
|
||||
);
|
||||
return Some(v.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.map(|var_span| (args_span, var_span))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn report_conflicting_borrow(&mut self,
|
||||
_context: Context,
|
||||
context: Context,
|
||||
common_prefix: &Lvalue,
|
||||
(lvalue, span): (&Lvalue, Span),
|
||||
gen_borrow_kind: BorrowKind,
|
||||
|
@ -1183,38 +1247,60 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
|
|||
|
||||
let issued_span = self.retrieve_borrow_span(issued_borrow);
|
||||
|
||||
let new_closure_span = self.find_closure_span(span, context.loc);
|
||||
let span = new_closure_span.map(|(args, _)| args).unwrap_or(span);
|
||||
let old_closure_span = self.find_closure_span(issued_span, issued_borrow.location);
|
||||
let issued_span = old_closure_span.map(|(args, _)| args).unwrap_or(issued_span);
|
||||
|
||||
let desc_lvalue = self.describe_lvalue(lvalue);
|
||||
|
||||
// FIXME: supply non-"" `opt_via` when appropriate
|
||||
let mut err = match (gen_borrow_kind, "immutable", "mutable",
|
||||
issued_borrow.kind, "immutable", "mutable") {
|
||||
(BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) |
|
||||
(BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) =>
|
||||
self.tcx.cannot_reborrow_already_borrowed(
|
||||
span, &self.describe_lvalue(lvalue), "", lft, issued_span,
|
||||
span, &desc_lvalue, "", lft, issued_span,
|
||||
"it", rgt, "", end_issued_loan_span, Origin::Mir),
|
||||
|
||||
(BorrowKind::Mut, _, _, BorrowKind::Mut, _, _) =>
|
||||
self.tcx.cannot_mutably_borrow_multiply(
|
||||
span, &self.describe_lvalue(lvalue), "", issued_span,
|
||||
span, &desc_lvalue, "", issued_span,
|
||||
"", end_issued_loan_span, Origin::Mir),
|
||||
|
||||
(BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) =>
|
||||
self.tcx.cannot_uniquely_borrow_by_two_closures(
|
||||
span, &self.describe_lvalue(lvalue), issued_span,
|
||||
span, &desc_lvalue, issued_span,
|
||||
end_issued_loan_span, Origin::Mir),
|
||||
|
||||
(BorrowKind::Unique, _, _, _, _, _) =>
|
||||
self.tcx.cannot_uniquely_borrow_by_one_closure(
|
||||
span, &self.describe_lvalue(lvalue), "",
|
||||
span, &desc_lvalue, "",
|
||||
issued_span, "it", "", end_issued_loan_span, Origin::Mir),
|
||||
|
||||
(_, _, _, BorrowKind::Unique, _, _) =>
|
||||
self.tcx.cannot_reborrow_already_uniquely_borrowed(
|
||||
span, &self.describe_lvalue(lvalue), "it", "",
|
||||
span, &desc_lvalue, "it", "",
|
||||
issued_span, "", end_issued_loan_span, Origin::Mir),
|
||||
|
||||
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) =>
|
||||
unreachable!(),
|
||||
};
|
||||
|
||||
if let Some((_, var_span)) = old_closure_span {
|
||||
err.span_label(
|
||||
var_span,
|
||||
format!("previous borrow occurs due to use of `{}` in closure", desc_lvalue),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((_, var_span)) = new_closure_span {
|
||||
err.span_label(
|
||||
var_span,
|
||||
format!("borrow occurs due to use of `{}` in closure", desc_lvalue),
|
||||
);
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
|
|
|
@ -503,31 +503,10 @@ fn link_staticlib(sess: &Session,
|
|||
if !all_native_libs.is_empty() {
|
||||
if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
|
||||
print_native_static_libs(sess, &all_native_libs);
|
||||
} else {
|
||||
// Fallback for backwards compatibility only
|
||||
print_native_static_libs_legacy(sess, &all_native_libs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_native_static_libs_legacy(sess: &Session, all_native_libs: &[NativeLibrary]) {
|
||||
sess.note_without_error("link against the following native artifacts when linking against \
|
||||
this static library");
|
||||
sess.note_without_error("This list will not be printed by default. \
|
||||
Please add --print=native-static-libs if you need this information");
|
||||
|
||||
for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) {
|
||||
let name = match lib.kind {
|
||||
NativeLibraryKind::NativeStaticNobundle |
|
||||
NativeLibraryKind::NativeUnknown => "library",
|
||||
NativeLibraryKind::NativeFramework => "framework",
|
||||
// These are included, no need to print them
|
||||
NativeLibraryKind::NativeStatic => continue,
|
||||
};
|
||||
sess.note_without_error(&format!("{}: {}", name, lib.name));
|
||||
}
|
||||
}
|
||||
|
||||
fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary]) {
|
||||
let lib_args: Vec<_> = all_native_libs.iter()
|
||||
.filter(|l| relevant_lib(sess, l))
|
||||
|
|
|
@ -1690,11 +1690,11 @@ impl Path {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
pub fn is_absolute(&self) -> bool {
|
||||
if !cfg!(target_os = "redox") {
|
||||
self.has_root() && (cfg!(unix) || self.prefix().is_some())
|
||||
} else {
|
||||
if cfg!(target_os = "redox") {
|
||||
// FIXME: Allow Redox prefixes
|
||||
has_redox_scheme(self.as_u8_slice())
|
||||
self.has_root() || has_redox_scheme(self.as_u8_slice())
|
||||
} else {
|
||||
self.has_root() && (cfg!(unix) || self.prefix().is_some())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@
|
|||
// except according to those terms.
|
||||
|
||||
use cell::UnsafeCell;
|
||||
use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg};
|
||||
use intrinsics::{atomic_cxchg, atomic_load, atomic_xadd, atomic_xchg};
|
||||
use ptr;
|
||||
use time::Duration;
|
||||
|
||||
use sys::mutex::{mutex_unlock, Mutex};
|
||||
use sys::syscall::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
|
||||
use sys::syscall::{futex, TimeSpec, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
|
||||
|
||||
pub struct Condvar {
|
||||
lock: UnsafeCell<*mut i32>,
|
||||
|
@ -63,8 +63,7 @@ impl Condvar {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn wait(&self, mutex: &Mutex) {
|
||||
unsafe {
|
||||
unsafe fn wait_inner(&self, mutex: &Mutex, timeout_ptr: *const TimeSpec) -> bool {
|
||||
let lock = self.lock.get();
|
||||
let seq = self.seq.get();
|
||||
|
||||
|
@ -78,18 +77,36 @@ impl Condvar {
|
|||
|
||||
mutex_unlock(*lock);
|
||||
|
||||
let _ = futex(seq, FUTEX_WAIT, *seq, 0, ptr::null_mut());
|
||||
let seq_before = atomic_load(seq);
|
||||
|
||||
let _ = futex(seq, FUTEX_WAIT, seq_before, timeout_ptr as usize, ptr::null_mut());
|
||||
|
||||
let seq_after = atomic_load(seq);
|
||||
|
||||
while atomic_xchg(*lock, 2) != 0 {
|
||||
let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut());
|
||||
}
|
||||
|
||||
seq_before != seq_after
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn wait(&self, mutex: &Mutex) {
|
||||
unsafe {
|
||||
assert!(self.wait_inner(mutex, ptr::null()));
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
|
||||
::sys_common::util::dumb_print(format_args!("condvar wait_timeout\n"));
|
||||
unimplemented!();
|
||||
pub fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
unsafe {
|
||||
let timeout = TimeSpec {
|
||||
tv_sec: dur.as_secs() as i64,
|
||||
tv_nsec: dur.subsec_nanos() as i32
|
||||
};
|
||||
|
||||
self.wait_inner(mutex, &timeout as *const TimeSpec)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -437,8 +437,7 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
|
|||
}
|
||||
|
||||
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
::sys_common::util::dumb_print(format_args!("Link\n"));
|
||||
unimplemented!();
|
||||
Err(Error::from_raw_os_error(syscall::ENOSYS))
|
||||
}
|
||||
|
||||
pub fn stat(p: &Path) -> io::Result<FileAttr> {
|
||||
|
|
|
@ -416,7 +416,7 @@ mod tests {
|
|||
// first one is zero:
|
||||
assert_eq!(i.intern("dog"), Symbol(0));
|
||||
// re-use gets the same entry:
|
||||
assert_eq!(i.intern ("dog"), Symbol(0));
|
||||
assert_eq!(i.intern("dog"), Symbol(0));
|
||||
// different string gets a different #:
|
||||
assert_eq!(i.intern("cat"), Symbol(1));
|
||||
assert_eq!(i.intern("cat"), Symbol(1));
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2017 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Tests that two closures cannot simultaneously have mutable
|
||||
// access to the variable, whether that mutable access be used
|
||||
// for direct assignment or for taking mutable ref. Issue #6801.
|
||||
|
||||
// compile-flags: -Z emit-end-regions -Z borrowck-mir
|
||||
|
||||
#![feature(box_syntax)]
|
||||
|
||||
fn to_fn_mut<F: FnMut()>(f: F) -> F { f }
|
||||
|
||||
fn a() {
|
||||
let mut x = 3;
|
||||
let c1 = to_fn_mut(|| x = 4);
|
||||
let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
}
|
||||
|
||||
fn set(x: &mut isize) {
|
||||
*x = 4;
|
||||
}
|
||||
|
||||
fn b() {
|
||||
let mut x = 3;
|
||||
let c1 = to_fn_mut(|| set(&mut x));
|
||||
let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
}
|
||||
|
||||
fn c() {
|
||||
let mut x = 3;
|
||||
let c1 = to_fn_mut(|| x = 5);
|
||||
let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
}
|
||||
|
||||
fn d() {
|
||||
let mut x = 3;
|
||||
let c1 = to_fn_mut(|| x = 5);
|
||||
let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
|
||||
//~^ ERROR cannot borrow `x` as mutable more than once
|
||||
}
|
||||
|
||||
fn g() {
|
||||
struct Foo {
|
||||
f: Box<isize>
|
||||
}
|
||||
|
||||
let mut x: Box<_> = box Foo { f: box 3 };
|
||||
let c1 = to_fn_mut(|| set(&mut *x.f));
|
||||
let c2 = to_fn_mut(|| set(&mut *x.f));
|
||||
//~^ ERROR cannot borrow `x` as mutable more than once
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:24:24
|
||||
|
|
||||
23 | let c1 = to_fn_mut(|| x = 4);
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
24 | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
25 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:34:24
|
||||
|
|
||||
33 | let c1 = to_fn_mut(|| set(&mut x));
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
34 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
35 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:40:24
|
||||
|
|
||||
39 | let c1 = to_fn_mut(|| x = 5);
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
40 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
41 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:46:24
|
||||
|
|
||||
45 | let c1 = to_fn_mut(|| x = 5);
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
46 | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
47 | //~^ ERROR cannot borrow `x` as mutable more than once
|
||||
48 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:57:24
|
||||
|
|
||||
56 | let c1 = to_fn_mut(|| set(&mut *x.f));
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
57 | let c2 = to_fn_mut(|| set(&mut *x.f));
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
58 | //~^ ERROR cannot borrow `x` as mutable more than once
|
||||
59 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:24:24
|
||||
|
|
||||
23 | let c1 = to_fn_mut(|| x = 4);
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
24 | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
25 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:34:24
|
||||
|
|
||||
33 | let c1 = to_fn_mut(|| set(&mut x));
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
34 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
35 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:40:24
|
||||
|
|
||||
39 | let c1 = to_fn_mut(|| x = 5);
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
40 | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
41 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:46:24
|
||||
|
|
||||
45 | let c1 = to_fn_mut(|| x = 5);
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
46 | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
47 | //~^ ERROR cannot borrow `x` as mutable more than once
|
||||
48 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
|
||||
--> $DIR/borrowck-closures-two-mut.rs:57:24
|
||||
|
|
||||
56 | let c1 = to_fn_mut(|| set(&mut *x.f));
|
||||
| -- - previous borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
57 | let c2 = to_fn_mut(|| set(&mut *x.f));
|
||||
| ^^ - borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| second mutable borrow occurs here
|
||||
58 | //~^ ERROR cannot borrow `x` as mutable more than once
|
||||
59 | }
|
||||
| - first borrow ends here
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2017 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
for _ in HashMap::new().iter().cloned() {}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
|
||||
--> $DIR/issue-33941.rs:14:36
|
||||
|
|
||||
14 | for _ in HashMap::new().iter().cloned() {}
|
||||
| ^^^^^^ expected tuple, found reference
|
||||
|
|
||||
= note: expected type `(&_, &_)`
|
||||
found type `&_`
|
||||
|
||||
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
|
||||
--> $DIR/issue-33941.rs:14:5
|
||||
|
|
||||
14 | for _ in HashMap::new().iter().cloned() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
|
||||
|
|
||||
= note: expected type `(&_, &_)`
|
||||
found type `&_`
|
||||
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
@ -259,9 +259,9 @@ impl TestProps {
|
|||
props
|
||||
}
|
||||
|
||||
pub fn from_file(testfile: &Path, config: &Config) -> Self {
|
||||
pub fn from_file(testfile: &Path, cfg: Option<&str>, config: &Config) -> Self {
|
||||
let mut props = TestProps::new();
|
||||
props.load_from(testfile, None, config);
|
||||
props.load_from(testfile, cfg, config);
|
||||
props
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ impl TestProps {
|
|||
/// tied to a particular revision `foo` (indicated by writing
|
||||
/// `//[foo]`), then the property is ignored unless `cfg` is
|
||||
/// `Some("foo")`.
|
||||
pub fn load_from(&mut self,
|
||||
fn load_from(&mut self,
|
||||
testfile: &Path,
|
||||
cfg: Option<&str>,
|
||||
config: &Config) {
|
||||
|
|
|
@ -493,6 +493,7 @@ fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf {
|
|||
config.stage_id);
|
||||
config.build_base.canonicalize()
|
||||
.unwrap_or_else(|_| config.build_base.clone())
|
||||
.join(&testpaths.relative_dir)
|
||||
.join(stamp_name)
|
||||
}
|
||||
|
||||
|
@ -524,6 +525,10 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
|
|||
let lib = lib.unwrap();
|
||||
inputs.push(mtime(&lib.path()));
|
||||
}
|
||||
if let Some(ref rustdoc_path) = config.rustdoc_path {
|
||||
inputs.push(mtime(&rustdoc_path));
|
||||
inputs.push(mtime(&rust_src_dir.join("src/etc/htmldocck.py")));
|
||||
}
|
||||
inputs.iter().any(|input| *input > stamp)
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ pub fn run(config: Config, testpaths: &TestPaths) {
|
|||
print!("\n\n");
|
||||
}
|
||||
debug!("running {:?}", testpaths.file.display());
|
||||
let base_props = TestProps::from_file(&testpaths.file, &config);
|
||||
let base_props = TestProps::from_file(&testpaths.file, None, &config);
|
||||
|
||||
let base_cx = TestCx { config: &config,
|
||||
props: &base_props,
|
||||
|
@ -81,8 +81,9 @@ pub fn run(config: Config, testpaths: &TestPaths) {
|
|||
base_cx.run_revision()
|
||||
} else {
|
||||
for revision in &base_props.revisions {
|
||||
let mut revision_props = base_props.clone();
|
||||
revision_props.load_from(&testpaths.file, Some(revision), &config);
|
||||
let revision_props = TestProps::from_file(&testpaths.file,
|
||||
Some(revision),
|
||||
&config);
|
||||
let rev_cx = TestCx {
|
||||
config: &config,
|
||||
props: &revision_props,
|
||||
|
|
Loading…
Reference in New Issue