Auto merge of #78001 - Dylan-DPC:rollup-zq3kxth, r=Dylan-DPC

Rollup of 14 pull requests

Successful merges:

 - #75023 (ensure arguments are included in count mismatch span)
 - #75265 (Add `str::{Split,RSplit,SplitN,RSplitN,SplitTerminator,RSplitTerminator,SplitInclusive}::as_str` methods)
 - #75675 (mangling: mangle impl params w/ v0 scheme)
 - #76084 (Refactor io/buffered.rs into submodules)
 - #76119 (Stabilize move_ref_pattern)
 - #77493 (ICEs should always print the top of the query stack)
 - #77619 (Use futex-based thread-parker for Wasm32.)
 - #77646 (For backtrace, use StaticMutex instead of a raw sys Mutex.)
 - #77648 (Static mutex is static)
 - #77657 (Cleanup cloudabi mutexes and condvars)
 - #77672 (Simplify doc-cfg rendering based on the current context)
 - #77780 (rustc_parse: fix spans on cast and range exprs with attrs)
 - #77935 (BTreeMap: make PartialCmp/PartialEq explicit and tested)
 - #77980 (Fix intra doc link for needs_drop)

Failed merges:

r? `@ghost`
This commit is contained in:
bors 2020-10-16 00:18:13 +00:00
commit b6e2dc6cde
121 changed files with 2898 additions and 2295 deletions

View File

@ -1258,9 +1258,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
// If backtraces are enabled, also print the query stack
let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
if backtrace {
TyCtxt::try_print_query_stack(&handler);
}
let num_frames = if backtrace { None } else { Some(2) };
TyCtxt::try_print_query_stack(&handler, num_frames);
#[cfg(windows)]
unsafe {

View File

@ -1,3 +1,5 @@
#### Note: this error code is no longer emitted by the compiler.
This error indicates that the bindings in a match arm would require a value to
be moved into more than one location, thus violating unique ownership. Code
like the following is invalid as it requires the entire `Option<String>` to be
@ -6,11 +8,13 @@ inner `String` to be moved into a variable called `s`.
Erroneous code example:
```compile_fail,E0007
```compile_fail,E0382
#![feature(bindings_after_at)]
let x = Some("s".to_string());
match x {
op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
op_string @ Some(s) => {}, // error: use of moved value
None => {},
}
```

View File

@ -270,6 +270,9 @@ declare_features! (
(accepted, track_caller, "1.46.0", Some(47809), None),
/// Allows `#[doc(alias = "...")]`.
(accepted, doc_alias, "1.48.0", Some(50146), None),
/// Allows patterns with concurrent by-move and by-ref bindings.
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
(accepted, move_ref_pattern, "1.48.0", Some(68354), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features

View File

@ -526,10 +526,6 @@ declare_features! (
/// For example, you can write `x @ Some(y)`.
(active, bindings_after_at, "1.41.0", Some(65490), None),
/// Allows patterns with concurrent by-move and by-ref bindings.
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
(active, move_ref_pattern, "1.42.0", Some(68354), None),
/// Allows `impl const Trait for T` syntax.
(active, const_trait_impl, "1.42.0", Some(67792), None),

View File

@ -2742,4 +2742,32 @@ impl<'hir> Node<'hir> {
_ => None,
}
}
pub fn hir_id(&self) -> Option<HirId> {
match self {
Node::Item(Item { hir_id, .. })
| Node::ForeignItem(ForeignItem { hir_id, .. })
| Node::TraitItem(TraitItem { hir_id, .. })
| Node::ImplItem(ImplItem { hir_id, .. })
| Node::Field(StructField { hir_id, .. })
| Node::AnonConst(AnonConst { hir_id, .. })
| Node::Expr(Expr { hir_id, .. })
| Node::Stmt(Stmt { hir_id, .. })
| Node::Ty(Ty { hir_id, .. })
| Node::Binding(Pat { hir_id, .. })
| Node::Pat(Pat { hir_id, .. })
| Node::Arm(Arm { hir_id, .. })
| Node::Block(Block { hir_id, .. })
| Node::Local(Local { hir_id, .. })
| Node::MacroDef(MacroDef { hir_id, .. })
| Node::Lifetime(Lifetime { hir_id, .. })
| Node::Param(Param { hir_id, .. })
| Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
Node::Variant(Variant { id, .. }) => Some(*id),
Node::Ctor(variant) => variant.ctor_hir_id(),
Node::Crate(_) | Node::Visibility(_) => None,
}
}
}

View File

@ -291,7 +291,17 @@ impl<'tcx> Instance<'tcx> {
}
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
Instance::new(def_id, tcx.empty_substs_for_def_id(def_id))
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
ty::GenericParamDefKind::Type { .. } => {
bug!("Instance::mono: {:?} has type parameters", def_id)
}
ty::GenericParamDefKind::Const { .. } => {
bug!("Instance::mono: {:?} has const parameters", def_id)
}
});
Instance::new(def_id, substs)
}
#[inline]

View File

@ -124,20 +124,23 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
pub fn try_print_query_stack(handler: &Handler) {
pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
eprintln!("query stack during panic:");
// Be careful reyling on global state here: this code is called from
// a panic hook, which means that the global `Handler` may be in a weird
// state if it was responsible for triggering the panic.
let mut i = 0;
ty::tls::with_context_opt(|icx| {
if let Some(icx) = icx {
let query_map = icx.tcx.queries.try_collect_active_jobs();
let mut current_query = icx.query;
let mut i = 0;
while let Some(query) = current_query {
if Some(i) == num_frames {
break;
}
let query_info =
if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) {
info
@ -163,7 +166,11 @@ impl<'tcx> TyCtxt<'tcx> {
}
});
eprintln!("end of query stack");
if num_frames == None || num_frames >= Some(i) {
eprintln!("end of query stack");
} else {
eprintln!("we're just showing a limited slice of the query stack");
}
}
}

View File

@ -6,9 +6,9 @@ use crate::mir::interpret::{sign_extend, truncate};
use crate::ty::fold::TypeFolder;
use crate::ty::layout::IntegerExt;
use crate::ty::query::TyCtxtAt;
use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef};
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
use crate::ty::TyKind::*;
use crate::ty::{self, DefIdTree, GenericParamDefKind, List, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
use rustc_apfloat::Float as _;
use rustc_ast as ast;
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@ -509,20 +509,6 @@ impl<'tcx> TyCtxt<'tcx> {
Some(ty::Binder::bind(env_ty))
}
/// Given the `DefId` of some item that has no type or const parameters, make
/// a suitable "empty substs" for it.
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> SubstsRef<'tcx> {
InternalSubsts::for_item(self, item_def_id, |param, _| match param.kind {
GenericParamDefKind::Lifetime => self.lifetimes.re_erased.into(),
GenericParamDefKind::Type { .. } => {
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
}
GenericParamDefKind::Const { .. } => {
bug!("empty_substs_for_def_id: {:?} has const parameters", item_def_id)
}
})
}
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
pub fn is_static(self, def_id: DefId) -> bool {
self.static_mutability(def_id).is_some()

View File

@ -71,13 +71,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
};
self.check_irrefutable(&loc.pat, msg, sp);
self.check_patterns(false, &loc.pat);
self.check_patterns(&loc.pat);
}
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
intravisit::walk_param(self, param);
self.check_irrefutable(&param.pat, "function argument", None);
self.check_patterns(false, &param.pat);
self.check_patterns(&param.pat);
}
}
@ -119,10 +119,7 @@ impl PatCtxt<'_, '_> {
}
impl<'tcx> MatchVisitor<'_, 'tcx> {
fn check_patterns(&mut self, has_guard: bool, pat: &Pat<'_>) {
if !self.tcx.features().move_ref_pattern {
check_legality_of_move_bindings(self, has_guard, pat);
}
fn check_patterns(&mut self, pat: &Pat<'_>) {
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
if !self.tcx.features().bindings_after_at {
check_legality_of_bindings_in_at_patterns(self, pat);
@ -165,7 +162,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
) {
for arm in arms {
// Check the arm for some things unrelated to exhaustiveness.
self.check_patterns(arm.guard.is_some(), &arm.pat);
self.check_patterns(&arm.pat);
}
let mut cx = self.new_cx(scrut.hir_id);
@ -601,65 +598,6 @@ fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> b
!cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env)
}
/// Check the legality of legality of by-move bindings.
fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pat: &Pat<'_>) {
let sess = cx.tcx.sess;
let typeck_results = cx.typeck_results;
// Find all by-ref spans.
let mut by_ref_spans = Vec::new();
pat.each_binding(|_, hir_id, span, _| {
if let Some(ty::BindByReference(_)) =
typeck_results.extract_binding_mode(sess, hir_id, span)
{
by_ref_spans.push(span);
}
});
// Find bad by-move spans:
let by_move_spans = &mut Vec::new();
let mut check_move = |p: &Pat<'_>, sub: Option<&Pat<'_>>| {
// Check legality of moving out of the enum.
//
// `x @ Foo(..)` is legal, but `x @ Foo(y)` isn't.
if sub.map_or(false, |p| p.contains_bindings()) {
struct_span_err!(sess, p.span, E0007, "cannot bind by-move with sub-bindings")
.span_label(p.span, "binds an already bound by-move value by moving it")
.emit();
} else if !has_guard && !by_ref_spans.is_empty() {
by_move_spans.push(p.span);
}
};
pat.walk_always(|p| {
if let hir::PatKind::Binding(.., sub) = &p.kind {
if let Some(ty::BindByValue(_)) =
typeck_results.extract_binding_mode(sess, p.hir_id, p.span)
{
if is_binding_by_move(cx, p.hir_id, p.span) {
check_move(p, sub.as_deref());
}
}
}
});
// Found some bad by-move spans, error!
if !by_move_spans.is_empty() {
let mut err = feature_err(
&sess.parse_sess,
sym::move_ref_pattern,
by_move_spans.clone(),
"binding by-move and by-ref in the same pattern is unstable",
);
for span in by_ref_spans.iter() {
err.span_label(*span, "by-ref pattern here");
}
for span in by_move_spans.iter() {
err.span_label(*span, "by-move pattern here");
}
err.emit();
}
}
/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
///
/// For example, this would reject:

View File

@ -246,11 +246,7 @@ impl<'a> Parser<'a> {
this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
})?;
// Make sure that the span of the parent node is larger than the span of lhs and rhs,
// including the attributes.
let lhs_span =
lhs.attrs.iter().find(|a| a.style == AttrStyle::Outer).map_or(lhs_span, |a| a.span);
let span = lhs_span.to(rhs.span);
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
lhs = match op {
AssocOp::Add
| AssocOp::Subtract
@ -411,7 +407,7 @@ impl<'a> Parser<'a> {
None
};
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
let span = lhs.span.to(rhs_span);
let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span);
let limits =
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new()))
@ -571,7 +567,11 @@ impl<'a> Parser<'a> {
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
) -> PResult<'a, P<Expr>> {
let mk_expr = |this: &mut Self, rhs: P<Ty>| {
this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), AttrVec::new())
this.mk_expr(
this.mk_expr_sp(&lhs, lhs_span, rhs.span),
expr_kind(lhs, rhs),
AttrVec::new(),
)
};
// Save the state of the parser before parsing type normally, in case there is a
@ -2324,4 +2324,14 @@ impl<'a> Parser<'a> {
pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
self.mk_expr(span, ExprKind::Err, AttrVec::new())
}
/// Create expression span ensuring the span of the parent node
/// is larger than the span of lhs and rhs, including the attributes.
fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
lhs.attrs
.iter()
.find(|a| a.style == AttrStyle::Outer)
.map_or(lhs_span, |a| a.span)
.to(rhs_span)
}
}

View File

@ -1744,7 +1744,7 @@ impl<'a> Parser<'a> {
}
};
let span = lo.to(self.token.span);
let span = lo.until(self.token.span);
Ok(Param {
attrs: attrs.into(),

View File

@ -115,7 +115,6 @@ fn get_symbol_hash<'tcx>(
}
// also include any type parameters (for generic items)
assert!(!substs.has_erasable_regions());
substs.hash_stable(&mut hcx, &mut hasher);
if let Some(instantiating_crate) = instantiating_crate {

View File

@ -6,7 +6,7 @@
use rustc_hir as hir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{Instance, TyCtxt};
use rustc_middle::ty::{subst::InternalSubsts, Instance, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
@ -36,8 +36,11 @@ impl SymbolNamesTest<'tcx> {
let def_id = tcx.hir().local_def_id(hir_id);
for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
if tcx.sess.check_name(attr, SYMBOL_NAME) {
// for now, can only use on monomorphic names
let instance = Instance::mono(tcx, def_id.to_def_id());
let def_id = def_id.to_def_id();
let instance = Instance::new(
def_id,
tcx.erase_regions(&InternalSubsts::identity_for_item(tcx, def_id)),
);
let mangled = tcx.symbol_name(instance);
tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled));
if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) {

View File

@ -259,7 +259,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
}
fn print_impl_path(
self,
mut self,
impl_def_id: DefId,
substs: &'tcx [GenericArg<'tcx>],
mut self_ty: Ty<'tcx>,
@ -284,12 +284,37 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
}
}
self.path_append_impl(
|cx| cx.print_def_path(parent_def_id, &[]),
&key.disambiguated_data,
self_ty,
impl_trait_ref,
)
self.push(match impl_trait_ref {
Some(_) => "X",
None => "M",
});
// Encode impl generic params if the substitutions contain parameters (implying
// polymorphization is enabled) and this isn't an inherent impl.
if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
self = self.path_generic_args(
|this| {
this.path_append_ns(
|cx| cx.print_def_path(parent_def_id, &[]),
'I',
key.disambiguated_data.disambiguator as u64,
"",
)
},
substs,
)?;
} else {
self.push_disambiguator(key.disambiguated_data.disambiguator as u64);
self = self.print_def_path(parent_def_id, &[])?;
}
self = self_ty.print(self)?;
if let Some(trait_ref) = impl_trait_ref {
self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
}
Ok(self)
}
fn print_region(mut self, region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
@ -538,6 +563,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
self.push_ident(&name);
Ok(self)
}
fn path_qualified(
mut self,
self_ty: Ty<'tcx>,
@ -552,24 +578,16 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
}
fn path_append_impl(
mut self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
disambiguated_data: &DisambiguatedDefPathData,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
self,
_: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
_: &DisambiguatedDefPathData,
_: Ty<'tcx>,
_: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
self.push(match trait_ref {
Some(_) => "X",
None => "M",
});
self.push_disambiguator(disambiguated_data.disambiguator as u64);
self = print_prefix(self)?;
self = self_ty.print(self)?;
if let Some(trait_ref) = trait_ref {
self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?;
}
Ok(self)
// Inlined into `print_impl_path`
unreachable!()
}
fn path_append(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
@ -603,6 +621,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
name.as_ref().map_or("", |s| &s[..]),
)
}
fn path_generic_args(
mut self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,

View File

@ -285,10 +285,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
let (fn_sig, def_span) = match *callee_ty.kind() {
ty::FnDef(def_id, _) => {
(callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id))
}
let (fn_sig, def_id) = match *callee_ty.kind() {
ty::FnDef(def_id, _) => (callee_ty.fn_sig(self.tcx), Some(def_id)),
ty::FnPtr(sig) => (sig, None),
ref t => {
let mut unit_variant = None;
@ -427,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs,
fn_sig.c_variadic,
TupleArgumentsFlag::DontTupleArguments,
def_span,
def_id,
);
fn_sig.output()

View File

@ -19,7 +19,7 @@ use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty};
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{self, Span};
use rustc_span::{self, MultiSpan, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode};
use std::mem::replace;
@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args_no_rcvr,
method.sig.c_variadic,
tuple_arguments,
self.tcx.hir().span_if_local(method.def_id),
Some(method.def_id),
);
method.sig.output()
}
@ -99,7 +99,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args: &'tcx [hir::Expr<'tcx>],
c_variadic: bool,
tuple_arguments: TupleArgumentsFlag,
def_span: Option<Span>,
def_id: Option<DefId>,
) {
let tcx = self.tcx;
// Grab the argument types, supplying fresh type variables
@ -172,9 +172,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().guess_head_span(sp)) {
err.span_label(def_s, "defined here");
if let Some(def_id) = def_id {
if let Some(node) = tcx.hir().get_if_local(def_id) {
let mut spans: MultiSpan = node
.ident()
.map(|ident| ident.span)
.unwrap_or_else(|| tcx.hir().span(node.hir_id().unwrap()))
.into();
if let Some(id) = node.body_id() {
let body = tcx.hir().body(id);
for param in body.params {
spans.push_span_label(param.span, String::new());
}
}
let def_kind = tcx.def_kind(def_id);
err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id)));
}
}
if sugg_unit {
let sugg_span = tcx.sess.source_map().end_point(expr.span);
// remove closing `)` from the span

View File

@ -257,8 +257,13 @@ impl<K, V> Root<K, V> {
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
/// `NodeRef` could be pointing to either type of node.
pub struct NodeRef<BorrowType, K, V, Type> {
/// The number of levels below the node.
/// The number of levels below the node, a property of the node that cannot be
/// entirely described by `Type` and that the node does not store itself either.
/// Unconstrained if `Type` is `LeafOrInternal`, must be zero if `Type` is `Leaf`,
/// and must be non-zero if `Type` is `Internal`.
height: usize,
/// The pointer to the leaf or internal node. The definition of `InternalNode`
/// ensures that the pointer is valid either way.
node: NonNull<LeafNode<K, V>>,
_marker: PhantomData<(BorrowType, Type)>,
}
@ -315,8 +320,8 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
unsafe { usize::from((*self.as_leaf_ptr()).len) }
}
/// Returns the height of this node in the whole tree. Zero height denotes the
/// leaf level.
/// Returns the height of this node with respect to the leaf level. Zero height means the
/// node is a leaf itself.
pub fn height(&self) -> usize {
self.height
}
@ -584,9 +589,11 @@ impl<'a, K, V, Type> NodeRef<marker::ValMut<'a>, K, V, Type> {
// to avoid aliasing with outstanding references to other elements,
// in particular, those returned to the caller in earlier iterations.
let leaf = self.node.as_ptr();
let keys = unsafe { &raw const (*leaf).keys };
let vals = unsafe { &raw mut (*leaf).vals };
// We must coerce to unsized array pointers because of Rust issue #74679.
let keys: *const [_] = unsafe { &raw const (*leaf).keys };
let vals: *mut [_] = unsafe { &raw mut (*leaf).vals };
let keys: *const [_] = keys;
let vals: *mut [_] = vals;
// SAFETY: The keys and values of a node must always be initialized up to length.
let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() };
let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() };
@ -817,11 +824,25 @@ impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, mar
}
}
impl<BorrowType, K, V, NodeType> NodeRef<BorrowType, K, V, NodeType> {
/// Could be a public implementation of PartialEq, but only used in this module.
fn eq(&self, other: &Self) -> bool {
let Self { node, height, _marker: _ } = self;
if *node == other.node {
debug_assert_eq!(*height, other.height);
true
} else {
false
}
}
}
impl<BorrowType, K, V, NodeType, HandleType> PartialEq
for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
{
fn eq(&self, other: &Self) -> bool {
self.node.node == other.node.node && self.idx == other.idx
let Self { node, idx, _marker: _ } = self;
node.eq(&other.node) && *idx == other.idx
}
}
@ -829,7 +850,8 @@ impl<BorrowType, K, V, NodeType, HandleType> PartialOrd
for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.node.node == other.node.node { Some(self.idx.cmp(&other.idx)) } else { None }
let Self { node, idx, _marker: _ } = self;
if node.eq(&other.node) { Some(idx.cmp(&other.idx)) } else { None }
}
}

View File

@ -1,4 +1,5 @@
use super::*;
use core::cmp::Ordering::*;
#[test]
fn test_splitpoint() {
@ -24,6 +25,38 @@ fn test_splitpoint() {
}
}
#[test]
fn test_partial_cmp_eq() {
let mut root1: Root<i32, ()> = Root::new_leaf();
let mut leaf1 = unsafe { root1.leaf_node_as_mut() };
leaf1.push(1, ());
root1.push_internal_level();
let root2: Root<i32, ()> = Root::new_leaf();
let leaf_edge_1a = root1.node_as_ref().first_leaf_edge().forget_node_type();
let leaf_edge_1b = root1.node_as_ref().last_leaf_edge().forget_node_type();
let top_edge_1 = root1.node_as_ref().first_edge();
let top_edge_2 = root2.node_as_ref().first_edge();
assert!(leaf_edge_1a == leaf_edge_1a);
assert!(leaf_edge_1a != leaf_edge_1b);
assert!(leaf_edge_1a != top_edge_1);
assert!(leaf_edge_1a != top_edge_2);
assert!(top_edge_1 == top_edge_1);
assert!(top_edge_1 != top_edge_2);
assert_eq!(leaf_edge_1a.partial_cmp(&leaf_edge_1a), Some(Equal));
assert_eq!(leaf_edge_1a.partial_cmp(&leaf_edge_1b), Some(Less));
assert_eq!(leaf_edge_1a.partial_cmp(&top_edge_1), None);
assert_eq!(leaf_edge_1a.partial_cmp(&top_edge_2), None);
assert_eq!(top_edge_1.partial_cmp(&top_edge_1), Some(Equal));
assert_eq!(top_edge_1.partial_cmp(&top_edge_2), None);
root1.pop_internal_level();
unsafe { root1.into_ref().deallocate_and_ascend() };
unsafe { root2.into_ref().deallocate_and_ascend() };
}
#[test]
#[cfg(target_arch = "x86_64")]
fn test_sizes() {

View File

@ -1082,7 +1082,7 @@ extern "rust-intrinsic" {
/// If the actual type neither requires drop glue nor implements
/// `Copy`, then the return value of this function is unspecified.
///
/// The stabilized version of this intrinsic is [`needs_drop`].
/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
pub fn needs_drop<T>() -> bool;

View File

@ -126,6 +126,8 @@
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
#![feature(str_split_as_str)]
#![feature(str_split_inclusive_as_str)]
#![feature(transparent_unions)]
#![feature(unboxed_closures)]
#![feature(unsized_locals)]

View File

@ -690,6 +690,17 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
},
}
}
#[inline]
fn as_str(&self) -> &'a str {
// `Self::get_end` doesn't change `self.start`
if self.finished {
return "";
}
// SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
}
}
generate_pattern_iterators! {
@ -710,6 +721,48 @@ generate_pattern_iterators! {
delegate double ended;
}
impl<'a, P: Pattern<'a>> Split<'a, P> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_as_str)]
/// let mut split = "Mary had a little lamb".split(' ');
/// assert_eq!(split.as_str(), "Mary had a little lamb");
/// split.next();
/// assert_eq!(split.as_str(), "had a little lamb");
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.0.as_str()
}
}
impl<'a, P: Pattern<'a>> RSplit<'a, P> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_as_str)]
/// let mut split = "Mary had a little lamb".rsplit(' ');
/// assert_eq!(split.as_str(), "Mary had a little lamb");
/// split.next();
/// assert_eq!(split.as_str(), "Mary had a little");
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.0.as_str()
}
}
generate_pattern_iterators! {
forward:
/// Created with the method [`split_terminator`].
@ -728,6 +781,48 @@ generate_pattern_iterators! {
delegate double ended;
}
impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_as_str)]
/// let mut split = "A..B..".split_terminator('.');
/// assert_eq!(split.as_str(), "A..B..");
/// split.next();
/// assert_eq!(split.as_str(), ".B..");
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.0.as_str()
}
}
impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_as_str)]
/// let mut split = "A..B..".rsplit_terminator('.');
/// assert_eq!(split.as_str(), "A..B..");
/// split.next();
/// assert_eq!(split.as_str(), "A..B");
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.0.as_str()
}
}
derive_pattern_clone! {
clone SplitNInternal
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
@ -784,6 +879,11 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
}
}
}
#[inline]
fn as_str(&self) -> &'a str {
self.iter.as_str()
}
}
generate_pattern_iterators! {
@ -804,6 +904,48 @@ generate_pattern_iterators! {
delegate single ended;
}
impl<'a, P: Pattern<'a>> SplitN<'a, P> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_as_str)]
/// let mut split = "Mary had a little lamb".splitn(3, ' ');
/// assert_eq!(split.as_str(), "Mary had a little lamb");
/// split.next();
/// assert_eq!(split.as_str(), "had a little lamb");
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.0.as_str()
}
}
impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_as_str)]
/// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
/// assert_eq!(split.as_str(), "Mary had a little lamb");
/// split.next();
/// assert_eq!(split.as_str(), "Mary had a little");
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.0.as_str()
}
}
derive_pattern_clone! {
clone MatchIndicesInternal
with |s| MatchIndicesInternal(s.0.clone())
@ -1134,6 +1276,28 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
#[unstable(feature = "split_inclusive", issue = "72360")]
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
/// Returns remainder of the splitted string
///
/// # Examples
///
/// ```
/// #![feature(str_split_inclusive_as_str)]
/// #![feature(split_inclusive)]
/// let mut split = "Mary had a little lamb".split_inclusive(' ');
/// assert_eq!(split.as_str(), "Mary had a little lamb");
/// split.next();
/// assert_eq!(split.as_str(), "had a little lamb");
/// split.by_ref().for_each(drop);
/// assert_eq!(split.as_str(), "");
/// ```
#[inline]
#[unstable(feature = "str_split_inclusive_as_str", issue = "77998")]
pub fn as_str(&self) -> &'a str {
self.0.as_str()
}
}
/// An iterator of [`u16`] over the string encoded as UTF-16.
///
/// This struct is created by the [`encode_utf16`] method on [`str`].

View File

@ -303,7 +303,8 @@ impl Backtrace {
// Capture a backtrace which start just before the function addressed by
// `ip`
fn create(ip: usize) -> Backtrace {
let _lock = lock();
// SAFETY: We don't attempt to lock this reentrantly.
let _lock = unsafe { lock() };
let mut frames = Vec::new();
let mut actual_start = None;
unsafe {
@ -408,7 +409,8 @@ impl Capture {
// Use the global backtrace lock to synchronize this as it's a
// requirement of the `backtrace` crate, and then actually resolve
// everything.
let _lock = lock();
// SAFETY: We don't attempt to lock this reentrantly.
let _lock = unsafe { lock() };
for frame in self.frames.iter_mut() {
let symbols = &mut frame.symbols;
let frame = match &frame.frame {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,423 @@
use crate::cmp;
use crate::fmt;
use crate::io::{self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, DEFAULT_BUF_SIZE};
/// The `BufReader<R>` struct adds buffering to any reader.
///
/// It can be excessively inefficient to work directly with a [`Read`] instance.
/// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`]
/// results in a system call. A `BufReader<R>` performs large, infrequent reads on
/// the underlying [`Read`] and maintains an in-memory buffer of the results.
///
/// `BufReader<R>` can improve the speed of programs that make *small* and
/// *repeated* read calls to the same file or network socket. It does not
/// help when reading very large amounts at once, or reading just one or a few
/// times. It also provides no advantage when reading from a source that is
/// already in memory, like a [`Vec`]`<u8>`.
///
/// When the `BufReader<R>` is dropped, the contents of its buffer will be
/// discarded. Creating multiple instances of a `BufReader<R>` on the same
/// stream can cause data loss. Reading from the underlying reader after
/// unwrapping the `BufReader<R>` with [`BufReader::into_inner`] can also cause
/// data loss.
///
/// [`TcpStream::read`]: Read::read
/// [`TcpStream`]: crate::net::TcpStream
///
/// # Examples
///
/// ```no_run
/// use std::io::prelude::*;
/// use std::io::BufReader;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let mut reader = BufReader::new(f);
///
/// let mut line = String::new();
/// let len = reader.read_line(&mut line)?;
/// println!("First line is {} bytes long", len);
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufReader<R> {
inner: R,
buf: Box<[u8]>,
pos: usize,
cap: usize,
}
impl<R: Read> BufReader<R> {
/// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KB,
/// but may change in the future.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let reader = BufReader::new(f);
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: R) -> BufReader<R> {
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
}
/// Creates a new `BufReader<R>` with the specified buffer capacity.
///
/// # Examples
///
/// Creating a buffer with ten bytes of capacity:
///
/// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let reader = BufReader::with_capacity(10, f);
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
unsafe {
let mut buffer = Vec::with_capacity(capacity);
buffer.set_len(capacity);
inner.initializer().initialize(&mut buffer);
BufReader { inner, buf: buffer.into_boxed_slice(), pos: 0, cap: 0 }
}
}
}
impl<R> BufReader<R> {
/// Gets a reference to the underlying reader.
///
/// It is inadvisable to directly read from the underlying reader.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let reader = BufReader::new(f1);
///
/// let f2 = reader.get_ref();
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &R {
&self.inner
}
/// Gets a mutable reference to the underlying reader.
///
/// It is inadvisable to directly read from the underlying reader.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let mut reader = BufReader::new(f1);
///
/// let f2 = reader.get_mut();
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
/// Returns a reference to the internally buffered data.
///
/// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty.
///
/// [`fill_buf`]: BufRead::fill_buf
///
/// # Examples
///
/// ```no_run
/// use std::io::{BufReader, BufRead};
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let mut reader = BufReader::new(f);
/// assert!(reader.buffer().is_empty());
///
/// if reader.fill_buf()?.len() > 0 {
/// assert!(!reader.buffer().is_empty());
/// }
/// Ok(())
/// }
/// ```
#[stable(feature = "bufreader_buffer", since = "1.37.0")]
pub fn buffer(&self) -> &[u8] {
&self.buf[self.pos..self.cap]
}
/// Returns the number of bytes the internal buffer can hold at once.
///
/// # Examples
///
/// ```no_run
/// use std::io::{BufReader, BufRead};
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f = File::open("log.txt")?;
/// let mut reader = BufReader::new(f);
///
/// let capacity = reader.capacity();
/// let buffer = reader.fill_buf()?;
/// assert!(buffer.len() <= capacity);
/// Ok(())
/// }
/// ```
#[stable(feature = "buffered_io_capacity", since = "1.46.0")]
pub fn capacity(&self) -> usize {
self.buf.len()
}
/// Unwraps this `BufReader<R>`, returning the underlying reader.
///
/// Note that any leftover data in the internal buffer is lost. Therefore,
/// a following read from the underlying reader may lead to data loss.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufReader;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let reader = BufReader::new(f1);
///
/// let f2 = reader.into_inner();
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> R {
self.inner
}
/// Invalidates all data in the internal buffer.
#[inline]
fn discard_buffer(&mut self) {
self.pos = 0;
self.cap = 0;
}
}
impl<R: Seek> BufReader<R> {
/// Seeks relative to the current position. If the new position lies within the buffer,
/// the buffer will not be flushed, allowing for more efficient seeks.
/// This method does not return the location of the underlying reader, so the caller
/// must track this information themselves if it is required.
#[unstable(feature = "bufreader_seek_relative", issue = "31100")]
pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
let pos = self.pos as u64;
if offset < 0 {
if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
self.pos = new_pos as usize;
return Ok(());
}
} else {
if let Some(new_pos) = pos.checked_add(offset as u64) {
if new_pos <= self.cap as u64 {
self.pos = new_pos as usize;
return Ok(());
}
}
}
self.seek(SeekFrom::Current(offset)).map(drop)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> Read for BufReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
// If we don't have any buffered data and we're doing a massive read
// (larger than our internal buffer), bypass our internal buffer
// entirely.
if self.pos == self.cap && buf.len() >= self.buf.len() {
self.discard_buffer();
return self.inner.read(buf);
}
let nread = {
let mut rem = self.fill_buf()?;
rem.read(buf)?
};
self.consume(nread);
Ok(nread)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
if self.pos == self.cap && total_len >= self.buf.len() {
self.discard_buffer();
return self.inner.read_vectored(bufs);
}
let nread = {
let mut rem = self.fill_buf()?;
rem.read_vectored(bufs)?
};
self.consume(nread);
Ok(nread)
}
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
// we can't skip unconditionally because of the large buffer case in read.
unsafe fn initializer(&self) -> Initializer {
self.inner.initializer()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read> BufRead for BufReader<R> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
// If we've reached the end of our internal buffer then we need to fetch
// some more data from the underlying reader.
// Branch using `>=` instead of the more correct `==`
// to tell the compiler that the pos..cap slice is always valid.
if self.pos >= self.cap {
debug_assert!(self.pos == self.cap);
self.cap = self.inner.read(&mut self.buf)?;
self.pos = 0;
}
Ok(&self.buf[self.pos..self.cap])
}
fn consume(&mut self, amt: usize) {
self.pos = cmp::min(self.pos + amt, self.cap);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<R> fmt::Debug for BufReader<R>
where
R: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("BufReader")
.field("reader", &self.inner)
.field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
.finish()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Seek> Seek for BufReader<R> {
/// Seek to an offset, in bytes, in the underlying reader.
///
/// The position used for seeking with [`SeekFrom::Current`]`(_)` is the
/// position the underlying reader would be at if the `BufReader<R>` had no
/// internal buffer.
///
/// Seeking always discards the internal buffer, even if the seek position
/// would otherwise fall within it. This guarantees that calling
/// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader
/// at the same position.
///
/// To seek without discarding the internal buffer, use [`BufReader::seek_relative`].
///
/// See [`std::io::Seek`] for more details.
///
/// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)`
/// where `n` minus the internal buffer length overflows an `i64`, two
/// seeks will be performed instead of one. If the second seek returns
/// [`Err`], the underlying reader will be left at the same position it would
/// have if you called `seek` with [`SeekFrom::Current`]`(0)`.
///
/// [`std::io::Seek`]: Seek
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let result: u64;
if let SeekFrom::Current(n) = pos {
let remainder = (self.cap - self.pos) as i64;
// it should be safe to assume that remainder fits within an i64 as the alternative
// means we managed to allocate 8 exbibytes and that's absurd.
// But it's not out of the realm of possibility for some weird underlying reader to
// support seeking by i64::MIN so we need to handle underflow when subtracting
// remainder.
if let Some(offset) = n.checked_sub(remainder) {
result = self.inner.seek(SeekFrom::Current(offset))?;
} else {
// seek backwards by our remainder, and then by the offset
self.inner.seek(SeekFrom::Current(-remainder))?;
self.discard_buffer();
result = self.inner.seek(SeekFrom::Current(n))?;
}
} else {
// Seeking with Start/End doesn't care about our buffer length.
result = self.inner.seek(pos)?;
}
self.discard_buffer();
Ok(result)
}
/// Returns the current seek position from the start of the stream.
///
/// The value returned is equivalent to `self.seek(SeekFrom::Current(0))`
/// but does not flush the internal buffer. Due to this optimization the
/// function does not guarantee that calling `.into_inner()` immediately
/// afterwards will yield the underlying reader at the same position. Use
/// [`BufReader::seek`] instead if you require that guarantee.
///
/// # Panics
///
/// This function will panic if the position of the inner reader is smaller
/// than the amount of buffered data. That can happen if the inner reader
/// has an incorrect implementation of [`Seek::stream_position`], or if the
/// position has gone out of sync due to calling [`Seek::seek`] directly on
/// the underlying reader.
///
/// # Example
///
/// ```no_run
/// #![feature(seek_convenience)]
/// use std::{
/// io::{self, BufRead, BufReader, Seek},
/// fs::File,
/// };
///
/// fn main() -> io::Result<()> {
/// let mut f = BufReader::new(File::open("foo.txt")?);
///
/// let before = f.stream_position()?;
/// f.read_line(&mut String::new())?;
/// let after = f.stream_position()?;
///
/// println!("The first line was {} bytes long", after - before);
/// Ok(())
/// }
/// ```
fn stream_position(&mut self) -> io::Result<u64> {
let remainder = (self.cap - self.pos) as u64;
self.inner.stream_position().map(|pos| {
pos.checked_sub(remainder).expect(
"overflow when subtracting remaining buffer size from inner stream position",
)
})
}
}

View File

@ -0,0 +1,387 @@
use crate::fmt;
use crate::io::{
self, Error, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
};
/// Wraps a writer and buffers its output.
///
/// It can be excessively inefficient to work directly with something that
/// implements [`Write`]. For example, every call to
/// [`write`][`TcpStream::write`] on [`TcpStream`] results in a system call. A
/// `BufWriter<W>` keeps an in-memory buffer of data and writes it to an underlying
/// writer in large, infrequent batches.
///
/// `BufWriter<W>` can improve the speed of programs that make *small* and
/// *repeated* write calls to the same file or network socket. It does not
/// help when writing very large amounts at once, or writing just one or a few
/// times. It also provides no advantage when writing to a destination that is
/// in memory, like a [`Vec`]<u8>`.
///
/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
/// dropping will attempt to flush the contents of the buffer, any errors
/// that happen in the process of dropping will be ignored. Calling [`flush`]
/// ensures that the buffer is empty and thus dropping will not even attempt
/// file operations.
///
/// # Examples
///
/// Let's write the numbers one through ten to a [`TcpStream`]:
///
/// ```no_run
/// use std::io::prelude::*;
/// use std::net::TcpStream;
///
/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
///
/// for i in 0..10 {
/// stream.write(&[i+1]).unwrap();
/// }
/// ```
///
/// Because we're not buffering, we write each one in turn, incurring the
/// overhead of a system call per byte written. We can fix this with a
/// `BufWriter<W>`:
///
/// ```no_run
/// use std::io::prelude::*;
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// for i in 0..10 {
/// stream.write(&[i+1]).unwrap();
/// }
/// stream.flush().unwrap();
/// ```
///
/// By wrapping the stream with a `BufWriter<W>`, these ten writes are all grouped
/// together by the buffer and will all be written out in one system call when
/// the `stream` is flushed.
///
/// [`TcpStream::write`]: Write::write
/// [`TcpStream`]: crate::net::TcpStream
/// [`flush`]: Write::flush
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufWriter<W: Write> {
inner: Option<W>,
buf: Vec<u8>,
// #30888: If the inner writer panics in a call to write, we don't want to
// write the buffered data a second time in BufWriter's destructor. This
// flag tells the Drop impl if it should skip the flush.
panicked: bool,
}
impl<W: Write> BufWriter<W> {
/// Creates a new `BufWriter<W>` with a default buffer capacity. The default is currently 8 KB,
/// but may change in the future.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> BufWriter<W> {
BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner)
}
/// Creates a new `BufWriter<W>` with the specified buffer capacity.
///
/// # Examples
///
/// Creating a buffer with a buffer of a hundred bytes.
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let stream = TcpStream::connect("127.0.0.1:34254").unwrap();
/// let mut buffer = BufWriter::with_capacity(100, stream);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize, inner: W) -> BufWriter<W> {
BufWriter { inner: Some(inner), buf: Vec::with_capacity(capacity), panicked: false }
}
/// Send data in our local buffer into the inner writer, looping as
/// necessary until either it's all been sent or an error occurs.
///
/// Because all the data in the buffer has been reported to our owner as
/// "successfully written" (by returning nonzero success values from
/// `write`), any 0-length writes from `inner` must be reported as i/o
/// errors from this method.
pub(super) fn flush_buf(&mut self) -> io::Result<()> {
/// Helper struct to ensure the buffer is updated after all the writes
/// are complete. It tracks the number of written bytes and drains them
/// all from the front of the buffer when dropped.
struct BufGuard<'a> {
buffer: &'a mut Vec<u8>,
written: usize,
}
impl<'a> BufGuard<'a> {
fn new(buffer: &'a mut Vec<u8>) -> Self {
Self { buffer, written: 0 }
}
/// The unwritten part of the buffer
fn remaining(&self) -> &[u8] {
&self.buffer[self.written..]
}
/// Flag some bytes as removed from the front of the buffer
fn consume(&mut self, amt: usize) {
self.written += amt;
}
/// true if all of the bytes have been written
fn done(&self) -> bool {
self.written >= self.buffer.len()
}
}
impl Drop for BufGuard<'_> {
fn drop(&mut self) {
if self.written > 0 {
self.buffer.drain(..self.written);
}
}
}
let mut guard = BufGuard::new(&mut self.buf);
let inner = self.inner.as_mut().unwrap();
while !guard.done() {
self.panicked = true;
let r = inner.write(guard.remaining());
self.panicked = false;
match r {
Ok(0) => {
return Err(Error::new(
ErrorKind::WriteZero,
"failed to write the buffered data",
));
}
Ok(n) => guard.consume(n),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
/// Buffer some data without flushing it, regardless of the size of the
/// data. Writes as much as possible without exceeding capacity. Returns
/// the number of bytes written.
pub(super) fn write_to_buf(&mut self, buf: &[u8]) -> usize {
let available = self.buf.capacity() - self.buf.len();
let amt_to_buffer = available.min(buf.len());
self.buf.extend_from_slice(&buf[..amt_to_buffer]);
amt_to_buffer
}
/// Gets a reference to the underlying writer.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // we can use reference just like buffer
/// let reference = buffer.get_ref();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W {
self.inner.as_ref().unwrap()
}
/// Gets a mutable reference to the underlying writer.
///
/// It is inadvisable to directly write to the underlying writer.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // we can use reference just like buffer
/// let reference = buffer.get_mut();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W {
self.inner.as_mut().unwrap()
}
/// Returns a reference to the internally buffered data.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // See how many bytes are currently buffered
/// let bytes_buffered = buf_writer.buffer().len();
/// ```
#[stable(feature = "bufreader_buffer", since = "1.37.0")]
pub fn buffer(&self) -> &[u8] {
&self.buf
}
/// Returns the number of bytes the internal buffer can hold without flushing.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let buf_writer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // Check the capacity of the inner buffer
/// let capacity = buf_writer.capacity();
/// // Calculate how many bytes can be written without flushing
/// let without_flush = capacity - buf_writer.buffer().len();
/// ```
#[stable(feature = "buffered_io_capacity", since = "1.46.0")]
pub fn capacity(&self) -> usize {
self.buf.capacity()
}
/// Unwraps this `BufWriter<W>`, returning the underlying writer.
///
/// The buffer is written out before returning the writer.
///
/// # Errors
///
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // unwrap the TcpStream and flush the buffer
/// let stream = buffer.into_inner().unwrap();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
match self.flush_buf() {
Err(e) => Err(IntoInnerError::new(self, e)),
Ok(()) => Ok(self.inner.take().unwrap()),
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Write for BufWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.buf.len() + buf.len() > self.buf.capacity() {
self.flush_buf()?;
}
// FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
if buf.len() >= self.buf.capacity() {
self.panicked = true;
let r = self.get_mut().write(buf);
self.panicked = false;
r
} else {
self.buf.extend_from_slice(buf);
Ok(buf.len())
}
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
// Normally, `write_all` just calls `write` in a loop. We can do better
// by calling `self.get_mut().write_all()` directly, which avoids
// round trips through the buffer in the event of a series of partial
// writes in some circumstances.
if self.buf.len() + buf.len() > self.buf.capacity() {
self.flush_buf()?;
}
// FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
if buf.len() >= self.buf.capacity() {
self.panicked = true;
let r = self.get_mut().write_all(buf);
self.panicked = false;
r
} else {
self.buf.extend_from_slice(buf);
Ok(())
}
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
if self.buf.len() + total_len > self.buf.capacity() {
self.flush_buf()?;
}
// FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
if total_len >= self.buf.capacity() {
self.panicked = true;
let r = self.get_mut().write_vectored(bufs);
self.panicked = false;
r
} else {
bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
Ok(total_len)
}
}
fn is_write_vectored(&self) -> bool {
self.get_ref().is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
self.flush_buf().and_then(|()| self.get_mut().flush())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for BufWriter<W>
where
W: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("BufWriter")
.field("writer", &self.inner.as_ref().unwrap())
.field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity()))
.finish()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + Seek> Seek for BufWriter<W> {
/// Seek to the offset, in bytes, in the underlying writer.
///
/// Seeking always writes out the internal buffer before seeking.
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.flush_buf()?;
self.get_mut().seek(pos)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Drop for BufWriter<W> {
fn drop(&mut self) {
if self.inner.is_some() && !self.panicked {
// dtors should not panic, so we ignore a failed flush
let _r = self.flush_buf();
}
}
}

View File

@ -0,0 +1,232 @@
use crate::fmt;
use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSlice, Write};
/// Wraps a writer and buffers output to it, flushing whenever a newline
/// (`0x0a`, `'\n'`) is detected.
///
/// The [`BufWriter`] struct wraps a writer and buffers its output.
/// But it only does this batched write when it goes out of scope, or when the
/// internal buffer is full. Sometimes, you'd prefer to write each line as it's
/// completed, rather than the entire buffer at once. Enter `LineWriter`. It
/// does exactly that.
///
/// Like [`BufWriter`], a `LineWriter`s buffer will also be flushed when the
/// `LineWriter` goes out of scope or when its internal buffer is full.
///
/// If there's still a partial line in the buffer when the `LineWriter` is
/// dropped, it will flush those contents.
///
/// # Examples
///
/// We can use `LineWriter` to write one line at a time, significantly
/// reducing the number of actual writes to the file.
///
/// ```no_run
/// use std::fs::{self, File};
/// use std::io::prelude::*;
/// use std::io::LineWriter;
///
/// fn main() -> std::io::Result<()> {
/// let road_not_taken = b"I shall be telling this with a sigh
/// Somewhere ages and ages hence:
/// Two roads diverged in a wood, and I -
/// I took the one less traveled by,
/// And that has made all the difference.";
///
/// let file = File::create("poem.txt")?;
/// let mut file = LineWriter::new(file);
///
/// file.write_all(b"I shall be telling this with a sigh")?;
///
/// // No bytes are written until a newline is encountered (or
/// // the internal buffer is filled).
/// assert_eq!(fs::read_to_string("poem.txt")?, "");
/// file.write_all(b"\n")?;
/// assert_eq!(
/// fs::read_to_string("poem.txt")?,
/// "I shall be telling this with a sigh\n",
/// );
///
/// // Write the rest of the poem.
/// file.write_all(b"Somewhere ages and ages hence:
/// Two roads diverged in a wood, and I -
/// I took the one less traveled by,
/// And that has made all the difference.")?;
///
/// // The last line of the poem doesn't end in a newline, so
/// // we have to flush or drop the `LineWriter` to finish
/// // writing.
/// file.flush()?;
///
/// // Confirm the whole poem was written.
/// assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]);
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LineWriter<W: Write> {
inner: BufWriter<W>,
}
impl<W: Write> LineWriter<W> {
/// Creates a new `LineWriter`.
///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
/// let file = LineWriter::new(file);
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(inner: W) -> LineWriter<W> {
// Lines typically aren't that long, don't use a giant buffer
LineWriter::with_capacity(1024, inner)
}
/// Creates a new `LineWriter` with a specified capacity for the internal
/// buffer.
///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
/// let file = LineWriter::with_capacity(100, file);
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
LineWriter { inner: BufWriter::with_capacity(capacity, inner) }
}
/// Gets a reference to the underlying writer.
///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
/// let file = LineWriter::new(file);
///
/// let reference = file.get_ref();
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_ref(&self) -> &W {
self.inner.get_ref()
}
/// Gets a mutable reference to the underlying writer.
///
/// Caution must be taken when calling methods on the mutable reference
/// returned as extra writes could corrupt the output stream.
///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
/// let mut file = LineWriter::new(file);
///
/// // we can use reference just like file
/// let reference = file.get_mut();
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut W {
self.inner.get_mut()
}
/// Unwraps this `LineWriter`, returning the underlying writer.
///
/// The internal buffer is written out before returning the writer.
///
/// # Errors
///
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
/// use std::io::LineWriter;
///
/// fn main() -> std::io::Result<()> {
/// let file = File::create("poem.txt")?;
///
/// let writer: LineWriter<File> = LineWriter::new(file);
///
/// let file: File = writer.into_inner()?;
/// Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
self.inner.into_inner().map_err(|err| err.new_wrapped(|inner| LineWriter { inner }))
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> Write for LineWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
LineWriterShim::new(&mut self.inner).write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
LineWriterShim::new(&mut self.inner).write_vectored(bufs)
}
fn is_write_vectored(&self) -> bool {
self.inner.is_write_vectored()
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
LineWriterShim::new(&mut self.inner).write_all(buf)
}
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
LineWriterShim::new(&mut self.inner).write_all_vectored(bufs)
}
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
LineWriterShim::new(&mut self.inner).write_fmt(fmt)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write> fmt::Debug for LineWriter<W>
where
W: fmt::Debug,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("LineWriter")
.field("writer", &self.get_ref())
.field(
"buffer",
&format_args!("{}/{}", self.inner.buffer().len(), self.inner.capacity()),
)
.finish()
}
}

View File

@ -0,0 +1,270 @@
use crate::io::{self, BufWriter, IoSlice, Write};
use crate::memchr;
/// Private helper struct for implementing the line-buffered writing logic.
/// This shim temporarily wraps a BufWriter, and uses its internals to
/// implement a line-buffered writer (specifically by using the internal
/// methods like write_to_buf and flush_buf). In this way, a more
/// efficient abstraction can be created than one that only had access to
/// `write` and `flush`, without needlessly duplicating a lot of the
/// implementation details of BufWriter. This also allows existing
/// `BufWriters` to be temporarily given line-buffering logic; this is what
/// enables Stdout to be alternately in line-buffered or block-buffered mode.
#[derive(Debug)]
pub struct LineWriterShim<'a, W: Write> {
buffer: &'a mut BufWriter<W>,
}
impl<'a, W: Write> LineWriterShim<'a, W> {
pub fn new(buffer: &'a mut BufWriter<W>) -> Self {
Self { buffer }
}
/// Get a mutable reference to the inner writer (that is, the writer
/// wrapped by the BufWriter). Be careful with this writer, as writes to
/// it will bypass the buffer.
fn inner_mut(&mut self) -> &mut W {
self.buffer.get_mut()
}
/// Get the content currently buffered in self.buffer
fn buffered(&self) -> &[u8] {
self.buffer.buffer()
}
/// Flush the buffer iff the last byte is a newline (indicating that an
/// earlier write only succeeded partially, and we want to retry flushing
/// the buffered line before continuing with a subsequent write)
fn flush_if_completed_line(&mut self) -> io::Result<()> {
match self.buffered().last().copied() {
Some(b'\n') => self.buffer.flush_buf(),
_ => Ok(()),
}
}
}
impl<'a, W: Write> Write for LineWriterShim<'a, W> {
/// Write some data into this BufReader with line buffering. This means
/// that, if any newlines are present in the data, the data up to the last
/// newline is sent directly to the underlying writer, and data after it
/// is buffered. Returns the number of bytes written.
///
/// This function operates on a "best effort basis"; in keeping with the
/// convention of `Write::write`, it makes at most one attempt to write
/// new data to the underlying writer. If that write only reports a partial
/// success, the remaining data will be buffered.
///
/// Because this function attempts to send completed lines to the underlying
/// writer, it will also flush the existing buffer if it ends with a
/// newline, even if the incoming data does not contain any newlines.
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let newline_idx = match memchr::memrchr(b'\n', buf) {
// If there are no new newlines (that is, if this write is less than
// one line), just do a regular buffered write (which may flush if
// we exceed the inner buffer's size)
None => {
self.flush_if_completed_line()?;
return self.buffer.write(buf);
}
// Otherwise, arrange for the lines to be written directly to the
// inner writer.
Some(newline_idx) => newline_idx + 1,
};
// Flush existing content to prepare for our write. We have to do this
// before attempting to write `buf` in order to maintain consistency;
// if we add `buf` to the buffer then try to flush it all at once,
// we're obligated to return Ok(), which would mean suppressing any
// errors that occur during flush.
self.buffer.flush_buf()?;
// This is what we're going to try to write directly to the inner
// writer. The rest will be buffered, if nothing goes wrong.
let lines = &buf[..newline_idx];
// Write `lines` directly to the inner writer. In keeping with the
// `write` convention, make at most one attempt to add new (unbuffered)
// data. Because this write doesn't touch the BufWriter state directly,
// and the buffer is known to be empty, we don't need to worry about
// self.buffer.panicked here.
let flushed = self.inner_mut().write(lines)?;
// If buffer returns Ok(0), propagate that to the caller without
// doing additional buffering; otherwise we're just guaranteeing
// an "ErrorKind::WriteZero" later.
if flushed == 0 {
return Ok(0);
}
// Now that the write has succeeded, buffer the rest (or as much of
// the rest as possible). If there were any unwritten newlines, we
// only buffer out to the last unwritten newline that fits in the
// buffer; this helps prevent flushing partial lines on subsequent
// calls to LineWriterShim::write.
// Handle the cases in order of most-common to least-common, under
// the presumption that most writes succeed in totality, and that most
// writes are smaller than the buffer.
// - Is this a partial line (ie, no newlines left in the unwritten tail)
// - If not, does the data out to the last unwritten newline fit in
// the buffer?
// - If not, scan for the last newline that *does* fit in the buffer
let tail = if flushed >= newline_idx {
&buf[flushed..]
} else if newline_idx - flushed <= self.buffer.capacity() {
&buf[flushed..newline_idx]
} else {
let scan_area = &buf[flushed..];
let scan_area = &scan_area[..self.buffer.capacity()];
match memchr::memrchr(b'\n', scan_area) {
Some(newline_idx) => &scan_area[..newline_idx + 1],
None => scan_area,
}
};
let buffered = self.buffer.write_to_buf(tail);
Ok(flushed + buffered)
}
fn flush(&mut self) -> io::Result<()> {
self.buffer.flush()
}
/// Write some vectored data into this BufReader with line buffering. This
/// means that, if any newlines are present in the data, the data up to
/// and including the buffer containing the last newline is sent directly
/// to the inner writer, and the data after it is buffered. Returns the
/// number of bytes written.
///
/// This function operates on a "best effort basis"; in keeping with the
/// convention of `Write::write`, it makes at most one attempt to write
/// new data to the underlying writer.
///
/// Because this function attempts to send completed lines to the underlying
/// writer, it will also flush the existing buffer if it contains any
/// newlines.
///
/// Because sorting through an array of `IoSlice` can be a bit convoluted,
/// This method differs from write in the following ways:
///
/// - It attempts to write the full content of all the buffers up to and
/// including the one containing the last newline. This means that it
/// may attempt to write a partial line, that buffer has data past the
/// newline.
/// - If the write only reports partial success, it does not attempt to
/// find the precise location of the written bytes and buffer the rest.
///
/// If the underlying vector doesn't support vectored writing, we instead
/// simply write the first non-empty buffer with `write`. This way, we
/// get the benefits of more granular partial-line handling without losing
/// anything in efficiency
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
// If there's no specialized behavior for write_vectored, just use
// write. This has the benefit of more granular partial-line handling.
if !self.is_write_vectored() {
return match bufs.iter().find(|buf| !buf.is_empty()) {
Some(buf) => self.write(buf),
None => Ok(0),
};
}
// Find the buffer containing the last newline
let last_newline_buf_idx = bufs
.iter()
.enumerate()
.rev()
.find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i));
// If there are no new newlines (that is, if this write is less than
// one line), just do a regular buffered write
let last_newline_buf_idx = match last_newline_buf_idx {
// No newlines; just do a normal buffered write
None => {
self.flush_if_completed_line()?;
return self.buffer.write_vectored(bufs);
}
Some(i) => i,
};
// Flush existing content to prepare for our write
self.buffer.flush_buf()?;
// This is what we're going to try to write directly to the inner
// writer. The rest will be buffered, if nothing goes wrong.
let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1);
// Write `lines` directly to the inner writer. In keeping with the
// `write` convention, make at most one attempt to add new (unbuffered)
// data. Because this write doesn't touch the BufWriter state directly,
// and the buffer is known to be empty, we don't need to worry about
// self.panicked here.
let flushed = self.inner_mut().write_vectored(lines)?;
// If inner returns Ok(0), propagate that to the caller without
// doing additional buffering; otherwise we're just guaranteeing
// an "ErrorKind::WriteZero" later.
if flushed == 0 {
return Ok(0);
}
// Don't try to reconstruct the exact amount written; just bail
// in the event of a partial write
let lines_len = lines.iter().map(|buf| buf.len()).sum();
if flushed < lines_len {
return Ok(flushed);
}
// Now that the write has succeeded, buffer the rest (or as much of the
// rest as possible)
let buffered: usize = tail
.iter()
.filter(|buf| !buf.is_empty())
.map(|buf| self.buffer.write_to_buf(buf))
.take_while(|&n| n > 0)
.sum();
Ok(flushed + buffered)
}
fn is_write_vectored(&self) -> bool {
self.buffer.is_write_vectored()
}
/// Write some data into this BufReader with line buffering. This means
/// that, if any newlines are present in the data, the data up to the last
/// newline is sent directly to the underlying writer, and data after it
/// is buffered.
///
/// Because this function attempts to send completed lines to the underlying
/// writer, it will also flush the existing buffer if it contains any
/// newlines, even if the incoming data does not contain any newlines.
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
match memchr::memrchr(b'\n', buf) {
// If there are no new newlines (that is, if this write is less than
// one line), just do a regular buffered write (which may flush if
// we exceed the inner buffer's size)
None => {
self.flush_if_completed_line()?;
self.buffer.write_all(buf)
}
Some(newline_idx) => {
let (lines, tail) = buf.split_at(newline_idx + 1);
if self.buffered().is_empty() {
self.inner_mut().write_all(lines)?;
} else {
// If there is any buffered data, we add the incoming lines
// to that buffer before flushing, which saves us at least
// one write call. We can't really do this with `write`,
// since we can't do this *and* not suppress errors *and*
// report a consistent state to the caller in a return
// value, but here in write_all it's fine.
self.buffer.write_all(lines)?;
self.buffer.flush_buf()?;
}
self.buffer.write_all(tail)
}
}
}
}

View File

@ -0,0 +1,151 @@
//! Buffering wrappers for I/O traits
mod bufreader;
mod bufwriter;
mod linewriter;
mod linewritershim;
#[cfg(test)]
mod tests;
use crate::error;
use crate::fmt;
use crate::io::Error;
pub use bufreader::BufReader;
pub use bufwriter::BufWriter;
pub use linewriter::LineWriter;
use linewritershim::LineWriterShim;
/// An error returned by [`BufWriter::into_inner`] which combines an error that
/// happened while writing out the buffer, and the buffered writer object
/// which may be used to recover from the condition.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // do stuff with the stream
///
/// // we want to get our `TcpStream` back, so let's try:
///
/// let stream = match stream.into_inner() {
/// Ok(s) => s,
/// Err(e) => {
/// // Here, e is an IntoInnerError
/// panic!("An error occurred");
/// }
/// };
/// ```
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoInnerError<W>(W, Error);
impl<W> IntoInnerError<W> {
/// Construct a new IntoInnerError
fn new(writer: W, error: Error) -> Self {
Self(writer, error)
}
/// Helper to construct a new IntoInnerError; intended to help with
/// adapters that wrap other adapters
fn new_wrapped<W2>(self, f: impl FnOnce(W) -> W2) -> IntoInnerError<W2> {
let Self(writer, error) = self;
IntoInnerError::new(f(writer), error)
}
/// Returns the error which caused the call to [`BufWriter::into_inner()`]
/// to fail.
///
/// This error was returned when attempting to write the internal buffer.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // do stuff with the stream
///
/// // we want to get our `TcpStream` back, so let's try:
///
/// let stream = match stream.into_inner() {
/// Ok(s) => s,
/// Err(e) => {
/// // Here, e is an IntoInnerError, let's log the inner error.
/// //
/// // We'll just 'log' to stdout for this example.
/// println!("{}", e.error());
///
/// panic!("An unexpected error occurred.");
/// }
/// };
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn error(&self) -> &Error {
&self.1
}
/// Returns the buffered writer instance which generated the error.
///
/// The returned object can be used for error recovery, such as
/// re-inspecting the buffer.
///
/// # Examples
///
/// ```no_run
/// use std::io::BufWriter;
/// use std::net::TcpStream;
///
/// let mut stream = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap());
///
/// // do stuff with the stream
///
/// // we want to get our `TcpStream` back, so let's try:
///
/// let stream = match stream.into_inner() {
/// Ok(s) => s,
/// Err(e) => {
/// // Here, e is an IntoInnerError, let's re-examine the buffer:
/// let buffer = e.into_inner();
///
/// // do stuff to try to recover
///
/// // afterwards, let's just return the stream
/// buffer.into_inner().unwrap()
/// }
/// };
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_inner(self) -> W {
self.0
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W> From<IntoInnerError<W>> for Error {
fn from(iie: IntoInnerError<W>) -> Error {
iie.1
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
#[allow(deprecated, deprecated_in_future)]
fn description(&self) -> &str {
error::Error::description(self.error())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W> fmt::Display for IntoInnerError<W> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.error().fmt(f)
}
}

View File

@ -1,4 +1,3 @@
use crate::cell::UnsafeCell;
use crate::mem;
use crate::sync::atomic::{AtomicU32, Ordering};
use crate::sys::cloudabi::abi;
@ -12,7 +11,7 @@ extern "C" {
}
pub struct Condvar {
condvar: UnsafeCell<AtomicU32>,
condvar: AtomicU32,
}
pub type MovableCondvar = Condvar;
@ -20,29 +19,28 @@ pub type MovableCondvar = Condvar;
unsafe impl Send for Condvar {}
unsafe impl Sync for Condvar {}
const NEW: Condvar =
Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) };
impl Condvar {
pub const fn new() -> Condvar {
NEW
Condvar { condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0) }
}
pub unsafe fn init(&mut self) {}
pub unsafe fn notify_one(&self) {
let condvar = self.condvar.get();
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
let ret = abi::condvar_signal(
&self.condvar as *const AtomicU32 as *mut abi::condvar,
abi::scope::PRIVATE,
1,
);
assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
}
}
pub unsafe fn notify_all(&self) {
let condvar = self.condvar.get();
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
let ret = abi::condvar_signal(
condvar as *mut abi::condvar,
&self.condvar as *const AtomicU32 as *mut abi::condvar,
abi::scope::PRIVATE,
abi::nthreads::MAX,
);
@ -53,20 +51,19 @@ impl Condvar {
pub unsafe fn wait(&self, mutex: &Mutex) {
let mutex = mutex::raw(mutex);
assert_eq!(
(*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
"This lock is not write-locked by this thread"
);
// Call into the kernel to wait on the condition variable.
let condvar = self.condvar.get();
let subscription = abi::subscription {
type_: abi::eventtype::CONDVAR,
union: abi::subscription_union {
condvar: abi::subscription_condvar {
condvar: condvar as *mut abi::condvar,
condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
condvar_scope: abi::scope::PRIVATE,
lock: mutex as *mut abi::lock,
lock: mutex as *const AtomicU32 as *mut abi::lock,
lock_scope: abi::scope::PRIVATE,
},
},
@ -86,13 +83,12 @@ impl Condvar {
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
let mutex = mutex::raw(mutex);
assert_eq!(
(*mutex).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
"This lock is not write-locked by this thread"
);
// Call into the kernel to wait on the condition variable.
let condvar = self.condvar.get();
let timeout =
checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
let subscriptions = [
@ -100,9 +96,9 @@ impl Condvar {
type_: abi::eventtype::CONDVAR,
union: abi::subscription_union {
condvar: abi::subscription_condvar {
condvar: condvar as *mut abi::condvar,
condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
condvar_scope: abi::scope::PRIVATE,
lock: mutex as *mut abi::lock,
lock: mutex as *const AtomicU32 as *mut abi::lock,
lock_scope: abi::scope::PRIVATE,
},
},
@ -124,7 +120,7 @@ impl Condvar {
let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
let ret = abi::poll(
subscriptions.as_ptr(),
mem::MaybeUninit::first_ptr_mut(&mut events),
mem::MaybeUninit::slice_as_mut_ptr(&mut events),
2,
nevents.as_mut_ptr(),
);
@ -144,9 +140,8 @@ impl Condvar {
}
pub unsafe fn destroy(&self) {
let condvar = self.condvar.get();
assert_eq!(
(*condvar).load(Ordering::Relaxed),
self.condvar.load(Ordering::Relaxed),
abi::CONDVAR_HAS_NO_WAITERS.0,
"Attempted to destroy a condition variable with blocked threads"
);

View File

@ -1,4 +1,4 @@
use crate::cell::UnsafeCell;
use crate::cell::Cell;
use crate::mem;
use crate::mem::MaybeUninit;
use crate::sync::atomic::{AtomicU32, Ordering};
@ -17,7 +17,7 @@ pub struct Mutex(RWLock);
pub type MovableMutex = Mutex;
pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
pub unsafe fn raw(m: &Mutex) -> &AtomicU32 {
rwlock::raw(&m.0)
}
@ -50,28 +50,23 @@ impl Mutex {
}
pub struct ReentrantMutex {
lock: UnsafeCell<MaybeUninit<AtomicU32>>,
recursion: UnsafeCell<MaybeUninit<u32>>,
lock: AtomicU32,
recursion: Cell<u32>,
}
unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}
impl ReentrantMutex {
pub const unsafe fn uninitialized() -> ReentrantMutex {
ReentrantMutex {
lock: UnsafeCell::new(MaybeUninit::uninit()),
recursion: UnsafeCell::new(MaybeUninit::uninit()),
}
ReentrantMutex { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), recursion: Cell::new(0) }
}
pub unsafe fn init(&self) {
*self.lock.get() = MaybeUninit::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
*self.recursion.get() = MaybeUninit::new(0);
}
pub unsafe fn init(&self) {}
pub unsafe fn try_lock(&self) -> bool {
// Attempt to acquire the lock.
let lock = (*self.lock.get()).as_mut_ptr();
let recursion = (*self.recursion.get()).as_mut_ptr();
if let Err(old) = (*lock).compare_exchange(
if let Err(old) = self.lock.compare_exchange(
abi::LOCK_UNLOCKED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
Ordering::Acquire,
@ -80,14 +75,14 @@ impl ReentrantMutex {
// If we fail to acquire the lock, it may be the case
// that we've already acquired it and may need to recurse.
if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
*recursion += 1;
self.recursion.set(self.recursion.get() + 1);
true
} else {
false
}
} else {
// Success.
assert_eq!(*recursion, 0, "Mutex has invalid recursion count");
assert_eq!(self.recursion.get(), 0, "Mutex has invalid recursion count");
true
}
}
@ -95,7 +90,7 @@ impl ReentrantMutex {
pub unsafe fn lock(&self) {
if !self.try_lock() {
// Call into the kernel to acquire a write lock.
let lock = self.lock.get();
let lock = &self.lock as *const AtomicU32;
let subscription = abi::subscription {
type_: abi::eventtype::LOCK_WRLOCK,
union: abi::subscription_union {
@ -116,17 +111,17 @@ impl ReentrantMutex {
}
pub unsafe fn unlock(&self) {
let lock = (*self.lock.get()).as_mut_ptr();
let recursion = (*self.recursion.get()).as_mut_ptr();
assert_eq!(
(*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
"This mutex is locked by a different thread"
);
if *recursion > 0 {
*recursion -= 1;
} else if !(*lock)
let r = self.recursion.get();
if r > 0 {
self.recursion.set(r - 1);
} else if !self
.lock
.compare_exchange(
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
abi::LOCK_UNLOCKED.0,
@ -137,19 +132,20 @@ impl ReentrantMutex {
{
// Lock is managed by kernelspace. Call into the kernel
// to unblock waiting threads.
let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
let ret = abi::lock_unlock(
&self.lock as *const AtomicU32 as *mut abi::lock,
abi::scope::PRIVATE,
);
assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
}
}
pub unsafe fn destroy(&self) {
let lock = (*self.lock.get()).as_mut_ptr();
let recursion = (*self.recursion.get()).as_mut_ptr();
assert_eq!(
(*lock).load(Ordering::Relaxed),
self.lock.load(Ordering::Relaxed),
abi::LOCK_UNLOCKED.0,
"Attempted to destroy locked mutex"
);
assert_eq!(*recursion, 0, "Recursion counter invalid");
assert_eq!(self.recursion.get(), 0, "Recursion counter invalid");
}
}

View File

@ -1,4 +1,3 @@
use crate::cell::UnsafeCell;
use crate::mem;
use crate::mem::MaybeUninit;
use crate::sync::atomic::{AtomicU32, Ordering};
@ -13,28 +12,25 @@ extern "C" {
static mut RDLOCKS_ACQUIRED: u32 = 0;
pub struct RWLock {
lock: UnsafeCell<AtomicU32>,
lock: AtomicU32,
}
pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
r.lock.get()
pub unsafe fn raw(r: &RWLock) -> &AtomicU32 {
&r.lock
}
unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {}
const NEW: RWLock = RWLock { lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)) };
impl RWLock {
pub const fn new() -> RWLock {
NEW
RWLock { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0) }
}
pub unsafe fn try_read(&self) -> bool {
let lock = self.lock.get();
let mut old = abi::LOCK_UNLOCKED.0;
while let Err(cur) =
(*lock).compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
self.lock.compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
{
if (cur & abi::LOCK_WRLOCKED.0) != 0 {
// Another thread already has a write lock.
@ -61,12 +57,11 @@ impl RWLock {
pub unsafe fn read(&self) {
if !self.try_read() {
// Call into the kernel to acquire a read lock.
let lock = self.lock.get();
let subscription = abi::subscription {
type_: abi::eventtype::LOCK_RDLOCK,
union: abi::subscription_union {
lock: abi::subscription_lock {
lock: lock as *mut abi::lock,
lock: &self.lock as *const AtomicU32 as *mut abi::lock,
lock_scope: abi::scope::PRIVATE,
},
},
@ -96,11 +91,10 @@ impl RWLock {
assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
let mut old = 1;
loop {
let lock = self.lock.get();
if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
// Last read lock while threads are waiting. Attempt to upgrade
// to a write lock before calling into the kernel to unlock.
if let Err(cur) = (*lock).compare_exchange_weak(
if let Err(cur) = self.lock.compare_exchange_weak(
old,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
Ordering::Acquire,
@ -109,7 +103,10 @@ impl RWLock {
old = cur;
} else {
// Call into the kernel to unlock.
let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
let ret = abi::lock_unlock(
&self.lock as *const AtomicU32 as *mut abi::lock,
abi::scope::PRIVATE,
);
assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
break;
}
@ -122,7 +119,7 @@ impl RWLock {
0,
"Attempted to read-unlock a write-locked rwlock"
);
if let Err(cur) = (*lock).compare_exchange_weak(
if let Err(cur) = self.lock.compare_exchange_weak(
old,
old - 1,
Ordering::Acquire,
@ -140,8 +137,7 @@ impl RWLock {
pub unsafe fn try_write(&self) -> bool {
// Attempt to acquire the lock.
let lock = self.lock.get();
if let Err(old) = (*lock).compare_exchange(
if let Err(old) = self.lock.compare_exchange(
abi::LOCK_UNLOCKED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
Ordering::Acquire,
@ -163,12 +159,11 @@ impl RWLock {
pub unsafe fn write(&self) {
if !self.try_write() {
// Call into the kernel to acquire a write lock.
let lock = self.lock.get();
let subscription = abi::subscription {
type_: abi::eventtype::LOCK_WRLOCK,
union: abi::subscription_union {
lock: abi::subscription_lock {
lock: lock as *mut abi::lock,
lock: &self.lock as *const AtomicU32 as *mut abi::lock,
lock_scope: abi::scope::PRIVATE,
},
},
@ -184,14 +179,14 @@ impl RWLock {
}
pub unsafe fn write_unlock(&self) {
let lock = self.lock.get();
assert_eq!(
(*lock).load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
"This rwlock is not write-locked by this thread"
);
if !(*lock)
if !self
.lock
.compare_exchange(
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
abi::LOCK_UNLOCKED.0,
@ -202,15 +197,17 @@ impl RWLock {
{
// Lock is managed by kernelspace. Call into the kernel
// to unblock waiting threads.
let ret = abi::lock_unlock(lock as *mut abi::lock, abi::scope::PRIVATE);
let ret = abi::lock_unlock(
&self.lock as *const AtomicU32 as *mut abi::lock,
abi::scope::PRIVATE,
);
assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
}
}
pub unsafe fn destroy(&self) {
let lock = self.lock.get();
assert_eq!(
(*lock).load(Ordering::Relaxed),
self.lock.load(Ordering::Relaxed),
abi::LOCK_UNLOCKED.0,
"Attempted to destroy locked rwlock"
);

View File

@ -470,7 +470,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
&mut environ
}
pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
pub unsafe fn env_lock() -> StaticMutexGuard {
// It is UB to attempt to acquire this mutex reentrantly!
static ENV_LOCK: StaticMutex = StaticMutex::new();
ENV_LOCK.lock()

View File

@ -212,7 +212,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
&mut environ
}
pub unsafe fn env_lock() -> StaticMutexGuard<'static> {
pub unsafe fn env_lock() -> StaticMutexGuard {
// It is UB to attempt to acquire this mutex reentrantly!
static ENV_LOCK: StaticMutex = StaticMutex::new();
ENV_LOCK.lock()

View File

@ -0,0 +1,17 @@
use crate::arch::wasm32;
use crate::convert::TryInto;
use crate::sync::atomic::AtomicI32;
use crate::time::Duration;
pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1);
unsafe {
wasm32::memory_atomic_wait32(futex as *const AtomicI32 as *mut i32, expected, timeout);
}
}
pub fn futex_wake(futex: &AtomicI32) {
unsafe {
wasm32::memory_atomic_notify(futex as *const AtomicI32 as *mut i32, 1);
}
}

View File

@ -55,6 +55,8 @@ cfg_if::cfg_if! {
pub mod mutex;
#[path = "rwlock_atomics.rs"]
pub mod rwlock;
#[path = "futex_atomics.rs"]
pub mod futex;
} else {
#[path = "../unsupported/condvar.rs"]
pub mod condvar;

View File

@ -8,27 +8,15 @@ use crate::io;
use crate::io::prelude::*;
use crate::path::{self, Path, PathBuf};
use crate::sync::atomic::{self, Ordering};
use crate::sys::mutex::Mutex;
use crate::sys_common::mutex::StaticMutex;
/// Max number of frames to print.
const MAX_NB_FRAMES: usize = 100;
pub fn lock() -> impl Drop {
struct Guard;
static LOCK: Mutex = Mutex::new();
impl Drop for Guard {
fn drop(&mut self) {
unsafe {
LOCK.unlock();
}
}
}
unsafe {
LOCK.lock();
Guard
}
// SAFETY: Don't attempt to lock this reentrantly.
pub unsafe fn lock() -> impl Drop {
static LOCK: StaticMutex = StaticMutex::new();
LOCK.lock()
}
/// Prints the current backtrace.

View File

@ -3,8 +3,7 @@ use crate::sys::mutex as imp;
/// An OS-based mutual exclusion lock, meant for use in static variables.
///
/// This mutex has a const constructor ([`StaticMutex::new`]), does not
/// implement `Drop` to cleanup resources, and causes UB when moved or used
/// reentrantly.
/// implement `Drop` to cleanup resources, and causes UB when used reentrantly.
///
/// This mutex does not implement poisoning.
///
@ -16,11 +15,6 @@ unsafe impl Sync for StaticMutex {}
impl StaticMutex {
/// Creates a new mutex for use.
///
/// Behavior is undefined if the mutex is moved after it is
/// first used with any of the functions below.
/// Also, the behavior is undefined if this mutex is ever used reentrantly,
/// i.e., `lock` is called by the thread currently holding the lock.
pub const fn new() -> Self {
Self(imp::Mutex::new())
}
@ -28,19 +22,19 @@ impl StaticMutex {
/// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
/// will be unlocked.
///
/// It is undefined behaviour to call this function while locked, or if the
/// mutex has been moved since the last time this was called.
/// It is undefined behaviour to call this function while locked by the
/// same thread.
#[inline]
pub unsafe fn lock(&self) -> StaticMutexGuard<'_> {
pub unsafe fn lock(&'static self) -> StaticMutexGuard {
self.0.lock();
StaticMutexGuard(&self.0)
}
}
#[must_use]
pub struct StaticMutexGuard<'a>(&'a imp::Mutex);
pub struct StaticMutexGuard(&'static imp::Mutex);
impl Drop for StaticMutexGuard<'_> {
impl Drop for StaticMutexGuard {
#[inline]
fn drop(&mut self) {
unsafe {

View File

@ -1,5 +1,9 @@
cfg_if::cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "android"))] {
if #[cfg(any(
target_os = "linux",
target_os = "android",
all(target_arch = "wasm32", target_feature = "atomics"),
))] {
mod futex;
pub use futex::Parker;
} else {

View File

@ -201,6 +201,37 @@ impl Cfg {
_ => false,
}
}
/// Attempt to simplify this cfg by assuming that `assume` is already known to be true, will
/// return `None` if simplification managed to completely eliminate any requirements from this
/// `Cfg`.
///
/// See `tests::test_simplify_with` for examples.
pub(crate) fn simplify_with(&self, assume: &Cfg) -> Option<Cfg> {
if self == assume {
return None;
}
if let Cfg::All(a) = self {
let mut sub_cfgs: Vec<Cfg> = if let Cfg::All(b) = assume {
a.iter().filter(|a| !b.contains(a)).cloned().collect()
} else {
a.iter().filter(|&a| a != assume).cloned().collect()
};
let len = sub_cfgs.len();
return match len {
0 => None,
1 => sub_cfgs.pop(),
_ => Some(Cfg::All(sub_cfgs)),
};
} else if let Cfg::All(b) = assume {
if b.contains(self) {
return None;
}
}
Some(self.clone())
}
}
impl ops::Not for Cfg {

View File

@ -433,3 +433,39 @@ fn test_render_long_html() {
);
})
}
#[test]
fn test_simplify_with() {
// This is a tiny subset of things that could be simplified, but it likely covers 90% of
// real world usecases well.
with_default_session_globals(|| {
let foo = word_cfg("foo");
let bar = word_cfg("bar");
let baz = word_cfg("baz");
let quux = word_cfg("quux");
let foobar = Cfg::All(vec![foo.clone(), bar.clone()]);
let barbaz = Cfg::All(vec![bar.clone(), baz.clone()]);
let foobarbaz = Cfg::All(vec![foo.clone(), bar.clone(), baz.clone()]);
let bazquux = Cfg::All(vec![baz.clone(), quux.clone()]);
// Unrelated cfgs don't affect each other
assert_eq!(foo.simplify_with(&bar).as_ref(), Some(&foo));
assert_eq!(foobar.simplify_with(&bazquux).as_ref(), Some(&foobar));
// Identical cfgs are eliminated
assert_eq!(foo.simplify_with(&foo), None);
assert_eq!(foobar.simplify_with(&foobar), None);
// Multiple cfgs eliminate a single assumed cfg
assert_eq!(foobar.simplify_with(&foo).as_ref(), Some(&bar));
assert_eq!(foobar.simplify_with(&bar).as_ref(), Some(&foo));
// A single cfg is eliminated by multiple assumed cfg containing it
assert_eq!(foo.simplify_with(&foobar), None);
// Multiple cfgs eliminate the matching subset of multiple assumed cfg
assert_eq!(foobar.simplify_with(&barbaz).as_ref(), Some(&foo));
assert_eq!(foobar.simplify_with(&foobarbaz), None);
});
}

View File

@ -1763,11 +1763,11 @@ crate fn shorten(s: String) -> String {
}
}
fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) {
fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) {
if let Some(ref name) = item.name {
info!("Documenting {}", name);
}
document_stability(w, cx, item, false);
document_stability(w, cx, item, false, parent);
document_full(w, item, cx, "", false);
}
@ -1851,8 +1851,14 @@ fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str,
}
}
fn document_stability(w: &mut Buffer, cx: &Context, item: &clean::Item, is_hidden: bool) {
let stabilities = short_stability(item, cx);
fn document_stability(
w: &mut Buffer,
cx: &Context,
item: &clean::Item,
is_hidden: bool,
parent: Option<&clean::Item>,
) {
let stabilities = short_stability(item, cx, parent);
if !stabilities.is_empty() {
write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" });
for stability in stabilities {
@ -1952,7 +1958,7 @@ pub fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering {
}
fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) {
document(w, cx, item);
document(w, cx, item, None);
let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
@ -2111,7 +2117,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
<td class='docblock-short'>{stab_tags}{docs}</td>\
</tr>",
name = *myitem.name.as_ref().unwrap(),
stab_tags = stability_tags(myitem),
stab_tags = stability_tags(myitem, item),
docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
class = myitem.type_(),
add = add,
@ -2135,7 +2141,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean:
/// Render the stability and deprecation tags that are displayed in the item's summary at the
/// module level.
fn stability_tags(item: &clean::Item) -> String {
fn stability_tags(item: &clean::Item, parent: &clean::Item) -> String {
let mut tags = String::new();
fn tag_html(class: &str, title: &str, contents: &str) -> String {
@ -2159,7 +2165,13 @@ fn stability_tags(item: &clean::Item) -> String {
tags += &tag_html("unstable", "", "Experimental");
}
if let Some(ref cfg) = item.attrs.cfg {
let cfg = match (&item.attrs.cfg, parent.attrs.cfg.as_ref()) {
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
(cfg, _) => cfg.as_deref().cloned(),
};
debug!("Portability {:?} - {:?} = {:?}", item.attrs.cfg, parent.attrs.cfg, cfg);
if let Some(ref cfg) = cfg {
tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html());
}
@ -2168,7 +2180,7 @@ fn stability_tags(item: &clean::Item) -> String {
/// Render the stability and/or deprecation warning that is displayed at the top of the item's
/// documentation.
fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
fn short_stability(item: &clean::Item, cx: &Context, parent: Option<&clean::Item>) -> Vec<String> {
let mut stability = vec![];
let error_codes = cx.shared.codes;
@ -2243,7 +2255,18 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
stability.push(format!("<div class='stab unstable'>{}</div>", message));
}
if let Some(ref cfg) = item.attrs.cfg {
let cfg = match (&item.attrs.cfg, parent.and_then(|p| p.attrs.cfg.as_ref())) {
(Some(cfg), Some(parent_cfg)) => cfg.simplify_with(parent_cfg),
(cfg, _) => cfg.as_deref().cloned(),
};
debug!(
"Portability {:?} - {:?} = {:?}",
item.attrs.cfg,
parent.and_then(|p| p.attrs.cfg.as_ref()),
cfg
);
if let Some(cfg) = cfg {
stability.push(format!("<div class='stab portability'>{}</div>", cfg.render_long_html()));
}
@ -2282,7 +2305,7 @@ fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Cons
}
write!(w, "</pre>");
document(w, cx, it)
document(w, cx, it, None)
}
fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
@ -2296,7 +2319,7 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static
name = it.name.as_ref().unwrap(),
typ = s.type_.print()
);
document(w, cx, it)
document(w, cx, it, None)
}
fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) {
@ -2329,7 +2352,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
.print(),
spotlight = spotlight_decl(&f.decl),
);
document(w, cx, it)
document(w, cx, it, None)
}
fn render_implementor(
@ -2354,6 +2377,7 @@ fn render_implementor(
w,
cx,
implementor,
None,
AssocItemLink::Anchor(None),
RenderMode::Normal,
implementor.impl_item.stable_since().as_deref(),
@ -2383,6 +2407,7 @@ fn render_impls(
&mut buffer,
cx,
i,
Some(containing_item),
assoc_link,
RenderMode::Normal,
containing_item.stable_since().as_deref(),
@ -2502,7 +2527,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
});
// Trait documentation
document(w, cx, it);
document(w, cx, it, None);
fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
write!(
@ -2520,6 +2545,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
let name = m.name.as_ref().unwrap();
info!("Documenting {} on {}", name, t.name.as_deref().unwrap_or_default());
let item_type = m.type_();
let id = cx.derive_id(format!("{}.{}", item_type, name));
write!(w, "<h3 id='{id}' class='method'><code>", id = id,);
@ -2527,7 +2553,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
write!(w, "</code>");
render_stability_since(w, m, t);
write!(w, "</h3>");
document(w, cx, m);
document(w, cx, m, Some(t));
}
if !types.is_empty() {
@ -2628,6 +2654,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
w,
cx,
&implementor,
None,
assoc_link,
RenderMode::Normal,
implementor.impl_item.stable_since().as_deref(),
@ -2890,7 +2917,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
write!(w, "</pre>")
});
document(w, cx, it);
document(w, cx, it, None);
let mut fields = s
.fields
.iter()
@ -2925,7 +2952,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
name = field.name.as_ref().unwrap(),
ty = ty.print()
);
document(w, cx, field);
document(w, cx, field, Some(it));
}
}
}
@ -2940,7 +2967,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union,
write!(w, "</pre>")
});
document(w, cx, it);
document(w, cx, it, None);
let mut fields = s
.fields
.iter()
@ -2972,7 +2999,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union,
if let Some(stability_class) = field.stability_class() {
write!(w, "<span class='stab {stab}'></span>", stab = stability_class);
}
document(w, cx, field);
document(w, cx, field, Some(it));
}
}
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
@ -3027,7 +3054,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
write!(w, "</pre>")
});
document(w, cx, it);
document(w, cx, it, None);
if !e.variants.is_empty() {
write!(
w,
@ -3060,7 +3087,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
}
}
write!(w, "</code></div>");
document(w, cx, variant);
document(w, cx, variant, Some(it));
document_non_exhaustive(w, variant);
use crate::clean::{Variant, VariantKind};
@ -3095,7 +3122,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
f = field.name.as_ref().unwrap(),
t = ty.print()
);
document(w, cx, field);
document(w, cx, field, Some(variant));
}
}
write!(w, "</div></div>");
@ -3293,6 +3320,10 @@ fn render_assoc_items(
what: AssocItemRender<'_>,
cache: &Cache,
) {
info!(
"Documenting associated items of {}",
containing_item.name.as_deref().unwrap_or_default()
);
let v = match cache.impls.get(&it) {
Some(v) => v,
None => return,
@ -3327,6 +3358,7 @@ fn render_assoc_items(
w,
cx,
i,
Some(containing_item),
AssocItemLink::Anchor(None),
render_mode,
containing_item.stable_since().as_deref(),
@ -3518,6 +3550,7 @@ fn render_impl(
w: &mut Buffer,
cx: &Context,
i: &Impl,
parent: Option<&clean::Item>,
link: AssocItemLink<'_>,
render_mode: RenderMode,
outer_version: Option<&str>,
@ -3600,6 +3633,7 @@ fn render_impl(
w: &mut Buffer,
cx: &Context,
item: &clean::Item,
parent: Option<&clean::Item>,
link: AssocItemLink<'_>,
render_mode: RenderMode,
is_default_item: bool,
@ -3684,7 +3718,7 @@ fn render_impl(
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
// We need the stability of the item from the trait
// because impls can't have a stability.
document_stability(w, cx, it, is_hidden);
document_stability(w, cx, it, is_hidden, parent);
if item.doc_value().is_some() {
document_full(w, item, cx, "", is_hidden);
} else if show_def_docs {
@ -3694,13 +3728,13 @@ fn render_impl(
}
}
} else {
document_stability(w, cx, item, is_hidden);
document_stability(w, cx, item, is_hidden, parent);
if show_def_docs {
document_full(w, item, cx, "", is_hidden);
}
}
} else {
document_stability(w, cx, item, is_hidden);
document_stability(w, cx, item, is_hidden, parent);
if show_def_docs {
document_short(w, item, link, "", is_hidden);
}
@ -3717,6 +3751,7 @@ fn render_impl(
w,
cx,
trait_item,
parent,
link,
render_mode,
false,
@ -3732,6 +3767,7 @@ fn render_impl(
cx: &Context,
t: &clean::Trait,
i: &clean::Impl,
parent: Option<&clean::Item>,
render_mode: RenderMode,
outer_version: Option<&str>,
show_def_docs: bool,
@ -3749,6 +3785,7 @@ fn render_impl(
w,
cx,
trait_item,
parent,
assoc_link,
render_mode,
true,
@ -3771,6 +3808,7 @@ fn render_impl(
cx,
t,
&i.inner_impl(),
parent,
render_mode,
outer_version,
show_def_docs,
@ -3799,7 +3837,7 @@ fn item_opaque_ty(
bounds = bounds(&t.bounds, false)
);
document(w, cx, it);
document(w, cx, it, None);
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
@ -3826,7 +3864,7 @@ fn item_trait_alias(
bounds(&t.bounds, true)
);
document(w, cx, it);
document(w, cx, it, None);
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
@ -3847,7 +3885,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed
type_ = t.type_.print()
);
document(w, cx, it);
document(w, cx, it, None);
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
@ -3866,7 +3904,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cac
it.name.as_ref().unwrap(),
);
document(w, cx, it);
document(w, cx, it, None);
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
}
@ -4511,7 +4549,7 @@ fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro)
None,
))
});
document(w, cx, it)
document(w, cx, it, None)
}
fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::ProcMacro) {
@ -4541,16 +4579,16 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr
write!(w, "</pre>");
}
}
document(w, cx, it)
document(w, cx, it, None)
}
fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cache) {
document(w, cx, it);
document(w, cx, it, None);
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
}
fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
document(w, cx, it)
document(w, cx, it, None)
}
crate const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";

View File

@ -0,0 +1,182 @@
#![crate_name = "globuliferous"]
#![feature(doc_cfg)]
// @has 'globuliferous/index.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' '^ratel$'
// @has 'globuliferous/ratel/index.html'
// @count - '//*[@class="stab portability"]' 8
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
// @matches - '//*[@class="stab portability"]' '^zoonosology$'
// @matches - '//*[@class="stab portability"]' '^yusho$'
// @matches - '//*[@class="stab portability"]' '^nunciative$'
// @matches - '//*[@class="stab portability"]' '^thionic$'
// @matches - '//*[@class="stab portability"]' '^zincic$'
// @matches - '//*[@class="stab portability"]' '^cosmotellurian$'
// @matches - '//*[@class="stab portability"]' '^aposiopesis$'
#[doc(cfg(feature = "ratel"))]
pub mod ratel {
// @has 'globuliferous/ratel/fn.ovicide.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
pub fn ovicide() {}
// @has 'globuliferous/ratel/fn.zoonosology.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate features ratel and zoonosology'
#[doc(cfg(feature = "zoonosology"))]
pub fn zoonosology() {}
// @has 'globuliferous/ratel/constant.DIAGRAPHICS.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
pub const DIAGRAPHICS: () = ();
// @has 'globuliferous/ratel/constant.YUSHO.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate features ratel and yusho'
#[doc(cfg(feature = "yusho"))]
pub const YUSHO: () = ();
// @has 'globuliferous/ratel/static.KEYBUGLE.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
pub static KEYBUGLE: () = ();
// @has 'globuliferous/ratel/static.NUNCIATIVE.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate features ratel and nunciative'
#[doc(cfg(feature = "nunciative"))]
pub static NUNCIATIVE: () = ();
// @has 'globuliferous/ratel/type.Wrick.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
pub type Wrick = ();
// @has 'globuliferous/ratel/type.Thionic.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate features ratel and thionic'
#[doc(cfg(feature = "thionic"))]
pub type Thionic = ();
// @has 'globuliferous/ratel/struct.Eventration.html'
// @count - '//*[@class="stab portability"]' 1
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
pub struct Eventration;
// @has 'globuliferous/ratel/struct.Zincic.html'
// @count - '//*[@class="stab portability"]' 2
// @matches - '//*[@class="stab portability"]' 'crate features ratel and zincic'
// @matches - '//*[@class="stab portability"]' 'crate feature rutherford'
#[doc(cfg(feature = "zincic"))]
pub struct Zincic {
pub rectigrade: (),
#[doc(cfg(feature = "rutherford"))]
pub rutherford: (),
}
// @has 'globuliferous/ratel/enum.Cosmotellurian.html'
// @count - '//*[@class="stab portability"]' 10
// @matches - '//*[@class="stab portability"]' 'crate features ratel and cosmotellurian'
// @matches - '//*[@class="stab portability"]' 'crate feature biotaxy'
// @matches - '//*[@class="stab portability"]' 'crate feature xiphopagus'
// @matches - '//*[@class="stab portability"]' 'crate feature juxtapositive'
// @matches - '//*[@class="stab portability"]' 'crate feature fuero'
// @matches - '//*[@class="stab portability"]' 'crate feature palaeophile'
// @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
// @matches - '//*[@class="stab portability"]' 'crate features broadcloth and xanthocomic'
// @matches - '//*[@class="stab portability"]' 'crate feature broadcloth'
// @matches - '//*[@class="stab portability"]' 'crate features broadcloth and whosoever'
#[doc(cfg(feature = "cosmotellurian"))]
pub enum Cosmotellurian {
Groundsel {
jagger: (),
#[doc(cfg(feature = "xiphopagus"))]
xiphopagus: (),
},
#[doc(cfg(feature = "biotaxy"))]
Biotaxy {
glossography: (),
#[doc(cfg(feature = "juxtapositive"))]
juxtapositive: (),
},
}
impl Cosmotellurian {
pub fn uxoricide() {}
#[doc(cfg(feature = "fuero"))]
pub fn fuero() {}
pub const MAMELLE: () = ();
#[doc(cfg(feature = "palaeophile"))]
pub const PALAEOPHILE: () = ();
}
#[doc(cfg(feature = "broadcloth"))]
impl Cosmotellurian {
pub fn trabeculated() {}
#[doc(cfg(feature = "xanthocomic"))]
pub fn xanthocomic() {}
pub const BRACHIFEROUS: () = ();
#[doc(cfg(feature = "whosoever"))]
pub const WHOSOEVER: () = ();
}
// @has 'globuliferous/ratel/trait.Gnotobiology.html'
// @count - '//*[@class="stab portability"]' 4
// @matches - '//*[@class="stab portability"]' 'crate feature ratel'
// @matches - '//*[@class="stab portability"]' 'crate feature unzymotic'
// @matches - '//*[@class="stab portability"]' 'crate feature summate'
// @matches - '//*[@class="stab portability"]' 'crate feature unctuous'
pub trait Gnotobiology {
const XYLOTHERAPY: ();
#[doc(cfg(feature = "unzymotic"))]
const UNZYMOTIC: ();
type Lepadoid;
#[doc(cfg(feature = "summate"))]
type Summate;
fn decalcomania();
#[doc(cfg(feature = "unctuous"))]
fn unctuous();
}
// @has 'globuliferous/ratel/trait.Aposiopesis.html'
// @count - '//*[@class="stab portability"]' 4
// @matches - '//*[@class="stab portability"]' 'crate features ratel and aposiopesis'
// @matches - '//*[@class="stab portability"]' 'crate feature umbracious'
// @matches - '//*[@class="stab portability"]' 'crate feature uakari'
// @matches - '//*[@class="stab portability"]' 'crate feature rotograph'
#[doc(cfg(feature = "aposiopesis"))]
pub trait Aposiopesis {
const REDHIBITION: ();
#[doc(cfg(feature = "umbracious"))]
const UMBRACIOUS: ();
type Ophthalmoscope;
#[doc(cfg(feature = "uakari"))]
type Uakari;
fn meseems();
#[doc(cfg(feature = "rotograph"))]
fn rotograph();
}
}

View File

@ -10,9 +10,8 @@ pub struct Portable;
// @has doc_cfg/unix_only/index.html \
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
// 'This is supported on Unix only.'
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix\Z'
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix and ARM\Z'
// @count - '//*[@class="stab portability"]' 3
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AARM\Z'
// @count - '//*[@class="stab portability"]' 2
#[doc(cfg(unix))]
pub mod unix_only {
// @has doc_cfg/unix_only/fn.unix_only_function.html \
@ -26,7 +25,7 @@ pub mod unix_only {
// @has doc_cfg/unix_only/trait.ArmOnly.html \
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
// 'This is supported on Unix and ARM only.'
// @count - '//*[@class="stab portability"]' 3
// @count - '//*[@class="stab portability"]' 2
#[doc(cfg(target_arch = "arm"))]
pub trait ArmOnly {
fn unix_and_arm_only_function();

View File

@ -14,45 +14,41 @@
pub struct Foo;
// @has 'foo/bar/index.html'
// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync$'
// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only'
// @has 'foo/bar/struct.Bar.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
#[doc(cfg(feature = "sync"))]
pub mod bar {
// @has 'foo/bar/struct.Bar.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
#[doc(cfg(feature = "sync"))]
pub struct Bar;
}
// @has 'foo/baz/index.html'
// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send$'
// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate features `sync` and `send` only'
// @has 'foo/baz/struct.Baz.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
#[doc(cfg(all(feature = "sync", feature = "send")))]
pub mod baz {
// @has 'foo/baz/struct.Baz.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
#[doc(cfg(feature = "sync"))]
pub struct Baz;
}
// @has 'foo/qux/struct.Qux.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
// @has 'foo/qux/index.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
#[doc(cfg(feature = "sync"))]
pub mod qux {
// @has 'foo/qux/struct.Qux.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
#[doc(cfg(all(feature = "sync", feature = "send")))]
pub struct Qux;
}
// @has 'foo/quux/index.html'
// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send and foo and bar$'
// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` and crate feature `send` and `foo` and `bar` only'
// @has 'foo/quux/struct.Quux.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo only.'
#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
pub mod quux {
// @has 'foo/quux/struct.Quux.html'
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.'
#[doc(cfg(all(feature = "send", feature = "sync", bar)))]
pub struct Quux;
}

View File

@ -1,13 +1,16 @@
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/arg-count-mismatch.rs:5:28
|
LL | fn f(x: isize) { }
| -------------- defined here
LL |
LL | fn main() { let i: (); i = f(); }
| ^-- supplied 0 arguments
| |
| expected 1 argument
|
note: function defined here
--> $DIR/arg-count-mismatch.rs:3:4
|
LL | fn f(x: isize) { }
| ^ --------
error: aborting due to previous error

View File

@ -3,8 +3,6 @@
#![feature(or_patterns)]
#![feature(box_patterns)]
#![feature(move_ref_pattern)]
enum Test {
Foo,
Bar,

View File

@ -1,5 +1,5 @@
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:40:9
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:38:9
|
LL | ref foo @ [.., ref mut bar] => (),
| -------^^^^^^^^-----------^
@ -8,7 +8,7 @@ LL | ref foo @ [.., ref mut bar] => (),
| immutable borrow, by `foo`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:124:9
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:122:9
|
LL | ref foo @ Some(box ref mut s) => (),
| -------^^^^^^^^^^^^---------^
@ -17,7 +17,7 @@ LL | ref foo @ Some(box ref mut s) => (),
| immutable borrow, by `foo`, occurs here
error[E0382]: borrow of moved value: `x`
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:22:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:20:5
|
LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
| - move occurs because `x` has type `[String; 4]`, which does not implement the `Copy` trait
@ -29,7 +29,7 @@ LL | &x;
| ^^ value borrowed here after move
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:32:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:30:5
|
LL | ref mut foo @ [.., _] => Some(foo),
| --------------------- mutable borrow occurs here
@ -41,7 +41,7 @@ LL | drop(r);
| - mutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:54:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:52:5
|
LL | [ref foo @ .., ref bar] => Some(foo),
| ------------ immutable borrow occurs here
@ -53,7 +53,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:66:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:64:5
|
LL | ref foo @ [.., ref bar] => Some(foo),
| ----------------------- immutable borrow occurs here
@ -65,7 +65,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0382]: borrow of moved value: `x`
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:80:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:78:5
|
LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
| - move occurs because `x` has type `Option<Test>`, which does not implement the `Copy` trait
@ -80,7 +80,7 @@ LL | &x;
| ^^ value borrowed here after move
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:90:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:88:5
|
LL | ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
| ------------------------------------- immutable borrow occurs here
@ -92,7 +92,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:102:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:100:5
|
LL | ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
| ----------------------------------------- mutable borrow occurs here
@ -104,7 +104,7 @@ LL | drop(r);
| - mutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:116:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:114:5
|
LL | ref foo @ Some(box ref s) => Some(foo),
| ------------------------- immutable borrow occurs here
@ -116,7 +116,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0382]: borrow of moved value: `x`
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:138:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:136:5
|
LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
| - move occurs because `x` has type `[Option<Test>; 4]`, which does not implement the `Copy` trait
@ -131,7 +131,7 @@ LL | &x;
| ^^ value borrowed here after move
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:148:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:146:5
|
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
| ------------------------------------------------- immutable borrow occurs here
@ -143,7 +143,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:160:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:158:5
|
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
| ---------- immutable borrow occurs here
@ -155,7 +155,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:174:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:172:5
|
LL | [_, ref a @ Some(box ref b), ..] => Some(a),
| ----------------------- immutable borrow occurs here
@ -167,7 +167,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:190:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:188:5
|
LL | [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
| ------------------------------------------- immutable borrow occurs here
@ -179,7 +179,7 @@ LL | drop(r);
| - immutable borrow later used here
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:204:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:202:5
|
LL | [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
| ----------------------------------------------- mutable borrow occurs here
@ -191,7 +191,7 @@ LL | drop(r);
| - mutable borrow later used here
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:218:5
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:216:5
|
LL | ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
| ------------------------------------------------------------ immutable borrow occurs here

View File

@ -7,24 +7,30 @@ LL | fn printf(_: *const u8, ...);
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
--> $DIR/variadic-ffi-1.rs:17:9
|
LL | fn foo(f: isize, x: u8, ...);
| ----------------------------- defined here
...
LL | foo();
| ^^^-- supplied 0 arguments
| |
| expected at least 2 arguments
|
note: function defined here
--> $DIR/variadic-ffi-1.rs:10:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^
error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
--> $DIR/variadic-ffi-1.rs:18:9
|
LL | fn foo(f: isize, x: u8, ...);
| ----------------------------- defined here
...
LL | foo(1);
| ^^^ - supplied 1 argument
| |
| expected at least 2 arguments
|
note: function defined here
--> $DIR/variadic-ffi-1.rs:10:8
|
LL | fn foo(f: isize, x: u8, ...);
| ^^^
error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:20:56

View File

@ -2,7 +2,7 @@ error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-no-fixed-args.rs:2:12
|
LL | fn foo(...);
| ^^^^
| ^^^
error: aborting due to previous error

View File

@ -7,8 +7,6 @@
// edition:2018
// ignore-wasm32-bare compiled with panic=abort by default
#![feature(move_ref_pattern)]
#![allow(unused)]
use std::{

View File

@ -2,7 +2,6 @@
// ignore-wasm32-bare compiled with panic=abort by default
#![feature(generators, generator_trait, untagged_unions)]
#![feature(move_ref_pattern)]
#![feature(bindings_after_at)]
#![allow(unused_assignments)]

View File

@ -1,11 +0,0 @@
#![feature(bindings_after_at)]
fn main() {
let x = Some("s".to_string());
match x {
op_string @ Some(s) => {},
//~^ ERROR E0007
//~| ERROR E0382
None => {},
}
}

View File

@ -1,22 +0,0 @@
error[E0007]: cannot bind by-move with sub-bindings
--> $DIR/E0007.rs:6:9
|
LL | op_string @ Some(s) => {},
| ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
error[E0382]: use of moved value
--> $DIR/E0007.rs:6:26
|
LL | let x = Some("s".to_string());
| - move occurs because `x` has type `Option<String>`, which does not implement the `Copy` trait
LL | match x {
LL | op_string @ Some(s) => {},
| -----------------^-
| | |
| | value used here after move
| value moved here
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0007, E0382.
For more information about an error, try `rustc --explain E0007`.

View File

@ -1,13 +1,16 @@
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
--> $DIR/E0060.rs:6:14
|
LL | fn printf(_: *const u8, ...) -> u32;
| ------------------------------------ defined here
...
LL | unsafe { printf(); }
| ^^^^^^-- supplied 0 arguments
| |
| expected at least 1 argument
|
note: function defined here
--> $DIR/E0060.rs:2:8
|
LL | fn printf(_: *const u8, ...) -> u32;
| ^^^^^^
error: aborting due to previous error

View File

@ -1,24 +1,30 @@
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/E0061.rs:6:5
|
LL | fn f(a: u16, b: &str) {}
| --------------------- defined here
...
LL | f(0);
| ^ - supplied 1 argument
| |
| expected 2 arguments
|
note: function defined here
--> $DIR/E0061.rs:1:4
|
LL | fn f(a: u16, b: &str) {}
| ^ ------ -------
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/E0061.rs:10:5
|
LL | fn f2(a: u16) {}
| ------------- defined here
...
LL | f2();
| ^^-- supplied 0 arguments
| |
| expected 1 argument
|
note: function defined here
--> $DIR/E0061.rs:3:4
|
LL | fn f2(a: u16) {}
| ^^ ------
error: aborting due to 2 previous errors

View File

@ -1,16 +1,16 @@
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/issue-58451.rs:12:9
|
LL | / fn f<I>(i: I)
LL | | where
LL | | I: IntoIterator,
LL | | I::Item: for<'a> Into<&'a ()>,
| |__________________________________- defined here
...
LL | f(&[f()]);
| ^-- supplied 0 arguments
| |
| expected 1 argument
LL | f(&[f()]);
| ^-- supplied 0 arguments
| |
| expected 1 argument
|
note: function defined here
--> $DIR/issue-58451.rs:5:4
|
LL | fn f<I>(i: I)
| ^ ----
error: aborting due to previous error

View File

@ -1,13 +1,16 @@
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/issue-18819.rs:16:5
|
LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
| ----------------------------------------------- defined here
...
LL | print_x(X);
| ^^^^^^^ - supplied 1 argument
| |
| expected 2 arguments
|
note: function defined here
--> $DIR/issue-18819.rs:11:4
|
LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
| ^^^^^^^ ---------------------- -----------
error: aborting due to previous error

View File

@ -4,11 +4,14 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
LL | $other(None)
| ---- supplied 1 argument
...
LL | fn some_function() {}
| ------------------ defined here
...
LL | some_macro!(some_function);
| ^^^^^^^^^^^^^ expected 0 arguments
|
note: function defined here
--> $DIR/issue-26094.rs:7:4
|
LL | fn some_function() {}
| ^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -1,13 +1,16 @@
error[E0061]: this function takes 1 argument but 2 arguments were supplied
--> $DIR/issue-4935.rs:5:13
|
LL | fn foo(a: usize) {}
| ---------------- defined here
LL |
LL | fn main() { foo(5, 6) }
| ^^^ - - supplied 2 arguments
| |
| expected 1 argument
|
note: function defined here
--> $DIR/issue-4935.rs:3:4
|
LL | fn foo(a: usize) {}
| ^^^ --------
error: aborting due to previous error

View File

@ -1,35 +1,44 @@
error[E0061]: this function takes 0 arguments but 1 argument was supplied
--> $DIR/method-call-err-msg.rs:13:7
|
LL | fn zero(self) -> Foo { self }
| -------------------- defined here
...
LL | x.zero(0)
| ^^^^ - supplied 1 argument
| |
| expected 0 arguments
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:5:8
|
LL | fn zero(self) -> Foo { self }
| ^^^^ ----
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/method-call-err-msg.rs:14:7
|
LL | fn one(self, _: isize) -> Foo { self }
| ----------------------------- defined here
...
LL | .one()
| ^^^- supplied 0 arguments
| |
| expected 1 argument
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:6:8
|
LL | fn one(self, _: isize) -> Foo { self }
| ^^^ ---- --------
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> $DIR/method-call-err-msg.rs:15:7
|
LL | fn two(self, _: isize, _: isize) -> Foo { self }
| --------------------------------------- defined here
...
LL | .two(0);
| ^^^ - supplied 1 argument
| |
| expected 2 arguments
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:7:8
|
LL | fn two(self, _: isize, _: isize) -> Foo { self }
| ^^^ ---- -------- --------
error[E0599]: no method named `take` found for struct `Foo` in the current scope
--> $DIR/method-call-err-msg.rs:19:7
@ -53,13 +62,16 @@ LL | .take()
error[E0061]: this function takes 3 arguments but 0 arguments were supplied
--> $DIR/method-call-err-msg.rs:21:7
|
LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
| ------------------------------------------ defined here
...
LL | y.three::<usize>();
| ^^^^^--------- supplied 0 arguments
| |
| expected 3 arguments
|
note: associated function defined here
--> $DIR/method-call-err-msg.rs:8:8
|
LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
| ^^^^^ ---- ---- ---- ----
error: aborting due to 5 previous errors

View File

@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/issue-38371.rs:4:8
|
LL | fn foo(&foo: Foo) {
| ^^^^------
| ^^^^-----
| | |
| | expected due to this
| expected struct `Foo`, found reference

View File

@ -6,7 +6,26 @@ fn foo(a: isize, b: isize, c: isize, d:isize) {
panic!();
}
// Check that all arguments are shown in the error message, even if they're across multiple lines.
fn bar(
a: i32,
b: i32,
c: i32,
d: i32,
e: i32,
f: i32,
) {
println!("{}", a);
println!("{}", b);
println!("{}", c);
println!("{}", d);
println!("{}", e);
println!("{}", f);
}
fn main() {
foo(1, 2, 3);
//~^ ERROR this function takes 4 arguments but 3
bar(1, 2, 3);
//~^ ERROR this function takes 6 arguments but 3
}

View File

@ -1,14 +1,43 @@
error[E0061]: this function takes 4 arguments but 3 arguments were supplied
--> $DIR/not-enough-arguments.rs:10:3
--> $DIR/not-enough-arguments.rs:27:3
|
LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
| --------------------------------------------- defined here
...
LL | foo(1, 2, 3);
| ^^^ - - - supplied 3 arguments
| |
| expected 4 arguments
|
note: function defined here
--> $DIR/not-enough-arguments.rs:5:4
|
LL | fn foo(a: isize, b: isize, c: isize, d:isize) {
| ^^^ -------- -------- -------- -------
error: aborting due to previous error
error[E0061]: this function takes 6 arguments but 3 arguments were supplied
--> $DIR/not-enough-arguments.rs:29:3
|
LL | bar(1, 2, 3);
| ^^^ - - - supplied 3 arguments
| |
| expected 6 arguments
|
note: function defined here
--> $DIR/not-enough-arguments.rs:10:4
|
LL | fn bar(
| ^^^
LL | a: i32,
| ------
LL | b: i32,
| ------
LL | c: i32,
| ------
LL | d: i32,
| ------
LL | e: i32,
| ------
LL | f: i32,
| ------
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0061`.

View File

@ -2,205 +2,205 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
|
LL | fn f1_1(x: isize, ...) {}
| ^^^^
| ^^^
error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
LL | fn f1_2(...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
LL | fn f1_2(...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
LL | extern "C" fn f2_1(x: isize, ...) {}
| ^^^^
| ^^^
error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
LL | extern "C" fn f2_2(...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
LL | extern "C" fn f2_2(...) {}
| ^^^^
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
LL | extern "C" fn f2_3(..., x: isize) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
LL | extern "C" fn f2_3(..., x: isize) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
|
LL | extern fn f3_1(x: isize, ...) {}
| ^^^^
| ^^^
error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
LL | extern fn f3_2(...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
LL | extern fn f3_2(...) {}
| ^^^^
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
LL | extern fn f3_3(..., x: isize) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
LL | extern fn f3_3(..., x: isize) {}
| ^^^^
| ^^^
error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
|
LL | fn e_f1(...);
| ^^^^
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
|
LL | fn e_f2(..., x: isize);
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
|
LL | fn i_f1(x: isize, ...) {}
| ^^^^
| ^^^
error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
LL | fn i_f2(...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
LL | fn i_f2(...) {}
| ^^^^
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
LL | fn i_f3(..., x: isize, ...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
LL | fn i_f3(..., x: isize, ...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
|
LL | fn i_f3(..., x: isize, ...) {}
| ^^^^
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
LL | fn i_f4(..., x: isize, ...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
LL | fn i_f4(..., x: isize, ...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
|
LL | fn i_f4(..., x: isize, ...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
|
LL | fn t_f1(x: isize, ...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
|
LL | fn t_f2(x: isize, ...);
| ^^^^
| ^^^
error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
LL | fn t_f3(...) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
LL | fn t_f3(...) {}
| ^^^^
| ^^^
error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
LL | fn t_f4(...);
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
LL | fn t_f4(...);
| ^^^^
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
LL | fn t_f5(..., x: isize) {}
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
LL | fn t_f5(..., x: isize) {}
| ^^^^
| ^^^
error: `...` must be the last argument of a C-variadic function
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
LL | fn t_f6(..., x: isize);
| ^^^^
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
LL | fn t_f6(..., x: isize);
| ^^^^
| ^^^
error: aborting due to 34 previous errors

View File

@ -3,7 +3,6 @@
// where one side is by-ref and the other is by-move.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
struct X {
x: (),

View File

@ -1,5 +1,5 @@
error: cannot move out of value because it is borrowed
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:15:14
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:14:14
|
LL | Some(ref _y @ _z) => {}
| ------^^^--
@ -8,7 +8,7 @@ LL | Some(ref _y @ _z) => {}
| value borrowed, by `_y`, here
error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:14
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:14
|
LL | Some(_z @ ref _y) => {}
| --^^^------
@ -18,7 +18,7 @@ LL | Some(_z @ ref _y) => {}
| move occurs because `_z` has type `X` which does not implement the `Copy` trait
error: cannot move out of value because it is borrowed
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:29:14
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:28:14
|
LL | Some(ref mut _y @ _z) => {}
| ----------^^^--
@ -27,7 +27,7 @@ LL | Some(ref mut _y @ _z) => {}
| value borrowed, by `_y`, here
error: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:14
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:14
|
LL | Some(_z @ ref mut _y) => {}
| --^^^----------
@ -37,7 +37,7 @@ LL | Some(_z @ ref mut _y) => {}
| move occurs because `_z` has type `X` which does not implement the `Copy` trait
error[E0382]: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:19
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:20:19
|
LL | Some(_z @ ref _y) => {}
| -----^^^^^^
@ -52,7 +52,7 @@ LL | Some(ref _z @ ref _y) => {}
| ^^^
error[E0382]: borrow of moved value
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:19
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:34:19
|
LL | Some(_z @ ref mut _y) => {}
| -----^^^^^^^^^^

View File

@ -1,7 +1,6 @@
// See issue #12534.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
fn main() {}

View File

@ -1,5 +1,5 @@
error[E0382]: use of moved value
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:10:12
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:12
|
LL | fn f(a @ A(u): A) -> Box<u8> {
| ------^-

View File

@ -1,7 +1,6 @@
// Test that moving on both sides of an `@` pattern is not allowed.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
fn main() {
struct U; // Not copy!

View File

@ -1,5 +1,5 @@
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:14:13
--> $DIR/borrowck-move-and-move.rs:13:13
|
LL | let a @ b = U;
| ----^ - move occurs because value has type `U`, which does not implement the `Copy` trait
@ -8,7 +8,7 @@ LL | let a @ b = U;
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:16:17
--> $DIR/borrowck-move-and-move.rs:15:17
|
LL | let a @ (b, c) = (U, U);
| --------^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@ -17,7 +17,7 @@ LL | let a @ (b, c) = (U, U);
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:18:17
--> $DIR/borrowck-move-and-move.rs:17:17
|
LL | let a @ (b, c) = (u(), u());
| --------^- ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@ -26,7 +26,7 @@ LL | let a @ (b, c) = (u(), u());
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:21:16
--> $DIR/borrowck-move-and-move.rs:20:16
|
LL | match Ok(U) {
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
@ -37,7 +37,7 @@ LL | a @ Ok(b) | a @ Err(b) => {}
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:21:29
--> $DIR/borrowck-move-and-move.rs:20:29
|
LL | match Ok(U) {
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
@ -48,7 +48,7 @@ LL | a @ Ok(b) | a @ Err(b) => {}
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:28:22
--> $DIR/borrowck-move-and-move.rs:27:22
|
LL | match [u(), u(), u(), u()] {
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
@ -59,7 +59,7 @@ LL | xs @ [a, .., b] => {}
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:32:18
--> $DIR/borrowck-move-and-move.rs:31:18
|
LL | match [u(), u(), u(), u()] {
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
@ -70,7 +70,7 @@ LL | xs @ [_, ys @ .., _] => {}
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:25:16
--> $DIR/borrowck-move-and-move.rs:24:16
|
LL | fn fun(a @ b: U) {}
| ----^

View File

@ -3,7 +3,6 @@
// Test `@` patterns combined with `box` patterns.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
#![feature(box_patterns)]
#[derive(Copy, Clone)]

View File

@ -1,7 +1,6 @@
// Test `@` patterns combined with `box` patterns.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
#![feature(box_patterns)]
#[derive(Copy, Clone)]

View File

@ -1,5 +1,5 @@
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-at-and-box.rs:37:9
--> $DIR/borrowck-pat-at-and-box.rs:36:9
|
LL | let ref a @ box b = Box::new(NC);
| -----^^^^^^^-
@ -8,7 +8,7 @@ LL | let ref a @ box b = Box::new(NC);
| value borrowed, by `a`, here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:39:9
--> $DIR/borrowck-pat-at-and-box.rs:38:9
|
LL | let ref a @ box ref mut b = Box::new(nc());
| -----^^^^^^^---------
@ -17,7 +17,7 @@ LL | let ref a @ box ref mut b = Box::new(nc());
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:41:9
--> $DIR/borrowck-pat-at-and-box.rs:40:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
@ -26,7 +26,7 @@ LL | let ref a @ box ref mut b = Box::new(NC);
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:43:9
--> $DIR/borrowck-pat-at-and-box.rs:42:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
@ -35,7 +35,7 @@ LL | let ref a @ box ref mut b = Box::new(NC);
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:46:9
--> $DIR/borrowck-pat-at-and-box.rs:45:9
|
LL | let ref a @ box ref mut b = Box::new(NC);
| -----^^^^^^^---------
@ -44,7 +44,7 @@ LL | let ref a @ box ref mut b = Box::new(NC);
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:52:9
--> $DIR/borrowck-pat-at-and-box.rs:51:9
|
LL | let ref mut a @ box ref b = Box::new(NC);
| ---------^^^^^^^-----
@ -53,7 +53,7 @@ LL | let ref mut a @ box ref b = Box::new(NC);
| mutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:66:9
--> $DIR/borrowck-pat-at-and-box.rs:65:9
|
LL | ref mut a @ box ref b => {
| ---------^^^^^^^-----
@ -62,7 +62,7 @@ LL | ref mut a @ box ref b => {
| mutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:58:11
--> $DIR/borrowck-pat-at-and-box.rs:57:11
|
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
| ---------^^^^^^^-----
@ -71,7 +71,7 @@ LL | fn f5(ref mut a @ box ref b: Box<NC>) {
| mutable borrow, by `a`, occurs here
error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:21:18
--> $DIR/borrowck-pat-at-and-box.rs:20:18
|
LL | let a @ box &b = Box::new(&C);
| ---------^ ------------ move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
@ -80,7 +80,7 @@ LL | let a @ box &b = Box::new(&C);
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:24:17
--> $DIR/borrowck-pat-at-and-box.rs:23:17
|
LL | let a @ box b = Box::new(C);
| --------^ ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
@ -89,7 +89,7 @@ LL | let a @ box b = Box::new(C);
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:34:17
--> $DIR/borrowck-pat-at-and-box.rs:33:17
|
LL | match Box::new(C) {
| ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
@ -100,7 +100,7 @@ LL | a @ box b => {}
| value moved here
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-at-and-box.rs:46:21
--> $DIR/borrowck-pat-at-and-box.rs:45:21
|
LL | let ref a @ box ref mut b = Box::new(NC);
| ------------^^^^^^^^^
@ -112,7 +112,7 @@ LL | drop(a);
| - immutable borrow later used here
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:52:25
--> $DIR/borrowck-pat-at-and-box.rs:51:25
|
LL | let ref mut a @ box ref b = Box::new(NC);
| ----------------^^^^^
@ -124,7 +124,7 @@ LL | *a = Box::new(NC);
| -- mutable borrow later used here
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:66:25
--> $DIR/borrowck-pat-at-and-box.rs:65:25
|
LL | ref mut a @ box ref b => {
| ----------------^^^^^
@ -136,7 +136,7 @@ LL | *a = Box::new(NC);
| -- mutable borrow later used here
error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:27:20
--> $DIR/borrowck-pat-at-and-box.rs:26:20
|
LL | fn f1(a @ box &b: Box<&C>) {}
| ---------^
@ -146,7 +146,7 @@ LL | fn f1(a @ box &b: Box<&C>) {}
| move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:30:19
--> $DIR/borrowck-pat-at-and-box.rs:29:19
|
LL | fn f2(a @ box b: Box<C>) {}
| --------^
@ -156,7 +156,7 @@ LL | fn f2(a @ box b: Box<C>) {}
| move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-at-and-box.rs:58:27
--> $DIR/borrowck-pat-at-and-box.rs:57:27
|
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
| ----------------^^^^^

View File

@ -2,7 +2,6 @@
// Currently this logic exists in THIR match checking as opposed to borrowck.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
fn main() {
struct U;

View File

@ -1,5 +1,5 @@
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:9:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:8:9
|
LL | let a @ ref b = U;
| -^^^-----

View File

@ -1,7 +1,6 @@
// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
fn main() {
struct U;

View File

@ -1,5 +1,5 @@
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:28:9
|
LL | let a @ ref b = U;
| -^^^-----
@ -9,7 +9,7 @@ LL | let a @ ref b = U;
| move occurs because `a` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:9
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| -^^^^^^^^^^^^---------^^^^^^-----^
@ -20,7 +20,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:14
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:14
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| -----^^^---------
@ -30,7 +30,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| move occurs because `b` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:33
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| -^^^-----
@ -40,7 +40,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| move occurs because `d` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:37:9
|
LL | let a @ [ref mut b, ref c] = [U, U];
| -^^^^---------^^-----^
@ -51,7 +51,7 @@ LL | let a @ [ref mut b, ref c] = [U, U];
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:40:9
|
LL | let a @ ref b = u();
| -^^^-----
@ -61,7 +61,7 @@ LL | let a @ ref b = u();
| move occurs because `a` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:9
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| -^^^^^^^^^^^^---------^^^^^^-----^
@ -72,7 +72,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:14
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:14
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| -----^^^---------
@ -82,7 +82,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| move occurs because `b` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:33
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| -^^^-----
@ -92,7 +92,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| move occurs because `d` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:50:9
|
LL | let a @ [ref mut b, ref c] = [u(), u()];
| -^^^^---------^^-----^
@ -103,7 +103,7 @@ LL | let a @ [ref mut b, ref c] = [u(), u()];
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:56:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9
|
LL | a @ Some(ref b) => {}
| -^^^^^^^^-----^
@ -113,7 +113,7 @@ LL | a @ Some(ref b) => {}
| move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:9
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
@ -124,7 +124,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:19
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:19
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| -----^^^---------
@ -134,7 +134,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| move occurs because `b` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:38
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| -^^^-----
@ -144,7 +144,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| move occurs because `d` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:70:9
|
LL | mut a @ Some([ref b, ref mut c]) => {}
| -----^^^^^^^^^-----^^---------^^
@ -155,7 +155,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
| move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:76:9
|
LL | a @ Some(ref b) => {}
| -^^^^^^^^-----^
@ -165,7 +165,7 @@ LL | a @ Some(ref b) => {}
| move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:9
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
@ -176,7 +176,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:19
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:19
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| -----^^^---------
@ -186,7 +186,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| move occurs because `b` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:38
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| -^^^-----
@ -196,7 +196,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| move occurs because `d` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:9
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:92:9
|
LL | mut a @ Some([ref b, ref mut c]) => {}
| -----^^^^^^^^^-----^^---------^^
@ -207,7 +207,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
| move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:13:11
|
LL | fn f1(a @ ref b: U) {}
| -^^^-----
@ -217,7 +217,7 @@ LL | fn f1(a @ ref b: U) {}
| move occurs because `a` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:11
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:11
|
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| -----^^^^^^^^-----^^^^^^^^^^-----^
@ -228,7 +228,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:20
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:20
|
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| -^^^-----
@ -238,7 +238,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| move occurs because `b` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:31
|
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| -----^^^-----
@ -248,7 +248,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| move occurs because `d` has type `U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:11
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:11
|
LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
| -^^^^---------^^-----^
@ -259,7 +259,7 @@ LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:22
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:22
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| --------^^^^^^^^^
@ -270,7 +270,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
error[E0382]: use of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:33
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| ------------------------^^^^^^^^^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@ -279,7 +279,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:37
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:30:37
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
| ----^^^^^
@ -290,7 +290,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:25
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:37:25
|
LL | let a @ [ref mut b, ref c] = [U, U];
| ----------------^^^^^- ------ move occurs because value has type `[U; 2]`, which does not implement the `Copy` trait
@ -299,7 +299,7 @@ LL | let a @ [ref mut b, ref c] = [U, U];
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:13
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:40:13
|
LL | let a @ ref b = u();
| ----^^^^^ --- move occurs because value has type `U`, which does not implement the `Copy` trait
@ -308,7 +308,7 @@ LL | let a @ ref b = u();
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:22
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:22
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| --------^^^^^^^^^
@ -319,7 +319,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
error[E0382]: use of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:33
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| ------------------------^^^^^^^^^- ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@ -328,7 +328,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:37
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:43:37
|
LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
| ----^^^^^
@ -339,7 +339,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:25
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:50:25
|
LL | let a @ [ref mut b, ref c] = [u(), u()];
| ----------------^^^^^- ---------- move occurs because value has type `[U; 2]`, which does not implement the `Copy` trait
@ -348,7 +348,7 @@ LL | let a @ [ref mut b, ref c] = [u(), u()];
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:27
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:27
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| --------^^^^^^^^^
@ -363,7 +363,7 @@ LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
| ^^^
error[E0382]: use of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:38
|
LL | match Some((U, U)) {
| ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
@ -374,7 +374,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:42
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:42
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| ----^^^^^
@ -389,7 +389,7 @@ LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
| ^^^
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:30
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:70:30
|
LL | match Some([U, U]) {
| ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
@ -400,7 +400,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:18
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:76:18
|
LL | match Some(u()) {
| --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait
@ -411,7 +411,7 @@ LL | a @ Some(ref b) => {}
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:27
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:27
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| --------^^^^^^^^^
@ -426,7 +426,7 @@ LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
| ^^^
error[E0382]: use of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:38
|
LL | match Some((u(), u())) {
| ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
@ -437,7 +437,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:42
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:82:42
|
LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {}
| ----^^^^^
@ -452,7 +452,7 @@ LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
| ^^^
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:30
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:92:30
|
LL | match Some([u(), u()]) {
| ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
@ -463,7 +463,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {}
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:15
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:13:15
|
LL | fn f1(a @ ref b: U) {}
| ----^^^^^
@ -473,7 +473,7 @@ LL | fn f1(a @ ref b: U) {}
| move occurs because value has type `U`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:24
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:24
|
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| ----^^^^^
@ -484,7 +484,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
error[E0382]: use of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:31
|
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| --------------------^^^^^^^^^^^^^-
@ -494,7 +494,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:39
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:17:39
|
LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
| --------^^^^^
@ -505,7 +505,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:27
--> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:27
|
LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
| ----------------^^^^^-

View File

@ -1,7 +1,6 @@
// Test that `ref mut? @ pat_with_by_move_bindings` is prevented.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
fn main() {
struct U;

View File

@ -1,5 +1,5 @@
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:23:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:22:9
|
LL | let ref a @ b = U;
| -----^^^-
@ -8,7 +8,7 @@ LL | let ref a @ b = U;
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:25:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:24:9
|
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@ -18,7 +18,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:25:18
--> $DIR/borrowck-pat-by-move-and-ref.rs:24:18
|
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| -----^^^-----
@ -27,7 +27,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| value borrowed, by `b`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:25:33
--> $DIR/borrowck-pat-by-move-and-ref.rs:24:33
|
LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| -----^^^-
@ -36,7 +36,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
| value borrowed, by `d`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:29:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:28:9
|
LL | let ref mut a @ [b, mut c] = [U, U];
| ---------^^^^-^^-----^
@ -46,7 +46,7 @@ LL | let ref mut a @ [b, mut c] = [U, U];
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:31:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
|
LL | let ref a @ b = u();
| -----^^^-
@ -55,7 +55,7 @@ LL | let ref a @ b = u();
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:32:9
|
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@ -65,7 +65,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:33:18
--> $DIR/borrowck-pat-by-move-and-ref.rs:32:18
|
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| -----^^^-----
@ -74,7 +74,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| value borrowed, by `b`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:33:33
--> $DIR/borrowck-pat-by-move-and-ref.rs:32:33
|
LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| -----^^^-
@ -83,7 +83,7 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
| value borrowed, by `d`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:37:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:36:9
|
LL | let ref mut a @ [b, mut c] = [u(), u()];
| ---------^^^^-^^-----^
@ -93,7 +93,7 @@ LL | let ref mut a @ [b, mut c] = [u(), u()];
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:41:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:40:9
|
LL | ref a @ Some(b) => {}
| -----^^^^^^^^-^
@ -102,7 +102,7 @@ LL | ref a @ Some(b) => {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:46:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:45:9
|
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
@ -112,7 +112,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:46:23
--> $DIR/borrowck-pat-by-move-and-ref.rs:45:23
|
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-----
@ -121,7 +121,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| value borrowed, by `b`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:46:38
--> $DIR/borrowck-pat-by-move-and-ref.rs:45:38
|
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-
@ -130,7 +130,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| value borrowed, by `d`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:53:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:52:9
|
LL | ref mut a @ Some([b, mut c]) => {}
| ---------^^^^^^^^^-^^-----^^
@ -140,7 +140,7 @@ LL | ref mut a @ Some([b, mut c]) => {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:58:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:57:9
|
LL | ref a @ Some(b) => {}
| -----^^^^^^^^-^
@ -149,7 +149,7 @@ LL | ref a @ Some(b) => {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:63:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:62:9
|
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
@ -159,7 +159,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:63:23
--> $DIR/borrowck-pat-by-move-and-ref.rs:62:23
|
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-----
@ -168,7 +168,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| value borrowed, by `b`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:63:38
--> $DIR/borrowck-pat-by-move-and-ref.rs:62:38
|
LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| -----^^^-
@ -177,7 +177,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {}
| value borrowed, by `d`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:70:9
--> $DIR/borrowck-pat-by-move-and-ref.rs:69:9
|
LL | ref mut a @ Some([b, mut c]) => {}
| ---------^^^^^^^^^-^^-----^^
@ -187,7 +187,7 @@ LL | ref mut a @ Some([b, mut c]) => {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
--> $DIR/borrowck-pat-by-move-and-ref.rs:13:11
|
LL | fn f1(ref a @ b: U) {}
| -----^^^-
@ -196,7 +196,7 @@ LL | fn f1(ref a @ b: U) {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:16:11
--> $DIR/borrowck-pat-by-move-and-ref.rs:15:11
|
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| -----^^^^^^^^^^^^-----^^^^^^^^^^-^
@ -206,7 +206,7 @@ LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:16:20
--> $DIR/borrowck-pat-by-move-and-ref.rs:15:20
|
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| -----^^^-----
@ -215,7 +215,7 @@ LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| value borrowed, by `b`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:16:35
--> $DIR/borrowck-pat-by-move-and-ref.rs:15:35
|
LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| -----^^^-
@ -224,7 +224,7 @@ LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
| value borrowed, by `d`, here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
--> $DIR/borrowck-pat-by-move-and-ref.rs:19:11
|
LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
| ---------^^^^-^^-----^

View File

@ -1,5 +1,4 @@
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
enum Option<T> {
None,

View File

@ -1,5 +1,5 @@
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9
|
LL | ref mut z @ &mut Some(ref a) => {
| ---------^^^^^^^^^^^^^-----^
@ -8,7 +8,7 @@ LL | ref mut z @ &mut Some(ref a) => {
| mutable borrow, by `z`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:34:9
|
LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
| ---------^^^^-----------------^
@ -18,7 +18,7 @@ LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:22
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:34:22
|
LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
| -----^^^---------
@ -27,7 +27,7 @@ LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
| immutable borrow, by `b`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:38:9
|
LL | let ref a @ ref mut b = U;
| -----^^^---------
@ -36,7 +36,7 @@ LL | let ref a @ ref mut b = U;
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:40:9
|
LL | let ref mut a @ ref b = U;
| ---------^^^-----
@ -45,7 +45,7 @@ LL | let ref mut a @ ref b = U;
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:42:9
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
@ -55,7 +55,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9
|
LL | let ref mut a @ (ref b, ref c) = (U, U);
| ---------^^^^-----^^-----^
@ -65,7 +65,7 @@ LL | let ref mut a @ (ref b, ref c) = (U, U);
| mutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:47:9
|
LL | let ref mut a @ ref b = u();
| ---------^^^-----
@ -74,7 +74,7 @@ LL | let ref mut a @ ref b = u();
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:52:9
|
LL | let ref a @ ref mut b = u();
| -----^^^---------
@ -83,7 +83,7 @@ LL | let ref a @ ref mut b = u();
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:58:9
|
LL | let ref mut a @ ref b = U;
| ---------^^^-----
@ -92,7 +92,7 @@ LL | let ref mut a @ ref b = U;
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:63:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:62:9
|
LL | let ref a @ ref mut b = U;
| -----^^^---------
@ -101,7 +101,7 @@ LL | let ref a @ ref mut b = U;
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:68:9
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
| ---------^^^^^^-----^
@ -110,7 +110,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
| mutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:33
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:68:33
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
| ---------^^^^^^^-----^
@ -119,7 +119,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:9
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| -----^^^^^^---------^
@ -128,7 +128,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:33
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:33
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| -----^^^^^^^---------^
@ -137,7 +137,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:9
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
| -----^^^^^^---------^
@ -146,7 +146,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:33
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:33
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
| -----^^^^^^^---------^
@ -155,7 +155,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:9
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
| ---------^^^^^^-----^
@ -164,7 +164,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
| mutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:33
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
| ---------^^^^^^^-----^
@ -173,7 +173,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:9
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| -----^^^^^^---------^
@ -182,7 +182,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:33
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| -----^^^^^^^---------^
@ -191,7 +191,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:9
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
| ---------^^^^^^-----^
@ -200,7 +200,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
| mutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:33
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:33
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
| ---------^^^^^^^-----^
@ -209,7 +209,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:118:9
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
@ -219,7 +219,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
@ -229,7 +229,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:9
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| -----^^^^---------^^---------^
@ -239,7 +239,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:136:9
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:135:9
|
LL | let ref mut a @ (ref b, ref c) = (U, U);
| ---------^^^^-----^^-----^
@ -249,7 +249,7 @@ LL | let ref mut a @ (ref b, ref c) = (U, U);
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
|
LL | fn f1(ref a @ ref mut b: U) {}
| -----^^^---------
@ -258,7 +258,7 @@ LL | fn f1(ref a @ ref mut b: U) {}
| immutable borrow, by `a`, occurs here
error: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
|
LL | fn f2(ref mut a @ ref b: U) {}
| ---------^^^-----
@ -267,7 +267,7 @@ LL | fn f2(ref mut a @ ref b: U) {}
| mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11
|
LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
| -----^^^^^^^^^^^----------------^^^^^^^^
@ -276,7 +276,7 @@ LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
| immutable borrow, by `a`, occurs here
error: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:22
|
LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
| -----^^^-------------
@ -286,7 +286,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
| immutable borrow, by `a`, occurs here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:30
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:30:30
|
LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
| ---------^^^-
@ -295,7 +295,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {}
| value borrowed, by `b`, here
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31
|
LL | ref mut z @ &mut Some(ref a) => {
| ----------------------^^^^^-
@ -307,7 +307,7 @@ LL | **z = None;
| ---------- mutable borrow later used here
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:21
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:47:21
|
LL | let ref mut a @ ref b = u();
| ------------^^^^^
@ -319,7 +319,7 @@ LL | *a = u();
| -------- mutable borrow later used here
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:17
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:52:17
|
LL | let ref a @ ref mut b = u();
| --------^^^^^^^^^
@ -331,7 +331,7 @@ LL | drop(a);
| - immutable borrow later used here
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:20
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:20
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| -----------^^^^^^^^^-
@ -343,7 +343,7 @@ LL | drop(a);
| - immutable borrow later used here
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:45
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:77:45
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| ------------^^^^^^^^^-
@ -355,7 +355,7 @@ LL | drop(a);
| - immutable borrow later used here
error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:61
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:88:61
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
| ^^^^^^ cannot assign
@ -363,7 +363,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
= note: variables bound in patterns are immutable until the end of the pattern guard
error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:95:61
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
| ^^^^^^^^^^^ cannot assign
@ -371,7 +371,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
= note: variables bound in patterns are immutable until the end of the pattern guard
error[E0507]: cannot move out of `b` in pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:66
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@ -379,7 +379,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error[E0507]: cannot move out of `b` in pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:102:66
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@ -387,7 +387,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error[E0507]: cannot move out of `a` in pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:66
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
| ^ move occurs because `a` has type `&mut std::result::Result<U, U>`, which does not implement the `Copy` trait
@ -395,7 +395,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error[E0507]: cannot move out of `a` in pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:110:66
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
| ^ move occurs because `a` has type `&mut std::result::Result<U, U>`, which does not implement the `Copy` trait
@ -403,7 +403,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:18
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:18
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| ---------^^^^^^^^^------------
@ -415,7 +415,7 @@ LL | drop(a);
| - immutable borrow later used here
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:29
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:29
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| --------------------^^^^^^^^^-
@ -427,7 +427,7 @@ LL | drop(a);
| - immutable borrow later used here
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:18
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:18
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| ---------^^^^^^^^^------------
@ -439,7 +439,7 @@ LL | drop(a);
| - immutable borrow later used here
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:29
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:130:29
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| --------------------^^^^^^^^^-

View File

@ -1,7 +1,6 @@
// Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
fn main() {
struct U;

View File

@ -1,5 +1,5 @@
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:28:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:27:9
|
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
@ -8,7 +8,7 @@ LL | let ref mut a @ ref mut b = U;
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:32:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
|
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
@ -17,7 +17,7 @@ LL | let ref mut a @ ref mut b = U;
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:35:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:34:9
|
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
@ -26,7 +26,7 @@ LL | let ref mut a @ ref mut b = U;
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:38:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:37:9
|
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
@ -35,7 +35,7 @@ LL | let ref mut a @ ref mut b = U;
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:42:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:41:9
|
LL | let ref mut a @ ref mut b = U;
| ---------^^^---------
@ -44,7 +44,7 @@ LL | let ref mut a @ ref mut b = U;
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:46:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:45:9
|
LL | let ref mut a @ (
| ^--------
@ -66,7 +66,7 @@ LL | | ) = (U, [U, U, U]);
| |_____^
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:56:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:55:9
|
LL | let ref mut a @ (
| ^--------
@ -88,7 +88,7 @@ LL | | ) = (u(), [u(), u(), u()]);
| |_________^
error: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:66:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:65:9
|
LL | let a @ (ref mut b, ref mut c) = (U, U);
| -^^^^---------^^---------^
@ -99,7 +99,7 @@ LL | let a @ (ref mut b, ref mut c) = (U, U);
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:69:9
|
LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
| -^^^^-^^^-^^-^^
@ -111,7 +111,7 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
| move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:73:9
|
LL | let a @ &mut ref mut b = &mut U;
| -^^^^^^^^---------
@ -121,7 +121,7 @@ LL | let a @ &mut ref mut b = &mut U;
| move occurs because `a` has type `&mut U` which does not implement the `Copy` trait
error: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:77:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:76:9
|
LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
| -^^^^^^^^^---------^^---------^
@ -132,7 +132,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
| move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:81:9
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
@ -141,7 +141,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:82:37
--> $DIR/borrowck-pat-ref-mut-twice.rs:81:37
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
@ -150,7 +150,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:88:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:87:9
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
@ -159,7 +159,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:88:37
--> $DIR/borrowck-pat-ref-mut-twice.rs:87:37
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
@ -168,7 +168,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:9
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
@ -177,7 +177,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:37
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:37
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
@ -186,7 +186,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:9
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^---------^
@ -195,7 +195,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:37
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:37
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------^^^^^^^---------^
@ -204,7 +204,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:11:11
--> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
|
LL | fn f1(ref mut a @ ref mut b: U) {}
| ---------^^^---------
@ -213,7 +213,7 @@ LL | fn f1(ref mut a @ ref mut b: U) {}
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:13:11
--> $DIR/borrowck-pat-ref-mut-twice.rs:12:11
|
LL | fn f2(ref mut a @ ref mut b: U) {}
| ---------^^^---------
@ -222,7 +222,7 @@ LL | fn f2(ref mut a @ ref mut b: U) {}
| first mutable borrow, by `a`, occurs here
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:16:9
--> $DIR/borrowck-pat-ref-mut-twice.rs:15:9
|
LL | ref mut a @ [
| ^--------
@ -240,7 +240,7 @@ LL | | ] : [[U; 4]; 5]
| |_________^
error: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:24:22
--> $DIR/borrowck-pat-ref-mut-twice.rs:23:22
|
LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
| ---------^^^-------------
@ -250,7 +250,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
| first mutable borrow, by `a`, occurs here
error: cannot move out of value because it is borrowed
--> $DIR/borrowck-pat-ref-mut-twice.rs:24:34
--> $DIR/borrowck-pat-ref-mut-twice.rs:23:34
|
LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
| ---------^^^-
@ -259,7 +259,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
| value borrowed, by `b`, here
error[E0499]: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:28:21
--> $DIR/borrowck-pat-ref-mut-twice.rs:27:21
|
LL | let ref mut a @ ref mut b = U;
| ------------^^^^^^^^^
@ -271,7 +271,7 @@ LL | drop(a);
| - first borrow later used here
error[E0499]: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:38:21
--> $DIR/borrowck-pat-ref-mut-twice.rs:37:21
|
LL | let ref mut a @ ref mut b = U;
| ------------^^^^^^^^^
@ -283,7 +283,7 @@ LL | *a = U;
| ------ first borrow later used here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:66:25
--> $DIR/borrowck-pat-ref-mut-twice.rs:65:25
|
LL | let a @ (ref mut b, ref mut c) = (U, U);
| ----------------^^^^^^^^^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
@ -292,7 +292,7 @@ LL | let a @ (ref mut b, ref mut c) = (U, U);
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:70:21
--> $DIR/borrowck-pat-ref-mut-twice.rs:69:21
|
LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
| ------------^-- -------- move occurs because value has type `&mut (U, [U; 2])`, which does not implement the `Copy` trait
@ -301,7 +301,7 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:74:18
--> $DIR/borrowck-pat-ref-mut-twice.rs:73:18
|
LL | let a @ &mut ref mut b = &mut U;
| ---------^^^^^^^^^ ------ move occurs because value has type `&mut U`, which does not implement the `Copy` trait
@ -310,7 +310,7 @@ LL | let a @ &mut ref mut b = &mut U;
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:77:30
--> $DIR/borrowck-pat-ref-mut-twice.rs:76:30
|
LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
| ---------------------^^^^^^^^^- ----------- move occurs because value has type `&mut (U, U)`, which does not implement the `Copy` trait
@ -319,7 +319,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
| value moved here
error[E0499]: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:24
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:24
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------------^^^^^^^^^-
@ -331,7 +331,7 @@ LL | *a = Err(U);
| ----------- first borrow later used here
error[E0499]: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:95:53
--> $DIR/borrowck-pat-ref-mut-twice.rs:94:53
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ----------------^^^^^^^^^-
@ -343,7 +343,7 @@ LL | *a = Err(U);
| ----------- first borrow later used here
error[E0499]: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:24
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:24
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------------^^^^^^^^^-
@ -355,7 +355,7 @@ LL | drop(a);
| - first borrow later used here
error[E0499]: cannot borrow value as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:107:53
--> $DIR/borrowck-pat-ref-mut-twice.rs:106:53
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ----------------^^^^^^^^^-

View File

@ -1,7 +1,6 @@
// Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
#[derive(Copy, Clone)]
struct C;

View File

@ -1,5 +1,5 @@
error[E0382]: use of moved value
--> $DIR/copy-and-move-mixed.rs:12:19
--> $DIR/copy-and-move-mixed.rs:11:19
|
LL | let a @ NC(b, c) = NC(C, C);
| ----------^- -------- move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait
@ -8,7 +8,7 @@ LL | let a @ NC(b, c) = NC(C, C);
| value moved here
error[E0382]: use of moved value
--> $DIR/copy-and-move-mixed.rs:15:19
--> $DIR/copy-and-move-mixed.rs:14:19
|
LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
| ----------^^^^^^^^^^^^- --------------- move occurs because value has type `NC<C, NC<C, C>>`, which does not implement the `Copy` trait
@ -17,7 +17,7 @@ LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
| value moved here
error[E0382]: use of moved value
--> $DIR/copy-and-move-mixed.rs:15:29
--> $DIR/copy-and-move-mixed.rs:14:29
|
LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
| ----------^-

View File

@ -8,7 +8,6 @@
// this would create problems for the generalization aforementioned.
#![feature(bindings_after_at)]
#![feature(move_ref_pattern)]
fn main() {
struct NotCopy;

View File

@ -1,5 +1,5 @@
error: cannot move out of value because it is borrowed
--> $DIR/default-binding-modes-both-sides-independent.rs:28:9
--> $DIR/default-binding-modes-both-sides-independent.rs:27:9
|
LL | let ref a @ b = NotCopy;
| -----^^^-
@ -8,7 +8,7 @@ LL | let ref a @ b = NotCopy;
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/default-binding-modes-both-sides-independent.rs:31:9
--> $DIR/default-binding-modes-both-sides-independent.rs:30:9
|
LL | let ref mut a @ b = NotCopy;
| ---------^^^-
@ -17,7 +17,7 @@ LL | let ref mut a @ b = NotCopy;
| value borrowed, by `a`, here
error: cannot move out of value because it is borrowed
--> $DIR/default-binding-modes-both-sides-independent.rs:36:12
--> $DIR/default-binding-modes-both-sides-independent.rs:35:12
|
LL | Ok(ref a @ b) | Err(b @ ref a) => {
| -----^^^-
@ -26,7 +26,7 @@ LL | Ok(ref a @ b) | Err(b @ ref a) => {
| value borrowed, by `a`, here
error: borrow of moved value
--> $DIR/default-binding-modes-both-sides-independent.rs:36:29
--> $DIR/default-binding-modes-both-sides-independent.rs:35:29
|
LL | Ok(ref a @ b) | Err(b @ ref a) => {
| -^^^-----
@ -36,7 +36,7 @@ LL | Ok(ref a @ b) | Err(b @ ref a) => {
| move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait
error: cannot move out of value because it is borrowed
--> $DIR/default-binding-modes-both-sides-independent.rs:44:9
--> $DIR/default-binding-modes-both-sides-independent.rs:43:9
|
LL | ref a @ b => {
| -----^^^-
@ -45,7 +45,7 @@ LL | ref a @ b => {
| value borrowed, by `a`, here
error[E0505]: cannot move out of value because it is borrowed
--> $DIR/default-binding-modes-both-sides-independent.rs:31:21
--> $DIR/default-binding-modes-both-sides-independent.rs:30:21
|
LL | let ref mut a @ b = NotCopy;
| ------------^

View File

@ -1,7 +1,5 @@
// check-pass
#![feature(move_ref_pattern)]
fn main() {}
struct U;

View File

@ -1,5 +1,3 @@
#![feature(move_ref_pattern)]
fn main() {}
struct U;

View File

@ -1,5 +1,5 @@
error[E0505]: cannot move out of `arr[..]` because it is borrowed
--> $DIR/borrowck-move-ref-pattern.rs:10:24
--> $DIR/borrowck-move-ref-pattern.rs:8:24
|
LL | let hold_all = &arr;
| ---- borrow of `arr` occurs here
@ -10,7 +10,7 @@ LL | drop(hold_all);
| -------- borrow later used here
error[E0384]: cannot assign twice to immutable variable `_x1`
--> $DIR/borrowck-move-ref-pattern.rs:11:5
--> $DIR/borrowck-move-ref-pattern.rs:9:5
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
| ---
@ -21,7 +21,7 @@ LL | _x1 = U;
| ^^^^^^^ cannot assign twice to immutable variable
error[E0505]: cannot move out of `arr[..]` because it is borrowed
--> $DIR/borrowck-move-ref-pattern.rs:13:10
--> $DIR/borrowck-move-ref-pattern.rs:11:10
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
| ------------ borrow of `arr[..]` occurs here
@ -32,7 +32,7 @@ LL | drop(_x0_hold);
| -------- borrow later used here
error[E0502]: cannot borrow `arr[..]` as mutable because it is also borrowed as immutable
--> $DIR/borrowck-move-ref-pattern.rs:15:16
--> $DIR/borrowck-move-ref-pattern.rs:13:16
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
| ---------------- immutable borrow occurs here
@ -44,7 +44,7 @@ LL | drop(xs_hold);
| ------- immutable borrow later used here
error[E0505]: cannot move out of `arr[..]` because it is borrowed
--> $DIR/borrowck-move-ref-pattern.rs:15:29
--> $DIR/borrowck-move-ref-pattern.rs:13:29
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
| ---------------- borrow of `arr[..]` occurs here
@ -56,7 +56,7 @@ LL | drop(xs_hold);
| ------- borrow later used here
error[E0505]: cannot move out of `arr[..]` because it is borrowed
--> $DIR/borrowck-move-ref-pattern.rs:15:34
--> $DIR/borrowck-move-ref-pattern.rs:13:34
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
| ---------------- borrow of `arr[..]` occurs here
@ -68,7 +68,7 @@ LL | drop(xs_hold);
| ------- borrow later used here
error[E0384]: cannot assign twice to immutable variable `_x1`
--> $DIR/borrowck-move-ref-pattern.rs:25:5
--> $DIR/borrowck-move-ref-pattern.rs:23:5
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
| ---
@ -79,7 +79,7 @@ LL | _x1 = U;
| ^^^^^^^ cannot assign twice to immutable variable
error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
--> $DIR/borrowck-move-ref-pattern.rs:26:20
--> $DIR/borrowck-move-ref-pattern.rs:24:20
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
| ------- immutable borrow occurs here
@ -91,7 +91,7 @@ LL | *_x0 = U;
| -------- immutable borrow later used here
error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
--> $DIR/borrowck-move-ref-pattern.rs:27:10
--> $DIR/borrowck-move-ref-pattern.rs:25:10
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
| ------- immutable borrow occurs here
@ -102,7 +102,7 @@ LL | *_x0 = U;
| -------- immutable borrow later used here
error[E0594]: cannot assign to `*_x0` which is behind a `&` reference
--> $DIR/borrowck-move-ref-pattern.rs:28:5
--> $DIR/borrowck-move-ref-pattern.rs:26:5
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
| ------- help: consider changing this to be a mutable reference: `ref mut _x0`
@ -111,7 +111,7 @@ LL | *_x0 = U;
| ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written
error[E0594]: cannot assign to `*_x2` which is behind a `&` reference
--> $DIR/borrowck-move-ref-pattern.rs:29:5
--> $DIR/borrowck-move-ref-pattern.rs:27:5
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
| ------- help: consider changing this to be a mutable reference: `ref mut _x2`
@ -120,7 +120,7 @@ LL | *_x2 = U;
| ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written
error[E0382]: use of moved value: `tup.1`
--> $DIR/borrowck-move-ref-pattern.rs:30:10
--> $DIR/borrowck-move-ref-pattern.rs:28:10
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
| --- value moved here
@ -131,7 +131,7 @@ LL | drop(tup.1);
= note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
error[E0382]: borrow of moved value: `tup.1`
--> $DIR/borrowck-move-ref-pattern.rs:31:20
--> $DIR/borrowck-move-ref-pattern.rs:29:20
|
LL | drop(tup.1);
| ----- value moved here
@ -141,7 +141,7 @@ LL | let _x1_hold = &tup.1;
= note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-move-ref-pattern.rs:33:20
--> $DIR/borrowck-move-ref-pattern.rs:31:20
|
LL | let (.., ref mut _x3) = tup;
| ----------- mutable borrow occurs here
@ -152,7 +152,7 @@ LL | drop(_x3);
| --- mutable borrow later used here
error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
--> $DIR/borrowck-move-ref-pattern.rs:34:20
--> $DIR/borrowck-move-ref-pattern.rs:32:20
|
LL | let (.., ref mut _x3) = tup;
| ----------- first mutable borrow occurs here
@ -164,7 +164,7 @@ LL | drop(_x3);
| --- first borrow later used here
error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
--> $DIR/borrowck-move-ref-pattern.rs:35:14
--> $DIR/borrowck-move-ref-pattern.rs:33:14
|
LL | let (.., ref mut _x3) = tup;
| ----------- first mutable borrow occurs here
@ -176,7 +176,7 @@ LL | drop(_x3);
| --- first borrow later used here
error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-move-ref-pattern.rs:36:14
--> $DIR/borrowck-move-ref-pattern.rs:34:14
|
LL | let (.., ref mut _x3) = tup;
| ----------- mutable borrow occurs here
@ -187,7 +187,7 @@ LL | drop(_x3);
| --- mutable borrow later used here
error[E0382]: use of moved value: `tup`
--> $DIR/borrowck-move-ref-pattern.rs:45:14
--> $DIR/borrowck-move-ref-pattern.rs:43:14
|
LL | let mut tup = (U, U, U);
| ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait

View File

@ -4,7 +4,6 @@
// check-pass
#![feature(move_ref_pattern)]
#![feature(bindings_after_at)]
fn main() {

View File

@ -1,23 +0,0 @@
fn main() {
#[derive(Clone)]
struct X {
x: (),
}
let mut tup = (X { x: () }, X { x: () });
match Some(tup.clone()) {
Some((y, ref z)) => {}
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
None => panic!(),
}
let (ref a, b) = tup.clone();
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
let (a, mut b) = &tup;
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
//~| ERROR cannot move out of a shared reference
let (mut a, b) = &mut tup;
//~^ ERROR binding by-move and by-ref in the same pattern is unstable
//~| ERROR cannot move out of a mutable reference
}

View File

@ -1,66 +0,0 @@
error[E0658]: binding by-move and by-ref in the same pattern is unstable
--> $DIR/feature-gate-move_ref_pattern.rs:8:15
|
LL | Some((y, ref z)) => {}
| ^ ----- by-ref pattern here
| |
| by-move pattern here
|
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
error[E0658]: binding by-move and by-ref in the same pattern is unstable
--> $DIR/feature-gate-move_ref_pattern.rs:13:17
|
LL | let (ref a, b) = tup.clone();
| ----- ^ by-move pattern here
| |
| by-ref pattern here
|
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
error[E0658]: binding by-move and by-ref in the same pattern is unstable
--> $DIR/feature-gate-move_ref_pattern.rs:16:13
|
LL | let (a, mut b) = &tup;
| - ^^^^^ by-move pattern here
| |
| by-ref pattern here
|
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
error[E0658]: binding by-move and by-ref in the same pattern is unstable
--> $DIR/feature-gate-move_ref_pattern.rs:20:10
|
LL | let (mut a, b) = &mut tup;
| ^^^^^ - by-ref pattern here
| |
| by-move pattern here
|
= note: see issue #68354 <https://github.com/rust-lang/rust/issues/68354> for more information
= help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable
error[E0507]: cannot move out of a shared reference
--> $DIR/feature-gate-move_ref_pattern.rs:16:22
|
LL | let (a, mut b) = &tup;
| ----- ^^^^
| |
| data moved here
| move occurs because `b` has type `X`, which does not implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/feature-gate-move_ref_pattern.rs:20:22
|
LL | let (mut a, b) = &mut tup;
| ----- ^^^^^^^^
| |
| data moved here
| move occurs because `a` has type `X`, which does not implement the `Copy` trait
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0507, E0658.
For more information about an error, try `rustc --explain E0507`.

View File

@ -1,7 +1,5 @@
// check-pass
#![feature(move_ref_pattern)]
enum E {
Foo(String, String, String),
}

View File

@ -1,5 +1,3 @@
#![feature(move_ref_pattern)]
fn main() {
struct S; // Not `Copy`.

View File

@ -1,5 +1,5 @@
error[E0382]: borrow of moved value: `tup0`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:31:10
|
LL | let mut tup0 = (S, S);
| -------- move occurs because `tup0` has type `(S, S)`, which does not implement the `Copy` trait
@ -14,7 +14,7 @@ LL | drop(&tup0);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup1`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:32:10
|
LL | let mut tup1 = (S, S, S);
| -------- move occurs because `tup1` has type `(S, S, S)`, which does not implement the `Copy` trait
@ -29,7 +29,7 @@ LL | drop(&tup1);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup2`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:35:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10
|
LL | let tup2 = (S, S);
| ---- move occurs because `tup2` has type `(S, S)`, which does not implement the `Copy` trait
@ -44,7 +44,7 @@ LL | drop(&tup2);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup3`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:36:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10
|
LL | let tup3 = (S, S, S);
| ---- move occurs because `tup3` has type `(S, S, S)`, which does not implement the `Copy` trait
@ -59,7 +59,7 @@ LL | drop(&tup3);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup4`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:39:10
|
LL | let tup4 = (S, S);
| ---- move occurs because `tup4` has type `(S, S)`, which does not implement the `Copy` trait
@ -74,7 +74,7 @@ LL | drop(&tup4.0);
| ^^^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr0`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10
|
LL | let mut arr0 = [S, S, S];
| -------- move occurs because `arr0` has type `[S; 3]`, which does not implement the `Copy` trait
@ -89,7 +89,7 @@ LL | drop(&arr0);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr1`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36
--> $DIR/move-ref-patterns-closure-captures-inside.rs:42:36
|
LL | let mut arr1 = [S, S, S, S, S];
| -------- move occurs because `arr1` has type `[S; 5]`, which does not implement the `Copy` trait
@ -104,7 +104,7 @@ LL | let [_, mov1, mov2, mov3, _] = &arr1;
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr2`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:45:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10
|
LL | let arr2 = [S, S, S];
| ---- move occurs because `arr2` has type `[S; 3]`, which does not implement the `Copy` trait
@ -119,7 +119,7 @@ LL | drop(&arr2);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr3`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:46:36
--> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36
|
LL | let arr3 = [S, S, S, S, S];
| ---- move occurs because `arr3` has type `[S; 5]`, which does not implement the `Copy` trait
@ -134,7 +134,7 @@ LL | let [_, mov1, mov2, mov3, _] = &arr3;
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup0`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:75:10
|
LL | let mut tup0: Option<(S, S)> = None;
| -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@ -148,7 +148,7 @@ LL | drop(&tup0);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup1`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:76:10
|
LL | let mut tup1: Option<(S, S, S)> = None;
| -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@ -163,7 +163,7 @@ LL | drop(&tup1);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup2`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:79:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10
|
LL | let tup2: Option<(S, S)> = None;
| ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@ -178,7 +178,7 @@ LL | drop(&tup2);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup3`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10
|
LL | let tup3: Option<(S, S, S)> = None;
| ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@ -193,7 +193,7 @@ LL | drop(&tup3);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup4`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:81:21
--> $DIR/move-ref-patterns-closure-captures-inside.rs:79:21
|
LL | let tup4: Option<(S, S)> = None;
| ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@ -208,7 +208,7 @@ LL | m!((ref x, _) = &tup4);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr0`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10
|
LL | let mut arr0: Option<[S; 3]> = None;
| -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@ -223,7 +223,7 @@ LL | drop(&arr0);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr1`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35
--> $DIR/move-ref-patterns-closure-captures-inside.rs:81:35
|
LL | let mut arr1: Option<[S; 5]> = None;
| -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
@ -238,7 +238,7 @@ LL | m!([_, mov1, mov2, mov3, _] = &arr1);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr2`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:84:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10
|
LL | let arr2: Option<[S; 3]> = None;
| ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@ -253,7 +253,7 @@ LL | drop(&arr2);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr3`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:85:35
--> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35
|
LL | let arr3: Option<[S; 5]> = None;
| ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
@ -267,7 +267,7 @@ LL | m!([_, mov1, mov2, mov3, _] = &arr3);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup0`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:111:10
|
LL | let mut tup0: Option<(S, S)> = None;
| -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@ -281,7 +281,7 @@ LL | drop(&tup0);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup1`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:112:10
|
LL | let mut tup1: Option<(S, S, S)> = None;
| -------- move occurs because `tup1` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@ -296,7 +296,7 @@ LL | drop(&tup1);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup2`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:115:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10
|
LL | let tup2: Option<(S, S)> = None;
| ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@ -311,7 +311,7 @@ LL | drop(&tup2);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup3`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10
|
LL | let tup3: Option<(S, S, S)> = None;
| ---- move occurs because `tup3` has type `Option<(S, S, S)>`, which does not implement the `Copy` trait
@ -326,7 +326,7 @@ LL | drop(&tup3);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `tup4`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:117:21
--> $DIR/move-ref-patterns-closure-captures-inside.rs:115:21
|
LL | let tup4: Option<(S, S)> = None;
| ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
@ -341,7 +341,7 @@ LL | m!((ref x, _) = &tup4);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr0`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10
|
LL | let mut arr0: Option<[S; 3]> = None;
| -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@ -356,7 +356,7 @@ LL | drop(&arr0);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr1`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35
--> $DIR/move-ref-patterns-closure-captures-inside.rs:117:35
|
LL | let mut arr1: Option<[S; 5]> = None;
| -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
@ -371,7 +371,7 @@ LL | m!([_, mov1, mov2, mov3, _] = &arr1);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr2`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:120:10
--> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10
|
LL | let arr2: Option<[S; 3]> = None;
| ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
@ -386,7 +386,7 @@ LL | drop(&arr2);
| ^^^^^ value borrowed here after move
error[E0382]: borrow of moved value: `arr3`
--> $DIR/move-ref-patterns-closure-captures-inside.rs:121:35
--> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35
|
LL | let arr3: Option<[S; 5]> = None;
| ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait

View File

@ -1,7 +1,5 @@
// check-pass
#![feature(move_ref_pattern)]
fn main() {
struct U;
fn accept_fn_once(_: impl FnOnce()) {}

View File

@ -1,5 +1,3 @@
#![feature(move_ref_pattern)]
fn main() {
struct U;
fn accept_fn_once(_: &impl FnOnce()) {}

View File

@ -1,5 +1,5 @@
error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
--> $DIR/move-ref-patterns-closure-captures.rs:11:14
--> $DIR/move-ref-patterns-closure-captures.rs:9:14
|
LL | let c1 = || {
| ^^ this closure implements `FnOnce`, not `FnMut`
@ -11,7 +11,7 @@ LL | accept_fn_mut(&c1);
| ------------- the requirement to implement `FnMut` derives from here
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
--> $DIR/move-ref-patterns-closure-captures.rs:11:14
--> $DIR/move-ref-patterns-closure-captures.rs:9:14
|
LL | let c1 = || {
| ^^ this closure implements `FnOnce`, not `Fn`
@ -23,7 +23,7 @@ LL | accept_fn(&c1);
| --------- the requirement to implement `Fn` derives from here
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
--> $DIR/move-ref-patterns-closure-captures.rs:22:14
--> $DIR/move-ref-patterns-closure-captures.rs:20:14
|
LL | let c2 = || {
| ^^ this closure implements `FnMut`, not `Fn`

View File

@ -1,5 +1,3 @@
#![feature(move_ref_pattern)]
fn main() {
struct U;

Some files were not shown because too many files have changed in this diff Show More