1
Fork 0

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

Rollup of 14 pull requests

Successful merges:

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

Failed merges:

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

View file

@ -1258,9 +1258,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
// If backtraces are enabled, also print the query stack // 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 {

View file

@ -1,3 +1,5 @@
#### Note: this error code is no longer emitted by the compiler.
This error indicates that the bindings in a match arm would require a value to 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 => {},
} }
``` ```

View file

@ -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

View file

@ -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),

View file

@ -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,
}
}
} }

View file

@ -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]

View file

@ -124,20 +124,23 @@ impl<'tcx> TyCtxt<'tcx> {
}) })
} }
pub fn try_print_query_stack(handler: &Handler) { pub fn try_print_query_stack(handler: &Handler, num_frames: Option<usize>) {
eprintln!("query stack during panic:"); 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");
}
} }
} }

View file

@ -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()

View file

@ -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(&param.pat, "function argument", None); self.check_irrefutable(&param.pat, "function argument", None);
self.check_patterns(false, &param.pat); self.check_patterns(&param.pat);
} }
} }
@ -119,10 +119,7 @@ impl PatCtxt<'_, '_> {
} }
impl<'tcx> MatchVisitor<'_, 'tcx> { 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:

View file

@ -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)
}
} }

View file

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

View file

@ -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 {

View file

@ -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) {

View file

@ -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>,

View file

@ -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()

View file

@ -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

View file

@ -257,8 +257,13 @@ impl<K, V> Root<K, V> {
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the /// `NodeRef` 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 }
} }
} }

View file

@ -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() {

View file

@ -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;

View file

@ -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)]

View file

@ -690,6 +690,17 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
}, },
} }
} }
#[inline]
fn as_str(&self) -> &'a str {
// `Self::get_end` doesn't change `self.start`
if self.finished {
return "";
}
// SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
}
} }
generate_pattern_iterators! { 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`].

View file

@ -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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
use crate::cell::UnsafeCell;
use crate::mem; use crate::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"
); );

View file

@ -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");
} }
} }

View file

@ -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"
); );

View file

@ -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()

View file

@ -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()

View file

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

View file

@ -55,6 +55,8 @@ cfg_if::cfg_if! {
pub mod mutex; 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;

View file

@ -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.

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

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

View file

@ -1763,11 +1763,11 @@ crate fn shorten(s: String) -> String {
} }
} }
fn document(w: &mut Buffer, cx: &Context, item: &clean::Item) { fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) {
if let Some(ref name) = item.name { 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";

View file

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

View file

@ -10,9 +10,8 @@ pub struct Portable;
// @has doc_cfg/unix_only/index.html \ // @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();

View file

@ -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;
} }

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -7,24 +7,30 @@ LL | fn printf(_: *const u8, ...);
error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied 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

View file

@ -2,7 +2,7 @@ error: C-variadic function must be declared with at least one named argument
--> $DIR/variadic-ffi-no-fixed-args.rs:2:12 --> $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

View file

@ -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::{

View file

@ -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)]

View file

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

View file

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

View file

@ -1,13 +1,16 @@
error[E0060]: this function takes at least 1 argument but 0 arguments were supplied 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
} }

View file

@ -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`.

View file

@ -2,205 +2,205 @@ error: only foreign or `unsafe extern "C" functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:5:19 --> $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

View file

@ -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: (),

View file

@ -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) => {}
| -----^^^^^^^^^^ | -----^^^^^^^^^^

View file

@ -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() {}

View file

@ -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> {
| ------^- | ------^-

View file

@ -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!

View file

@ -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) {}
| ----^ | ----^

View file

@ -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)]

View file

@ -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)]

View file

@ -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>) {
| ----------------^^^^^ | ----------------^^^^^

View file

@ -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;

View file

@ -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;
| -^^^----- | -^^^-----

View file

@ -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;

View file

@ -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]) {}
| ----------------^^^^^- | ----------------^^^^^-

View file

@ -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;

View file

@ -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]) {}
| ---------^^^^-^^-----^ | ---------^^^^-^^-----^

View file

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

View file

@ -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);
| --------------------^^^^^^^^^- | --------------------^^^^^^^^^-

View file

@ -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;

View file

@ -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) => {
| ----------------^^^^^^^^^- | ----------------^^^^^^^^^-

View file

@ -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;

View file

@ -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));
| ----------^- | ----------^-

View file

@ -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;

View file

@ -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;
| ------------^ | ------------^

View file

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

View file

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

View file

@ -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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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

View file

@ -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()) {}

View file

@ -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()) {}

View file

@ -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`

View file

@ -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