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:
commit
b6e2dc6cde
121 changed files with 2898 additions and 2295 deletions
|
@ -1258,9 +1258,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||||
// If backtraces are enabled, also print the query stack
|
// If backtraces are enabled, also print the query stack
|
||||||
let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
|
let backtrace = env::var_os("RUST_BACKTRACE").map(|x| &x != "0").unwrap_or(false);
|
||||||
|
|
||||||
if backtrace {
|
let num_frames = if backtrace { None } else { Some(2) };
|
||||||
TyCtxt::try_print_query_stack(&handler);
|
|
||||||
}
|
TyCtxt::try_print_query_stack(&handler, num_frames);
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -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
|
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
|
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
|
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:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0007
|
```compile_fail,E0382
|
||||||
|
#![feature(bindings_after_at)]
|
||||||
|
|
||||||
let x = Some("s".to_string());
|
let x = Some("s".to_string());
|
||||||
|
|
||||||
match x {
|
match x {
|
||||||
op_string @ Some(s) => {}, // error: cannot bind by-move with sub-bindings
|
op_string @ Some(s) => {}, // error: use of moved value
|
||||||
None => {},
|
None => {},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -270,6 +270,9 @@ declare_features! (
|
||||||
(accepted, track_caller, "1.46.0", Some(47809), None),
|
(accepted, track_caller, "1.46.0", Some(47809), None),
|
||||||
/// Allows `#[doc(alias = "...")]`.
|
/// Allows `#[doc(alias = "...")]`.
|
||||||
(accepted, doc_alias, "1.48.0", Some(50146), None),
|
(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
|
// feature-group-end: accepted features
|
||||||
|
|
|
@ -526,10 +526,6 @@ declare_features! (
|
||||||
/// For example, you can write `x @ Some(y)`.
|
/// For example, you can write `x @ Some(y)`.
|
||||||
(active, bindings_after_at, "1.41.0", Some(65490), None),
|
(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.
|
/// Allows `impl const Trait for T` syntax.
|
||||||
(active, const_trait_impl, "1.42.0", Some(67792), None),
|
(active, const_trait_impl, "1.42.0", Some(67792), None),
|
||||||
|
|
||||||
|
|
|
@ -2742,4 +2742,32 @@ impl<'hir> Node<'hir> {
|
||||||
_ => None,
|
_ => 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,17 @@ impl<'tcx> Instance<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> 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]
|
#[inline]
|
||||||
|
|
|
@ -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:");
|
eprintln!("query stack during panic:");
|
||||||
|
|
||||||
// Be careful reyling on global state here: this code is called from
|
// 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
|
// a panic hook, which means that the global `Handler` may be in a weird
|
||||||
// state if it was responsible for triggering the panic.
|
// state if it was responsible for triggering the panic.
|
||||||
|
let mut i = 0;
|
||||||
ty::tls::with_context_opt(|icx| {
|
ty::tls::with_context_opt(|icx| {
|
||||||
if let Some(icx) = icx {
|
if let Some(icx) = icx {
|
||||||
let query_map = icx.tcx.queries.try_collect_active_jobs();
|
let query_map = icx.tcx.queries.try_collect_active_jobs();
|
||||||
|
|
||||||
let mut current_query = icx.query;
|
let mut current_query = icx.query;
|
||||||
let mut i = 0;
|
|
||||||
|
|
||||||
while let Some(query) = current_query {
|
while let Some(query) = current_query {
|
||||||
|
if Some(i) == num_frames {
|
||||||
|
break;
|
||||||
|
}
|
||||||
let query_info =
|
let query_info =
|
||||||
if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) {
|
if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) {
|
||||||
info
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ use crate::mir::interpret::{sign_extend, truncate};
|
||||||
use crate::ty::fold::TypeFolder;
|
use crate::ty::fold::TypeFolder;
|
||||||
use crate::ty::layout::IntegerExt;
|
use crate::ty::layout::IntegerExt;
|
||||||
use crate::ty::query::TyCtxtAt;
|
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::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_apfloat::Float as _;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
|
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
|
||||||
|
@ -509,20 +509,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
Some(ty::Binder::bind(env_ty))
|
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.
|
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
|
||||||
pub fn is_static(self, def_id: DefId) -> bool {
|
pub fn is_static(self, def_id: DefId) -> bool {
|
||||||
self.static_mutability(def_id).is_some()
|
self.static_mutability(def_id).is_some()
|
||||||
|
|
|
@ -71,13 +71,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
|
||||||
hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
|
hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
|
||||||
};
|
};
|
||||||
self.check_irrefutable(&loc.pat, msg, sp);
|
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>) {
|
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
||||||
intravisit::walk_param(self, param);
|
intravisit::walk_param(self, param);
|
||||||
self.check_irrefutable(¶m.pat, "function argument", None);
|
self.check_irrefutable(¶m.pat, "function argument", None);
|
||||||
self.check_patterns(false, ¶m.pat);
|
self.check_patterns(¶m.pat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,10 +119,7 @@ impl PatCtxt<'_, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MatchVisitor<'_, 'tcx> {
|
impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||||
fn check_patterns(&mut self, has_guard: bool, pat: &Pat<'_>) {
|
fn check_patterns(&mut self, pat: &Pat<'_>) {
|
||||||
if !self.tcx.features().move_ref_pattern {
|
|
||||||
check_legality_of_move_bindings(self, has_guard, pat);
|
|
||||||
}
|
|
||||||
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
|
pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
|
||||||
if !self.tcx.features().bindings_after_at {
|
if !self.tcx.features().bindings_after_at {
|
||||||
check_legality_of_bindings_in_at_patterns(self, pat);
|
check_legality_of_bindings_in_at_patterns(self, pat);
|
||||||
|
@ -165,7 +162,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||||
) {
|
) {
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
// Check the arm for some things unrelated to exhaustiveness.
|
// 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);
|
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)
|
!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.
|
/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
|
||||||
///
|
///
|
||||||
/// For example, this would reject:
|
/// For example, this would reject:
|
||||||
|
|
|
@ -246,11 +246,7 @@ impl<'a> Parser<'a> {
|
||||||
this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
|
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,
|
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
|
||||||
// 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);
|
|
||||||
lhs = match op {
|
lhs = match op {
|
||||||
AssocOp::Add
|
AssocOp::Add
|
||||||
| AssocOp::Subtract
|
| AssocOp::Subtract
|
||||||
|
@ -411,7 +407,7 @@ impl<'a> Parser<'a> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let rhs_span = rhs.as_ref().map_or(cur_op_span, |x| x.span);
|
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 =
|
let limits =
|
||||||
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed };
|
||||||
Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new()))
|
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,
|
expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
|
||||||
) -> PResult<'a, P<Expr>> {
|
) -> PResult<'a, P<Expr>> {
|
||||||
let mk_expr = |this: &mut Self, rhs: P<Ty>| {
|
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
|
// 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> {
|
pub(super) fn mk_expr_err(&self, span: Span) -> P<Expr> {
|
||||||
self.mk_expr(span, ExprKind::Err, AttrVec::new())
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1744,7 +1744,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let span = lo.to(self.token.span);
|
let span = lo.until(self.token.span);
|
||||||
|
|
||||||
Ok(Param {
|
Ok(Param {
|
||||||
attrs: attrs.into(),
|
attrs: attrs.into(),
|
||||||
|
|
|
@ -115,7 +115,6 @@ fn get_symbol_hash<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// also include any type parameters (for generic items)
|
// also include any type parameters (for generic items)
|
||||||
assert!(!substs.has_erasable_regions());
|
|
||||||
substs.hash_stable(&mut hcx, &mut hasher);
|
substs.hash_stable(&mut hcx, &mut hasher);
|
||||||
|
|
||||||
if let Some(instantiating_crate) = instantiating_crate {
|
if let Some(instantiating_crate) = instantiating_crate {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
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};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
|
||||||
const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
|
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);
|
let def_id = tcx.hir().local_def_id(hir_id);
|
||||||
for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
|
for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
|
||||||
if tcx.sess.check_name(attr, SYMBOL_NAME) {
|
if tcx.sess.check_name(attr, SYMBOL_NAME) {
|
||||||
// for now, can only use on monomorphic names
|
let def_id = def_id.to_def_id();
|
||||||
let instance = Instance::mono(tcx, 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);
|
let mangled = tcx.symbol_name(instance);
|
||||||
tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled));
|
tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled));
|
||||||
if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) {
|
if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) {
|
||||||
|
|
|
@ -259,7 +259,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_impl_path(
|
fn print_impl_path(
|
||||||
self,
|
mut self,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
substs: &'tcx [GenericArg<'tcx>],
|
substs: &'tcx [GenericArg<'tcx>],
|
||||||
mut self_ty: Ty<'tcx>,
|
mut self_ty: Ty<'tcx>,
|
||||||
|
@ -284,12 +284,37 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.path_append_impl(
|
self.push(match impl_trait_ref {
|
||||||
|cx| cx.print_def_path(parent_def_id, &[]),
|
Some(_) => "X",
|
||||||
&key.disambiguated_data,
|
None => "M",
|
||||||
self_ty,
|
});
|
||||||
impl_trait_ref,
|
|
||||||
)
|
// 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> {
|
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);
|
self.push_ident(&name);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_qualified(
|
fn path_qualified(
|
||||||
mut self,
|
mut self,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
|
@ -552,24 +578,16 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_append_impl(
|
fn path_append_impl(
|
||||||
mut self,
|
self,
|
||||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
_: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||||
disambiguated_data: &DisambiguatedDefPathData,
|
_: &DisambiguatedDefPathData,
|
||||||
self_ty: Ty<'tcx>,
|
_: Ty<'tcx>,
|
||||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
_: Option<ty::TraitRef<'tcx>>,
|
||||||
) -> Result<Self::Path, Self::Error> {
|
) -> Result<Self::Path, Self::Error> {
|
||||||
self.push(match trait_ref {
|
// Inlined into `print_impl_path`
|
||||||
Some(_) => "X",
|
unreachable!()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_append(
|
fn path_append(
|
||||||
self,
|
self,
|
||||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
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[..]),
|
name.as_ref().map_or("", |s| &s[..]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path_generic_args(
|
fn path_generic_args(
|
||||||
mut self,
|
mut self,
|
||||||
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
|
||||||
|
|
|
@ -285,10 +285,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let (fn_sig, def_span) = match *callee_ty.kind() {
|
let (fn_sig, def_id) = match *callee_ty.kind() {
|
||||||
ty::FnDef(def_id, _) => {
|
ty::FnDef(def_id, _) => (callee_ty.fn_sig(self.tcx), Some(def_id)),
|
||||||
(callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id))
|
|
||||||
}
|
|
||||||
ty::FnPtr(sig) => (sig, None),
|
ty::FnPtr(sig) => (sig, None),
|
||||||
ref t => {
|
ref t => {
|
||||||
let mut unit_variant = None;
|
let mut unit_variant = None;
|
||||||
|
@ -427,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
arg_exprs,
|
arg_exprs,
|
||||||
fn_sig.c_variadic,
|
fn_sig.c_variadic,
|
||||||
TupleArgumentsFlag::DontTupleArguments,
|
TupleArgumentsFlag::DontTupleArguments,
|
||||||
def_span,
|
def_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn_sig.output()
|
fn_sig.output()
|
||||||
|
|
|
@ -19,7 +19,7 @@ use rustc_middle::ty::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::{sym, Ident};
|
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 rustc_trait_selection::traits::{self, ObligationCauseCode};
|
||||||
|
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
args_no_rcvr,
|
args_no_rcvr,
|
||||||
method.sig.c_variadic,
|
method.sig.c_variadic,
|
||||||
tuple_arguments,
|
tuple_arguments,
|
||||||
self.tcx.hir().span_if_local(method.def_id),
|
Some(method.def_id),
|
||||||
);
|
);
|
||||||
method.sig.output()
|
method.sig.output()
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
args: &'tcx [hir::Expr<'tcx>],
|
args: &'tcx [hir::Expr<'tcx>],
|
||||||
c_variadic: bool,
|
c_variadic: bool,
|
||||||
tuple_arguments: TupleArgumentsFlag,
|
tuple_arguments: TupleArgumentsFlag,
|
||||||
def_span: Option<Span>,
|
def_id: Option<DefId>,
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
// Grab the argument types, supplying fresh type variables
|
// 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)) {
|
if let Some(def_id) = def_id {
|
||||||
err.span_label(def_s, "defined here");
|
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 {
|
if sugg_unit {
|
||||||
let sugg_span = tcx.sess.source_map().end_point(expr.span);
|
let sugg_span = tcx.sess.source_map().end_point(expr.span);
|
||||||
// remove closing `)` from the span
|
// remove closing `)` from the span
|
||||||
|
|
|
@ -257,8 +257,13 @@ impl<K, V> Root<K, V> {
|
||||||
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
|
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
|
||||||
/// `NodeRef` could be pointing to either type of node.
|
/// `NodeRef` could be pointing to either type of node.
|
||||||
pub struct NodeRef<BorrowType, K, V, Type> {
|
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,
|
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>>,
|
node: NonNull<LeafNode<K, V>>,
|
||||||
_marker: PhantomData<(BorrowType, Type)>,
|
_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) }
|
unsafe { usize::from((*self.as_leaf_ptr()).len) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the height of this node in the whole tree. Zero height denotes the
|
/// Returns the height of this node with respect to the leaf level. Zero height means the
|
||||||
/// leaf level.
|
/// node is a leaf itself.
|
||||||
pub fn height(&self) -> usize {
|
pub fn height(&self) -> usize {
|
||||||
self.height
|
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,
|
// to avoid aliasing with outstanding references to other elements,
|
||||||
// in particular, those returned to the caller in earlier iterations.
|
// in particular, those returned to the caller in earlier iterations.
|
||||||
let leaf = self.node.as_ptr();
|
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.
|
// We must coerce to unsized array pointers because of Rust issue #74679.
|
||||||
let keys: *const [_] = unsafe { &raw const (*leaf).keys };
|
let keys: *const [_] = keys;
|
||||||
let vals: *mut [_] = unsafe { &raw mut (*leaf).vals };
|
let vals: *mut [_] = vals;
|
||||||
// SAFETY: The keys and values of a node must always be initialized up to length.
|
// 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 key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() };
|
||||||
let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() };
|
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
|
impl<BorrowType, K, V, NodeType, HandleType> PartialEq
|
||||||
for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
|
for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
|
||||||
{
|
{
|
||||||
fn eq(&self, other: &Self) -> bool {
|
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>
|
for Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType>
|
||||||
{
|
{
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use core::cmp::Ordering::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_splitpoint() {
|
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]
|
#[test]
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn test_sizes() {
|
fn test_sizes() {
|
||||||
|
|
|
@ -1082,7 +1082,7 @@ extern "rust-intrinsic" {
|
||||||
/// If the actual type neither requires drop glue nor implements
|
/// If the actual type neither requires drop glue nor implements
|
||||||
/// `Copy`, then the return value of this function is unspecified.
|
/// `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")]
|
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
|
||||||
pub fn needs_drop<T>() -> bool;
|
pub fn needs_drop<T>() -> bool;
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,8 @@
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(std_internals)]
|
#![feature(std_internals)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
#![feature(str_split_as_str)]
|
||||||
|
#![feature(str_split_inclusive_as_str)]
|
||||||
#![feature(transparent_unions)]
|
#![feature(transparent_unions)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(unsized_locals)]
|
#![feature(unsized_locals)]
|
||||||
|
|
|
@ -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! {
|
generate_pattern_iterators! {
|
||||||
|
@ -710,6 +721,48 @@ generate_pattern_iterators! {
|
||||||
delegate double ended;
|
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! {
|
generate_pattern_iterators! {
|
||||||
forward:
|
forward:
|
||||||
/// Created with the method [`split_terminator`].
|
/// Created with the method [`split_terminator`].
|
||||||
|
@ -728,6 +781,48 @@ generate_pattern_iterators! {
|
||||||
delegate double ended;
|
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! {
|
derive_pattern_clone! {
|
||||||
clone SplitNInternal
|
clone SplitNInternal
|
||||||
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
|
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! {
|
generate_pattern_iterators! {
|
||||||
|
@ -804,6 +904,48 @@ generate_pattern_iterators! {
|
||||||
delegate single ended;
|
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! {
|
derive_pattern_clone! {
|
||||||
clone MatchIndicesInternal
|
clone MatchIndicesInternal
|
||||||
with |s| MatchIndicesInternal(s.0.clone())
|
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")]
|
#[unstable(feature = "split_inclusive", issue = "72360")]
|
||||||
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
|
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.
|
/// An iterator of [`u16`] over the string encoded as UTF-16.
|
||||||
///
|
///
|
||||||
/// This struct is created by the [`encode_utf16`] method on [`str`].
|
/// This struct is created by the [`encode_utf16`] method on [`str`].
|
||||||
|
|
|
@ -303,7 +303,8 @@ impl Backtrace {
|
||||||
// Capture a backtrace which start just before the function addressed by
|
// Capture a backtrace which start just before the function addressed by
|
||||||
// `ip`
|
// `ip`
|
||||||
fn create(ip: usize) -> Backtrace {
|
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 frames = Vec::new();
|
||||||
let mut actual_start = None;
|
let mut actual_start = None;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -408,7 +409,8 @@ impl Capture {
|
||||||
// Use the global backtrace lock to synchronize this as it's a
|
// Use the global backtrace lock to synchronize this as it's a
|
||||||
// requirement of the `backtrace` crate, and then actually resolve
|
// requirement of the `backtrace` crate, and then actually resolve
|
||||||
// everything.
|
// everything.
|
||||||
let _lock = lock();
|
// SAFETY: We don't attempt to lock this reentrantly.
|
||||||
|
let _lock = unsafe { lock() };
|
||||||
for frame in self.frames.iter_mut() {
|
for frame in self.frames.iter_mut() {
|
||||||
let symbols = &mut frame.symbols;
|
let symbols = &mut frame.symbols;
|
||||||
let frame = match &frame.frame {
|
let frame = match &frame.frame {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
423
library/std/src/io/buffered/bufreader.rs
Normal file
423
library/std/src/io/buffered/bufreader.rs
Normal 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",
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
387
library/std/src/io/buffered/bufwriter.rs
Normal file
387
library/std/src/io/buffered/bufwriter.rs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
232
library/std/src/io/buffered/linewriter.rs
Normal file
232
library/std/src/io/buffered/linewriter.rs
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
270
library/std/src/io/buffered/linewritershim.rs
Normal file
270
library/std/src/io/buffered/linewritershim.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
151
library/std/src/io/buffered/mod.rs
Normal file
151
library/std/src/io/buffered/mod.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::cell::UnsafeCell;
|
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||||
use crate::sys::cloudabi::abi;
|
use crate::sys::cloudabi::abi;
|
||||||
|
@ -12,7 +11,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Condvar {
|
pub struct Condvar {
|
||||||
condvar: UnsafeCell<AtomicU32>,
|
condvar: AtomicU32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MovableCondvar = Condvar;
|
pub type MovableCondvar = Condvar;
|
||||||
|
@ -20,29 +19,28 @@ pub type MovableCondvar = Condvar;
|
||||||
unsafe impl Send for Condvar {}
|
unsafe impl Send for Condvar {}
|
||||||
unsafe impl Sync for Condvar {}
|
unsafe impl Sync for Condvar {}
|
||||||
|
|
||||||
const NEW: Condvar =
|
|
||||||
Condvar { condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)) };
|
|
||||||
|
|
||||||
impl Condvar {
|
impl Condvar {
|
||||||
pub const fn new() -> 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 init(&mut self) {}
|
||||||
|
|
||||||
pub unsafe fn notify_one(&self) {
|
pub unsafe fn notify_one(&self) {
|
||||||
let condvar = self.condvar.get();
|
if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
||||||
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
let ret = abi::condvar_signal(
|
||||||
let ret = abi::condvar_signal(condvar as *mut abi::condvar, abi::scope::PRIVATE, 1);
|
&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");
|
assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn notify_all(&self) {
|
pub unsafe fn notify_all(&self) {
|
||||||
let condvar = self.condvar.get();
|
if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
||||||
if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
|
|
||||||
let ret = abi::condvar_signal(
|
let ret = abi::condvar_signal(
|
||||||
condvar as *mut abi::condvar,
|
&self.condvar as *const AtomicU32 as *mut abi::condvar,
|
||||||
abi::scope::PRIVATE,
|
abi::scope::PRIVATE,
|
||||||
abi::nthreads::MAX,
|
abi::nthreads::MAX,
|
||||||
);
|
);
|
||||||
|
@ -53,20 +51,19 @@ impl Condvar {
|
||||||
pub unsafe fn wait(&self, mutex: &Mutex) {
|
pub unsafe fn wait(&self, mutex: &Mutex) {
|
||||||
let mutex = mutex::raw(mutex);
|
let mutex = mutex::raw(mutex);
|
||||||
assert_eq!(
|
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,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
"This lock is not write-locked by this thread"
|
"This lock is not write-locked by this thread"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Call into the kernel to wait on the condition variable.
|
// Call into the kernel to wait on the condition variable.
|
||||||
let condvar = self.condvar.get();
|
|
||||||
let subscription = abi::subscription {
|
let subscription = abi::subscription {
|
||||||
type_: abi::eventtype::CONDVAR,
|
type_: abi::eventtype::CONDVAR,
|
||||||
union: abi::subscription_union {
|
union: abi::subscription_union {
|
||||||
condvar: abi::subscription_condvar {
|
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,
|
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,
|
lock_scope: abi::scope::PRIVATE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -86,13 +83,12 @@ impl Condvar {
|
||||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||||
let mutex = mutex::raw(mutex);
|
let mutex = mutex::raw(mutex);
|
||||||
assert_eq!(
|
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,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
"This lock is not write-locked by this thread"
|
"This lock is not write-locked by this thread"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Call into the kernel to wait on the condition variable.
|
// Call into the kernel to wait on the condition variable.
|
||||||
let condvar = self.condvar.get();
|
|
||||||
let timeout =
|
let timeout =
|
||||||
checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
|
checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
|
||||||
let subscriptions = [
|
let subscriptions = [
|
||||||
|
@ -100,9 +96,9 @@ impl Condvar {
|
||||||
type_: abi::eventtype::CONDVAR,
|
type_: abi::eventtype::CONDVAR,
|
||||||
union: abi::subscription_union {
|
union: abi::subscription_union {
|
||||||
condvar: abi::subscription_condvar {
|
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,
|
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,
|
lock_scope: abi::scope::PRIVATE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -124,7 +120,7 @@ impl Condvar {
|
||||||
let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
|
let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
|
||||||
let ret = abi::poll(
|
let ret = abi::poll(
|
||||||
subscriptions.as_ptr(),
|
subscriptions.as_ptr(),
|
||||||
mem::MaybeUninit::first_ptr_mut(&mut events),
|
mem::MaybeUninit::slice_as_mut_ptr(&mut events),
|
||||||
2,
|
2,
|
||||||
nevents.as_mut_ptr(),
|
nevents.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
|
@ -144,9 +140,8 @@ impl Condvar {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn destroy(&self) {
|
pub unsafe fn destroy(&self) {
|
||||||
let condvar = self.condvar.get();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(*condvar).load(Ordering::Relaxed),
|
self.condvar.load(Ordering::Relaxed),
|
||||||
abi::CONDVAR_HAS_NO_WAITERS.0,
|
abi::CONDVAR_HAS_NO_WAITERS.0,
|
||||||
"Attempted to destroy a condition variable with blocked threads"
|
"Attempted to destroy a condition variable with blocked threads"
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::cell::UnsafeCell;
|
use crate::cell::Cell;
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::mem::MaybeUninit;
|
use crate::mem::MaybeUninit;
|
||||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
@ -17,7 +17,7 @@ pub struct Mutex(RWLock);
|
||||||
|
|
||||||
pub type MovableMutex = Mutex;
|
pub type MovableMutex = Mutex;
|
||||||
|
|
||||||
pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
|
pub unsafe fn raw(m: &Mutex) -> &AtomicU32 {
|
||||||
rwlock::raw(&m.0)
|
rwlock::raw(&m.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,28 +50,23 @@ impl Mutex {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReentrantMutex {
|
pub struct ReentrantMutex {
|
||||||
lock: UnsafeCell<MaybeUninit<AtomicU32>>,
|
lock: AtomicU32,
|
||||||
recursion: UnsafeCell<MaybeUninit<u32>>,
|
recursion: Cell<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for ReentrantMutex {}
|
||||||
|
unsafe impl Sync for ReentrantMutex {}
|
||||||
|
|
||||||
impl ReentrantMutex {
|
impl ReentrantMutex {
|
||||||
pub const unsafe fn uninitialized() -> ReentrantMutex {
|
pub const unsafe fn uninitialized() -> ReentrantMutex {
|
||||||
ReentrantMutex {
|
ReentrantMutex { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), recursion: Cell::new(0) }
|
||||||
lock: UnsafeCell::new(MaybeUninit::uninit()),
|
|
||||||
recursion: UnsafeCell::new(MaybeUninit::uninit()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn init(&self) {
|
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 try_lock(&self) -> bool {
|
pub unsafe fn try_lock(&self) -> bool {
|
||||||
// Attempt to acquire the lock.
|
// Attempt to acquire the lock.
|
||||||
let lock = (*self.lock.get()).as_mut_ptr();
|
if let Err(old) = self.lock.compare_exchange(
|
||||||
let recursion = (*self.recursion.get()).as_mut_ptr();
|
|
||||||
if let Err(old) = (*lock).compare_exchange(
|
|
||||||
abi::LOCK_UNLOCKED.0,
|
abi::LOCK_UNLOCKED.0,
|
||||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
Ordering::Acquire,
|
Ordering::Acquire,
|
||||||
|
@ -80,14 +75,14 @@ impl ReentrantMutex {
|
||||||
// If we fail to acquire the lock, it may be the case
|
// If we fail to acquire the lock, it may be the case
|
||||||
// that we've already acquired it and may need to recurse.
|
// 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 {
|
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
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Success.
|
// Success.
|
||||||
assert_eq!(*recursion, 0, "Mutex has invalid recursion count");
|
assert_eq!(self.recursion.get(), 0, "Mutex has invalid recursion count");
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +90,7 @@ impl ReentrantMutex {
|
||||||
pub unsafe fn lock(&self) {
|
pub unsafe fn lock(&self) {
|
||||||
if !self.try_lock() {
|
if !self.try_lock() {
|
||||||
// Call into the kernel to acquire a write 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 {
|
let subscription = abi::subscription {
|
||||||
type_: abi::eventtype::LOCK_WRLOCK,
|
type_: abi::eventtype::LOCK_WRLOCK,
|
||||||
union: abi::subscription_union {
|
union: abi::subscription_union {
|
||||||
|
@ -116,17 +111,17 @@ impl ReentrantMutex {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn unlock(&self) {
|
pub unsafe fn unlock(&self) {
|
||||||
let lock = (*self.lock.get()).as_mut_ptr();
|
|
||||||
let recursion = (*self.recursion.get()).as_mut_ptr();
|
|
||||||
assert_eq!(
|
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,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
"This mutex is locked by a different thread"
|
"This mutex is locked by a different thread"
|
||||||
);
|
);
|
||||||
|
|
||||||
if *recursion > 0 {
|
let r = self.recursion.get();
|
||||||
*recursion -= 1;
|
if r > 0 {
|
||||||
} else if !(*lock)
|
self.recursion.set(r - 1);
|
||||||
|
} else if !self
|
||||||
|
.lock
|
||||||
.compare_exchange(
|
.compare_exchange(
|
||||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
abi::LOCK_UNLOCKED.0,
|
abi::LOCK_UNLOCKED.0,
|
||||||
|
@ -137,19 +132,20 @@ impl ReentrantMutex {
|
||||||
{
|
{
|
||||||
// Lock is managed by kernelspace. Call into the kernel
|
// Lock is managed by kernelspace. Call into the kernel
|
||||||
// to unblock waiting threads.
|
// 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");
|
assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn destroy(&self) {
|
pub unsafe fn destroy(&self) {
|
||||||
let lock = (*self.lock.get()).as_mut_ptr();
|
|
||||||
let recursion = (*self.recursion.get()).as_mut_ptr();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(*lock).load(Ordering::Relaxed),
|
self.lock.load(Ordering::Relaxed),
|
||||||
abi::LOCK_UNLOCKED.0,
|
abi::LOCK_UNLOCKED.0,
|
||||||
"Attempted to destroy locked mutex"
|
"Attempted to destroy locked mutex"
|
||||||
);
|
);
|
||||||
assert_eq!(*recursion, 0, "Recursion counter invalid");
|
assert_eq!(self.recursion.get(), 0, "Recursion counter invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::cell::UnsafeCell;
|
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::mem::MaybeUninit;
|
use crate::mem::MaybeUninit;
|
||||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
@ -13,28 +12,25 @@ extern "C" {
|
||||||
static mut RDLOCKS_ACQUIRED: u32 = 0;
|
static mut RDLOCKS_ACQUIRED: u32 = 0;
|
||||||
|
|
||||||
pub struct RWLock {
|
pub struct RWLock {
|
||||||
lock: UnsafeCell<AtomicU32>,
|
lock: AtomicU32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
|
pub unsafe fn raw(r: &RWLock) -> &AtomicU32 {
|
||||||
r.lock.get()
|
&r.lock
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for RWLock {}
|
unsafe impl Send for RWLock {}
|
||||||
unsafe impl Sync for RWLock {}
|
unsafe impl Sync for RWLock {}
|
||||||
|
|
||||||
const NEW: RWLock = RWLock { lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)) };
|
|
||||||
|
|
||||||
impl RWLock {
|
impl RWLock {
|
||||||
pub const fn new() -> RWLock {
|
pub const fn new() -> RWLock {
|
||||||
NEW
|
RWLock { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn try_read(&self) -> bool {
|
pub unsafe fn try_read(&self) -> bool {
|
||||||
let lock = self.lock.get();
|
|
||||||
let mut old = abi::LOCK_UNLOCKED.0;
|
let mut old = abi::LOCK_UNLOCKED.0;
|
||||||
while let Err(cur) =
|
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 {
|
if (cur & abi::LOCK_WRLOCKED.0) != 0 {
|
||||||
// Another thread already has a write lock.
|
// Another thread already has a write lock.
|
||||||
|
@ -61,12 +57,11 @@ impl RWLock {
|
||||||
pub unsafe fn read(&self) {
|
pub unsafe fn read(&self) {
|
||||||
if !self.try_read() {
|
if !self.try_read() {
|
||||||
// Call into the kernel to acquire a read lock.
|
// Call into the kernel to acquire a read lock.
|
||||||
let lock = self.lock.get();
|
|
||||||
let subscription = abi::subscription {
|
let subscription = abi::subscription {
|
||||||
type_: abi::eventtype::LOCK_RDLOCK,
|
type_: abi::eventtype::LOCK_RDLOCK,
|
||||||
union: abi::subscription_union {
|
union: abi::subscription_union {
|
||||||
lock: abi::subscription_lock {
|
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,
|
lock_scope: abi::scope::PRIVATE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -96,11 +91,10 @@ impl RWLock {
|
||||||
assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
|
assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
|
||||||
let mut old = 1;
|
let mut old = 1;
|
||||||
loop {
|
loop {
|
||||||
let lock = self.lock.get();
|
|
||||||
if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
|
if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
|
||||||
// Last read lock while threads are waiting. Attempt to upgrade
|
// Last read lock while threads are waiting. Attempt to upgrade
|
||||||
// to a write lock before calling into the kernel to unlock.
|
// 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,
|
old,
|
||||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
|
||||||
Ordering::Acquire,
|
Ordering::Acquire,
|
||||||
|
@ -109,7 +103,10 @@ impl RWLock {
|
||||||
old = cur;
|
old = cur;
|
||||||
} else {
|
} else {
|
||||||
// Call into the kernel to unlock.
|
// 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");
|
assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +119,7 @@ impl RWLock {
|
||||||
0,
|
0,
|
||||||
"Attempted to read-unlock a write-locked rwlock"
|
"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,
|
||||||
old - 1,
|
old - 1,
|
||||||
Ordering::Acquire,
|
Ordering::Acquire,
|
||||||
|
@ -140,8 +137,7 @@ impl RWLock {
|
||||||
|
|
||||||
pub unsafe fn try_write(&self) -> bool {
|
pub unsafe fn try_write(&self) -> bool {
|
||||||
// Attempt to acquire the lock.
|
// Attempt to acquire the lock.
|
||||||
let lock = self.lock.get();
|
if let Err(old) = self.lock.compare_exchange(
|
||||||
if let Err(old) = (*lock).compare_exchange(
|
|
||||||
abi::LOCK_UNLOCKED.0,
|
abi::LOCK_UNLOCKED.0,
|
||||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
Ordering::Acquire,
|
Ordering::Acquire,
|
||||||
|
@ -163,12 +159,11 @@ impl RWLock {
|
||||||
pub unsafe fn write(&self) {
|
pub unsafe fn write(&self) {
|
||||||
if !self.try_write() {
|
if !self.try_write() {
|
||||||
// Call into the kernel to acquire a write lock.
|
// Call into the kernel to acquire a write lock.
|
||||||
let lock = self.lock.get();
|
|
||||||
let subscription = abi::subscription {
|
let subscription = abi::subscription {
|
||||||
type_: abi::eventtype::LOCK_WRLOCK,
|
type_: abi::eventtype::LOCK_WRLOCK,
|
||||||
union: abi::subscription_union {
|
union: abi::subscription_union {
|
||||||
lock: abi::subscription_lock {
|
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,
|
lock_scope: abi::scope::PRIVATE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -184,14 +179,14 @@ impl RWLock {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn write_unlock(&self) {
|
pub unsafe fn write_unlock(&self) {
|
||||||
let lock = self.lock.get();
|
|
||||||
assert_eq!(
|
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,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
"This rwlock is not write-locked by this thread"
|
"This rwlock is not write-locked by this thread"
|
||||||
);
|
);
|
||||||
|
|
||||||
if !(*lock)
|
if !self
|
||||||
|
.lock
|
||||||
.compare_exchange(
|
.compare_exchange(
|
||||||
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
__pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
|
||||||
abi::LOCK_UNLOCKED.0,
|
abi::LOCK_UNLOCKED.0,
|
||||||
|
@ -202,15 +197,17 @@ impl RWLock {
|
||||||
{
|
{
|
||||||
// Lock is managed by kernelspace. Call into the kernel
|
// Lock is managed by kernelspace. Call into the kernel
|
||||||
// to unblock waiting threads.
|
// 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");
|
assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn destroy(&self) {
|
pub unsafe fn destroy(&self) {
|
||||||
let lock = self.lock.get();
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(*lock).load(Ordering::Relaxed),
|
self.lock.load(Ordering::Relaxed),
|
||||||
abi::LOCK_UNLOCKED.0,
|
abi::LOCK_UNLOCKED.0,
|
||||||
"Attempted to destroy locked rwlock"
|
"Attempted to destroy locked rwlock"
|
||||||
);
|
);
|
||||||
|
|
|
@ -470,7 +470,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
|
||||||
&mut environ
|
&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!
|
// It is UB to attempt to acquire this mutex reentrantly!
|
||||||
static ENV_LOCK: StaticMutex = StaticMutex::new();
|
static ENV_LOCK: StaticMutex = StaticMutex::new();
|
||||||
ENV_LOCK.lock()
|
ENV_LOCK.lock()
|
||||||
|
|
|
@ -212,7 +212,7 @@ pub unsafe fn environ() -> *mut *const *const c_char {
|
||||||
&mut environ
|
&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!
|
// It is UB to attempt to acquire this mutex reentrantly!
|
||||||
static ENV_LOCK: StaticMutex = StaticMutex::new();
|
static ENV_LOCK: StaticMutex = StaticMutex::new();
|
||||||
ENV_LOCK.lock()
|
ENV_LOCK.lock()
|
||||||
|
|
17
library/std/src/sys/wasm/futex_atomics.rs
Normal file
17
library/std/src/sys/wasm/futex_atomics.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,8 @@ cfg_if::cfg_if! {
|
||||||
pub mod mutex;
|
pub mod mutex;
|
||||||
#[path = "rwlock_atomics.rs"]
|
#[path = "rwlock_atomics.rs"]
|
||||||
pub mod rwlock;
|
pub mod rwlock;
|
||||||
|
#[path = "futex_atomics.rs"]
|
||||||
|
pub mod futex;
|
||||||
} else {
|
} else {
|
||||||
#[path = "../unsupported/condvar.rs"]
|
#[path = "../unsupported/condvar.rs"]
|
||||||
pub mod condvar;
|
pub mod condvar;
|
||||||
|
|
|
@ -8,27 +8,15 @@ use crate::io;
|
||||||
use crate::io::prelude::*;
|
use crate::io::prelude::*;
|
||||||
use crate::path::{self, Path, PathBuf};
|
use crate::path::{self, Path, PathBuf};
|
||||||
use crate::sync::atomic::{self, Ordering};
|
use crate::sync::atomic::{self, Ordering};
|
||||||
use crate::sys::mutex::Mutex;
|
use crate::sys_common::mutex::StaticMutex;
|
||||||
|
|
||||||
/// Max number of frames to print.
|
/// Max number of frames to print.
|
||||||
const MAX_NB_FRAMES: usize = 100;
|
const MAX_NB_FRAMES: usize = 100;
|
||||||
|
|
||||||
pub fn lock() -> impl Drop {
|
// SAFETY: Don't attempt to lock this reentrantly.
|
||||||
struct Guard;
|
pub unsafe fn lock() -> impl Drop {
|
||||||
static LOCK: Mutex = Mutex::new();
|
static LOCK: StaticMutex = StaticMutex::new();
|
||||||
|
LOCK.lock()
|
||||||
impl Drop for Guard {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
LOCK.unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
LOCK.lock();
|
|
||||||
Guard
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints the current backtrace.
|
/// Prints the current backtrace.
|
||||||
|
|
|
@ -3,8 +3,7 @@ use crate::sys::mutex as imp;
|
||||||
/// An OS-based mutual exclusion lock, meant for use in static variables.
|
/// An OS-based mutual exclusion lock, meant for use in static variables.
|
||||||
///
|
///
|
||||||
/// This mutex has a const constructor ([`StaticMutex::new`]), does not
|
/// This mutex has a const constructor ([`StaticMutex::new`]), does not
|
||||||
/// implement `Drop` to cleanup resources, and causes UB when moved or used
|
/// implement `Drop` to cleanup resources, and causes UB when used reentrantly.
|
||||||
/// reentrantly.
|
|
||||||
///
|
///
|
||||||
/// This mutex does not implement poisoning.
|
/// This mutex does not implement poisoning.
|
||||||
///
|
///
|
||||||
|
@ -16,11 +15,6 @@ unsafe impl Sync for StaticMutex {}
|
||||||
|
|
||||||
impl StaticMutex {
|
impl StaticMutex {
|
||||||
/// Creates a new mutex for use.
|
/// 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 {
|
pub const fn new() -> Self {
|
||||||
Self(imp::Mutex::new())
|
Self(imp::Mutex::new())
|
||||||
}
|
}
|
||||||
|
@ -28,19 +22,19 @@ impl StaticMutex {
|
||||||
/// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
|
/// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
|
||||||
/// will be unlocked.
|
/// will be unlocked.
|
||||||
///
|
///
|
||||||
/// It is undefined behaviour to call this function while locked, or if the
|
/// It is undefined behaviour to call this function while locked by the
|
||||||
/// mutex has been moved since the last time this was called.
|
/// same thread.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn lock(&self) -> StaticMutexGuard<'_> {
|
pub unsafe fn lock(&'static self) -> StaticMutexGuard {
|
||||||
self.0.lock();
|
self.0.lock();
|
||||||
StaticMutexGuard(&self.0)
|
StaticMutexGuard(&self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct StaticMutexGuard<'a>(&'a imp::Mutex);
|
pub struct StaticMutexGuard(&'static imp::Mutex);
|
||||||
|
|
||||||
impl Drop for StaticMutexGuard<'_> {
|
impl Drop for StaticMutexGuard {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
cfg_if::cfg_if! {
|
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;
|
mod futex;
|
||||||
pub use futex::Parker;
|
pub use futex::Parker;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -201,6 +201,37 @@ impl Cfg {
|
||||||
_ => false,
|
_ => 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 {
|
impl ops::Not for Cfg {
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
if let Some(ref name) = item.name {
|
||||||
info!("Documenting {}", name);
|
info!("Documenting {}", name);
|
||||||
}
|
}
|
||||||
document_stability(w, cx, item, false);
|
document_stability(w, cx, item, false, parent);
|
||||||
document_full(w, item, cx, "", false);
|
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) {
|
fn document_stability(
|
||||||
let stabilities = short_stability(item, cx);
|
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() {
|
if !stabilities.is_empty() {
|
||||||
write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" });
|
write!(w, "<div class='stability{}'>", if is_hidden { " hidden" } else { "" });
|
||||||
for stability in stabilities {
|
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]) {
|
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>>();
|
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>\
|
<td class='docblock-short'>{stab_tags}{docs}</td>\
|
||||||
</tr>",
|
</tr>",
|
||||||
name = *myitem.name.as_ref().unwrap(),
|
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(),
|
docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
|
||||||
class = myitem.type_(),
|
class = myitem.type_(),
|
||||||
add = add,
|
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
|
/// Render the stability and deprecation tags that are displayed in the item's summary at the
|
||||||
/// module level.
|
/// module level.
|
||||||
fn stability_tags(item: &clean::Item) -> String {
|
fn stability_tags(item: &clean::Item, parent: &clean::Item) -> String {
|
||||||
let mut tags = String::new();
|
let mut tags = String::new();
|
||||||
|
|
||||||
fn tag_html(class: &str, title: &str, contents: &str) -> String {
|
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");
|
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());
|
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
|
/// Render the stability and/or deprecation warning that is displayed at the top of the item's
|
||||||
/// documentation.
|
/// 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 mut stability = vec![];
|
||||||
let error_codes = cx.shared.codes;
|
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));
|
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()));
|
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>");
|
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) {
|
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(),
|
name = it.name.as_ref().unwrap(),
|
||||||
typ = s.type_.print()
|
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) {
|
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(),
|
.print(),
|
||||||
spotlight = spotlight_decl(&f.decl),
|
spotlight = spotlight_decl(&f.decl),
|
||||||
);
|
);
|
||||||
document(w, cx, it)
|
document(w, cx, it, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_implementor(
|
fn render_implementor(
|
||||||
|
@ -2354,6 +2377,7 @@ fn render_implementor(
|
||||||
w,
|
w,
|
||||||
cx,
|
cx,
|
||||||
implementor,
|
implementor,
|
||||||
|
None,
|
||||||
AssocItemLink::Anchor(None),
|
AssocItemLink::Anchor(None),
|
||||||
RenderMode::Normal,
|
RenderMode::Normal,
|
||||||
implementor.impl_item.stable_since().as_deref(),
|
implementor.impl_item.stable_since().as_deref(),
|
||||||
|
@ -2383,6 +2407,7 @@ fn render_impls(
|
||||||
&mut buffer,
|
&mut buffer,
|
||||||
cx,
|
cx,
|
||||||
i,
|
i,
|
||||||
|
Some(containing_item),
|
||||||
assoc_link,
|
assoc_link,
|
||||||
RenderMode::Normal,
|
RenderMode::Normal,
|
||||||
containing_item.stable_since().as_deref(),
|
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
|
// 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) {
|
fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
|
||||||
write!(
|
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) {
|
fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item) {
|
||||||
let name = m.name.as_ref().unwrap();
|
let name = m.name.as_ref().unwrap();
|
||||||
|
info!("Documenting {} on {}", name, t.name.as_deref().unwrap_or_default());
|
||||||
let item_type = m.type_();
|
let item_type = m.type_();
|
||||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||||
write!(w, "<h3 id='{id}' class='method'><code>", id = id,);
|
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>");
|
write!(w, "</code>");
|
||||||
render_stability_since(w, m, t);
|
render_stability_since(w, m, t);
|
||||||
write!(w, "</h3>");
|
write!(w, "</h3>");
|
||||||
document(w, cx, m);
|
document(w, cx, m, Some(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !types.is_empty() {
|
if !types.is_empty() {
|
||||||
|
@ -2628,6 +2654,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
|
||||||
w,
|
w,
|
||||||
cx,
|
cx,
|
||||||
&implementor,
|
&implementor,
|
||||||
|
None,
|
||||||
assoc_link,
|
assoc_link,
|
||||||
RenderMode::Normal,
|
RenderMode::Normal,
|
||||||
implementor.impl_item.stable_since().as_deref(),
|
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>")
|
write!(w, "</pre>")
|
||||||
});
|
});
|
||||||
|
|
||||||
document(w, cx, it);
|
document(w, cx, it, None);
|
||||||
let mut fields = s
|
let mut fields = s
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.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(),
|
name = field.name.as_ref().unwrap(),
|
||||||
ty = ty.print()
|
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>")
|
write!(w, "</pre>")
|
||||||
});
|
});
|
||||||
|
|
||||||
document(w, cx, it);
|
document(w, cx, it, None);
|
||||||
let mut fields = s
|
let mut fields = s
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.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() {
|
if let Some(stability_class) = field.stability_class() {
|
||||||
write!(w, "<span class='stab {stab}'></span>", stab = 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)
|
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>")
|
write!(w, "</pre>")
|
||||||
});
|
});
|
||||||
|
|
||||||
document(w, cx, it);
|
document(w, cx, it, None);
|
||||||
if !e.variants.is_empty() {
|
if !e.variants.is_empty() {
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
|
@ -3060,7 +3087,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, ca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(w, "</code></div>");
|
write!(w, "</code></div>");
|
||||||
document(w, cx, variant);
|
document(w, cx, variant, Some(it));
|
||||||
document_non_exhaustive(w, variant);
|
document_non_exhaustive(w, variant);
|
||||||
|
|
||||||
use crate::clean::{Variant, VariantKind};
|
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(),
|
f = field.name.as_ref().unwrap(),
|
||||||
t = ty.print()
|
t = ty.print()
|
||||||
);
|
);
|
||||||
document(w, cx, field);
|
document(w, cx, field, Some(variant));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(w, "</div></div>");
|
write!(w, "</div></div>");
|
||||||
|
@ -3293,6 +3320,10 @@ fn render_assoc_items(
|
||||||
what: AssocItemRender<'_>,
|
what: AssocItemRender<'_>,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
) {
|
) {
|
||||||
|
info!(
|
||||||
|
"Documenting associated items of {}",
|
||||||
|
containing_item.name.as_deref().unwrap_or_default()
|
||||||
|
);
|
||||||
let v = match cache.impls.get(&it) {
|
let v = match cache.impls.get(&it) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return,
|
None => return,
|
||||||
|
@ -3327,6 +3358,7 @@ fn render_assoc_items(
|
||||||
w,
|
w,
|
||||||
cx,
|
cx,
|
||||||
i,
|
i,
|
||||||
|
Some(containing_item),
|
||||||
AssocItemLink::Anchor(None),
|
AssocItemLink::Anchor(None),
|
||||||
render_mode,
|
render_mode,
|
||||||
containing_item.stable_since().as_deref(),
|
containing_item.stable_since().as_deref(),
|
||||||
|
@ -3518,6 +3550,7 @@ fn render_impl(
|
||||||
w: &mut Buffer,
|
w: &mut Buffer,
|
||||||
cx: &Context,
|
cx: &Context,
|
||||||
i: &Impl,
|
i: &Impl,
|
||||||
|
parent: Option<&clean::Item>,
|
||||||
link: AssocItemLink<'_>,
|
link: AssocItemLink<'_>,
|
||||||
render_mode: RenderMode,
|
render_mode: RenderMode,
|
||||||
outer_version: Option<&str>,
|
outer_version: Option<&str>,
|
||||||
|
@ -3600,6 +3633,7 @@ fn render_impl(
|
||||||
w: &mut Buffer,
|
w: &mut Buffer,
|
||||||
cx: &Context,
|
cx: &Context,
|
||||||
item: &clean::Item,
|
item: &clean::Item,
|
||||||
|
parent: Option<&clean::Item>,
|
||||||
link: AssocItemLink<'_>,
|
link: AssocItemLink<'_>,
|
||||||
render_mode: RenderMode,
|
render_mode: RenderMode,
|
||||||
is_default_item: bool,
|
is_default_item: bool,
|
||||||
|
@ -3684,7 +3718,7 @@ fn render_impl(
|
||||||
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
|
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
|
||||||
// We need the stability of the item from the trait
|
// We need the stability of the item from the trait
|
||||||
// because impls can't have a stability.
|
// 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() {
|
if item.doc_value().is_some() {
|
||||||
document_full(w, item, cx, "", is_hidden);
|
document_full(w, item, cx, "", is_hidden);
|
||||||
} else if show_def_docs {
|
} else if show_def_docs {
|
||||||
|
@ -3694,13 +3728,13 @@ fn render_impl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
document_stability(w, cx, item, is_hidden);
|
document_stability(w, cx, item, is_hidden, parent);
|
||||||
if show_def_docs {
|
if show_def_docs {
|
||||||
document_full(w, item, cx, "", is_hidden);
|
document_full(w, item, cx, "", is_hidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
document_stability(w, cx, item, is_hidden);
|
document_stability(w, cx, item, is_hidden, parent);
|
||||||
if show_def_docs {
|
if show_def_docs {
|
||||||
document_short(w, item, link, "", is_hidden);
|
document_short(w, item, link, "", is_hidden);
|
||||||
}
|
}
|
||||||
|
@ -3717,6 +3751,7 @@ fn render_impl(
|
||||||
w,
|
w,
|
||||||
cx,
|
cx,
|
||||||
trait_item,
|
trait_item,
|
||||||
|
parent,
|
||||||
link,
|
link,
|
||||||
render_mode,
|
render_mode,
|
||||||
false,
|
false,
|
||||||
|
@ -3732,6 +3767,7 @@ fn render_impl(
|
||||||
cx: &Context,
|
cx: &Context,
|
||||||
t: &clean::Trait,
|
t: &clean::Trait,
|
||||||
i: &clean::Impl,
|
i: &clean::Impl,
|
||||||
|
parent: Option<&clean::Item>,
|
||||||
render_mode: RenderMode,
|
render_mode: RenderMode,
|
||||||
outer_version: Option<&str>,
|
outer_version: Option<&str>,
|
||||||
show_def_docs: bool,
|
show_def_docs: bool,
|
||||||
|
@ -3749,6 +3785,7 @@ fn render_impl(
|
||||||
w,
|
w,
|
||||||
cx,
|
cx,
|
||||||
trait_item,
|
trait_item,
|
||||||
|
parent,
|
||||||
assoc_link,
|
assoc_link,
|
||||||
render_mode,
|
render_mode,
|
||||||
true,
|
true,
|
||||||
|
@ -3771,6 +3808,7 @@ fn render_impl(
|
||||||
cx,
|
cx,
|
||||||
t,
|
t,
|
||||||
&i.inner_impl(),
|
&i.inner_impl(),
|
||||||
|
parent,
|
||||||
render_mode,
|
render_mode,
|
||||||
outer_version,
|
outer_version,
|
||||||
show_def_docs,
|
show_def_docs,
|
||||||
|
@ -3799,7 +3837,7 @@ fn item_opaque_ty(
|
||||||
bounds = bounds(&t.bounds, false)
|
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
|
// 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
|
// 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)
|
bounds(&t.bounds, true)
|
||||||
);
|
);
|
||||||
|
|
||||||
document(w, cx, it);
|
document(w, cx, it, None);
|
||||||
|
|
||||||
// Render any items associated directly to this alias, as otherwise they
|
// 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
|
// 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()
|
type_ = t.type_.print()
|
||||||
);
|
);
|
||||||
|
|
||||||
document(w, cx, it);
|
document(w, cx, it, None);
|
||||||
|
|
||||||
// Render any items associated directly to this alias, as otherwise they
|
// 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
|
// 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(),
|
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)
|
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,
|
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) {
|
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>");
|
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) {
|
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)
|
render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
|
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";
|
crate const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang";
|
||||||
|
|
182
src/test/rustdoc/doc-cfg-simplification.rs
Normal file
182
src/test/rustdoc/doc-cfg-simplification.rs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,9 +10,8 @@ pub struct Portable;
|
||||||
// @has doc_cfg/unix_only/index.html \
|
// @has doc_cfg/unix_only/index.html \
|
||||||
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
||||||
// 'This is supported on Unix only.'
|
// 'This is supported on Unix only.'
|
||||||
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix\Z'
|
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AARM\Z'
|
||||||
// @matches - '//*[@class="module-item"]//*[@class="stab portability"]' '\AUnix and ARM\Z'
|
// @count - '//*[@class="stab portability"]' 2
|
||||||
// @count - '//*[@class="stab portability"]' 3
|
|
||||||
#[doc(cfg(unix))]
|
#[doc(cfg(unix))]
|
||||||
pub mod unix_only {
|
pub mod unix_only {
|
||||||
// @has doc_cfg/unix_only/fn.unix_only_function.html \
|
// @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 \
|
// @has doc_cfg/unix_only/trait.ArmOnly.html \
|
||||||
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
// '//*[@id="main"]/*[@class="stability"]/*[@class="stab portability"]' \
|
||||||
// 'This is supported on Unix and ARM only.'
|
// 'This is supported on Unix and ARM only.'
|
||||||
// @count - '//*[@class="stab portability"]' 3
|
// @count - '//*[@class="stab portability"]' 2
|
||||||
#[doc(cfg(target_arch = "arm"))]
|
#[doc(cfg(target_arch = "arm"))]
|
||||||
pub trait ArmOnly {
|
pub trait ArmOnly {
|
||||||
fn unix_and_arm_only_function();
|
fn unix_and_arm_only_function();
|
||||||
|
|
|
@ -14,45 +14,41 @@
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
// @has 'foo/bar/index.html'
|
// @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.'
|
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
|
||||||
#[doc(cfg(feature = "sync"))]
|
#[doc(cfg(feature = "sync"))]
|
||||||
pub mod bar {
|
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"))]
|
#[doc(cfg(feature = "sync"))]
|
||||||
pub struct Bar;
|
pub struct Bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @has 'foo/baz/index.html'
|
// @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.'
|
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
|
||||||
#[doc(cfg(all(feature = "sync", feature = "send")))]
|
#[doc(cfg(all(feature = "sync", feature = "send")))]
|
||||||
pub mod baz {
|
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"))]
|
#[doc(cfg(feature = "sync"))]
|
||||||
pub struct Baz;
|
pub struct Baz;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @has 'foo/qux/struct.Qux.html'
|
// @has 'foo/qux/index.html'
|
||||||
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.'
|
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.'
|
||||||
#[doc(cfg(feature = "sync"))]
|
#[doc(cfg(feature = "sync"))]
|
||||||
pub mod qux {
|
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")))]
|
#[doc(cfg(all(feature = "sync", feature = "send")))]
|
||||||
pub struct Qux;
|
pub struct Qux;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @has 'foo/quux/index.html'
|
// @has 'foo/quux/index.html'
|
||||||
// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send and foo and bar$'
|
// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo only.'
|
||||||
// @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.'
|
|
||||||
#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
|
#[doc(cfg(all(feature = "sync", feature = "send", foo)))]
|
||||||
pub mod quux {
|
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)))]
|
#[doc(cfg(all(feature = "send", feature = "sync", bar)))]
|
||||||
pub struct Quux;
|
pub struct Quux;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||||
--> $DIR/arg-count-mismatch.rs:5:28
|
--> $DIR/arg-count-mismatch.rs:5:28
|
||||||
|
|
|
|
||||||
LL | fn f(x: isize) { }
|
|
||||||
| -------------- defined here
|
|
||||||
LL |
|
|
||||||
LL | fn main() { let i: (); i = f(); }
|
LL | fn main() { let i: (); i = f(); }
|
||||||
| ^-- supplied 0 arguments
|
| ^-- supplied 0 arguments
|
||||||
| |
|
| |
|
||||||
| expected 1 argument
|
| 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
enum Test {
|
enum Test {
|
||||||
Foo,
|
Foo,
|
||||||
Bar,
|
Bar,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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] => (),
|
LL | ref foo @ [.., ref mut bar] => (),
|
||||||
| -------^^^^^^^^-----------^
|
| -------^^^^^^^^-----------^
|
||||||
|
@ -8,7 +8,7 @@ LL | ref foo @ [.., ref mut bar] => (),
|
||||||
| immutable borrow, by `foo`, occurs here
|
| immutable borrow, by `foo`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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) => (),
|
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
|
| immutable borrow, by `foo`, occurs here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `x`
|
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]) {
|
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
|
| - 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
|
| ^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
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),
|
LL | ref mut foo @ [.., _] => Some(foo),
|
||||||
| --------------------- mutable borrow occurs here
|
| --------------------- mutable borrow occurs here
|
||||||
|
@ -41,7 +41,7 @@ LL | drop(r);
|
||||||
| - mutable borrow later used here
|
| - mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | [ref foo @ .., ref bar] => Some(foo),
|
||||||
| ------------ immutable borrow occurs here
|
| ------------ immutable borrow occurs here
|
||||||
|
@ -53,7 +53,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | ref foo @ [.., ref bar] => Some(foo),
|
||||||
| ----------------------- immutable borrow occurs here
|
| ----------------------- immutable borrow occurs here
|
||||||
|
@ -65,7 +65,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `x`
|
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>) {
|
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
|
| - 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
|
| ^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||||
| ------------------------------------- immutable borrow occurs here
|
| ------------------------------------- immutable borrow occurs here
|
||||||
|
@ -92,7 +92,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
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),
|
LL | ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||||
| ----------------------------------------- mutable borrow occurs here
|
| ----------------------------------------- mutable borrow occurs here
|
||||||
|
@ -104,7 +104,7 @@ LL | drop(r);
|
||||||
| - mutable borrow later used here
|
| - mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | ref foo @ Some(box ref s) => Some(foo),
|
||||||
| ------------------------- immutable borrow occurs here
|
| ------------------------- immutable borrow occurs here
|
||||||
|
@ -116,7 +116,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `x`
|
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]) {
|
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
|
| - 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
|
| ^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
|
||||||
| ------------------------------------------------- immutable borrow occurs here
|
| ------------------------------------------------- immutable borrow occurs here
|
||||||
|
@ -143,7 +143,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
|
||||||
| ---------- immutable borrow occurs here
|
| ---------- immutable borrow occurs here
|
||||||
|
@ -155,7 +155,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | [_, ref a @ Some(box ref b), ..] => Some(a),
|
||||||
| ----------------------- immutable borrow occurs here
|
| ----------------------- immutable borrow occurs here
|
||||||
|
@ -167,7 +167,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||||
| ------------------------------------------- immutable borrow occurs here
|
| ------------------------------------------- immutable borrow occurs here
|
||||||
|
@ -179,7 +179,7 @@ LL | drop(r);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
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),
|
LL | [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||||
| ----------------------------------------------- mutable borrow occurs here
|
| ----------------------------------------------- mutable borrow occurs here
|
||||||
|
@ -191,7 +191,7 @@ LL | drop(r);
|
||||||
| - mutable borrow later used here
|
| - mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
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),
|
LL | ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||||
| ------------------------------------------------------------ immutable borrow occurs here
|
| ------------------------------------------------------------ immutable borrow occurs here
|
||||||
|
|
|
@ -7,24 +7,30 @@ LL | fn printf(_: *const u8, ...);
|
||||||
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
|
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
|
||||||
--> $DIR/variadic-ffi-1.rs:17:9
|
--> $DIR/variadic-ffi-1.rs:17:9
|
||||||
|
|
|
|
||||||
LL | fn foo(f: isize, x: u8, ...);
|
|
||||||
| ----------------------------- defined here
|
|
||||||
...
|
|
||||||
LL | foo();
|
LL | foo();
|
||||||
| ^^^-- supplied 0 arguments
|
| ^^^-- supplied 0 arguments
|
||||||
| |
|
| |
|
||||||
| expected at least 2 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
|
error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
|
||||||
--> $DIR/variadic-ffi-1.rs:18:9
|
--> $DIR/variadic-ffi-1.rs:18:9
|
||||||
|
|
|
|
||||||
LL | fn foo(f: isize, x: u8, ...);
|
|
||||||
| ----------------------------- defined here
|
|
||||||
...
|
|
||||||
LL | foo(1);
|
LL | foo(1);
|
||||||
| ^^^ - supplied 1 argument
|
| ^^^ - supplied 1 argument
|
||||||
| |
|
| |
|
||||||
| expected at least 2 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[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/variadic-ffi-1.rs:20:56
|
--> $DIR/variadic-ffi-1.rs:20:56
|
||||||
|
|
|
@ -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
|
--> $DIR/variadic-ffi-no-fixed-args.rs:2:12
|
||||||
|
|
|
|
||||||
LL | fn foo(...);
|
LL | fn foo(...);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
// ignore-wasm32-bare compiled with panic=abort by default
|
// ignore-wasm32-bare compiled with panic=abort by default
|
||||||
|
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// ignore-wasm32-bare compiled with panic=abort by default
|
// ignore-wasm32-bare compiled with panic=abort by default
|
||||||
|
|
||||||
#![feature(generators, generator_trait, untagged_unions)]
|
#![feature(generators, generator_trait, untagged_unions)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
|
|
||||||
#![allow(unused_assignments)]
|
#![allow(unused_assignments)]
|
||||||
|
|
|
@ -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 => {},
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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`.
|
|
|
@ -1,13 +1,16 @@
|
||||||
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
|
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
|
||||||
--> $DIR/E0060.rs:6:14
|
--> $DIR/E0060.rs:6:14
|
||||||
|
|
|
|
||||||
LL | fn printf(_: *const u8, ...) -> u32;
|
|
||||||
| ------------------------------------ defined here
|
|
||||||
...
|
|
||||||
LL | unsafe { printf(); }
|
LL | unsafe { printf(); }
|
||||||
| ^^^^^^-- supplied 0 arguments
|
| ^^^^^^-- supplied 0 arguments
|
||||||
| |
|
| |
|
||||||
| expected at least 1 argument
|
| 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,30 @@
|
||||||
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
||||||
--> $DIR/E0061.rs:6:5
|
--> $DIR/E0061.rs:6:5
|
||||||
|
|
|
|
||||||
LL | fn f(a: u16, b: &str) {}
|
|
||||||
| --------------------- defined here
|
|
||||||
...
|
|
||||||
LL | f(0);
|
LL | f(0);
|
||||||
| ^ - supplied 1 argument
|
| ^ - supplied 1 argument
|
||||||
| |
|
| |
|
||||||
| expected 2 arguments
|
| 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
|
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||||
--> $DIR/E0061.rs:10:5
|
--> $DIR/E0061.rs:10:5
|
||||||
|
|
|
|
||||||
LL | fn f2(a: u16) {}
|
|
||||||
| ------------- defined here
|
|
||||||
...
|
|
||||||
LL | f2();
|
LL | f2();
|
||||||
| ^^-- supplied 0 arguments
|
| ^^-- supplied 0 arguments
|
||||||
| |
|
| |
|
||||||
| expected 1 argument
|
| expected 1 argument
|
||||||
|
|
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/E0061.rs:3:4
|
||||||
|
|
|
||||||
|
LL | fn f2(a: u16) {}
|
||||||
|
| ^^ ------
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||||
--> $DIR/issue-58451.rs:12:9
|
--> $DIR/issue-58451.rs:12:9
|
||||||
|
|
|
|
||||||
LL | / fn f<I>(i: I)
|
LL | f(&[f()]);
|
||||||
LL | | where
|
| ^-- supplied 0 arguments
|
||||||
LL | | I: IntoIterator,
|
| |
|
||||||
LL | | I::Item: for<'a> Into<&'a ()>,
|
| expected 1 argument
|
||||||
| |__________________________________- defined here
|
|
|
||||||
...
|
note: function defined here
|
||||||
LL | f(&[f()]);
|
--> $DIR/issue-58451.rs:5:4
|
||||||
| ^-- supplied 0 arguments
|
|
|
||||||
| |
|
LL | fn f<I>(i: I)
|
||||||
| expected 1 argument
|
| ^ ----
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
||||||
--> $DIR/issue-18819.rs:16:5
|
--> $DIR/issue-18819.rs:16:5
|
||||||
|
|
|
|
||||||
LL | fn print_x(_: &dyn Foo<Item=bool>, extra: &str) {
|
|
||||||
| ----------------------------------------------- defined here
|
|
||||||
...
|
|
||||||
LL | print_x(X);
|
LL | print_x(X);
|
||||||
| ^^^^^^^ - supplied 1 argument
|
| ^^^^^^^ - supplied 1 argument
|
||||||
| |
|
| |
|
||||||
| expected 2 arguments
|
| 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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,14 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
|
||||||
LL | $other(None)
|
LL | $other(None)
|
||||||
| ---- supplied 1 argument
|
| ---- supplied 1 argument
|
||||||
...
|
...
|
||||||
LL | fn some_function() {}
|
|
||||||
| ------------------ defined here
|
|
||||||
...
|
|
||||||
LL | some_macro!(some_function);
|
LL | some_macro!(some_function);
|
||||||
| ^^^^^^^^^^^^^ expected 0 arguments
|
| ^^^^^^^^^^^^^ expected 0 arguments
|
||||||
|
|
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/issue-26094.rs:7:4
|
||||||
|
|
|
||||||
|
LL | fn some_function() {}
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
error[E0061]: this function takes 1 argument but 2 arguments were supplied
|
||||||
--> $DIR/issue-4935.rs:5:13
|
--> $DIR/issue-4935.rs:5:13
|
||||||
|
|
|
|
||||||
LL | fn foo(a: usize) {}
|
|
||||||
| ---------------- defined here
|
|
||||||
LL |
|
|
||||||
LL | fn main() { foo(5, 6) }
|
LL | fn main() { foo(5, 6) }
|
||||||
| ^^^ - - supplied 2 arguments
|
| ^^^ - - supplied 2 arguments
|
||||||
| |
|
| |
|
||||||
| expected 1 argument
|
| expected 1 argument
|
||||||
|
|
|
||||||
|
note: function defined here
|
||||||
|
--> $DIR/issue-4935.rs:3:4
|
||||||
|
|
|
||||||
|
LL | fn foo(a: usize) {}
|
||||||
|
| ^^^ --------
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,35 +1,44 @@
|
||||||
error[E0061]: this function takes 0 arguments but 1 argument was supplied
|
error[E0061]: this function takes 0 arguments but 1 argument was supplied
|
||||||
--> $DIR/method-call-err-msg.rs:13:7
|
--> $DIR/method-call-err-msg.rs:13:7
|
||||||
|
|
|
|
||||||
LL | fn zero(self) -> Foo { self }
|
|
||||||
| -------------------- defined here
|
|
||||||
...
|
|
||||||
LL | x.zero(0)
|
LL | x.zero(0)
|
||||||
| ^^^^ - supplied 1 argument
|
| ^^^^ - supplied 1 argument
|
||||||
| |
|
| |
|
||||||
| expected 0 arguments
|
| 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
|
error[E0061]: this function takes 1 argument but 0 arguments were supplied
|
||||||
--> $DIR/method-call-err-msg.rs:14:7
|
--> $DIR/method-call-err-msg.rs:14:7
|
||||||
|
|
|
|
||||||
LL | fn one(self, _: isize) -> Foo { self }
|
|
||||||
| ----------------------------- defined here
|
|
||||||
...
|
|
||||||
LL | .one()
|
LL | .one()
|
||||||
| ^^^- supplied 0 arguments
|
| ^^^- supplied 0 arguments
|
||||||
| |
|
| |
|
||||||
| expected 1 argument
|
| 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
|
error[E0061]: this function takes 2 arguments but 1 argument was supplied
|
||||||
--> $DIR/method-call-err-msg.rs:15:7
|
--> $DIR/method-call-err-msg.rs:15:7
|
||||||
|
|
|
|
||||||
LL | fn two(self, _: isize, _: isize) -> Foo { self }
|
|
||||||
| --------------------------------------- defined here
|
|
||||||
...
|
|
||||||
LL | .two(0);
|
LL | .two(0);
|
||||||
| ^^^ - supplied 1 argument
|
| ^^^ - supplied 1 argument
|
||||||
| |
|
| |
|
||||||
| expected 2 arguments
|
| 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
|
error[E0599]: no method named `take` found for struct `Foo` in the current scope
|
||||||
--> $DIR/method-call-err-msg.rs:19:7
|
--> $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
|
error[E0061]: this function takes 3 arguments but 0 arguments were supplied
|
||||||
--> $DIR/method-call-err-msg.rs:21:7
|
--> $DIR/method-call-err-msg.rs:21:7
|
||||||
|
|
|
|
||||||
LL | fn three<T>(self, _: T, _: T, _: T) -> Foo { self }
|
|
||||||
| ------------------------------------------ defined here
|
|
||||||
...
|
|
||||||
LL | y.three::<usize>();
|
LL | y.three::<usize>();
|
||||||
| ^^^^^--------- supplied 0 arguments
|
| ^^^^^--------- supplied 0 arguments
|
||||||
| |
|
| |
|
||||||
| expected 3 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
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/issue-38371.rs:4:8
|
--> $DIR/issue-38371.rs:4:8
|
||||||
|
|
|
|
||||||
LL | fn foo(&foo: Foo) {
|
LL | fn foo(&foo: Foo) {
|
||||||
| ^^^^------
|
| ^^^^-----
|
||||||
| | |
|
| | |
|
||||||
| | expected due to this
|
| | expected due to this
|
||||||
| expected struct `Foo`, found reference
|
| expected struct `Foo`, found reference
|
||||||
|
|
|
@ -6,7 +6,26 @@ fn foo(a: isize, b: isize, c: isize, d:isize) {
|
||||||
panic!();
|
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() {
|
fn main() {
|
||||||
foo(1, 2, 3);
|
foo(1, 2, 3);
|
||||||
//~^ ERROR this function takes 4 arguments but 3
|
//~^ ERROR this function takes 4 arguments but 3
|
||||||
|
bar(1, 2, 3);
|
||||||
|
//~^ ERROR this function takes 6 arguments but 3
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,43 @@
|
||||||
error[E0061]: this function takes 4 arguments but 3 arguments were supplied
|
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);
|
LL | foo(1, 2, 3);
|
||||||
| ^^^ - - - supplied 3 arguments
|
| ^^^ - - - supplied 3 arguments
|
||||||
| |
|
| |
|
||||||
| expected 4 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`.
|
For more information about this error, try `rustc --explain E0061`.
|
||||||
|
|
|
@ -2,205 +2,205 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
|
||||||
|
|
|
|
||||||
LL | fn f1_1(x: isize, ...) {}
|
LL | fn f1_1(x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: C-variadic function must be declared with at least one named argument
|
error: C-variadic function must be declared with at least one named argument
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
||||||
|
|
|
|
||||||
LL | fn f1_2(...) {}
|
LL | fn f1_2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
||||||
|
|
|
|
||||||
LL | fn f1_2(...) {}
|
LL | fn f1_2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f2_1(x: isize, ...) {}
|
LL | extern "C" fn f2_1(x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: C-variadic function must be declared with at least one named argument
|
error: C-variadic function must be declared with at least one named argument
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f2_2(...) {}
|
LL | extern "C" fn f2_2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f2_2(...) {}
|
LL | extern "C" fn f2_2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f2_3(..., x: isize) {}
|
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
||||||
|
|
|
|
||||||
LL | extern "C" fn f2_3(..., x: isize) {}
|
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
|
||||||
|
|
|
|
||||||
LL | extern fn f3_1(x: isize, ...) {}
|
LL | extern fn f3_1(x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: C-variadic function must be declared with at least one named argument
|
error: C-variadic function must be declared with at least one named argument
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
||||||
|
|
|
|
||||||
LL | extern fn f3_2(...) {}
|
LL | extern fn f3_2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
||||||
|
|
|
|
||||||
LL | extern fn f3_2(...) {}
|
LL | extern fn f3_2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
||||||
|
|
|
|
||||||
LL | extern fn f3_3(..., x: isize) {}
|
LL | extern fn f3_3(..., x: isize) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
||||||
|
|
|
|
||||||
LL | extern fn f3_3(..., x: isize) {}
|
LL | extern fn f3_3(..., x: isize) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: C-variadic function must be declared with at least one named argument
|
error: C-variadic function must be declared with at least one named argument
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
|
||||||
|
|
|
|
||||||
LL | fn e_f1(...);
|
LL | fn e_f1(...);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
|
||||||
|
|
|
|
||||||
LL | fn e_f2(..., x: isize);
|
LL | fn e_f2(..., x: isize);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
|
||||||
|
|
|
|
||||||
LL | fn i_f1(x: isize, ...) {}
|
LL | fn i_f1(x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: C-variadic function must be declared with at least one named argument
|
error: C-variadic function must be declared with at least one named argument
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
||||||
|
|
|
|
||||||
LL | fn i_f2(...) {}
|
LL | fn i_f2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
||||||
|
|
|
|
||||||
LL | fn i_f2(...) {}
|
LL | fn i_f2(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
||||||
|
|
|
|
||||||
LL | fn i_f3(..., x: isize, ...) {}
|
LL | fn i_f3(..., x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
||||||
|
|
|
|
||||||
LL | fn i_f3(..., x: isize, ...) {}
|
LL | fn i_f3(..., x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
|
||||||
|
|
|
|
||||||
LL | fn i_f3(..., x: isize, ...) {}
|
LL | fn i_f3(..., x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
||||||
|
|
|
|
||||||
LL | fn i_f4(..., x: isize, ...) {}
|
LL | fn i_f4(..., x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
||||||
|
|
|
|
||||||
LL | fn i_f4(..., x: isize, ...) {}
|
LL | fn i_f4(..., x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
|
||||||
|
|
|
|
||||||
LL | fn i_f4(..., x: isize, ...) {}
|
LL | fn i_f4(..., x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
|
||||||
|
|
|
|
||||||
LL | fn t_f1(x: isize, ...) {}
|
LL | fn t_f1(x: isize, ...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
|
||||||
|
|
|
|
||||||
LL | fn t_f2(x: isize, ...);
|
LL | fn t_f2(x: isize, ...);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: C-variadic function must be declared with at least one named argument
|
error: C-variadic function must be declared with at least one named argument
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
||||||
|
|
|
|
||||||
LL | fn t_f3(...) {}
|
LL | fn t_f3(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
||||||
|
|
|
|
||||||
LL | fn t_f3(...) {}
|
LL | fn t_f3(...) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: C-variadic function must be declared with at least one named argument
|
error: C-variadic function must be declared with at least one named argument
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
||||||
|
|
|
|
||||||
LL | fn t_f4(...);
|
LL | fn t_f4(...);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
||||||
|
|
|
|
||||||
LL | fn t_f4(...);
|
LL | fn t_f4(...);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
||||||
|
|
|
|
||||||
LL | fn t_f5(..., x: isize) {}
|
LL | fn t_f5(..., x: isize) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
||||||
|
|
|
|
||||||
LL | fn t_f5(..., x: isize) {}
|
LL | fn t_f5(..., x: isize) {}
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: `...` must be the last argument of a C-variadic function
|
error: `...` must be the last argument of a C-variadic function
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
||||||
|
|
|
|
||||||
LL | fn t_f6(..., x: isize);
|
LL | fn t_f6(..., x: isize);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
||||||
|
|
|
|
||||||
LL | fn t_f6(..., x: isize);
|
LL | fn t_f6(..., x: isize);
|
||||||
| ^^^^
|
| ^^^
|
||||||
|
|
||||||
error: aborting due to 34 previous errors
|
error: aborting due to 34 previous errors
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
// where one side is by-ref and the other is by-move.
|
// where one side is by-ref and the other is by-move.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
struct X {
|
struct X {
|
||||||
x: (),
|
x: (),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: cannot move out of value because it is borrowed
|
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) => {}
|
LL | Some(ref _y @ _z) => {}
|
||||||
| ------^^^--
|
| ------^^^--
|
||||||
|
@ -8,7 +8,7 @@ LL | Some(ref _y @ _z) => {}
|
||||||
| value borrowed, by `_y`, here
|
| value borrowed, by `_y`, here
|
||||||
|
|
||||||
error: borrow of moved value
|
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) => {}
|
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
|
| move occurs because `_z` has type `X` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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) => {}
|
LL | Some(ref mut _y @ _z) => {}
|
||||||
| ----------^^^--
|
| ----------^^^--
|
||||||
|
@ -27,7 +27,7 @@ LL | Some(ref mut _y @ _z) => {}
|
||||||
| value borrowed, by `_y`, here
|
| value borrowed, by `_y`, here
|
||||||
|
|
||||||
error: borrow of moved value
|
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) => {}
|
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
|
| move occurs because `_z` has type `X` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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) => {}
|
LL | Some(_z @ ref _y) => {}
|
||||||
| -----^^^^^^
|
| -----^^^^^^
|
||||||
|
@ -52,7 +52,7 @@ LL | Some(ref _z @ ref _y) => {}
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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) => {}
|
LL | Some(_z @ ref mut _y) => {}
|
||||||
| -----^^^^^^^^^^
|
| -----^^^^^^^^^^
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// See issue #12534.
|
// See issue #12534.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0382]: use of moved value
|
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> {
|
LL | fn f(a @ A(u): A) -> Box<u8> {
|
||||||
| ------^-
|
| ------^-
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Test that moving on both sides of an `@` pattern is not allowed.
|
// Test that moving on both sides of an `@` pattern is not allowed.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U; // Not copy!
|
struct U; // Not copy!
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0382]: use of moved value
|
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;
|
LL | let a @ b = U;
|
||||||
| ----^ - move occurs because value has type `U`, which does not implement the `Copy` trait
|
| ----^ - 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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);
|
LL | let a @ (b, c) = (U, U);
|
||||||
| --------^- ------ move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
| --------^- ------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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());
|
LL | let a @ (b, c) = (u(), u());
|
||||||
| --------^- ---------- move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
| --------^- ---------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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) {
|
LL | match Ok(U) {
|
||||||
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
|
| ----- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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) {
|
LL | match Ok(U) {
|
||||||
| ----- move occurs because value has type `std::result::Result<U, U>`, which does not implement the `Copy` trait
|
| ----- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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()] {
|
LL | match [u(), u(), u(), u()] {
|
||||||
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
|
| -------------------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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()] {
|
LL | match [u(), u(), u(), u()] {
|
||||||
| -------------------- move occurs because value has type `[U; 4]`, which does not implement the `Copy` trait
|
| -------------------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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) {}
|
LL | fn fun(a @ b: U) {}
|
||||||
| ----^
|
| ----^
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
// Test `@` patterns combined with `box` patterns.
|
// Test `@` patterns combined with `box` patterns.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Test `@` patterns combined with `box` patterns.
|
// Test `@` patterns combined with `box` patterns.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: cannot move out of value because it is borrowed
|
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);
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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());
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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);
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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 => {
|
LL | ref mut a @ box ref b => {
|
||||||
| ---------^^^^^^^-----
|
| ---------^^^^^^^-----
|
||||||
|
@ -62,7 +62,7 @@ LL | ref mut a @ box ref b => {
|
||||||
| mutable borrow, by `a`, occurs here
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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>) {
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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);
|
LL | let a @ box &b = Box::new(&C);
|
||||||
| ---------^ ------------ move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
|
| ---------^ ------------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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);
|
LL | let a @ box b = Box::new(C);
|
||||||
| --------^ ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
|
| --------^ ----------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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) {
|
LL | match Box::new(C) {
|
||||||
| ----------- move occurs because value has type `Box<C>`, which does not implement the `Copy` trait
|
| ----------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
LL | let ref a @ box ref mut b = Box::new(NC);
|
||||||
| ------------^^^^^^^^^
|
| ------------^^^^^^^^^
|
||||||
|
@ -112,7 +112,7 @@ LL | drop(a);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
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);
|
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
|
| -- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
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 => {
|
LL | ref mut a @ box ref b => {
|
||||||
| ----------------^^^^^
|
| ----------------^^^^^
|
||||||
|
@ -136,7 +136,7 @@ LL | *a = Box::new(NC);
|
||||||
| -- mutable borrow later used here
|
| -- mutable borrow later used here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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>) {}
|
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
|
| move occurs because value has type `Box<&C>`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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>) {}
|
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
|
| 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
|
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>) {
|
LL | fn f5(ref mut a @ box ref b: Box<NC>) {
|
||||||
| ----------------^^^^^
|
| ----------------^^^^^
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// Currently this logic exists in THIR match checking as opposed to borrowck.
|
// Currently this logic exists in THIR match checking as opposed to borrowck.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U;
|
struct U;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: borrow of moved value
|
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;
|
LL | let a @ ref b = U;
|
||||||
| -^^^-----
|
| -^^^-----
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented.
|
// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U;
|
struct U;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: borrow of moved value
|
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;
|
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
|
| move occurs because `a` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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);
|
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
|
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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);
|
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
|
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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);
|
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
|
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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];
|
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
|
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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();
|
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
|
| move occurs because `a` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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());
|
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
|
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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());
|
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
|
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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());
|
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
|
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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()];
|
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
|
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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) => {}
|
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
|
| move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) => {}
|
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
|
| move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) => {}
|
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
|
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) => {}
|
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
|
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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]) => {}
|
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
|
| move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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) => {}
|
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
|
| move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) => {}
|
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
|
| move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) => {}
|
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
|
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) => {}
|
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
|
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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]) => {}
|
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
|
| move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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) {}
|
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
|
| move occurs because `a` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) {}
|
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
|
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) {}
|
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
|
| move occurs because `b` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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)) {}
|
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
|
| move occurs because `d` has type `U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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]) {}
|
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
|
| move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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);
|
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
|
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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);
|
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
|
| ------------------------^^^^^^^^^- ------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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);
|
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
|
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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];
|
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
|
| ----------------^^^^^- ------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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();
|
LL | let a @ ref b = u();
|
||||||
| ----^^^^^ --- move occurs because value has type `U`, which does not implement the `Copy` trait
|
| ----^^^^^ --- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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());
|
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
|
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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());
|
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
|
| ------------------------^^^^^^^^^- ---------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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());
|
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
|
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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()];
|
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
|
| ----------------^^^^^- ---------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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)) => {}
|
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
|
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)) {
|
LL | match Some((U, U)) {
|
||||||
| ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
|
| ------------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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)) => {}
|
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
|
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]) {
|
LL | match Some([U, U]) {
|
||||||
| ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
|
| ------------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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()) {
|
LL | match Some(u()) {
|
||||||
| --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait
|
| --------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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)) => {}
|
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
|
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())) {
|
LL | match Some((u(), u())) {
|
||||||
| ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
|
| ---------------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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)) => {}
|
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
|
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()]) {
|
LL | match Some([u(), u()]) {
|
||||||
| ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
|
| ---------------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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) {}
|
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
|
| move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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)) {}
|
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
|
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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)) {}
|
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
|
| move occurs because value has type `(U, U)`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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)) {}
|
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
|
= note: move occurs because value has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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]) {}
|
LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
|
||||||
| ----------------^^^^^-
|
| ----------------^^^^^-
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Test that `ref mut? @ pat_with_by_move_bindings` is prevented.
|
// Test that `ref mut? @ pat_with_by_move_bindings` is prevented.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U;
|
struct U;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: cannot move out of value because it is borrowed
|
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;
|
LL | let ref a @ b = U;
|
||||||
| -----^^^-
|
| -----^^^-
|
||||||
|
@ -8,7 +8,7 @@ LL | let ref a @ b = U;
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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);
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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);
|
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
|
| value borrowed, by `b`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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);
|
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
|
| value borrowed, by `d`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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];
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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();
|
LL | let ref a @ b = u();
|
||||||
| -----^^^-
|
| -----^^^-
|
||||||
|
@ -55,7 +55,7 @@ LL | let ref a @ b = u();
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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());
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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());
|
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
|
| value borrowed, by `b`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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());
|
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
|
| value borrowed, by `d`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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()];
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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) => {}
|
LL | ref a @ Some(b) => {}
|
||||||
| -----^^^^^^^^-^
|
| -----^^^^^^^^-^
|
||||||
|
@ -102,7 +102,7 @@ LL | ref a @ Some(b) => {}
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) => {}
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) => {}
|
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
|
| value borrowed, by `b`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) => {}
|
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
|
| value borrowed, by `d`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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]) => {}
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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) => {}
|
LL | ref a @ Some(b) => {}
|
||||||
| -----^^^^^^^^-^
|
| -----^^^^^^^^-^
|
||||||
|
@ -149,7 +149,7 @@ LL | ref a @ Some(b) => {}
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) => {}
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) => {}
|
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
|
| value borrowed, by `b`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) => {}
|
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
|
| value borrowed, by `d`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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]) => {}
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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) {}
|
LL | fn f1(ref a @ b: U) {}
|
||||||
| -----^^^-
|
| -----^^^-
|
||||||
|
@ -196,7 +196,7 @@ LL | fn f1(ref a @ b: U) {}
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) {}
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) {}
|
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
|
| value borrowed, by `b`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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)) {}
|
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
|
| value borrowed, by `d`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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]) {}
|
LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
|
||||||
| ---------^^^^-^^-----^
|
| ---------^^^^-^^-----^
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
enum Option<T> {
|
enum Option<T> {
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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) => {
|
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
|
| mutable borrow, by `z`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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
|
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
|
| immutable borrow, by `b`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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;
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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;
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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);
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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();
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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();
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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;
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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;
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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) => {
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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) => {
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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) => {
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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) => {
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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 } => {}
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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 } => {}
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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 } => {}
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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 } => {}
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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 } => {}
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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 } => {}
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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 } => {}
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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 } => {}
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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);
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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) {}
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as immutable because it is also borrowed as mutable
|
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) {}
|
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
|
| mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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]) {}
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
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) {}
|
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
|
| immutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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) {}
|
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
|
| value borrowed, by `b`, here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
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) => {
|
LL | ref mut z @ &mut Some(ref a) => {
|
||||||
| ----------------------^^^^^-
|
| ----------------------^^^^^-
|
||||||
|
@ -307,7 +307,7 @@ LL | **z = None;
|
||||||
| ---------- mutable borrow later used here
|
| ---------- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
|
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();
|
LL | let ref mut a @ ref b = u();
|
||||||
| ------------^^^^^
|
| ------------^^^^^
|
||||||
|
@ -319,7 +319,7 @@ LL | *a = u();
|
||||||
| -------- mutable borrow later used here
|
| -------- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
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();
|
LL | let ref a @ ref mut b = u();
|
||||||
| --------^^^^^^^^^
|
| --------^^^^^^^^^
|
||||||
|
@ -331,7 +331,7 @@ LL | drop(a);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
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) => {
|
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
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
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) => {
|
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
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
|
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 } => {}
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
|
||||||
| ^^^^^^ cannot assign
|
| ^^^^^^ 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
|
= 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
|
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 } => {}
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
|
||||||
| ^^^^^^^^^^^ cannot assign
|
| ^^^^^^^^^^^ 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
|
= note: variables bound in patterns are immutable until the end of the pattern guard
|
||||||
|
|
||||||
error[E0507]: cannot move out of `b` in 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 } => {}
|
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
|
| ^ 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
|
= 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
|
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 } => {}
|
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
|
| ^ 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
|
= 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
|
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 } => {}
|
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
|
| ^ 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
|
= 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
|
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 } => {}
|
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
|
| ^ 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
|
= 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
|
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);
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||||
| ---------^^^^^^^^^------------
|
| ---------^^^^^^^^^------------
|
||||||
|
@ -415,7 +415,7 @@ LL | drop(a);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||||
| --------------------^^^^^^^^^-
|
| --------------------^^^^^^^^^-
|
||||||
|
@ -427,7 +427,7 @@ LL | drop(a);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||||
| ---------^^^^^^^^^------------
|
| ---------^^^^^^^^^------------
|
||||||
|
@ -439,7 +439,7 @@ LL | drop(a);
|
||||||
| - immutable borrow later used here
|
| - immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
|
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);
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
|
||||||
| --------------------^^^^^^^^^-
|
| --------------------^^^^^^^^^-
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
|
// Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U;
|
struct U;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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;
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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;
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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;
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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;
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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;
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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 @ (
|
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
|
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 @ (
|
LL | let ref mut a @ (
|
||||||
| ^--------
|
| ^--------
|
||||||
|
@ -88,7 +88,7 @@ LL | | ) = (u(), [u(), u(), u()]);
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
||||||
error: borrow of moved value
|
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);
|
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
|
| move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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 ^--
|
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
|
| move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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;
|
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
|
| move occurs because `a` has type `&mut U` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: borrow of moved value
|
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);
|
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
|
| 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
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) {}
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) {}
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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 @ [
|
LL | ref mut a @ [
|
||||||
| ^--------
|
| ^--------
|
||||||
|
@ -240,7 +240,7 @@ LL | | ] : [[U; 4]; 5]
|
||||||
| |_________^
|
| |_________^
|
||||||
|
|
||||||
error: cannot borrow value as mutable more than once at a time
|
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) {}
|
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
|
| first mutable borrow, by `a`, occurs here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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) {}
|
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
|
| value borrowed, by `b`, here
|
||||||
|
|
||||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
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;
|
LL | let ref mut a @ ref mut b = U;
|
||||||
| ------------^^^^^^^^^
|
| ------------^^^^^^^^^
|
||||||
|
@ -271,7 +271,7 @@ LL | drop(a);
|
||||||
| - first borrow later used here
|
| - first borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
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;
|
LL | let ref mut a @ ref mut b = U;
|
||||||
| ------------^^^^^^^^^
|
| ------------^^^^^^^^^
|
||||||
|
@ -283,7 +283,7 @@ LL | *a = U;
|
||||||
| ------ first borrow later used here
|
| ------ first borrow later used here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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);
|
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
|
| ----------------^^^^^^^^^- ------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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 ^--
|
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
|
| ------------^-- -------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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;
|
LL | let a @ &mut ref mut b = &mut U;
|
||||||
| ---------^^^^^^^^^ ------ move occurs because value has type `&mut U`, which does not implement the `Copy` trait
|
| ---------^^^^^^^^^ ------ 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: borrow of moved value
|
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);
|
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
|
| ---------------------^^^^^^^^^- ----------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| ----------- first borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| ----------- first borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
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) => {
|
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
|
| - first borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow value as mutable more than once at a time
|
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) => {
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
|
||||||
| ----------------^^^^^^^^^-
|
| ----------------^^^^^^^^^-
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden.
|
// Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
struct C;
|
struct C;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0382]: use of moved value
|
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);
|
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
|
| ----------^- -------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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));
|
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
|
| ----------^^^^^^^^^^^^- --------------- 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
|
| value moved here
|
||||||
|
|
||||||
error[E0382]: use of moved value
|
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));
|
LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
|
||||||
| ----------^-
|
| ----------^-
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
// this would create problems for the generalization aforementioned.
|
// this would create problems for the generalization aforementioned.
|
||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct NotCopy;
|
struct NotCopy;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: cannot move out of value because it is borrowed
|
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;
|
LL | let ref a @ b = NotCopy;
|
||||||
| -----^^^-
|
| -----^^^-
|
||||||
|
@ -8,7 +8,7 @@ LL | let ref a @ b = NotCopy;
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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;
|
LL | let ref mut a @ b = NotCopy;
|
||||||
| ---------^^^-
|
| ---------^^^-
|
||||||
|
@ -17,7 +17,7 @@ LL | let ref mut a @ b = NotCopy;
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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) => {
|
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
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error: borrow of moved value
|
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) => {
|
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
|
| move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait
|
||||||
|
|
||||||
error: cannot move out of value because it is borrowed
|
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 => {
|
LL | ref a @ b => {
|
||||||
| -----^^^-
|
| -----^^^-
|
||||||
|
@ -45,7 +45,7 @@ LL | ref a @ b => {
|
||||||
| value borrowed, by `a`, here
|
| value borrowed, by `a`, here
|
||||||
|
|
||||||
error[E0505]: cannot move out of value because it is borrowed
|
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;
|
LL | let ref mut a @ b = NotCopy;
|
||||||
| ------------^
|
| ------------^
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
struct U;
|
struct U;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
struct U;
|
struct U;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
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;
|
LL | let hold_all = &arr;
|
||||||
| ---- borrow of `arr` occurs here
|
| ---- borrow of `arr` occurs here
|
||||||
|
@ -10,7 +10,7 @@ LL | drop(hold_all);
|
||||||
| -------- borrow later used here
|
| -------- borrow later used here
|
||||||
|
|
||||||
error[E0384]: cannot assign twice to immutable variable `_x1`
|
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;
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||||
| ---
|
| ---
|
||||||
|
@ -21,7 +21,7 @@ LL | _x1 = U;
|
||||||
| ^^^^^^^ cannot assign twice to immutable variable
|
| ^^^^^^^ cannot assign twice to immutable variable
|
||||||
|
|
||||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
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;
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||||
| ------------ borrow of `arr[..]` occurs here
|
| ------------ borrow of `arr[..]` occurs here
|
||||||
|
@ -32,7 +32,7 @@ LL | drop(_x0_hold);
|
||||||
| -------- borrow later used here
|
| -------- borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `arr[..]` as mutable because it is also borrowed as immutable
|
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;
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||||
| ---------------- immutable borrow occurs here
|
| ---------------- immutable borrow occurs here
|
||||||
|
@ -44,7 +44,7 @@ LL | drop(xs_hold);
|
||||||
| ------- immutable borrow later used here
|
| ------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
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;
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||||
| ---------------- borrow of `arr[..]` occurs here
|
| ---------------- borrow of `arr[..]` occurs here
|
||||||
|
@ -56,7 +56,7 @@ LL | drop(xs_hold);
|
||||||
| ------- borrow later used here
|
| ------- borrow later used here
|
||||||
|
|
||||||
error[E0505]: cannot move out of `arr[..]` because it is borrowed
|
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;
|
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
|
||||||
| ---------------- borrow of `arr[..]` occurs here
|
| ---------------- borrow of `arr[..]` occurs here
|
||||||
|
@ -68,7 +68,7 @@ LL | drop(xs_hold);
|
||||||
| ------- borrow later used here
|
| ------- borrow later used here
|
||||||
|
|
||||||
error[E0384]: cannot assign twice to immutable variable `_x1`
|
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;
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||||
| ---
|
| ---
|
||||||
|
@ -79,7 +79,7 @@ LL | _x1 = U;
|
||||||
| ^^^^^^^ cannot assign twice to immutable variable
|
| ^^^^^^^ cannot assign twice to immutable variable
|
||||||
|
|
||||||
error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
|
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;
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||||
| ------- immutable borrow occurs here
|
| ------- immutable borrow occurs here
|
||||||
|
@ -91,7 +91,7 @@ LL | *_x0 = U;
|
||||||
| -------- immutable borrow later used here
|
| -------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
|
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;
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||||
| ------- immutable borrow occurs here
|
| ------- immutable borrow occurs here
|
||||||
|
@ -102,7 +102,7 @@ LL | *_x0 = U;
|
||||||
| -------- immutable borrow later used here
|
| -------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0594]: cannot assign to `*_x0` which is behind a `&` reference
|
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;
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||||
| ------- help: consider changing this to be a mutable reference: `ref mut _x0`
|
| ------- 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
|
| ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
||||||
error[E0594]: cannot assign to `*_x2` which is behind a `&` reference
|
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;
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||||
| ------- help: consider changing this to be a mutable reference: `ref mut _x2`
|
| ------- 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
|
| ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written
|
||||||
|
|
||||||
error[E0382]: use of moved value: `tup.1`
|
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;
|
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
|
||||||
| --- value moved here
|
| --- 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
|
= note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup.1`
|
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);
|
LL | drop(tup.1);
|
||||||
| ----- value moved here
|
| ----- 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
|
= 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
|
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;
|
LL | let (.., ref mut _x3) = tup;
|
||||||
| ----------- mutable borrow occurs here
|
| ----------- mutable borrow occurs here
|
||||||
|
@ -152,7 +152,7 @@ LL | drop(_x3);
|
||||||
| --- mutable borrow later used here
|
| --- mutable borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
|
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;
|
LL | let (.., ref mut _x3) = tup;
|
||||||
| ----------- first mutable borrow occurs here
|
| ----------- first mutable borrow occurs here
|
||||||
|
@ -164,7 +164,7 @@ LL | drop(_x3);
|
||||||
| --- first borrow later used here
|
| --- first borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `tup.3` as mutable more than once at a time
|
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;
|
LL | let (.., ref mut _x3) = tup;
|
||||||
| ----------- first mutable borrow occurs here
|
| ----------- first mutable borrow occurs here
|
||||||
|
@ -176,7 +176,7 @@ LL | drop(_x3);
|
||||||
| --- first borrow later used here
|
| --- first borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable
|
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;
|
LL | let (.., ref mut _x3) = tup;
|
||||||
| ----------- mutable borrow occurs here
|
| ----------- mutable borrow occurs here
|
||||||
|
@ -187,7 +187,7 @@ LL | drop(_x3);
|
||||||
| --- mutable borrow later used here
|
| --- mutable borrow later used here
|
||||||
|
|
||||||
error[E0382]: use of moved value: `tup`
|
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);
|
LL | let mut tup = (U, U, U);
|
||||||
| ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait
|
| ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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`.
|
|
|
@ -1,7 +1,5 @@
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
enum E {
|
enum E {
|
||||||
Foo(String, String, String),
|
Foo(String, String, String),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct S; // Not `Copy`.
|
struct S; // Not `Copy`.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0382]: borrow of moved value: `tup0`
|
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);
|
LL | let mut tup0 = (S, S);
|
||||||
| -------- move occurs because `tup0` has type `(S, S)`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup1`
|
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);
|
LL | let mut tup1 = (S, S, S);
|
||||||
| -------- move occurs because `tup1` has type `(S, S, S)`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup2`
|
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);
|
LL | let tup2 = (S, S);
|
||||||
| ---- move occurs because `tup2` has type `(S, S)`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup3`
|
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);
|
LL | let tup3 = (S, S, S);
|
||||||
| ---- move occurs because `tup3` has type `(S, S, S)`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup4`
|
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);
|
LL | let tup4 = (S, S);
|
||||||
| ---- move occurs because `tup4` has type `(S, S)`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr0`
|
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];
|
LL | let mut arr0 = [S, S, S];
|
||||||
| -------- move occurs because `arr0` has type `[S; 3]`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr1`
|
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];
|
LL | let mut arr1 = [S, S, S, S, S];
|
||||||
| -------- move occurs because `arr1` has type `[S; 5]`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr2`
|
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];
|
LL | let arr2 = [S, S, S];
|
||||||
| ---- move occurs because `arr2` has type `[S; 3]`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr3`
|
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];
|
LL | let arr3 = [S, S, S, S, S];
|
||||||
| ---- move occurs because `arr3` has type `[S; 5]`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup0`
|
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;
|
LL | let mut tup0: Option<(S, S)> = None;
|
||||||
| -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup1`
|
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;
|
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
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup2`
|
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;
|
LL | let tup2: Option<(S, S)> = None;
|
||||||
| ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup3`
|
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;
|
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
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup4`
|
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;
|
LL | let tup4: Option<(S, S)> = None;
|
||||||
| ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr0`
|
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;
|
LL | let mut arr0: Option<[S; 3]> = None;
|
||||||
| -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr1`
|
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;
|
LL | let mut arr1: Option<[S; 5]> = None;
|
||||||
| -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr2`
|
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;
|
LL | let arr2: Option<[S; 3]> = None;
|
||||||
| ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr3`
|
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;
|
LL | let arr3: Option<[S; 5]> = None;
|
||||||
| ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup0`
|
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;
|
LL | let mut tup0: Option<(S, S)> = None;
|
||||||
| -------- move occurs because `tup0` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup1`
|
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;
|
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
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup2`
|
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;
|
LL | let tup2: Option<(S, S)> = None;
|
||||||
| ---- move occurs because `tup2` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup3`
|
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;
|
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
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `tup4`
|
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;
|
LL | let tup4: Option<(S, S)> = None;
|
||||||
| ---- move occurs because `tup4` has type `Option<(S, S)>`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr0`
|
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;
|
LL | let mut arr0: Option<[S; 3]> = None;
|
||||||
| -------- move occurs because `arr0` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr1`
|
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;
|
LL | let mut arr1: Option<[S; 5]> = None;
|
||||||
| -------- move occurs because `arr1` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
| -------- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr2`
|
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;
|
LL | let arr2: Option<[S; 3]> = None;
|
||||||
| ---- move occurs because `arr2` has type `Option<[S; 3]>`, which does not implement the `Copy` trait
|
| ---- 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
|
| ^^^^^ value borrowed here after move
|
||||||
|
|
||||||
error[E0382]: borrow of moved value: `arr3`
|
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;
|
LL | let arr3: Option<[S; 5]> = None;
|
||||||
| ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
| ---- move occurs because `arr3` has type `Option<[S; 5]>`, which does not implement the `Copy` trait
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U;
|
struct U;
|
||||||
fn accept_fn_once(_: impl FnOnce()) {}
|
fn accept_fn_once(_: impl FnOnce()) {}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U;
|
struct U;
|
||||||
fn accept_fn_once(_: &impl FnOnce()) {}
|
fn accept_fn_once(_: &impl FnOnce()) {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
|
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 = || {
|
LL | let c1 = || {
|
||||||
| ^^ this closure implements `FnOnce`, not `FnMut`
|
| ^^ this closure implements `FnOnce`, not `FnMut`
|
||||||
|
@ -11,7 +11,7 @@ LL | accept_fn_mut(&c1);
|
||||||
| ------------- the requirement to implement `FnMut` derives from here
|
| ------------- the requirement to implement `FnMut` derives from here
|
||||||
|
|
||||||
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
|
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 = || {
|
LL | let c1 = || {
|
||||||
| ^^ this closure implements `FnOnce`, not `Fn`
|
| ^^ this closure implements `FnOnce`, not `Fn`
|
||||||
|
@ -23,7 +23,7 @@ LL | accept_fn(&c1);
|
||||||
| --------- the requirement to implement `Fn` derives from here
|
| --------- the requirement to implement `Fn` derives from here
|
||||||
|
|
||||||
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
|
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 = || {
|
LL | let c2 = || {
|
||||||
| ^^ this closure implements `FnMut`, not `Fn`
|
| ^^ this closure implements `FnMut`, not `Fn`
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![feature(move_ref_pattern)]
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
struct U;
|
struct U;
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue